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