2 * Generic platform ehci driver
4 * Copyright 2007 Steven Brown <sbrown@cortland.com>
5 * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
7 * Derived from the ohci-ssb driver
8 * Copyright 2007 Michael Buesch <m@bues.ch>
10 * Derived from the EHCI-PCI driver
11 * Copyright (c) 2000-2004 by David Brownell
13 * Derived from the ohci-pci driver
14 * Copyright 1999 Roman Weissgaerber
15 * Copyright 2000-2002 David Brownell
16 * Copyright 1999 Linus Torvalds
17 * Copyright 1999 Gregory P. Smith
19 * Licensed under the GNU/GPL. See COPYING for details.
21 #include <linux/platform_device.h>
22 #include <linux/usb/ehci_pdriver.h>
24 static int ehci_platform_reset(struct usb_hcd
*hcd
)
26 struct platform_device
*pdev
= to_platform_device(hcd
->self
.controller
);
27 struct usb_ehci_pdata
*pdata
= pdev
->dev
.platform_data
;
28 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
31 hcd
->has_tt
= pdata
->has_tt
;
32 ehci
->has_synopsys_hc_bug
= pdata
->has_synopsys_hc_bug
;
33 ehci
->big_endian_desc
= pdata
->big_endian_desc
;
34 ehci
->big_endian_mmio
= pdata
->big_endian_mmio
;
36 ehci
->caps
= hcd
->regs
+ pdata
->caps_offset
;
37 retval
= ehci_setup(hcd
);
41 if (pdata
->port_power_on
)
42 ehci_port_power(ehci
, 1);
43 if (pdata
->port_power_off
)
44 ehci_port_power(ehci
, 0);
49 static const struct hc_driver ehci_platform_hc_driver
= {
50 .description
= hcd_name
,
51 .product_desc
= "Generic Platform EHCI Controller",
52 .hcd_priv_size
= sizeof(struct ehci_hcd
),
55 .flags
= HCD_MEMORY
| HCD_USB2
,
57 .reset
= ehci_platform_reset
,
60 .shutdown
= ehci_shutdown
,
62 .urb_enqueue
= ehci_urb_enqueue
,
63 .urb_dequeue
= ehci_urb_dequeue
,
64 .endpoint_disable
= ehci_endpoint_disable
,
65 .endpoint_reset
= ehci_endpoint_reset
,
67 .get_frame_number
= ehci_get_frame
,
69 .hub_status_data
= ehci_hub_status_data
,
70 .hub_control
= ehci_hub_control
,
71 #if defined(CONFIG_PM)
72 .bus_suspend
= ehci_bus_suspend
,
73 .bus_resume
= ehci_bus_resume
,
75 .relinquish_port
= ehci_relinquish_port
,
76 .port_handed_over
= ehci_port_handed_over
,
78 .clear_tt_buffer_complete
= ehci_clear_tt_buffer_complete
,
81 static int __devinit
ehci_platform_probe(struct platform_device
*dev
)
84 struct resource
*res_mem
;
88 BUG_ON(!dev
->dev
.platform_data
);
93 irq
= platform_get_irq(dev
, 0);
95 pr_err("no irq provided");
98 res_mem
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
100 pr_err("no memory recourse provided");
104 hcd
= usb_create_hcd(&ehci_platform_hc_driver
, &dev
->dev
,
105 dev_name(&dev
->dev
));
109 hcd
->rsrc_start
= res_mem
->start
;
110 hcd
->rsrc_len
= resource_size(res_mem
);
112 if (!request_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
, hcd_name
)) {
113 pr_err("controller already in use");
118 hcd
->regs
= ioremap_nocache(hcd
->rsrc_start
, hcd
->rsrc_len
);
120 goto err_release_region
;
121 err
= usb_add_hcd(hcd
, irq
, IRQF_SHARED
);
125 platform_set_drvdata(dev
, hcd
);
132 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
138 static int __devexit
ehci_platform_remove(struct platform_device
*dev
)
140 struct usb_hcd
*hcd
= platform_get_drvdata(dev
);
144 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
146 platform_set_drvdata(dev
, NULL
);
153 static int ehci_platform_suspend(struct device
*dev
)
155 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
156 bool do_wakeup
= device_may_wakeup(dev
);
158 return ehci_suspend(hcd
, do_wakeup
);
161 static int ehci_platform_resume(struct device
*dev
)
163 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
165 ehci_resume(hcd
, false);
169 #else /* !CONFIG_PM */
170 #define ehci_platform_suspend NULL
171 #define ehci_platform_resume NULL
172 #endif /* CONFIG_PM */
174 static const struct platform_device_id ehci_platform_table
[] = {
175 { "ehci-platform", 0 },
178 MODULE_DEVICE_TABLE(platform
, ehci_platform_table
);
180 static const struct dev_pm_ops ehci_platform_pm_ops
= {
181 .suspend
= ehci_platform_suspend
,
182 .resume
= ehci_platform_resume
,
185 static struct platform_driver ehci_platform_driver
= {
186 .id_table
= ehci_platform_table
,
187 .probe
= ehci_platform_probe
,
188 .remove
= __devexit_p(ehci_platform_remove
),
189 .shutdown
= usb_hcd_platform_shutdown
,
191 .owner
= THIS_MODULE
,
192 .name
= "ehci-platform",
193 .pm
= &ehci_platform_pm_ops
,