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