aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-pxa27x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ohci-pxa27x.c')
-rw-r--r--drivers/usb/host/ohci-pxa27x.c85
1 files changed, 43 insertions, 42 deletions
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 9d65ec30799..c165d1ebed5 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)