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->regs)) 118 return PTR_ERR(udc->regs); 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_get_property(dev->of_node, "extcon", NULL)) { 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 int 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 0; 238 239 /* dma pool cleanup */ 240 free_dma_pools(dev); 241 242 udc_remove(dev); 243 244 platform_set_drvdata(pdev, NULL); 245 246 if (dev->drd_wq) { 247 flush_workqueue(dev->drd_wq); 248 destroy_workqueue(dev->drd_wq); 249 } 250 251 phy_power_off(dev->udc_phy); 252 phy_exit(dev->udc_phy); 253 extcon_unregister_notifier(dev->edev, EXTCON_USB, &dev->nb); 254 255 dev_info(&pdev->dev, "Synopsys UDC platform driver removed\n"); 256 257 return 0; 258 } 259 260 #ifdef CONFIG_PM_SLEEP 261 static int udc_plat_suspend(struct device *dev) 262 { 263 struct udc *udc; 264 265 udc = dev_get_drvdata(dev); 266 stop_udc(udc); 267 268 if (extcon_get_state(udc->edev, EXTCON_USB) > 0) { 269 dev_dbg(udc->dev, "device -> idle\n"); 270 stop_udc(udc); 271 } 272 phy_power_off(udc->udc_phy); 273 phy_exit(udc->udc_phy); 274 275 return 0; 276 } 277 278 static int udc_plat_resume(struct device *dev) 279 { 280 struct udc *udc; 281 int ret; 282 283 udc = dev_get_drvdata(dev); 284 285 ret = phy_init(udc->udc_phy); 286 if (ret) { 287 dev_err(udc->dev, "UDC phy init failure"); 288 return ret; 289 } 290 291 ret = phy_power_on(udc->udc_phy); 292 if (ret) { 293 dev_err(udc->dev, "UDC phy power on failure"); 294 phy_exit(udc->udc_phy); 295 return ret; 296 } 297 298 if (extcon_get_state(udc->edev, EXTCON_USB) > 0) { 299 dev_dbg(udc->dev, "idle -> device\n"); 300 start_udc(udc); 301 } 302 303 return 0; 304 } 305 static const struct dev_pm_ops udc_plat_pm_ops = { 306 .suspend = udc_plat_suspend, 307 .resume = udc_plat_resume, 308 }; 309 #endif 310 311 #if defined(CONFIG_OF) 312 static const struct of_device_id of_udc_match[] = { 313 { .compatible = "brcm,ns2-udc", }, 314 { .compatible = "brcm,cygnus-udc", }, 315 { .compatible = "brcm,iproc-udc", }, 316 { } 317 }; 318 MODULE_DEVICE_TABLE(of, of_udc_match); 319 #endif 320 321 static struct platform_driver udc_plat_driver = { 322 .probe = udc_plat_probe, 323 .remove = udc_plat_remove, 324 .driver = { 325 .name = "snps-udc-plat", 326 .of_match_table = of_match_ptr(of_udc_match), 327 #ifdef CONFIG_PM_SLEEP 328 .pm = &udc_plat_pm_ops, 329 #endif 330 }, 331 }; 332 module_platform_driver(udc_plat_driver); 333 334 MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); 335 MODULE_AUTHOR("Broadcom"); 336 MODULE_LICENSE("GPL v2"); 337