diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c index 5633bc5..699cbef 100644 --- a/drivers/usb/c67x00/c67x00-drv.c +++ b/drivers/usb/c67x00/c67x00-drv.c @@ -39,6 +39,10 @@ #include #include #include +#if defined(CONFIG_OF) +#include +#include +#endif #include "c67x00.h" #include "c67x00-hcd.h" @@ -87,8 +91,9 @@ static irqreturn_t c67x00_irq(int irq, void *__dev) struct c67x00_sie *sie; u16 msg, int_status; int i, count = 8; - +// printk("Handling IRQ!\n"); int_status = c67x00_ll_hpi_status(c67x00); + printk("C67X00_DBG:c67x00_irq() - Handling IRQ number %d\n",int_status); if (!int_status) return IRQ_NONE; @@ -225,14 +230,241 @@ static struct platform_driver c67x00_driver = { }; MODULE_ALIAS("platform:c67x00"); +/* --------------------------------------------------------------------- + * OF_Platform Bus Support + */ + +#if defined(CONFIG_OF) +static int __devinit c67x00_of_probe(struct of_device *dev, + const struct of_device_id *match) +{ + struct c67x00_device *c67x00; + struct c67x00_platform_data *pdata; + struct resource r_irq_struct; + struct resource *res; + struct resource memory; + struct device_node *dp = dev->node; + struct resource* r_irq = &r_irq_struct; + u32* iprop; + int len, ret, i; + + /* Request memory region */ + printk("C67X00_DBG:c67x00_of_probe() - Request memory region\n"); + ret = of_address_to_resource(dp, 0, &memory); + if (ret) + return -ENXIO; + + res = request_mem_region(memory.start, memory.end - memory.start + 1, + dev_name(&dev->dev)); + + if (!res){ + dev_err(&dev->dev, "Memory region busy\n"); + return -EBUSY; + } + + /* Allocate device and platform_data structs */ + printk("C67X00_DBG:c67x00_of_probe() - Allocating data structs\n"); + c67x00 = kzalloc(sizeof(*c67x00), GFP_KERNEL); + if (!c67x00) + return -ENOMEM; + + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata){ + ret = -ENOMEM; + goto request_mem_failed; + } + + /* Configure c67x00 device */ + printk("C67X00_DBG:c67x00_of_probe() - Configuring c67x00 device\n"); + c67x00->hpi.base = ioremap(memory.start, memory.end - memory.start + 1); + + if (!c67x00->hpi.base) { + dev_err(&dev->dev, "Unable to map HPI registers\n"); + ret = -EIO; + goto map_failed; + } + + /* Configure platform data based on the device-tree data */ + printk("C67X00_DBG:c67x00_of_probe() - Configure platform data based on the device-tree data\n"); + spin_lock_init(&c67x00->hpi.lock); + //TODO: Check that we are using the ML403 + + iprop = of_get_property(dev->node, "xlnx,hpi_regstep", &len); + if (!iprop || len < sizeof(*iprop)) { + dev_err(&dev->dev, "No 'xlnx,hpi_regstep property'\n"); + ret = -EIO; + goto map_failed; //TODO + } + c67x00->hpi.regstep = *iprop; + printk("C67X00_DBG:c67x00_of_probe() - hpi.regstep: %x\n", c67x00->hpi.regstep); + + iprop = of_get_property(dev->node, "xlnx,sie1_config", &len); + if (!iprop || len < sizeof(*iprop)) { + dev_err(&dev->dev, "No 'xlnx,sie1_config'\n"); + ret = -EIO; + goto map_failed; //TODO + } + pdata->sie_config = *iprop; + printk("C67X00_DBG:c67x00_of_probe() - SIE_config: %x\n", pdata->sie_config); + + iprop = of_get_property(dev->node, "xlnx,sie2_config", &len); + if (!iprop || len < sizeof(*iprop)) { + dev_err(&dev->dev, "No 'xlnx,sie2_config'\n"); + ret = -EIO; + goto map_failed; //TODO + } + pdata->sie_config |= *iprop << 4; + printk("C67X00_DBG:c67x00_of_probe() - SIE_config: %x\n", pdata->sie_config); + + c67x00->pdata = pdata; + c67x00->pdev = dev; + + /* Low-level initizalization */ + printk("C67X00_DBG:c67x00_of_probe() - Low-level initizalization \n"); + c67x00_ll_init(c67x00); + c67x00_ll_hpi_reg_init(c67x00); + + /* Request IRQ */ + printk("C67X00_DBG:c67x00_of_probe() - Registering IRQ\n"); + dev_dbg(&dev->dev, "Registering IRQ\n"); + ret = of_irq_to_resource(dev->node, 0, r_irq); + + if (ret == NO_IRQ) { + dev_err(&dev->dev, "Couldn't find IRQ in device-tree\n"); + goto request_irq_failed; + } + printk("C67X00_DBG:c67x00_of_probe() - Trying to register IRQ:%d @ %d\n",ret,r_irq->start); + ret = request_irq(r_irq->start, c67x00_irq, 0, dev_name(&dev->dev), c67x00); + if (ret) { + dev_err(&dev->dev, "Cannot claim IRQ\n"); + goto request_irq_failed; + } + + /* Reset c67x00 as part of the initizalization*/ + printk("C67X00_DBG:c67x00_of_probe() - Low-level reset\n"); + ret = c67x00_ll_reset(c67x00); + if (ret) { + printk("Device reset failed\n"); + dev_err(&dev->dev, "Device reset failed\n"); + goto reset_failed; + } + + /* Probe each of the SIEs */ + printk("C67X00_DBG:c67x00_of_probe() - Configuring SIEs\n"); + dev_dbg(&dev->dev, "Configuring SIEs\n"); + for (i = 0; i < C67X00_SIES; i++) + c67x00_probe_sie(&c67x00->sie[i], c67x00, i); + printk("C67X00_DBG:c67x00_of_probe() - Saving driver data\n"); + dev_set_drvdata(&dev->dev, c67x00); + return 0; + + reset_failed: + free_irq(r_irq->start, c67x00); + request_irq_failed: + iounmap(c67x00->hpi.base); + map_failed: + release_mem_region(memory.start, memory.end - memory.start + 1); + kfree(pdata); + request_mem_failed: + kfree(c67x00); + + return ret; +} + +static int __devexit c67x00_of_remove(struct of_device *dev) +{ + struct c67x00_device *c67x00 = dev_get_drvdata(dev); + struct resource *res; + int i; + + dev_dbg(dev, "c67x00_free(%p)\n", dev); + + for (i = 0; i < C67X00_SIES; i++) + c67x00_remove_sie(&c67x00->sie[i]); + + c67x00_ll_release(c67x00); + + //TODO: release IRQ? +// res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +// if (res) +// free_irq(res->start, c67x00); + + iounmap(c67x00->hpi.base); + + +// res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +// if (res) +// release_mem_region(res->start, res->end - res->start + 1); + + kfree(c67x00); + + return 0; +} + +/* Match table for of_platform binding */ +static struct of_device_id c67x00_of_match[] __devinitdata = { + { .compatible = "cy,c67x00", }, + { .compatible = "cy,c67300", }, + {}, +}; +MODULE_DEVICE_TABLE(of, c67x00_of_match); + +static struct of_platform_driver c67x00_of_driver = { + .owner = THIS_MODULE, + .name = "c67x00", + .match_table = c67x00_of_match, + .probe = c67x00_of_probe, + .remove = __devexit_p(c67x00_of_remove), + .driver = { + .name = "c67x00", + .owner = THIS_MODULE, + }, +}; + +/* Registration helpers to keep the number of #ifdefs to a minimum */ +static inline int __init c67x00_of_register(void) +{ + pr_debug("c67x00: registering OF binding\n"); + return of_register_platform_driver(&c67x00_of_driver); +} + +static inline void __exit c67x00_of_unregister(void) +{ + of_unregister_platform_driver(&c67x00_of_driver); +} +#else /* CONFIG_OF */ +/* CONFIG_OF not enabled; do nothing helpers */ +static inline int __init c67x00_of_register(void) { return 0; } +static inline void __exit c67x00_of_unregister(void) { } +#endif /* CONFIG_OF */ + static int __init c67x00_init(void) { - return platform_driver_register(&c67x00_driver); + int rc; + + rc = c67x00_of_register(); + if (rc) + goto err_of; + + pr_debug("c67x00: registering platform binding\n"); + rc = platform_driver_register(&c67x00_driver); + if (rc) + goto err_plat; + + return 0; + +err_of: + c67x00_of_unregister(); +err_plat: + printk("c67x00: registration failed; err:%i\n",rc); + return rc; } static void __exit c67x00_exit(void) { + pr_debug("Unregistering c67x00\n"); platform_driver_unregister(&c67x00_driver); + c67x00_of_unregister(); } module_init(c67x00_init); diff --git a/drivers/usb/c67x00/c67x00-ll-hpi.c b/drivers/usb/c67x00/c67x00-ll-hpi.c index a9636f4..2e7061a 100644 --- a/drivers/usb/c67x00/c67x00-ll-hpi.c +++ b/drivers/usb/c67x00/c67x00-ll-hpi.c @@ -219,6 +219,7 @@ void c67x00_ll_hpi_reg_init(struct c67x00_device *dev) for (i = 0; i < C67X00_SIES; i++) { hpi_write_word(dev, SIEMSG_REG(i), 0); hpi_read_word(dev, SIEMSG_REG(i)); + printk("C67X00_DBG:c67x00_ll_hpi_reg_init(): Reg:%d written=0x00 ; read: %d\n",SIEMSG_REG(i)); } } @@ -240,8 +241,9 @@ void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie) static inline u16 ll_recv_msg(struct c67x00_device *dev) { u16 res; - + printk("C67X00_DBG:ll_recv_msg() - calling wait_for_completion_timeout \n"); res = wait_for_completion_timeout(&dev->hpi.lcp.msg_received, 5 * HZ); + printk("C67X00_DBG:ll_recv_msg() res=%d\n", res); WARN_ON(!res); return (res == 0) ? -EIO : 0; @@ -388,10 +390,13 @@ void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status) int c67x00_ll_reset(struct c67x00_device *dev) { int rc; - + mutex_lock(&dev->hpi.lcp.mutex); + printk("C67X00_DBG:c67x00_ll_reset() - Send mbox\n"); hpi_send_mbox(dev, COMM_RESET); + printk("C67X00_DBG:c67x00_ll_reset() - recv_msg\n"); rc = ll_recv_msg(dev); + printk("C67X00_DBG:c67x00_ll_reset() - done recv_msg\n"); mutex_unlock(&dev->hpi.lcp.mutex); return rc;