1 /*-
2 * Copyright (c) 2015 The FreeBSD Foundation
3 *
4 * This software was developed by Semihalf under
5 * the sponsorship of the FreeBSD Foundation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 /* PCIe external MAC root complex driver (PEM) for Cavium Thunder SOC */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "opt_platform.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/bus.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/rman.h>
43 #include <sys/endian.h>
44
45 #ifdef FDT
46 #include <dev/ofw/openfirm.h>
47 #include <dev/ofw/ofw_bus.h>
48 #include <dev/ofw/ofw_bus_subr.h>
49 #include <dev/ofw/ofw_pci.h>
50 #endif
51
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/pcireg.h>
54 #include <dev/pci/pci_host_generic.h>
55 #include <dev/pci/pcib_private.h>
56
57 #include <machine/bus.h>
58 #include <machine/resource.h>
59 #include <machine/smp.h>
60 #include <machine/intr.h>
61
62 #include <arm64/cavium/thunder_pcie_common.h>
63 #include <arm64/cavium/thunder_pcie_pem.h>
64 #include "pcib_if.h"
65
66 #define THUNDER_PEM_DEVICE_ID 0xa020
67 #define THUNDER_PEM_VENDOR_ID 0x177d
68
69 /* ThunderX specific defines */
70 #define THUNDER_PEMn_REG_BASE(unit) (0x87e0c0000000UL | ((unit) << 24))
71 #define PCIERC_CFG002 0x08
72 #define PCIERC_CFG006 0x18
73 #define PCIERC_CFG032 0x80
74 #define PCIERC_CFG006_SEC_BUS(reg) (((reg) >> 8) & 0xFF)
75 #define PEM_CFG_RD_REG_ALIGN(reg) ((reg) & ~0x3)
76 #define PEM_CFG_RD_REG_DATA(val) (((val) >> 32) & 0xFFFFFFFF)
77 #define PEM_CFG_RD 0x30
78 #define PEM_CFG_LINK_MASK 0x3
79 #define PEM_CFG_LINK_RDY 0x3
80 #define PEM_CFG_SLIX_TO_REG(slix) ((slix) << 4)
81 #define SBNUM_OFFSET 0x8
82 #define SBNUM_MASK 0xFF
83 #define PEM_ON_REG 0x420
84 #define PEM_CTL_STATUS 0x0
85 #define PEM_LINK_ENABLE (1 << 4)
86 #define PEM_LINK_DLLA (1 << 29)
87 #define PEM_LINK_LT (1 << 27)
88 #define PEM_BUS_SHIFT (24)
89 #define PEM_SLOT_SHIFT (19)
90 #define PEM_FUNC_SHIFT (16)
91 #define SLIX_S2M_REGX_ACC 0x874001000000UL
92 #define SLIX_S2M_REGX_ACC_SIZE 0x1000
93 #define SLIX_S2M_REGX_ACC_SPACING 0x001000000000UL
94 #define SLI_BASE 0x880000000000UL
95 #define SLI_WINDOW_SPACING 0x004000000000UL
96 #define SLI_PCI_OFFSET 0x001000000000UL
97 #define SLI_NODE_SHIFT (44)
98 #define SLI_NODE_MASK (3)
99 #define SLI_GROUP_SHIFT (40)
100 #define SLI_ID_SHIFT (24)
101 #define SLI_ID_MASK (7)
102 #define SLI_PEMS_PER_GROUP (3)
103 #define SLI_GROUPS_PER_NODE (2)
104 #define SLI_PEMS_PER_NODE (SLI_PEMS_PER_GROUP * SLI_GROUPS_PER_NODE)
105 #define SLI_ACC_REG_CNT (256)
106
107 /*
108 * Each PEM device creates its own bus with
109 * own address translation, so we can adjust bus addresses
110 * as we want. To support 32-bit cards let's assume
111 * PCI window assignment looks as following:
112 *
113 * 0x00000000 - 0x000FFFFF IO
114 * 0x00100000 - 0xFFFFFFFF Memory
115 */
116 #define PCI_IO_BASE 0x00000000UL
117 #define PCI_IO_SIZE 0x00100000UL
118 #define PCI_MEMORY_BASE PCI_IO_SIZE
119 #define PCI_MEMORY_SIZE 0xFFF00000UL
120
121 #define RID_PEM_SPACE 1
122
123 static int thunder_pem_activate_resource(device_t, device_t, int, int,
124 struct resource *);
125 static int thunder_pem_adjust_resource(device_t, device_t, int,
126 struct resource *, rman_res_t, rman_res_t);
127 static struct resource * thunder_pem_alloc_resource(device_t, device_t, int,
128 int *, rman_res_t, rman_res_t, rman_res_t, u_int);
129 static int thunder_pem_alloc_msi(device_t, device_t, int, int, int *);
130 static int thunder_pem_release_msi(device_t, device_t, int, int *);
131 static int thunder_pem_alloc_msix(device_t, device_t, int *);
132 static int thunder_pem_release_msix(device_t, device_t, int);
133 static int thunder_pem_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
134 static int thunder_pem_get_id(device_t, device_t, enum pci_id_type,
135 uintptr_t *);
136 static int thunder_pem_attach(device_t);
137 static int thunder_pem_deactivate_resource(device_t, device_t, int, int,
138 struct resource *);
139 static bus_dma_tag_t thunder_pem_get_dma_tag(device_t, device_t);
140 static int thunder_pem_detach(device_t);
141 static uint64_t thunder_pem_config_reg_read(struct thunder_pem_softc *, int);
142 static int thunder_pem_link_init(struct thunder_pem_softc *);
143 static int thunder_pem_maxslots(device_t);
144 static int thunder_pem_probe(device_t);
145 static uint32_t thunder_pem_read_config(device_t, u_int, u_int, u_int, u_int,
146 int);
147 static int thunder_pem_read_ivar(device_t, device_t, int, uintptr_t *);
148 static void thunder_pem_release_all(device_t);
149 static int thunder_pem_release_resource(device_t, device_t, int, int,
150 struct resource *);
151 static struct rman * thunder_pem_rman(struct thunder_pem_softc *, int);
152 static void thunder_pem_slix_s2m_regx_acc_modify(struct thunder_pem_softc *,
153 int, int);
154 static void thunder_pem_write_config(device_t, u_int, u_int, u_int, u_int,
155 uint32_t, int);
156 static int thunder_pem_write_ivar(device_t, device_t, int, uintptr_t);
157
158 /* Global handlers for SLI interface */
159 static bus_space_handle_t sli0_s2m_regx_base = 0;
160 static bus_space_handle_t sli1_s2m_regx_base = 0;
161
162 static device_method_t thunder_pem_methods[] = {
163 /* Device interface */
164 DEVMETHOD(device_probe, thunder_pem_probe),
165 DEVMETHOD(device_attach, thunder_pem_attach),
166 DEVMETHOD(device_detach, thunder_pem_detach),
167
168 /* Bus interface */
169 DEVMETHOD(bus_read_ivar, thunder_pem_read_ivar),
170 DEVMETHOD(bus_write_ivar, thunder_pem_write_ivar),
171 DEVMETHOD(bus_alloc_resource, thunder_pem_alloc_resource),
172 DEVMETHOD(bus_release_resource, thunder_pem_release_resource),
173 DEVMETHOD(bus_adjust_resource, thunder_pem_adjust_resource),
174 DEVMETHOD(bus_activate_resource, thunder_pem_activate_resource),
175 DEVMETHOD(bus_deactivate_resource, thunder_pem_deactivate_resource),
176 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
177 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
178
179 DEVMETHOD(bus_get_dma_tag, thunder_pem_get_dma_tag),
180
181 /* pcib interface */
182 DEVMETHOD(pcib_maxslots, thunder_pem_maxslots),
183 DEVMETHOD(pcib_read_config, thunder_pem_read_config),
184 DEVMETHOD(pcib_write_config, thunder_pem_write_config),
185 DEVMETHOD(pcib_alloc_msix, thunder_pem_alloc_msix),
186 DEVMETHOD(pcib_release_msix, thunder_pem_release_msix),
187 DEVMETHOD(pcib_alloc_msi, thunder_pem_alloc_msi),
188 DEVMETHOD(pcib_release_msi, thunder_pem_release_msi),
189 DEVMETHOD(pcib_map_msi, thunder_pem_map_msi),
190 DEVMETHOD(pcib_get_id, thunder_pem_get_id),
191
192 DEVMETHOD_END
193 };
194
195 DEFINE_CLASS_0(pcib, thunder_pem_driver, thunder_pem_methods,
196 sizeof(struct thunder_pem_softc));
197
198 extern struct bus_space memmap_bus;
199
200 DRIVER_MODULE(thunder_pem, pci, thunder_pem_driver, 0, 0);
201 MODULE_DEPEND(thunder_pem, pci, 1, 1, 1);
202
203 static int
204 thunder_pem_maxslots(device_t dev)
205 {
206
207 #if 0
208 /* max slots per bus acc. to standard */
209 return (PCI_SLOTMAX);
210 #else
211 /*
212 * ARM64TODO Workaround - otherwise an em(4) interface appears to be
213 * present on every PCI function on the bus to which it is connected
214 */
215 return (0);
216 #endif
217 }
218
219 static int
220 thunder_pem_read_ivar(device_t dev, device_t child, int index,
221 uintptr_t *result)
222 {
223 struct thunder_pem_softc *sc;
224 int secondary_bus = 0;
225
226 sc = device_get_softc(dev);
227
228 if (index == PCIB_IVAR_BUS) {
229 secondary_bus = thunder_pem_config_reg_read(sc, PCIERC_CFG006);
230 *result = PCIERC_CFG006_SEC_BUS(secondary_bus);
231 return (0);
232 }
233 if (index == PCIB_IVAR_DOMAIN) {
234 *result = sc->id;
235 return (0);
236 }
237
238 return (ENOENT);
239 }
240
241 static int
242 thunder_pem_write_ivar(device_t dev, device_t child, int index,
243 uintptr_t value)
244 {
245
246 return (ENOENT);
247 }
248
249 static int
250 thunder_pem_activate_resource(device_t dev, device_t child, int type, int rid,
251 struct resource *r)
252 {
253 int err;
254 bus_addr_t paddr;
255 bus_size_t psize;
256 bus_space_handle_t vaddr;
257 struct thunder_pem_softc *sc;
258
259 if ((err = rman_activate_resource(r)) != 0)
260 return (err);
261
262 sc = device_get_softc(dev);
263
264 /*
265 * If this is a memory resource, map it into the kernel.
266 */
267 if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
268 paddr = (bus_addr_t)rman_get_start(r);
269 psize = (bus_size_t)rman_get_size(r);
270
271 paddr = range_addr_pci_to_phys(sc->ranges, paddr);
272
273 err = bus_space_map(&memmap_bus, paddr, psize, 0, &vaddr);
274 if (err != 0) {
275 rman_deactivate_resource(r);
276 return (err);
277 }
278 rman_set_bustag(r, &memmap_bus);
279 rman_set_virtual(r, (void *)vaddr);
280 rman_set_bushandle(r, vaddr);
281 }
282 return (0);
283 }
284
285 /*
286 * This function is an exact copy of nexus_deactivate_resource()
287 * Keep it up-to-date with all changes in nexus. To be removed
288 * once bus-mapping interface is developed.
289 */
290 static int
291 thunder_pem_deactivate_resource(device_t bus, device_t child, int type, int rid,
292 struct resource *r)
293 {
294 bus_size_t psize;
295 bus_space_handle_t vaddr;
296
297 psize = (bus_size_t)rman_get_size(r);
298 vaddr = rman_get_bushandle(r);
299
300 if (vaddr != 0) {
301 bus_space_unmap(&memmap_bus, vaddr, psize);
302 rman_set_virtual(r, NULL);
303 rman_set_bushandle(r, 0);
304 }
305
306 return (rman_deactivate_resource(r));
307 }
308
309 static int
310 thunder_pem_adjust_resource(device_t dev, device_t child, int type,
311 struct resource *res, rman_res_t start, rman_res_t end)
312 {
313 struct thunder_pem_softc *sc;
314 struct rman *rm;
315
316 sc = device_get_softc(dev);
317 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
318 if (type == PCI_RES_BUS)
319 return (pci_domain_adjust_bus(sc->id, child, res, start, end));
320 #endif
321
322 rm = thunder_pem_rman(sc, type);
323 if (rm == NULL)
324 return (bus_generic_adjust_resource(dev, child, type, res,
325 start, end));
326 if (!rman_is_region_manager(res, rm))
327 /*
328 * This means a child device has a memory or I/O
329 * resource not from you which shouldn't happen.
330 */
331 return (EINVAL);
332 return (rman_adjust_resource(res, start, end));
333 }
334
335 static bus_dma_tag_t
336 thunder_pem_get_dma_tag(device_t dev, device_t child)
337 {
338 struct thunder_pem_softc *sc;
339
340 sc = device_get_softc(dev);
341 return (sc->dmat);
342 }
343
344 static int
345 thunder_pem_alloc_msi(device_t pci, device_t child, int count, int maxcount,
346 int *irqs)
347 {
348 device_t bus;
349
350 bus = device_get_parent(pci);
351 return (PCIB_ALLOC_MSI(device_get_parent(bus), child, count, maxcount,
352 irqs));
353 }
354
355 static int
356 thunder_pem_release_msi(device_t pci, device_t child, int count, int *irqs)
357 {
358 device_t bus;
359
360 bus = device_get_parent(pci);
361 return (PCIB_RELEASE_MSI(device_get_parent(bus), child, count, irqs));
362 }
363
364 static int
365 thunder_pem_alloc_msix(device_t pci, device_t child, int *irq)
366 {
367 device_t bus;
368
369 bus = device_get_parent(pci);
370 return (PCIB_ALLOC_MSIX(device_get_parent(bus), child, irq));
371 }
372
373 static int
374 thunder_pem_release_msix(device_t pci, device_t child, int irq)
375 {
376 device_t bus;
377
378 bus = device_get_parent(pci);
379 return (PCIB_RELEASE_MSIX(device_get_parent(bus), child, irq));
380 }
381
382 static int
383 thunder_pem_map_msi(device_t pci, device_t child, int irq, uint64_t *addr,
384 uint32_t *data)
385 {
386 device_t bus;
387
388 bus = device_get_parent(pci);
389 return (PCIB_MAP_MSI(device_get_parent(bus), child, irq, addr, data));
390 }
391
392 static int
393 thunder_pem_get_id(device_t pci, device_t child, enum pci_id_type type,
394 uintptr_t *id)
395 {
396 int bsf;
397 int pem;
398
399 if (type != PCI_ID_MSI)
400 return (pcib_get_id(pci, child, type, id));
401
402 bsf = pci_get_rid(child);
403
404 /* PEM (PCIe MAC/root complex) number is equal to domain */
405 pem = pci_get_domain(child);
406
407 /*
408 * Set appropriate device ID (passed by the HW along with
409 * the transaction to memory) for different root complex
410 * numbers using hard-coded domain portion for each group.
411 */
412 if (pem < 3)
413 *id = (0x1 << PCI_RID_DOMAIN_SHIFT) | bsf;
414 else if (pem < 6)
415 *id = (0x3 << PCI_RID_DOMAIN_SHIFT) | bsf;
416 else if (pem < 9)
417 *id = (0x9 << PCI_RID_DOMAIN_SHIFT) | bsf;
418 else if (pem < 12)
419 *id = (0xB << PCI_RID_DOMAIN_SHIFT) | bsf;
420 else
421 return (ENXIO);
422
423 return (0);
424 }
425
426 static int
427 thunder_pem_identify(device_t dev)
428 {
429 struct thunder_pem_softc *sc;
430 rman_res_t start;
431
432 sc = device_get_softc(dev);
433 start = rman_get_start(sc->reg);
434
435 /* Calculate PEM designations from its address */
436 sc->node = (start >> SLI_NODE_SHIFT) & SLI_NODE_MASK;
437 sc->id = ((start >> SLI_ID_SHIFT) & SLI_ID_MASK) +
438 (SLI_PEMS_PER_NODE * sc->node);
439 sc->sli = sc->id % SLI_PEMS_PER_GROUP;
440 sc->sli_group = (sc->id / SLI_PEMS_PER_GROUP) % SLI_GROUPS_PER_NODE;
441 sc->sli_window_base = SLI_BASE |
442 (((uint64_t)sc->node) << SLI_NODE_SHIFT) |
443 ((uint64_t)sc->sli_group << SLI_GROUP_SHIFT);
444 sc->sli_window_base += SLI_WINDOW_SPACING * sc->sli;
445
446 return (0);
447 }
448
449 static void
450 thunder_pem_slix_s2m_regx_acc_modify(struct thunder_pem_softc *sc,
451 int sli_group, int slix)
452 {
453 uint64_t regval;
454 bus_space_handle_t handle = 0;
455
456 KASSERT(slix >= 0 && slix <= SLI_ACC_REG_CNT, ("Invalid SLI index"));
457
458 if (sli_group == 0)
459 handle = sli0_s2m_regx_base;
460 else if (sli_group == 1)
461 handle = sli1_s2m_regx_base;
462 else
463 device_printf(sc->dev, "SLI group is not correct\n");
464
465 if (handle) {
466 /* Clear lower 32-bits of the SLIx register */
467 regval = bus_space_read_8(sc->reg_bst, handle,
468 PEM_CFG_SLIX_TO_REG(slix));
469 regval &= ~(0xFFFFFFFFUL);
470 bus_space_write_8(sc->reg_bst, handle,
471 PEM_CFG_SLIX_TO_REG(slix), regval);
472 }
473 }
474
475 static int
476 thunder_pem_link_init(struct thunder_pem_softc *sc)
477 {
478 uint64_t regval;
479
480 /* check whether PEM is safe to access. */
481 regval = bus_space_read_8(sc->reg_bst, sc->reg_bsh, PEM_ON_REG);
482 if ((regval & PEM_CFG_LINK_MASK) != PEM_CFG_LINK_RDY) {
483 device_printf(sc->dev, "PEM%d is not ON\n", sc->id);
484 return (ENXIO);
485 }
486
487 regval = bus_space_read_8(sc->reg_bst, sc->reg_bsh, PEM_CTL_STATUS);
488 regval |= PEM_LINK_ENABLE;
489 bus_space_write_8(sc->reg_bst, sc->reg_bsh, PEM_CTL_STATUS, regval);
490
491 /* Wait 1ms as per Cavium specification */
492 DELAY(1000);
493
494 regval = thunder_pem_config_reg_read(sc, PCIERC_CFG032);
495
496 if (((regval & PEM_LINK_DLLA) == 0) || ((regval & PEM_LINK_LT) != 0)) {
497 device_printf(sc->dev, "PCIe RC: Port %d Link Timeout\n",
498 sc->id);
499 return (ENXIO);
500 }
501
502 return (0);
503 }
504
505 static int
506 thunder_pem_init(struct thunder_pem_softc *sc)
507 {
508 int i, retval = 0;
509
510 retval = thunder_pem_link_init(sc);
511 if (retval) {
512 device_printf(sc->dev, "%s failed\n", __func__);
513 return retval;
514 }
515
516 /* To support 32-bit PCIe devices, set S2M_REGx_ACC[BA]=0x0 */
517 for (i = 0; i < SLI_ACC_REG_CNT; i++) {
518 thunder_pem_slix_s2m_regx_acc_modify(sc, sc->sli_group, i);
519 }
520
521 return (retval);
522 }
523
524 static uint64_t
525 thunder_pem_config_reg_read(struct thunder_pem_softc *sc, int reg)
526 {
527 uint64_t data;
528
529 /* Write to ADDR register */
530 bus_space_write_8(sc->reg_bst, sc->reg_bsh, PEM_CFG_RD,
531 PEM_CFG_RD_REG_ALIGN(reg));
532 bus_space_barrier(sc->reg_bst, sc->reg_bsh, PEM_CFG_RD, 8,
533 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
534 /* Read from DATA register */
535 data = PEM_CFG_RD_REG_DATA(bus_space_read_8(sc->reg_bst, sc->reg_bsh,
536 PEM_CFG_RD));
537
538 return (data);
539 }
540
541 static uint32_t
542 thunder_pem_read_config(device_t dev, u_int bus, u_int slot,
543 u_int func, u_int reg, int bytes)
544 {
545 uint64_t offset;
546 uint32_t data;
547 struct thunder_pem_softc *sc;
548 bus_space_tag_t t;
549 bus_space_handle_t h;
550
551 if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
552 (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
553 return (~0U);
554
555 sc = device_get_softc(dev);
556
557 /* Calculate offset */
558 offset = (bus << PEM_BUS_SHIFT) | (slot << PEM_SLOT_SHIFT) |
559 (func << PEM_FUNC_SHIFT);
560 t = sc->reg_bst;
561 h = sc->pem_sli_base;
562
563 bus_space_map(sc->reg_bst, sc->sli_window_base + offset,
564 PCIE_REGMAX, 0, &h);
565
566 switch (bytes) {
567 case 1:
568 data = bus_space_read_1(t, h, reg);
569 break;
570 case 2:
571 data = le16toh(bus_space_read_2(t, h, reg));
572 break;
573 case 4:
574 data = le32toh(bus_space_read_4(t, h, reg));
575 break;
576 default:
577 data = ~0U;
578 break;
579 }
580
581 bus_space_unmap(sc->reg_bst, h, PCIE_REGMAX);
582
583 return (data);
584 }
585
586 static void
587 thunder_pem_write_config(device_t dev, u_int bus, u_int slot,
588 u_int func, u_int reg, uint32_t val, int bytes)
589 {
590 uint64_t offset;
591 struct thunder_pem_softc *sc;
592 bus_space_tag_t t;
593 bus_space_handle_t h;
594
595 if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
596 (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
597 return;
598
599 sc = device_get_softc(dev);
600
601 /* Calculate offset */
602 offset = (bus << PEM_BUS_SHIFT) | (slot << PEM_SLOT_SHIFT) |
603 (func << PEM_FUNC_SHIFT);
604 t = sc->reg_bst;
605 h = sc->pem_sli_base;
606
607 bus_space_map(sc->reg_bst, sc->sli_window_base + offset,
608 PCIE_REGMAX, 0, &h);
609
610 switch (bytes) {
611 case 1:
612 bus_space_write_1(t, h, reg, val);
613 break;
614 case 2:
615 bus_space_write_2(t, h, reg, htole16(val));
616 break;
617 case 4:
618 bus_space_write_4(t, h, reg, htole32(val));
619 break;
620 default:
621 break;
622 }
623
624 bus_space_unmap(sc->reg_bst, h, PCIE_REGMAX);
625 }
626
627 static struct resource *
628 thunder_pem_alloc_resource(device_t dev, device_t child, int type, int *rid,
629 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
630 {
631 struct thunder_pem_softc *sc = device_get_softc(dev);
632 struct rman *rm = NULL;
633 struct resource *res;
634 device_t parent_dev;
635
636 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
637 if (type == PCI_RES_BUS)
638 return (pci_domain_alloc_bus(sc->id, child, rid, start, end,
639 count, flags));
640 #endif
641 rm = thunder_pem_rman(sc, type);
642 if (rm == NULL) {
643 /* Find parent device. On ThunderX we know an exact path. */
644 parent_dev = device_get_parent(device_get_parent(dev));
645 return (BUS_ALLOC_RESOURCE(parent_dev, dev, type, rid, start,
646 end, count, flags));
647 }
648
649 if (!RMAN_IS_DEFAULT_RANGE(start, end)) {
650 /*
651 * We might get PHYS addresses here inherited from EFI.
652 * Convert to PCI if necessary.
653 */
654 if (range_addr_is_phys(sc->ranges, start, count)) {
655 start = range_addr_phys_to_pci(sc->ranges, start);
656 end = start + count - 1;
657 }
658 }
659
660 if (bootverbose) {
661 device_printf(dev,
662 "thunder_pem_alloc_resource: start=%#lx, end=%#lx, count=%#lx\n",
663 start, end, count);
664 }
665
666 res = rman_reserve_resource(rm, start, end, count, flags, child);
667 if (res == NULL)
668 goto fail;
669
670 rman_set_rid(res, *rid);
671
672 if (flags & RF_ACTIVE)
673 if (bus_activate_resource(child, type, *rid, res)) {
674 rman_release_resource(res);
675 goto fail;
676 }
677
678 return (res);
679
680 fail:
681 if (bootverbose) {
682 device_printf(dev, "%s FAIL: type=%d, rid=%d, "
683 "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
684 __func__, type, *rid, start, end, count, flags);
685 }
686
687 return (NULL);
688 }
689
690 static int
691 thunder_pem_release_resource(device_t dev, device_t child, int type, int rid,
692 struct resource *res)
693 {
694 device_t parent_dev;
695 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
696 struct thunder_pem_softc *sc = device_get_softc(dev);
697
698 if (type == PCI_RES_BUS)
699 return (pci_domain_release_bus(sc->id, child, rid, res));
700 #endif
701 /* Find parent device. On ThunderX we know an exact path. */
702 parent_dev = device_get_parent(device_get_parent(dev));
703
704 if ((type != SYS_RES_MEMORY) && (type != SYS_RES_IOPORT))
705 return (BUS_RELEASE_RESOURCE(parent_dev, child,
706 type, rid, res));
707
708 return (rman_release_resource(res));
709 }
710
711 static struct rman *
712 thunder_pem_rman(struct thunder_pem_softc *sc, int type)
713 {
714
715 switch (type) {
716 case SYS_RES_IOPORT:
717 return (&sc->io_rman);
718 case SYS_RES_MEMORY:
719 return (&sc->mem_rman);
720 default:
721 break;
722 }
723
724 return (NULL);
725 }
726
727 static int
728 thunder_pem_probe(device_t dev)
729 {
730 uint16_t pci_vendor_id;
731 uint16_t pci_device_id;
732
733 pci_vendor_id = pci_get_vendor(dev);
734 pci_device_id = pci_get_device(dev);
735
736 if ((pci_vendor_id == THUNDER_PEM_VENDOR_ID) &&
737 (pci_device_id == THUNDER_PEM_DEVICE_ID)) {
738 device_set_desc_copy(dev, THUNDER_PEM_DESC);
739 return (0);
740 }
741
742 return (ENXIO);
743 }
744
745 static int
746 thunder_pem_attach(device_t dev)
747 {
748 devclass_t pci_class;
749 device_t parent;
750 struct thunder_pem_softc *sc;
751 int error;
752 int rid;
753 int tuple;
754 uint64_t base, size;
755 struct rman *rman;
756
757 sc = device_get_softc(dev);
758 sc->dev = dev;
759
760 /* Allocate memory for resource */
761 pci_class = devclass_find("pci");
762 parent = device_get_parent(dev);
763 if (device_get_devclass(parent) == pci_class)
764 rid = PCIR_BAR(0);
765 else
766 rid = RID_PEM_SPACE;
767
768 sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
769 &rid, RF_ACTIVE);
770 if (sc->reg == NULL) {
771 device_printf(dev, "Failed to allocate resource\n");
772 return (ENXIO);
773 }
774 sc->reg_bst = rman_get_bustag(sc->reg);
775 sc->reg_bsh = rman_get_bushandle(sc->reg);
776
777 /* Create the parent DMA tag to pass down the coherent flag */
778 error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
779 1, 0, /* alignment, bounds */
780 BUS_SPACE_MAXADDR, /* lowaddr */
781 BUS_SPACE_MAXADDR, /* highaddr */
782 NULL, NULL, /* filter, filterarg */
783 BUS_SPACE_MAXSIZE, /* maxsize */
784 BUS_SPACE_UNRESTRICTED, /* nsegments */
785 BUS_SPACE_MAXSIZE, /* maxsegsize */
786 BUS_DMA_COHERENT, /* flags */
787 NULL, NULL, /* lockfunc, lockarg */
788 &sc->dmat);
789 if (error != 0)
790 return (error);
791
792 /* Map SLI, do it only once */
793 if (!sli0_s2m_regx_base) {
794 bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC,
795 SLIX_S2M_REGX_ACC_SIZE, 0, &sli0_s2m_regx_base);
796 }
797 if (!sli1_s2m_regx_base) {
798 bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC +
799 SLIX_S2M_REGX_ACC_SPACING, SLIX_S2M_REGX_ACC_SIZE, 0,
800 &sli1_s2m_regx_base);
801 }
802
803 if ((sli0_s2m_regx_base == 0) || (sli1_s2m_regx_base == 0)) {
804 device_printf(dev,
805 "bus_space_map failed to map slix_s2m_regx_base\n");
806 goto fail;
807 }
808
809 /* Identify PEM */
810 if (thunder_pem_identify(dev) != 0)
811 goto fail;
812
813 /* Initialize rman and allocate regions */
814 sc->mem_rman.rm_type = RMAN_ARRAY;
815 sc->mem_rman.rm_descr = "PEM PCIe Memory";
816 error = rman_init(&sc->mem_rman);
817 if (error != 0) {
818 device_printf(dev, "memory rman_init() failed. error = %d\n",
819 error);
820 goto fail;
821 }
822 sc->io_rman.rm_type = RMAN_ARRAY;
823 sc->io_rman.rm_descr = "PEM PCIe IO";
824 error = rman_init(&sc->io_rman);
825 if (error != 0) {
826 device_printf(dev, "IO rman_init() failed. error = %d\n",
827 error);
828 goto fail_mem;
829 }
830
831 /*
832 * We ignore the values that may have been provided in FDT
833 * and configure ranges according to the below formula
834 * for all types of devices. This is because some DTBs provided
835 * by EFI do not have proper ranges property or don't have them
836 * at all.
837 */
838 /* Fill memory window */
839 sc->ranges[0].pci_base = PCI_MEMORY_BASE;
840 sc->ranges[0].size = PCI_MEMORY_SIZE;
841 sc->ranges[0].phys_base = sc->sli_window_base + SLI_PCI_OFFSET +
842 sc->ranges[0].pci_base;
843 sc->ranges[0].flags = SYS_RES_MEMORY;
844
845 /* Fill IO window */
846 sc->ranges[1].pci_base = PCI_IO_BASE;
847 sc->ranges[1].size = PCI_IO_SIZE;
848 sc->ranges[1].phys_base = sc->sli_window_base + SLI_PCI_OFFSET +
849 sc->ranges[1].pci_base;
850 sc->ranges[1].flags = SYS_RES_IOPORT;
851
852 for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
853 base = sc->ranges[tuple].pci_base;
854 size = sc->ranges[tuple].size;
855 if (size == 0)
856 continue; /* empty range element */
857
858 rman = thunder_pem_rman(sc, sc->ranges[tuple].flags);
859 if (rman != NULL)
860 error = rman_manage_region(rman, base,
861 base + size - 1);
862 else
863 error = EINVAL;
864 if (error) {
865 device_printf(dev,
866 "rman_manage_region() failed. error = %d\n", error);
867 rman_fini(&sc->mem_rman);
868 return (error);
869 }
870 if (bootverbose) {
871 device_printf(dev,
872 "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx, Flags:0x%jx\n",
873 sc->ranges[tuple].pci_base,
874 sc->ranges[tuple].phys_base,
875 sc->ranges[tuple].size,
876 sc->ranges[tuple].flags);
877 }
878 }
879
880 if (thunder_pem_init(sc)) {
881 device_printf(dev, "Failure during PEM init\n");
882 goto fail_io;
883 }
884
885 device_add_child(dev, "pci", -1);
886
887 return (bus_generic_attach(dev));
888
889 fail_io:
890 rman_fini(&sc->io_rman);
891 fail_mem:
892 rman_fini(&sc->mem_rman);
893 fail:
894 bus_free_resource(dev, SYS_RES_MEMORY, sc->reg);
895 return (ENXIO);
896 }
897
898 static void
899 thunder_pem_release_all(device_t dev)
900 {
901 struct thunder_pem_softc *sc;
902
903 sc = device_get_softc(dev);
904
905 rman_fini(&sc->io_rman);
906 rman_fini(&sc->mem_rman);
907
908 if (sc->reg != NULL)
909 bus_free_resource(dev, SYS_RES_MEMORY, sc->reg);
910 }
911
912 static int
913 thunder_pem_detach(device_t dev)
914 {
915
916 thunder_pem_release_all(dev);
917
918 return (0);
919 }
Cache object: 73b1affca4f4ce2efd2d9d681cfe41b9
|