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/usb/of.h> 15 #include <linux/platform_data/mv_usb.h> 16 #include <linux/io.h> 17 18 #include <linux/usb/hcd.h> 19 20 #include "ehci.h" 21 22 /* registers */ 23 #define U2x_CAPREGS_OFFSET 0x100 24 25 #define CAPLENGTH_MASK (0xff) 26 27 #define hcd_to_ehci_hcd_mv(h) ((struct ehci_hcd_mv *)hcd_to_ehci(h)->priv) 28 29 struct ehci_hcd_mv { 30 /* Which mode does this ehci running OTG/Host ? */ 31 int mode; 32 33 void __iomem *base; 34 void __iomem *cap_regs; 35 void __iomem *op_regs; 36 37 struct usb_phy *otg; 38 struct clk *clk; 39 40 struct phy *phy; 41 42 int (*set_vbus)(unsigned int vbus); 43 }; 44 45 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) 46 { 47 clk_prepare_enable(ehci_mv->clk); 48 } 49 50 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) 51 { 52 clk_disable_unprepare(ehci_mv->clk); 53 } 54 55 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) 56 { 57 ehci_clock_enable(ehci_mv); 58 return phy_init(ehci_mv->phy); 59 } 60 61 static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv) 62 { 63 phy_exit(ehci_mv->phy); 64 ehci_clock_disable(ehci_mv); 65 } 66 67 static int mv_ehci_reset(struct usb_hcd *hcd) 68 { 69 struct device *dev = hcd->self.controller; 70 struct ehci_hcd_mv *ehci_mv = hcd_to_ehci_hcd_mv(hcd); 71 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 72 u32 status; 73 int retval; 74 75 if (ehci_mv == NULL) { 76 dev_err(dev, "Can not find private ehci data\n"); 77 return -ENODEV; 78 } 79 80 hcd->has_tt = 1; 81 82 retval = ehci_setup(hcd); 83 if (retval) 84 dev_err(dev, "ehci_setup failed %d\n", retval); 85 86 if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) { 87 status = ehci_readl(ehci, &ehci->regs->port_status[0]); 88 status |= PORT_TEST_FORCE; 89 ehci_writel(ehci, status, &ehci->regs->port_status[0]); 90 status &= ~PORT_TEST_FORCE; 91 ehci_writel(ehci, status, &ehci->regs->port_status[0]); 92 } 93 94 return retval; 95 } 96 97 static struct hc_driver __read_mostly ehci_platform_hc_driver; 98 99 static const struct ehci_driver_overrides platform_overrides __initconst = { 100 .reset = mv_ehci_reset, 101 .extra_priv_size = sizeof(struct ehci_hcd_mv), 102 }; 103 104 static int mv_ehci_probe(struct platform_device *pdev) 105 { 106 struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); 107 struct usb_hcd *hcd; 108 struct ehci_hcd *ehci; 109 struct ehci_hcd_mv *ehci_mv; 110 struct resource *r; 111 int retval = -ENODEV; 112 u32 offset; 113 114 if (usb_disabled()) 115 return -ENODEV; 116 117 hcd = usb_create_hcd(&ehci_platform_hc_driver, &pdev->dev, "mv ehci"); 118 if (!hcd) 119 return -ENOMEM; 120 121 platform_set_drvdata(pdev, hcd); 122 ehci_mv = hcd_to_ehci_hcd_mv(hcd); 123 124 ehci_mv->mode = MV_USB_MODE_HOST; 125 if (pdata) { 126 ehci_mv->mode = pdata->mode; 127 ehci_mv->set_vbus = pdata->set_vbus; 128 } 129 130 ehci_mv->phy = devm_phy_optional_get(&pdev->dev, "usb"); 131 if (IS_ERR(ehci_mv->phy)) { 132 retval = PTR_ERR(ehci_mv->phy); 133 if (retval != -EPROBE_DEFER) 134 dev_err(&pdev->dev, "Failed to get phy.\n"); 135 goto err_put_hcd; 136 } 137 138 ehci_mv->clk = devm_clk_get(&pdev->dev, NULL); 139 if (IS_ERR(ehci_mv->clk)) { 140 dev_err(&pdev->dev, "error getting clock\n"); 141 retval = PTR_ERR(ehci_mv->clk); 142 goto err_put_hcd; 143 } 144 145 146 147 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 148 ehci_mv->base = devm_ioremap_resource(&pdev->dev, r); 149 if (IS_ERR(ehci_mv->base)) { 150 retval = PTR_ERR(ehci_mv->base); 151 goto err_put_hcd; 152 } 153 154 retval = mv_ehci_enable(ehci_mv); 155 if (retval) { 156 dev_err(&pdev->dev, "init phy error %d\n", retval); 157 goto err_put_hcd; 158 } 159 160 ehci_mv->cap_regs = 161 (void __iomem *) ((unsigned long) ehci_mv->base + U2x_CAPREGS_OFFSET); 162 offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; 163 ehci_mv->op_regs = 164 (void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset); 165 166 hcd->rsrc_start = r->start; 167 hcd->rsrc_len = resource_size(r); 168 hcd->regs = ehci_mv->op_regs; 169 170 hcd->irq = platform_get_irq(pdev, 0); 171 if (!hcd->irq) { 172 dev_err(&pdev->dev, "Cannot get irq."); 173 retval = -ENODEV; 174 goto err_disable_clk; 175 } 176 177 ehci = hcd_to_ehci(hcd); 178 ehci->caps = (struct ehci_caps __iomem *) ehci_mv->cap_regs; 179 180 if (ehci_mv->mode == MV_USB_MODE_OTG) { 181 ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 182 if (IS_ERR(ehci_mv->otg)) { 183 retval = PTR_ERR(ehci_mv->otg); 184 185 if (retval == -ENXIO) 186 dev_info(&pdev->dev, "MV_USB_MODE_OTG " 187 "must have CONFIG_USB_PHY enabled\n"); 188 else 189 dev_err(&pdev->dev, 190 "unable to find transceiver\n"); 191 goto err_disable_clk; 192 } 193 194 retval = otg_set_host(ehci_mv->otg->otg, &hcd->self); 195 if (retval < 0) { 196 dev_err(&pdev->dev, 197 "unable to register with transceiver\n"); 198 retval = -ENODEV; 199 goto err_disable_clk; 200 } 201 /* otg will enable clock before use as host */ 202 mv_ehci_disable(ehci_mv); 203 } else { 204 if (ehci_mv->set_vbus) 205 ehci_mv->set_vbus(1); 206 207 retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); 208 if (retval) { 209 dev_err(&pdev->dev, 210 "failed to add hcd with err %d\n", retval); 211 goto err_set_vbus; 212 } 213 device_wakeup_enable(hcd->self.controller); 214 } 215 216 dev_info(&pdev->dev, 217 "successful find EHCI device with regs 0x%p irq %d" 218 " working in %s mode\n", hcd->regs, hcd->irq, 219 ehci_mv->mode == MV_USB_MODE_OTG ? "OTG" : "Host"); 220 221 return 0; 222 223 err_set_vbus: 224 if (ehci_mv->set_vbus) 225 ehci_mv->set_vbus(0); 226 err_disable_clk: 227 mv_ehci_disable(ehci_mv); 228 err_put_hcd: 229 usb_put_hcd(hcd); 230 231 return retval; 232 } 233 234 static int mv_ehci_remove(struct platform_device *pdev) 235 { 236 struct usb_hcd *hcd = platform_get_drvdata(pdev); 237 struct ehci_hcd_mv *ehci_mv = hcd_to_ehci_hcd_mv(hcd); 238 239 if (hcd->rh_registered) 240 usb_remove_hcd(hcd); 241 242 if (!IS_ERR_OR_NULL(ehci_mv->otg)) 243 otg_set_host(ehci_mv->otg->otg, NULL); 244 245 if (ehci_mv->mode == MV_USB_MODE_HOST) { 246 if (ehci_mv->set_vbus) 247 ehci_mv->set_vbus(0); 248 249 mv_ehci_disable(ehci_mv); 250 } 251 252 usb_put_hcd(hcd); 253 254 return 0; 255 } 256 257 MODULE_ALIAS("mv-ehci"); 258 259 static const struct platform_device_id ehci_id_table[] = { 260 {"pxa-u2oehci", 0}, 261 {"pxa-sph", 0}, 262 {}, 263 }; 264 265 static void mv_ehci_shutdown(struct platform_device *pdev) 266 { 267 struct usb_hcd *hcd = platform_get_drvdata(pdev); 268 269 if (!hcd->rh_registered) 270 return; 271 272 if (hcd->driver->shutdown) 273 hcd->driver->shutdown(hcd); 274 } 275 276 static const struct of_device_id ehci_mv_dt_ids[] = { 277 { .compatible = "marvell,pxau2o-ehci", }, 278 {}, 279 }; 280 281 static struct platform_driver ehci_mv_driver = { 282 .probe = mv_ehci_probe, 283 .remove = mv_ehci_remove, 284 .shutdown = mv_ehci_shutdown, 285 .driver = { 286 .name = "mv-ehci", 287 .bus = &platform_bus_type, 288 .of_match_table = ehci_mv_dt_ids, 289 }, 290 .id_table = ehci_id_table, 291 }; 292 293 static int __init ehci_platform_init(void) 294 { 295 if (usb_disabled()) 296 return -ENODEV; 297 298 ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides); 299 return platform_driver_register(&ehci_mv_driver); 300 } 301 module_init(ehci_platform_init); 302 303 static void __exit ehci_platform_cleanup(void) 304 { 305 platform_driver_unregister(&ehci_mv_driver); 306 } 307 module_exit(ehci_platform_cleanup); 308 309 MODULE_DESCRIPTION("Marvell EHCI driver"); 310 MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>"); 311 MODULE_AUTHOR("Neil Zhang <zhangwm@marvell.com>"); 312 MODULE_ALIAS("mv-ehci"); 313 MODULE_LICENSE("GPL"); 314 MODULE_DEVICE_TABLE(of, ehci_mv_dt_ids); 315