aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@rpsys.net>2005-11-12 09:22:11 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-04 16:48:28 -0500
commit81f280e22f14d6d976620acaa1b346a90f4e1adc (patch)
tree298db1ef614489451fecdd35439c630c8086a368
parent88026842b0a760145aa71d69e74fbc9ec118ca44 (diff)
[PATCH] USB: pxa27x OHCI - Separate platform code from main driver
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 <rpurdie@rpsys.net> Signed-off-by: Nicolas Pitre <nico@cam.org> Acked-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/arm/mach-pxa/mainstone.c21
-rw-r--r--arch/arm/mach-pxa/pxa27x.c6
-rw-r--r--drivers/usb/host/ohci-pxa27x.c85
-rw-r--r--include/asm-arm/arch-pxa/ohci.h18
4 files changed, 88 insertions, 42 deletions
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 07892f4012d8..277498ae5b6c 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -43,6 +43,7 @@
43#include <asm/arch/pxafb.h> 43#include <asm/arch/pxafb.h>
44#include <asm/arch/mmc.h> 44#include <asm/arch/mmc.h>
45#include <asm/arch/irda.h> 45#include <asm/arch/irda.h>
46#include <asm/arch/ohci.h>
46 47
47#include "generic.h" 48#include "generic.h"
48 49
@@ -393,6 +394,25 @@ static struct platform_device *platform_devices[] __initdata = {
393 &mst_flash_device[1], 394 &mst_flash_device[1],
394}; 395};
395 396
397static int mainstone_ohci_init(struct device *dev)
398{
399 /* setup Port1 GPIO pin. */
400 pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
401 pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
402
403 /* Set the Power Control Polarity Low and Power Sense
404 Polarity Low to active low. */
405 UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
406 ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
407
408 return 0;
409}
410
411static struct pxaohci_platform_data mainstone_ohci_platform_data = {
412 .port_mode = PMM_PERPORT_MODE,
413 .init = mainstone_ohci_init,
414};
415
396static void __init mainstone_init(void) 416static void __init mainstone_init(void)
397{ 417{
398 int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */ 418 int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
@@ -424,6 +444,7 @@ static void __init mainstone_init(void)
424 444
425 pxa_set_mci_info(&mainstone_mci_platform_data); 445 pxa_set_mci_info(&mainstone_mci_platform_data);
426 pxa_set_ficp_info(&mainstone_ficp_platform_data); 446 pxa_set_ficp_info(&mainstone_ficp_platform_data);
447 pxa_set_ohci_info(&mainstone_ohci_platform_data);
427} 448}
428 449
429 450
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index c722a9a91fcc..b41b1efaa2cf 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -21,6 +21,7 @@
21#include <asm/hardware.h> 21#include <asm/hardware.h>
22#include <asm/irq.h> 22#include <asm/irq.h>
23#include <asm/arch/pxa-regs.h> 23#include <asm/arch/pxa-regs.h>
24#include <asm/arch/ohci.h>
24 25
25#include "generic.h" 26#include "generic.h"
26 27
@@ -194,6 +195,11 @@ static struct platform_device ohci_device = {
194 .resource = pxa27x_ohci_resources, 195 .resource = pxa27x_ohci_resources,
195}; 196};
196 197
198void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
199{
200 ohci_device.dev.platform_data = info;
201}
202
197static struct platform_device *devices[] __initdata = { 203static struct platform_device *devices[] __initdata = {
198 &ohci_device, 204 &ohci_device,
199}; 205};
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 9d65ec307990..c165d1ebed5c 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -26,18 +26,12 @@
26#include <asm/mach-types.h> 26#include <asm/mach-types.h>
27#include <asm/hardware.h> 27#include <asm/hardware.h>
28#include <asm/arch/pxa-regs.h> 28#include <asm/arch/pxa-regs.h>
29 29#include <asm/arch/ohci.h>
30
31#define PMM_NPS_MODE 1
32#define PMM_GLOBAL_MODE 2
33#define PMM_PERPORT_MODE 3
34 30
35#define PXA_UHC_MAX_PORTNUM 3 31#define PXA_UHC_MAX_PORTNUM 3
36 32
37#define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 ) 33#define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 )
38 34
39static int pxa27x_ohci_pmm_state;
40
41/* 35/*
42 PMM_NPS_MODE -- PMM Non-power switching mode 36 PMM_NPS_MODE -- PMM Non-power switching mode
43 Ports are powered continuously. 37 Ports are powered continuously.
@@ -50,8 +44,6 @@ static int pxa27x_ohci_pmm_state;
50 */ 44 */
51static int pxa27x_ohci_select_pmm( int mode ) 45static int pxa27x_ohci_select_pmm( int mode )
52{ 46{
53 pxa27x_ohci_pmm_state = mode;
54
55 switch ( mode ) { 47 switch ( mode ) {
56 case PMM_NPS_MODE: 48 case PMM_NPS_MODE:
57 UHCRHDA |= RH_A_NPS; 49 UHCRHDA |= RH_A_NPS;
@@ -71,7 +63,6 @@ static int pxa27x_ohci_select_pmm( int mode )
71 "Invalid mode %d, set to non-power switch mode.\n", 63 "Invalid mode %d, set to non-power switch mode.\n",
72 mode ); 64 mode );
73 65
74 pxa27x_ohci_pmm_state = PMM_NPS_MODE;
75 UHCRHDA |= RH_A_NPS; 66 UHCRHDA |= RH_A_NPS;
76 } 67 }
77 68
@@ -82,8 +73,13 @@ extern int usb_disabled(void);
82 73
83/*-------------------------------------------------------------------------*/ 74/*-------------------------------------------------------------------------*/
84 75
85static void pxa27x_start_hc(struct platform_device *dev) 76static int pxa27x_start_hc(struct device *dev)
86{ 77{
78 int retval = 0;
79 struct pxaohci_platform_data *inf;
80
81 inf = dev->platform_data;
82
87 pxa_set_cken(CKEN10_USBHOST, 1); 83 pxa_set_cken(CKEN10_USBHOST, 1);
88 84
89 UHCHR |= UHCHR_FHR; 85 UHCHR |= UHCHR_FHR;
@@ -94,21 +90,11 @@ static void pxa27x_start_hc(struct platform_device *dev)
94 while (UHCHR & UHCHR_FSBIR) 90 while (UHCHR & UHCHR_FSBIR)
95 cpu_relax(); 91 cpu_relax();
96 92
97 /* This could be properly abstracted away through the 93 if (inf->init)
98 device data the day more machines are supported and 94 retval = inf->init(dev);
99 their differences can be figured out correctly. */
100 if (machine_is_mainstone()) {
101 /* setup Port1 GPIO pin. */
102 pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
103 pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
104
105 /* Set the Power Control Polarity Low and Power Sense
106 Polarity Low to active low. Supply power to USB ports. */
107 UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
108 ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
109 95
110 pxa27x_ohci_pmm_state = PMM_PERPORT_MODE; 96 if (retval < 0)
111 } 97 return retval;
112 98
113 UHCHR &= ~UHCHR_SSE; 99 UHCHR &= ~UHCHR_SSE;
114 100
@@ -117,10 +103,19 @@ static void pxa27x_start_hc(struct platform_device *dev)
117 /* Clear any OTG Pin Hold */ 103 /* Clear any OTG Pin Hold */
118 if (PSSR & PSSR_OTGPH) 104 if (PSSR & PSSR_OTGPH)
119 PSSR |= PSSR_OTGPH; 105 PSSR |= PSSR_OTGPH;
106
107 return 0;
120} 108}
121 109
122static void pxa27x_stop_hc(struct platform_device *dev) 110static void pxa27x_stop_hc(struct device *dev)
123{ 111{
112 struct pxaohci_platform_data *inf;
113
114 inf = dev->platform_data;
115
116 if (inf->exit)
117 inf->exit(dev);
118
124 UHCHR |= UHCHR_FHR; 119 UHCHR |= UHCHR_FHR;
125 udelay(11); 120 udelay(11);
126 UHCHR &= ~UHCHR_FHR; 121 UHCHR &= ~UHCHR_FHR;
@@ -147,22 +142,27 @@ static void pxa27x_stop_hc(struct platform_device *dev)
147 * through the hotplug entry's driver_data. 142 * through the hotplug entry's driver_data.
148 * 143 *
149 */ 144 */
150int usb_hcd_pxa27x_probe (const struct hc_driver *driver, 145int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev)
151 struct platform_device *dev)
152{ 146{
153 int retval; 147 int retval;
154 struct usb_hcd *hcd; 148 struct usb_hcd *hcd;
149 struct pxaohci_platform_data *inf;
150
151 inf = pdev->dev.platform_data;
155 152
156 if (dev->resource[1].flags != IORESOURCE_IRQ) { 153 if (!inf)
154 return -ENODEV;
155
156 if (pdev->resource[1].flags != IORESOURCE_IRQ) {
157 pr_debug ("resource[1] is not IORESOURCE_IRQ"); 157 pr_debug ("resource[1] is not IORESOURCE_IRQ");
158 return -ENOMEM; 158 return -ENOMEM;
159 } 159 }
160 160
161 hcd = usb_create_hcd (driver, &dev->dev, "pxa27x"); 161 hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
162 if (!hcd) 162 if (!hcd)
163 return -ENOMEM; 163 return -ENOMEM;
164 hcd->rsrc_start = dev->resource[0].start; 164 hcd->rsrc_start = pdev->resource[0].start;
165 hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; 165 hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
166 166
167 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 167 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
168 pr_debug("request_mem_region failed"); 168 pr_debug("request_mem_region failed");
@@ -177,18 +177,22 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
177 goto err2; 177 goto err2;
178 } 178 }
179 179
180 pxa27x_start_hc(dev); 180 if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) {
181 pr_debug("pxa27x_start_hc failed");
182 goto err3;
183 }
181 184
182 /* Select Power Management Mode */ 185 /* Select Power Management Mode */
183 pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state); 186 pxa27x_ohci_select_pmm(inf->port_mode);
184 187
185 ohci_hcd_init(hcd_to_ohci(hcd)); 188 ohci_hcd_init(hcd_to_ohci(hcd));
186 189
187 retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); 190 retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
188 if (retval == 0) 191 if (retval == 0)
189 return retval; 192 return retval;
190 193
191 pxa27x_stop_hc(dev); 194 pxa27x_stop_hc(&pdev->dev);
195 err3:
192 iounmap(hcd->regs); 196 iounmap(hcd->regs);
193 err2: 197 err2:
194 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 198 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
@@ -211,10 +215,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
211 * context, normally "rmmod", "apmd", or something similar. 215 * context, normally "rmmod", "apmd", or something similar.
212 * 216 *
213 */ 217 */
214void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev) 218void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
215{ 219{
216 usb_remove_hcd(hcd); 220 usb_remove_hcd(hcd);
217 pxa27x_stop_hc(dev); 221 pxa27x_stop_hc(&pdev->dev);
218 iounmap(hcd->regs); 222 iounmap(hcd->regs);
219 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 223 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
220 usb_put_hcd(hcd); 224 usb_put_hcd(hcd);
@@ -292,15 +296,12 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
292 296
293static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev) 297static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
294{ 298{
295 int ret;
296
297 pr_debug ("In ohci_hcd_pxa27x_drv_probe"); 299 pr_debug ("In ohci_hcd_pxa27x_drv_probe");
298 300
299 if (usb_disabled()) 301 if (usb_disabled())
300 return -ENODEV; 302 return -ENODEV;
301 303
302 ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev); 304 return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
303 return ret;
304} 305}
305 306
306static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) 307static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
diff --git a/include/asm-arm/arch-pxa/ohci.h b/include/asm-arm/arch-pxa/ohci.h
new file mode 100644
index 000000000000..7da89569061e
--- /dev/null
+++ b/include/asm-arm/arch-pxa/ohci.h
@@ -0,0 +1,18 @@
1#ifndef ASMARM_ARCH_OHCI_H
2#define ASMARM_ARCH_OHCI_H
3
4struct device;
5
6struct pxaohci_platform_data {
7 int (*init)(struct device *);
8 void (*exit)(struct device *);
9
10 int port_mode;
11#define PMM_NPS_MODE 1
12#define PMM_GLOBAL_MODE 2
13#define PMM_PERPORT_MODE 3
14};
15
16extern void pxa_set_ohci_info(struct pxaohci_platform_data *info);
17
18#endif