1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Cadence PCI Glue driver. 4 * 5 * Copyright (C) 2019 Cadence. 6 * 7 * Author: Pawel Laszczak <pawell@cadence.com> 8 * 9 */ 10 11 #include <linux/platform_device.h> 12 #include <linux/dma-mapping.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 #include <linux/pci.h> 17 18 #include "core.h" 19 #include "gadget-export.h" 20 21 #define PCI_BAR_HOST 0 22 #define PCI_BAR_OTG 0 23 #define PCI_BAR_DEV 2 24 25 #define PCI_DEV_FN_HOST_DEVICE 0 26 #define PCI_DEV_FN_OTG 1 27 28 #define PCI_DRIVER_NAME "cdns-pci-usbssp" 29 #define PLAT_DRIVER_NAME "cdns-usbssp" 30 31 #define CDNS_VENDOR_ID 0x17cd 32 #define CDNS_DEVICE_ID 0x0200 33 #define CDNS_DRD_ID 0x0100 34 #define CDNS_DRD_IF (PCI_CLASS_SERIAL_USB << 8 | 0x80) 35 36 static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev) 37 { 38 /* 39 * Gets the second function. 40 * Platform has two function. The fist keeps resources for 41 * Host/Device while the secon keeps resources for DRD/OTG. 42 */ 43 if (pdev->device == CDNS_DEVICE_ID) 44 return pci_get_device(pdev->vendor, CDNS_DRD_ID, NULL); 45 else if (pdev->device == CDNS_DRD_ID) 46 return pci_get_device(pdev->vendor, CDNS_DEVICE_ID, NULL); 47 48 return NULL; 49 } 50 51 static int cdnsp_pci_probe(struct pci_dev *pdev, 52 const struct pci_device_id *id) 53 { 54 struct device *dev = &pdev->dev; 55 struct pci_dev *func; 56 struct resource *res; 57 struct cdns *cdnsp; 58 int ret; 59 60 /* 61 * For GADGET/HOST PCI (devfn) function number is 0, 62 * for OTG PCI (devfn) function number is 1. 63 */ 64 if (!id || (pdev->devfn != PCI_DEV_FN_HOST_DEVICE && 65 pdev->devfn != PCI_DEV_FN_OTG)) 66 return -EINVAL; 67 68 func = cdnsp_get_second_fun(pdev); 69 if (!func) 70 return -EINVAL; 71 72 if (func->class == PCI_CLASS_SERIAL_USB_XHCI || 73 pdev->class == PCI_CLASS_SERIAL_USB_XHCI) { 74 ret = -EINVAL; 75 goto put_pci; 76 } 77 78 ret = pcim_enable_device(pdev); 79 if (ret) { 80 dev_err(&pdev->dev, "Enabling PCI device has failed %d\n", ret); 81 goto put_pci; 82 } 83 84 pci_set_master(pdev); 85 if (pci_is_enabled(func)) { 86 cdnsp = pci_get_drvdata(func); 87 } else { 88 cdnsp = kzalloc(sizeof(*cdnsp), GFP_KERNEL); 89 if (!cdnsp) { 90 ret = -ENOMEM; 91 goto disable_pci; 92 } 93 } 94 95 /* For GADGET device function number is 0. */ 96 if (pdev->devfn == 0) { 97 resource_size_t rsrc_start, rsrc_len; 98 99 /* Function 0: host(BAR_0) + device(BAR_1).*/ 100 dev_dbg(dev, "Initialize resources\n"); 101 rsrc_start = pci_resource_start(pdev, PCI_BAR_DEV); 102 rsrc_len = pci_resource_len(pdev, PCI_BAR_DEV); 103 res = devm_request_mem_region(dev, rsrc_start, rsrc_len, "dev"); 104 if (!res) { 105 dev_dbg(dev, "controller already in use\n"); 106 ret = -EBUSY; 107 goto free_cdnsp; 108 } 109 110 cdnsp->dev_regs = devm_ioremap(dev, rsrc_start, rsrc_len); 111 if (!cdnsp->dev_regs) { 112 dev_dbg(dev, "error mapping memory\n"); 113 ret = -EFAULT; 114 goto free_cdnsp; 115 } 116 117 cdnsp->dev_irq = pdev->irq; 118 dev_dbg(dev, "USBSS-DEV physical base addr: %pa\n", 119 &rsrc_start); 120 121 res = &cdnsp->xhci_res[0]; 122 res->start = pci_resource_start(pdev, PCI_BAR_HOST); 123 res->end = pci_resource_end(pdev, PCI_BAR_HOST); 124 res->name = "xhci"; 125 res->flags = IORESOURCE_MEM; 126 dev_dbg(dev, "USBSS-XHCI physical base addr: %pa\n", 127 &res->start); 128 129 /* Interrupt for XHCI, */ 130 res = &cdnsp->xhci_res[1]; 131 res->start = pdev->irq; 132 res->name = "host"; 133 res->flags = IORESOURCE_IRQ; 134 } else { 135 res = &cdnsp->otg_res; 136 res->start = pci_resource_start(pdev, PCI_BAR_OTG); 137 res->end = pci_resource_end(pdev, PCI_BAR_OTG); 138 res->name = "otg"; 139 res->flags = IORESOURCE_MEM; 140 dev_dbg(dev, "CDNSP-DRD physical base addr: %pa\n", 141 &res->start); 142 143 /* Interrupt for OTG/DRD. */ 144 cdnsp->otg_irq = pdev->irq; 145 } 146 147 if (pci_is_enabled(func)) { 148 cdnsp->dev = dev; 149 cdnsp->gadget_init = cdnsp_gadget_init; 150 151 ret = cdns_init(cdnsp); 152 if (ret) 153 goto free_cdnsp; 154 } 155 156 pci_set_drvdata(pdev, cdnsp); 157 158 device_wakeup_enable(&pdev->dev); 159 if (pci_dev_run_wake(pdev)) 160 pm_runtime_put_noidle(&pdev->dev); 161 162 return 0; 163 164 free_cdnsp: 165 if (!pci_is_enabled(func)) 166 kfree(cdnsp); 167 168 disable_pci: 169 pci_disable_device(pdev); 170 171 put_pci: 172 pci_dev_put(func); 173 174 return ret; 175 } 176 177 static void cdnsp_pci_remove(struct pci_dev *pdev) 178 { 179 struct cdns *cdnsp; 180 struct pci_dev *func; 181 182 func = cdnsp_get_second_fun(pdev); 183 cdnsp = (struct cdns *)pci_get_drvdata(pdev); 184 185 if (pci_dev_run_wake(pdev)) 186 pm_runtime_get_noresume(&pdev->dev); 187 188 if (pci_is_enabled(func)) { 189 cdns_remove(cdnsp); 190 } else { 191 kfree(cdnsp); 192 } 193 194 pci_dev_put(func); 195 } 196 197 static int __maybe_unused cdnsp_pci_suspend(struct device *dev) 198 { 199 struct cdns *cdns = dev_get_drvdata(dev); 200 201 return cdns_suspend(cdns); 202 } 203 204 static int __maybe_unused cdnsp_pci_resume(struct device *dev) 205 { 206 struct cdns *cdns = dev_get_drvdata(dev); 207 unsigned long flags; 208 int ret; 209 210 spin_lock_irqsave(&cdns->lock, flags); 211 ret = cdns_resume(cdns, 1); 212 spin_unlock_irqrestore(&cdns->lock, flags); 213 214 return ret; 215 } 216 217 static const struct dev_pm_ops cdnsp_pci_pm_ops = { 218 SET_SYSTEM_SLEEP_PM_OPS(cdnsp_pci_suspend, cdnsp_pci_resume) 219 }; 220 221 static const struct pci_device_id cdnsp_pci_ids[] = { 222 { PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 223 PCI_CLASS_SERIAL_USB_DEVICE, PCI_ANY_ID }, 224 { PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 225 CDNS_DRD_IF, PCI_ANY_ID }, 226 { PCI_VENDOR_ID_CDNS, CDNS_DRD_ID, PCI_ANY_ID, PCI_ANY_ID, 227 CDNS_DRD_IF, PCI_ANY_ID }, 228 { 0, } 229 }; 230 231 static struct pci_driver cdnsp_pci_driver = { 232 .name = "cdnsp-pci", 233 .id_table = &cdnsp_pci_ids[0], 234 .probe = cdnsp_pci_probe, 235 .remove = cdnsp_pci_remove, 236 .driver = { 237 .pm = &cdnsp_pci_pm_ops, 238 } 239 }; 240 241 module_pci_driver(cdnsp_pci_driver); 242 MODULE_DEVICE_TABLE(pci, cdnsp_pci_ids); 243 244 MODULE_ALIAS("pci:cdnsp"); 245 MODULE_AUTHOR("Pawel Laszczak <pawell@cadence.com>"); 246 MODULE_LICENSE("GPL v2"); 247 MODULE_DESCRIPTION("Cadence CDNSP PCI driver"); 248