wil6210: boot loader
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / ath / wil6210 / pcie_bus.c
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, false);
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");