@@ -39,6 +39,10 @@
#include <linux/list.h>
#include <linux/usb.h>
#include <linux/usb/c67x00.h>
+#if defined(CONFIG_OF)
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#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);
@@ -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;