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 struct clk *clk; 37 }; 38 39 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) 40 { 41 clk_prepare_enable(ehci_mv->clk); 42 } 43 44 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) 45 { 46 clk_disable_unprepare(ehci_mv->clk); 47 } 48 49 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) 50 { 51 int retval; 52 53 ehci_clock_enable(ehci_mv); 54 if (ehci_mv->pdata->phy_init) { 55 retval = ehci_mv->pdata->phy_init(ehci_mv->phy_regs); 56 if (retval) 57 return retval; 58 } 59 60 return 0; 61 } 62 63 static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv) 64 { 65 if (ehci_mv->pdata->phy_deinit) 66 ehci_mv->pdata->phy_deinit(ehci_mv->phy_regs); 67 ehci_clock_disable(ehci_mv); 68 } 69 70 static int mv_ehci_reset(struct usb_hcd *hcd) 71 { 72 struct device *dev = hcd->self.controller; 73 struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev); 74 int retval; 75 76 if (ehci_mv == NULL) { 77 dev_err(dev, "Can not find private ehci data\n"); 78 return -ENODEV; 79 } 80 81 hcd->has_tt = 1; 82 83 retval = ehci_setup(hcd); 84 if (retval) 85 dev_err(dev, "ehci_setup failed %d\n", retval); 86 87 return retval; 88 } 89 90 static const struct hc_driver mv_ehci_hc_driver = { 91 .description = hcd_name, 92 .product_desc = "Marvell EHCI", 93 .hcd_priv_size = sizeof(struct ehci_hcd), 94 95 /* 96 * generic hardware linkage 97 */ 98 .irq = ehci_irq, 99 .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, 100 101 /* 102 * basic lifecycle operations 103 */ 104 .reset = mv_ehci_reset, 105 .start = ehci_run, 106 .stop = ehci_stop, 107 .shutdown = ehci_shutdown, 108 109 /* 110 * managing i/o requests and associated device resources 111 */ 112 .urb_enqueue = ehci_urb_enqueue, 113 .urb_dequeue = ehci_urb_dequeue, 114 .endpoint_disable = ehci_endpoint_disable, 115 .endpoint_reset = ehci_endpoint_reset, 116 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 117 118 /* 119 * scheduling support 120 */ 121 .get_frame_number = ehci_get_frame, 122 123 /* 124 * root hub support 125 */ 126 .hub_status_data = ehci_hub_status_data, 127 .hub_control = ehci_hub_control, 128 .bus_suspend = ehci_bus_suspend, 129 .bus_resume = ehci_bus_resume, 130 }; 131 132 static int mv_ehci_probe(struct platform_device *pdev) 133 { 134 struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); 135 struct usb_hcd *hcd; 136 struct ehci_hcd *ehci; 137 struct ehci_hcd_mv *ehci_mv; 138 struct resource *r; 139 int retval = -ENODEV; 140 u32 offset; 141 142 if (!pdata) { 143 dev_err(&pdev->dev, "missing platform_data\n"); 144 return -ENODEV; 145 } 146 147 if (usb_disabled()) 148 return -ENODEV; 149 150 hcd = usb_create_hcd(&mv_ehci_hc_driver, &pdev->dev, "mv ehci"); 151 if (!hcd) 152 return -ENOMEM; 153 154 ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL); 155 if (ehci_mv == NULL) { 156 retval = -ENOMEM; 157 goto err_put_hcd; 158 } 159 160 platform_set_drvdata(pdev, ehci_mv); 161 ehci_mv->pdata = pdata; 162 ehci_mv->hcd = hcd; 163 164 ehci_mv->clk = devm_clk_get(&pdev->dev, NULL); 165 if (IS_ERR(ehci_mv->clk)) { 166 dev_err(&pdev->dev, "error getting clock\n"); 167 retval = PTR_ERR(ehci_mv->clk); 168 goto err_put_hcd; 169 } 170 171 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs"); 172 ehci_mv->phy_regs = devm_ioremap_resource(&pdev->dev, r); 173 if (IS_ERR(ehci_mv->phy_regs)) { 174 retval = PTR_ERR(ehci_mv->phy_regs); 175 goto err_put_hcd; 176 } 177 178 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs"); 179 ehci_mv->cap_regs = devm_ioremap_resource(&pdev->dev, r); 180 if (IS_ERR(ehci_mv->cap_regs)) { 181 retval = PTR_ERR(ehci_mv->cap_regs); 182 goto err_put_hcd; 183 } 184 185 retval = mv_ehci_enable(ehci_mv); 186 if (retval) { 187 dev_err(&pdev->dev, "init phy error %d\n", retval); 188 goto err_put_hcd; 189 } 190 191 offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; 192 ehci_mv->op_regs = 193 (void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset); 194 195 hcd->rsrc_start = r->start; 196 hcd->rsrc_len = resource_size(r); 197 hcd->regs = ehci_mv->op_regs; 198 199 hcd->irq = platform_get_irq(pdev, 0); 200 if (!hcd->irq) { 201 dev_err(&pdev->dev, "Cannot get irq."); 202 retval = -ENODEV; 203 goto err_disable_clk; 204 } 205 206 ehci = hcd_to_ehci(hcd); 207 ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs; 208 209 ehci_mv->mode = pdata->mode; 210 if (ehci_mv->mode == MV_USB_MODE_OTG) { 211 ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 212 if (IS_ERR(ehci_mv->otg)) { 213 retval = PTR_ERR(ehci_mv->otg); 214 215 if (retval == -ENXIO) 216 dev_info(&pdev->dev, "MV_USB_MODE_OTG " 217 "must have CONFIG_USB_PHY enabled\n"); 218 else 219 dev_err(&pdev->dev, 220 "unable to find transceiver\n"); 221 goto err_disable_clk; 222 } 223 224 retval = otg_set_host(ehci_mv->otg->otg, &hcd->self); 225 if (retval < 0) { 226 dev_err(&pdev->dev, 227 "unable to register with transceiver\n"); 228 retval = -ENODEV; 229 goto err_disable_clk; 230 } 231 /* otg will enable clock before use as host */ 232 mv_ehci_disable(ehci_mv); 233 } else { 234 if (pdata->set_vbus) 235 pdata->set_vbus(1); 236 237 retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); 238 if (retval) { 239 dev_err(&pdev->dev, 240 "failed to add hcd with err %d\n", retval); 241 goto err_set_vbus; 242 } 243 device_wakeup_enable(hcd->self.controller); 244 } 245 246 if (pdata->private_init) 247 pdata->private_init(ehci_mv->op_regs, ehci_mv->phy_regs); 248 249 dev_info(&pdev->dev, 250 "successful find EHCI device with regs 0x%p irq %d" 251 " working in %s mode\n", hcd->regs, hcd->irq, 252 ehci_mv->mode == MV_USB_MODE_OTG ? "OTG" : "Host"); 253 254 return 0; 255 256 err_set_vbus: 257 if (pdata->set_vbus) 258 pdata->set_vbus(0); 259 err_disable_clk: 260 mv_ehci_disable(ehci_mv); 261 err_put_hcd: 262 usb_put_hcd(hcd); 263 264 return retval; 265 } 266 267 static int mv_ehci_remove(struct platform_device *pdev) 268 { 269 struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev); 270 struct usb_hcd *hcd = ehci_mv->hcd; 271 272 if (hcd->rh_registered) 273 usb_remove_hcd(hcd); 274 275 if (!IS_ERR_OR_NULL(ehci_mv->otg)) 276 otg_set_host(ehci_mv->otg->otg, NULL); 277 278 if (ehci_mv->mode == MV_USB_MODE_HOST) { 279 if (ehci_mv->pdata->set_vbus) 280 ehci_mv->pdata->set_vbus(0); 281 282 mv_ehci_disable(ehci_mv); 283 } 284 285 usb_put_hcd(hcd); 286 287 return 0; 288 } 289 290 MODULE_ALIAS("mv-ehci"); 291 292 static const struct platform_device_id ehci_id_table[] = { 293 {"pxa-u2oehci", PXA_U2OEHCI}, 294 {"pxa-sph", PXA_SPH}, 295 {"mmp3-hsic", MMP3_HSIC}, 296 {"mmp3-fsic", MMP3_FSIC}, 297 {}, 298 }; 299 300 static void mv_ehci_shutdown(struct platform_device *pdev) 301 { 302 struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev); 303 struct usb_hcd *hcd = ehci_mv->hcd; 304 305 if (!hcd->rh_registered) 306 return; 307 308 if (hcd->driver->shutdown) 309 hcd->driver->shutdown(hcd); 310 } 311 312 static struct platform_driver ehci_mv_driver = { 313 .probe = mv_ehci_probe, 314 .remove = mv_ehci_remove, 315 .shutdown = mv_ehci_shutdown, 316 .driver = { 317 .name = "mv-ehci", 318 .bus = &platform_bus_type, 319 }, 320 .id_table = ehci_id_table, 321 }; 322