dwc3-pci.c 7.3 KB
Newer Older
1 2 3 4 5 6 7 8
/**
 * dwc3-pci.c - PCI Specific glue layer
 *
 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
 *
 * Authors: Felipe Balbi <balbi@ti.com>,
 *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
 *
F
Felipe Balbi 已提交
9 10 11
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2  of
 * the License as published by the Free Software Foundation.
12
 *
F
Felipe Balbi 已提交
13 14 15 16
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
17 18 19
 */

#include <linux/kernel.h>
20
#include <linux/module.h>
21 22
#include <linux/slab.h>
#include <linux/pci.h>
23
#include <linux/pm_runtime.h>
24
#include <linux/platform_device.h>
25 26
#include <linux/gpio/consumer.h>
#include <linux/acpi.h>
27

28 29
#include "platform_data.h"

J
John Youn 已提交
30 31 32 33 34 35 36 37
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3		0xabcd
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI	0xabce
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31	0xabcf
#define PCI_DEVICE_ID_INTEL_BYT			0x0f37
#define PCI_DEVICE_ID_INTEL_MRFLD		0x119e
#define PCI_DEVICE_ID_INTEL_BSW			0x22b7
#define PCI_DEVICE_ID_INTEL_SPTLP		0x9d30
#define PCI_DEVICE_ID_INTEL_SPTH		0xa130
38
#define PCI_DEVICE_ID_INTEL_BXT			0x0aaa
39
#define PCI_DEVICE_ID_INTEL_BXT_M		0x1aaa
40
#define PCI_DEVICE_ID_INTEL_APL			0x5aaa
41

42 43 44 45 46 47 48 49 50
static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
static const struct acpi_gpio_params cs_gpios = { 1, 0, false };

static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = {
	{ "reset-gpios", &reset_gpios, 1 },
	{ "cs-gpios", &cs_gpios, 1 },
	{ },
};

51
static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3)
H
Heikki Krogerus 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
{
	if (pdev->vendor == PCI_VENDOR_ID_AMD &&
	    pdev->device == PCI_DEVICE_ID_AMD_NL_USB) {
		struct dwc3_platform_data pdata;

		memset(&pdata, 0, sizeof(pdata));

		pdata.has_lpm_erratum = true;
		pdata.lpm_nyet_threshold = 0xf;

		pdata.u2exit_lfps_quirk = true;
		pdata.u2ss_inp3_quirk = true;
		pdata.req_p1p2p3_quirk = true;
		pdata.del_p1p2p3_quirk = true;
		pdata.del_phy_power_chg_quirk = true;
		pdata.lfps_filter_quirk = true;
		pdata.rx_detect_poll_quirk = true;

		pdata.tx_de_emphasis_quirk = true;
		pdata.tx_de_emphasis = 1;

		/*
		 * FIXME these quirks should be removed when AMD NL
		 * taps out
		 */
		pdata.disable_scramble_quirk = true;
		pdata.dis_u3_susphy_quirk = true;
		pdata.dis_u2_susphy_quirk = true;

81
		return platform_device_add_data(dwc3, &pdata, sizeof(pdata));
H
Heikki Krogerus 已提交
82 83
	}

84 85 86 87 88 89 90
	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
	    pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
		struct gpio_desc *gpio;

		acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
					  acpi_dwc3_byt_gpios);

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
		/*
		 * These GPIOs will turn on the USB2 PHY. Note that we have to
		 * put the gpio descriptors again here because the phy driver
		 * might want to grab them, too.
		 */
		gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
		if (IS_ERR(gpio))
			return PTR_ERR(gpio);

		gpiod_set_value_cansleep(gpio, 1);
		gpiod_put(gpio);

		gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
		if (IS_ERR(gpio))
			return PTR_ERR(gpio);
106

107
		if (gpio) {
108 109 110 111 112 113
			gpiod_set_value_cansleep(gpio, 1);
			gpiod_put(gpio);
			usleep_range(10000, 11000);
		}
	}

114 115 116 117 118 119 120 121 122 123
	if (pdev->vendor == PCI_VENDOR_ID_SYNOPSYS &&
	    (pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 ||
	     pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI ||
	     pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31)) {

		struct dwc3_platform_data pdata;

		memset(&pdata, 0, sizeof(pdata));
		pdata.usb3_lpm_capable = true;
		pdata.has_lpm_erratum = true;
124
		pdata.dis_enblslpm_quirk = true;
125

126
		return platform_device_add_data(dwc3, &pdata, sizeof(pdata));
127 128
	}

H
Heikki Krogerus 已提交
129 130
	return 0;
}
131

B
Bill Pemberton 已提交
132
static int dwc3_pci_probe(struct pci_dev *pci,
133 134 135 136
		const struct pci_device_id *id)
{
	struct resource		res[2];
	struct platform_device	*dwc3;
137
	int			ret;
C
Chanho Park 已提交
138
	struct device		*dev = &pci->dev;
139

140
	ret = pcim_enable_device(pci);
141
	if (ret) {
C
Chanho Park 已提交
142 143
		dev_err(dev, "failed to enable pci device\n");
		return -ENODEV;
144 145 146 147
	}

	pci_set_master(pci);

148
	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
149
	if (!dwc3) {
C
Chanho Park 已提交
150
		dev_err(dev, "couldn't allocate dwc3 device\n");
151
		return -ENOMEM;
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
	}

	memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));

	res[0].start	= pci_resource_start(pci, 0);
	res[0].end	= pci_resource_end(pci, 0);
	res[0].name	= "dwc_usb3";
	res[0].flags	= IORESOURCE_MEM;

	res[1].start	= pci->irq;
	res[1].name	= "dwc_usb3";
	res[1].flags	= IORESOURCE_IRQ;

	ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
	if (ret) {
C
Chanho Park 已提交
167
		dev_err(dev, "couldn't add resources to dwc3 device\n");
168
		return ret;
169 170
	}

C
Chanho Park 已提交
171
	dwc3->dev.parent = dev;
172
	ACPI_COMPANION_SET(&dwc3->dev, ACPI_COMPANION(dev));
173

174
	ret = dwc3_pci_quirks(pci, dwc3);
175 176 177
	if (ret)
		goto err;

178 179
	ret = platform_device_add(dwc3);
	if (ret) {
C
Chanho Park 已提交
180
		dev_err(dev, "failed to register dwc3 device\n");
H
Heikki Krogerus 已提交
181
		goto err;
182 183
	}

184 185
	device_init_wakeup(dev, true);
	device_set_run_wake(dev, true);
186
	pci_set_drvdata(pci, dwc3);
187 188
	pm_runtime_put(dev);

189
	return 0;
H
Heikki Krogerus 已提交
190
err:
191 192 193 194
	platform_device_put(dwc3);
	return ret;
}

B
Bill Pemberton 已提交
195
static void dwc3_pci_remove(struct pci_dev *pci)
196
{
197 198
	device_init_wakeup(&pci->dev, false);
	pm_runtime_get(&pci->dev);
199
	acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev));
H
Heikki Krogerus 已提交
200
	platform_device_unregister(pci_get_drvdata(pci));
201 202
}

203
static const struct pci_device_id dwc3_pci_id_table[] = {
204 205 206 207
	{
		PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
				PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
	},
208 209 210 211
	{
		PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
				PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI),
	},
212 213 214 215
	{
		PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
				PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31),
	},
216
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
217
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
218
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
219 220
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
221
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
222
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_M), },
223
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
224
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
225 226 227 228
	{  }	/* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
#ifdef CONFIG_PM
static int dwc3_pci_runtime_suspend(struct device *dev)
{
	if (device_run_wake(dev))
		return 0;

	return -EBUSY;
}

static int dwc3_pci_pm_dummy(struct device *dev)
{
	/*
	 * There's nothing to do here. No, seriously. Everything is either taken
	 * care either by PCI subsystem or dwc3/core.c, so we have nothing
	 * missing here.
	 *
	 * So you'd think we didn't need this at all, but PCI subsystem will
	 * bail out if we don't have a valid callback :-s
	 */
	return 0;
}
#endif /* CONFIG_PM */

static struct dev_pm_ops dwc3_pci_dev_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_pm_dummy, dwc3_pci_pm_dummy)
	SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_pm_dummy,
		NULL)
};

258
static struct pci_driver dwc3_pci_driver = {
259
	.name		= "dwc3-pci",
260 261
	.id_table	= dwc3_pci_id_table,
	.probe		= dwc3_pci_probe,
B
Bill Pemberton 已提交
262
	.remove		= dwc3_pci_remove,
263 264 265
	.driver		= {
		.pm	= &dwc3_pci_dev_pm_ops,
	}
266 267 268
};

MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
F
Felipe Balbi 已提交
269
MODULE_LICENSE("GPL v2");
270 271
MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");

G
Greg Kroah-Hartman 已提交
272
module_pci_driver(dwc3_pci_driver);