diff options
Diffstat (limited to 'target/linux/ppc40x/patches-3.3/120-usb-isp116x-hcd-add-of-binding.patch')
-rw-r--r-- | target/linux/ppc40x/patches-3.3/120-usb-isp116x-hcd-add-of-binding.patch | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/target/linux/ppc40x/patches-3.3/120-usb-isp116x-hcd-add-of-binding.patch b/target/linux/ppc40x/patches-3.3/120-usb-isp116x-hcd-add-of-binding.patch new file mode 100644 index 0000000..2f25022 --- /dev/null +++ b/target/linux/ppc40x/patches-3.3/120-usb-isp116x-hcd-add-of-binding.patch @@ -0,0 +1,289 @@ +--- a/drivers/usb/host/isp116x-hcd.c ++++ b/drivers/usb/host/isp116x-hcd.c +@@ -1535,6 +1535,7 @@ static struct hc_driver isp116x_hc_drive + + /*----------------------------------------------------------------*/ + ++#ifdef CONFIG_USB_ISP116X_HCD_PLATFORM + static int isp116x_remove(struct platform_device *pdev) + { + struct usb_hcd *hcd = platform_get_drvdata(pdev); +@@ -1708,22 +1709,249 @@ static struct platform_driver isp116x_dr + }, + }; + ++static inline int isp116x_platform_register(void) ++{ ++ return platform_driver_register(&isp116x_driver); ++} ++ ++static inline void isp116x_platform_unregister(void) ++{ ++ platform_driver_unregister(&isp116x_driver); ++} ++#else ++static inline int isp116x_platform_register(void) { return 0; }; ++static void isp116x_platform_unregister(void) {}; ++#endif /* CONFIG_USB_ISP116X_PLATFORM */ ++ ++/*-----------------------------------------------------------------*/ ++ ++#ifdef CONFIG_USB_ISP116X_HCD_OF ++ ++#include <linux/of_platform.h> ++ ++#ifdef USE_PLATFORM_DELAY ++static void isp116x_of_delay(struct device *ddev, int delay) ++{ ++ ndelay(delay); ++} ++#else ++#define isp116x_of_delay NULL ++#endif ++ ++static int __devinit isp116x_of_probe(struct platform_device *op) ++{ ++ struct device_node *dn = op->dev.of_node; ++ struct usb_hcd *hcd; ++ struct isp116x *isp116x; ++ struct resource addr, data; ++ struct isp116x_platform_data *board; ++ void __iomem *addr_reg; ++ void __iomem *data_reg; ++ int irq; ++ int ret = 0; ++ unsigned long irqflags; ++ ++ ret = of_address_to_resource(dn, 0, &data); ++ if (ret) ++ return ret; ++ ++ ret = of_address_to_resource(dn, 1, &addr); ++ if (ret) ++ return ret; ++ ++ board = kzalloc(sizeof(struct isp116x_platform_data), GFP_KERNEL); ++ if (board == NULL) ++ return -ENOMEM; ++ ++ if (!request_mem_region(addr.start, resource_size(&addr), hcd_name)) { ++ ret = -EBUSY; ++ goto err_free_board; ++ } ++ ++ addr_reg = ioremap_nocache(addr.start, resource_size(&addr)); ++ if (addr_reg == NULL) { ++ ret = -ENOMEM; ++ goto err_release_addr; ++ } ++ ++ if (!request_mem_region(data.start, resource_size(&data), hcd_name)) { ++ ret = -EBUSY; ++ goto err_unmap_addr; ++ } ++ ++ data_reg = ioremap_nocache(data.start, resource_size(&data)); ++ if (data_reg == NULL) { ++ ret = -ENOMEM; ++ goto err_release_data; ++ } ++ ++ irq = irq_of_parse_and_map(dn, 0); ++ if (irq == NO_IRQ) { ++ ret = -EINVAL; ++ goto err_unmap_data; ++ } ++ ++ /* allocate and initialize hcd */ ++ hcd = usb_create_hcd(&isp116x_hc_driver, &op->dev, dev_name(&op->dev)); ++ if (!hcd) { ++ ret = -ENOMEM; ++ goto err_irq_dispose; ++ } ++ ++ /* this rsrc_start is bogus */ ++ hcd->rsrc_start = addr.start; ++ isp116x = hcd_to_isp116x(hcd); ++ isp116x->data_reg = data_reg; ++ isp116x->addr_reg = addr_reg; ++ isp116x->board = board; ++ spin_lock_init(&isp116x->lock); ++ INIT_LIST_HEAD(&isp116x->async); ++ ++ board->delay = isp116x_of_delay; ++ if (of_get_property(dn, "sel15Kres", NULL)) ++ board->sel15Kres = 1; ++ if (of_get_property(dn, "oc_enable", NULL)) ++ board->oc_enable = 1; ++ if (of_get_property(dn, "remote_wakeup_enable", NULL)) ++ board->remote_wakeup_enable = 1; ++ ++ if (of_get_property(dn, "int_act_high", NULL)) ++ board->int_act_high = 1; ++ if (of_get_property(dn, "int_edge_triggered", NULL)) ++ board->int_edge_triggered = 1; ++ ++ if (board->int_edge_triggered) ++ irqflags = board->int_act_high ? IRQF_TRIGGER_RISING : ++ IRQF_TRIGGER_FALLING; ++ else ++ irqflags = board->int_act_high ? IRQF_TRIGGER_HIGH : ++ IRQF_TRIGGER_LOW; ++ ++ ret = usb_add_hcd(hcd, irq, irqflags | IRQF_DISABLED); ++ if (ret) ++ goto err_put_hcd; ++ ++ ret = create_debug_file(isp116x); ++ if (ret) { ++ ERR("Couldn't create debugfs entry\n"); ++ goto err_remove_hcd; ++ } ++ ++ return 0; ++ ++ err_remove_hcd: ++ usb_remove_hcd(hcd); ++ err_put_hcd: ++ usb_put_hcd(hcd); ++ err_irq_dispose: ++ irq_dispose_mapping(irq); ++ err_unmap_data: ++ iounmap(data_reg); ++ err_release_data: ++ release_mem_region(data.start, resource_size(&data)); ++ err_unmap_addr: ++ iounmap(addr_reg); ++ err_release_addr: ++ release_mem_region(addr.start, resource_size(&addr)); ++ err_free_board: ++ kfree(board); ++ return ret; ++} ++ ++static __devexit int isp116x_of_remove(struct platform_device *op) ++{ ++ struct usb_hcd *hcd = dev_get_drvdata(&op->dev); ++ struct isp116x *isp116x; ++ struct resource res; ++ ++ if (!hcd) ++ return 0; ++ ++ dev_set_drvdata(&op->dev, NULL); ++ ++ isp116x = hcd_to_isp116x(hcd); ++ remove_debug_file(isp116x); ++ usb_remove_hcd(hcd); ++ ++ irq_dispose_mapping(hcd->irq); ++ ++ iounmap(isp116x->data_reg); ++ (void) of_address_to_resource(op->dev.of_node, 0, &res); ++ release_mem_region(res.start, resource_size(&res)); ++ ++ iounmap(isp116x->addr_reg); ++ (void) of_address_to_resource(op->dev.of_node, 1, &res); ++ release_mem_region(res.start, resource_size(&res)); ++ ++ kfree(isp116x->board); ++ usb_put_hcd(hcd); ++ ++ return 0; ++} ++ ++static struct of_device_id isp116x_of_match[] = { ++ { .compatible = "isp116x-hcd", }, ++ {}, ++}; ++ ++static struct platform_driver isp116x_of_platform_driver = { ++ .probe = isp116x_of_probe, ++ .remove = __devexit_p(isp116x_of_remove), ++ .driver = { ++ .name = "isp116x-hcd-of", ++ .owner = THIS_MODULE, ++ .of_match_table = isp116x_of_match, ++ }, ++}; ++ ++static int __init isp116x_of_register(void) ++{ ++ return platform_driver_register(&isp116x_of_platform_driver); ++} ++ ++static void __exit isp116x_of_unregister(void) ++{ ++ platform_driver_unregister(&isp116x_of_platform_driver); ++} ++ ++MODULE_DEVICE_TABLE(of, isp116x_of_match); ++ ++#else ++static inline int isp116x_of_register(void) { return 0; }; ++static void isp116x_of_unregister(void) {}; ++#endif /* CONFIG_USB_ISP116X_HCD_OF */ ++ + /*-----------------------------------------------------------------*/ + + static int __init isp116x_init(void) + { ++ int ret; ++ + if (usb_disabled()) + return -ENODEV; + + INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION); +- return platform_driver_register(&isp116x_driver); ++ ret = isp116x_platform_register(); ++ if (ret) ++ return ret; ++ ++ ret = isp116x_of_register(); ++ if (ret) ++ goto err_platform_unregister; ++ ++ return 0; ++ ++ err_platform_unregister: ++ isp116x_platform_unregister(); ++ return ret; + } + + module_init(isp116x_init); + + static void __exit isp116x_cleanup(void) + { +- platform_driver_unregister(&isp116x_driver); ++ isp116x_of_unregister(); ++ isp116x_platform_unregister(); + } + + module_exit(isp116x_cleanup); +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -251,6 +251,24 @@ config USB_ISP116X_HCD + To compile this driver as a module, choose M here: the + module will be called isp116x-hcd. + ++config USB_ISP116X_HCD_PLATFORM ++ bool "ISP116X support for controllers on platform bus" ++ depends on USB_ISP116X_HCD ++ default n if PPC_OF ++ default y ++ ---help--- ++ Enables support for the ISP116x USB controller present on the ++ platform bus. ++ ++config USB_ISP116X_HCD_OF ++ bool "ISP116X support for controllers on OF platform bus" ++ depends on USB_ISP116X_HCD && PPC_OF ++ default y if PPC_OF ++ default n ++ ---help--- ++ Enables support for the ISP116x USB controller present on the ++ OpenFirmware platform bus. ++ + config USB_ISP1760_HCD + tristate "ISP 1760 HCD support" + depends on USB && EXPERIMENTAL |