xref: /freebsd/sys/arm64/cavium/thunder_pcie_pem.c (revision 397e83df75e0fcd0d3fcb95ae4d794cb7600fc89)
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 #include "opt_platform.h"
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
40 #include <sys/rman.h>
41 #include <sys/endian.h>
42 
43 #include <vm/vm.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, struct resource *);
124 static int thunder_pem_adjust_resource(device_t, device_t,
125     struct resource *, rman_res_t, rman_res_t);
126 static struct resource * thunder_pem_alloc_resource(device_t, device_t, int,
127     int *, rman_res_t, rman_res_t, rman_res_t, u_int);
128 static int thunder_pem_alloc_msi(device_t, device_t, int, int, int *);
129 static int thunder_pem_release_msi(device_t, device_t, int, int *);
130 static int thunder_pem_alloc_msix(device_t, device_t, int *);
131 static int thunder_pem_release_msix(device_t, device_t, int);
132 static int thunder_pem_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
133 static int thunder_pem_get_id(device_t, device_t, enum pci_id_type,
134     uintptr_t *);
135 static int thunder_pem_attach(device_t);
136 static int thunder_pem_deactivate_resource(device_t, device_t,
137     struct resource *);
138 static int thunder_pem_map_resource(device_t, device_t, struct resource *,
139     struct resource_map_request *, struct resource_map *);
140 static int thunder_pem_unmap_resource(device_t, device_t, struct resource *,
141     struct resource_map *);
142 static bus_dma_tag_t thunder_pem_get_dma_tag(device_t, device_t);
143 static int thunder_pem_detach(device_t);
144 static uint64_t thunder_pem_config_reg_read(struct thunder_pem_softc *, int);
145 static int thunder_pem_link_init(struct thunder_pem_softc *);
146 static int thunder_pem_maxslots(device_t);
147 static int thunder_pem_probe(device_t);
148 static uint32_t thunder_pem_read_config(device_t, u_int, u_int, u_int, u_int,
149     int);
150 static int thunder_pem_read_ivar(device_t, device_t, int, uintptr_t *);
151 static void thunder_pem_release_all(device_t);
152 static int thunder_pem_release_resource(device_t, device_t, struct resource *);
153 static struct rman * thunder_pem_get_rman(device_t, int, u_int);
154 static void thunder_pem_slix_s2m_regx_acc_modify(struct thunder_pem_softc *,
155     int, int);
156 static void thunder_pem_write_config(device_t, u_int, u_int, u_int, u_int,
157     uint32_t, int);
158 static int thunder_pem_write_ivar(device_t, device_t, int, uintptr_t);
159 
160 /* Global handlers for SLI interface */
161 static bus_space_handle_t sli0_s2m_regx_base = 0;
162 static bus_space_handle_t sli1_s2m_regx_base = 0;
163 
164 static device_method_t thunder_pem_methods[] = {
165 	/* Device interface */
166 	DEVMETHOD(device_probe,			thunder_pem_probe),
167 	DEVMETHOD(device_attach,		thunder_pem_attach),
168 	DEVMETHOD(device_detach,		thunder_pem_detach),
169 
170 	/* Bus interface */
171 	DEVMETHOD(bus_read_ivar,		thunder_pem_read_ivar),
172 	DEVMETHOD(bus_write_ivar,		thunder_pem_write_ivar),
173 	DEVMETHOD(bus_get_rman,			thunder_pem_get_rman),
174 	DEVMETHOD(bus_alloc_resource,		thunder_pem_alloc_resource),
175 	DEVMETHOD(bus_release_resource,		thunder_pem_release_resource),
176 	DEVMETHOD(bus_adjust_resource,		thunder_pem_adjust_resource),
177 	DEVMETHOD(bus_activate_resource,	thunder_pem_activate_resource),
178 	DEVMETHOD(bus_deactivate_resource,	thunder_pem_deactivate_resource),
179 	DEVMETHOD(bus_map_resource,		thunder_pem_map_resource),
180 	DEVMETHOD(bus_unmap_resource,		thunder_pem_unmap_resource),
181 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
182 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
183 
184 	DEVMETHOD(bus_get_dma_tag,		thunder_pem_get_dma_tag),
185 
186 	/* pcib interface */
187 	DEVMETHOD(pcib_maxslots,		thunder_pem_maxslots),
188 	DEVMETHOD(pcib_read_config,		thunder_pem_read_config),
189 	DEVMETHOD(pcib_write_config,		thunder_pem_write_config),
190 	DEVMETHOD(pcib_alloc_msix,		thunder_pem_alloc_msix),
191 	DEVMETHOD(pcib_release_msix,		thunder_pem_release_msix),
192 	DEVMETHOD(pcib_alloc_msi,		thunder_pem_alloc_msi),
193 	DEVMETHOD(pcib_release_msi,		thunder_pem_release_msi),
194 	DEVMETHOD(pcib_map_msi,			thunder_pem_map_msi),
195 	DEVMETHOD(pcib_get_id,			thunder_pem_get_id),
196 
197 	DEVMETHOD_END
198 };
199 
200 DEFINE_CLASS_0(pcib, thunder_pem_driver, thunder_pem_methods,
201     sizeof(struct thunder_pem_softc));
202 
203 extern struct bus_space memmap_bus;
204 
205 DRIVER_MODULE(thunder_pem, pci, thunder_pem_driver, 0, 0);
206 MODULE_DEPEND(thunder_pem, pci, 1, 1, 1);
207 
208 static int
209 thunder_pem_maxslots(device_t dev)
210 {
211 
212 #if 0
213 	/* max slots per bus acc. to standard */
214 	return (PCI_SLOTMAX);
215 #else
216 	/*
217 	 * ARM64TODO Workaround - otherwise an em(4) interface appears to be
218 	 * present on every PCI function on the bus to which it is connected
219 	 */
220 	return (0);
221 #endif
222 }
223 
224 static int
225 thunder_pem_read_ivar(device_t dev, device_t child, int index,
226     uintptr_t *result)
227 {
228 	struct thunder_pem_softc *sc;
229 	int secondary_bus = 0;
230 
231 	sc = device_get_softc(dev);
232 
233 	if (index == PCIB_IVAR_BUS) {
234 		secondary_bus = thunder_pem_config_reg_read(sc, PCIERC_CFG006);
235 		*result = PCIERC_CFG006_SEC_BUS(secondary_bus);
236 		return (0);
237 	}
238 	if (index == PCIB_IVAR_DOMAIN) {
239 		*result = sc->id;
240 		return (0);
241 	}
242 
243 	return (ENOENT);
244 }
245 
246 static int
247 thunder_pem_write_ivar(device_t dev, device_t child, int index,
248     uintptr_t value)
249 {
250 
251 	return (ENOENT);
252 }
253 
254 static int
255 thunder_pem_activate_resource(device_t dev, device_t child, struct resource *r)
256 {
257 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
258 	struct thunder_pem_softc *sc;
259 
260 	sc = device_get_softc(dev);
261 #endif
262 	switch (rman_get_type(r)) {
263 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
264 	case PCI_RES_BUS:
265 		return (pci_domain_activate_bus(sc->id, child, r));
266 #endif
267 	case SYS_RES_MEMORY:
268 	case SYS_RES_IOPORT:
269 		return (bus_generic_rman_activate_resource(dev, child, r));
270 	default:
271 		return (bus_generic_activate_resource(dev, child, r));
272 	}
273 }
274 
275 static int
276 thunder_pem_deactivate_resource(device_t dev, device_t child,
277     struct resource *r)
278 {
279 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
280 	struct thunder_pem_softc *sc;
281 
282 	sc = device_get_softc(dev);
283 #endif
284 	switch (rman_get_type(r)) {
285 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
286 	case PCI_RES_BUS:
287 		return (pci_domain_deactivate_bus(sc->id, child, r));
288 #endif
289 	case SYS_RES_MEMORY:
290 	case SYS_RES_IOPORT:
291 		return (bus_generic_rman_deactivate_resource(dev, child, r));
292 	default:
293 		return (bus_generic_deactivate_resource(dev, child, r));
294 	}
295 }
296 
297 static int
298 thunder_pem_map_resource(device_t dev, device_t child, struct resource *r,
299     struct resource_map_request *argsp, struct resource_map *map)
300 {
301 	struct resource_map_request args;
302 	struct thunder_pem_softc *sc;
303 	rman_res_t length, start;
304 	int error;
305 
306 	/* Resources must be active to be mapped. */
307 	if (!(rman_get_flags(r) & RF_ACTIVE))
308 		return (ENXIO);
309 
310 	switch (rman_get_type(r)) {
311 	case SYS_RES_MEMORY:
312 	case SYS_RES_IOPORT:
313 		break;
314 	default:
315 		return (EINVAL);
316 	}
317 
318 	resource_init_map_request(&args);
319 	error = resource_validate_map_request(r, argsp, &args, &start, &length);
320 	if (error)
321 		return (error);
322 
323 	sc = device_get_softc(dev);
324 	start = range_addr_pci_to_phys(sc->ranges, start);
325 	error = bus_space_map(&memmap_bus, start, length, 0, &map->r_bushandle);
326 	if (error)
327 		return (error);
328 	map->r_bustag = &memmap_bus;
329 	map->r_vaddr = (void *)map->r_bushandle;
330 	map->r_size = length;
331 	return (0);
332 }
333 
334 static int
335 thunder_pem_unmap_resource(device_t dev, device_t child, struct resource *r,
336     struct resource_map *map)
337 {
338 
339 	switch (rman_get_type(r)) {
340 	case SYS_RES_MEMORY:
341 	case SYS_RES_IOPORT:
342 		bus_space_unmap(map->r_bustag, map->r_bushandle, map->r_size);
343 		return (0);
344 	default:
345 		return (EINVAL);
346 	}
347 }
348 
349 static int
350 thunder_pem_adjust_resource(device_t dev, device_t child, struct resource *res,
351     rman_res_t start, rman_res_t end)
352 {
353 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
354 	struct thunder_pem_softc *sc;
355 
356 	sc = device_get_softc(dev);
357 #endif
358 	switch (rman_get_type(res)) {
359 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
360 	case PCI_RES_BUS:
361 		return (pci_domain_adjust_bus(sc->id, child, res, start, end));
362 #endif
363 	case SYS_RES_MEMORY:
364 	case SYS_RES_IOPORT:
365 		return (bus_generic_rman_adjust_resource(dev, child, res, start,
366 		    end));
367 	default:
368 		return (bus_generic_adjust_resource(dev, child, res, start,
369 		    end));
370 	}
371 }
372 
373 static bus_dma_tag_t
374 thunder_pem_get_dma_tag(device_t dev, device_t child)
375 {
376 	struct thunder_pem_softc *sc;
377 
378 	sc = device_get_softc(dev);
379 	return (sc->dmat);
380 }
381 
382 static int
383 thunder_pem_alloc_msi(device_t pci, device_t child, int count, int maxcount,
384     int *irqs)
385 {
386 	device_t bus;
387 
388 	bus = device_get_parent(pci);
389 	return (PCIB_ALLOC_MSI(device_get_parent(bus), child, count, maxcount,
390 	    irqs));
391 }
392 
393 static int
394 thunder_pem_release_msi(device_t pci, device_t child, int count, int *irqs)
395 {
396 	device_t bus;
397 
398 	bus = device_get_parent(pci);
399 	return (PCIB_RELEASE_MSI(device_get_parent(bus), child, count, irqs));
400 }
401 
402 static int
403 thunder_pem_alloc_msix(device_t pci, device_t child, int *irq)
404 {
405 	device_t bus;
406 
407 	bus = device_get_parent(pci);
408 	return (PCIB_ALLOC_MSIX(device_get_parent(bus), child, irq));
409 }
410 
411 static int
412 thunder_pem_release_msix(device_t pci, device_t child, int irq)
413 {
414 	device_t bus;
415 
416 	bus = device_get_parent(pci);
417 	return (PCIB_RELEASE_MSIX(device_get_parent(bus), child, irq));
418 }
419 
420 static int
421 thunder_pem_map_msi(device_t pci, device_t child, int irq, uint64_t *addr,
422     uint32_t *data)
423 {
424 	device_t bus;
425 
426 	bus = device_get_parent(pci);
427 	return (PCIB_MAP_MSI(device_get_parent(bus), child, irq, addr, data));
428 }
429 
430 static int
431 thunder_pem_get_id(device_t pci, device_t child, enum pci_id_type type,
432     uintptr_t *id)
433 {
434 	int bsf;
435 	int pem;
436 
437 	if (type != PCI_ID_MSI)
438 		return (pcib_get_id(pci, child, type, id));
439 
440 	bsf = pci_get_rid(child);
441 
442 	/* PEM (PCIe MAC/root complex) number is equal to domain */
443 	pem = pci_get_domain(child);
444 
445 	/*
446 	 * Set appropriate device ID (passed by the HW along with
447 	 * the transaction to memory) for different root complex
448 	 * numbers using hard-coded domain portion for each group.
449 	 */
450 	if (pem < 3)
451 		*id = (0x1 << PCI_RID_DOMAIN_SHIFT) | bsf;
452 	else if (pem < 6)
453 		*id = (0x3 << PCI_RID_DOMAIN_SHIFT) | bsf;
454 	else if (pem < 9)
455 		*id = (0x9 << PCI_RID_DOMAIN_SHIFT) | bsf;
456 	else if (pem < 12)
457 		*id = (0xB << PCI_RID_DOMAIN_SHIFT) | bsf;
458 	else
459 		return (ENXIO);
460 
461 	return (0);
462 }
463 
464 static int
465 thunder_pem_identify(device_t dev)
466 {
467 	struct thunder_pem_softc *sc;
468 	rman_res_t start;
469 
470 	sc = device_get_softc(dev);
471 	start = rman_get_start(sc->reg);
472 
473 	/* Calculate PEM designations from its address */
474 	sc->node = (start >> SLI_NODE_SHIFT) & SLI_NODE_MASK;
475 	sc->id = ((start >> SLI_ID_SHIFT) & SLI_ID_MASK) +
476 	    (SLI_PEMS_PER_NODE * sc->node);
477 	sc->sli = sc->id % SLI_PEMS_PER_GROUP;
478 	sc->sli_group = (sc->id / SLI_PEMS_PER_GROUP) % SLI_GROUPS_PER_NODE;
479 	sc->sli_window_base = SLI_BASE |
480 	    (((uint64_t)sc->node) << SLI_NODE_SHIFT) |
481 	    ((uint64_t)sc->sli_group << SLI_GROUP_SHIFT);
482 	sc->sli_window_base += SLI_WINDOW_SPACING * sc->sli;
483 
484 	return (0);
485 }
486 
487 static void
488 thunder_pem_slix_s2m_regx_acc_modify(struct thunder_pem_softc *sc,
489     int sli_group, int slix)
490 {
491 	uint64_t regval;
492 	bus_space_handle_t handle = 0;
493 
494 	KASSERT(slix >= 0 && slix <= SLI_ACC_REG_CNT, ("Invalid SLI index"));
495 
496 	if (sli_group == 0)
497 		handle = sli0_s2m_regx_base;
498 	else if (sli_group == 1)
499 		handle = sli1_s2m_regx_base;
500 	else
501 		device_printf(sc->dev, "SLI group is not correct\n");
502 
503 	if (handle) {
504 		/* Clear lower 32-bits of the SLIx register */
505 		regval = bus_space_read_8(sc->reg_bst, handle,
506 		    PEM_CFG_SLIX_TO_REG(slix));
507 		regval &= ~(0xFFFFFFFFUL);
508 		bus_space_write_8(sc->reg_bst, handle,
509 		    PEM_CFG_SLIX_TO_REG(slix), regval);
510 	}
511 }
512 
513 static int
514 thunder_pem_link_init(struct thunder_pem_softc *sc)
515 {
516 	uint64_t regval;
517 
518 	/* check whether PEM is safe to access. */
519 	regval = bus_space_read_8(sc->reg_bst, sc->reg_bsh, PEM_ON_REG);
520 	if ((regval & PEM_CFG_LINK_MASK) != PEM_CFG_LINK_RDY) {
521 		device_printf(sc->dev, "PEM%d is not ON\n", sc->id);
522 		return (ENXIO);
523 	}
524 
525 	regval = bus_space_read_8(sc->reg_bst, sc->reg_bsh, PEM_CTL_STATUS);
526 	regval |= PEM_LINK_ENABLE;
527 	bus_space_write_8(sc->reg_bst, sc->reg_bsh, PEM_CTL_STATUS, regval);
528 
529 	/* Wait 1ms as per Cavium specification */
530 	DELAY(1000);
531 
532 	regval = thunder_pem_config_reg_read(sc, PCIERC_CFG032);
533 
534 	if (((regval & PEM_LINK_DLLA) == 0) || ((regval & PEM_LINK_LT) != 0)) {
535 		device_printf(sc->dev, "PCIe RC: Port %d Link Timeout\n",
536 		    sc->id);
537 		return (ENXIO);
538 	}
539 
540 	return (0);
541 }
542 
543 static int
544 thunder_pem_init(struct thunder_pem_softc *sc)
545 {
546 	int i, retval = 0;
547 
548 	retval = thunder_pem_link_init(sc);
549 	if (retval) {
550 		device_printf(sc->dev, "%s failed\n", __func__);
551 		return retval;
552 	}
553 
554 	/* To support 32-bit PCIe devices, set S2M_REGx_ACC[BA]=0x0 */
555 	for (i = 0; i < SLI_ACC_REG_CNT; i++) {
556 		thunder_pem_slix_s2m_regx_acc_modify(sc, sc->sli_group, i);
557 	}
558 
559 	return (retval);
560 }
561 
562 static uint64_t
563 thunder_pem_config_reg_read(struct thunder_pem_softc *sc, int reg)
564 {
565 	uint64_t data;
566 
567 	/* Write to ADDR register */
568 	bus_space_write_8(sc->reg_bst, sc->reg_bsh, PEM_CFG_RD,
569 	    PEM_CFG_RD_REG_ALIGN(reg));
570 	bus_space_barrier(sc->reg_bst, sc->reg_bsh, PEM_CFG_RD, 8,
571 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
572 	/* Read from DATA register */
573 	data = PEM_CFG_RD_REG_DATA(bus_space_read_8(sc->reg_bst, sc->reg_bsh,
574 	    PEM_CFG_RD));
575 
576 	return (data);
577 }
578 
579 static uint32_t
580 thunder_pem_read_config(device_t dev, u_int bus, u_int slot,
581     u_int func, u_int reg, int bytes)
582 {
583 	uint64_t offset;
584 	uint32_t data;
585 	struct thunder_pem_softc *sc;
586 	bus_space_tag_t	t;
587 	bus_space_handle_t h;
588 
589 	if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
590 	    (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
591 		return (~0U);
592 
593 	sc = device_get_softc(dev);
594 
595 	/* Calculate offset */
596 	offset = (bus << PEM_BUS_SHIFT) | (slot << PEM_SLOT_SHIFT) |
597 	    (func << PEM_FUNC_SHIFT);
598 	t = sc->reg_bst;
599 	h = sc->pem_sli_base;
600 
601 	bus_space_map(sc->reg_bst, sc->sli_window_base + offset,
602 	    PCIE_REGMAX, 0, &h);
603 
604 	switch (bytes) {
605 	case 1:
606 		data = bus_space_read_1(t, h, reg);
607 		break;
608 	case 2:
609 		data = le16toh(bus_space_read_2(t, h, reg));
610 		break;
611 	case 4:
612 		data = le32toh(bus_space_read_4(t, h, reg));
613 		break;
614 	default:
615 		data = ~0U;
616 		break;
617 	}
618 
619 	bus_space_unmap(sc->reg_bst, h, PCIE_REGMAX);
620 
621 	return (data);
622 }
623 
624 static void
625 thunder_pem_write_config(device_t dev, u_int bus, u_int slot,
626     u_int func, u_int reg, uint32_t val, int bytes)
627 {
628 	uint64_t offset;
629 	struct thunder_pem_softc *sc;
630 	bus_space_tag_t	t;
631 	bus_space_handle_t h;
632 
633 	if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
634 	    (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
635 		return;
636 
637 	sc = device_get_softc(dev);
638 
639 	/* Calculate offset */
640 	offset = (bus << PEM_BUS_SHIFT) | (slot << PEM_SLOT_SHIFT) |
641 	    (func << PEM_FUNC_SHIFT);
642 	t = sc->reg_bst;
643 	h = sc->pem_sli_base;
644 
645 	bus_space_map(sc->reg_bst, sc->sli_window_base + offset,
646 	    PCIE_REGMAX, 0, &h);
647 
648 	switch (bytes) {
649 	case 1:
650 		bus_space_write_1(t, h, reg, val);
651 		break;
652 	case 2:
653 		bus_space_write_2(t, h, reg, htole16(val));
654 		break;
655 	case 4:
656 		bus_space_write_4(t, h, reg, htole32(val));
657 		break;
658 	default:
659 		break;
660 	}
661 
662 	bus_space_unmap(sc->reg_bst, h, PCIE_REGMAX);
663 }
664 
665 static struct resource *
666 thunder_pem_alloc_resource(device_t dev, device_t child, int type, int *rid,
667     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
668 {
669 	struct thunder_pem_softc *sc = device_get_softc(dev);
670 	struct resource *res;
671 	device_t parent_dev;
672 
673 	switch (type) {
674 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
675 	case PCI_RES_BUS:
676 		return (pci_domain_alloc_bus(sc->id, child, rid, start,  end,
677 		    count, flags));
678 #endif
679 	case SYS_RES_IOPORT:
680 	case SYS_RES_MEMORY:
681 		break;
682 	default:
683 		/* Find parent device. On ThunderX we know an exact path. */
684 		parent_dev = device_get_parent(device_get_parent(dev));
685 		return (BUS_ALLOC_RESOURCE(parent_dev, dev, type, rid, start,
686 		    end, count, flags));
687 	}
688 
689 	if (!RMAN_IS_DEFAULT_RANGE(start, end)) {
690 		/*
691 		 * We might get PHYS addresses here inherited from EFI.
692 		 * Convert to PCI if necessary.
693 		 */
694 		if (range_addr_is_phys(sc->ranges, start, count)) {
695 			start = range_addr_phys_to_pci(sc->ranges, start);
696 			end = start + count - 1;
697 		}
698 	}
699 
700 	if (bootverbose) {
701 		device_printf(dev,
702 		    "thunder_pem_alloc_resource: start=%#lx, end=%#lx, count=%#lx\n",
703 		    start, end, count);
704 	}
705 
706 	res = bus_generic_rman_alloc_resource(dev, child, type, rid, start,
707 	    end, count, flags);
708 	if (res == NULL && bootverbose) {
709 		device_printf(dev, "%s FAIL: type=%d, rid=%d, "
710 		    "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
711 		    __func__, type, *rid, start, end, count, flags);
712 	}
713 
714 	return (res);
715 }
716 
717 static int
718 thunder_pem_release_resource(device_t dev, device_t child, struct resource *res)
719 {
720 	device_t parent_dev;
721 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
722 	struct thunder_pem_softc *sc = device_get_softc(dev);
723 #endif
724 
725 	switch (rman_get_type(res)) {
726 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
727 	case PCI_RES_BUS:
728 		return (pci_domain_release_bus(sc->id, child, res));
729 #endif
730 	case SYS_RES_MEMORY:
731 	case SYS_RES_IOPORT:
732 		return (bus_generic_rman_release_resource(dev, child, res));
733 	default:
734 		/* Find parent device. On ThunderX we know an exact path. */
735 		parent_dev = device_get_parent(device_get_parent(dev));
736 		return (BUS_RELEASE_RESOURCE(parent_dev, child, res));
737 	}
738 }
739 
740 static struct rman *
741 thunder_pem_get_rman(device_t bus, int type, u_int flags)
742 {
743 	struct thunder_pem_softc *sc;
744 
745 	sc = device_get_softc(bus);
746 	switch (type) {
747 	case SYS_RES_IOPORT:
748 		return (&sc->io_rman);
749 	case SYS_RES_MEMORY:
750 		return (&sc->mem_rman);
751 	default:
752 		break;
753 	}
754 
755 	return (NULL);
756 }
757 
758 static int
759 thunder_pem_probe(device_t dev)
760 {
761 	uint16_t pci_vendor_id;
762 	uint16_t pci_device_id;
763 
764 	pci_vendor_id = pci_get_vendor(dev);
765 	pci_device_id = pci_get_device(dev);
766 
767 	if ((pci_vendor_id == THUNDER_PEM_VENDOR_ID) &&
768 	    (pci_device_id == THUNDER_PEM_DEVICE_ID)) {
769 		device_set_desc_copy(dev, THUNDER_PEM_DESC);
770 		return (0);
771 	}
772 
773 	return (ENXIO);
774 }
775 
776 static int
777 thunder_pem_attach(device_t dev)
778 {
779 	struct resource_map_request req;
780 	struct resource_map map;
781 	devclass_t pci_class;
782 	device_t parent;
783 	struct thunder_pem_softc *sc;
784 	int error;
785 	int rid;
786 	int tuple;
787 	uint64_t base, size;
788 	struct rman *rman;
789 
790 	sc = device_get_softc(dev);
791 	sc->dev = dev;
792 
793 	/* Allocate memory for resource */
794 	pci_class = devclass_find("pci");
795 	parent = device_get_parent(dev);
796 	if (device_get_devclass(parent) == pci_class)
797 		rid = PCIR_BAR(0);
798 	else
799 		rid = RID_PEM_SPACE;
800 
801 	sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
802 	    &rid, RF_ACTIVE | RF_UNMAPPED);
803 	if (sc->reg == NULL) {
804 		device_printf(dev, "Failed to allocate resource\n");
805 		return (ENXIO);
806 	}
807 	resource_init_map_request(&req);
808 	req.memattr = VM_MEMATTR_DEVICE_NP;
809 	error = bus_map_resource(dev, SYS_RES_MEMORY, sc->reg, &req, &map);
810 	if (error != 0) {
811 		device_printf(dev, "could not map memory.\n");
812 		return (error);
813 	}
814 	rman_set_mapping(sc->reg, &map);
815 
816 	sc->reg_bst = rman_get_bustag(sc->reg);
817 	sc->reg_bsh = rman_get_bushandle(sc->reg);
818 
819 	/* Create the parent DMA tag to pass down the coherent flag */
820 	error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
821 	    1, 0,			/* alignment, bounds */
822 	    BUS_SPACE_MAXADDR,		/* lowaddr */
823 	    BUS_SPACE_MAXADDR,		/* highaddr */
824 	    NULL, NULL,			/* filter, filterarg */
825 	    BUS_SPACE_MAXSIZE,		/* maxsize */
826 	    BUS_SPACE_UNRESTRICTED,	/* nsegments */
827 	    BUS_SPACE_MAXSIZE,		/* maxsegsize */
828 	    BUS_DMA_COHERENT,		/* flags */
829 	    NULL, NULL,			/* lockfunc, lockarg */
830 	    &sc->dmat);
831 	if (error != 0)
832 		return (error);
833 
834 	/* Map SLI, do it only once */
835 	if (!sli0_s2m_regx_base) {
836 		bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC,
837 		    SLIX_S2M_REGX_ACC_SIZE, 0, &sli0_s2m_regx_base);
838 	}
839 	if (!sli1_s2m_regx_base) {
840 		bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC +
841 		    SLIX_S2M_REGX_ACC_SPACING, SLIX_S2M_REGX_ACC_SIZE, 0,
842 		    &sli1_s2m_regx_base);
843 	}
844 
845 	if ((sli0_s2m_regx_base == 0) || (sli1_s2m_regx_base == 0)) {
846 		device_printf(dev,
847 		    "bus_space_map failed to map slix_s2m_regx_base\n");
848 		goto fail;
849 	}
850 
851 	/* Identify PEM */
852 	if (thunder_pem_identify(dev) != 0)
853 		goto fail;
854 
855 	/* Initialize rman and allocate regions */
856 	sc->mem_rman.rm_type = RMAN_ARRAY;
857 	sc->mem_rman.rm_descr = "PEM PCIe Memory";
858 	error = rman_init(&sc->mem_rman);
859 	if (error != 0) {
860 		device_printf(dev, "memory rman_init() failed. error = %d\n",
861 		    error);
862 		goto fail;
863 	}
864 	sc->io_rman.rm_type = RMAN_ARRAY;
865 	sc->io_rman.rm_descr = "PEM PCIe IO";
866 	error = rman_init(&sc->io_rman);
867 	if (error != 0) {
868 		device_printf(dev, "IO rman_init() failed. error = %d\n",
869 		    error);
870 		goto fail_mem;
871 	}
872 
873 	/*
874 	 * We ignore the values that may have been provided in FDT
875 	 * and configure ranges according to the below formula
876 	 * for all types of devices. This is because some DTBs provided
877 	 * by EFI do not have proper ranges property or don't have them
878 	 * at all.
879 	 */
880 	/* Fill memory window */
881 	sc->ranges[0].pci_base = PCI_MEMORY_BASE;
882 	sc->ranges[0].size = PCI_MEMORY_SIZE;
883 	sc->ranges[0].phys_base = sc->sli_window_base + SLI_PCI_OFFSET +
884 	    sc->ranges[0].pci_base;
885 	sc->ranges[0].flags = SYS_RES_MEMORY;
886 
887 	/* Fill IO window */
888 	sc->ranges[1].pci_base = PCI_IO_BASE;
889 	sc->ranges[1].size = PCI_IO_SIZE;
890 	sc->ranges[1].phys_base = sc->sli_window_base + SLI_PCI_OFFSET +
891 	    sc->ranges[1].pci_base;
892 	sc->ranges[1].flags = SYS_RES_IOPORT;
893 
894 	for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
895 		base = sc->ranges[tuple].pci_base;
896 		size = sc->ranges[tuple].size;
897 		if (size == 0)
898 			continue; /* empty range element */
899 
900 		rman = thunder_pem_get_rman(dev, sc->ranges[tuple].flags, 0);
901 		if (rman != NULL)
902 			error = rman_manage_region(rman, base,
903 			    base + size - 1);
904 		else
905 			error = EINVAL;
906 		if (error) {
907 			device_printf(dev,
908 			    "rman_manage_region() failed. error = %d\n", error);
909 			rman_fini(&sc->mem_rman);
910 			return (error);
911 		}
912 		if (bootverbose) {
913 			device_printf(dev,
914 			    "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx, Flags:0x%jx\n",
915 			    sc->ranges[tuple].pci_base,
916 			    sc->ranges[tuple].phys_base,
917 			    sc->ranges[tuple].size,
918 			    sc->ranges[tuple].flags);
919 		}
920 	}
921 
922 	if (thunder_pem_init(sc)) {
923 		device_printf(dev, "Failure during PEM init\n");
924 		goto fail_io;
925 	}
926 
927 	device_add_child(dev, "pci", -1);
928 
929 	return (bus_generic_attach(dev));
930 
931 fail_io:
932 	rman_fini(&sc->io_rman);
933 fail_mem:
934 	rman_fini(&sc->mem_rman);
935 fail:
936 	bus_free_resource(dev, SYS_RES_MEMORY, sc->reg);
937 	return (ENXIO);
938 }
939 
940 static void
941 thunder_pem_release_all(device_t dev)
942 {
943 	struct thunder_pem_softc *sc;
944 
945 	sc = device_get_softc(dev);
946 
947 	rman_fini(&sc->io_rman);
948 	rman_fini(&sc->mem_rman);
949 
950 	if (sc->reg != NULL)
951 		bus_free_resource(dev, SYS_RES_MEMORY, sc->reg);
952 }
953 
954 static int
955 thunder_pem_detach(device_t dev)
956 {
957 
958 	thunder_pem_release_all(dev);
959 
960 	return (0);
961 }
962