xref: /linux/drivers/usb/dwc3/dwc3-pci.c (revision 4949009eb8d40a441dcddcd96e101e77d31cf1b2)
1 /**
2  * dwc3-pci.c - PCI Specific glue layer
3  *
4  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
5  *
6  * Authors: Felipe Balbi <balbi@ti.com>,
7  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2  of
11  * the License as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  */
18 
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/slab.h>
22 #include <linux/pci.h>
23 #include <linux/platform_device.h>
24 
25 #include <linux/usb/otg.h>
26 #include <linux/usb/usb_phy_generic.h>
27 
28 #include "platform_data.h"
29 
30 /* FIXME define these in <linux/pci_ids.h> */
31 #define PCI_VENDOR_ID_SYNOPSYS		0x16c3
32 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3	0xabcd
33 #define PCI_DEVICE_ID_INTEL_BYT		0x0f37
34 #define PCI_DEVICE_ID_INTEL_MRFLD	0x119e
35 #define PCI_DEVICE_ID_INTEL_BSW		0x22B7
36 #define PCI_DEVICE_ID_INTEL_SPTLP	0x9d30
37 #define PCI_DEVICE_ID_INTEL_SPTH	0xa130
38 
39 struct dwc3_pci {
40 	struct device		*dev;
41 	struct platform_device	*dwc3;
42 	struct platform_device	*usb2_phy;
43 	struct platform_device	*usb3_phy;
44 };
45 
46 static int dwc3_pci_register_phys(struct dwc3_pci *glue)
47 {
48 	struct usb_phy_generic_platform_data pdata;
49 	struct platform_device	*pdev;
50 	int			ret;
51 
52 	memset(&pdata, 0x00, sizeof(pdata));
53 
54 	pdev = platform_device_alloc("usb_phy_generic", 0);
55 	if (!pdev)
56 		return -ENOMEM;
57 
58 	glue->usb2_phy = pdev;
59 	pdata.type = USB_PHY_TYPE_USB2;
60 	pdata.gpio_reset = -1;
61 
62 	ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata));
63 	if (ret)
64 		goto err1;
65 
66 	pdev = platform_device_alloc("usb_phy_generic", 1);
67 	if (!pdev) {
68 		ret = -ENOMEM;
69 		goto err1;
70 	}
71 
72 	glue->usb3_phy = pdev;
73 	pdata.type = USB_PHY_TYPE_USB3;
74 
75 	ret = platform_device_add_data(glue->usb3_phy, &pdata, sizeof(pdata));
76 	if (ret)
77 		goto err2;
78 
79 	ret = platform_device_add(glue->usb2_phy);
80 	if (ret)
81 		goto err2;
82 
83 	ret = platform_device_add(glue->usb3_phy);
84 	if (ret)
85 		goto err3;
86 
87 	return 0;
88 
89 err3:
90 	platform_device_del(glue->usb2_phy);
91 
92 err2:
93 	platform_device_put(glue->usb3_phy);
94 
95 err1:
96 	platform_device_put(glue->usb2_phy);
97 
98 	return ret;
99 }
100 
101 static int dwc3_pci_probe(struct pci_dev *pci,
102 		const struct pci_device_id *id)
103 {
104 	struct resource		res[2];
105 	struct platform_device	*dwc3;
106 	struct dwc3_pci		*glue;
107 	int			ret;
108 	struct device		*dev = &pci->dev;
109 	struct dwc3_platform_data dwc3_pdata;
110 
111 	memset(&dwc3_pdata, 0x00, sizeof(dwc3_pdata));
112 
113 	glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
114 	if (!glue)
115 		return -ENOMEM;
116 
117 	glue->dev = dev;
118 
119 	ret = pcim_enable_device(pci);
120 	if (ret) {
121 		dev_err(dev, "failed to enable pci device\n");
122 		return -ENODEV;
123 	}
124 
125 	pci_set_master(pci);
126 
127 	ret = dwc3_pci_register_phys(glue);
128 	if (ret) {
129 		dev_err(dev, "couldn't register PHYs\n");
130 		return ret;
131 	}
132 
133 	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
134 	if (!dwc3) {
135 		dev_err(dev, "couldn't allocate dwc3 device\n");
136 		return -ENOMEM;
137 	}
138 
139 	memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
140 
141 	res[0].start	= pci_resource_start(pci, 0);
142 	res[0].end	= pci_resource_end(pci, 0);
143 	res[0].name	= "dwc_usb3";
144 	res[0].flags	= IORESOURCE_MEM;
145 
146 	res[1].start	= pci->irq;
147 	res[1].name	= "dwc_usb3";
148 	res[1].flags	= IORESOURCE_IRQ;
149 
150 	if (pci->vendor == PCI_VENDOR_ID_AMD &&
151 			pci->device == PCI_DEVICE_ID_AMD_NL_USB) {
152 		dwc3_pdata.has_lpm_erratum = true;
153 		dwc3_pdata.lpm_nyet_threshold = 0xf;
154 
155 		dwc3_pdata.u2exit_lfps_quirk = true;
156 		dwc3_pdata.u2ss_inp3_quirk = true;
157 		dwc3_pdata.req_p1p2p3_quirk = true;
158 		dwc3_pdata.del_p1p2p3_quirk = true;
159 		dwc3_pdata.del_phy_power_chg_quirk = true;
160 		dwc3_pdata.lfps_filter_quirk = true;
161 		dwc3_pdata.rx_detect_poll_quirk = true;
162 
163 		dwc3_pdata.tx_de_emphasis_quirk = true;
164 		dwc3_pdata.tx_de_emphasis = 1;
165 
166 		/*
167 		 * FIXME these quirks should be removed when AMD NL
168 		 * taps out
169 		 */
170 		dwc3_pdata.disable_scramble_quirk = true;
171 		dwc3_pdata.dis_u3_susphy_quirk = true;
172 		dwc3_pdata.dis_u2_susphy_quirk = true;
173 	}
174 
175 	ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
176 	if (ret) {
177 		dev_err(dev, "couldn't add resources to dwc3 device\n");
178 		return ret;
179 	}
180 
181 	pci_set_drvdata(pci, glue);
182 
183 	ret = platform_device_add_data(dwc3, &dwc3_pdata, sizeof(dwc3_pdata));
184 	if (ret)
185 		goto err3;
186 
187 	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
188 
189 	dwc3->dev.dma_mask = dev->dma_mask;
190 	dwc3->dev.dma_parms = dev->dma_parms;
191 	dwc3->dev.parent = dev;
192 	glue->dwc3 = dwc3;
193 
194 	ret = platform_device_add(dwc3);
195 	if (ret) {
196 		dev_err(dev, "failed to register dwc3 device\n");
197 		goto err3;
198 	}
199 
200 	return 0;
201 
202 err3:
203 	platform_device_put(dwc3);
204 	return ret;
205 }
206 
207 static void dwc3_pci_remove(struct pci_dev *pci)
208 {
209 	struct dwc3_pci	*glue = pci_get_drvdata(pci);
210 
211 	platform_device_unregister(glue->dwc3);
212 	platform_device_unregister(glue->usb2_phy);
213 	platform_device_unregister(glue->usb3_phy);
214 }
215 
216 static const struct pci_device_id dwc3_pci_id_table[] = {
217 	{
218 		PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
219 				PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
220 	},
221 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
222 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
223 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
224 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
225 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
226 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
227 	{  }	/* Terminating Entry */
228 };
229 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
230 
231 #ifdef CONFIG_PM_SLEEP
232 static int dwc3_pci_suspend(struct device *dev)
233 {
234 	struct pci_dev	*pci = to_pci_dev(dev);
235 
236 	pci_disable_device(pci);
237 
238 	return 0;
239 }
240 
241 static int dwc3_pci_resume(struct device *dev)
242 {
243 	struct pci_dev	*pci = to_pci_dev(dev);
244 	int		ret;
245 
246 	ret = pci_enable_device(pci);
247 	if (ret) {
248 		dev_err(dev, "can't re-enable device --> %d\n", ret);
249 		return ret;
250 	}
251 
252 	pci_set_master(pci);
253 
254 	return 0;
255 }
256 #endif /* CONFIG_PM_SLEEP */
257 
258 static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
259 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
260 };
261 
262 static struct pci_driver dwc3_pci_driver = {
263 	.name		= "dwc3-pci",
264 	.id_table	= dwc3_pci_id_table,
265 	.probe		= dwc3_pci_probe,
266 	.remove		= dwc3_pci_remove,
267 	.driver		= {
268 		.pm	= &dwc3_pci_dev_pm_ops,
269 	},
270 };
271 
272 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
273 MODULE_LICENSE("GPL v2");
274 MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");
275 
276 module_pci_driver(dwc3_pci_driver);
277