1 /* 2 * Copyright (C) 2011 Marvell International Ltd. All rights reserved. 3 * Author: Chao Xie <chao.xie@marvell.com> 4 * Neil Zhang <zhangwm@marvell.com> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/platform_device.h> 15 #include <linux/clk.h> 16 #include <linux/err.h> 17 #include <linux/usb/otg.h> 18 #include <linux/platform_data/mv_usb.h> 19 20 #define CAPLENGTH_MASK (0xff) 21 22 struct ehci_hcd_mv { 23 struct usb_hcd *hcd; 24 25 /* Which mode does this ehci running OTG/Host ? */ 26 int mode; 27 28 void __iomem *phy_regs; 29 void __iomem *cap_regs; 30 void __iomem *op_regs; 31 32 struct usb_phy *otg; 33 34 struct mv_usb_platform_data *pdata; 35 36 /* clock source and total clock number */ 37 unsigned int clknum; 38 struct clk *clk[0]; 39 }; 40 41 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) 42 { 43 unsigned int i; 44 45 for (i = 0; i < ehci_mv->clknum; i++) 46 clk_enable(ehci_mv->clk[i]); 47 } 48 49 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) 50 { 51 unsigned int i; 52 53 for (i = 0; i < ehci_mv->clknum; i++) 54 clk_disable(ehci_mv->clk[i]); 55 } 56 57 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) 58 { 59 int retval; 60 61 ehci_clock_enable(ehci_mv); 62 if (ehci_mv->pdata->phy_init) { 63 retval = ehci_mv->pdata->phy_init(ehci_mv->phy_regs); 64 if (retval) 65 return retval; 66 } 67 68 return 0; 69 } 70 71 static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv) 72 { 73 if (ehci_mv->pdata->phy_deinit) 74 ehci_mv->pdata->phy_deinit(ehci_mv->phy_regs); 75 ehci_clock_disable(ehci_mv); 76 } 77 78 static int mv_ehci_reset(struct usb_hcd *hcd) 79 { 80 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 81 struct device *dev = hcd->self.controller; 82 struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev); 83 int retval; 84 85 if (ehci_mv == NULL) { 86 dev_err(dev, "Can not find private ehci data\n"); 87 return -ENODEV; 88 } 89 90 /* 91 * data structure init 92 */ 93 retval = ehci_init(hcd); 94 if (retval) { 95 dev_err(dev, "ehci_init failed %d\n", retval); 96 return retval; 97 } 98 99 hcd->has_tt = 1; 100 ehci->sbrn = 0x20; 101 102 retval = ehci_reset(ehci); 103 if (retval) { 104 dev_err(dev, "ehci_reset failed %d\n", retval); 105 return retval; 106 } 107 108 return 0; 109 } 110 111 static const struct hc_driver mv_ehci_hc_driver = { 112 .description = hcd_name, 113 .product_desc = "Marvell EHCI", 114 .hcd_priv_size = sizeof(struct ehci_hcd), 115 116 /* 117 * generic hardware linkage 118 */ 119 .irq = ehci_irq, 120 .flags = HCD_MEMORY | HCD_USB2, 121 122 /* 123 * basic lifecycle operations 124 */ 125 .reset = mv_ehci_reset, 126 .start = ehci_run, 127 .stop = ehci_stop, 128 .shutdown = ehci_shutdown, 129 130 /* 131 * managing i/o requests and associated device resources 132 */ 133 .urb_enqueue = ehci_urb_enqueue, 134 .urb_dequeue = ehci_urb_dequeue, 135 .endpoint_disable = ehci_endpoint_disable, 136 .endpoint_reset = ehci_endpoint_reset, 137 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 138 139 /* 140 * scheduling support 141 */ 142 .get_frame_number = ehci_get_frame, 143 144 /* 145 * root hub support 146 */ 147 .hub_status_data = ehci_hub_status_data, 148 .hub_control = ehci_hub_control, 149 .bus_suspend = ehci_bus_suspend, 150 .bus_resume = ehci_bus_resume, 151 }; 152 153 static int mv_ehci_probe(struct platform_device *pdev) 154 { 155 struct mv_usb_platform_data *pdata = pdev->dev.platform_data; 156 struct usb_hcd *hcd; 157 struct ehci_hcd *ehci; 158 struct ehci_hcd_mv *ehci_mv; 159 struct resource *r; 160 int clk_i, retval = -ENODEV; 161 u32 offset; 162 size_t size; 163 164 if (!pdata) { 165 dev_err(&pdev->dev, "missing platform_data\n"); 166 return -ENODEV; 167 } 168 169 if (usb_disabled()) 170 return -ENODEV; 171 172 hcd = usb_create_hcd(&mv_ehci_hc_driver, &pdev->dev, "mv ehci"); 173 if (!hcd) 174 return -ENOMEM; 175 176 size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum; 177 ehci_mv = kzalloc(size, GFP_KERNEL); 178 if (ehci_mv == NULL) { 179 dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n"); 180 retval = -ENOMEM; 181 goto err_put_hcd; 182 } 183 184 platform_set_drvdata(pdev, ehci_mv); 185 ehci_mv->pdata = pdata; 186 ehci_mv->hcd = hcd; 187 188 ehci_mv->clknum = pdata->clknum; 189 for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) { 190 ehci_mv->clk[clk_i] = 191 clk_get(&pdev->dev, pdata->clkname[clk_i]); 192 if (IS_ERR(ehci_mv->clk[clk_i])) { 193 dev_err(&pdev->dev, "error get clck \"%s\"\n", 194 pdata->clkname[clk_i]); 195 retval = PTR_ERR(ehci_mv->clk[clk_i]); 196 goto err_put_clk; 197 } 198 } 199 200 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs"); 201 if (r == NULL) { 202 dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); 203 retval = -ENODEV; 204 goto err_put_clk; 205 } 206 207 ehci_mv->phy_regs = ioremap(r->start, resource_size(r)); 208 if (ehci_mv->phy_regs == 0) { 209 dev_err(&pdev->dev, "failed to map phy I/O memory\n"); 210 retval = -EFAULT; 211 goto err_put_clk; 212 } 213 214 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs"); 215 if (!r) { 216 dev_err(&pdev->dev, "no I/O memory resource defined\n"); 217 retval = -ENODEV; 218 goto err_iounmap_phyreg; 219 } 220 221 ehci_mv->cap_regs = ioremap(r->start, resource_size(r)); 222 if (ehci_mv->cap_regs == NULL) { 223 dev_err(&pdev->dev, "failed to map I/O memory\n"); 224 retval = -EFAULT; 225 goto err_iounmap_phyreg; 226 } 227 228 retval = mv_ehci_enable(ehci_mv); 229 if (retval) { 230 dev_err(&pdev->dev, "init phy error %d\n", retval); 231 goto err_iounmap_capreg; 232 } 233 234 offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; 235 ehci_mv->op_regs = 236 (void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset); 237 238 hcd->rsrc_start = r->start; 239 hcd->rsrc_len = r->end - r->start + 1; 240 hcd->regs = ehci_mv->op_regs; 241 242 hcd->irq = platform_get_irq(pdev, 0); 243 if (!hcd->irq) { 244 dev_err(&pdev->dev, "Cannot get irq."); 245 retval = -ENODEV; 246 goto err_disable_clk; 247 } 248 249 ehci = hcd_to_ehci(hcd); 250 ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs; 251 ehci->regs = (struct ehci_regs *) ehci_mv->op_regs; 252 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); 253 254 ehci_mv->mode = pdata->mode; 255 if (ehci_mv->mode == MV_USB_MODE_OTG) { 256 #ifdef CONFIG_USB_OTG_UTILS 257 ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2); 258 if (IS_ERR_OR_NULL(ehci_mv->otg)) { 259 dev_err(&pdev->dev, 260 "unable to find transceiver\n"); 261 retval = -ENODEV; 262 goto err_disable_clk; 263 } 264 265 retval = otg_set_host(ehci_mv->otg->otg, &hcd->self); 266 if (retval < 0) { 267 dev_err(&pdev->dev, 268 "unable to register with transceiver\n"); 269 retval = -ENODEV; 270 goto err_put_transceiver; 271 } 272 /* otg will enable clock before use as host */ 273 mv_ehci_disable(ehci_mv); 274 #else 275 dev_info(&pdev->dev, "MV_USB_MODE_OTG " 276 "must have CONFIG_USB_OTG_UTILS enabled\n"); 277 goto err_disable_clk; 278 #endif 279 } else { 280 if (pdata->set_vbus) 281 pdata->set_vbus(1); 282 283 retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); 284 if (retval) { 285 dev_err(&pdev->dev, 286 "failed to add hcd with err %d\n", retval); 287 goto err_set_vbus; 288 } 289 } 290 291 if (pdata->private_init) 292 pdata->private_init(ehci_mv->op_regs, ehci_mv->phy_regs); 293 294 dev_info(&pdev->dev, 295 "successful find EHCI device with regs 0x%p irq %d" 296 " working in %s mode\n", hcd->regs, hcd->irq, 297 ehci_mv->mode == MV_USB_MODE_OTG ? "OTG" : "Host"); 298 299 return 0; 300 301 err_set_vbus: 302 if (pdata->set_vbus) 303 pdata->set_vbus(0); 304 #ifdef CONFIG_USB_OTG_UTILS 305 err_put_transceiver: 306 if (!IS_ERR_OR_NULL(ehci_mv->otg)) 307 usb_put_phy(ehci_mv->otg); 308 #endif 309 err_disable_clk: 310 mv_ehci_disable(ehci_mv); 311 err_iounmap_capreg: 312 iounmap(ehci_mv->cap_regs); 313 err_iounmap_phyreg: 314 iounmap(ehci_mv->phy_regs); 315 err_put_clk: 316 for (clk_i--; clk_i >= 0; clk_i--) 317 clk_put(ehci_mv->clk[clk_i]); 318 platform_set_drvdata(pdev, NULL); 319 kfree(ehci_mv); 320 err_put_hcd: 321 usb_put_hcd(hcd); 322 323 return retval; 324 } 325 326 static int mv_ehci_remove(struct platform_device *pdev) 327 { 328 struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev); 329 struct usb_hcd *hcd = ehci_mv->hcd; 330 int clk_i; 331 332 if (hcd->rh_registered) 333 usb_remove_hcd(hcd); 334 335 if (!IS_ERR_OR_NULL(ehci_mv->otg)) { 336 otg_set_host(ehci_mv->otg->otg, NULL); 337 usb_put_phy(ehci_mv->otg); 338 } 339 340 if (ehci_mv->mode == MV_USB_MODE_HOST) { 341 if (ehci_mv->pdata->set_vbus) 342 ehci_mv->pdata->set_vbus(0); 343 344 mv_ehci_disable(ehci_mv); 345 } 346 347 iounmap(ehci_mv->cap_regs); 348 iounmap(ehci_mv->phy_regs); 349 350 for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) 351 clk_put(ehci_mv->clk[clk_i]); 352 353 platform_set_drvdata(pdev, NULL); 354 355 kfree(ehci_mv); 356 usb_put_hcd(hcd); 357 358 return 0; 359 } 360 361 MODULE_ALIAS("mv-ehci"); 362 363 static const struct platform_device_id ehci_id_table[] = { 364 {"pxa-u2oehci", PXA_U2OEHCI}, 365 {"pxa-sph", PXA_SPH}, 366 {"mmp3-hsic", MMP3_HSIC}, 367 {"mmp3-fsic", MMP3_FSIC}, 368 {}, 369 }; 370 371 static void mv_ehci_shutdown(struct platform_device *pdev) 372 { 373 struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev); 374 struct usb_hcd *hcd = ehci_mv->hcd; 375 376 if (!hcd->rh_registered) 377 return; 378 379 if (hcd->driver->shutdown) 380 hcd->driver->shutdown(hcd); 381 } 382 383 static struct platform_driver ehci_mv_driver = { 384 .probe = mv_ehci_probe, 385 .remove = mv_ehci_remove, 386 .shutdown = mv_ehci_shutdown, 387 .driver = { 388 .name = "mv-ehci", 389 .bus = &platform_bus_type, 390 }, 391 .id_table = ehci_id_table, 392 }; 393