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