xref: /openbsd-src/sys/dev/fdt/dwpcie.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /*	$OpenBSD: dwpcie.c,v 1.22 2020/07/14 15:42:19 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 #define  IMX8MM_GPR_PCIE_SSC_EN				(1 << 16)
123 #define  IMX8MM_GPR_PCIE_POWER_OFF			(1 << 17)
124 #define  IMX8MM_GPR_PCIE_CMN_RST			(1 << 18)
125 #define  IMX8MM_GPR_PCIE_AUX_EN				(1 << 19)
126 #define  IMX8MM_GPR_PCIE_REF_CLK_MASK			(0x3 << 24)
127 #define  IMX8MM_GPR_PCIE_REF_CLK_PLL			(0x3 << 24)
128 #define  IMX8MM_GPR_PCIE_REF_CLK_EXT			(0x2 << 24)
129 
130 #define IMX8MM_PCIE_PHY_CMN_REG62			0x188
131 #define  IMX8MM_PCIE_PHY_CMN_REG62_PLL_CLK_OUT			0x08
132 #define IMX8MM_PCIE_PHY_CMN_REG64			0x190
133 #define  IMX8MM_PCIE_PHY_CMN_REG64_AUX_RX_TX_TERM		0x8c
134 #define IMX8MM_PCIE_PHY_CMN_REG75			0x1d4
135 #define  IMX8MM_PCIE_PHY_CMN_REG75_PLL_DONE			0x3
136 #define IMX8MM_PCIE_PHY_TRSV_REG5			0x414
137 #define  IMX8MM_PCIE_PHY_TRSV_REG5_GEN1_DEEMP			0x2d
138 #define IMX8MM_PCIE_PHY_TRSV_REG6			0x418
139 #define  IMX8MM_PCIE_PHY_TRSV_REG6_GEN2_DEEMP			0xf
140 
141 #define ANATOP_PLLOUT_CTL			0x74
142 #define  ANATOP_PLLOUT_CTL_CKE				(1 << 4)
143 #define  ANATOP_PLLOUT_CTL_SEL_SYSPLL1			0xb
144 #define  ANATOP_PLLOUT_CTL_SEL_MASK			0xf
145 #define ANATOP_PLLOUT_DIV			0x7c
146 #define  ANATOP_PLLOUT_DIV_SYSPLL1			0x7
147 
148 #define HREAD4(sc, reg)							\
149 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
150 #define HWRITE4(sc, reg, val)						\
151 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
152 #define HSET4(sc, reg, bits)						\
153 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
154 #define HCLR4(sc, reg, bits)						\
155 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
156 
157 struct dwpcie_range {
158 	uint32_t		flags;
159 	uint64_t		pci_base;
160 	uint64_t		phys_base;
161 	uint64_t		size;
162 };
163 
164 struct dwpcie_softc {
165 	struct device		sc_dev;
166 	bus_space_tag_t		sc_iot;
167 	bus_space_handle_t	sc_ioh;
168 	bus_space_handle_t	sc_cfg0_ioh;
169 	bus_space_handle_t	sc_cfg1_ioh;
170 
171 	bus_addr_t		sc_cfg0_base;
172 	bus_size_t		sc_cfg0_size;
173 	bus_addr_t		sc_cfg1_base;
174 	bus_size_t		sc_cfg1_size;
175 	bus_addr_t		sc_io_base;
176 	bus_addr_t		sc_io_bus_addr;
177 	bus_size_t		sc_io_size;
178 	bus_addr_t		sc_mem_base;
179 	bus_addr_t		sc_mem_bus_addr;
180 	bus_size_t		sc_mem_size;
181 
182 	int			sc_node;
183 	int			sc_acells;
184 	int			sc_scells;
185 	int			sc_pacells;
186 	int			sc_pscells;
187 	struct dwpcie_range	*sc_ranges;
188 	int			sc_nranges;
189 
190 	struct bus_space	sc_bus_iot;
191 	struct bus_space	sc_bus_memt;
192 
193 	struct arm64_pci_chipset sc_pc;
194 	int			sc_bus;
195 
196 	int			sc_num_viewport;
197 	bus_addr_t		sc_atu_base;
198 	int			sc_atu_unroll;
199 
200 	void			*sc_ih;
201 };
202 
203 int dwpcie_match(struct device *, void *, void *);
204 void dwpcie_attach(struct device *, struct device *, void *);
205 
206 struct cfattach	dwpcie_ca = {
207 	sizeof (struct dwpcie_softc), dwpcie_match, dwpcie_attach
208 };
209 
210 struct cfdriver dwpcie_cd = {
211 	NULL, "dwpcie", DV_DULL
212 };
213 
214 int
215 dwpcie_match(struct device *parent, void *match, void *aux)
216 {
217 	struct fdt_attach_args *faa = aux;
218 
219 	return (OF_is_compatible(faa->fa_node, "marvell,armada8k-pcie") ||
220 	    OF_is_compatible(faa->fa_node, "fsl,imx8mm-pcie") ||
221 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-pcie"));
222 }
223 
224 void	dwpcie_atu_config(struct dwpcie_softc *, int, int,
225 	    uint64_t, uint64_t, uint64_t);
226 void	dwpcie_link_config(struct dwpcie_softc *);
227 int	dwpcie_link_up(struct dwpcie_softc *);
228 
229 int	dwpcie_armada8k_init(struct dwpcie_softc *);
230 int	dwpcie_armada8k_link_up(struct dwpcie_softc *);
231 int	dwpcie_armada8k_intr(void *);
232 
233 int	dwpcie_imx8mq_init(struct dwpcie_softc *);
234 int	dwpcie_imx8mq_intr(void *);
235 
236 void	dwpcie_attach_hook(struct device *, struct device *,
237 	    struct pcibus_attach_args *);
238 int	dwpcie_bus_maxdevs(void *, int);
239 pcitag_t dwpcie_make_tag(void *, int, int, int);
240 void	dwpcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
241 int	dwpcie_conf_size(void *, pcitag_t);
242 pcireg_t dwpcie_conf_read(void *, pcitag_t, int);
243 void	dwpcie_conf_write(void *, pcitag_t, int, pcireg_t);
244 
245 int	dwpcie_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
246 const char *dwpcie_intr_string(void *, pci_intr_handle_t);
247 void	*dwpcie_intr_establish(void *, pci_intr_handle_t, int,
248 	    struct cpu_info *, int (*)(void *), void *, char *);
249 void	dwpcie_intr_disestablish(void *, void *);
250 
251 int	dwpcie_bs_iomap(bus_space_tag_t, bus_addr_t, bus_size_t, int,
252 	    bus_space_handle_t *);
253 int	dwpcie_bs_memmap(bus_space_tag_t, bus_addr_t, bus_size_t, int,
254 	    bus_space_handle_t *);
255 
256 void
257 dwpcie_attach(struct device *parent, struct device *self, void *aux)
258 {
259 	struct dwpcie_softc *sc = (struct dwpcie_softc *)self;
260 	struct fdt_attach_args *faa = aux;
261 	struct pcibus_attach_args pba;
262 	bus_addr_t iobase, iolimit;
263 	bus_addr_t membase, memlimit;
264 	uint32_t bus_range[2];
265 	uint32_t *ranges;
266 	int i, j, nranges, rangeslen;
267 	pcireg_t bir, blr, csr;
268 	int error = 0;
269 
270 	if (faa->fa_nreg < 2) {
271 		printf(": no registers\n");
272 		return;
273 	}
274 
275 	sc->sc_iot = faa->fa_iot;
276 	sc->sc_node = faa->fa_node;
277 
278 	sc->sc_acells = OF_getpropint(sc->sc_node, "#address-cells",
279 	    faa->fa_acells);
280 	sc->sc_scells = OF_getpropint(sc->sc_node, "#size-cells",
281 	    faa->fa_scells);
282 	sc->sc_pacells = faa->fa_acells;
283 	sc->sc_pscells = faa->fa_scells;
284 
285 	rangeslen = OF_getproplen(sc->sc_node, "ranges");
286 	if (rangeslen <= 0 || (rangeslen % sizeof(uint32_t)) ||
287 	     (rangeslen / sizeof(uint32_t)) % (sc->sc_acells +
288 	     sc->sc_pacells + sc->sc_scells)) {
289 		printf(": invalid ranges property\n");
290 		return;
291 	}
292 
293 	ranges = malloc(rangeslen, M_TEMP, M_WAITOK);
294 	OF_getpropintarray(sc->sc_node, "ranges", ranges,
295 	    rangeslen);
296 
297 	nranges = (rangeslen / sizeof(uint32_t)) /
298 	    (sc->sc_acells + sc->sc_pacells + sc->sc_scells);
299 	sc->sc_ranges = mallocarray(nranges,
300 	    sizeof(struct dwpcie_range), M_TEMP, M_WAITOK);
301 	sc->sc_nranges = nranges;
302 
303 	for (i = 0, j = 0; i < sc->sc_nranges; i++) {
304 		sc->sc_ranges[i].flags = ranges[j++];
305 		sc->sc_ranges[i].pci_base = ranges[j++];
306 		if (sc->sc_acells - 1 == 2) {
307 			sc->sc_ranges[i].pci_base <<= 32;
308 			sc->sc_ranges[i].pci_base |= ranges[j++];
309 		}
310 		sc->sc_ranges[i].phys_base = ranges[j++];
311 		if (sc->sc_pacells == 2) {
312 			sc->sc_ranges[i].phys_base <<= 32;
313 			sc->sc_ranges[i].phys_base |= ranges[j++];
314 		}
315 		sc->sc_ranges[i].size = ranges[j++];
316 		if (sc->sc_scells == 2) {
317 			sc->sc_ranges[i].size <<= 32;
318 			sc->sc_ranges[i].size |= ranges[j++];
319 		}
320 	}
321 
322 	free(ranges, M_TEMP, rangeslen);
323 
324 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
325 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
326 		free(sc->sc_ranges, M_TEMP, sc->sc_nranges *
327 		    sizeof(struct dwpcie_range));
328 		printf(": can't map ctrl registers\n");
329 		return;
330 	}
331 
332 	sc->sc_cfg0_base = faa->fa_reg[1].addr;
333 	sc->sc_cfg0_size = faa->fa_reg[1].size / 2;
334 	sc->sc_cfg0_base = faa->fa_reg[1].addr + sc->sc_cfg0_size;
335 	sc->sc_cfg1_size = sc->sc_cfg0_size;
336 
337 	if (bus_space_map(sc->sc_iot, sc->sc_cfg0_base,
338 	    sc->sc_cfg1_size, 0, &sc->sc_cfg0_ioh)) {
339 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
340 		free(sc->sc_ranges, M_TEMP, sc->sc_nranges *
341 		    sizeof(struct dwpcie_range));
342 		printf(": can't map config registers\n");
343 		return;
344 	}
345 
346 	if (bus_space_map(sc->sc_iot, sc->sc_cfg1_base,
347 	    sc->sc_cfg1_size, 0, &sc->sc_cfg1_ioh)) {
348 		bus_space_unmap(sc->sc_iot, sc->sc_cfg0_ioh, sc->sc_cfg0_size);
349 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
350 		free(sc->sc_ranges, M_TEMP, sc->sc_nranges *
351 		    sizeof(struct dwpcie_range));
352 		printf(": can't map config registers\n");
353 		return;
354 	}
355 
356 	sc->sc_num_viewport = OF_getpropint(sc->sc_node, "num-viewport", 2);
357 
358 	printf("\n");
359 
360 	pinctrl_byname(sc->sc_node, "default");
361 
362 	clock_set_assigned(sc->sc_node);
363 
364 	if (OF_is_compatible(sc->sc_node, "marvell,armada8k-pcie"))
365 		error = dwpcie_armada8k_init(sc);
366 	if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-pcie") ||
367 	    OF_is_compatible(sc->sc_node, "fsl,imx8mq-pcie"))
368 		error = dwpcie_imx8mq_init(sc);
369 	if (error != 0) {
370 		bus_space_unmap(sc->sc_iot, sc->sc_cfg1_ioh, sc->sc_cfg1_size);
371 		bus_space_unmap(sc->sc_iot, sc->sc_cfg0_ioh, sc->sc_cfg0_size);
372 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
373 		free(sc->sc_ranges, M_TEMP, sc->sc_nranges *
374 		    sizeof(struct dwpcie_range));
375 		printf("%s: can't initialize hardware\n",
376 		    sc->sc_dev.dv_xname);
377 		return;
378 	}
379 
380 	if (HREAD4(sc, IATU_VIEWPORT) == 0xffffffff) {
381 		sc->sc_atu_base = 0x300000;
382 		sc->sc_atu_unroll = 1;
383 	}
384 
385 	/* Set up address translation for I/O space. */
386 	sc->sc_io_bus_addr = sc->sc_mem_bus_addr = -1;
387 	for (i = 0; i < sc->sc_nranges; i++) {
388 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x01000000 &&
389 		    sc->sc_ranges[i].size > 0) {
390 			sc->sc_io_base = sc->sc_ranges[i].phys_base;
391 			sc->sc_io_bus_addr = sc->sc_ranges[i].pci_base;
392 			sc->sc_io_size = sc->sc_ranges[i].size;
393 		}
394 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000 &&
395 		    sc->sc_ranges[i].size > 0) {
396 			sc->sc_mem_base = sc->sc_ranges[i].phys_base;
397 			sc->sc_mem_bus_addr = sc->sc_ranges[i].pci_base;
398 			sc->sc_mem_size = sc->sc_ranges[i].size;
399 		}
400 	}
401 
402 	dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX0,
403 	    IATU_REGION_CTRL_1_TYPE_MEM, sc->sc_mem_base,
404 	    sc->sc_mem_bus_addr, sc->sc_mem_size);
405 	if (sc->sc_num_viewport > 2)
406 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX2,
407 		    IATU_REGION_CTRL_1_TYPE_IO, sc->sc_io_base,
408 		    sc->sc_io_bus_addr, sc->sc_io_size);
409 
410 	/* Enable modification of read-only bits. */
411 	HSET4(sc, MISC_CONTROL_1, MISC_CONTROL_1_DBI_RO_WR_EN);
412 
413 	/* A Root Port is a PCI-PCI Bridge. */
414 	HWRITE4(sc, PCI_CLASS_REG,
415 	    PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT |
416 	    PCI_SUBCLASS_BRIDGE_PCI << PCI_SUBCLASS_SHIFT);
417 
418 	/* Clear BAR as U-Boot seems to leave garbage in it. */
419 	HWRITE4(sc, PCI_MAPREG_START, PCI_MAPREG_MEM_TYPE_64BIT);
420 	HWRITE4(sc, PCI_MAPREG_START + 4, 0);
421 
422 	/* Make sure read-only bits are write-protected. */
423 	HCLR4(sc, MISC_CONTROL_1, MISC_CONTROL_1_DBI_RO_WR_EN);
424 
425 	/* Set up bus range. */
426 	if (OF_getpropintarray(sc->sc_node, "bus-range", bus_range,
427 	    sizeof(bus_range)) != sizeof(bus_range) ||
428 	    bus_range[0] >= 32 || bus_range[1] >= 32) {
429 		bus_range[0] = 0;
430 		bus_range[1] = 31;
431 	}
432 	sc->sc_bus = bus_range[0];
433 
434 	/* Initialize bus range. */
435 	bir = bus_range[0];
436 	bir |= ((bus_range[0] + 1) << 8);
437 	bir |= (bus_range[1] << 16);
438 	HWRITE4(sc, PPB_REG_BUSINFO, bir);
439 
440 	/* Initialize I/O window. */
441 	iobase = sc->sc_io_bus_addr;
442 	iolimit = iobase + sc->sc_io_size - 1;
443 	blr = iolimit & PPB_IO_MASK;
444 	blr |= (iobase >> PPB_IO_SHIFT);
445 	HWRITE4(sc, PPB_REG_IOSTATUS, blr);
446 	blr = (iobase & 0xffff0000) >> 16;
447 	blr |= iolimit & 0xffff0000;
448 	HWRITE4(sc, PPB_REG_IO_HI, blr);
449 
450 	/* Initialize memory mapped I/O window. */
451 	membase = sc->sc_mem_bus_addr;
452 	memlimit = membase + sc->sc_mem_size - 1;
453 	blr = memlimit & PPB_MEM_MASK;
454 	blr |= (membase >> PPB_MEM_SHIFT);
455 	HWRITE4(sc, PPB_REG_MEM, blr);
456 
457 	/* Reset prefetchable memory mapped I/O window. */
458 	HWRITE4(sc, PPB_REG_PREFMEM, 0x0000ffff);
459 	HWRITE4(sc, PPB_REG_PREFBASE_HI32, 0);
460 	HWRITE4(sc, PPB_REG_PREFLIM_HI32, 0);
461 
462 	csr = PCI_COMMAND_MASTER_ENABLE;
463 	if (iolimit > iobase)
464 		csr |= PCI_COMMAND_IO_ENABLE;
465 	if (memlimit > membase)
466 		csr |= PCI_COMMAND_MEM_ENABLE;
467 	HWRITE4(sc, PCI_COMMAND_STATUS_REG, csr);
468 
469 	memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot));
470 	sc->sc_bus_iot.bus_private = sc;
471 	sc->sc_bus_iot._space_map = dwpcie_bs_iomap;
472 	memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt));
473 	sc->sc_bus_memt.bus_private = sc;
474 	sc->sc_bus_memt._space_map = dwpcie_bs_memmap;
475 
476 	sc->sc_pc.pc_conf_v = sc;
477 	sc->sc_pc.pc_attach_hook = dwpcie_attach_hook;
478 	sc->sc_pc.pc_bus_maxdevs = dwpcie_bus_maxdevs;
479 	sc->sc_pc.pc_make_tag = dwpcie_make_tag;
480 	sc->sc_pc.pc_decompose_tag = dwpcie_decompose_tag;
481 	sc->sc_pc.pc_conf_size = dwpcie_conf_size;
482 	sc->sc_pc.pc_conf_read = dwpcie_conf_read;
483 	sc->sc_pc.pc_conf_write = dwpcie_conf_write;
484 
485 	sc->sc_pc.pc_intr_v = sc;
486 	sc->sc_pc.pc_intr_map = dwpcie_intr_map;
487 	sc->sc_pc.pc_intr_map_msi = _pci_intr_map_msi;
488 	sc->sc_pc.pc_intr_map_msix = _pci_intr_map_msix;
489 	sc->sc_pc.pc_intr_string = dwpcie_intr_string;
490 	sc->sc_pc.pc_intr_establish = dwpcie_intr_establish;
491 	sc->sc_pc.pc_intr_disestablish = dwpcie_intr_disestablish;
492 
493 	memset(&pba, 0, sizeof(pba));
494 	pba.pba_busname = "pci";
495 	pba.pba_iot = &sc->sc_bus_iot;
496 	pba.pba_memt = &sc->sc_bus_memt;
497 	pba.pba_dmat = faa->fa_dmat;
498 	pba.pba_pc = &sc->sc_pc;
499 	pba.pba_domain = pci_ndomains++;
500 	pba.pba_bus = sc->sc_bus;
501 	if (OF_is_compatible(faa->fa_node, "marvell,armada8k-pcie"))
502 		pba.pba_flags |= PCI_FLAGS_MSI_ENABLED;
503 
504 	config_found(self, &pba, NULL);
505 }
506 
507 void
508 dwpcie_link_config(struct dwpcie_softc *sc)
509 {
510 	uint32_t mode, width, reg;
511 	int lanes;
512 
513 	lanes = OF_getpropint(sc->sc_node, "num-lanes", 0);
514 
515 	switch (lanes) {
516 	case 1:
517 		mode = PCIE_PORT_LINK_CTRL_LANES_1;
518 		width = PCIE_LINK_WIDTH_SPEED_CTRL_LANES_1;
519 		break;
520 	case 2:
521 		mode = PCIE_PORT_LINK_CTRL_LANES_2;
522 		width = PCIE_LINK_WIDTH_SPEED_CTRL_LANES_2;
523 		break;
524 	case 4:
525 		mode = PCIE_PORT_LINK_CTRL_LANES_4;
526 		width = PCIE_LINK_WIDTH_SPEED_CTRL_LANES_4;
527 		break;
528 	case 8:
529 		mode = PCIE_PORT_LINK_CTRL_LANES_8;
530 		width = PCIE_LINK_WIDTH_SPEED_CTRL_LANES_8;
531 		break;
532 	default:
533 		printf("%s: %d lanes not supported\n", __func__, lanes);
534 		return;
535 	}
536 
537 	reg = HREAD4(sc, PCIE_PORT_LINK_CTRL);
538 	reg &= ~PCIE_PORT_LINK_CTRL_LANES_MASK;
539 	reg |= mode;
540 	HWRITE4(sc, PCIE_PORT_LINK_CTRL, reg);
541 
542 	reg = HREAD4(sc, PCIE_LINK_WIDTH_SPEED_CTRL);
543 	reg &= ~PCIE_LINK_WIDTH_SPEED_CTRL_LANES_MASK;
544 	reg |= width;
545 	HWRITE4(sc, PCIE_LINK_WIDTH_SPEED_CTRL, reg);
546 
547 	reg = HREAD4(sc, PCIE_LINK_WIDTH_SPEED_CTRL);
548 	reg |= PCIE_LINK_WIDTH_SPEED_CTRL_CHANGE;
549 	HWRITE4(sc, PCIE_LINK_WIDTH_SPEED_CTRL, reg);
550 }
551 
552 int
553 dwpcie_armada8k_init(struct dwpcie_softc *sc)
554 {
555 	uint32_t reg;
556 	int timo;
557 
558 	clock_enable_all(sc->sc_node);
559 
560 	dwpcie_link_config(sc);
561 
562 	if (!dwpcie_armada8k_link_up(sc)) {
563 		reg = HREAD4(sc, PCIE_GLOBAL_CTRL);
564 		reg &= ~PCIE_GLOBAL_CTRL_APP_LTSSM_EN;
565 		HWRITE4(sc, PCIE_GLOBAL_CTRL, reg);
566 	}
567 
568 	/* Enable Root Complex mode. */
569 	reg = HREAD4(sc, PCIE_GLOBAL_CTRL);
570 	reg &= ~PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK;
571 	reg |= PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC;
572 	HWRITE4(sc, PCIE_GLOBAL_CTRL, reg);
573 
574 	HWRITE4(sc, PCIE_ARCACHE_TRC, PCIE_ARCACHE_TRC_DEFAULT);
575 	HWRITE4(sc, PCIE_AWCACHE_TRC, PCIE_AWCACHE_TRC_DEFAULT);
576 	reg = HREAD4(sc, PCIE_ARUSER);
577 	reg &= ~PCIE_AXUSER_DOMAIN_MASK;
578 	reg |= PCIE_AXUSER_DOMAIN_OUTER_SHARABLE;
579 	HWRITE4(sc, PCIE_ARUSER, reg);
580 	reg = HREAD4(sc, PCIE_AWUSER);
581 	reg &= ~PCIE_AXUSER_DOMAIN_MASK;
582 	reg |= PCIE_AXUSER_DOMAIN_OUTER_SHARABLE;
583 	HWRITE4(sc, PCIE_AWUSER, reg);
584 
585 	if (!dwpcie_armada8k_link_up(sc)) {
586 		reg = HREAD4(sc, PCIE_GLOBAL_CTRL);
587 		reg |= PCIE_GLOBAL_CTRL_APP_LTSSM_EN;
588 		HWRITE4(sc, PCIE_GLOBAL_CTRL, reg);
589 	}
590 
591 	for (timo = 40; timo > 0; timo--) {
592 		if (dwpcie_armada8k_link_up(sc))
593 			break;
594 		delay(1000);
595 	}
596 	if (timo == 0)
597 		return ETIMEDOUT;
598 
599 	sc->sc_ih = fdt_intr_establish(sc->sc_node, IPL_AUDIO | IPL_MPSAFE,
600 	    dwpcie_armada8k_intr, sc, sc->sc_dev.dv_xname);
601 
602 	/* Unmask INTx interrupts. */
603 	HWRITE4(sc, PCIE_GLOBAL_INT_MASK,
604 	    PCIE_GLOBAL_INT_MASK_INT_A | PCIE_GLOBAL_INT_MASK_INT_B |
605 	    PCIE_GLOBAL_INT_MASK_INT_C | PCIE_GLOBAL_INT_MASK_INT_D);
606 
607 	return 0;
608 }
609 
610 int
611 dwpcie_armada8k_link_up(struct dwpcie_softc *sc)
612 {
613 	uint32_t reg, mask;
614 
615 	mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP;
616 	mask |= PCIE_GLOBAL_STATUS_PHY_LINK_UP;
617 	reg = HREAD4(sc, PCIE_GLOBAL_STATUS);
618 	return ((reg & mask) == mask);
619 }
620 
621 int
622 dwpcie_armada8k_intr(void *arg)
623 {
624 	struct dwpcie_softc *sc = arg;
625 	uint32_t cause;
626 
627 	/* Acknowledge interrupts. */
628 	cause = HREAD4(sc, PCIE_GLOBAL_INT_CAUSE);
629 	HWRITE4(sc, PCIE_GLOBAL_INT_CAUSE, cause);
630 
631 	/* INTx interrupt, so not really ours. */
632 	return 0;
633 }
634 
635 int
636 dwpcie_imx8mq_init(struct dwpcie_softc *sc)
637 {
638 	uint32_t *clkreq_gpio, *disable_gpio, *reset_gpio;
639 	ssize_t clkreq_gpiolen, disable_gpiolen, reset_gpiolen;
640 	struct regmap *anatop, *gpr, *phy;
641 	uint32_t off, reg;
642 	int error, timo;
643 
644 	if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-pcie")) {
645 		anatop = regmap_bycompatible("fsl,imx8mm-anatop");
646 		gpr = regmap_bycompatible("fsl,imx8mm-iomuxc-gpr");
647 		phy = regmap_bycompatible("fsl,imx7d-pcie-phy");
648 		KASSERT(phy != NULL);
649 	} else {
650 		anatop = regmap_bycompatible("fsl,imx8mq-anatop");
651 		gpr = regmap_bycompatible("fsl,imx8mq-iomuxc-gpr");
652 	}
653 	KASSERT(anatop != NULL);
654 	KASSERT(gpr != NULL);
655 
656 	clkreq_gpiolen = OF_getproplen(sc->sc_node, "clkreq-gpio");
657 	disable_gpiolen = OF_getproplen(sc->sc_node, "disable-gpio");
658 	reset_gpiolen = OF_getproplen(sc->sc_node, "reset-gpio");
659 
660 	if (clkreq_gpiolen > 0) {
661 		clkreq_gpio = malloc(clkreq_gpiolen, M_TEMP, M_WAITOK);
662 		OF_getpropintarray(sc->sc_node, "clkreq-gpio", clkreq_gpio,
663 		    clkreq_gpiolen);
664 		gpio_controller_config_pin(clkreq_gpio, GPIO_CONFIG_OUTPUT);
665 		gpio_controller_set_pin(clkreq_gpio, 1);
666 	}
667 
668 	if (disable_gpiolen > 0) {
669 		disable_gpio = malloc(disable_gpiolen, M_TEMP, M_WAITOK);
670 		OF_getpropintarray(sc->sc_node, "disable-gpio", disable_gpio,
671 		    disable_gpiolen);
672 		gpio_controller_config_pin(disable_gpio, GPIO_CONFIG_OUTPUT);
673 		gpio_controller_set_pin(disable_gpio, 0);
674 	}
675 
676 	if (reset_gpiolen > 0) {
677 		reset_gpio = malloc(reset_gpiolen, M_TEMP, M_WAITOK);
678 		OF_getpropintarray(sc->sc_node, "reset-gpio", reset_gpio,
679 		    reset_gpiolen);
680 		gpio_controller_config_pin(reset_gpio, GPIO_CONFIG_OUTPUT);
681 		gpio_controller_set_pin(reset_gpio, 1);
682 	}
683 
684 	power_domain_enable(sc->sc_node);
685 	reset_assert(sc->sc_node, "pciephy");
686 	reset_assert(sc->sc_node, "apps");
687 
688 	reg = regmap_read_4(gpr, IOMUXC_GPR12);
689 	if (OF_getpropint(sc->sc_node, "ctrl-id", 0) == 0) {
690 		off = IOMUXC_GPR14;
691 		reg &= ~IMX8MQ_GPR_PCIE1_DEVICE_TYPE_MASK;
692 		reg |= IMX8MQ_GPR_PCIE1_DEVICE_TYPE_RC;
693 	} else {
694 		off = IOMUXC_GPR16;
695 		reg &= ~IMX8MQ_GPR_PCIE2_DEVICE_TYPE_MASK;
696 		reg |= IMX8MQ_GPR_PCIE2_DEVICE_TYPE_RC;
697 	}
698 	regmap_write_4(gpr, IOMUXC_GPR12, reg);
699 
700 	if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-pcie")) {
701 		if (OF_getproplen(sc->sc_node, "ext_osc") == 0 ||
702 		    OF_getpropint(sc->sc_node, "ext_osc", 0)) {
703 			reg = regmap_read_4(gpr, off);
704 			reg &= ~(IMX8MQ_GPR_PCIE_REF_USE_PAD |
705 			    IMX8MM_GPR_PCIE_SSC_EN |
706 			    IMX8MM_GPR_PCIE_POWER_OFF |
707 			    IMX8MM_GPR_PCIE_REF_CLK_MASK);
708 			reg |= (IMX8MM_GPR_PCIE_AUX_EN |
709 			    IMX8MM_GPR_PCIE_REF_CLK_EXT);
710 			regmap_write_4(gpr, off, reg);
711 			delay(100);
712 			reg = regmap_read_4(gpr, off);
713 			reg |= IMX8MM_GPR_PCIE_CMN_RST;
714 			regmap_write_4(gpr, off, reg);
715 			delay(200);
716 		} else {
717 			reg = regmap_read_4(gpr, off);
718 			reg &= ~(IMX8MQ_GPR_PCIE_REF_USE_PAD |
719 			    IMX8MM_GPR_PCIE_SSC_EN |
720 			    IMX8MM_GPR_PCIE_POWER_OFF |
721 			    IMX8MM_GPR_PCIE_REF_CLK_MASK);
722 			reg |= (IMX8MM_GPR_PCIE_AUX_EN |
723 			    IMX8MM_GPR_PCIE_REF_CLK_PLL);
724 			regmap_write_4(gpr, off, reg);
725 			delay(100);
726 			regmap_write_4(phy, IMX8MM_PCIE_PHY_CMN_REG62,
727 			    IMX8MM_PCIE_PHY_CMN_REG62_PLL_CLK_OUT);
728 			regmap_write_4(phy, IMX8MM_PCIE_PHY_CMN_REG64,
729 			    IMX8MM_PCIE_PHY_CMN_REG64_AUX_RX_TX_TERM);
730 			reg = regmap_read_4(gpr, off);
731 			reg |= IMX8MM_GPR_PCIE_CMN_RST;
732 			regmap_write_4(gpr, off, reg);
733 			delay(200);
734 			regmap_write_4(phy, IMX8MM_PCIE_PHY_TRSV_REG5,
735 			    IMX8MM_PCIE_PHY_TRSV_REG5_GEN1_DEEMP);
736 			regmap_write_4(phy, IMX8MM_PCIE_PHY_TRSV_REG6,
737 			    IMX8MM_PCIE_PHY_TRSV_REG6_GEN2_DEEMP);
738 		}
739 	} else {
740 		if (OF_getproplen(sc->sc_node, "ext_osc") == 0 ||
741 		    OF_getpropint(sc->sc_node, "ext_osc", 0)) {
742 			reg = regmap_read_4(gpr, off);
743 			reg |= IMX8MQ_GPR_PCIE_REF_USE_PAD;
744 			regmap_write_4(gpr, off, reg);
745 		} else {
746 			reg = regmap_read_4(gpr, off);
747 			reg &= ~IMX8MQ_GPR_PCIE_REF_USE_PAD;
748 			regmap_write_4(gpr, off, reg);
749 
750 			regmap_write_4(anatop, ANATOP_PLLOUT_CTL,
751 			    ANATOP_PLLOUT_CTL_CKE |
752 			    ANATOP_PLLOUT_CTL_SEL_SYSPLL1);
753 			regmap_write_4(anatop, ANATOP_PLLOUT_DIV,
754 			    ANATOP_PLLOUT_DIV_SYSPLL1);
755 		}
756 	}
757 
758 	clock_enable(sc->sc_node, "pcie_phy");
759 	clock_enable(sc->sc_node, "pcie_bus");
760 	clock_enable(sc->sc_node, "pcie");
761 	clock_enable(sc->sc_node, "pcie_aux");
762 
763 	/* Allow clocks to stabilize. */
764 	delay(200);
765 
766 	if (reset_gpiolen > 0) {
767 		gpio_controller_set_pin(reset_gpio, 1);
768 		delay(100000);
769 		gpio_controller_set_pin(reset_gpio, 0);
770 	}
771 
772 	reset_deassert(sc->sc_node, "pciephy");
773 
774 	if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-pcie")) {
775 		for (timo = 2000; timo > 0; timo--) {
776 			if (regmap_read_4(phy, IMX8MM_PCIE_PHY_CMN_REG75) ==
777 			    IMX8MM_PCIE_PHY_CMN_REG75_PLL_DONE)
778 				break;
779 			delay(10);
780 		}
781 		if (timo == 0) {
782 			error = ETIMEDOUT;
783 			goto err;
784 		}
785 	}
786 
787 	reg = HREAD4(sc, 0x100000 + PCIE_RC_LCR);
788 	reg &= ~PCIE_RC_LCR_L1EL_MASK;
789 	reg |= PCIE_RC_LCR_L1EL_64US;
790 	HWRITE4(sc, 0x100000 + PCIE_RC_LCR, reg);
791 
792 	dwpcie_link_config(sc);
793 
794 	reg = HREAD4(sc, PCIE_RC_LCR);
795 	reg &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
796 	reg |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
797 	HWRITE4(sc, PCIE_RC_LCR, reg);
798 
799 	reset_deassert(sc->sc_node, "apps");
800 
801 	for (timo = 20000; timo > 0; timo--) {
802 		if (dwpcie_link_up(sc))
803 			break;
804 		delay(10);
805 	}
806 	if (timo == 0) {
807 		error = ETIMEDOUT;
808 		goto err;
809 	}
810 
811 	if (OF_getpropint(sc->sc_node, "fsl,max-link-speed", 1) >= 2) {
812 		reg = HREAD4(sc, PCIE_RC_LCR);
813 		reg &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
814 		reg |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
815 		HWRITE4(sc, PCIE_RC_LCR, reg);
816 
817 		reg = HREAD4(sc, PCIE_LINK_WIDTH_SPEED_CTRL);
818 		reg |= PCIE_LINK_WIDTH_SPEED_CTRL_CHANGE;
819 		HWRITE4(sc, PCIE_LINK_WIDTH_SPEED_CTRL, reg);
820 
821 		for (timo = 20000; timo > 0; timo--) {
822 			if (dwpcie_link_up(sc))
823 				break;
824 			delay(10);
825 		}
826 		if (timo == 0) {
827 			error = ETIMEDOUT;
828 			goto err;
829 		}
830 	}
831 
832 	sc->sc_ih = fdt_intr_establish(sc->sc_node, IPL_AUDIO | IPL_MPSAFE,
833 	    dwpcie_imx8mq_intr, sc, sc->sc_dev.dv_xname);
834 
835 	/* Unmask INTx interrupts. */
836 	HWRITE4(sc, PCIE_GLOBAL_INT_MASK,
837 	    PCIE_GLOBAL_INT_MASK_INT_A | PCIE_GLOBAL_INT_MASK_INT_B |
838 	    PCIE_GLOBAL_INT_MASK_INT_C | PCIE_GLOBAL_INT_MASK_INT_D);
839 
840 	error = 0;
841 err:
842 	if (clkreq_gpiolen > 0)
843 		free(clkreq_gpio, M_TEMP, clkreq_gpiolen);
844 	if (disable_gpiolen > 0)
845 		free(disable_gpio, M_TEMP, disable_gpiolen);
846 	if (reset_gpiolen > 0)
847 		free(reset_gpio, M_TEMP, reset_gpiolen);
848 	return error;
849 }
850 
851 int
852 dwpcie_imx8mq_intr(void *arg)
853 {
854 	struct dwpcie_softc *sc = arg;
855 	uint32_t cause;
856 
857 	/* Acknowledge interrupts. */
858 	cause = HREAD4(sc, PCIE_GLOBAL_INT_CAUSE);
859 	HWRITE4(sc, PCIE_GLOBAL_INT_CAUSE, cause);
860 
861 	/* INTx interrupt, so not really ours. */
862 	return 0;
863 }
864 
865 void
866 dwpcie_atu_config(struct dwpcie_softc *sc, int index, int type,
867     uint64_t cpu_addr, uint64_t pci_addr, uint64_t size)
868 {
869 	uint32_t reg, off;
870 	int timo;
871 
872 	off = sc->sc_atu_base + IATU_OFFSET_UNROLL(index);
873 	if (!sc->sc_atu_unroll) {
874 		off = IATU_OFFSET_VIEWPORT;
875 		HWRITE4(sc, IATU_VIEWPORT, index);
876 	}
877 
878 	HWRITE4(sc, off + IATU_LWR_BASE_ADDR, cpu_addr);
879 	HWRITE4(sc, off + IATU_UPPER_BASE_ADDR, cpu_addr >> 32);
880 	HWRITE4(sc, off + IATU_LIMIT_ADDR, cpu_addr + size - 1);
881 	HWRITE4(sc, off + IATU_LWR_TARGET_ADDR, pci_addr);
882 	HWRITE4(sc, off + IATU_UPPER_TARGET_ADDR, pci_addr >> 32);
883 	HWRITE4(sc, off + IATU_REGION_CTRL_1, type);
884 	HWRITE4(sc, off + IATU_REGION_CTRL_2, IATU_REGION_CTRL_2_REGION_EN);
885 
886 	for (timo = 5; timo > 0; timo--) {
887 		reg = HREAD4(sc, off + IATU_REGION_CTRL_2);
888 		if (reg & IATU_REGION_CTRL_2_REGION_EN)
889 			break;
890 		delay(9000);
891 	}
892 	if (timo == 0)
893 		printf("%s:%d: timeout\n", __func__, __LINE__);
894 }
895 
896 int
897 dwpcie_link_up(struct dwpcie_softc *sc)
898 {
899 	uint32_t reg;
900 
901 	reg = HREAD4(sc, PCIE_PHY_DEBUG_R1);
902 	if ((reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) != 0 &&
903 	    (reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING) == 0)
904 		return 1;
905 	return 0;
906 }
907 
908 void
909 dwpcie_attach_hook(struct device *parent, struct device *self,
910     struct pcibus_attach_args *pba)
911 {
912 }
913 
914 int
915 dwpcie_bus_maxdevs(void *v, int bus)
916 {
917 	struct dwpcie_softc *sc = v;
918 
919 	if (bus == sc->sc_bus || bus == sc->sc_bus + 1)
920 		return 1;
921 	return 32;
922 }
923 
924 pcitag_t
925 dwpcie_make_tag(void *v, int bus, int device, int function)
926 {
927 	return ((bus << 24) | (device << 19) | (function << 16));
928 }
929 
930 void
931 dwpcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
932 {
933 	if (bp != NULL)
934 		*bp = (tag >> 24) & 0xff;
935 	if (dp != NULL)
936 		*dp = (tag >> 19) & 0x1f;
937 	if (fp != NULL)
938 		*fp = (tag >> 16) & 0x7;
939 }
940 
941 int
942 dwpcie_conf_size(void *v, pcitag_t tag)
943 {
944 	return PCIE_CONFIG_SPACE_SIZE;
945 }
946 
947 pcireg_t
948 dwpcie_conf_read(void *v, pcitag_t tag, int reg)
949 {
950 	struct dwpcie_softc *sc = v;
951 	int bus, dev, fn;
952 	uint32_t ret;
953 
954 	dwpcie_decompose_tag(sc, tag, &bus, &dev, &fn);
955 	if (bus == sc->sc_bus) {
956 		KASSERT(dev == 0);
957 		return HREAD4(sc, tag | reg);
958 	}
959 
960 	if (bus == sc->sc_bus + 1) {
961 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
962 		    IATU_REGION_CTRL_1_TYPE_CFG0,
963 		    sc->sc_cfg0_base, tag, sc->sc_cfg0_size);
964 		ret = bus_space_read_4(sc->sc_iot, sc->sc_cfg0_ioh, reg);
965 	} else {
966 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
967 		    IATU_REGION_CTRL_1_TYPE_CFG1,
968 		    sc->sc_cfg1_base, tag, sc->sc_cfg1_size);
969 		ret = bus_space_read_4(sc->sc_iot, sc->sc_cfg1_ioh, reg);
970 	}
971 	if (sc->sc_num_viewport <= 2)
972 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
973 		    IATU_REGION_CTRL_1_TYPE_IO, sc->sc_io_base,
974 		    sc->sc_io_bus_addr, sc->sc_io_size);
975 
976 	return ret;
977 }
978 
979 void
980 dwpcie_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
981 {
982 	struct dwpcie_softc *sc = v;
983 	int bus, dev, fn;
984 
985 	dwpcie_decompose_tag(sc, tag, &bus, &dev, &fn);
986 	if (bus == sc->sc_bus) {
987 		KASSERT(dev == 0);
988 		HWRITE4(sc, tag | reg, data);
989 		return;
990 	}
991 
992 	if (bus == sc->sc_bus + 1) {
993 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
994 		    IATU_REGION_CTRL_1_TYPE_CFG0,
995 		    sc->sc_cfg0_base, tag, sc->sc_cfg0_size);
996 		bus_space_write_4(sc->sc_iot, sc->sc_cfg0_ioh, reg, data);
997 	} else {
998 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
999 		    IATU_REGION_CTRL_1_TYPE_CFG1,
1000 		    sc->sc_cfg1_base, tag, sc->sc_cfg1_size);
1001 		bus_space_write_4(sc->sc_iot, sc->sc_cfg1_ioh, reg, data);
1002 	}
1003 	if (sc->sc_num_viewport <= 2)
1004 		dwpcie_atu_config(sc, IATU_VIEWPORT_INDEX1,
1005 		    IATU_REGION_CTRL_1_TYPE_IO, sc->sc_io_base,
1006 		    sc->sc_io_bus_addr, sc->sc_io_size);
1007 }
1008 
1009 int
1010 dwpcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
1011 {
1012 	int pin = pa->pa_rawintrpin;
1013 
1014 	if (pin == 0 || pin > PCI_INTERRUPT_PIN_MAX)
1015 		return -1;
1016 
1017 	if (pa->pa_tag == 0)
1018 		return -1;
1019 
1020 	ihp->ih_pc = pa->pa_pc;
1021 	ihp->ih_tag = pa->pa_intrtag;
1022 	ihp->ih_intrpin = pa->pa_intrpin;
1023 	ihp->ih_type = PCI_INTX;
1024 
1025 	return 0;
1026 }
1027 
1028 const char *
1029 dwpcie_intr_string(void *v, pci_intr_handle_t ih)
1030 {
1031 	switch (ih.ih_type) {
1032 	case PCI_MSI:
1033 		return "msi";
1034 	case PCI_MSIX:
1035 		return "msix";
1036 	}
1037 
1038 	return "intx";
1039 }
1040 
1041 void *
1042 dwpcie_intr_establish(void *v, pci_intr_handle_t ih, int level,
1043     struct cpu_info *ci, int (*func)(void *), void *arg, char *name)
1044 {
1045 	struct dwpcie_softc *sc = v;
1046 	void *cookie;
1047 
1048 	KASSERT(ih.ih_type != PCI_NONE);
1049 
1050 	if (ih.ih_type != PCI_INTX) {
1051 		uint64_t addr, data;
1052 
1053 		/* Assume hardware passes Requester ID as sideband data. */
1054 		data = pci_requester_id(ih.ih_pc, ih.ih_tag);
1055 		cookie = fdt_intr_establish_msi_cpu(sc->sc_node, &addr,
1056 		    &data, level, ci, func, arg, (void *)name);
1057 		if (cookie == NULL)
1058 			return NULL;
1059 
1060 		/* TODO: translate address to the PCI device's view */
1061 
1062 		if (ih.ih_type == PCI_MSIX) {
1063 			pci_msix_enable(ih.ih_pc, ih.ih_tag,
1064 			    &sc->sc_bus_memt, ih.ih_intrpin, addr, data);
1065 		} else
1066 			pci_msi_enable(ih.ih_pc, ih.ih_tag, addr, data);
1067 	} else {
1068 		int bus, dev, fn;
1069 		uint32_t reg[4];
1070 
1071 		dwpcie_decompose_tag(sc, ih.ih_tag, &bus, &dev, &fn);
1072 
1073 		reg[0] = bus << 16 | dev << 11 | fn << 8;
1074 		reg[1] = reg[2] = 0;
1075 		reg[3] = ih.ih_intrpin;
1076 
1077 		cookie = fdt_intr_establish_imap_cpu(sc->sc_node, reg,
1078 		    sizeof(reg), level, ci, func, arg, name);
1079 	}
1080 
1081 	return cookie;
1082 }
1083 
1084 void
1085 dwpcie_intr_disestablish(void *v, void *cookie)
1086 {
1087 	panic("%s", __func__);
1088 }
1089 
1090 int
1091 dwpcie_bs_iomap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
1092     int flags, bus_space_handle_t *bshp)
1093 {
1094 	struct dwpcie_softc *sc = t->bus_private;
1095 	int i;
1096 
1097 	for (i = 0; i < sc->sc_nranges; i++) {
1098 		uint64_t pci_start = sc->sc_ranges[i].pci_base;
1099 		uint64_t pci_end = pci_start + sc->sc_ranges[i].size;
1100 		uint64_t phys_start = sc->sc_ranges[i].phys_base;
1101 
1102 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x01000000 &&
1103 		    addr >= pci_start && addr + size <= pci_end) {
1104 			return bus_space_map(sc->sc_iot,
1105 			    addr - pci_start + phys_start, size, flags, bshp);
1106 		}
1107 	}
1108 
1109 	return ENXIO;
1110 }
1111 
1112 int
1113 dwpcie_bs_memmap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
1114     int flags, bus_space_handle_t *bshp)
1115 {
1116 	struct dwpcie_softc *sc = t->bus_private;
1117 	int i;
1118 
1119 	for (i = 0; i < sc->sc_nranges; i++) {
1120 		uint64_t pci_start = sc->sc_ranges[i].pci_base;
1121 		uint64_t pci_end = pci_start + sc->sc_ranges[i].size;
1122 		uint64_t phys_start = sc->sc_ranges[i].phys_base;
1123 
1124 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000 &&
1125 		    addr >= pci_start && addr + size <= pci_end) {
1126 			return bus_space_map(sc->sc_iot,
1127 			    addr - pci_start + phys_start, size, flags, bshp);
1128 		}
1129 	}
1130 
1131 	return ENXIO;
1132 }
1133