]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/pci/pci_host_generic.c
cxgbe(4): Add a sysctl to control the tx credit reclaim mechanism for
[FreeBSD/FreeBSD.git] / sys / dev / pci / pci_host_generic.c
1 /*-
2  * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
3  * Copyright (c) 2014 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * This software was developed by Semihalf under
7  * the sponsorship of the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 /* Generic ECAM PCIe driver */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include "opt_platform.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/rman.h>
43 #include <sys/module.h>
44 #include <sys/bus.h>
45 #include <sys/endian.h>
46
47 #include <dev/pci/pcivar.h>
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcib_private.h>
50 #include <dev/pci/pci_host_generic.h>
51
52 #include <machine/bus.h>
53 #include <machine/intr.h>
54
55 #include "pcib_if.h"
56
57 /* Assembling ECAM Configuration Address */
58 #define PCIE_BUS_SHIFT          20
59 #define PCIE_SLOT_SHIFT         15
60 #define PCIE_FUNC_SHIFT         12
61 #define PCIE_BUS_MASK           0xFF
62 #define PCIE_SLOT_MASK          0x1F
63 #define PCIE_FUNC_MASK          0x07
64 #define PCIE_REG_MASK           0xFFF
65
66 #define PCIE_ADDR_OFFSET(bus, slot, func, reg)                  \
67         ((((bus) & PCIE_BUS_MASK) << PCIE_BUS_SHIFT)    |       \
68         (((slot) & PCIE_SLOT_MASK) << PCIE_SLOT_SHIFT)  |       \
69         (((func) & PCIE_FUNC_MASK) << PCIE_FUNC_SHIFT)  |       \
70         ((reg) & PCIE_REG_MASK))
71
72 typedef void (*pci_host_generic_quirk_function)(device_t);
73
74 struct pci_host_generic_quirk_entry {
75         int impl;
76         int part;
77         int var;
78         int rev;
79         pci_host_generic_quirk_function func;
80 };
81
82 struct pci_host_generic_block_entry {
83         int impl;
84         int part;
85         int var;
86         int rev;
87         int bus;
88         int slot;
89 };
90
91 /* Forward prototypes */
92
93 static uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
94     u_int func, u_int reg, int bytes);
95 static void generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
96     u_int func, u_int reg, uint32_t val, int bytes);
97 static int generic_pcie_maxslots(device_t dev);
98 static int generic_pcie_read_ivar(device_t dev, device_t child, int index,
99     uintptr_t *result);
100 static int generic_pcie_write_ivar(device_t dev, device_t child, int index,
101     uintptr_t value);
102
103 #if defined(__aarch64__)
104 static void pci_host_generic_apply_quirks(device_t);
105 static void thunderx2_ahci_bar_quirk(device_t);
106
107 struct pci_host_generic_quirk_entry pci_host_generic_quirks[] =
108 {
109         {CPU_IMPL_CAVIUM, CPU_PART_THUNDERX2, 0, 0, thunderx2_ahci_bar_quirk},
110         {0, 0, 0, 0, NULL}
111 };
112
113 struct pci_host_generic_block_entry pci_host_generic_blocked[] =
114 {
115         /* ThunderX2 AHCI on second socket */
116         {CPU_IMPL_CAVIUM, CPU_PART_THUNDERX2, 0, 0, 0x80, 0x10},
117         {0, 0, 0, 0, 0, 0}
118 };
119 #endif
120
121 int
122 pci_host_generic_core_attach(device_t dev)
123 {
124         struct generic_pcie_core_softc *sc;
125         int error;
126         int rid;
127
128         sc = device_get_softc(dev);
129         sc->dev = dev;
130
131         /* Create the parent DMA tag to pass down the coherent flag */
132         error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
133             1, 0,                               /* alignment, bounds */
134             BUS_SPACE_MAXADDR,                  /* lowaddr */
135             BUS_SPACE_MAXADDR,                  /* highaddr */
136             NULL, NULL,                         /* filter, filterarg */
137             BUS_SPACE_MAXSIZE,                  /* maxsize */
138             BUS_SPACE_UNRESTRICTED,             /* nsegments */
139             BUS_SPACE_MAXSIZE,                  /* maxsegsize */
140             sc->coherent ? BUS_DMA_COHERENT : 0, /* flags */
141             NULL, NULL,                         /* lockfunc, lockarg */
142             &sc->dmat);
143         if (error != 0)
144                 return (error);
145
146         rid = 0;
147         sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE | RF_SHAREABLE);
148         if (sc->res == NULL) {
149                 device_printf(dev, "could not map memory.\n");
150                 return (ENXIO);
151         }
152
153         sc->bst = rman_get_bustag(sc->res);
154         sc->bsh = rman_get_bushandle(sc->res);
155
156         sc->mem_rman.rm_type = RMAN_ARRAY;
157         sc->mem_rman.rm_descr = "PCIe Memory";
158         sc->io_rman.rm_type = RMAN_ARRAY;
159         sc->io_rman.rm_descr = "PCIe IO window";
160
161         /* Initialize rman and allocate memory regions */
162         error = rman_init(&sc->mem_rman);
163         if (error) {
164                 device_printf(dev, "rman_init() failed. error = %d\n", error);
165                 return (error);
166         }
167
168         error = rman_init(&sc->io_rman);
169         if (error) {
170                 device_printf(dev, "rman_init() failed. error = %d\n", error);
171                 return (error);
172         }
173
174 #if defined(__aarch64__)
175         pci_host_generic_apply_quirks(dev);
176 #endif
177
178         return (0);
179 }
180
181 #if defined(__aarch64__)
182 static void
183 pci_host_generic_apply_quirks(device_t dev)
184 {
185         struct pci_host_generic_quirk_entry *quirk;
186
187         quirk = pci_host_generic_quirks;
188         while (1) {
189                 if (quirk->impl == 0)
190                         break;
191
192                 if (CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK,
193                     quirk->impl, quirk->part, quirk->var, quirk->rev) &&
194                     quirk->func != NULL)
195                         quirk->func(dev);
196
197                 quirk++;
198         }
199 }
200 #endif
201
202 static uint32_t
203 generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
204     u_int func, u_int reg, int bytes)
205 {
206         struct generic_pcie_core_softc *sc;
207         bus_space_handle_t h;
208         bus_space_tag_t t;
209         uint64_t offset;
210         uint32_t data;
211 #if defined(__aarch64__)
212         struct pci_host_generic_block_entry *block;
213 #endif
214
215         if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
216             (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
217                 return (~0U);
218
219 #if defined(__aarch64__)
220         block = pci_host_generic_blocked;
221         while (1) {
222                 if (block->impl == 0)
223                         break;
224
225                 if (CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK,
226                     block->impl, block->part, block->var, block->rev) &&
227                     block->bus == bus && block->slot == slot)
228                         return (~0);
229
230                 block++;
231         }
232 #endif
233
234         sc = device_get_softc(dev);
235
236         offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
237         t = sc->bst;
238         h = sc->bsh;
239
240         switch (bytes) {
241         case 1:
242                 data = bus_space_read_1(t, h, offset);
243                 break;
244         case 2:
245                 data = le16toh(bus_space_read_2(t, h, offset));
246                 break;
247         case 4:
248                 data = le32toh(bus_space_read_4(t, h, offset));
249                 break;
250         default:
251                 return (~0U);
252         }
253
254         return (data);
255 }
256
257 static void
258 generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
259     u_int func, u_int reg, uint32_t val, int bytes)
260 {
261         struct generic_pcie_core_softc *sc;
262         bus_space_handle_t h;
263         bus_space_tag_t t;
264         uint64_t offset;
265
266         if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
267             (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
268                 return;
269
270         sc = device_get_softc(dev);
271
272         offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
273
274         t = sc->bst;
275         h = sc->bsh;
276
277         switch (bytes) {
278         case 1:
279                 bus_space_write_1(t, h, offset, val);
280                 break;
281         case 2:
282                 bus_space_write_2(t, h, offset, htole16(val));
283                 break;
284         case 4:
285                 bus_space_write_4(t, h, offset, htole32(val));
286                 break;
287         default:
288                 return;
289         }
290 }
291
292 static int
293 generic_pcie_maxslots(device_t dev)
294 {
295
296         return (31); /* max slots per bus acc. to standard */
297 }
298
299 static int
300 generic_pcie_read_ivar(device_t dev, device_t child, int index,
301     uintptr_t *result)
302 {
303         struct generic_pcie_core_softc *sc;
304         int secondary_bus;
305
306         sc = device_get_softc(dev);
307
308         if (index == PCIB_IVAR_BUS) {
309                 /* this pcib adds only pci bus 0 as child */
310                 secondary_bus = 0;
311                 *result = secondary_bus;
312                 return (0);
313
314         }
315
316         if (index == PCIB_IVAR_DOMAIN) {
317                 *result = sc->ecam;
318                 return (0);
319         }
320
321         if (bootverbose)
322                 device_printf(dev, "ERROR: Unknown index %d.\n", index);
323         return (ENOENT);
324 }
325
326 static int
327 generic_pcie_write_ivar(device_t dev, device_t child, int index,
328     uintptr_t value)
329 {
330
331         return (ENOENT);
332 }
333
334 static struct rman *
335 generic_pcie_rman(struct generic_pcie_core_softc *sc, int type)
336 {
337
338         switch (type) {
339         case SYS_RES_IOPORT:
340                 return (&sc->io_rman);
341         case SYS_RES_MEMORY:
342                 return (&sc->mem_rman);
343         default:
344                 break;
345         }
346
347         return (NULL);
348 }
349
350 int
351 pci_host_generic_core_release_resource(device_t dev, device_t child, int type,
352     int rid, struct resource *res)
353 {
354         struct generic_pcie_core_softc *sc;
355         struct rman *rm;
356
357         sc = device_get_softc(dev);
358
359 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
360         if (type == PCI_RES_BUS) {
361                 return (pci_domain_release_bus(sc->ecam, child, rid, res));
362         }
363 #endif
364
365         rm = generic_pcie_rman(sc, type);
366         if (rm != NULL) {
367                 KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
368                 rman_release_resource(res);
369         }
370
371         return (bus_generic_release_resource(dev, child, type, rid, res));
372 }
373
374 struct resource *
375 pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
376     int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
377 {
378         struct generic_pcie_core_softc *sc;
379         struct resource *res;
380         struct rman *rm;
381
382         sc = device_get_softc(dev);
383
384 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
385         if (type == PCI_RES_BUS) {
386                 return (pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
387                     count, flags));
388         }
389 #endif
390
391         rm = generic_pcie_rman(sc, type);
392         if (rm == NULL)
393                 return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
394                     type, rid, start, end, count, flags));
395
396         if (bootverbose) {
397                 device_printf(dev,
398                     "rman_reserve_resource: start=%#jx, end=%#jx, count=%#jx\n",
399                     start, end, count);
400         }
401
402         res = rman_reserve_resource(rm, start, end, count, flags, child);
403         if (res == NULL)
404                 goto fail;
405
406         rman_set_rid(res, *rid);
407
408         if (flags & RF_ACTIVE)
409                 if (bus_activate_resource(child, type, *rid, res)) {
410                         rman_release_resource(res);
411                         goto fail;
412                 }
413
414         return (res);
415
416 fail:
417         device_printf(dev, "%s FAIL: type=%d, rid=%d, "
418             "start=%016jx, end=%016jx, count=%016jx, flags=%x\n",
419             __func__, type, *rid, start, end, count, flags);
420
421         return (NULL);
422 }
423
424 static int
425 generic_pcie_adjust_resource(device_t dev, device_t child, int type,
426     struct resource *res, rman_res_t start, rman_res_t end)
427 {
428         struct generic_pcie_core_softc *sc;
429         struct rman *rm;
430
431         sc = device_get_softc(dev);
432 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
433         if (type == PCI_RES_BUS)
434                 return (pci_domain_adjust_bus(sc->ecam, child, res, start,
435                     end));
436 #endif
437
438         rm = generic_pcie_rman(sc, type);
439         if (rm != NULL)
440                 return (rman_adjust_resource(res, start, end));
441         return (bus_generic_adjust_resource(dev, child, type, res, start, end));
442 }
443
444 static bus_dma_tag_t
445 generic_pcie_get_dma_tag(device_t dev, device_t child)
446 {
447         struct generic_pcie_core_softc *sc;
448
449         sc = device_get_softc(dev);
450         return (sc->dmat);
451 }
452
453 static device_method_t generic_pcie_methods[] = {
454         DEVMETHOD(device_attach,                pci_host_generic_core_attach),
455         DEVMETHOD(bus_read_ivar,                generic_pcie_read_ivar),
456         DEVMETHOD(bus_write_ivar,               generic_pcie_write_ivar),
457         DEVMETHOD(bus_alloc_resource,           pci_host_generic_core_alloc_resource),
458         DEVMETHOD(bus_adjust_resource,          generic_pcie_adjust_resource),
459         DEVMETHOD(bus_release_resource,         pci_host_generic_core_release_resource),
460         DEVMETHOD(bus_setup_intr,               bus_generic_setup_intr),
461         DEVMETHOD(bus_teardown_intr,            bus_generic_teardown_intr),
462
463         DEVMETHOD(bus_get_dma_tag,              generic_pcie_get_dma_tag),
464
465         /* pcib interface */
466         DEVMETHOD(pcib_maxslots,                generic_pcie_maxslots),
467         DEVMETHOD(pcib_read_config,             generic_pcie_read_config),
468         DEVMETHOD(pcib_write_config,            generic_pcie_write_config),
469
470         DEVMETHOD_END
471 };
472
473 DEFINE_CLASS_0(pcib, generic_pcie_core_driver,
474     generic_pcie_methods, sizeof(struct generic_pcie_core_softc));
475
476 #if defined(__aarch64__)
477 static void thunderx2_ahci_bar_quirk(device_t dev)
478 {
479
480         /*
481          * XXX:
482          * On ThunderX2, AHCI BAR2 address is wrong. It needs to precisely
483          * match the one described in datasheet. Fixup it unconditionally.
484          */
485         if (device_get_unit(dev) == 0) {
486                 device_printf(dev, "running AHCI BAR fixup\n");
487                 PCIB_WRITE_CONFIG(dev, 0, 16, 0, 0x18, 0x01440000, 4);
488                 PCIB_WRITE_CONFIG(dev, 0, 16, 0, 0x1c, 0x40, 4);
489                 PCIB_WRITE_CONFIG(dev, 0, 16, 1, 0x18, 0x01450000, 4);
490                 PCIB_WRITE_CONFIG(dev, 0, 16, 1, 0x1c, 0x40, 4);
491         }
492 }
493 #endif