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 udc->virt_addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 116 if (IS_ERR(udc->virt_addr)) 117 return PTR_ERR(udc->virt_addr); 118 119 /* udc csr registers base */ 120 udc->csr = udc->virt_addr + UDC_CSR_ADDR; 121 122 /* dev registers base */ 123 udc->regs = udc->virt_addr + UDC_DEVCFG_ADDR; 124 125 /* ep registers base */ 126 udc->ep_regs = udc->virt_addr + UDC_EPREGS_ADDR; 127 128 /* fifo's base */ 129 udc->rxfifo = (u32 __iomem *)(udc->virt_addr + UDC_RXFIFO_ADDR); 130 udc->txfifo = (u32 __iomem *)(udc->virt_addr + UDC_TXFIFO_ADDR); 131 132 udc->phys_addr = (unsigned long)res->start; 133 134 udc->irq = irq_of_parse_and_map(dev->of_node, 0); 135 if (udc->irq <= 0) { 136 dev_err(dev, "Can't parse and map interrupt\n"); 137 return -EINVAL; 138 } 139 140 udc->udc_phy = devm_of_phy_get_by_index(dev, dev->of_node, 0); 141 if (IS_ERR(udc->udc_phy)) { 142 dev_err(dev, "Failed to obtain phy from device tree\n"); 143 return PTR_ERR(udc->udc_phy); 144 } 145 146 ret = phy_init(udc->udc_phy); 147 if (ret) { 148 dev_err(dev, "UDC phy init failed"); 149 return ret; 150 } 151 152 ret = phy_power_on(udc->udc_phy); 153 if (ret) { 154 dev_err(dev, "UDC phy power on failed"); 155 phy_exit(udc->udc_phy); 156 return ret; 157 } 158 159 /* Register for extcon if supported */ 160 if (of_property_present(dev->of_node, "extcon")) { 161 udc->edev = extcon_get_edev_by_phandle(dev, 0); 162 if (IS_ERR(udc->edev)) { 163 if (PTR_ERR(udc->edev) == -EPROBE_DEFER) 164 return -EPROBE_DEFER; 165 dev_err(dev, "Invalid or missing extcon\n"); 166 ret = PTR_ERR(udc->edev); 167 goto exit_phy; 168 } 169 170 udc->nb.notifier_call = usbd_connect_notify; 171 ret = extcon_register_notifier(udc->edev, EXTCON_USB, 172 &udc->nb); 173 if (ret < 0) { 174 dev_err(dev, "Can't register extcon device\n"); 175 goto exit_phy; 176 } 177 178 ret = extcon_get_state(udc->edev, EXTCON_USB); 179 if (ret < 0) { 180 dev_err(dev, "Can't get cable state\n"); 181 goto exit_extcon; 182 } else if (ret) { 183 udc->conn_type = ret; 184 } 185 INIT_DELAYED_WORK(&udc->drd_work, udc_drd_work); 186 } 187 188 /* init dma pools */ 189 if (use_dma) { 190 ret = init_dma_pools(udc); 191 if (ret != 0) 192 goto exit_extcon; 193 } 194 195 ret = devm_request_irq(dev, udc->irq, udc_irq, IRQF_SHARED, 196 "snps-udc", udc); 197 if (ret < 0) { 198 dev_err(dev, "Request irq %d failed for UDC\n", udc->irq); 199 goto exit_dma; 200 } 201 202 platform_set_drvdata(pdev, udc); 203 udc->chiprev = UDC_BCM_REV; 204 205 if (udc_probe(udc)) { 206 ret = -ENODEV; 207 goto exit_dma; 208 } 209 dev_info(dev, "Synopsys UDC platform driver probe successful\n"); 210 211 return 0; 212 213 exit_dma: 214 if (use_dma) 215 free_dma_pools(udc); 216 exit_extcon: 217 if (udc->edev) 218 extcon_unregister_notifier(udc->edev, EXTCON_USB, &udc->nb); 219 exit_phy: 220 if (udc->udc_phy) { 221 phy_power_off(udc->udc_phy); 222 phy_exit(udc->udc_phy); 223 } 224 return ret; 225 } 226 227 static void udc_plat_remove(struct platform_device *pdev) 228 { 229 struct udc *dev; 230 231 dev = platform_get_drvdata(pdev); 232 233 usb_del_gadget_udc(&dev->gadget); 234 /* gadget driver must not be registered */ 235 if (WARN_ON(dev->driver)) 236 return; 237 238 /* dma pool cleanup */ 239 free_dma_pools(dev); 240 241 udc_remove(dev); 242 243 platform_set_drvdata(pdev, NULL); 244 245 phy_power_off(dev->udc_phy); 246 phy_exit(dev->udc_phy); 247 extcon_unregister_notifier(dev->edev, EXTCON_USB, &dev->nb); 248 249 dev_info(&pdev->dev, "Synopsys UDC platform driver removed\n"); 250 } 251 252 #ifdef CONFIG_PM_SLEEP 253 static int udc_plat_suspend(struct device *dev) 254 { 255 struct udc *udc; 256 257 udc = dev_get_drvdata(dev); 258 stop_udc(udc); 259 260 if (extcon_get_state(udc->edev, EXTCON_USB) > 0) { 261 dev_dbg(udc->dev, "device -> idle\n"); 262 stop_udc(udc); 263 } 264 phy_power_off(udc->udc_phy); 265 phy_exit(udc->udc_phy); 266 267 return 0; 268 } 269 270 static int udc_plat_resume(struct device *dev) 271 { 272 struct udc *udc; 273 int ret; 274 275 udc = dev_get_drvdata(dev); 276 277 ret = phy_init(udc->udc_phy); 278 if (ret) { 279 dev_err(udc->dev, "UDC phy init failure"); 280 return ret; 281 } 282 283 ret = phy_power_on(udc->udc_phy); 284 if (ret) { 285 dev_err(udc->dev, "UDC phy power on failure"); 286 phy_exit(udc->udc_phy); 287 return ret; 288 } 289 290 if (extcon_get_state(udc->edev, EXTCON_USB) > 0) { 291 dev_dbg(udc->dev, "idle -> device\n"); 292 start_udc(udc); 293 } 294 295 return 0; 296 } 297 static const struct dev_pm_ops udc_plat_pm_ops = { 298 .suspend = udc_plat_suspend, 299 .resume = udc_plat_resume, 300 }; 301 #endif 302 303 static const struct of_device_id of_udc_match[] = { 304 { .compatible = "brcm,ns2-udc", }, 305 { .compatible = "brcm,cygnus-udc", }, 306 { .compatible = "brcm,iproc-udc", }, 307 { } 308 }; 309 MODULE_DEVICE_TABLE(of, of_udc_match); 310 311 static struct platform_driver udc_plat_driver = { 312 .probe = udc_plat_probe, 313 .remove_new = udc_plat_remove, 314 .driver = { 315 .name = "snps-udc-plat", 316 .of_match_table = of_udc_match, 317 #ifdef CONFIG_PM_SLEEP 318 .pm = &udc_plat_pm_ops, 319 #endif 320 }, 321 }; 322 module_platform_driver(udc_plat_driver); 323 324 MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); 325 MODULE_AUTHOR("Broadcom"); 326 MODULE_LICENSE("GPL v2"); 327