File Index
Files and directories
Sign in
FILE

dwc3-pci.c

File preview with syntax highlighting.

linux-6.19.14/drivers/usb/dwc3/dwc3-pci.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * dwc3-pci.c - PCI Specific glue layer
  4 *
  5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com
  6 *
  7 * Authors: Felipe Balbi <balbi@ti.com>,
  8 *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  9 */
 10
 11#include <linux/dmi.h>
 12#include <linux/kernel.h>
 13#include <linux/module.h>
 14#include <linux/slab.h>
 15#include <linux/pci.h>
 16#include <linux/workqueue.h>
 17#include <linux/pm_runtime.h>
 18#include <linux/platform_device.h>
 19#include <linux/gpio/consumer.h>
 20#include <linux/gpio/machine.h>
 21#include <linux/acpi.h>
 22#include <linux/delay.h>
 23
 24#define PCI_DEVICE_ID_INTEL_CMLLP		0x02ee
 25#define PCI_DEVICE_ID_INTEL_CMLH		0x06ee
 26#define PCI_DEVICE_ID_INTEL_BXT			0x0aaa
 27#define PCI_DEVICE_ID_INTEL_BYT			0x0f37
 28#define PCI_DEVICE_ID_INTEL_MRFLD		0x119e
 29#define PCI_DEVICE_ID_INTEL_BXT_M		0x1aaa
 30#define PCI_DEVICE_ID_INTEL_BSW			0x22b7
 31#define PCI_DEVICE_ID_INTEL_GLK			0x31aa
 32#define PCI_DEVICE_ID_INTEL_ICLLP		0x34ee
 33#define PCI_DEVICE_ID_INTEL_TGPH		0x43ee
 34#define PCI_DEVICE_ID_INTEL_ADL			0x460e
 35#define PCI_DEVICE_ID_INTEL_ADLN		0x465e
 36#define PCI_DEVICE_ID_INTEL_EHL			0x4b7e
 37#define PCI_DEVICE_ID_INTEL_WCL			0x4d7e
 38#define PCI_DEVICE_ID_INTEL_JSP			0x4dee
 39#define PCI_DEVICE_ID_INTEL_ADL_PCH		0x51ee
 40#define PCI_DEVICE_ID_INTEL_ADLN_PCH		0x54ee
 41#define PCI_DEVICE_ID_INTEL_APL			0x5aaa
 42#define PCI_DEVICE_ID_INTEL_NVLS_PCH		0x6e6f
 43#define PCI_DEVICE_ID_INTEL_ARLH_PCH		0x777e
 44#define PCI_DEVICE_ID_INTEL_RPLS		0x7a61
 45#define PCI_DEVICE_ID_INTEL_MTL			0x7e7e
 46#define PCI_DEVICE_ID_INTEL_ADLS		0x7ae1
 47#define PCI_DEVICE_ID_INTEL_MTLM		0x7eb1
 48#define PCI_DEVICE_ID_INTEL_MTLP		0x7ec1
 49#define PCI_DEVICE_ID_INTEL_MTLS		0x7f6f
 50#define PCI_DEVICE_ID_INTEL_TGL			0x9a15
 51#define PCI_DEVICE_ID_INTEL_SPTLP		0x9d30
 52#define PCI_DEVICE_ID_INTEL_CNPLP		0x9dee
 53#define PCI_DEVICE_ID_INTEL_TGPLP		0xa0ee
 54#define PCI_DEVICE_ID_INTEL_SPTH		0xa130
 55#define PCI_DEVICE_ID_INTEL_KBP			0xa2b0
 56#define PCI_DEVICE_ID_INTEL_CNPH		0xa36e
 57#define PCI_DEVICE_ID_INTEL_CNPV		0xa3b0
 58#define PCI_DEVICE_ID_INTEL_RPL			0xa70e
 59#define PCI_DEVICE_ID_INTEL_NVLH		0xd37f
 60#define PCI_DEVICE_ID_INTEL_PTLH		0xe332
 61#define PCI_DEVICE_ID_INTEL_PTLH_PCH		0xe37e
 62#define PCI_DEVICE_ID_INTEL_PTLU		0xe432
 63#define PCI_DEVICE_ID_INTEL_PTLU_PCH		0xe47e
 64#define PCI_DEVICE_ID_AMD_MR			0x163a
 65
 66#define PCI_INTEL_BXT_DSM_GUID		"732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
 67#define PCI_INTEL_BXT_FUNC_PMU_PWR	4
 68#define PCI_INTEL_BXT_STATE_D0		0
 69#define PCI_INTEL_BXT_STATE_D3		3
 70
 71#define GP_RWBAR			1
 72#define GP_RWREG1			0xa0
 73#define GP_RWREG1_ULPI_REFCLK_DISABLE	(1 << 17)
 74
 75/**
 76 * struct dwc3_pci - Driver private structure
 77 * @dwc3: child dwc3 platform_device
 78 * @pci: our link to PCI bus
 79 * @guid: _DSM GUID
 80 * @has_dsm_for_pm: true for devices which need to run _DSM on runtime PM
 81 * @wakeup_work: work for asynchronous resume
 82 */
 83struct dwc3_pci {
 84	struct platform_device *dwc3;
 85	struct pci_dev *pci;
 86
 87	guid_t guid;
 88
 89	unsigned int has_dsm_for_pm:1;
 90	struct work_struct wakeup_work;
 91};
 92
 93static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
 94static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
 95
 96static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = {
 97	{ "reset-gpios", &reset_gpios, 1 },
 98	{ "cs-gpios", &cs_gpios, 1 },
 99	{ },
100};
101
102static struct gpiod_lookup_table platform_bytcr_gpios = {
103	.dev_id		= "0000:00:16.0",
104	.table		= {
105		GPIO_LOOKUP("INT33FC:00", 54, "cs", GPIO_ACTIVE_HIGH),
106		GPIO_LOOKUP("INT33FC:02", 14, "reset", GPIO_ACTIVE_HIGH),
107		{}
108	},
109};
110
111static int dwc3_byt_enable_ulpi_refclock(struct pci_dev *pci)
112{
113	void __iomem	*reg;
114	u32		value;
115
116	reg = pcim_iomap(pci, GP_RWBAR, 0);
117	if (!reg)
118		return -ENOMEM;
119
120	value = readl(reg + GP_RWREG1);
121	if (!(value & GP_RWREG1_ULPI_REFCLK_DISABLE))
122		goto unmap; /* ULPI refclk already enabled */
123
124	value &= ~GP_RWREG1_ULPI_REFCLK_DISABLE;
125	writel(value, reg + GP_RWREG1);
126	/* This comes from the Intel Android x86 tree w/o any explanation */
127	msleep(100);
128unmap:
129	pcim_iounmap(pci, reg);
130	return 0;
131}
132
133static const struct property_entry dwc3_pci_intel_properties[] = {
134	PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
135	PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
136	{}
137};
138
139static const struct property_entry dwc3_pci_intel_phy_charger_detect_properties[] = {
140	PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
141	PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
142	PROPERTY_ENTRY_BOOL("linux,phy_charger_detect"),
143	PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
144	{}
145};
146
147static const struct property_entry dwc3_pci_intel_byt_properties[] = {
148	PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
149	PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
150	PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
151	{}
152};
153
154/*
155 * Intel Merrifield SoC uses these endpoints for tracing and they cannot
156 * be re-allocated if being used because the side band flow control signals
157 * are hard wired to certain endpoints:
158 * - 1 High BW Bulk IN (IN#1) (RTIT)
159 * - 1 1KB BW Bulk IN (IN#8) + 1 1KB BW Bulk OUT (Run Control) (OUT#8)
160 */
161static const u8 dwc3_pci_mrfld_reserved_endpoints[] = { 3, 16, 17 };
162
163static const struct property_entry dwc3_pci_mrfld_properties[] = {
164	PROPERTY_ENTRY_STRING("dr_mode", "otg"),
165	PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"),
166	PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
167	PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
168	PROPERTY_ENTRY_U8_ARRAY("snps,reserved-endpoints", dwc3_pci_mrfld_reserved_endpoints),
169	PROPERTY_ENTRY_BOOL("snps,usb2-gadget-lpm-disable"),
170	PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
171	{}
172};
173
174static const struct property_entry dwc3_pci_amd_properties[] = {
175	PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"),
176	PROPERTY_ENTRY_U8("snps,lpm-nyet-threshold", 0xf),
177	PROPERTY_ENTRY_BOOL("snps,u2exit_lfps_quirk"),
178	PROPERTY_ENTRY_BOOL("snps,u2ss_inp3_quirk"),
179	PROPERTY_ENTRY_BOOL("snps,req_p1p2p3_quirk"),
180	PROPERTY_ENTRY_BOOL("snps,del_p1p2p3_quirk"),
181	PROPERTY_ENTRY_BOOL("snps,del_phy_power_chg_quirk"),
182	PROPERTY_ENTRY_BOOL("snps,lfps_filter_quirk"),
183	PROPERTY_ENTRY_BOOL("snps,rx_detect_poll_quirk"),
184	PROPERTY_ENTRY_BOOL("snps,tx_de_emphasis_quirk"),
185	PROPERTY_ENTRY_U8("snps,tx_de_emphasis", 1),
186	/* FIXME these quirks should be removed when AMD NL tapes out */
187	PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"),
188	PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
189	PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
190	PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
191	{}
192};
193
194static const struct property_entry dwc3_pci_mr_properties[] = {
195	PROPERTY_ENTRY_STRING("dr_mode", "otg"),
196	PROPERTY_ENTRY_BOOL("usb-role-switch"),
197	PROPERTY_ENTRY_STRING("role-switch-default-mode", "host"),
198	PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
199	{}
200};
201
202static const struct software_node dwc3_pci_intel_swnode = {
203	.properties = dwc3_pci_intel_properties,
204};
205
206static const struct software_node dwc3_pci_intel_phy_charger_detect_swnode = {
207	.properties = dwc3_pci_intel_phy_charger_detect_properties,
208};
209
210static const struct software_node dwc3_pci_intel_byt_swnode = {
211	.properties = dwc3_pci_intel_byt_properties,
212};
213
214static const struct software_node dwc3_pci_intel_mrfld_swnode = {
215	.properties = dwc3_pci_mrfld_properties,
216};
217
218static const struct software_node dwc3_pci_amd_swnode = {
219	.properties = dwc3_pci_amd_properties,
220};
221
222static const struct software_node dwc3_pci_amd_mr_swnode = {
223	.properties = dwc3_pci_mr_properties,
224};
225
226static int dwc3_pci_quirks(struct dwc3_pci *dwc,
227			   const struct software_node *swnode)
228{
229	struct pci_dev			*pdev = dwc->pci;
230
231	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
232		if (pdev->device == PCI_DEVICE_ID_INTEL_BXT ||
233		    pdev->device == PCI_DEVICE_ID_INTEL_BXT_M ||
234		    pdev->device == PCI_DEVICE_ID_INTEL_EHL) {
235			guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid);
236			dwc->has_dsm_for_pm = true;
237		}
238
239		if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
240			struct gpio_desc *gpio;
241			const char *bios_ver;
242			int ret;
243
244			/* On BYT the FW does not always enable the refclock */
245			ret = dwc3_byt_enable_ulpi_refclock(pdev);
246			if (ret)
247				return ret;
248
249			ret = devm_acpi_dev_add_driver_gpios(&pdev->dev,
250					acpi_dwc3_byt_gpios);
251			if (ret)
252				dev_dbg(&pdev->dev, "failed to add mapping table\n");
253
254			/*
255			 * A lot of BYT devices lack ACPI resource entries for
256			 * the GPIOs. If the ACPI entry for the GPIO controller
257			 * is present add a fallback mapping to the reference
258			 * design GPIOs which all boards seem to use.
259			 */
260			if (acpi_dev_present("INT33FC", NULL, -1))
261				gpiod_add_lookup_table(&platform_bytcr_gpios);
262
263			/*
264			 * These GPIOs will turn on the USB2 PHY. Note that we have to
265			 * put the gpio descriptors again here because the phy driver
266			 * might want to grab them, too.
267			 */
268			gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
269			if (IS_ERR(gpio))
270				return PTR_ERR(gpio);
271
272			gpiod_set_value_cansleep(gpio, 1);
273			gpiod_put(gpio);
274
275			gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
276			if (IS_ERR(gpio))
277				return PTR_ERR(gpio);
278
279			if (gpio) {
280				gpiod_set_value_cansleep(gpio, 1);
281				gpiod_put(gpio);
282				usleep_range(10000, 11000);
283			}
284
285			/*
286			 * Make the pdev name predictable (only 1 DWC3 on BYT)
287			 * and patch the phy dev-name into the lookup table so
288			 * that the phy-driver can get the GPIOs.
289			 */
290			dwc->dwc3->id = PLATFORM_DEVID_NONE;
291			platform_bytcr_gpios.dev_id = "dwc3.ulpi";
292
293			/*
294			 * Some Android tablets with a Crystal Cove PMIC
295			 * (INT33FD), rely on the TUSB1211 phy for charger
296			 * detection. These can be identified by them _not_
297			 * using the standard ACPI battery and ac drivers.
298			 */
299			bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
300			if (acpi_dev_present("INT33FD", "1", 2) &&
301			    acpi_quirk_skip_acpi_ac_and_battery() &&
302			    /* Lenovo Yoga Tablet 2 Pro 1380 uses LC824206XA instead */
303			    !(bios_ver &&
304			      strstarts(bios_ver, "BLADE_21.X64.0005.R00.1504101516"))) {
305				dev_info(&pdev->dev, "Using TUSB1211 phy for charger detection\n");
306				swnode = &dwc3_pci_intel_phy_charger_detect_swnode;
307			}
308		}
309	}
310
311	return device_add_software_node(&dwc->dwc3->dev, swnode);
312}
313
314#ifdef CONFIG_PM
315static void dwc3_pci_resume_work(struct work_struct *work)
316{
317	struct dwc3_pci *dwc = container_of(work, struct dwc3_pci, wakeup_work);
318	struct platform_device *dwc3 = dwc->dwc3;
319	int ret;
320
321	ret = pm_runtime_get_sync(&dwc3->dev);
322	if (ret < 0) {
323		pm_runtime_put_sync_autosuspend(&dwc3->dev);
324		return;
325	}
326
327	pm_runtime_put_sync_autosuspend(&dwc3->dev);
328}
329#endif
330
331static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
332{
333	struct dwc3_pci		*dwc;
334	struct resource		res[2];
335	int			ret;
336	struct device		*dev = &pci->dev;
337
338	ret = pcim_enable_device(pci);
339	if (ret) {
340		dev_err(dev, "failed to enable pci device\n");
341		return -ENODEV;
342	}
343
344	pci_set_master(pci);
345
346	dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
347	if (!dwc)
348		return -ENOMEM;
349
350	dwc->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
351	if (!dwc->dwc3)
352		return -ENOMEM;
353
354	memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
355
356	res[0].start	= pci_resource_start(pci, 0);
357	res[0].end	= pci_resource_end(pci, 0);
358	res[0].name	= "dwc_usb3";
359	res[0].flags	= IORESOURCE_MEM;
360
361	res[1].start	= pci->irq;
362	res[1].name	= "dwc_usb3";
363	res[1].flags	= IORESOURCE_IRQ;
364
365	ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res));
366	if (ret) {
367		dev_err(dev, "couldn't add resources to dwc3 device\n");
368		goto err;
369	}
370
371	dwc->pci = pci;
372	dwc->dwc3->dev.parent = dev;
373	ACPI_COMPANION_SET(&dwc->dwc3->dev, ACPI_COMPANION(dev));
374
375	ret = dwc3_pci_quirks(dwc, (void *)id->driver_data);
376	if (ret)
377		goto err;
378
379	ret = platform_device_add(dwc->dwc3);
380	if (ret) {
381		dev_err(dev, "failed to register dwc3 device\n");
382		goto err;
383	}
384
385	device_init_wakeup(dev, true);
386	pci_set_drvdata(pci, dwc);
387	pm_runtime_put(dev);
388#ifdef CONFIG_PM
389	INIT_WORK(&dwc->wakeup_work, dwc3_pci_resume_work);
390#endif
391
392	return 0;
393err:
394	device_remove_software_node(&dwc->dwc3->dev);
395	platform_device_put(dwc->dwc3);
396	return ret;
397}
398
399static void dwc3_pci_remove(struct pci_dev *pci)
400{
401	struct dwc3_pci		*dwc = pci_get_drvdata(pci);
402	struct pci_dev		*pdev = dwc->pci;
403
404	if (pdev->device == PCI_DEVICE_ID_INTEL_BYT)
405		gpiod_remove_lookup_table(&platform_bytcr_gpios);
406#ifdef CONFIG_PM
407	cancel_work_sync(&dwc->wakeup_work);
408#endif
409	device_init_wakeup(&pci->dev, false);
410	pm_runtime_get(&pci->dev);
411	device_remove_software_node(&dwc->dwc3->dev);
412	platform_device_unregister(dwc->dwc3);
413}
414
415static const struct pci_device_id dwc3_pci_id_table[] = {
416	{ PCI_DEVICE_DATA(INTEL, CMLLP, &dwc3_pci_intel_swnode) },
417	{ PCI_DEVICE_DATA(INTEL, CMLH, &dwc3_pci_intel_swnode) },
418	{ PCI_DEVICE_DATA(INTEL, BXT, &dwc3_pci_intel_swnode) },
419	{ PCI_DEVICE_DATA(INTEL, BYT, &dwc3_pci_intel_byt_swnode) },
420	{ PCI_DEVICE_DATA(INTEL, MRFLD, &dwc3_pci_intel_mrfld_swnode) },
421	{ PCI_DEVICE_DATA(INTEL, BXT_M, &dwc3_pci_intel_swnode) },
422	{ PCI_DEVICE_DATA(INTEL, BSW, &dwc3_pci_intel_swnode) },
423	{ PCI_DEVICE_DATA(INTEL, GLK, &dwc3_pci_intel_swnode) },
424	{ PCI_DEVICE_DATA(INTEL, ICLLP, &dwc3_pci_intel_swnode) },
425	{ PCI_DEVICE_DATA(INTEL, TGPH, &dwc3_pci_intel_swnode) },
426	{ PCI_DEVICE_DATA(INTEL, ADL, &dwc3_pci_intel_swnode) },
427	{ PCI_DEVICE_DATA(INTEL, ADLN, &dwc3_pci_intel_swnode) },
428	{ PCI_DEVICE_DATA(INTEL, EHL, &dwc3_pci_intel_swnode) },
429	{ PCI_DEVICE_DATA(INTEL, WCL, &dwc3_pci_intel_swnode) },
430	{ PCI_DEVICE_DATA(INTEL, JSP, &dwc3_pci_intel_swnode) },
431	{ PCI_DEVICE_DATA(INTEL, ADL_PCH, &dwc3_pci_intel_swnode) },
432	{ PCI_DEVICE_DATA(INTEL, ADLN_PCH, &dwc3_pci_intel_swnode) },
433	{ PCI_DEVICE_DATA(INTEL, APL, &dwc3_pci_intel_swnode) },
434	{ PCI_DEVICE_DATA(INTEL, NVLS_PCH, &dwc3_pci_intel_swnode) },
435	{ PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) },
436	{ PCI_DEVICE_DATA(INTEL, RPLS, &dwc3_pci_intel_swnode) },
437	{ PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) },
438	{ PCI_DEVICE_DATA(INTEL, ADLS, &dwc3_pci_intel_swnode) },
439	{ PCI_DEVICE_DATA(INTEL, MTLM, &dwc3_pci_intel_swnode) },
440	{ PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) },
441	{ PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) },
442	{ PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) },
443	{ PCI_DEVICE_DATA(INTEL, SPTLP, &dwc3_pci_intel_swnode) },
444	{ PCI_DEVICE_DATA(INTEL, CNPLP, &dwc3_pci_intel_swnode) },
445	{ PCI_DEVICE_DATA(INTEL, TGPLP, &dwc3_pci_intel_swnode) },
446	{ PCI_DEVICE_DATA(INTEL, SPTH, &dwc3_pci_intel_swnode) },
447	{ PCI_DEVICE_DATA(INTEL, KBP, &dwc3_pci_intel_swnode) },
448	{ PCI_DEVICE_DATA(INTEL, CNPH, &dwc3_pci_intel_swnode) },
449	{ PCI_DEVICE_DATA(INTEL, CNPV, &dwc3_pci_intel_swnode) },
450	{ PCI_DEVICE_DATA(INTEL, RPL, &dwc3_pci_intel_swnode) },
451	{ PCI_DEVICE_DATA(INTEL, NVLH, &dwc3_pci_intel_swnode) },
452	{ PCI_DEVICE_DATA(INTEL, PTLH, &dwc3_pci_intel_swnode) },
453	{ PCI_DEVICE_DATA(INTEL, PTLH_PCH, &dwc3_pci_intel_swnode) },
454	{ PCI_DEVICE_DATA(INTEL, PTLU, &dwc3_pci_intel_swnode) },
455	{ PCI_DEVICE_DATA(INTEL, PTLU_PCH, &dwc3_pci_intel_swnode) },
456
457	{ PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) },
458	{ PCI_DEVICE_DATA(AMD, MR, &dwc3_pci_amd_mr_swnode) },
459
460	{  }	/* Terminating Entry */
461};
462MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
463
464#if defined(CONFIG_PM) || defined(CONFIG_PM_SLEEP)
465static int dwc3_pci_dsm(struct dwc3_pci *dwc, int param)
466{
467	union acpi_object *obj;
468	union acpi_object tmp;
469	union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
470
471	if (!dwc->has_dsm_for_pm)
472		return 0;
473
474	tmp.type = ACPI_TYPE_INTEGER;
475	tmp.integer.value = param;
476
477	obj = acpi_evaluate_dsm(ACPI_HANDLE(&dwc->pci->dev), &dwc->guid,
478			1, PCI_INTEL_BXT_FUNC_PMU_PWR, &argv4);
479	if (!obj) {
480		dev_err(&dwc->pci->dev, "failed to evaluate _DSM\n");
481		return -EIO;
482	}
483
484	ACPI_FREE(obj);
485
486	return 0;
487}
488#endif /* CONFIG_PM || CONFIG_PM_SLEEP */
489
490#ifdef CONFIG_PM
491static int dwc3_pci_runtime_suspend(struct device *dev)
492{
493	struct dwc3_pci		*dwc = dev_get_drvdata(dev);
494
495	if (device_can_wakeup(dev))
496		return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3);
497
498	return -EBUSY;
499}
500
501static int dwc3_pci_runtime_resume(struct device *dev)
502{
503	struct dwc3_pci		*dwc = dev_get_drvdata(dev);
504	int			ret;
505
506	ret = dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0);
507	if (ret)
508		return ret;
509
510	queue_work(pm_wq, &dwc->wakeup_work);
511
512	return 0;
513}
514#endif /* CONFIG_PM */
515
516#ifdef CONFIG_PM_SLEEP
517static int dwc3_pci_suspend(struct device *dev)
518{
519	struct dwc3_pci		*dwc = dev_get_drvdata(dev);
520
521	return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3);
522}
523
524static int dwc3_pci_resume(struct device *dev)
525{
526	struct dwc3_pci		*dwc = dev_get_drvdata(dev);
527
528	return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0);
529}
530#endif /* CONFIG_PM_SLEEP */
531
532static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
533	SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
534	SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_runtime_resume,
535		NULL)
536};
537
538static struct pci_driver dwc3_pci_driver = {
539	.name		= "dwc3-pci",
540	.id_table	= dwc3_pci_id_table,
541	.probe		= dwc3_pci_probe,
542	.remove		= dwc3_pci_remove,
543	.driver		= {
544		.pm	= &dwc3_pci_dev_pm_ops,
545	}
546};
547
548MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
549MODULE_LICENSE("GPL v2");
550MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");
551
552module_pci_driver(dwc3_pci_driver);
~/ Read-only file preview.