2 * OHCI HCD (Host Controller Driver) for USB.
4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
5 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
6 * (C) Copyright 2002 Hewlett-Packard Company
10 * Written by Christopher Hoover <ch@hpl.hp.com>
11 * Based on fragments of previous driver by Russell King et al.
13 * Modified for LH7A404 from ohci-sa1111.c
14 * by Durgesh Pattamatta <pattamattad@sharpsec.com>
16 * Modified for pxa27x from ohci-lh7a404.c
17 * by Nick Bane <nick@cecomputing.co.uk> 26-8-2004
19 * This file is licenced under the GPL.
22 #include <linux/device.h>
23 #include <linux/signal.h>
24 #include <linux/platform_device.h>
26 #include <asm/mach-types.h>
27 #include <asm/hardware.h>
28 #include <asm/arch/pxa-regs.h>
29 #include <asm/arch/ohci.h>
31 #define PXA_UHC_MAX_PORTNUM 3
33 #define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 )
36 PMM_NPS_MODE -- PMM Non-power switching mode
37 Ports are powered continuously.
39 PMM_GLOBAL_MODE -- PMM global switching mode
40 All ports are powered at the same time.
42 PMM_PERPORT_MODE -- PMM per port switching mode
43 Ports are powered individually.
45 static int pxa27x_ohci_select_pmm( int mode
)
52 UHCRHDA
&= ~(RH_A_NPS
& RH_A_PSM
);
54 case PMM_PERPORT_MODE
:
55 UHCRHDA
&= ~(RH_A_NPS
);
58 /* Set port power control mask bits, only 3 ports. */
63 "Invalid mode %d, set to non-power switch mode.\n",
72 extern int usb_disabled(void);
74 /*-------------------------------------------------------------------------*/
76 static int pxa27x_start_hc(struct device
*dev
)
79 struct pxaohci_platform_data
*inf
;
81 inf
= dev
->platform_data
;
83 pxa_set_cken(CKEN_USBHOST
, 1);
90 while (UHCHR
& UHCHR_FSBIR
)
94 retval
= inf
->init(dev
);
101 UHCHIE
= (UHCHIE_UPRIE
| UHCHIE_RWIE
);
103 /* Clear any OTG Pin Hold */
104 if (PSSR
& PSSR_OTGPH
)
110 static void pxa27x_stop_hc(struct device
*dev
)
112 struct pxaohci_platform_data
*inf
;
114 inf
= dev
->platform_data
;
126 pxa_set_cken(CKEN_USBHOST
, 0);
130 /*-------------------------------------------------------------------------*/
132 /* configure so an HC device and id are always provided */
133 /* always called with process context; sleeping is OK */
137 * usb_hcd_pxa27x_probe - initialize pxa27x-based HCDs
138 * Context: !in_interrupt()
140 * Allocates basic resources for this USB host controller, and
141 * then invokes the start() method for the HCD associated with it
142 * through the hotplug entry's driver_data.
145 int usb_hcd_pxa27x_probe (const struct hc_driver
*driver
, struct platform_device
*pdev
)
149 struct pxaohci_platform_data
*inf
;
151 inf
= pdev
->dev
.platform_data
;
156 if (pdev
->resource
[1].flags
!= IORESOURCE_IRQ
) {
157 pr_debug ("resource[1] is not IORESOURCE_IRQ");
161 hcd
= usb_create_hcd (driver
, &pdev
->dev
, "pxa27x");
164 hcd
->rsrc_start
= pdev
->resource
[0].start
;
165 hcd
->rsrc_len
= pdev
->resource
[0].end
- pdev
->resource
[0].start
+ 1;
167 if (!request_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
, hcd_name
)) {
168 pr_debug("request_mem_region failed");
173 hcd
->regs
= ioremap(hcd
->rsrc_start
, hcd
->rsrc_len
);
175 pr_debug("ioremap failed");
180 if ((retval
= pxa27x_start_hc(&pdev
->dev
)) < 0) {
181 pr_debug("pxa27x_start_hc failed");
185 /* Select Power Management Mode */
186 pxa27x_ohci_select_pmm(inf
->port_mode
);
188 if (inf
->power_budget
)
189 hcd
->power_budget
= inf
->power_budget
;
191 ohci_hcd_init(hcd_to_ohci(hcd
));
193 retval
= usb_add_hcd(hcd
, pdev
->resource
[1].start
, IRQF_DISABLED
);
197 pxa27x_stop_hc(&pdev
->dev
);
201 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
208 /* may be called without controller electrically present */
209 /* may be called with controller, bus, and devices active */
212 * usb_hcd_pxa27x_remove - shutdown processing for pxa27x-based HCDs
213 * @dev: USB Host Controller being removed
214 * Context: !in_interrupt()
216 * Reverses the effect of usb_hcd_pxa27x_probe(), first invoking
217 * the HCD's stop() method. It is always called from a thread
218 * context, normally "rmmod", "apmd", or something similar.
221 void usb_hcd_pxa27x_remove (struct usb_hcd
*hcd
, struct platform_device
*pdev
)
224 pxa27x_stop_hc(&pdev
->dev
);
226 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
230 /*-------------------------------------------------------------------------*/
233 ohci_pxa27x_start (struct usb_hcd
*hcd
)
235 struct ohci_hcd
*ohci
= hcd_to_ohci (hcd
);
238 ohci_dbg (ohci
, "ohci_pxa27x_start, ohci:%p", ohci
);
240 /* The value of NDP in roothub_a is incorrect on this hardware */
243 if ((ret
= ohci_init(ohci
)) < 0)
246 if ((ret
= ohci_run (ohci
)) < 0) {
247 err ("can't start %s", hcd
->self
.bus_name
);
255 /*-------------------------------------------------------------------------*/
257 static const struct hc_driver ohci_pxa27x_hc_driver
= {
258 .description
= hcd_name
,
259 .product_desc
= "PXA27x OHCI",
260 .hcd_priv_size
= sizeof(struct ohci_hcd
),
263 * generic hardware linkage
266 .flags
= HCD_USB11
| HCD_MEMORY
,
269 * basic lifecycle operations
271 .start
= ohci_pxa27x_start
,
273 .shutdown
= ohci_shutdown
,
276 * managing i/o requests and associated device resources
278 .urb_enqueue
= ohci_urb_enqueue
,
279 .urb_dequeue
= ohci_urb_dequeue
,
280 .endpoint_disable
= ohci_endpoint_disable
,
285 .get_frame_number
= ohci_get_frame
,
290 .hub_status_data
= ohci_hub_status_data
,
291 .hub_control
= ohci_hub_control
,
292 .hub_irq_enable
= ohci_rhsc_enable
,
294 .bus_suspend
= ohci_bus_suspend
,
295 .bus_resume
= ohci_bus_resume
,
297 .start_port_reset
= ohci_start_port_reset
,
300 /*-------------------------------------------------------------------------*/
302 static int ohci_hcd_pxa27x_drv_probe(struct platform_device
*pdev
)
304 pr_debug ("In ohci_hcd_pxa27x_drv_probe");
309 return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver
, pdev
);
312 static int ohci_hcd_pxa27x_drv_remove(struct platform_device
*pdev
)
314 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
316 usb_hcd_pxa27x_remove(hcd
, pdev
);
317 platform_set_drvdata(pdev
, NULL
);
322 static int ohci_hcd_pxa27x_drv_suspend(struct platform_device
*pdev
, pm_message_t state
)
324 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
325 struct ohci_hcd
*ohci
= hcd_to_ohci(hcd
);
327 if (time_before(jiffies
, ohci
->next_statechange
))
329 ohci
->next_statechange
= jiffies
;
331 pxa27x_stop_hc(&pdev
->dev
);
332 hcd
->state
= HC_STATE_SUSPENDED
;
333 pdev
->dev
.power
.power_state
= PMSG_SUSPEND
;
338 static int ohci_hcd_pxa27x_drv_resume(struct platform_device
*pdev
)
340 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
341 struct ohci_hcd
*ohci
= hcd_to_ohci(hcd
);
344 if (time_before(jiffies
, ohci
->next_statechange
))
346 ohci
->next_statechange
= jiffies
;
348 if ((status
= pxa27x_start_hc(&pdev
->dev
)) < 0)
351 pdev
->dev
.power
.power_state
= PMSG_ON
;
352 usb_hcd_resume_root_hub(hcd
);
359 static struct platform_driver ohci_hcd_pxa27x_driver
= {
360 .probe
= ohci_hcd_pxa27x_drv_probe
,
361 .remove
= ohci_hcd_pxa27x_drv_remove
,
362 .shutdown
= usb_hcd_platform_shutdown
,
364 .suspend
= ohci_hcd_pxa27x_drv_suspend
,
365 .resume
= ohci_hcd_pxa27x_drv_resume
,
368 .name
= "pxa27x-ohci",