2 * OHCI HCD (Host Controller Driver) for USB.
4 * Copyright (C) 2010 ST Microelectronics.
5 * Deepak Sikri<deepak.sikri@st.com>
7 * Based on various ohci-*.c drivers
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
14 #include <linux/signal.h>
15 #include <linux/platform_device.h>
16 #include <linux/clk.h>
24 #define to_spear_ohci(hcd) (struct spear_ohci *)hcd_to_ohci(hcd)
26 static void spear_start_ohci(struct spear_ohci
*ohci
)
28 clk_prepare_enable(ohci
->clk
);
31 static void spear_stop_ohci(struct spear_ohci
*ohci
)
33 clk_disable_unprepare(ohci
->clk
);
36 static int ohci_spear_start(struct usb_hcd
*hcd
)
38 struct ohci_hcd
*ohci
= hcd_to_ohci(hcd
);
41 ret
= ohci_init(ohci
);
44 ohci
->regs
= hcd
->regs
;
48 dev_err(hcd
->self
.controller
, "can't start\n");
53 create_debug_files(ohci
);
61 static const struct hc_driver ohci_spear_hc_driver
= {
62 .description
= hcd_name
,
63 .product_desc
= "SPEAr OHCI",
64 .hcd_priv_size
= sizeof(struct spear_ohci
),
66 /* generic hardware linkage */
68 .flags
= HCD_USB11
| HCD_MEMORY
,
70 /* basic lifecycle operations */
71 .start
= ohci_spear_start
,
73 .shutdown
= ohci_shutdown
,
75 .bus_suspend
= ohci_bus_suspend
,
76 .bus_resume
= ohci_bus_resume
,
79 /* managing i/o requests and associated device resources */
80 .urb_enqueue
= ohci_urb_enqueue
,
81 .urb_dequeue
= ohci_urb_dequeue
,
82 .endpoint_disable
= ohci_endpoint_disable
,
84 /* scheduling support */
85 .get_frame_number
= ohci_get_frame
,
87 /* root hub support */
88 .hub_status_data
= ohci_hub_status_data
,
89 .hub_control
= ohci_hub_control
,
91 .start_port_reset
= ohci_start_port_reset
,
94 static int spear_ohci_hcd_drv_probe(struct platform_device
*pdev
)
96 const struct hc_driver
*driver
= &ohci_spear_hc_driver
;
97 struct usb_hcd
*hcd
= NULL
;
99 struct spear_ohci
*ohci_p
;
100 struct resource
*res
;
103 irq
= platform_get_irq(pdev
, 0);
110 * Right now device-tree probed devices don't get dma_mask set.
111 * Since shared usb code relies on it, set it here for now.
112 * Once we have dma capability bindings this can go away.
114 if (!pdev
->dev
.dma_mask
)
115 pdev
->dev
.dma_mask
= &pdev
->dev
.coherent_dma_mask
;
116 if (!pdev
->dev
.coherent_dma_mask
)
117 pdev
->dev
.coherent_dma_mask
= DMA_BIT_MASK(32);
119 usbh_clk
= devm_clk_get(&pdev
->dev
, NULL
);
120 if (IS_ERR(usbh_clk
)) {
121 dev_err(&pdev
->dev
, "Error getting interface clock\n");
122 retval
= PTR_ERR(usbh_clk
);
126 hcd
= usb_create_hcd(driver
, &pdev
->dev
, dev_name(&pdev
->dev
));
132 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
138 hcd
->rsrc_start
= pdev
->resource
[0].start
;
139 hcd
->rsrc_len
= resource_size(res
);
140 if (!devm_request_mem_region(&pdev
->dev
, hcd
->rsrc_start
, hcd
->rsrc_len
,
142 dev_dbg(&pdev
->dev
, "request_mem_region failed\n");
147 hcd
->regs
= devm_ioremap(&pdev
->dev
, hcd
->rsrc_start
, hcd
->rsrc_len
);
149 dev_dbg(&pdev
->dev
, "ioremap failed\n");
154 ohci_p
= (struct spear_ohci
*)hcd_to_ohci(hcd
);
155 ohci_p
->clk
= usbh_clk
;
156 spear_start_ohci(ohci_p
);
157 ohci_hcd_init(hcd_to_ohci(hcd
));
159 retval
= usb_add_hcd(hcd
, platform_get_irq(pdev
, 0), 0);
163 spear_stop_ohci(ohci_p
);
167 dev_err(&pdev
->dev
, "init fail, %d\n", retval
);
172 static int spear_ohci_hcd_drv_remove(struct platform_device
*pdev
)
174 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
175 struct spear_ohci
*ohci_p
= to_spear_ohci(hcd
);
179 spear_stop_ohci(ohci_p
);
185 #if defined(CONFIG_PM)
186 static int spear_ohci_hcd_drv_suspend(struct platform_device
*dev
,
187 pm_message_t message
)
189 struct usb_hcd
*hcd
= platform_get_drvdata(dev
);
190 struct ohci_hcd
*ohci
= hcd_to_ohci(hcd
);
191 struct spear_ohci
*ohci_p
= to_spear_ohci(hcd
);
193 if (time_before(jiffies
, ohci
->next_statechange
))
195 ohci
->next_statechange
= jiffies
;
197 spear_stop_ohci(ohci_p
);
201 static int spear_ohci_hcd_drv_resume(struct platform_device
*dev
)
203 struct usb_hcd
*hcd
= platform_get_drvdata(dev
);
204 struct ohci_hcd
*ohci
= hcd_to_ohci(hcd
);
205 struct spear_ohci
*ohci_p
= to_spear_ohci(hcd
);
207 if (time_before(jiffies
, ohci
->next_statechange
))
209 ohci
->next_statechange
= jiffies
;
211 spear_start_ohci(ohci_p
);
212 ohci_resume(hcd
, false);
217 static struct of_device_id spear_ohci_id_table
[] = {
218 { .compatible
= "st,spear600-ohci", },
222 /* Driver definition to register with the platform bus */
223 static struct platform_driver spear_ohci_hcd_driver
= {
224 .probe
= spear_ohci_hcd_drv_probe
,
225 .remove
= spear_ohci_hcd_drv_remove
,
227 .suspend
= spear_ohci_hcd_drv_suspend
,
228 .resume
= spear_ohci_hcd_drv_resume
,
231 .owner
= THIS_MODULE
,
232 .name
= "spear-ohci",
233 .of_match_table
= spear_ohci_id_table
,
237 MODULE_ALIAS("platform:spear-ohci");