xref: /openbsd-src/sys/dev/fdt/dwpcie.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: dwpcie.c,v 1.15 2019/08/26 11:24:03 patrick Exp $	*/
2 /*
3  * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/extent.h>
22 #include <sys/malloc.h>
23 
24 #include <machine/intr.h>
25 #include <machine/bus.h>
26 #include <machine/fdt.h>
27 
28 #include <dev/pci/pcidevs.h>
29 #include <dev/pci/pcireg.h>
30 #include <dev/pci/pcivar.h>
31 #include <dev/pci/ppbreg.h>
32 
33 #include <dev/ofw/openfirm.h>
34 #include <dev/ofw/ofw_clock.h>
35 #include <dev/ofw/ofw_gpio.h>
36 #include <dev/ofw/ofw_misc.h>
37 #include <dev/ofw/ofw_pinctrl.h>
38 #include <dev/ofw/ofw_power.h>
39 #include <dev/ofw/fdt.h>
40 
41 /* Registers */
42 #define PCIE_PORT_LINK_CTRL		0x710
43 #define  PCIE_PORT_LINK_CTRL_LANES_MASK			(0x3f << 16)
44 #define  PCIE_PORT_LINK_CTRL_LANES_1			(0x1 << 16)
45 #define  PCIE_PORT_LINK_CTRL_LANES_2			(0x3 << 16)
46 #define  PCIE_PORT_LINK_CTRL_LANES_4			(0x7 << 16)
47 #define  PCIE_PORT_LINK_CTRL_LANES_8			(0xf << 16)
48 #define PCIE_PHY_DEBUG_R1		0x72c
49 #define  PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING	(1 << 29)
50 #define  PCIE_PHY_DEBUG_R1_XMLH_LINK_UP			(1 << 4)
51 #define PCIE_LINK_WIDTH_SPEED_CTRL	0x80c
52 #define  PCIE_LINK_WIDTH_SPEED_CTRL_LANES_MASK		(0x1f << 8)
53 #define  PCIE_LINK_WIDTH_SPEED_CTRL_LANES_1		(0x1 << 8)
54 #define  PCIE_LINK_WIDTH_SPEED_CTRL_LANES_2		(0x2 << 8)
55 #define  PCIE_LINK_WIDTH_SPEED_CTRL_LANES_4		(0x4 << 8)
56 #define  PCIE_LINK_WIDTH_SPEED_CTRL_LANES_8		(0x8 << 8)
57 #define  PCIE_LINK_WIDTH_SPEED_CTRL_CHANGE		(1 << 17)
58 
59 #define MISC_CONTROL_1		0x8bc
60 #define  MISC_CONTROL_1_DBI_RO_WR_EN	(1 << 0)
61 #define IATU_VIEWPORT		0x900
62 #define  IATU_VIEWPORT_INDEX0		0
63 #define  IATU_VIEWPORT_INDEX1		1
64 #define  IATU_VIEWPORT_INDEX2		2
65 #define IATU_OFFSET_VIEWPORT	0x904
66 #define IATU_OFFSET_UNROLL(x)	(0x200 * (x))
67 #define IATU_REGION_CTRL_1	0x000
68 #define  IATU_REGION_CTRL_1_TYPE_MEM	0
69 #define  IATU_REGION_CTRL_1_TYPE_IO	2
70 #define  IATU_REGION_CTRL_1_TYPE_CFG0	4
71 #define  IATU_REGION_CTRL_1_TYPE_CFG1	5
72 #define IATU_REGION_CTRL_2	0x004
73 #define  IATU_REGION_CTRL_2_REGION_EN	(1U << 31)
74 #define IATU_LWR_BASE_ADDR	0x08
75 #define IATU_UPPER_BASE_ADDR	0x0c
76 #define IATU_LIMIT_ADDR		0x10
77 #define IATU_LWR_TARGET_ADDR	0x14
78 #define IATU_UPPER_TARGET_ADDR	0x18
79 
80 #define PCIE_GLOBAL_CTRL	0x8000
81 #define  PCIE_GLOBAL_CTRL_APP_LTSSM_EN		(1 << 2)
82 #define  PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK	(0xf << 4)
83 #define  PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC	(0x4 << 4)
84 #define PCIE_GLOBAL_STATUS	0x8008
85 #define  PCIE_GLOBAL_STATUS_RDLH_LINK_UP	(1 << 1)
86 #define  PCIE_GLOBAL_STATUS_PHY_LINK_UP		(1 << 9)
87 #define PCIE_PM_STATUS		0x8014
88 #define PCIE_GLOBAL_INT_CAUSE	0x801c
89 #define PCIE_GLOBAL_INT_MASK	0x8020
90 #define  PCIE_GLOBAL_INT_MASK_INT_A		(1 << 9)
91 #define  PCIE_GLOBAL_INT_MASK_INT_B		(1 << 10)
92 #define  PCIE_GLOBAL_INT_MASK_INT_C		(1 << 11)
93 #define  PCIE_GLOBAL_INT_MASK_INT_D		(1 << 12)
94 #define PCIE_ARCACHE_TRC	0x8050
95 #define  PCIE_ARCACHE_TRC_DEFAULT		0x3511
96 #define PCIE_AWCACHE_TRC	0x8054
97 #define  PCIE_AWCACHE_TRC_DEFAULT		0x5311
98 #define PCIE_ARUSER		0x805c
99 #define PCIE_AWUSER		0x8060
100 #define  PCIE_AXUSER_DOMAIN_MASK		(0x3 << 4)
101 #define  PCIE_AXUSER_DOMAIN_INNER_SHARABLE	(0x1 << 4)
102 #define  PCIE_AXUSER_DOMAIN_OUTER_SHARABLE	(0x2 << 4)
103 
104 /* i.MX8MQ registers */
105 #define PCIE_RC_LCR				0x7c
106 #define  PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1		0x1
107 #define  PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2		0x2
108 #define  PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK		0xf
109 #define  PCIE_RC_LCR_L1EL_MASK				(0x7 << 15)
110 #define  PCIE_RC_LCR_L1EL_64US				(0x6 << 15)
111 
112 #define IOMUXC_GPR12				0x30
113 #define  IMX8MQ_GPR_PCIE2_DEVICE_TYPE_MASK		(0xf << 8)
114 #define  IMX8MQ_GPR_PCIE2_DEVICE_TYPE_RC		(0x4 << 8)
115 #define  IMX8MQ_GPR_PCIE1_DEVICE_TYPE_MASK		(0xf << 12)
116 #define  IMX8MQ_GPR_PCIE1_DEVICE_TYPE_RC		(0x4 << 12)
117 #define IOMUXC_GPR14				0x38
118 #define IOMUXC_GPR16				0x40
119 #define  IMX8MQ_GPR_PCIE_REF_USE_PAD			(1 << 9)
120 #define  IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN		(1 << 10)
121 #define  IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE		(1 << 11)
122 
123 #define ANATOP_PLLOUT_CTL			0x74
124 #define  ANATOP_PLLOUT_CTL_CKE				(1 << 4)
125 #define  ANATOP_PLLOUT_CTL_SEL_SYSPLL1			0xb
126 #define  ANATOP_PLLOUT_CTL_SEL_MASK			0xf
127 #define ANATOP_PLLOUT_DIV			0x7c
128 #define  ANATOP_PLLOUT_DIV_SYSPLL1			0x7
129 
130 #define HREAD4(sc, reg)							\
131 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
132 #define HWRITE4(sc, reg, val)						\
133 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
134 #define HSET4(sc, reg, bits)						\
135 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
136 #define HCLR4(sc, reg, bits)						\
137 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
138 
139 struct dwpcie_range {
140 	uint32_t		flags;
141 	uint64_t		pci_base;
142 	uint64_t		phys_base;
143 	uint64_t		size;
144 };
145 
146 struct dwpcie_softc {
147 	struct device		sc_dev;
148 	bus_space_tag_t		sc_iot;
149 	bus_space_handle_t	sc_ioh;
150 	bus_space_handle_t	sc_cfg0_ioh;
151 	bus_space_handle_t	sc_cfg1_ioh;
152 
153 	bus_addr_t		sc_cfg0_base;
154 	bus_size_t		sc_cfg0_size;
155 	bus_addr_t		sc_cfg1_base;
156 	bus_size_t		sc_cfg1_size;
157 	bus_addr_t		sc_io_base;
158 	bus_addr_t		sc_io_bus_addr;
159 	bus_size_t		sc_io_size;
160 	bus_addr_t		sc_mem_base;
161 	bus_addr_t		sc_mem_bus_addr;
162 	bus_size_t		sc_mem_size;
163 
164 	int			sc_node;
165 	int			sc_acells;
166 	int			sc_scells;
167 	int			sc_pacells;
168 	int			sc_pscells;
169 	struct dwpcie_range	*sc_ranges;
170 	int			sc_nranges;
171 
172 	struct bus_space	sc_bus_iot;
173 	struct bus_space	sc_bus_memt;
174 
175 	struct arm64_pci_chipset sc_pc;
176 	int			sc_bus;
177 
178 	int			sc_num_viewport;
179 	bus_addr_t		sc_atu_base;
180 	int			sc_atu_unroll;
181 
182 	void			*sc_ih;
183 };
184 
185 int dwpcie_match(struct device *, void *, void *);
186 void dwpcie_attach(struct device *, struct device *, void *);
187 
188 struct cfattach	dwpcie_ca = {
189 	sizeof (struct dwpcie_softc), dwpcie_match, dwpcie_attach
190 };
191 
192 struct cfdriver dwpcie_cd = {
193 	NULL, "dwpcie", DV_DULL
194 };
195 
196 int
197 dwpcie_match(struct device *parent, void *match, void *aux)
198 {
199 	struct fdt_attach_args *faa = aux;
200 
201 	return (OF_is_compatible(faa->fa_node, "marvell,armada8k-pcie") ||
202 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-pcie"));
203 }
204 
205 void	dwpcie_atu_config(struct dwpcie_softc *, int, int,
206 	    uint64_t, uint64_t, uint64_t);
207 void	dwpcie_link_config(struct dwpcie_softc *);
208 int	dwpcie_link_up(struct dwpcie_softc *);
209 
210 void	dwpcie_armada8k_init(struct dwpcie_softc *);
211 int	dwpcie_armada8k_link_up(struct dwpcie_softc *);
212 int	dwpcie_armada8k_intr(void *);
213 
214 void	dwpcie_imx8mq_init(struct dwpcie_softc *);
215 int	dwpcie_imx8mq_intr(void *);
216 
217 void	dwpcie_attach_hook(struct device *, struct device *,
218 	    struct pcibus_attach_args *);
219 int	dwpcie_bus_maxdevs(void *, int);
220 pcitag_t dwpcie_make_tag(void *, int, int, int);
221 void	dwpcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
222 int	dwpcie_conf_size(void *, pcitag_t);
223 pcireg_t dwpcie_conf_read(void *, pcitag_t, int);
224 void	dwpcie_conf_write(void *, pcitag_t, int, pcireg_t);
225 
226 int	dwpcie_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
227 const char *dwpcie_intr_string(void *, pci_intr_handle_t);
228 void	*dwpcie_intr_establish(void *, pci_intr_handle_t, int,
229 	    int (*)(void *), void *, char *);
230 void	dwpcie_intr_disestablish(void *, void *);
231 
232 void	*dwpcie_armada8k_intr_establish(void *, pci_intr_handle_t, int,
233 	    int (*)(void *), void *, char *);
234 
235 int	dwpcie_bs_iomap(bus_space_tag_t, bus_addr_t, bus_size_t, int,
236 	    bus_space_handle_t *);
237 int	dwpcie_bs_memmap(bus_space_tag_t, bus_addr_t, bus_size_t, int,
238 	    bus_space_handle_t *);
239 
240 void
241 dwpcie_attach(struct device *parent, struct device *self, void *aux)
242 {
243 	struct dwpcie_softc *sc = (struct dwpcie_softc *)self;
244 	struct fdt_attach_args *faa = aux;
245 	struct pcibus_attach_args pba;
246 	bus_addr_t iobase, iolimit;
247 	bus_addr_t membase, memlimit;
248 	uint32_t bus_range[2];
249 	uint32_t *ranges;
250 	int i, j, nranges, rangeslen;
251 	pcireg_t bir, blr, csr;
252 
253 	if (faa->fa_nreg < 2) {
254 		printf(": no registers\n");
255 		return;
256 	}
257 
258 	sc->sc_iot = faa->fa_iot;
259 	sc->sc_node = faa->fa_node;
260 
261 	sc->sc_acells = OF_getpropint(sc->sc_node, "#address-cells",
262 	    faa->fa_acells);
263 	sc->sc_scells = OF_getpropint(sc->sc_node, "#size-cells",
264 	    faa->fa_scells);
265 	sc->sc_pacells = faa->fa_acells;
266 	sc->sc_pscells = faa->fa_scells;
267 
268 	rangeslen = OF_getproplen(sc->sc_node, "ranges");
269 	if (rangeslen <= 0 || (rangeslen % sizeof(uint32_t)) ||
270 	     (rangeslen / sizeof(uint32_t)) % (sc->sc_acells +
271 	     sc->sc_pacells + sc->sc_scells)) {
272 		printf(": invalid ranges property\n");
273 		return;
274 	}
275 
276 	ranges = malloc(rangeslen, M_TEMP, M_WAITOK);
277 	OF_getpropintarray(sc->sc_node, "ranges", ranges,
278 	    rangeslen);
279 
280 	nranges = (rangeslen / sizeof(uint32_t)) /
281 	    (sc->sc_acells + sc->sc_pacells + sc->sc_scells);
282 	sc->sc_ranges = mallocarray(nranges,
283 	    sizeof(struct dwpcie_range), M_TEMP, M_WAITOK);
284 	sc->sc_nranges = nranges;
285 
286 	for (i = 0, j = 0; i < sc->sc_nranges; i++) {
287 		sc->sc_ranges[i].flags = ranges[j++];
288 		sc->sc_ranges[i].pci_base = ranges[j++];
289 		if (sc->sc_acells - 1 == 2) {
290 			sc->sc_ranges[i].pci_base <<= 32;
291 			sc->sc_ranges[i].pci_base |= ranges[j++];
292 		}
293 		sc->sc_ranges[i].phys_base = ranges[j++];
294 		if (sc->sc_pacells == 2) {
295 			sc->sc_ranges[i].phys_base <<= 32;
296 			sc->sc_ranges[i].phys_base |= ranges[j++];
297 		}
298 		sc->sc_ranges[i].size = ranges[j++];
299 		if (sc->sc_scells == 2) {
300 			sc->sc_ranges[i].size <<= 32;
301 			sc->sc_ranges[i].size |= ranges[j++];
302 		}
303 	}
304 
305 	free(ranges, M_TEMP, rangeslen);
306 
307 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
308 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
309 		printf(": can't map ctrl registers\n");
310 		return;
311 	}
312 
313 	sc->sc_cfg0_base = faa->fa_reg[1].addr;
314 	sc->sc_cfg0_size = faa->fa_reg[1].size / 2;
315 	sc->sc_cfg0_base = faa->fa_reg[1].addr + sc->sc_cfg0_size;
316 	sc->sc_cfg1_size = sc->sc_cfg0_size;
317 
318 	if (bus_space_map(sc->sc_iot, sc->sc_cfg0_base,
319 	    sc->sc_cfg1_size, 0, &sc->sc_cfg0_ioh)) {
320 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
321 		printf(": can't map config registers\n");
322 		return;
323 	}
324 
325 	if (bus_space_map(sc->sc_iot, sc->sc_cfg1_base,
326 	    sc->sc_cfg1_size, 0, &sc->sc_cfg1_ioh)) {
327 		bus_space_unmap(sc->sc_iot, sc->sc_cfg0_ioh, sc->sc_cfg0_size);
328 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
329 		printf(": can't map config registers\n");
330 		return;
331 	}
332 
333 	sc->sc_num_viewport = OF_getpropint(sc->sc_node, "num-viewport", 2);
334 
335 	printf("\n");
336 
337 	pinctrl_byname(sc->sc_node, "default");
338 
339 	clock_set_assigned(sc->sc_node);
340 
341 	if (OF_is_compatible(sc->sc_node, "marvell,armada8k-pcie"))
342 		dwpcie_armada8k_init(sc);
343 	if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-pcie"))
344 		dwpcie_imx8mq_init(sc);
345 
346 	if (HREAD4(sc, IATU_VIEWPORT) == 0xffffffff) {
347 		sc->sc_atu_base = 0x300000;
348 		sc->sc_atu_unroll = 1;
349 	}
350 
351 	/* Set up address translation for I/O space. */
352 	sc->sc_io_bus_addr = sc->sc_mem_bus_addr = -1;
353 	for (i = 0; i < sc->sc_nranges; i++) {
354 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x01000000 &&
355 		    sc->sc_ranges[i].size > 0) {
356 			sc->sc_io_base = sc->sc_ranges[i].phys_base;
357 			sc->sc_io_bus_addr = sc->sc_ranges[i].pci_base;
358 			sc->sc_io_size = sc->sc_ranges[i].size;
359 		}
360 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000 &&
361 		    sc->sc_ranges[i].size > 0) {
362 			sc->sc_mem_base = sc->sc_ranges[i].phys_base;
363 			sc->sc_mem_bus_addr = sc->sc_ranges[i].pci_base;
364 			sc->sc_mem_size = sc->sc_ranges[i].size;
365 		}
366 	}
367 
368 	dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX0,
369 	    IATU_REGION_CTRL_1_TYPE_MEM, sc->sc_mem_base,
370 	    sc->sc_mem_bus_addr, sc->sc_mem_size);
371 	if (sc->sc_num_viewport > 2)
372 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX2,
373 		    IATU_REGION_CTRL_1_TYPE_IO, sc->sc_io_base,
374 		    sc->sc_io_bus_addr, sc->sc_io_size);
375 
376 	/* Enable modification of read-only bits. */
377 	HSET4(sc, MISC_CONTROL_1, MISC_CONTROL_1_DBI_RO_WR_EN);
378 
379 	/* A Root Port is a PCI-PCI Bridge. */
380 	HWRITE4(sc, PCI_CLASS_REG,
381 	    PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT |
382 	    PCI_SUBCLASS_BRIDGE_PCI << PCI_SUBCLASS_SHIFT);
383 
384 	/* Clear BAR as U-Boot seems to leave garbage in it. */
385 	HWRITE4(sc, PCI_MAPREG_START, PCI_MAPREG_MEM_TYPE_64BIT);
386 	HWRITE4(sc, PCI_MAPREG_START + 4, 0);
387 
388 	/* Make sure read-only bits are write-protected. */
389 	HCLR4(sc, MISC_CONTROL_1, MISC_CONTROL_1_DBI_RO_WR_EN);
390 
391 	/* Set up bus range. */
392 	if (OF_getpropintarray(sc->sc_node, "bus-range", bus_range,
393 	    sizeof(bus_range)) != sizeof(bus_range) ||
394 	    bus_range[0] >= 32 || bus_range[1] >= 32) {
395 		bus_range[0] = 0;
396 		bus_range[1] = 31;
397 	}
398 	sc->sc_bus = bus_range[0];
399 
400 	/* Initialize bus range. */
401 	bir = bus_range[0];
402 	bir |= ((bus_range[0] + 1) << 8);
403 	bir |= (bus_range[1] << 16);
404 	HWRITE4(sc, PPB_REG_BUSINFO, bir);
405 
406 	/* Initialize I/O window. */
407 	iobase = sc->sc_io_bus_addr;
408 	iolimit = iobase + sc->sc_io_size - 1;
409 	blr = iolimit & PPB_IO_MASK;
410 	blr |= (iobase >> PPB_IO_SHIFT);
411 	HWRITE4(sc, PPB_REG_IOSTATUS, blr);
412 	blr = (iobase & 0xffff0000) >> 16;
413 	blr |= iolimit & 0xffff0000;
414 	HWRITE4(sc, PPB_REG_IO_HI, blr);
415 
416 	/* Initialize memory mapped I/O window. */
417 	membase = sc->sc_mem_bus_addr;
418 	memlimit = membase + sc->sc_mem_size - 1;
419 	blr = memlimit & PPB_MEM_MASK;
420 	blr |= (membase >> PPB_MEM_SHIFT);
421 	HWRITE4(sc, PPB_REG_MEM, blr);
422 
423 	/* Reset prefetchable memory mapped I/O window. */
424 	HWRITE4(sc, PPB_REG_PREFMEM, 0x0000ffff);
425 	HWRITE4(sc, PPB_REG_PREFBASE_HI32, 0);
426 	HWRITE4(sc, PPB_REG_PREFLIM_HI32, 0);
427 
428 	csr = PCI_COMMAND_MASTER_ENABLE;
429 	if (iolimit > iobase)
430 		csr |= PCI_COMMAND_IO_ENABLE;
431 	if (memlimit > membase)
432 		csr |= PCI_COMMAND_MEM_ENABLE;
433 	HWRITE4(sc, PCI_COMMAND_STATUS_REG, csr);
434 
435 	memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot));
436 	sc->sc_bus_iot.bus_private = sc;
437 	sc->sc_bus_iot._space_map = dwpcie_bs_iomap;
438 	memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt));
439 	sc->sc_bus_memt.bus_private = sc;
440 	sc->sc_bus_memt._space_map = dwpcie_bs_memmap;
441 
442 	sc->sc_pc.pc_conf_v = sc;
443 	sc->sc_pc.pc_attach_hook = dwpcie_attach_hook;
444 	sc->sc_pc.pc_bus_maxdevs = dwpcie_bus_maxdevs;
445 	sc->sc_pc.pc_make_tag = dwpcie_make_tag;
446 	sc->sc_pc.pc_decompose_tag = dwpcie_decompose_tag;
447 	sc->sc_pc.pc_conf_size = dwpcie_conf_size;
448 	sc->sc_pc.pc_conf_read = dwpcie_conf_read;
449 	sc->sc_pc.pc_conf_write = dwpcie_conf_write;
450 
451 	sc->sc_pc.pc_intr_v = sc;
452 	sc->sc_pc.pc_intr_map = dwpcie_intr_map;
453 	sc->sc_pc.pc_intr_map_msi = _pci_intr_map_msi;
454 	sc->sc_pc.pc_intr_map_msix = _pci_intr_map_msix;
455 	sc->sc_pc.pc_intr_string = dwpcie_intr_string;
456 	sc->sc_pc.pc_intr_establish = dwpcie_intr_establish;
457 	sc->sc_pc.pc_intr_disestablish = dwpcie_intr_disestablish;
458 
459 	memset(&pba, 0, sizeof(pba));
460 	pba.pba_busname = "pci";
461 	pba.pba_iot = &sc->sc_bus_iot;
462 	pba.pba_memt = &sc->sc_bus_memt;
463 	pba.pba_dmat = faa->fa_dmat;
464 	pba.pba_pc = &sc->sc_pc;
465 	pba.pba_domain = pci_ndomains++;
466 	pba.pba_bus = sc->sc_bus;
467 	if (OF_is_compatible(faa->fa_node, "marvell,armada8k-pcie"))
468 		pba.pba_flags |= PCI_FLAGS_MSI_ENABLED;
469 
470 	config_found(self, &pba, NULL);
471 }
472 
473 void
474 dwpcie_link_config(struct dwpcie_softc *sc)
475 {
476 	uint32_t mode, width, reg;
477 	int lanes;
478 
479 	lanes = OF_getpropint(sc->sc_node, "num-lanes", 0);
480 
481 	switch (lanes) {
482 	case 1:
483 		mode = PCIE_PORT_LINK_CTRL_LANES_1;
484 		width = PCIE_LINK_WIDTH_SPEED_CTRL_LANES_1;
485 		break;
486 	case 2:
487 		mode = PCIE_PORT_LINK_CTRL_LANES_2;
488 		width = PCIE_LINK_WIDTH_SPEED_CTRL_LANES_2;
489 		break;
490 	case 4:
491 		mode = PCIE_PORT_LINK_CTRL_LANES_4;
492 		width = PCIE_LINK_WIDTH_SPEED_CTRL_LANES_4;
493 		break;
494 	case 8:
495 		mode = PCIE_PORT_LINK_CTRL_LANES_8;
496 		width = PCIE_LINK_WIDTH_SPEED_CTRL_LANES_8;
497 		break;
498 	default:
499 		printf("%s: %d lanes not supported\n", __func__, lanes);
500 		return;
501 	}
502 
503 	reg = HREAD4(sc, PCIE_PORT_LINK_CTRL);
504 	reg &= ~PCIE_PORT_LINK_CTRL_LANES_MASK;
505 	reg |= mode;
506 	HWRITE4(sc, PCIE_PORT_LINK_CTRL, reg);
507 
508 	reg = HREAD4(sc, PCIE_LINK_WIDTH_SPEED_CTRL);
509 	reg &= ~PCIE_LINK_WIDTH_SPEED_CTRL_LANES_MASK;
510 	reg |= width;
511 	HWRITE4(sc, PCIE_LINK_WIDTH_SPEED_CTRL, reg);
512 
513 	reg = HREAD4(sc, PCIE_LINK_WIDTH_SPEED_CTRL);
514 	reg |= PCIE_LINK_WIDTH_SPEED_CTRL_CHANGE;
515 	HWRITE4(sc, PCIE_LINK_WIDTH_SPEED_CTRL, reg);
516 }
517 
518 void
519 dwpcie_armada8k_init(struct dwpcie_softc *sc)
520 {
521 	uint32_t reg;
522 	int timo;
523 
524 	clock_enable_all(sc->sc_node);
525 
526 	dwpcie_link_config(sc);
527 
528 	if (!dwpcie_armada8k_link_up(sc)) {
529 		reg = HREAD4(sc, PCIE_GLOBAL_CTRL);
530 		reg &= ~PCIE_GLOBAL_CTRL_APP_LTSSM_EN;
531 		HWRITE4(sc, PCIE_GLOBAL_CTRL, reg);
532 	}
533 
534 	/* Enable Root Complex mode. */
535 	reg = HREAD4(sc, PCIE_GLOBAL_CTRL);
536 	reg &= ~PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK;
537 	reg |= PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC;
538 	HWRITE4(sc, PCIE_GLOBAL_CTRL, reg);
539 
540 	HWRITE4(sc, PCIE_ARCACHE_TRC, PCIE_ARCACHE_TRC_DEFAULT);
541 	HWRITE4(sc, PCIE_AWCACHE_TRC, PCIE_AWCACHE_TRC_DEFAULT);
542 	reg = HREAD4(sc, PCIE_ARUSER);
543 	reg &= ~PCIE_AXUSER_DOMAIN_MASK;
544 	reg |= PCIE_AXUSER_DOMAIN_OUTER_SHARABLE;
545 	HWRITE4(sc, PCIE_ARUSER, reg);
546 	reg = HREAD4(sc, PCIE_AWUSER);
547 	reg &= ~PCIE_AXUSER_DOMAIN_MASK;
548 	reg |= PCIE_AXUSER_DOMAIN_OUTER_SHARABLE;
549 	HWRITE4(sc, PCIE_AWUSER, reg);
550 
551 	if (!dwpcie_armada8k_link_up(sc)) {
552 		reg = HREAD4(sc, PCIE_GLOBAL_CTRL);
553 		reg |= PCIE_GLOBAL_CTRL_APP_LTSSM_EN;
554 		HWRITE4(sc, PCIE_GLOBAL_CTRL, reg);
555 	}
556 
557 	for (timo = 40; timo > 0; timo--) {
558 		if (dwpcie_armada8k_link_up(sc))
559 			break;
560 		delay(1000);
561 	}
562 
563 	sc->sc_ih = fdt_intr_establish(sc->sc_node, IPL_AUDIO | IPL_MPSAFE,
564 	    dwpcie_armada8k_intr, sc, sc->sc_dev.dv_xname);
565 
566 	/* Unmask INTx interrupts. */
567 	HWRITE4(sc, PCIE_GLOBAL_INT_MASK,
568 	    PCIE_GLOBAL_INT_MASK_INT_A | PCIE_GLOBAL_INT_MASK_INT_B |
569 	    PCIE_GLOBAL_INT_MASK_INT_C | PCIE_GLOBAL_INT_MASK_INT_D);
570 }
571 
572 int
573 dwpcie_armada8k_link_up(struct dwpcie_softc *sc)
574 {
575 	uint32_t reg, mask;
576 
577 	mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP;
578 	mask |= PCIE_GLOBAL_STATUS_PHY_LINK_UP;
579 	reg = HREAD4(sc, PCIE_GLOBAL_STATUS);
580 	return ((reg & mask) == mask);
581 }
582 
583 int
584 dwpcie_armada8k_intr(void *arg)
585 {
586 	struct dwpcie_softc *sc = arg;
587 	uint32_t cause;
588 
589 	/* Acknowledge interrupts. */
590 	cause = HREAD4(sc, PCIE_GLOBAL_INT_CAUSE);
591 	HWRITE4(sc, PCIE_GLOBAL_INT_CAUSE, cause);
592 
593 	/* INTx interrupt, so not really ours. */
594 	return 0;
595 }
596 
597 void
598 dwpcie_imx8mq_init(struct dwpcie_softc *sc)
599 {
600 	uint32_t *clkreq_gpio, *disable_gpio, *reset_gpio;
601 	ssize_t clkreq_gpiolen, disable_gpiolen, reset_gpiolen;
602 	struct regmap *anatop, *gpr;
603 	uint32_t off, reg;
604 	int timo;
605 
606 	anatop = regmap_bycompatible("fsl,imx8mq-anatop");
607 	gpr = regmap_bycompatible("fsl,imx8mq-iomuxc-gpr");
608 	KASSERT(anatop != NULL);
609 	KASSERT(gpr != NULL);
610 
611 	clkreq_gpiolen = OF_getproplen(sc->sc_node, "clkreq-gpio");
612 	disable_gpiolen = OF_getproplen(sc->sc_node, "disable-gpio");
613 	reset_gpiolen = OF_getproplen(sc->sc_node, "reset-gpio");
614 
615 	if (clkreq_gpiolen > 0) {
616 		clkreq_gpio = malloc(clkreq_gpiolen, M_TEMP, M_WAITOK);
617 		OF_getpropintarray(sc->sc_node, "clkreq-gpio", clkreq_gpio,
618 		    clkreq_gpiolen);
619 		gpio_controller_config_pin(clkreq_gpio, GPIO_CONFIG_OUTPUT);
620 		gpio_controller_set_pin(clkreq_gpio, 1);
621 	}
622 
623 	if (disable_gpiolen > 0) {
624 		disable_gpio = malloc(disable_gpiolen, M_TEMP, M_WAITOK);
625 		OF_getpropintarray(sc->sc_node, "disable-gpio", disable_gpio,
626 		    disable_gpiolen);
627 		gpio_controller_config_pin(disable_gpio, GPIO_CONFIG_OUTPUT);
628 		gpio_controller_set_pin(disable_gpio, 0);
629 	}
630 
631 	if (reset_gpiolen > 0) {
632 		reset_gpio = malloc(reset_gpiolen, M_TEMP, M_WAITOK);
633 		OF_getpropintarray(sc->sc_node, "reset-gpio", reset_gpio,
634 		    reset_gpiolen);
635 		gpio_controller_config_pin(reset_gpio, GPIO_CONFIG_OUTPUT);
636 		gpio_controller_set_pin(reset_gpio, 1);
637 	}
638 
639 	power_domain_enable(sc->sc_node);
640 	reset_assert(sc->sc_node, "pciephy");
641 	reset_assert(sc->sc_node, "apps");
642 
643 	reg = regmap_read_4(gpr, IOMUXC_GPR12);
644 	if (OF_getpropint(sc->sc_node, "ctrl-id", 0) == 0) {
645 		off = IOMUXC_GPR14;
646 		reg &= ~IMX8MQ_GPR_PCIE1_DEVICE_TYPE_MASK;
647 		reg |= IMX8MQ_GPR_PCIE1_DEVICE_TYPE_RC;
648 	} else {
649 		off = IOMUXC_GPR16;
650 		reg &= ~IMX8MQ_GPR_PCIE2_DEVICE_TYPE_MASK;
651 		reg |= IMX8MQ_GPR_PCIE2_DEVICE_TYPE_RC;
652 	}
653 	regmap_write_4(gpr, IOMUXC_GPR12, reg);
654 
655 	if (OF_getproplen(sc->sc_node, "ext_osc") == 0) {
656 		reg = regmap_read_4(gpr, off);
657 		reg |= IMX8MQ_GPR_PCIE_REF_USE_PAD;
658 		regmap_write_4(gpr, off, reg);
659 	} else {
660 		reg = regmap_read_4(gpr, off);
661 		reg &= ~IMX8MQ_GPR_PCIE_REF_USE_PAD;
662 		regmap_write_4(gpr, off, reg);
663 
664 		regmap_write_4(anatop, ANATOP_PLLOUT_CTL,
665 		    ANATOP_PLLOUT_CTL_CKE | ANATOP_PLLOUT_CTL_SEL_SYSPLL1);
666 		regmap_write_4(anatop, ANATOP_PLLOUT_DIV,
667 		    ANATOP_PLLOUT_DIV_SYSPLL1);
668 	}
669 
670 	clock_enable(sc->sc_node, "pcie_phy");
671 	clock_enable(sc->sc_node, "pcie_bus");
672 	clock_enable(sc->sc_node, "pcie");
673 
674 	/* Allow clocks to stabilize. */
675 	delay(200);
676 
677 	if (reset_gpiolen > 0) {
678 		gpio_controller_set_pin(reset_gpio, 1);
679 		delay(20000);
680 		gpio_controller_set_pin(reset_gpio, 0);
681 		delay(20000);
682 	}
683 
684 	reset_deassert(sc->sc_node, "pciephy");
685 
686 	reg = HREAD4(sc, 0x100000 + PCIE_RC_LCR);
687 	reg &= ~PCIE_RC_LCR_L1EL_MASK;
688 	reg |= PCIE_RC_LCR_L1EL_64US;
689 	HWRITE4(sc, 0x100000 + PCIE_RC_LCR, reg);
690 
691 	dwpcie_link_config(sc);
692 
693 	reg = HREAD4(sc, PCIE_RC_LCR);
694 	reg &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
695 	reg |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
696 	HWRITE4(sc, PCIE_RC_LCR, reg);
697 
698 	reset_deassert(sc->sc_node, "apps");
699 
700 	for (timo = 20000; timo > 0; timo--) {
701 		if (dwpcie_link_up(sc))
702 			break;
703 		delay(10);
704 	}
705 	if (timo == 0)
706 		printf("%s:%d: timeout\n", __func__, __LINE__);
707 
708 	if (OF_getpropint(sc->sc_node, "fsl,max-link-speed", 1) >= 2) {
709 		reg = HREAD4(sc, PCIE_RC_LCR);
710 		reg &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
711 		reg |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
712 		HWRITE4(sc, PCIE_RC_LCR, reg);
713 
714 		reg = HREAD4(sc, PCIE_LINK_WIDTH_SPEED_CTRL);
715 		reg |= PCIE_LINK_WIDTH_SPEED_CTRL_CHANGE;
716 		HWRITE4(sc, PCIE_LINK_WIDTH_SPEED_CTRL, reg);
717 
718 		for (timo = 20000; timo > 0; timo--) {
719 			if (dwpcie_link_up(sc))
720 				break;
721 			delay(10);
722 		}
723 		if (timo == 0)
724 			printf("%s:%d: timeout\n", __func__, __LINE__);
725 	}
726 
727 	sc->sc_ih = fdt_intr_establish(sc->sc_node, IPL_AUDIO | IPL_MPSAFE,
728 	    dwpcie_imx8mq_intr, sc, sc->sc_dev.dv_xname);
729 
730 	/* Unmask INTx interrupts. */
731 	HWRITE4(sc, PCIE_GLOBAL_INT_MASK,
732 	    PCIE_GLOBAL_INT_MASK_INT_A | PCIE_GLOBAL_INT_MASK_INT_B |
733 	    PCIE_GLOBAL_INT_MASK_INT_C | PCIE_GLOBAL_INT_MASK_INT_D);
734 
735 	if (clkreq_gpiolen > 0)
736 		free(clkreq_gpio, M_TEMP, clkreq_gpiolen);
737 	if (disable_gpiolen > 0)
738 		free(disable_gpio, M_TEMP, disable_gpiolen);
739 	if (reset_gpiolen > 0)
740 		free(reset_gpio, M_TEMP, reset_gpiolen);
741 }
742 
743 int
744 dwpcie_imx8mq_intr(void *arg)
745 {
746 	struct dwpcie_softc *sc = arg;
747 	uint32_t cause;
748 
749 	/* Acknowledge interrupts. */
750 	cause = HREAD4(sc, PCIE_GLOBAL_INT_CAUSE);
751 	HWRITE4(sc, PCIE_GLOBAL_INT_CAUSE, cause);
752 
753 	/* INTx interrupt, so not really ours. */
754 	return 0;
755 }
756 
757 void
758 dwpcie_atu_config(struct dwpcie_softc *sc, int index, int type,
759     uint64_t cpu_addr, uint64_t pci_addr, uint64_t size)
760 {
761 	uint32_t reg, off;
762 	int timo;
763 
764 	off = sc->sc_atu_base + IATU_OFFSET_UNROLL(index);
765 	if (!sc->sc_atu_unroll) {
766 		off = IATU_OFFSET_VIEWPORT;
767 		HWRITE4(sc, IATU_VIEWPORT, index);
768 	}
769 
770 	HWRITE4(sc, off + IATU_LWR_BASE_ADDR, cpu_addr);
771 	HWRITE4(sc, off + IATU_UPPER_BASE_ADDR, cpu_addr >> 32);
772 	HWRITE4(sc, off + IATU_LIMIT_ADDR, cpu_addr + size - 1);
773 	HWRITE4(sc, off + IATU_LWR_TARGET_ADDR, pci_addr);
774 	HWRITE4(sc, off + IATU_UPPER_TARGET_ADDR, pci_addr >> 32);
775 	HWRITE4(sc, off + IATU_REGION_CTRL_1, type);
776 	HWRITE4(sc, off + IATU_REGION_CTRL_2, IATU_REGION_CTRL_2_REGION_EN);
777 
778 	for (timo = 5; timo > 0; timo--) {
779 		reg = HREAD4(sc, off + IATU_REGION_CTRL_2);
780 		if (reg & IATU_REGION_CTRL_2_REGION_EN)
781 			break;
782 		delay(9000);
783 	}
784 	if (timo == 0)
785 		printf("%s:%d: timeout\n", __func__, __LINE__);
786 }
787 
788 int
789 dwpcie_link_up(struct dwpcie_softc *sc)
790 {
791 	uint32_t reg;
792 
793 	reg = HREAD4(sc, PCIE_PHY_DEBUG_R1);
794 	if ((reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) != 0 &&
795 	    (reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING) == 0)
796 		return 1;
797 	return 0;
798 }
799 
800 void
801 dwpcie_attach_hook(struct device *parent, struct device *self,
802     struct pcibus_attach_args *pba)
803 {
804 }
805 
806 int
807 dwpcie_bus_maxdevs(void *v, int bus)
808 {
809 	struct dwpcie_softc *sc = v;
810 
811 	if (bus == sc->sc_bus || bus == sc->sc_bus + 1)
812 		return 1;
813 	return 32;
814 }
815 
816 pcitag_t
817 dwpcie_make_tag(void *v, int bus, int device, int function)
818 {
819 	return ((bus << 24) | (device << 19) | (function << 16));
820 }
821 
822 void
823 dwpcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
824 {
825 	if (bp != NULL)
826 		*bp = (tag >> 24) & 0xff;
827 	if (dp != NULL)
828 		*dp = (tag >> 19) & 0x1f;
829 	if (fp != NULL)
830 		*fp = (tag >> 16) & 0x7;
831 }
832 
833 int
834 dwpcie_conf_size(void *v, pcitag_t tag)
835 {
836 	return PCIE_CONFIG_SPACE_SIZE;
837 }
838 
839 pcireg_t
840 dwpcie_conf_read(void *v, pcitag_t tag, int reg)
841 {
842 	struct dwpcie_softc *sc = v;
843 	int bus, dev, fn;
844 	uint32_t ret;
845 
846 	dwpcie_decompose_tag(sc, tag, &bus, &dev, &fn);
847 	if (bus == sc->sc_bus) {
848 		KASSERT(dev == 0);
849 		return HREAD4(sc, tag | reg);
850 	}
851 
852 	if (bus == sc->sc_bus + 1) {
853 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
854 		    IATU_REGION_CTRL_1_TYPE_CFG0,
855 		    sc->sc_cfg0_base, tag, sc->sc_cfg0_size);
856 		ret = bus_space_read_4(sc->sc_iot, sc->sc_cfg0_ioh, reg);
857 	} else {
858 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
859 		    IATU_REGION_CTRL_1_TYPE_CFG1,
860 		    sc->sc_cfg1_base, tag, sc->sc_cfg1_size);
861 		ret = bus_space_read_4(sc->sc_iot, sc->sc_cfg1_ioh, reg);
862 	}
863 	if (sc->sc_num_viewport <= 2)
864 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
865 		    IATU_REGION_CTRL_1_TYPE_IO, sc->sc_io_base,
866 		    sc->sc_io_bus_addr, sc->sc_io_size);
867 
868 	return ret;
869 }
870 
871 void
872 dwpcie_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
873 {
874 	struct dwpcie_softc *sc = v;
875 	int bus, dev, fn;
876 
877 	dwpcie_decompose_tag(sc, tag, &bus, &dev, &fn);
878 	if (bus == sc->sc_bus) {
879 		KASSERT(dev == 0);
880 		HWRITE4(sc, tag | reg, data);
881 		return;
882 	}
883 
884 	if (bus == sc->sc_bus + 1) {
885 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
886 		    IATU_REGION_CTRL_1_TYPE_CFG0,
887 		    sc->sc_cfg0_base, tag, sc->sc_cfg0_size);
888 		bus_space_write_4(sc->sc_iot, sc->sc_cfg0_ioh, reg, data);
889 	} else {
890 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
891 		    IATU_REGION_CTRL_1_TYPE_CFG1,
892 		    sc->sc_cfg1_base, tag, sc->sc_cfg1_size);
893 		bus_space_write_4(sc->sc_iot, sc->sc_cfg1_ioh, reg, data);
894 	}
895 	if (sc->sc_num_viewport <= 2)
896 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
897 		    IATU_REGION_CTRL_1_TYPE_IO, sc->sc_io_base,
898 		    sc->sc_io_bus_addr, sc->sc_io_size);
899 }
900 
901 int
902 dwpcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
903 {
904 	int pin = pa->pa_rawintrpin;
905 
906 	if (pin == 0 || pin > PCI_INTERRUPT_PIN_MAX)
907 		return -1;
908 
909 	if (pa->pa_tag == 0)
910 		return -1;
911 
912 	ihp->ih_pc = pa->pa_pc;
913 	ihp->ih_tag = pa->pa_intrtag;
914 	ihp->ih_intrpin = pa->pa_intrpin;
915 	ihp->ih_type = PCI_INTX;
916 
917 	return 0;
918 }
919 
920 const char *
921 dwpcie_intr_string(void *v, pci_intr_handle_t ih)
922 {
923 	switch (ih.ih_type) {
924 	case PCI_MSI:
925 		return "msi";
926 	case PCI_MSIX:
927 		return "msix";
928 	}
929 
930 	return "intx";
931 }
932 
933 void *
934 dwpcie_intr_establish(void *v, pci_intr_handle_t ih, int level,
935     int (*func)(void *), void *arg, char *name)
936 {
937 	struct dwpcie_softc *sc = v;
938 	void *cookie;
939 
940 	KASSERT(ih.ih_type != PCI_NONE);
941 
942 	if (ih.ih_type != PCI_INTX) {
943 		uint64_t addr, data;
944 
945 		/* Assume hardware passes Requester ID as sideband data. */
946 		data = pci_requester_id(ih.ih_pc, ih.ih_tag);
947 		cookie = fdt_intr_establish_msi(sc->sc_node, &addr,
948 		    &data, level, func, arg, (void *)name);
949 		if (cookie == NULL)
950 			return NULL;
951 
952 		/* TODO: translate address to the PCI device's view */
953 
954 		if (ih.ih_type == PCI_MSIX) {
955 			pci_msix_enable(ih.ih_pc, ih.ih_tag,
956 			    &sc->sc_bus_memt, ih.ih_intrpin, addr, data);
957 		} else
958 			pci_msi_enable(ih.ih_pc, ih.ih_tag, addr, data);
959 	} else {
960 		int bus, dev, fn;
961 		uint32_t reg[4];
962 
963 		dwpcie_decompose_tag(sc, ih.ih_tag, &bus, &dev, &fn);
964 
965 		reg[0] = bus << 16 | dev << 11 | fn << 8;
966 		reg[1] = reg[2] = 0;
967 		reg[3] = ih.ih_intrpin;
968 
969 		cookie = fdt_intr_establish_imap(sc->sc_node, reg,
970 		    sizeof(reg), level, func, arg, name);
971 	}
972 
973 	return cookie;
974 }
975 
976 void
977 dwpcie_intr_disestablish(void *v, void *cookie)
978 {
979 	panic("%s", __func__);
980 }
981 
982 int
983 dwpcie_bs_iomap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
984     int flags, bus_space_handle_t *bshp)
985 {
986 	struct dwpcie_softc *sc = t->bus_private;
987 	int i;
988 
989 	for (i = 0; i < sc->sc_nranges; i++) {
990 		uint64_t pci_start = sc->sc_ranges[i].pci_base;
991 		uint64_t pci_end = pci_start + sc->sc_ranges[i].size;
992 		uint64_t phys_start = sc->sc_ranges[i].phys_base;
993 
994 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x01000000 &&
995 		    addr >= pci_start && addr + size <= pci_end) {
996 			return bus_space_map(sc->sc_iot,
997 			    addr - pci_start + phys_start, size, flags, bshp);
998 		}
999 	}
1000 
1001 	return ENXIO;
1002 }
1003 
1004 int
1005 dwpcie_bs_memmap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
1006     int flags, bus_space_handle_t *bshp)
1007 {
1008 	struct dwpcie_softc *sc = t->bus_private;
1009 	int i;
1010 
1011 	for (i = 0; i < sc->sc_nranges; i++) {
1012 		uint64_t pci_start = sc->sc_ranges[i].pci_base;
1013 		uint64_t pci_end = pci_start + sc->sc_ranges[i].size;
1014 		uint64_t phys_start = sc->sc_ranges[i].phys_base;
1015 
1016 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000 &&
1017 		    addr >= pci_start && addr + size <= pci_end) {
1018 			return bus_space_map(sc->sc_iot,
1019 			    addr - pci_start + phys_start, size, flags, bshp);
1020 		}
1021 	}
1022 
1023 	return ENXIO;
1024 }
1025