diff --git a/.config b/.config index 93fa18afe..470123376 100644 --- a/.config +++ b/.config @@ -1792,6 +1792,7 @@ CONFIG_PCI_ENDPOINT_TEST=m # CONFIG_VCPU_STALL_DETECTOR is not set # CONFIG_NSM is not set # CONFIG_MCHP_LAN966X_PCI is not set +CONFIG_MISC_JMM_VCAP=y # CONFIG_C2PORT is not set # diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b9ca56930..626152d80 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -644,6 +644,9 @@ config MCHP_LAN966X_PCI - lan966x-miim (MDIO_MSCC_MIIM) - lan966x-switch (LAN966X_SWITCH) +config MISC_JMM_VCAP + tristate "JMM_VCAP Driver" + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 917b9a718..cef74a483 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_GP_PCI1XXXX) += mchp_pci1xxxx/ obj-$(CONFIG_VCPU_STALL_DETECTOR) += vcpu_stall_detector.o obj-$(CONFIG_TMR_MANAGER) += xilinx_tmr_manager.o obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o +obj-$(CONFIG_MISC_JMM_VCAP) += jmm_vcap.o obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o obj-$(CONFIG_NSM) += nsm.o diff --git a/drivers/misc/jmm_vcap.c b/drivers/misc/jmm_vcap.c new file mode 100644 index 000000000..2fe454b5f --- /dev/null +++ b/drivers/misc/jmm_vcap.c @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static struct jmm_vcap { + struct gpio_desc *gpio; + int gpio_state; + uint8_t *ocm_base; + size_t ocm_len; +} jmm_vcap; + + +/* +** This function will be called when we open the Misc device file +*/ +static int jmm_vcap_open(struct inode *inode, struct file *file) +{ + pr_info("jmm_vcap device open\n"); + return 0; +} + +/* +** This function will be called when we close the Misc Device file +*/ +static int jmm_vcap_close(struct inode *inodep, struct file *filp) +{ + pr_info("jmm_vcap device close\n"); + return 0; +} + +/* +** This function will be called when we write the Misc Device file +*/ +static ssize_t jmm_vcap_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + pr_info("jmm_vcap device write\n"); + + /* We are not doing anything with this data now */ + + return -ENODEV; +} + +/* +** This function will be called when we read the Misc Device file +*/ +static ssize_t jmm_vcap_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + + if (*f_pos>=jmm_vcap.ocm_len) return 0; + + if ((*f_pos+count)>jmm_vcap.ocm_len) { + count=jmm_vcap.ocm_len-*f_pos; + } + + if (copy_to_user(buf, jmm_vcap.ocm_base+(*f_pos), count)) + return -EFAULT; + + (*f_pos) += count; + + return count; +} + +static loff_t jmm_vcap_llseek(struct file *filp, loff_t offset, int whence) +{ +loff_t new_offset; + + +switch(whence) { +case SEEK_SET: + new_offset=offset; + break; +case SEEK_CUR: + new_offset=filp->f_pos + offset; + break; +case SEEK_END: + new_offset=jmm_vcap.ocm_len + offset; + break; +default: + return -EINVAL; +} + + +if (new_offset<0) + return -EINVAL; +if (new_offset>jmm_vcap.ocm_len) + return -EINVAL; + +filp->f_pos=new_offset; + +return new_offset; +} + + +//File operation structure +static const struct file_operations fops = { + .owner = THIS_MODULE, + .write = jmm_vcap_write, + .read = jmm_vcap_read, + .open = jmm_vcap_open, + .release = jmm_vcap_close, + .llseek = jmm_vcap_llseek, +}; + +//Misc device structure +struct miscdevice jmm_vcap_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "jmm_vcap", + .fops = &fops, +}; + + +static const struct of_device_id jmm_vcap_of_match[] = { + { .compatible = "jmm,video-capture-device" }, + { /* end of table */ } +}; +MODULE_DEVICE_TABLE(of, jmm_vcap_of_match); + + +static int jmm_vcap_probe(struct platform_device *pdev) +{ + struct resource *res; + const struct of_device_id *match; + uint8_t *ptr; + + + match = of_match_node(jmm_vcap_of_match, pdev->dev.of_node); + pr_info("jmm_vcap match %px\n",match); + printk(KERN_ERR "jmm_vcap" "jmm_vcap match %px\n",match); + if (!match) { + dev_err(&pdev->dev, "of_match_node() failed\n"); + printk(KERN_ERR "jmm_vcap" "of_match_node() failed\n"); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "can't get parent mmio range\n"); + printk(KERN_ERR "jmm_vcap" "can't get parent mmio range\n"); + return -EINVAL; + } + + jmm_vcap.gpio = devm_gpiod_get(&(pdev->dev), NULL, GPIOD_OUT_LOW); + if (IS_ERR(jmm_vcap.gpio)) { + dev_err(&pdev->dev, "can't get enable gpio\n"); + printk(KERN_ERR "jmm_vcap" "can't get enable gpio\n"); + return -EINVAL; + } + + jmm_vcap.ocm_len=res->end - res->start; + jmm_vcap.ocm_len++; + pr_info("jmm_vcap resource indicates length of 0x%x\n",jmm_vcap.ocm_len); + printk(KERN_ERR "jmm_vcap" "jmm_vcap resource indicates length of 0x%x\n",jmm_vcap.ocm_len); + + ptr = devm_ioremap_resource(&pdev->dev, res); + pr_info("jmm_vcap devm_ioremap_resource() gives %px\n",ptr); + printk(KERN_ERR "jmm_vcap" "jmm_vcap devm_ioremap_resource() gives %px\n",ptr); + + if (IS_ERR(ptr)) + return PTR_ERR(ptr); + + jmm_vcap.ocm_base=ptr; + + gpiod_set_value(jmm_vcap.gpio,1); + + return 0; +} + +/** + * zynq_gpio_remove - Driver removal function + * @pdev: platform device instance + * + * Return: 0 always + */ +static void jmm_vcap_remove(struct platform_device *pdev) +{ + //struct zynq_gpio *gpio = platform_get_drvdata(pdev); + + jmm_vcap.ocm_base=NULL; +} + +static struct platform_driver jmm_vcap_driver = { + .driver = { + .name = "jmm-vcap", + .of_match_table = jmm_vcap_of_match, + }, + .probe = jmm_vcap_probe, + .remove = jmm_vcap_remove, +}; + + +static int __init jmm_vcap_init(void) +{ + int error; + + //jmm_vcap_driver->driver.owner = THIS_MODULE; + //jmm_vcap_driver->driver.bus=&platform_bus_type; + + error=platform_driver_register(&jmm_vcap_driver); + if (error) { + pr_err("platform_driver_register failed!!!\n"); + printk(KERN_ERR "jmm_vcap" "platform_driver_register failed!!!\n"); + return error; + } + + error = misc_register(&jmm_vcap_device); + if (error) { + platform_driver_unregister(&jmm_vcap_driver); + pr_err("misc_register failed!!!\n"); + printk(KERN_ERR "jmm_vcap" "misc_register failed!!!\n"); + return error; + } + + pr_info("misc_register init done!!!\n"); + printk(KERN_ERR "jmm_vcap" "misc_register init done!!!\n"); + +#if 0 + jmm_vcap = ioremap(0xfffc0000,0x40000); + pr_info("jmm_vcap mapped at %px\n",jmm_vcap); +#endif + + return 0; +} + +static void __exit jmm_vcap_exit(void) +{ + misc_deregister(&jmm_vcap_device); + platform_driver_unregister(&jmm_vcap_driver); + + pr_info("misc_register exit done!!!\n"); + +#if 0 + if (jmm_vcap.ocm_base) iounmap(jmm_vcap.ocm_base); +#endif +} + +module_init(jmm_vcap_init) +module_exit(jmm_vcap_exit) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("meh"); +MODULE_DESCRIPTION("jmm_vcap driver"); +MODULE_VERSION("1.00"); + + +