On Tuesday 12 December 2006 10:11 am, Sylvain Munaut wrote: > PPC embedded systems can have a ohci controller builtin. In the > new model, it will end up as a driver on the of_platform bus, > this patches takes care of them. > > Signed-off-by: Sylvain Munaut <[EMAIL PROTECTED]> Acked-by: David Brownell <[EMAIL PROTECTED]>
> --- > drivers/usb/host/Kconfig | 23 ++++ > drivers/usb/host/ohci-hcd.c | 20 +++ > drivers/usb/host/ohci-ppc-of.c | 232 > ++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 274 insertions(+), 1 deletions(-) > > diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig > index 8325998..6271187 100644 > --- a/drivers/usb/host/Kconfig > +++ b/drivers/usb/host/Kconfig > @@ -112,9 +112,30 @@ config USB_OHCI_HCD_PPC_SOC > Enables support for the USB controller on the MPC52xx or > STB03xxx processor chip. If unsure, say Y. > > +config USB_OHCI_HCD_PPC_OF > + bool "OHCI support for PPC USB controller on OF platform bus" > + depends on USB_OHCI_HCD && PPC_OF > + default y > + ---help--- > + Enables support for the USB controller PowerPC present on the > + OpenFirmware platform bus. > + > +config USB_OHCI_HCD_PPC_OF_BE > + bool "Support big endian HC" > + depends on USB_OHCI_HCD_PPC_OF > + default y > + select USB_OHCI_BIG_ENDIAN_DESC > + select USB_OHCI_BIG_ENDIAN_MMIO > + > +config USB_OHCI_HCD_PPC_OF_LE > + bool "Support little endian HC" > + depends on USB_OHCI_HCD_PPC_OF > + default n > + select USB_OHCI_LITTLE_ENDIAN > + > config USB_OHCI_HCD_PCI > bool "OHCI support for PCI-bus USB controllers" > - depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx) > + depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || > USB_OHCI_HCD_PPC_OF) > default y > select USB_OHCI_LITTLE_ENDIAN > ---help--- > diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c > index d052041..8797c39 100644 > --- a/drivers/usb/host/ohci-hcd.c > +++ b/drivers/usb/host/ohci-hcd.c > @@ -964,8 +964,14 @@ #include "ohci-pnx4008.c" > #define PLATFORM_DRIVER usb_hcd_pnx4008_driver > #endif > > +#ifdef CONFIG_USB_OHCI_HCD_PPC_OF > +#include "ohci-ppc-of.c" > +#define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver > +#endif > + > #if !defined(PCI_DRIVER) && \ > !defined(PLATFORM_DRIVER) && \ > + !defined(OF_PLATFORM_DRIVER) && \ > !defined(SA1111_DRIVER) > #error "missing bus glue for ohci-hcd" > #endif > @@ -989,6 +995,13 @@ #ifdef PLATFORM_DRIVER > ls++; > #endif > > +#ifdef OF_PLATFORM_DRIVER > + retval = of_register_platform_driver(&OF_PLATFORM_DRIVER); > + if (retval < 0) > + goto error; > + ls++; > +#endif > + > #ifdef SA1111_DRIVER > retval = sa1111_driver_register(&SA1111_DRIVER); > if (retval < 0) > @@ -1011,6 +1024,10 @@ #ifdef PLATFORM_DRIVER > if (ls--) > platform_driver_unregister(&PLATFORM_DRIVER); > #endif > +#ifdef OF_PLATFORM_DRIVER > + if (ls--) > + of_unregister_platform_driver(&OF_PLATFORM_DRIVER); > +#endif > #ifdef SA1111_DRIVER > if (ls--) > sa1111_driver_unregister(&SA1111_DRIVER); > @@ -1027,6 +1044,9 @@ #endif > #ifdef SA1111_DRIVER > sa1111_driver_unregister(&SA1111_DRIVER); > #endif > +#ifdef OF_PLATFORM_DRIVER > + of_unregister_platform_driver(&OF_PLATFORM_DRIVER); > +#endif > #ifdef PLATFORM_DRIVER > platform_driver_unregister(&PLATFORM_DRIVER); > #endif > diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c > new file mode 100644 > index 0000000..84b555b > --- /dev/null > +++ b/drivers/usb/host/ohci-ppc-of.c > @@ -0,0 +1,232 @@ > +/* > + * OHCI HCD (Host Controller Driver) for USB. > + * > + * (C) Copyright 1999 Roman Weissgaerber <[EMAIL PROTECTED]> > + * (C) Copyright 2000-2002 David Brownell <[EMAIL PROTECTED]> > + * (C) Copyright 2002 Hewlett-Packard Company > + * (C) Copyright 2006 Sylvain Munaut <[EMAIL PROTECTED]> > + * > + * Bus glue for OHCI HC on the of_platform bus > + * > + * Modified for of_platform bus from ohci-sa1111.c > + * > + * This file is licenced under the GPL. > + */ > + > +#include <linux/signal.h> > + > +#include <asm/of_platform.h> > +#include <asm/prom.h> > + > + > +static int __devinit > +ohci_ppc_of_start(struct usb_hcd *hcd) > +{ > + struct ohci_hcd *ohci = hcd_to_ohci(hcd); > + int ret; > + > + if ((ret = ohci_init(ohci)) < 0) > + return ret; > + > + if ((ret = ohci_run(ohci)) < 0) { > + err("can't start %s", ohci_to_hcd(ohci)->self.bus_name); > + ohci_stop(hcd); > + return ret; > + } > + > + return 0; > +} > + > +static const struct hc_driver ohci_ppc_of_hc_driver = { > + .description = hcd_name, > + .product_desc = "OF OHCI", > + .hcd_priv_size = sizeof(struct ohci_hcd), > + > + /* > + * generic hardware linkage > + */ > + .irq = ohci_irq, > + .flags = HCD_USB11 | HCD_MEMORY, > + > + /* > + * basic lifecycle operations > + */ > + .start = ohci_ppc_of_start, > + .stop = ohci_stop, > + .shutdown = ohci_shutdown, > + > + /* > + * managing i/o requests and associated device resources > + */ > + .urb_enqueue = ohci_urb_enqueue, > + .urb_dequeue = ohci_urb_dequeue, > + .endpoint_disable = ohci_endpoint_disable, > + > + /* > + * scheduling support > + */ > + .get_frame_number = ohci_get_frame, > + > + /* > + * root hub support > + */ > + .hub_status_data = ohci_hub_status_data, > + .hub_control = ohci_hub_control, > + .hub_irq_enable = ohci_rhsc_enable, > +#ifdef CONFIG_PM > + .bus_suspend = ohci_bus_suspend, > + .bus_resume = ohci_bus_resume, > +#endif > + .start_port_reset = ohci_start_port_reset, > +}; > + > + > +static int __devinit > +ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) > +{ > + struct device_node *dn = op->node; > + struct usb_hcd *hcd; > + struct ohci_hcd *ohci; > + struct resource res; > + int irq; > + > + int rv; > + int is_bigendian; > + > + if (usb_disabled()) > + return -ENODEV; > + > + is_bigendian = > + device_is_compatible(dn, "ohci-bigendian") || > + device_is_compatible(dn, "ohci-be");; > + > + dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n"); > + > + rv = of_address_to_resource(dn, 0, &res); > + if (rv) > + return rv; > + > + hcd = usb_create_hcd(&ohci_ppc_of_hc_driver, &op->dev, "PPC-OF USB"); > + if (!hcd) > + return -ENOMEM; > + > + hcd->rsrc_start = res.start; > + hcd->rsrc_len = res.end - res.start + 1; > + > + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { > + printk(KERN_ERR __FILE__ ": request_mem_region failed\n"); > + rv = -EBUSY; > + goto err_rmr; > + } > + > + irq = irq_of_parse_and_map(dn, 0); > + if (irq == NO_IRQ) { > + printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); > + rv = -EBUSY; > + goto err_irq; > + } > + > + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); > + if (!hcd->regs) { > + printk(KERN_ERR __FILE__ ": ioremap failed\n"); > + rv = -ENOMEM; > + goto err_ioremap; > + } > + > + ohci = hcd_to_ohci(hcd); > + if (is_bigendian) > + ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; > + > + ohci_hcd_init(ohci); > + > + rv = usb_add_hcd(hcd, irq, 0); > + if (rv == 0) > + return 0; > + > + iounmap(hcd->regs); > +err_ioremap: > + irq_dispose_mapping(irq); > +err_irq: > + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); > +err_rmr: > + usb_put_hcd(hcd); > + > + return rv; > +} > + > +static int ohci_hcd_ppc_of_remove(struct of_device *op) > +{ > + struct usb_hcd *hcd = dev_get_drvdata(&op->dev); > + dev_set_drvdata(&op->dev, NULL); > + > + dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); > + > + usb_remove_hcd(hcd); > + > + iounmap(hcd->regs); > + irq_dispose_mapping(hcd->irq); > + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); > + > + usb_put_hcd(hcd); > + > + return 0; > +} > + > +static int ohci_hcd_ppc_of_shutdown(struct of_device *op) > +{ > + struct usb_hcd *hcd = dev_get_drvdata(&op->dev); > + > + if (hcd->driver->shutdown) > + hcd->driver->shutdown(hcd); > + > + return 0; > +} > + > + > +static struct of_device_id ohci_hcd_ppc_of_match[] = { > +#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE > + { > + .name = "usb", > + .compatible = "ohci-bigendian", > + }, > + { > + .name = "usb", > + .compatible = "ohci-be", > + }, > +#endif > +#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_LE > + { > + .name = "usb", > + .compatible = "ohci-littledian", > + }, > + { > + .name = "usb", > + .compatible = "ohci-le", > + }, > +#endif > + {}, > +}; > +MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); > + > +#if !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \ > + !defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE) > +#error "No endianess selected for ppc-of-ohci" > +#endif > + > + > +static struct of_platform_driver ohci_hcd_ppc_of_driver = { > + .name = "ppc-of-ohci", > + .match_table = ohci_hcd_ppc_of_match, > + .probe = ohci_hcd_ppc_of_probe, > + .remove = ohci_hcd_ppc_of_remove, > + .shutdown = ohci_hcd_ppc_of_shutdown, > +#ifdef CONFIG_PM > + /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ > + /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ > +#endif > + .driver = { > + .name = "ppc-of-ohci", > + .owner = THIS_MODULE, > + }, > +}; > + > -- > 1.4.2 > ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel