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