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
);
25 ehci
->caps
= hcd
->regs
;
26 ret
= ehci_setup(hcd
);
28 ehci
->need_io_watchdog
= 0;
32 static const struct hc_driver ehci_au1xxx_hc_driver
= {
33 .description
= hcd_name
,
34 .product_desc
= "Au1xxx EHCI",
35 .hcd_priv_size
= sizeof(struct ehci_hcd
),
38 * generic hardware linkage
41 .flags
= HCD_MEMORY
| HCD_USB2
,
44 * basic lifecycle operations
46 * FIXME -- ehci_init() doesn't do enough here.
47 * See ehci-ppc-soc for a complete implementation.
49 .reset
= au1xxx_ehci_setup
,
52 .shutdown
= ehci_shutdown
,
55 * managing i/o requests and associated device resources
57 .urb_enqueue
= ehci_urb_enqueue
,
58 .urb_dequeue
= ehci_urb_dequeue
,
59 .endpoint_disable
= ehci_endpoint_disable
,
60 .endpoint_reset
= ehci_endpoint_reset
,
65 .get_frame_number
= ehci_get_frame
,
70 .hub_status_data
= ehci_hub_status_data
,
71 .hub_control
= ehci_hub_control
,
72 .bus_suspend
= ehci_bus_suspend
,
73 .bus_resume
= ehci_bus_resume
,
74 .relinquish_port
= ehci_relinquish_port
,
75 .port_handed_over
= ehci_port_handed_over
,
77 .clear_tt_buffer_complete
= ehci_clear_tt_buffer_complete
,
80 static int ehci_hcd_au1xxx_drv_probe(struct platform_device
*pdev
)
89 if (pdev
->resource
[1].flags
!= IORESOURCE_IRQ
) {
90 pr_debug("resource[1] is not IORESOURCE_IRQ");
93 hcd
= usb_create_hcd(&ehci_au1xxx_hc_driver
, &pdev
->dev
, "Au1xxx");
97 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
98 hcd
->rsrc_start
= res
->start
;
99 hcd
->rsrc_len
= resource_size(res
);
101 if (!request_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
, hcd_name
)) {
102 pr_debug("request_mem_region failed");
107 hcd
->regs
= ioremap(hcd
->rsrc_start
, hcd
->rsrc_len
);
109 pr_debug("ioremap failed");
114 if (alchemy_usb_control(ALCHEMY_USB_EHCI0
, 1)) {
115 printk(KERN_INFO
"%s: controller init failed!\n", pdev
->name
);
120 ret
= usb_add_hcd(hcd
, pdev
->resource
[1].start
,
123 platform_set_drvdata(pdev
, hcd
);
127 alchemy_usb_control(ALCHEMY_USB_EHCI0
, 0);
131 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
137 static int ehci_hcd_au1xxx_drv_remove(struct platform_device
*pdev
)
139 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
142 alchemy_usb_control(ALCHEMY_USB_EHCI0
, 0);
144 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
146 platform_set_drvdata(pdev
, NULL
);
152 static int ehci_hcd_au1xxx_drv_suspend(struct device
*dev
)
154 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
155 bool do_wakeup
= device_may_wakeup(dev
);
158 rc
= ehci_suspend(hcd
, do_wakeup
);
159 alchemy_usb_control(ALCHEMY_USB_EHCI0
, 0);
164 static int ehci_hcd_au1xxx_drv_resume(struct device
*dev
)
166 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
168 alchemy_usb_control(ALCHEMY_USB_EHCI0
, 1);
169 ehci_resume(hcd
, false);
174 static const struct dev_pm_ops au1xxx_ehci_pmops
= {
175 .suspend
= ehci_hcd_au1xxx_drv_suspend
,
176 .resume
= ehci_hcd_au1xxx_drv_resume
,
179 #define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops
182 #define AU1XXX_EHCI_PMOPS NULL
185 static struct platform_driver ehci_hcd_au1xxx_driver
= {
186 .probe
= ehci_hcd_au1xxx_drv_probe
,
187 .remove
= ehci_hcd_au1xxx_drv_remove
,
188 .shutdown
= usb_hcd_platform_shutdown
,
190 .name
= "au1xxx-ehci",
191 .owner
= THIS_MODULE
,
192 .pm
= AU1XXX_EHCI_PMOPS
,
196 MODULE_ALIAS("platform:au1xxx-ehci");