diff options
-rw-r--r-- | arch/arm/mach-pxa/mainstone.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pxa27x.c | 85 | ||||
-rw-r--r-- | include/asm-arm/arch-pxa/ohci.h | 18 |
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 | ||
397 | static 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 | |||
411 | static struct pxaohci_platform_data mainstone_ohci_platform_data = { | ||
412 | .port_mode = PMM_PERPORT_MODE, | ||
413 | .init = mainstone_ohci_init, | ||
414 | }; | ||
415 | |||
396 | static void __init mainstone_init(void) | 416 | static 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 | ||
198 | void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) | ||
199 | { | ||
200 | ohci_device.dev.platform_data = info; | ||
201 | } | ||
202 | |||
197 | static struct platform_device *devices[] __initdata = { | 203 | static 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 | ||
39 | static 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 | */ |
51 | static int pxa27x_ohci_select_pmm( int mode ) | 45 | static 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 | ||
85 | static void pxa27x_start_hc(struct platform_device *dev) | 76 | static 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 | ||
122 | static void pxa27x_stop_hc(struct platform_device *dev) | 110 | static 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 | */ |
150 | int usb_hcd_pxa27x_probe (const struct hc_driver *driver, | 145 | int 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 | */ |
214 | void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev) | 218 | void 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 | ||
293 | static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev) | 297 | static 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 | ||
306 | static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) | 307 | static 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 | |||
4 | struct device; | ||
5 | |||
6 | struct 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 | |||
16 | extern void pxa_set_ohci_info(struct pxaohci_platform_data *info); | ||
17 | |||
18 | #endif | ||