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