1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * snps_udc_plat.c - Synopsys UDC Platform Driver 4 * 5 * Copyright (C) 2016 Broadcom 6 */ 7 8 #include <linux/extcon.h> 9 #include <linux/of_address.h> 10 #include <linux/of_irq.h> 11 #include <linux/of_gpio.h> 12 #include <linux/platform_device.h> 13 #include <linux/phy/phy.h> 14 #include <linux/module.h> 15 #include <linux/dmapool.h> 16 #include <linux/interrupt.h> 17 #include <linux/moduleparam.h> 18 #include "amd5536udc.h" 19 20 /* description */ 21 #define UDC_MOD_DESCRIPTION "Synopsys UDC platform driver" 22 23 static void start_udc(struct udc *udc) 24 { 25 if (udc->driver) { 26 dev_info(udc->dev, "Connecting...\n"); 27 udc_enable_dev_setup_interrupts(udc); 28 udc_basic_init(udc); 29 udc->connected = 1; 30 } 31 } 32 33 static void stop_udc(struct udc *udc) 34 { 35 int tmp; 36 u32 reg; 37 38 spin_lock(&udc->lock); 39 40 /* Flush the receieve fifo */ 41 reg = readl(&udc->regs->ctl); 42 reg |= AMD_BIT(UDC_DEVCTL_SRX_FLUSH); 43 writel(reg, &udc->regs->ctl); 44 45 reg = readl(&udc->regs->ctl); 46 reg &= ~(AMD_BIT(UDC_DEVCTL_SRX_FLUSH)); 47 writel(reg, &udc->regs->ctl); 48 dev_dbg(udc->dev, "ep rx queue flushed\n"); 49 50 /* Mask interrupts. Required more so when the 51 * UDC is connected to a DRD phy. 52 */ 53 udc_mask_unused_interrupts(udc); 54 55 /* Disconnect gadget driver */ 56 if (udc->driver) { 57 spin_unlock(&udc->lock); 58 udc->driver->disconnect(&udc->gadget); 59 spin_lock(&udc->lock); 60 61 /* empty queues */ 62 for (tmp = 0; tmp < UDC_EP_NUM; tmp++) 63 empty_req_queue(&udc->ep[tmp]); 64 } 65 udc->connected = 0; 66 67 spin_unlock(&udc->lock); 68 dev_info(udc->dev, "Device disconnected\n"); 69 } 70 71 static void udc_drd_work(struct work_struct *work) 72 { 73 struct udc *udc; 74 75 udc = container_of(to_delayed_work(work), 76 struct udc, drd_work); 77 78 if (udc->conn_type) { 79 dev_dbg(udc->dev, "idle -> device\n"); 80 start_udc(udc); 81 } else { 82 dev_dbg(udc->dev, "device -> idle\n"); 83 stop_udc(udc); 84 } 85 } 86 87 static int usbd_connect_notify(struct notifier_block *self, 88 unsigned long event, void *ptr) 89 { 90 struct udc *udc = container_of(self, struct udc, nb); 91 92 dev_dbg(udc->dev, "%s: event: %lu\n", __func__, event); 93 94 udc->conn_type = event; 95 96 schedule_delayed_work(&udc->drd_work, 0); 97 98 return NOTIFY_OK; 99 } 100 101 static int udc_plat_probe(struct platform_device *pdev) 102 { 103 struct device *dev = &pdev->dev; 104 struct resource *res; 105 struct udc *udc; 106 int ret; 107 108 udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL); 109 if (!udc) 110 return -ENOMEM; 111 112 spin_lock_init(&udc->lock); 113 udc->dev = dev; 114 115 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 116 udc->virt_addr = devm_ioremap_resource(dev, res); 117 if (IS_ERR(udc->virt_addr)) 118 return PTR_ERR(udc->virt_addr); 119 120 /* udc csr registers base */ 121 udc->csr = udc->virt_addr + UDC_CSR_ADDR; 122 123 /* dev registers base */ 124 udc->regs = udc->virt_addr + UDC_DEVCFG_ADDR; 125 126 /* ep registers base */ 127 udc->ep_regs = udc->virt_addr + UDC_EPREGS_ADDR; 128 129 /* fifo's base */ 130 udc->rxfifo = (u32 __iomem *)(udc->virt_addr + UDC_RXFIFO_ADDR); 131 udc->txfifo = (u32 __iomem *)(udc->virt_addr + UDC_TXFIFO_ADDR); 132 133 udc->phys_addr = (unsigned long)res->start; 134 135 udc->irq = irq_of_parse_and_map(dev->of_node, 0); 136 if (udc->irq <= 0) { 137 dev_err(dev, "Can't parse and map interrupt\n"); 138 return -EINVAL; 139 } 140 141 udc->udc_phy = devm_of_phy_get_by_index(dev, dev->of_node, 0); 142 if (IS_ERR(udc->udc_phy)) { 143 dev_err(dev, "Failed to obtain phy from device tree\n"); 144 return PTR_ERR(udc->udc_phy); 145 } 146 147 ret = phy_init(udc->udc_phy); 148 if (ret) { 149 dev_err(dev, "UDC phy init failed"); 150 return ret; 151 } 152 153 ret = phy_power_on(udc->udc_phy); 154 if (ret) { 155 dev_err(dev, "UDC phy power on failed"); 156 phy_exit(udc->udc_phy); 157 return ret; 158 } 159 160 /* Register for extcon if supported */ 161 if (of_property_present(dev->of_node, "extcon")) { 162 udc->edev = extcon_get_edev_by_phandle(dev, 0); 163 if (IS_ERR(udc->edev)) { 164 if (PTR_ERR(udc->edev) == -EPROBE_DEFER) 165 return -EPROBE_DEFER; 166 dev_err(dev, "Invalid or missing extcon\n"); 167 ret = PTR_ERR(udc->edev); 168 goto exit_phy; 169 } 170 171 udc->nb.notifier_call = usbd_connect_notify; 172 ret = extcon_register_notifier(udc->edev, EXTCON_USB, 173 &udc->nb); 174 if (ret < 0) { 175 dev_err(dev, "Can't register extcon device\n"); 176 goto exit_phy; 177 } 178 179 ret = extcon_get_state(udc->edev, EXTCON_USB); 180 if (ret < 0) { 181 dev_err(dev, "Can't get cable state\n"); 182 goto exit_extcon; 183 } else if (ret) { 184 udc->conn_type = ret; 185 } 186 INIT_DELAYED_WORK(&udc->drd_work, udc_drd_work); 187 } 188 189 /* init dma pools */ 190 if (use_dma) { 191 ret = init_dma_pools(udc); 192 if (ret != 0) 193 goto exit_extcon; 194 } 195 196 ret = devm_request_irq(dev, udc->irq, udc_irq, IRQF_SHARED, 197 "snps-udc", udc); 198 if (ret < 0) { 199 dev_err(dev, "Request irq %d failed for UDC\n", udc->irq); 200 goto exit_dma; 201 } 202 203 platform_set_drvdata(pdev, udc); 204 udc->chiprev = UDC_BCM_REV; 205 206 if (udc_probe(udc)) { 207 ret = -ENODEV; 208 goto exit_dma; 209 } 210 dev_info(dev, "Synopsys UDC platform driver probe successful\n"); 211 212 return 0; 213 214 exit_dma: 215 if (use_dma) 216 free_dma_pools(udc); 217 exit_extcon: 218 if (udc->edev) 219 extcon_unregister_notifier(udc->edev, EXTCON_USB, &udc->nb); 220 exit_phy: 221 if (udc->udc_phy) { 222 phy_power_off(udc->udc_phy); 223 phy_exit(udc->udc_phy); 224 } 225 return ret; 226 } 227 228 static void udc_plat_remove(struct platform_device *pdev) 229 { 230 struct udc *dev; 231 232 dev = platform_get_drvdata(pdev); 233 234 usb_del_gadget_udc(&dev->gadget); 235 /* gadget driver must not be registered */ 236 if (WARN_ON(dev->driver)) 237 return; 238 239 /* dma pool cleanup */ 240 free_dma_pools(dev); 241 242 udc_remove(dev); 243 244 platform_set_drvdata(pdev, NULL); 245 246 phy_power_off(dev->udc_phy); 247 phy_exit(dev->udc_phy); 248 extcon_unregister_notifier(dev->edev, EXTCON_USB, &dev->nb); 249 250 dev_info(&pdev->dev, "Synopsys UDC platform driver removed\n"); 251 } 252 253 #ifdef CONFIG_PM_SLEEP 254 static int udc_plat_suspend(struct device *dev) 255 { 256 struct udc *udc; 257 258 udc = dev_get_drvdata(dev); 259 stop_udc(udc); 260 261 if (extcon_get_state(udc->edev, EXTCON_USB) > 0) { 262 dev_dbg(udc->dev, "device -> idle\n"); 263 stop_udc(udc); 264 } 265 phy_power_off(udc->udc_phy); 266 phy_exit(udc->udc_phy); 267 268 return 0; 269 } 270 271 static int udc_plat_resume(struct device *dev) 272 { 273 struct udc *udc; 274 int ret; 275 276 udc = dev_get_drvdata(dev); 277 278 ret = phy_init(udc->udc_phy); 279 if (ret) { 280 dev_err(udc->dev, "UDC phy init failure"); 281 return ret; 282 } 283 284 ret = phy_power_on(udc->udc_phy); 285 if (ret) { 286 dev_err(udc->dev, "UDC phy power on failure"); 287 phy_exit(udc->udc_phy); 288 return ret; 289 } 290 291 if (extcon_get_state(udc->edev, EXTCON_USB) > 0) { 292 dev_dbg(udc->dev, "idle -> device\n"); 293 start_udc(udc); 294 } 295 296 return 0; 297 } 298 static const struct dev_pm_ops udc_plat_pm_ops = { 299 .suspend = udc_plat_suspend, 300 .resume = udc_plat_resume, 301 }; 302 #endif 303 304 #if defined(CONFIG_OF) 305 static const struct of_device_id of_udc_match[] = { 306 { .compatible = "brcm,ns2-udc", }, 307 { .compatible = "brcm,cygnus-udc", }, 308 { .compatible = "brcm,iproc-udc", }, 309 { } 310 }; 311 MODULE_DEVICE_TABLE(of, of_udc_match); 312 #endif 313 314 static struct platform_driver udc_plat_driver = { 315 .probe = udc_plat_probe, 316 .remove_new = udc_plat_remove, 317 .driver = { 318 .name = "snps-udc-plat", 319 .of_match_table = of_match_ptr(of_udc_match), 320 #ifdef CONFIG_PM_SLEEP 321 .pm = &udc_plat_pm_ops, 322 #endif 323 }, 324 }; 325 module_platform_driver(udc_plat_driver); 326 327 MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); 328 MODULE_AUTHOR("Broadcom"); 329 MODULE_LICENSE("GPL v2"); 330