1 /*
2  * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <linux/module.h>
18 #include <linux/pci.h>
19 #include <linux/moduleparam.h>
20 #include <linux/interrupt.h>
21 
22 #include "wil6210.h"
23 
24 static int use_msi = 1;
25 module_param(use_msi, int, S_IRUGO);
26 MODULE_PARM_DESC(use_msi,
27 		 " Use MSI interrupt: "
28 		 "0 - don't, 1 - (default) - single, or 3");
29 
30 static bool debug_fw; /* = false; */
31 module_param(debug_fw, bool, S_IRUGO);
32 MODULE_PARM_DESC(debug_fw, " load driver if FW not ready. For FW debug");
33 
34 static
35 void wil_set_capabilities(struct wil6210_priv *wil)
36 {
37 	u32 rev_id = ioread32(wil->csr + HOSTADDR(RGF_USER_JTAG_DEV_ID));
38 
39 	bitmap_zero(wil->hw_capabilities, hw_capability_last);
40 
41 	switch (rev_id) {
42 	case JTAG_DEV_ID_MARLON_B0:
43 		wil->hw_name = "Marlon B0";
44 		wil->hw_version = HW_VER_MARLON_B0;
45 		break;
46 	case JTAG_DEV_ID_SPARROW_A0:
47 		wil->hw_name = "Sparrow A0";
48 		wil->hw_version = HW_VER_SPARROW_A0;
49 		break;
50 	case JTAG_DEV_ID_SPARROW_A1:
51 		wil->hw_name = "Sparrow A1";
52 		wil->hw_version = HW_VER_SPARROW_A1;
53 		break;
54 	case JTAG_DEV_ID_SPARROW_B0:
55 		wil->hw_name = "Sparrow B0";
56 		wil->hw_version = HW_VER_SPARROW_B0;
57 		break;
58 	default:
59 		wil_err(wil, "Unknown board hardware 0x%08x\n", rev_id);
60 		wil->hw_name = "Unknown";
61 		wil->hw_version = HW_VER_UNKNOWN;
62 	}
63 
64 	wil_info(wil, "Board hardware is %s\n", wil->hw_name);
65 
66 	if (wil->hw_version >= HW_VER_SPARROW_A0)
67 		set_bit(hw_capability_reset_v2, wil->hw_capabilities);
68 
69 	if (wil->hw_version >= HW_VER_SPARROW_B0)
70 		set_bit(hw_capability_advanced_itr_moderation,
71 			wil->hw_capabilities);
72 }
73 
74 void wil_disable_irq(struct wil6210_priv *wil)
75 {
76 	int irq = wil->pdev->irq;
77 
78 	disable_irq(irq);
79 	if (wil->n_msi == 3) {
80 		disable_irq(irq + 1);
81 		disable_irq(irq + 2);
82 	}
83 }
84 
85 void wil_enable_irq(struct wil6210_priv *wil)
86 {
87 	int irq = wil->pdev->irq;
88 
89 	enable_irq(irq);
90 	if (wil->n_msi == 3) {
91 		enable_irq(irq + 1);
92 		enable_irq(irq + 2);
93 	}
94 }
95 
96 /* Bus ops */
97 static int wil_if_pcie_enable(struct wil6210_priv *wil)
98 {
99 	struct pci_dev *pdev = wil->pdev;
100 	int rc;
101 	/* on platforms with buggy ACPI, pdev->msi_enabled may be set to
102 	 * allow pci_enable_device to work. This indicates INTx was not routed
103 	 * and only MSI should be used
104 	 */
105 	int msi_only = pdev->msi_enabled;
106 
107 	wil_dbg_misc(wil, "%s()\n", __func__);
108 
109 	pdev->msi_enabled = 0;
110 
111 	pci_set_master(pdev);
112 
113 	/*
114 	 * how many MSI interrupts to request?
115 	 */
116 	switch (use_msi) {
117 	case 3:
118 	case 1:
119 		wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi);
120 		break;
121 	case 0:
122 		wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n");
123 		break;
124 	default:
125 		wil_err(wil, "Invalid use_msi=%d, default to 1\n", use_msi);
126 		use_msi = 1;
127 	}
128 
129 	if (use_msi == 3 && pci_enable_msi_range(pdev, 3, 3) < 0) {
130 		wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
131 		use_msi = 1;
132 	}
133 
134 	if (use_msi == 1 && pci_enable_msi(pdev)) {
135 		wil_err(wil, "pci_enable_msi failed, use INTx\n");
136 		use_msi = 0;
137 	}
138 
139 	wil->n_msi = use_msi;
140 
141 	if ((wil->n_msi == 0) && msi_only) {
142 		wil_err(wil, "Interrupt pin not routed, unable to use INTx\n");
143 		rc = -ENODEV;
144 		goto stop_master;
145 	}
146 
147 	rc = wil6210_init_irq(wil, pdev->irq);
148 	if (rc)
149 		goto stop_master;
150 
151 	/* need reset here to obtain MAC */
152 	mutex_lock(&wil->mutex);
153 	rc = wil_reset(wil);
154 	mutex_unlock(&wil->mutex);
155 	if (debug_fw)
156 		rc = 0;
157 	if (rc)
158 		goto release_irq;
159 
160 	return 0;
161 
162  release_irq:
163 	wil6210_fini_irq(wil, pdev->irq);
164 	/* safe to call if no MSI */
165 	pci_disable_msi(pdev);
166  stop_master:
167 	pci_clear_master(pdev);
168 	return rc;
169 }
170 
171 static int wil_if_pcie_disable(struct wil6210_priv *wil)
172 {
173 	struct pci_dev *pdev = wil->pdev;
174 
175 	wil_dbg_misc(wil, "%s()\n", __func__);
176 
177 	pci_clear_master(pdev);
178 	/* disable and release IRQ */
179 	wil6210_fini_irq(wil, pdev->irq);
180 	/* safe to call if no MSI */
181 	pci_disable_msi(pdev);
182 	/* TODO: disable HW */
183 
184 	return 0;
185 }
186 
187 static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
188 {
189 	struct wil6210_priv *wil;
190 	struct device *dev = &pdev->dev;
191 	void __iomem *csr;
192 	int rc;
193 
194 	/* check HW */
195 	dev_info(&pdev->dev, WIL_NAME
196 		 " device found [%04x:%04x] (rev %x)\n",
197 		 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
198 
199 	if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
200 		dev_err(&pdev->dev, "Not " WIL_NAME "? "
201 			"BAR0 size is %lu while expecting %lu\n",
202 			(ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE);
203 		return -ENODEV;
204 	}
205 
206 	rc = pci_enable_device(pdev);
207 	if (rc) {
208 		dev_err(&pdev->dev,
209 			"pci_enable_device failed, retry with MSI only\n");
210 		/* Work around for platforms that can't allocate IRQ:
211 		 * retry with MSI only
212 		 */
213 		pdev->msi_enabled = 1;
214 		rc = pci_enable_device(pdev);
215 	}
216 	if (rc)
217 		return -ENODEV;
218 	/* rollback to err_disable_pdev */
219 
220 	rc = pci_request_region(pdev, 0, WIL_NAME);
221 	if (rc) {
222 		dev_err(&pdev->dev, "pci_request_region failed\n");
223 		goto err_disable_pdev;
224 	}
225 	/* rollback to err_release_reg */
226 
227 	csr = pci_ioremap_bar(pdev, 0);
228 	if (!csr) {
229 		dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
230 		rc = -ENODEV;
231 		goto err_release_reg;
232 	}
233 	/* rollback to err_iounmap */
234 	dev_info(&pdev->dev, "CSR at %pR -> 0x%p\n", &pdev->resource[0], csr);
235 
236 	wil = wil_if_alloc(dev, csr);
237 	if (IS_ERR(wil)) {
238 		rc = (int)PTR_ERR(wil);
239 		dev_err(dev, "wil_if_alloc failed: %d\n", rc);
240 		goto err_iounmap;
241 	}
242 	/* rollback to if_free */
243 
244 	pci_set_drvdata(pdev, wil);
245 	wil->pdev = pdev;
246 	wil_set_capabilities(wil);
247 	wil6210_clear_irq(wil);
248 
249 	wil->platform_handle =
250 			wil_platform_init(&pdev->dev, &wil->platform_ops);
251 
252 	/* FW should raise IRQ when ready */
253 	rc = wil_if_pcie_enable(wil);
254 	if (rc) {
255 		wil_err(wil, "Enable device failed\n");
256 		goto if_free;
257 	}
258 	/* rollback to bus_disable */
259 
260 	rc = wil_if_add(wil);
261 	if (rc) {
262 		wil_err(wil, "wil_if_add failed: %d\n", rc);
263 		goto bus_disable;
264 	}
265 
266 	wil6210_debugfs_init(wil);
267 
268 	/* check FW is alive */
269 	wmi_echo(wil);
270 
271 	return 0;
272 
273  bus_disable:
274 	wil_if_pcie_disable(wil);
275  if_free:
276 	if (wil->platform_ops.uninit)
277 		wil->platform_ops.uninit(wil->platform_handle);
278 	wil_if_free(wil);
279  err_iounmap:
280 	pci_iounmap(pdev, csr);
281  err_release_reg:
282 	pci_release_region(pdev, 0);
283  err_disable_pdev:
284 	pci_disable_device(pdev);
285 
286 	return rc;
287 }
288 
289 static void wil_pcie_remove(struct pci_dev *pdev)
290 {
291 	struct wil6210_priv *wil = pci_get_drvdata(pdev);
292 	void __iomem *csr = wil->csr;
293 
294 	wil_dbg_misc(wil, "%s()\n", __func__);
295 
296 	wil6210_debugfs_remove(wil);
297 	wil_if_remove(wil);
298 	wil_if_pcie_disable(wil);
299 	if (wil->platform_ops.uninit)
300 		wil->platform_ops.uninit(wil->platform_handle);
301 	wil_if_free(wil);
302 	pci_iounmap(pdev, csr);
303 	pci_release_region(pdev, 0);
304 	pci_disable_device(pdev);
305 }
306 
307 static const struct pci_device_id wil6210_pcie_ids[] = {
308 	{ PCI_DEVICE(0x1ae9, 0x0301) },
309 	{ PCI_DEVICE(0x1ae9, 0x0310) },
310 	{ PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */
311 	{ /* end: all zeroes */	},
312 };
313 MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
314 
315 static struct pci_driver wil6210_driver = {
316 	.probe		= wil_pcie_probe,
317 	.remove		= wil_pcie_remove,
318 	.id_table	= wil6210_pcie_ids,
319 	.name		= WIL_NAME,
320 };
321 
322 module_pci_driver(wil6210_driver);
323 
324 MODULE_LICENSE("Dual BSD/GPL");
325 MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>");
326 MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card");
327