1/*	$NetBSD: imxpcie.c,v 1.5 2024/06/02 13:28:45 andvar Exp $	*/
2
3/*
4 * Copyright (c) 2019  Genetec Corporation.  All rights reserved.
5 * Written by Hashimoto Kenichi for Genetec Corporation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * i.MX6 On-Chip PCI Express Controller
31 */
32
33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: imxpcie.c,v 1.5 2024/06/02 13:28:45 andvar Exp $");
35
36#include "opt_pci.h"
37#include "opt_fdt.h"
38
39#include "pci.h"
40#include "locators.h"
41
42#define	_INTR_PRIVATE
43
44#include <sys/bus.h>
45#include <sys/device.h>
46#include <sys/intr.h>
47#include <sys/systm.h>
48#include <sys/param.h>
49#include <sys/kernel.h>
50#include <sys/extent.h>
51#include <sys/queue.h>
52#include <sys/mutex.h>
53#include <sys/kmem.h>
54
55#include <machine/frame.h>
56#include <arm/cpufunc.h>
57
58#include <dev/pci/pcireg.h>
59#include <dev/pci/pcivar.h>
60#include <dev/pci/pciconf.h>
61#include <dev/clk/clk_backend.h>
62
63#include <arm/imx/imxpciereg.h>
64#include <arm/imx/imxpcievar.h>
65#include <arm/nxp/imx6_iomuxreg.h>
66
67#define PCIE_CONF_LOCK(s)	(s) = disable_interrupts(I32_bit)
68#define PCIE_CONF_UNLOCK(s)	restore_interrupts((s))
69
70#define PCIE_READ(sc, reg)					\
71	bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, reg)
72#define PCIE_WRITE(sc, reg, val)				\
73	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, reg, val)
74
75static void imxpcie_init(pci_chipset_tag_t, void *);
76static void imxpcie_setup(struct imxpcie_softc * const);
77
78static void imxpcie_attach_hook(device_t, device_t, struct pcibus_attach_args *);
79static int imxpcie_bus_maxdevs(void *, int);
80static pcitag_t imxpcie_make_tag(void *, int, int, int);
81static void imxpcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
82static pcireg_t imxpcie_conf_read(void *, pcitag_t, int);
83static void imxpcie_conf_write(void *, pcitag_t, int, pcireg_t);
84#ifdef __HAVE_PCI_CONF_HOOK
85static int imxpcie_conf_hook(void *, int, int, int, pcireg_t);
86#endif
87static void imxpcie_conf_interrupt(void *, int, int, int, int, int *);
88
89static int imxpcie_intr_map(const struct pci_attach_args *, pci_intr_handle_t *);
90static const char *imxpcie_intr_string(void *, pci_intr_handle_t, char *, size_t);
91const struct evcnt *imxpcie_intr_evcnt(void *, pci_intr_handle_t);
92static void * imxpcie_intr_establish(void *, pci_intr_handle_t, int,
93    int (*)(void *), void *, const char *);
94static void imxpcie_intr_disestablish(void *, void *);
95
96static int
97imxpcie_linkup_status(struct imxpcie_softc *sc)
98{
99	return PCIE_READ(sc, PCIE_PL_DEBUG1) & PCIE_PL_DEBUG1_XMLH_LINK_UP;
100}
101
102static int
103imxpcie_valid_device(struct imxpcie_softc *sc, int bus, int dev)
104{
105	if (bus != 0 && !imxpcie_linkup_status(sc))
106		return 0;
107	if (bus <= 1 && dev > 0)
108		return 0;
109
110	return 1;
111}
112
113static int
114imxpcie_init_phy(struct imxpcie_softc *sc)
115{
116	uint32_t v;
117
118	/* initialize IOMUX */
119	v = sc->sc_gpr_read(sc, IOMUX_GPR12);
120	v &= ~IOMUX_GPR12_APP_LTSSM_ENABLE;
121	sc->sc_gpr_write(sc, IOMUX_GPR12, v);
122
123	v &= ~IOMUX_GPR12_LOS_LEVEL;
124	v |= __SHIFTIN(9, IOMUX_GPR12_LOS_LEVEL);
125	sc->sc_gpr_write(sc, IOMUX_GPR12, v);
126
127	v = 0;
128	v |= __SHIFTIN(0x7f, IOMUX_GPR8_PCS_TX_SWING_LOW);
129	v |= __SHIFTIN(0x7f, IOMUX_GPR8_PCS_TX_SWING_FULL);
130	v |= __SHIFTIN(20, IOMUX_GPR8_PCS_TX_DEEMPH_GEN2_6DB);
131	v |= __SHIFTIN(20, IOMUX_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB);
132	v |= __SHIFTIN(20, IOMUX_GPR8_PCS_TX_DEEMPH_GEN1);
133	sc->sc_gpr_write(sc, IOMUX_GPR8, v);
134
135	v = sc->sc_gpr_read(sc, IOMUX_GPR12);
136	v &= ~IOMUX_GPR12_DEVICE_TYPE;
137	v |= IOMUX_GPR12_DEVICE_TYPE_PCIE_RC;
138	sc->sc_gpr_write(sc, IOMUX_GPR12, v);
139
140	return 0;
141}
142
143static int
144imxpcie_phy_wait_ack(struct imxpcie_softc *sc, int ack)
145{
146	uint32_t v;
147	int timeout;
148
149	for (timeout = 10; timeout > 0; --timeout) {
150		v = PCIE_READ(sc, PCIE_PL_PHY_STATUS);
151		if (!!(v & PCIE_PL_PHY_STATUS_ACK) == !!ack)
152			return 0;
153		delay(1);
154	}
155
156	return -1;
157}
158
159static int
160imxpcie_phy_addr(struct imxpcie_softc *sc, uint32_t addr)
161{
162	uint32_t v;
163
164	v = __SHIFTIN(addr, PCIE_PL_PHY_CTRL_DATA);
165	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, v);
166
167	v |= PCIE_PL_PHY_CTRL_CAP_ADR;
168	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, v);
169
170	if (imxpcie_phy_wait_ack(sc, 1))
171		return -1;
172
173	v = __SHIFTIN(addr, PCIE_PL_PHY_CTRL_DATA);
174	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, v);
175
176	if (imxpcie_phy_wait_ack(sc, 0))
177		return -1;
178
179	return 0;
180}
181
182static int
183imxpcie_phy_write(struct imxpcie_softc *sc, uint32_t addr, uint16_t data)
184{
185	/* write address */
186	if (imxpcie_phy_addr(sc, addr) != 0)
187		return -1;
188
189	/* store data */
190	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, __SHIFTIN(data, PCIE_PL_PHY_CTRL_DATA));
191
192	/* assert CAP_DAT and wait ack */
193	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, __SHIFTIN(data, PCIE_PL_PHY_CTRL_DATA) | PCIE_PL_PHY_CTRL_CAP_DAT);
194	if (imxpcie_phy_wait_ack(sc, 1))
195		return -1;
196
197	/* deassert CAP_DAT and wait ack */
198	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, __SHIFTIN(data, PCIE_PL_PHY_CTRL_DATA));
199	if (imxpcie_phy_wait_ack(sc, 0))
200		return -1;
201
202	/* assert WR and wait ack */
203	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, PCIE_PL_PHY_CTRL_WR);
204	if (imxpcie_phy_wait_ack(sc, 1))
205		return -1;
206
207	/* deassert WR and wait ack */
208	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, __SHIFTIN(data, PCIE_PL_PHY_CTRL_DATA));
209	if (imxpcie_phy_wait_ack(sc, 0))
210		return -1;
211
212	/* done */
213	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, 0);
214
215	return 0;
216}
217
218static int
219imxpcie_phy_read(struct imxpcie_softc *sc, uint32_t addr)
220{
221	uint32_t v;
222
223	/* write address */
224	if (imxpcie_phy_addr(sc, addr) != 0)
225		return -1;
226
227	/* assert RD */
228	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, PCIE_PL_PHY_CTRL_RD);
229	if (imxpcie_phy_wait_ack(sc, 1))
230		return -1;
231
232	/* read data */
233	v = __SHIFTOUT(PCIE_READ(sc, PCIE_PL_PHY_STATUS),
234	    PCIE_PL_PHY_STATUS_DATA);
235
236	/* deassert RD */
237	PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, 0);
238	if (imxpcie_phy_wait_ack(sc, 0))
239		return -1;
240
241	return v;
242}
243
244static int
245imxpcie_assert_core_reset(struct imxpcie_softc *sc)
246{
247	uint32_t gpr1 = sc->sc_gpr_read(sc, IOMUX_GPR1);
248
249	if (sc->sc_have_sw_reset) {
250		gpr1 |= IOMUX_GPR1_PCIE_SW_RST;
251		sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
252	} else {
253		uint32_t gpr12 = sc->sc_gpr_read(sc, IOMUX_GPR12);
254
255		/* already enabled by bootloader */
256		if ((gpr1 & IOMUX_GPR1_REF_SSP_EN) &&
257		    (gpr12 & IOMUX_GPR12_APP_LTSSM_ENABLE)) {
258			uint32_t v = PCIE_READ(sc, PCIE_PL_PFLR);
259			v &= ~PCIE_PL_PFLR_LINK_STATE;
260			v |= PCIE_PL_PFLR_FORCE_LINK;
261			PCIE_WRITE(sc, PCIE_PL_PFLR, v);
262
263			gpr12 &= ~IOMUX_GPR12_APP_LTSSM_ENABLE;
264			sc->sc_gpr_write(sc, IOMUX_GPR12, gpr12);
265		}
266	}
267
268	gpr1 |= IOMUX_GPR1_TEST_POWERDOWN;
269	sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
270	gpr1 &= ~IOMUX_GPR1_REF_SSP_EN;
271	sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
272
273	return 0;
274}
275
276static int
277imxpcie_deassert_core_reset(struct imxpcie_softc *sc)
278{
279	int error;
280
281	error = clk_enable(sc->sc_clk_pcie);
282	if (error) {
283		aprint_error_dev(sc->sc_dev, "couldn't enable pcie: %d\n", error);
284		return error;
285	}
286
287	if (sc->sc_ext_osc) {
288		error = clk_enable(sc->sc_clk_pcie_ext);
289		if (error) {
290			aprint_error_dev(sc->sc_dev, "couldn't enable ext: %d\n", error);
291			return error;
292		}
293	} else {
294		error = clk_enable(sc->sc_clk_pcie_bus);
295		if (error) {
296			aprint_error_dev(sc->sc_dev, "couldn't enable pcie_bus: %d\n",
297			    error);
298			return error;
299		}
300	}
301
302	error = clk_enable(sc->sc_clk_pcie_phy);
303	if (error) {
304		aprint_error_dev(sc->sc_dev, "couldn't enable pcie_ref: %d\n", error);
305		return error;
306	}
307
308	uint32_t gpr1 = sc->sc_gpr_read(sc, IOMUX_GPR1);
309
310	delay(50 * 1000);
311
312	gpr1 &= ~IOMUX_GPR1_TEST_POWERDOWN;
313	sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
314	delay(10);
315	gpr1 |= IOMUX_GPR1_REF_SSP_EN;
316	sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
317
318	delay(50 * 1000);
319
320	/* Reset */
321	if (sc->sc_reset != NULL)
322		sc->sc_reset(sc);
323
324	if (sc->sc_have_sw_reset) {
325		gpr1 &= ~IOMUX_GPR1_PCIE_SW_RST;
326		sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
327		delay(200);
328	}
329
330	uint64_t rate;
331	if (sc->sc_ext_osc)
332		rate = clk_get_rate(sc->sc_clk_pcie_ext);
333	else
334		rate = clk_get_rate(sc->sc_clk_pcie_phy);
335	aprint_normal_dev(sc->sc_dev, "PCIe ref clk %d MHz\n", (int)(rate / 1000 / 1000));
336
337	int mult;
338	int div;
339	if (rate == 100000000) {
340		mult = 25;
341		div = 0;
342	} else if (rate == 125000000) {
343		mult = 40;
344		div = 1;
345	} else if (rate == 200000000) {
346		mult = 25;
347		div = 1;
348	} else {
349		return -1;
350	}
351
352	uint32_t val;
353	val = imxpcie_phy_read(sc, PCIE_PHY_MPLL_OVRD_IN_LO);
354	val &= ~MPLL_MULTIPLIER;
355	val |= __SHIFTIN(mult, MPLL_MULTIPLIER);
356	val |= MPLL_MULTIPLIER_OVRD;
357	imxpcie_phy_write(sc, PCIE_PHY_MPLL_OVRD_IN_LO, val);
358
359	val = imxpcie_phy_read(sc, PCIE_PHY_ATEOVRD);
360	val &= ~REF_CLKDIV2;
361	val |= __SHIFTIN(div, REF_CLKDIV2);
362	val |= ATEOVRD_EN;
363	imxpcie_phy_write(sc, PCIE_PHY_ATEOVRD, val);
364
365	return 0;
366}
367
368static int
369imxpcie_wait_for_link(struct imxpcie_softc *sc)
370{
371#define LINKUP_RETRY	20000
372	for (int retry = LINKUP_RETRY; retry > 0; --retry) {
373		if (!imxpcie_linkup_status(sc)) {
374			delay(10);
375			continue;
376		}
377
378		uint32_t valid = imxpcie_phy_read(sc, PCIE_PHY_RX_ASIC_OUT) &
379		    PCIE_PHY_RX_ASIC_OUT_VALID;
380		uint32_t ltssm = __SHIFTOUT(PCIE_READ(sc, PCIE_PL_DEBUG0),
381		    PCIE_PL_DEBUG0_XMLH_LTSSM_STATE);
382
383		if ((ltssm == 0x0d) && !valid) {
384			aprint_normal_dev(sc->sc_dev, "resetting PCIe phy\n");
385
386			uint32_t v = imxpcie_phy_read(sc, PCIE_PHY_RX_OVRD_IN_LO);
387			v |= PCIE_PHY_RX_OVRD_IN_LO_RX_PLL_EN_OVRD;
388			v |= PCIE_PHY_RX_OVRD_IN_LO_RX_DATA_EN_OVRD;
389			imxpcie_phy_write(sc, PCIE_PHY_RX_OVRD_IN_LO, v);
390
391			delay(3000);
392
393			v = imxpcie_phy_read(sc, PCIE_PHY_RX_OVRD_IN_LO);
394			v &= ~PCIE_PHY_RX_OVRD_IN_LO_RX_PLL_EN_OVRD;
395			v &= ~PCIE_PHY_RX_OVRD_IN_LO_RX_DATA_EN_OVRD;
396			imxpcie_phy_write(sc, PCIE_PHY_RX_OVRD_IN_LO, v);
397		}
398
399		return 0;
400	}
401
402	aprint_error_dev(sc->sc_dev, "Link Up failed.\n");
403
404	return -1;
405}
406
407static int
408imxpcie_wait_for_changespeed(struct imxpcie_softc *sc)
409{
410#define CHANGESPEED_RETRY	200
411	for (int retry = CHANGESPEED_RETRY; retry > 0; --retry) {
412		uint32_t v = PCIE_READ(sc, PCIE_PL_G2CR);
413		if (!(v & PCIE_PL_G2CR_DIRECTED_SPEED_CHANGE))
414			return 0;
415		delay(100);
416	}
417
418	aprint_error_dev(sc->sc_dev, "Speed change timeout.\n");
419
420	return -1;
421}
422
423static void
424imxpcie_linkup(struct imxpcie_softc *sc)
425{
426	uint32_t v;
427	int ret;
428
429	imxpcie_assert_core_reset(sc);
430	imxpcie_init_phy(sc);
431	imxpcie_deassert_core_reset(sc);
432
433	imxpcie_setup(sc);
434
435	/* GEN1 Operation */
436	v = PCIE_READ(sc, PCIE_RC_LCR);
437	v &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS;
438	v |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
439	PCIE_WRITE(sc, PCIE_RC_LCR, v);
440
441	/* Link Up */
442	v = sc->sc_gpr_read(sc, IOMUX_GPR12);
443	v |= IOMUX_GPR12_APP_LTSSM_ENABLE;
444	sc->sc_gpr_write(sc, IOMUX_GPR12, v);
445
446	ret = imxpcie_wait_for_link(sc);
447	if (ret)
448		goto error;
449
450	/* Allow Gen2 mode */
451	v = PCIE_READ(sc, PCIE_RC_LCR);
452	v &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS;
453	v |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
454	PCIE_WRITE(sc, PCIE_RC_LCR, v);
455
456	/* Change speed */
457	v = PCIE_READ(sc, PCIE_PL_G2CR);
458	v |= PCIE_PL_G2CR_DIRECTED_SPEED_CHANGE;
459	PCIE_WRITE(sc, PCIE_PL_G2CR, v);
460
461	ret = imxpcie_wait_for_changespeed(sc);
462	if (ret)
463		goto error;
464
465	ret = imxpcie_wait_for_link(sc);
466	if (ret)
467		goto error;
468
469	v = PCIE_READ(sc, PCIE_RC_LCSR);
470	aprint_normal_dev(sc->sc_dev, "LinkUp, Gen %d\n",
471	    (int)__SHIFTOUT(v, PCIE_RC_LCSR_LINK_SPEED));
472
473	return;
474
475error:
476	aprint_error_dev(sc->sc_dev, "PCIE_PL_DEBUG0,1 = %08x, %08x\n",
477	    PCIE_READ(sc, PCIE_PL_DEBUG0), PCIE_READ(sc, PCIE_PL_DEBUG1));
478
479	return;
480}
481
482void
483imxpcie_attach_common(struct imxpcie_softc * const sc)
484{
485	struct pcibus_attach_args pba;
486
487	if (bus_space_map(sc->sc_iot, sc->sc_root_addr, sc->sc_root_size, 0,
488		&sc->sc_root_ioh)) {
489		aprint_error_dev(sc->sc_dev, "Cannot map root config\n");
490		return;
491	}
492
493	imxpcie_linkup(sc);
494
495	TAILQ_INIT(&sc->sc_intrs);
496	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
497
498	imxpcie_init(&sc->sc_pc, sc);
499
500	if (sc->sc_pci_netbsd_configure != NULL)
501		sc->sc_pci_netbsd_configure(sc);
502
503	memset(&pba, 0, sizeof(pba));
504	pba.pba_flags = PCI_FLAGS_MEM_OKAY |
505	    PCI_FLAGS_IO_OKAY;
506	pba.pba_iot = sc->sc_iot;
507	pba.pba_memt = sc->sc_iot;
508	pba.pba_dmat = sc->sc_dmat;
509	pba.pba_pc = &sc->sc_pc;
510	pba.pba_bus = 0;
511
512	config_found(sc->sc_dev, &pba, pcibusprint,
513	    CFARGS(.devhandle = device_handle(sc->sc_dev)));
514}
515
516int
517imxpcie_intr(void *priv)
518{
519	struct imxpcie_softc *sc = priv;
520	struct imxpcie_ih *pcie_ih;
521
522	for (int i = 0; i < 8; i++) {
523		uint32_t v = PCIE_READ(sc, PCIE_PL_MSICIN_STATUS + i * 0xC);
524		int bit;
525		while ((bit = ffs(v) - 1) >= 0) {
526			PCIE_WRITE(sc, PCIE_PL_MSICIN_STATUS + i * 0xC,
527			    __BIT(bit));
528			v &= ~__BIT(bit);
529		}
530	}
531
532	mutex_enter(&sc->sc_lock);
533	int rv = 0;
534	const u_int lastgen = sc->sc_intrgen;
535	TAILQ_FOREACH(pcie_ih, &sc->sc_intrs, ih_entry) {
536		int (*callback)(void *) = pcie_ih->ih_handler;
537		void *arg = pcie_ih->ih_arg;
538		mutex_exit(&sc->sc_lock);
539		rv += callback(arg);
540		mutex_enter(&sc->sc_lock);
541		if (lastgen != sc->sc_intrgen)
542			break;
543	}
544	mutex_exit(&sc->sc_lock);
545
546	return rv;
547}
548
549static void
550imxpcie_setup(struct imxpcie_softc * const sc)
551{
552	uint32_t v;
553
554	/* Setup RC */
555	v = PCIE_READ(sc, PCIE_PL_PLCR);
556	v &= ~PCIE_PL_PLCR_LINK_MODE_ENABLE;
557	v |= __SHIFTIN(1, PCIE_PL_PLCR_LINK_MODE_ENABLE);
558	PCIE_WRITE(sc, PCIE_PL_PLCR, v);
559
560	v = PCIE_READ(sc, PCIE_PL_G2CR);
561	v &= ~PCIE_PL_G2CR_PREDETERMINED_NUMBER_OF_LANES;
562	v |= __SHIFTIN(1, PCIE_PL_G2CR_PREDETERMINED_NUMBER_OF_LANES);
563	PCIE_WRITE(sc, PCIE_PL_G2CR, v);
564
565	/* BARs */
566	PCIE_WRITE(sc, PCI_BAR0, 0x00000004);
567	PCIE_WRITE(sc, PCI_BAR1, 0x00000000);
568
569	/* Interrupt pins */
570	v = PCIE_READ(sc, PCI_INTERRUPT_REG);
571	v &= ~(PCI_INTERRUPT_PIN_MASK << PCI_INTERRUPT_PIN_SHIFT);
572	v |= PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT;
573	PCIE_WRITE(sc, PCI_INTERRUPT_REG, v);
574
575	/* Bus number */
576	v = PCIE_READ(sc, PCI_BRIDGE_BUS_REG);
577	v &= ~(PCI_BRIDGE_BUS_SUBORDINATE | PCI_BRIDGE_BUS_SECONDARY |
578	    PCI_BRIDGE_BUS_PRIMARY);
579	v |= PCI_BRIDGE_BUS_NUM_SUBORDINATE(1);
580	v |= PCI_BRIDGE_BUS_NUM_SECONDARY(1);
581	v |= PCI_BRIDGE_BUS_NUM_PRIMARY(0);
582	PCIE_WRITE(sc, PCI_BRIDGE_BUS_REG, v);
583
584	/* Command register */
585	v = PCIE_READ(sc, PCI_COMMAND_STATUS_REG);
586	v |= PCI_COMMAND_IO_ENABLE |
587	    PCI_COMMAND_MEM_ENABLE |
588	    PCI_COMMAND_MASTER_ENABLE |
589	    PCI_COMMAND_SERR_ENABLE;
590	PCIE_WRITE(sc, PCI_COMMAND_STATUS_REG, v);
591
592	PCIE_WRITE(sc, PCI_CLASS_REG,
593	    PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
594		PCI_SUBCLASS_BRIDGE_PCI,
595		PCI_INTERFACE_BRIDGE_PCI_PCI));
596
597	PCIE_WRITE(sc, PCIE_PL_IATUVR, 0);
598
599	PCIE_WRITE(sc, PCIE_PL_IATURLBA, sc->sc_root_addr);
600	PCIE_WRITE(sc, PCIE_PL_IATURUBA, 0);
601	PCIE_WRITE(sc, PCIE_PL_IATURLA, sc->sc_root_addr + sc->sc_root_size);
602
603	PCIE_WRITE(sc, PCIE_PL_IATURLTA, 0);
604	PCIE_WRITE(sc, PCIE_PL_IATURUTA, 0);
605	PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG0);
606	PCIE_WRITE(sc, PCIE_PL_IATURC2, PCIE_PL_IATURC2_REGION_ENABLE);
607}
608
609void
610imxpcie_init(pci_chipset_tag_t pc, void *priv)
611{
612	pc->pc_conf_v = priv;
613	pc->pc_attach_hook = imxpcie_attach_hook;
614	pc->pc_bus_maxdevs = imxpcie_bus_maxdevs;
615	pc->pc_make_tag = imxpcie_make_tag;
616	pc->pc_decompose_tag = imxpcie_decompose_tag;
617	pc->pc_conf_read = imxpcie_conf_read;
618	pc->pc_conf_write = imxpcie_conf_write;
619#ifdef __HAVE_PCI_CONF_HOOK
620	pc->pc_conf_hook = imxpcie_conf_hook;
621#endif
622	pc->pc_conf_interrupt = imxpcie_conf_interrupt;
623
624	pc->pc_intr_v = priv;
625	pc->pc_intr_map = imxpcie_intr_map;
626	pc->pc_intr_string = imxpcie_intr_string;
627	pc->pc_intr_evcnt = imxpcie_intr_evcnt;
628	pc->pc_intr_establish = imxpcie_intr_establish;
629	pc->pc_intr_disestablish = imxpcie_intr_disestablish;
630}
631
632static void
633imxpcie_attach_hook(device_t parent, device_t self,
634    struct pcibus_attach_args *pba)
635{
636	/* nothing to do */
637}
638
639static int
640imxpcie_bus_maxdevs(void *v, int busno)
641{
642	return 32;
643}
644
645static pcitag_t
646imxpcie_make_tag(void *v, int b, int d, int f)
647{
648	return (b << 16) | (d << 11) | (f << 8);
649}
650
651static void
652imxpcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
653{
654	if (bp)
655		*bp = (tag >> 16) & 0xff;
656	if (dp)
657		*dp = (tag >> 11) & 0x1f;
658	if (fp)
659		*fp = (tag >> 8) & 0x7;
660}
661
662/*
663 * work around.
664 * If there is no PCIe devices, DABT will be generated by read/write access to
665 * config area, so replace original DABT handler with simple jump-back one.
666 */
667extern u_int data_abort_handler_address;
668static bool data_abort_flag;
669static void
670imxpcie_data_abort_handler(trapframe_t *tf)
671{
672	data_abort_flag = true;
673	tf->tf_pc += 0x4;
674	return;
675}
676
677static pcireg_t
678imxpcie_conf_read(void *v, pcitag_t tag, int offset)
679{
680	struct imxpcie_softc *sc = v;
681	bus_space_handle_t bsh;
682	int b, d, f;
683	pcireg_t ret = -1;
684	int s;
685
686	imxpcie_decompose_tag(v, tag, &b, &d, &f);
687
688	if ((unsigned int)offset >= PCI_EXTCONF_SIZE)
689		return ret;
690	if (!imxpcie_valid_device(sc, b, d))
691		return ret;
692
693	PCIE_WRITE(sc, PCIE_PL_IATUVR, 0);
694	if (b < 2)
695		PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG0);
696	else
697		PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG1);
698
699	if (b == 0) {
700		bsh = sc->sc_ioh;
701	} else {
702		PCIE_WRITE(sc, PCIE_PL_IATURLTA, tag << 8);
703		bsh = sc->sc_root_ioh;
704	}
705	PCIE_READ(sc, PCIE_PL_IATURC2);
706
707	PCIE_CONF_LOCK(s);
708
709	u_int saved = data_abort_handler_address;
710	data_abort_handler_address = (u_int)imxpcie_data_abort_handler;
711	data_abort_flag = false;
712
713	ret = bus_space_read_4(sc->sc_iot, bsh, offset & ~0x3);
714
715	data_abort_handler_address = saved;
716
717	PCIE_CONF_UNLOCK(s);
718
719	if (data_abort_flag)
720		ret = -1;
721
722	return ret;
723}
724
725static void
726imxpcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
727{
728	struct imxpcie_softc *sc = v;
729	bus_space_handle_t bsh;
730	int b, d, f;
731	int s;
732
733	imxpcie_decompose_tag(v, tag, &b, &d, &f);
734
735	if ((unsigned int)offset >= PCI_EXTCONF_SIZE)
736		return;
737	if (!imxpcie_valid_device(sc, b, d))
738		return;
739
740	PCIE_WRITE(sc, PCIE_PL_IATUVR, 0);
741	if (b < 2)
742		PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG0);
743	else
744		PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG1);
745
746	if (b == 0) {
747		bsh = sc->sc_ioh;
748	} else {
749		PCIE_WRITE(sc, PCIE_PL_IATURLTA, tag << 8);
750		bsh = sc->sc_root_ioh;
751	}
752	PCIE_READ(sc, PCIE_PL_IATURC2);
753
754	PCIE_CONF_LOCK(s);
755
756	u_int saved = data_abort_handler_address;
757	data_abort_handler_address = (u_int)imxpcie_data_abort_handler;
758
759	bus_space_write_4(sc->sc_iot, bsh, offset & ~0x3, val);
760
761	data_abort_handler_address = saved;
762
763	PCIE_CONF_UNLOCK(s);
764
765	return;
766}
767
768#ifdef __HAVE_PCI_CONF_HOOK
769static int
770imxpcie_conf_hook(void *v, int b, int d, int f, pcireg_t id)
771{
772	return PCI_CONF_DEFAULT;
773}
774#endif
775
776static void
777imxpcie_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz,
778    int *ilinep)
779{
780	/* nothing to do */
781}
782
783static int
784imxpcie_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih)
785{
786	if (pa->pa_intrpin == 0)
787		return EINVAL;
788	*ih = pa->pa_intrpin;
789	return 0;
790}
791
792static const char *
793imxpcie_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len)
794{
795	if (ih == PCI_INTERRUPT_PIN_NONE)
796		return NULL;
797
798	snprintf(buf, len, "pci");
799
800	return buf;
801}
802
803const struct evcnt *
804imxpcie_intr_evcnt(void *v, pci_intr_handle_t ih)
805{
806	return NULL;
807}
808
809static void *
810imxpcie_intr_establish(void *v, pci_intr_handle_t ih, int ipl,
811    int (*callback)(void *), void *arg, const char *xname)
812{
813	struct imxpcie_softc *sc = v;
814	struct imxpcie_ih *pcie_ih;
815
816	if (ih == 0)
817		return NULL;
818
819	pcie_ih = kmem_alloc(sizeof(*pcie_ih), KM_SLEEP);
820	pcie_ih->ih_handler = callback;
821	pcie_ih->ih_arg = arg;
822	pcie_ih->ih_ipl = ipl;
823
824	mutex_enter(&sc->sc_lock);
825	TAILQ_INSERT_TAIL(&sc->sc_intrs, pcie_ih, ih_entry);
826	sc->sc_intrgen++;
827	mutex_exit(&sc->sc_lock);
828
829	return pcie_ih;
830}
831
832static void
833imxpcie_intr_disestablish(void *v, void *vih)
834{
835	struct imxpcie_softc *sc = v;
836	struct imxpcie_ih *pcie_ih = vih;
837
838	mutex_enter(&sc->sc_lock);
839	TAILQ_REMOVE(&sc->sc_intrs, pcie_ih, ih_entry);
840	sc->sc_intrgen++;
841	mutex_exit(&sc->sc_lock);
842
843	kmem_free(pcie_ih, sizeof(*pcie_ih));
844}
845