From rpurdie@rpsys.net Sat Nov 12 06:24:32 2005 From: Richard Purdie Subject: [usb patch 1/2] pxa27x OHCI - Separate platform code from main driver To: Greg KH Date: Sat, 12 Nov 2005 14:22:11 +0000 Message-Id: <1131805332.7597.17.camel@localhost.localdomain> To allow multiple platforms to use the PXA27x OHCI driver, the platform code needs to be moved into the board specific files in arch/arm/mach-pxa. This patch does this for mainstone and adds preliminary hooks to allow other boards to use the driver. This has been compile tested for mainstone and successfully run on Spitz (Sharp Zaurus SL-C3000) with the addition of an appropriate board support file. Signed-off-by: Richard Purdie Signed-off-by: Nicolas Pitre Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/mainstone.c | 21 +++++++++ arch/arm/mach-pxa/pxa27x.c | 6 ++ drivers/usb/host/ohci-pxa27x.c | 85 ++++++++++++++++++++-------------------- include/asm-arm/arch-pxa/ohci.h | 18 ++++++++ 4 files changed, 88 insertions(+), 42 deletions(-) --- gregkh-2.6.orig/drivers/usb/host/ohci-pxa27x.c +++ gregkh-2.6/drivers/usb/host/ohci-pxa27x.c @@ -26,18 +26,12 @@ #include #include #include - - -#define PMM_NPS_MODE 1 -#define PMM_GLOBAL_MODE 2 -#define PMM_PERPORT_MODE 3 +#include #define PXA_UHC_MAX_PORTNUM 3 #define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 ) -static int pxa27x_ohci_pmm_state; - /* PMM_NPS_MODE -- PMM Non-power switching mode Ports are powered continuously. @@ -50,8 +44,6 @@ static int pxa27x_ohci_pmm_state; */ static int pxa27x_ohci_select_pmm( int mode ) { - pxa27x_ohci_pmm_state = mode; - switch ( mode ) { case PMM_NPS_MODE: UHCRHDA |= RH_A_NPS; @@ -71,7 +63,6 @@ static int pxa27x_ohci_select_pmm( int m "Invalid mode %d, set to non-power switch mode.\n", mode ); - pxa27x_ohci_pmm_state = PMM_NPS_MODE; UHCRHDA |= RH_A_NPS; } @@ -82,8 +73,13 @@ extern int usb_disabled(void); /*-------------------------------------------------------------------------*/ -static void pxa27x_start_hc(struct platform_device *dev) +static int pxa27x_start_hc(struct device *dev) { + int retval = 0; + struct pxaohci_platform_data *inf; + + inf = dev->platform_data; + pxa_set_cken(CKEN10_USBHOST, 1); UHCHR |= UHCHR_FHR; @@ -94,21 +90,11 @@ static void pxa27x_start_hc(struct platf while (UHCHR & UHCHR_FSBIR) cpu_relax(); - /* This could be properly abstracted away through the - device data the day more machines are supported and - their differences can be figured out correctly. */ - if (machine_is_mainstone()) { - /* setup Port1 GPIO pin. */ - pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ - pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ - - /* Set the Power Control Polarity Low and Power Sense - Polarity Low to active low. Supply power to USB ports. */ - UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & - ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); + if (inf->init) + retval = inf->init(dev); - pxa27x_ohci_pmm_state = PMM_PERPORT_MODE; - } + if (retval < 0) + return retval; UHCHR &= ~UHCHR_SSE; @@ -117,10 +103,19 @@ static void pxa27x_start_hc(struct platf /* Clear any OTG Pin Hold */ if (PSSR & PSSR_OTGPH) PSSR |= PSSR_OTGPH; + + return 0; } -static void pxa27x_stop_hc(struct platform_device *dev) +static void pxa27x_stop_hc(struct device *dev) { + struct pxaohci_platform_data *inf; + + inf = dev->platform_data; + + if (inf->exit) + inf->exit(dev); + UHCHR |= UHCHR_FHR; udelay(11); UHCHR &= ~UHCHR_FHR; @@ -147,22 +142,27 @@ static void pxa27x_stop_hc(struct platfo * through the hotplug entry's driver_data. * */ -int usb_hcd_pxa27x_probe (const struct hc_driver *driver, - struct platform_device *dev) +int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev) { int retval; struct usb_hcd *hcd; + struct pxaohci_platform_data *inf; + + inf = pdev->dev.platform_data; - if (dev->resource[1].flags != IORESOURCE_IRQ) { + if (!inf) + return -ENODEV; + + if (pdev->resource[1].flags != IORESOURCE_IRQ) { pr_debug ("resource[1] is not IORESOURCE_IRQ"); return -ENOMEM; } - hcd = usb_create_hcd (driver, &dev->dev, "pxa27x"); + hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x"); if (!hcd) return -ENOMEM; - hcd->rsrc_start = dev->resource[0].start; - hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; + hcd->rsrc_start = pdev->resource[0].start; + hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { pr_debug("request_mem_region failed"); @@ -177,18 +177,22 @@ int usb_hcd_pxa27x_probe (const struct h goto err2; } - pxa27x_start_hc(dev); + if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) { + pr_debug("pxa27x_start_hc failed"); + goto err3; + } /* Select Power Management Mode */ - pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state); + pxa27x_ohci_select_pmm(inf->port_mode); ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); + retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT); if (retval == 0) return retval; - pxa27x_stop_hc(dev); + pxa27x_stop_hc(&pdev->dev); + err3: iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); @@ -211,10 +215,10 @@ int usb_hcd_pxa27x_probe (const struct h * context, normally "rmmod", "apmd", or something similar. * */ -void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev) +void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev) { usb_remove_hcd(hcd); - pxa27x_stop_hc(dev); + pxa27x_stop_hc(&pdev->dev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); @@ -292,15 +296,12 @@ static const struct hc_driver ohci_pxa27 static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev) { - int ret; - pr_debug ("In ohci_hcd_pxa27x_drv_probe"); if (usb_disabled()) return -ENODEV; - ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev); - return ret; + return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev); } static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) --- gregkh-2.6.orig/arch/arm/mach-pxa/pxa27x.c +++ gregkh-2.6/arch/arm/mach-pxa/pxa27x.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "generic.h" @@ -194,6 +195,11 @@ static struct platform_device ohci_devic .resource = pxa27x_ohci_resources, }; +void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) +{ + ohci_device.dev.platform_data = info; +} + static struct platform_device *devices[] __initdata = { &ohci_device, }; --- /dev/null +++ gregkh-2.6/include/asm-arm/arch-pxa/ohci.h @@ -0,0 +1,18 @@ +#ifndef ASMARM_ARCH_OHCI_H +#define ASMARM_ARCH_OHCI_H + +struct device; + +struct pxaohci_platform_data { + int (*init)(struct device *); + void (*exit)(struct device *); + + int port_mode; +#define PMM_NPS_MODE 1 +#define PMM_GLOBAL_MODE 2 +#define PMM_PERPORT_MODE 3 +}; + +extern void pxa_set_ohci_info(struct pxaohci_platform_data *info); + +#endif --- gregkh-2.6.orig/arch/arm/mach-pxa/mainstone.c +++ gregkh-2.6/arch/arm/mach-pxa/mainstone.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "generic.h" @@ -393,6 +394,25 @@ static struct platform_device *platform_ &mst_flash_device[1], }; +static int mainstone_ohci_init(struct device *dev) +{ + /* setup Port1 GPIO pin. */ + pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ + pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ + + /* Set the Power Control Polarity Low and Power Sense + Polarity Low to active low. */ + UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & + ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); + + return 0; +} + +static struct pxaohci_platform_data mainstone_ohci_platform_data = { + .port_mode = PMM_PERPORT_MODE, + .init = mainstone_ohci_init, +}; + static void __init mainstone_init(void) { int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */ @@ -424,6 +444,7 @@ static void __init mainstone_init(void) pxa_set_mci_info(&mainstone_mci_platform_data); pxa_set_ficp_info(&mainstone_ficp_platform_data); + pxa_set_ohci_info(&mainstone_ohci_platform_data); }