2 * EHCI HCD (Host Controller Driver) for USB.
4 * Bus Glue for AMD Alchemy Au1xxx
6 * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
8 * Modified for AMD Alchemy Au1200 EHC
9 * by K.Boge <karsten.boge@amd.com>
11 * This file is licenced under the GPL.
14 #include <linux/platform_device.h>
15 #include <asm/mach-au1x00/au1000.h>
18 extern int usb_disabled(void);
20 static int au1xxx_ehci_setup(struct usb_hcd
*hcd
)
22 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
23 int ret
= ehci_init(hcd
);
25 ehci
->need_io_watchdog
= 0;
30 static const struct hc_driver ehci_au1xxx_hc_driver
= {
31 .description
= hcd_name
,
32 .product_desc
= "Au1xxx EHCI",
33 .hcd_priv_size
= sizeof(struct ehci_hcd
),
36 * generic hardware linkage
39 .flags
= HCD_MEMORY
| HCD_USB2
,
42 * basic lifecycle operations
44 * FIXME -- ehci_init() doesn't do enough here.
45 * See ehci-ppc-soc for a complete implementation.
47 .reset
= au1xxx_ehci_setup
,
50 .shutdown
= ehci_shutdown
,
53 * managing i/o requests and associated device resources
55 .urb_enqueue
= ehci_urb_enqueue
,
56 .urb_dequeue
= ehci_urb_dequeue
,
57 .endpoint_disable
= ehci_endpoint_disable
,
58 .endpoint_reset
= ehci_endpoint_reset
,
63 .get_frame_number
= ehci_get_frame
,
68 .hub_status_data
= ehci_hub_status_data
,
69 .hub_control
= ehci_hub_control
,
70 .bus_suspend
= ehci_bus_suspend
,
71 .bus_resume
= ehci_bus_resume
,
72 .relinquish_port
= ehci_relinquish_port
,
73 .port_handed_over
= ehci_port_handed_over
,
75 .clear_tt_buffer_complete
= ehci_clear_tt_buffer_complete
,
78 static int ehci_hcd_au1xxx_drv_probe(struct platform_device
*pdev
)
81 struct ehci_hcd
*ehci
;
88 if (pdev
->resource
[1].flags
!= IORESOURCE_IRQ
) {
89 pr_debug("resource[1] is not IORESOURCE_IRQ");
92 hcd
= usb_create_hcd(&ehci_au1xxx_hc_driver
, &pdev
->dev
, "Au1xxx");
96 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
97 hcd
->rsrc_start
= res
->start
;
98 hcd
->rsrc_len
= resource_size(res
);
100 if (!request_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
, hcd_name
)) {
101 pr_debug("request_mem_region failed");
106 hcd
->regs
= ioremap(hcd
->rsrc_start
, hcd
->rsrc_len
);
108 pr_debug("ioremap failed");
113 if (alchemy_usb_control(ALCHEMY_USB_EHCI0
, 1)) {
114 printk(KERN_INFO
"%s: controller init failed!\n", pdev
->name
);
119 ehci
= hcd_to_ehci(hcd
);
120 ehci
->caps
= hcd
->regs
;
121 ehci
->regs
= hcd
->regs
+
122 HC_LENGTH(ehci
, readl(&ehci
->caps
->hc_capbase
));
123 /* cache this readonly data; minimize chip reads */
124 ehci
->hcs_params
= readl(&ehci
->caps
->hcs_params
);
126 ret
= usb_add_hcd(hcd
, pdev
->resource
[1].start
,
129 platform_set_drvdata(pdev
, hcd
);
133 alchemy_usb_control(ALCHEMY_USB_EHCI0
, 0);
137 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
143 static int ehci_hcd_au1xxx_drv_remove(struct platform_device
*pdev
)
145 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
148 alchemy_usb_control(ALCHEMY_USB_EHCI0
, 0);
150 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
152 platform_set_drvdata(pdev
, NULL
);
158 static int ehci_hcd_au1xxx_drv_suspend(struct device
*dev
)
160 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
161 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
165 if (time_before(jiffies
, ehci
->next_statechange
))
168 /* Root hub was already suspended. Disable irq emission and
169 * mark HW unaccessible. The PM and USB cores make sure that
170 * the root hub is either suspended or stopped.
172 ehci_prepare_ports_for_controller_suspend(ehci
, device_may_wakeup(dev
));
173 spin_lock_irqsave(&ehci
->lock
, flags
);
174 ehci_writel(ehci
, 0, &ehci
->regs
->intr_enable
);
175 (void)ehci_readl(ehci
, &ehci
->regs
->intr_enable
);
177 clear_bit(HCD_FLAG_HW_ACCESSIBLE
, &hcd
->flags
);
178 spin_unlock_irqrestore(&ehci
->lock
, flags
);
180 // could save FLADJ in case of Vaux power loss
181 // ... we'd only use it to handle clock skew
183 alchemy_usb_control(ALCHEMY_USB_EHCI0
, 0);
188 static int ehci_hcd_au1xxx_drv_resume(struct device
*dev
)
190 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
191 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
193 alchemy_usb_control(ALCHEMY_USB_EHCI0
, 1);
195 // maybe restore FLADJ
197 if (time_before(jiffies
, ehci
->next_statechange
))
200 /* Mark hardware accessible again as we are out of D3 state by now */
201 set_bit(HCD_FLAG_HW_ACCESSIBLE
, &hcd
->flags
);
203 /* If CF is still set, we maintained PCI Vaux power.
204 * Just undo the effect of ehci_pci_suspend().
206 if (ehci_readl(ehci
, &ehci
->regs
->configured_flag
) == FLAG_CF
) {
207 int mask
= INTR_MASK
;
209 ehci_prepare_ports_for_controller_resume(ehci
);
210 if (!hcd
->self
.root_hub
->do_remote_wakeup
)
212 ehci_writel(ehci
, mask
, &ehci
->regs
->intr_enable
);
213 ehci_readl(ehci
, &ehci
->regs
->intr_enable
);
217 ehci_dbg(ehci
, "lost power, restarting\n");
218 usb_root_hub_lost_power(hcd
->self
.root_hub
);
220 /* Else reset, to cope with power loss or flush-to-storage
221 * style "resume" having let BIOS kick in during reboot.
223 (void) ehci_halt(ehci
);
224 (void) ehci_reset(ehci
);
226 /* emptying the schedule aborts any urbs */
227 spin_lock_irq(&ehci
->lock
);
229 end_unlink_async(ehci
);
231 spin_unlock_irq(&ehci
->lock
);
233 ehci_writel(ehci
, ehci
->command
, &ehci
->regs
->command
);
234 ehci_writel(ehci
, FLAG_CF
, &ehci
->regs
->configured_flag
);
235 ehci_readl(ehci
, &ehci
->regs
->command
); /* unblock posted writes */
237 /* here we "know" root ports should always stay powered */
238 ehci_port_power(ehci
, 1);
240 ehci
->rh_state
= EHCI_RH_SUSPENDED
;
245 static const struct dev_pm_ops au1xxx_ehci_pmops
= {
246 .suspend
= ehci_hcd_au1xxx_drv_suspend
,
247 .resume
= ehci_hcd_au1xxx_drv_resume
,
250 #define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops
253 #define AU1XXX_EHCI_PMOPS NULL
256 static struct platform_driver ehci_hcd_au1xxx_driver
= {
257 .probe
= ehci_hcd_au1xxx_drv_probe
,
258 .remove
= ehci_hcd_au1xxx_drv_remove
,
259 .shutdown
= usb_hcd_platform_shutdown
,
261 .name
= "au1xxx-ehci",
262 .owner
= THIS_MODULE
,
263 .pm
= AU1XXX_EHCI_PMOPS
,
267 MODULE_ALIAS("platform:au1xxx-ehci");