aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-mxc.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/usb/host/ehci-mxc.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/usb/host/ehci-mxc.c')
-rw-r--r--drivers/usb/host/ehci-mxc.c129
1 files changed, 92 insertions, 37 deletions
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index ec7f5d2c90d..555a73c864b 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -24,23 +24,47 @@
24#include <linux/usb/ulpi.h> 24#include <linux/usb/ulpi.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26 26
27#include <linux/platform_data/usb-ehci-mxc.h> 27#include <mach/hardware.h>
28#include <mach/mxc_ehci.h>
28 29
29#include <asm/mach-types.h> 30#include <asm/mach-types.h>
30 31
31#define ULPI_VIEWPORT_OFFSET 0x170 32#define ULPI_VIEWPORT_OFFSET 0x170
32 33
33struct ehci_mxc_priv { 34struct ehci_mxc_priv {
34 struct clk *usbclk, *ahbclk, *phyclk; 35 struct clk *usbclk, *ahbclk, *phy1clk;
35 struct usb_hcd *hcd; 36 struct usb_hcd *hcd;
36}; 37};
37 38
38/* called during probe() after chip reset completes */ 39/* called during probe() after chip reset completes */
39static int ehci_mxc_setup(struct usb_hcd *hcd) 40static int ehci_mxc_setup(struct usb_hcd *hcd)
40{ 41{
42 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
43 int retval;
44
45 dbg_hcs_params(ehci, "reset");
46 dbg_hcc_params(ehci, "reset");
47
48 /* cache this readonly data; minimize chip reads */
49 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
50
41 hcd->has_tt = 1; 51 hcd->has_tt = 1;
42 52
43 return ehci_setup(hcd); 53 retval = ehci_halt(ehci);
54 if (retval)
55 return retval;
56
57 /* data structure init */
58 retval = ehci_init(hcd);
59 if (retval)
60 return retval;
61
62 ehci->sbrn = 0x20;
63
64 ehci_reset(ehci);
65
66 ehci_port_power(ehci, 0);
67 return 0;
44} 68}
45 69
46static const struct hc_driver ehci_mxc_hc_driver = { 70static const struct hc_driver ehci_mxc_hc_driver = {
@@ -112,7 +136,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
112 if (!hcd) 136 if (!hcd)
113 return -ENOMEM; 137 return -ENOMEM;
114 138
115 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 139 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
116 if (!priv) { 140 if (!priv) {
117 ret = -ENOMEM; 141 ret = -ENOMEM;
118 goto err_alloc; 142 goto err_alloc;
@@ -122,40 +146,51 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
122 if (!res) { 146 if (!res) {
123 dev_err(dev, "Found HC with no register addr. Check setup!\n"); 147 dev_err(dev, "Found HC with no register addr. Check setup!\n");
124 ret = -ENODEV; 148 ret = -ENODEV;
125 goto err_alloc; 149 goto err_get_resource;
126 } 150 }
127 151
128 hcd->rsrc_start = res->start; 152 hcd->rsrc_start = res->start;
129 hcd->rsrc_len = resource_size(res); 153 hcd->rsrc_len = resource_size(res);
130 154
131 hcd->regs = devm_request_and_ioremap(&pdev->dev, res); 155 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
156 dev_dbg(dev, "controller already in use\n");
157 ret = -EBUSY;
158 goto err_request_mem;
159 }
160
161 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
132 if (!hcd->regs) { 162 if (!hcd->regs) {
133 dev_err(dev, "error mapping memory\n"); 163 dev_err(dev, "error mapping memory\n");
134 ret = -EFAULT; 164 ret = -EFAULT;
135 goto err_alloc; 165 goto err_ioremap;
136 } 166 }
137 167
138 /* enable clocks */ 168 /* enable clocks */
139 priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); 169 priv->usbclk = clk_get(dev, "usb");
140 if (IS_ERR(priv->usbclk)) { 170 if (IS_ERR(priv->usbclk)) {
141 ret = PTR_ERR(priv->usbclk); 171 ret = PTR_ERR(priv->usbclk);
142 goto err_alloc; 172 goto err_clk;
143 } 173 }
144 clk_prepare_enable(priv->usbclk); 174 clk_enable(priv->usbclk);
145 175
146 priv->ahbclk = devm_clk_get(&pdev->dev, "ahb"); 176 if (!cpu_is_mx35() && !cpu_is_mx25()) {
147 if (IS_ERR(priv->ahbclk)) { 177 priv->ahbclk = clk_get(dev, "usb_ahb");
148 ret = PTR_ERR(priv->ahbclk); 178 if (IS_ERR(priv->ahbclk)) {
149 goto err_clk_ahb; 179 ret = PTR_ERR(priv->ahbclk);
180 goto err_clk_ahb;
181 }
182 clk_enable(priv->ahbclk);
150 } 183 }
151 clk_prepare_enable(priv->ahbclk);
152 184
153 /* "dr" device has its own clock on i.MX51 */ 185 /* "dr" device has its own clock on i.MX51 */
154 priv->phyclk = devm_clk_get(&pdev->dev, "phy"); 186 if (cpu_is_mx51() && (pdev->id == 0)) {
155 if (IS_ERR(priv->phyclk)) 187 priv->phy1clk = clk_get(dev, "usb_phy1");
156 priv->phyclk = NULL; 188 if (IS_ERR(priv->phy1clk)) {
157 if (priv->phyclk) 189 ret = PTR_ERR(priv->phy1clk);
158 clk_prepare_enable(priv->phyclk); 190 goto err_clk_phy;
191 }
192 clk_enable(priv->phy1clk);
193 }
159 194
160 195
161 /* call platform specific init function */ 196 /* call platform specific init function */
@@ -185,13 +220,13 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
185 /* Initialize the transceiver */ 220 /* Initialize the transceiver */
186 if (pdata->otg) { 221 if (pdata->otg) {
187 pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; 222 pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
188 ret = usb_phy_init(pdata->otg); 223 ret = otg_init(pdata->otg);
189 if (ret) { 224 if (ret) {
190 dev_err(dev, "unable to init transceiver, probably missing\n"); 225 dev_err(dev, "unable to init transceiver, probably missing\n");
191 ret = -ENODEV; 226 ret = -ENODEV;
192 goto err_add; 227 goto err_add;
193 } 228 }
194 ret = otg_set_vbus(pdata->otg->otg, 1); 229 ret = otg_set_vbus(pdata->otg, 1);
195 if (ret) { 230 if (ret) {
196 dev_err(dev, "unable to enable vbus on transceiver\n"); 231 dev_err(dev, "unable to enable vbus on transceiver\n");
197 goto err_add; 232 goto err_add;
@@ -201,7 +236,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
201 priv->hcd = hcd; 236 priv->hcd = hcd;
202 platform_set_drvdata(pdev, priv); 237 platform_set_drvdata(pdev, priv);
203 238
204 ret = usb_add_hcd(hcd, irq, IRQF_SHARED); 239 ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
205 if (ret) 240 if (ret)
206 goto err_add; 241 goto err_add;
207 242
@@ -212,11 +247,9 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
212 * It's in violation of USB specs 247 * It's in violation of USB specs
213 */ 248 */
214 if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) { 249 if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) {
215 flags = usb_phy_io_read(pdata->otg, 250 flags = otg_io_read(pdata->otg, ULPI_OTG_CTRL);
216 ULPI_OTG_CTRL);
217 flags |= ULPI_OTG_CTRL_CHRGVBUS; 251 flags |= ULPI_OTG_CTRL_CHRGVBUS;
218 ret = usb_phy_io_write(pdata->otg, flags, 252 ret = otg_io_write(pdata->otg, flags, ULPI_OTG_CTRL);
219 ULPI_OTG_CTRL);
220 if (ret) { 253 if (ret) {
221 dev_err(dev, "unable to set CHRVBUS\n"); 254 dev_err(dev, "unable to set CHRVBUS\n");
222 goto err_add; 255 goto err_add;
@@ -230,12 +263,25 @@ err_add:
230 if (pdata && pdata->exit) 263 if (pdata && pdata->exit)
231 pdata->exit(pdev); 264 pdata->exit(pdev);
232err_init: 265err_init:
233 if (priv->phyclk) 266 if (priv->phy1clk) {
234 clk_disable_unprepare(priv->phyclk); 267 clk_disable(priv->phy1clk);
235 268 clk_put(priv->phy1clk);
236 clk_disable_unprepare(priv->ahbclk); 269 }
270err_clk_phy:
271 if (priv->ahbclk) {
272 clk_disable(priv->ahbclk);
273 clk_put(priv->ahbclk);
274 }
237err_clk_ahb: 275err_clk_ahb:
238 clk_disable_unprepare(priv->usbclk); 276 clk_disable(priv->usbclk);
277 clk_put(priv->usbclk);
278err_clk:
279 iounmap(hcd->regs);
280err_ioremap:
281 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
282err_request_mem:
283err_get_resource:
284 kfree(priv);
239err_alloc: 285err_alloc:
240 usb_put_hcd(hcd); 286 usb_put_hcd(hcd);
241 return ret; 287 return ret;
@@ -251,17 +297,26 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
251 pdata->exit(pdev); 297 pdata->exit(pdev);
252 298
253 if (pdata->otg) 299 if (pdata->otg)
254 usb_phy_shutdown(pdata->otg); 300 otg_shutdown(pdata->otg);
255 301
256 usb_remove_hcd(hcd); 302 usb_remove_hcd(hcd);
303 iounmap(hcd->regs);
304 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
257 usb_put_hcd(hcd); 305 usb_put_hcd(hcd);
258 platform_set_drvdata(pdev, NULL); 306 platform_set_drvdata(pdev, NULL);
259 307
260 clk_disable_unprepare(priv->usbclk); 308 clk_disable(priv->usbclk);
261 clk_disable_unprepare(priv->ahbclk); 309 clk_put(priv->usbclk);
310 if (priv->ahbclk) {
311 clk_disable(priv->ahbclk);
312 clk_put(priv->ahbclk);
313 }
314 if (priv->phy1clk) {
315 clk_disable(priv->phy1clk);
316 clk_put(priv->phy1clk);
317 }
262 318
263 if (priv->phyclk) 319 kfree(priv);
264 clk_disable_unprepare(priv->phyclk);
265 320
266 return 0; 321 return 0;
267} 322}