2 * Driver for EHCI HCD on SPEAR SOC
4 * Copyright (C) 2010 ST Micro Electronics,
5 * Deepak Sikri <deepak.sikri@st.com>
7 * Based on various ehci-*.c drivers
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
14 #include <linux/clk.h>
15 #include <linux/jiffies.h>
17 #include <linux/platform_device.h>
25 #define to_spear_ehci(hcd) (struct spear_ehci *)hcd_to_ehci(hcd)
27 static void spear_start_ehci(struct spear_ehci
*ehci
)
29 clk_prepare_enable(ehci
->clk
);
32 static void spear_stop_ehci(struct spear_ehci
*ehci
)
34 clk_disable_unprepare(ehci
->clk
);
37 static int ehci_spear_setup(struct usb_hcd
*hcd
)
39 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
42 /* registers start at offset 0x0 */
43 ehci
->caps
= hcd
->regs
;
45 retval
= ehci_setup(hcd
);
49 ehci_port_power(ehci
, 0);
54 static const struct hc_driver ehci_spear_hc_driver
= {
55 .description
= hcd_name
,
56 .product_desc
= "SPEAr EHCI",
57 .hcd_priv_size
= sizeof(struct spear_ehci
),
59 /* generic hardware linkage */
61 .flags
= HCD_MEMORY
| HCD_USB2
,
63 /* basic lifecycle operations */
64 .reset
= ehci_spear_setup
,
67 .shutdown
= ehci_shutdown
,
69 /* managing i/o requests and associated device resources */
70 .urb_enqueue
= ehci_urb_enqueue
,
71 .urb_dequeue
= ehci_urb_dequeue
,
72 .endpoint_disable
= ehci_endpoint_disable
,
73 .endpoint_reset
= ehci_endpoint_reset
,
75 /* scheduling support */
76 .get_frame_number
= ehci_get_frame
,
78 /* root hub support */
79 .hub_status_data
= ehci_hub_status_data
,
80 .hub_control
= ehci_hub_control
,
81 .bus_suspend
= ehci_bus_suspend
,
82 .bus_resume
= ehci_bus_resume
,
83 .relinquish_port
= ehci_relinquish_port
,
84 .port_handed_over
= ehci_port_handed_over
,
85 .clear_tt_buffer_complete
= ehci_clear_tt_buffer_complete
,
89 static int ehci_spear_drv_suspend(struct device
*dev
)
91 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
92 bool do_wakeup
= device_may_wakeup(dev
);
94 return ehci_suspend(hcd
, do_wakeup
);
97 static int ehci_spear_drv_resume(struct device
*dev
)
99 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
101 ehci_resume(hcd
, false);
104 #endif /* CONFIG_PM */
106 static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops
, ehci_spear_drv_suspend
,
107 ehci_spear_drv_resume
);
109 static u64 spear_ehci_dma_mask
= DMA_BIT_MASK(32);
111 static int spear_ehci_hcd_drv_probe(struct platform_device
*pdev
)
113 struct usb_hcd
*hcd
;
114 struct spear_ehci
*ehci
;
115 struct resource
*res
;
116 struct clk
*usbh_clk
;
117 const struct hc_driver
*driver
= &ehci_spear_hc_driver
;
119 char clk_name
[20] = "usbh_clk";
120 static int instance
= -1;
125 irq
= platform_get_irq(pdev
, 0);
132 * Right now device-tree probed devices don't get dma_mask set.
133 * Since shared usb code relies on it, set it here for now.
134 * Once we have dma capability bindings this can go away.
136 if (!pdev
->dev
.dma_mask
)
137 pdev
->dev
.dma_mask
= &spear_ehci_dma_mask
;
140 * Increment the device instance, when probing via device-tree
146 sprintf(clk_name
, "usbh.%01d_clk", instance
);
148 usbh_clk
= clk_get(NULL
, clk_name
);
149 if (IS_ERR(usbh_clk
)) {
150 dev_err(&pdev
->dev
, "Error getting interface clock\n");
151 retval
= PTR_ERR(usbh_clk
);
152 goto fail_get_usbh_clk
;
155 hcd
= usb_create_hcd(driver
, &pdev
->dev
, dev_name(&pdev
->dev
));
158 goto fail_create_hcd
;
161 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
164 goto fail_request_resource
;
167 hcd
->rsrc_start
= res
->start
;
168 hcd
->rsrc_len
= resource_size(res
);
169 if (!request_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
,
170 driver
->description
)) {
172 goto fail_request_resource
;
175 hcd
->regs
= ioremap(hcd
->rsrc_start
, hcd
->rsrc_len
);
176 if (hcd
->regs
== NULL
) {
177 dev_dbg(&pdev
->dev
, "error mapping memory\n");
182 ehci
= (struct spear_ehci
*)hcd_to_ehci(hcd
);
183 ehci
->clk
= usbh_clk
;
185 spear_start_ehci(ehci
);
186 retval
= usb_add_hcd(hcd
, irq
, IRQF_SHARED
);
193 spear_stop_ehci(ehci
);
196 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
197 fail_request_resource
:
203 dev_err(&pdev
->dev
, "init fail, %d\n", retval
);
208 static int spear_ehci_hcd_drv_remove(struct platform_device
*pdev
)
210 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
211 struct spear_ehci
*ehci_p
= to_spear_ehci(hcd
);
220 spear_stop_ehci(ehci_p
);
222 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
226 clk_put(ehci_p
->clk
);
231 static struct of_device_id spear_ehci_id_table
[] __devinitdata
= {
232 { .compatible
= "st,spear600-ehci", },
236 static struct platform_driver spear_ehci_hcd_driver
= {
237 .probe
= spear_ehci_hcd_drv_probe
,
238 .remove
= spear_ehci_hcd_drv_remove
,
239 .shutdown
= usb_hcd_platform_shutdown
,
241 .name
= "spear-ehci",
242 .bus
= &platform_bus_type
,
243 .pm
= &ehci_spear_pm_ops
,
244 .of_match_table
= of_match_ptr(spear_ehci_id_table
),
248 MODULE_ALIAS("platform:spear-ehci");