4 * Copyright (c) 2001 Wasabi Systems, Inc.
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * PCI configuration support for RMI XLS SoC
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD$");
48 #include <sys/cdefs.h>
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/device.h>
53 #include <sys/extent.h>
54 #include <sys/malloc.h>
56 #include <uvm/uvm_extern.h>
58 #include <machine/bus.h>
59 #include <machine/intr.h>
61 #include <mips/rmi/rmixlreg.h>
62 #include <mips/rmi/rmixlvar.h>
63 #include <mips/rmi/rmixl_pcievar.h>
65 #include <mips/rmi/rmixl_obiovar.h>
67 #include <dev/pci/pcivar.h>
68 #include <dev/pci/pcidevs.h>
69 #include <dev/pci/pciconf.h>
71 #ifdef PCI_NETBSD_CONFIGURE
72 #include <mips/cache.h>
75 #include <machine/pci_machdep.h>
78 int rmixl_pcie_debug
= PCI_DEBUG
;
79 # define DPRINTF(x) do { if (rmixl_pcie_debug) printf x ; } while (0)
85 # define STATIC static
92 * XLS PCIe Extended Configuration Registers
94 #define RMIXL_PCIE_ECFG_UESR 0x104 /* Uncorrectable Error Status Reg */
95 #define RMIXL_PCIE_ECFG_UEMR 0x108 /* Uncorrectable Error Mask Reg */
96 #define RMIXL_PCIE_ECFG_UEVR 0x10c /* Uncorrectable Error seVerity Reg */
97 #define PCIE_ECFG_UEVR_DFLT \
98 (__BITS(18,17) | __BIT(31) | __BITS(5,4) | __BIT(0))
99 #define PCIE_ECFG_UExR_RESV (__BITS(31,21) | __BITS(11,6) | __BITS(3,1))
100 #define RMIXL_PCIE_ECFG_CESR 0x110 /* Correctable Error Status Reg */
101 #define RMIXL_PCIE_ECFG_CEMR 0x114 /* Correctable Error Mask Reg */
102 #define PCIE_ECFG_CExR_RESV (__BITS(31,14) | __BITS(11,9) | __BITS(5,1))
103 #define RMIXL_PCIE_ECFG_ACCR 0x118 /* Adv. Capabilities Control Reg */
104 #define RMIXL_PCIE_ECFG_HLRn(n) (0x11c + ((n) * 4)) /* Header Log Regs */
105 #define RMIXL_PCIE_ECFG_RECR 0x12c /* Root Error Command Reg */
106 #define PCIE_ECFG_RECR_RESV __BITS(31,3)
107 #define RMIXL_PCIE_ECFG_RESR 0x130 /* Root Error Status Reg */
108 #define PCIE_ECFG_RESR_RESV __BITS(26,7)
109 #define RMIXL_PCIE_ECFG_ESI 0x134 /* Error Source Identification Reg */
110 #define RMIXL_PCIE_ECFG_DSNCR 0x140 /* Dev Serial Number Capability Regs */
112 static const struct {
115 } pcie_ecfg_errs_tab
[] = {
116 { RMIXL_PCIE_ECFG_UESR
, (__BITS(20,12) | __BIT(4)) },
117 { RMIXL_PCIE_ECFG_CESR
, (__BITS(20,12) | __BIT(4)) },
118 { RMIXL_PCIE_ECFG_HLRn(0), 0 },
119 { RMIXL_PCIE_ECFG_HLRn(1), 0 },
120 { RMIXL_PCIE_ECFG_HLRn(2), 0 },
121 { RMIXL_PCIE_ECFG_HLRn(3), 0 },
122 { RMIXL_PCIE_ECFG_RESR
, __BITS(6,0) },
123 { RMIXL_PCIE_ECFG_ESI
, 0 },
125 #define PCIE_ECFG_ERRS_OFFTAB_NENTRIES \
126 (sizeof(pcie_ecfg_errs_tab)/sizeof(pcie_ecfg_errs_tab[0]))
128 static int rmixl_pcie_match(device_t
, cfdata_t
, void *);
129 static void rmixl_pcie_attach(device_t
, device_t
, void *);
130 static void rmixl_pcie_init(struct rmixl_pcie_softc
*);
131 static void rmixl_pcie_init_ecfg(struct rmixl_pcie_softc
*);
132 static void rmixl_pcie_attach_hook(struct device
*, struct device
*,
133 struct pcibus_attach_args
*);
134 static void rmixl_pcie_lnkcfg_4xx(rmixl_pcie_lnktab_t
*, uint32_t);
135 static void rmixl_pcie_lnkcfg_408Lite(rmixl_pcie_lnktab_t
*, uint32_t);
136 static void rmixl_pcie_lnkcfg_2xx(rmixl_pcie_lnktab_t
*, uint32_t);
137 static void rmixl_pcie_lnkcfg_1xx(rmixl_pcie_lnktab_t
*, uint32_t);
138 static void rmixl_pcie_lnkcfg(struct rmixl_pcie_softc
*);
139 static void rmixl_pcie_errata(struct rmixl_pcie_softc
*);
140 static void rmixl_conf_interrupt(void *, int, int, int, int, int *);
141 static int rmixl_pcie_bus_maxdevs(void *, int);
142 static pcitag_t
rmixl_tag_to_ecfg(pcitag_t
);
143 static pcitag_t
rmixl_pcie_make_tag(void *, int, int, int);
144 static void rmixl_pcie_decompose_tag(void *, pcitag_t
, int *, int *, int *);
145 void rmixl_pcie_tag_print(const char *restrict
, void *, pcitag_t
, int, vaddr_t
, u_long
);
146 static int rmixl_pcie_conf_setup(struct rmixl_pcie_softc
*,
147 pcitag_t
, int *, bus_space_tag_t
*,
148 bus_space_handle_t
*);
149 static pcireg_t
rmixl_pcie_conf_read(void *, pcitag_t
, int);
150 static void rmixl_pcie_conf_write(void *, pcitag_t
, int, pcireg_t
);
152 static int rmixl_pcie_intr_map(struct pci_attach_args
*,
153 pci_intr_handle_t
*);
155 rmixl_pcie_intr_string(void *, pci_intr_handle_t
);
156 static const struct evcnt
*
157 rmixl_pcie_intr_evcnt(void *, pci_intr_handle_t
);
158 static void *rmixl_pcie_intr_establish(void *, pci_intr_handle_t
,
159 int, int (*)(void *), void *);
160 static void rmixl_pcie_intr_disestablish(void *, void *);
161 #if defined(DEBUG) || defined(DDB)
162 int rmixl_pcie_error_check(void);
164 static int _rmixl_pcie_error_check(void *);
165 static int rmixl_pcie_error_intr(void *);
170 #define PCI_CONF_LOCK(s) (s) = splhigh()
171 #define PCI_CONF_UNLOCK(s) splx((s))
174 #define RMIXL_PCIE_CONCAT3(a,b,c) a ## b ## c
175 #define RMIXL_PCIE_BAR_INIT(reg, bar, size, align) { \
176 struct extent *ext = rmixl_configuration.rc_phys_ex; \
177 u_long region_start; \
181 err = extent_alloc(ext, (size), (align), 0UL, EX_NOWAIT, \
184 panic("%s: extent_alloc(%p, %#lx, %#lx, %#lx, %#x, %p)",\
185 __func__, ext, size, align, 0UL, EX_NOWAIT, \
187 ba = (uint64_t)region_start; \
188 ba *= (1024 * 1024); \
189 bar = RMIXL_PCIE_CONCAT3(RMIXL_PCIE_,reg,_BAR)(ba, 1); \
190 DPRINTF(("PCIE %s BAR was not enabled by firmware\n" \
191 "enabling %s at phys %#" PRIxBUSADDR ", size %lu MB\n", \
192 __STRING(reg), __STRING(reg), ba, size)); \
193 RMIXL_IOREG_WRITE(RMIXL_IO_DEV_BRIDGE + \
194 RMIXL_PCIE_CONCAT3(RMIXL_SBC_PCIE_,reg,_BAR), bar); \
195 bar = RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE + \
196 RMIXL_PCIE_CONCAT3(RMIXL_SBC_PCIE_,reg,_BAR)); \
197 DPRINTF(("%s: %s BAR %#x\n", __func__, __STRING(reg), bar)); \
201 #if defined(DEBUG) || defined(DDB)
202 static void *rmixl_pcie_v
;
205 CFATTACH_DECL_NEW(rmixl_pcie
, sizeof(struct rmixl_pcie_softc
),
206 rmixl_pcie_match
, rmixl_pcie_attach
, NULL
, NULL
);
208 static int rmixl_pcie_found
;
211 * rmixl_cache_err_dis:
212 * - disable Cache, Data ECC, Snoop Tag Parity, Tag Parity errors
213 * - clear the cache error log
214 * - return previous value from RMIXL_PCR_L1D_CONFIG0
216 static inline uint64_t
217 rmixl_cache_err_dis(void)
221 r
= rmixl_mfcr(RMIXL_PCR_L1D_CONFIG0
);
222 rmixl_mtcr(RMIXL_PCR_L1D_CONFIG0
, r
& ~0x2e);
223 rmixl_mtcr(RMIXL_PCR_L1D_CACHE_ERROR_LOG
, 0);
228 * rmixl_cache_err_restore:
229 * - clear the cache error log, cache error overflow log,
230 * and cache interrupt registers
231 * - restore previous value to RMIXL_PCR_L1D_CONFIG0
234 rmixl_cache_err_restore(uint64_t r
)
236 rmixl_mtcr(RMIXL_PCR_L1D_CACHE_ERROR_LOG
, 0);
237 rmixl_mtcr(RMIXL_PCR_L1D_CACHE_ERROR_OVF_LO
, 0);
238 rmixl_mtcr(RMIXL_PCR_L1D_CACHE_INTERRUPT
, 0);
239 rmixl_mtcr(RMIXL_PCR_L1D_CONFIG0
, r
);
242 static inline uint64_t
243 rmixl_cache_err_check(void)
245 return rmixl_mfcr(RMIXL_PCR_L1D_CACHE_ERROR_LOG
);
249 rmixl_pcie_match(device_t parent
, cfdata_t cf
, void *aux
)
254 * for now there is only one PCIe Interface on chip
255 * this could change with furture RMI XL family designs
257 if (rmixl_pcie_found
)
260 /* read GPIO Reset Configuration register */
261 /* XXX FIXME define the offset */
262 r
= RMIXL_IOREG_READ(RMIXL_IO_DEV_GPIO
+ RMIXL_GPIO_RESET_CFG
);
266 return 0; /* strapped for SRIO */
272 rmixl_pcie_attach(device_t parent
, device_t self
, void *aux
)
274 struct rmixl_pcie_softc
*sc
= device_private(self
);
275 struct obio_attach_args
*obio
= aux
;
276 struct rmixl_config
*rcp
= &rmixl_configuration
;
277 struct pcibus_attach_args pba
;
280 rmixl_pcie_found
= 1;
283 aprint_normal(" RMI XLS PCIe Interface\n");
285 rmixl_pcie_lnkcfg(sc
);
287 rmixl_pcie_errata(sc
);
289 sc
->sc_29bit_dmat
= obio
->obio_29bit_dmat
;
290 sc
->sc_32bit_dmat
= obio
->obio_32bit_dmat
;
291 sc
->sc_64bit_dmat
= obio
->obio_64bit_dmat
;
294 * get PCI config space base addr from SBC PCIe CFG BAR
295 * initialize it if necessary
297 bar
= RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE
+ RMIXL_SBC_PCIE_CFG_BAR
);
298 DPRINTF(("%s: PCIE_CFG_BAR %#x\n", __func__
, bar
));
299 if ((bar
& RMIXL_PCIE_CFG_BAR_ENB
) == 0) {
300 u_long n
= RMIXL_PCIE_CFG_SIZE
/ (1024 * 1024);
301 RMIXL_PCIE_BAR_INIT(CFG
, bar
, n
, n
);
303 rcp
->rc_pcie_cfg_pbase
= (bus_addr_t
)RMIXL_PCIE_CFG_BAR_TO_BA(bar
);
304 rcp
->rc_pcie_cfg_size
= (bus_size_t
)RMIXL_PCIE_CFG_SIZE
;
307 * get PCIE Extended config space base addr from SBC PCIe ECFG BAR
308 * initialize it if necessary
310 bar
= RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE
+ RMIXL_SBC_PCIE_ECFG_BAR
);
311 DPRINTF(("%s: PCIE_ECFG_BAR %#x\n", __func__
, bar
));
312 if ((bar
& RMIXL_PCIE_ECFG_BAR_ENB
) == 0) {
313 u_long n
= RMIXL_PCIE_ECFG_SIZE
/ (1024 * 1024);
314 RMIXL_PCIE_BAR_INIT(ECFG
, bar
, n
, n
);
316 rcp
->rc_pcie_ecfg_pbase
= (bus_addr_t
)RMIXL_PCIE_ECFG_BAR_TO_BA(bar
);
317 rcp
->rc_pcie_ecfg_size
= (bus_size_t
)RMIXL_PCIE_ECFG_SIZE
;
320 * get PCI MEM space base [addr, size] from SBC PCIe MEM BAR
321 * initialize it if necessary
323 bar
= RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE
+ RMIXL_SBC_PCIE_MEM_BAR
);
324 DPRINTF(("%s: PCIE_MEM_BAR %#x\n", __func__
, bar
));
325 if ((bar
& RMIXL_PCIE_MEM_BAR_ENB
) == 0) {
326 u_long n
= 256; /* 256 MB */
327 RMIXL_PCIE_BAR_INIT(MEM
, bar
, n
, n
);
329 rcp
->rc_pci_mem_pbase
= (bus_addr_t
)RMIXL_PCIE_MEM_BAR_TO_BA(bar
);
330 rcp
->rc_pci_mem_size
= (bus_size_t
)RMIXL_PCIE_MEM_BAR_TO_SIZE(bar
);
333 * get PCI IO space base [addr, size] from SBC PCIe IO BAR
334 * initialize it if necessary
336 bar
= RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE
+ RMIXL_SBC_PCIE_IO_BAR
);
337 DPRINTF(("%s: PCIE_IO_BAR %#x\n", __func__
, bar
));
338 if ((bar
& RMIXL_PCIE_IO_BAR_ENB
) == 0) {
339 u_long n
= 32; /* 32 MB */
340 RMIXL_PCIE_BAR_INIT(IO
, bar
, n
, n
);
342 rcp
->rc_pci_io_pbase
= (bus_addr_t
)RMIXL_PCIE_IO_BAR_TO_BA(bar
);
343 rcp
->rc_pci_io_size
= (bus_size_t
)RMIXL_PCIE_IO_BAR_TO_SIZE(bar
);
346 * initialize the PCI CFG, ECFG bus space tags
348 rmixl_pcie_cfg_bus_mem_init(&rcp
->rc_pcie_cfg_memt
, rcp
);
349 sc
->sc_pcie_cfg_memt
= &rcp
->rc_pcie_cfg_memt
;
351 rmixl_pcie_ecfg_bus_mem_init(&rcp
->rc_pcie_ecfg_memt
, rcp
);
352 sc
->sc_pcie_ecfg_memt
= &rcp
->rc_pcie_ecfg_memt
;
355 * initialize the PCI MEM and IO bus space tags
357 rmixl_pcie_bus_mem_init(&rcp
->rc_pci_memt
, rcp
);
358 rmixl_pcie_bus_io_init(&rcp
->rc_pci_iot
, rcp
);
361 * initialize the extended configuration regs
363 rmixl_pcie_init_ecfg(sc
);
366 * initialize the PCI chipset tag
373 memset(&pba
, 0, sizeof(pba
));
374 pba
.pba_memt
= &rcp
->rc_pci_memt
;
375 pba
.pba_iot
= &rcp
->rc_pci_iot
;
376 pba
.pba_dmat
= sc
->sc_29bit_dmat
; /* XXX */
378 pba
.pba_dmat64
= NULL
;
380 pba
.pba_pc
= &sc
->sc_pci_chipset
;
382 pba
.pba_bridgetag
= NULL
;
383 pba
.pba_intrswiz
= 0;
385 pba
.pba_flags
= PCI_FLAGS_IO_ENABLED
| PCI_FLAGS_MEM_ENABLED
|
386 PCI_FLAGS_MRL_OKAY
| PCI_FLAGS_MRM_OKAY
| PCI_FLAGS_MWI_OKAY
;
388 (void) config_found_ia(self
, "pcibus", &pba
, pcibusprint
);
392 * rmixl_pcie_lnkcfg_4xx - link configs for XLS4xx and XLS6xx
393 * use IO_AD[11] and IO_AD[10], observable in
394 * Bits[21:20] of the GPIO Reset Configuration register
397 rmixl_pcie_lnkcfg_4xx(rmixl_pcie_lnktab_t
*ltp
, uint32_t grcr
)
400 static const rmixl_pcie_lnkcfg_t lnktab_4xx
[4][4] = {
401 {{ LCFG_EP
, 4}, {LCFG_NO
, 0}, {LCFG_NO
, 0}, {LCFG_NO
, 0}},
402 {{ LCFG_RC
, 4}, {LCFG_NO
, 0}, {LCFG_NO
, 0}, {LCFG_NO
, 0}},
403 {{ LCFG_EP
, 1}, {LCFG_RC
, 1}, {LCFG_RC
, 1}, {LCFG_RC
, 1}},
404 {{ LCFG_RC
, 1}, {LCFG_RC
, 1}, {LCFG_RC
, 1}, {LCFG_RC
, 1}},
406 static const char *lnkstr_4xx
[4] = {
412 index
= (grcr
>> 20) & 3;
414 ltp
->cfg
= lnktab_4xx
[index
];
415 ltp
->str
= lnkstr_4xx
[index
];
419 * rmixl_pcie_lnkcfg_408Lite - link configs for XLS408Lite and XLS04A
420 * use IO_AD[11] and IO_AD[10], observable in
421 * Bits[21:20] of the GPIO Reset Configuration register
424 rmixl_pcie_lnkcfg_408Lite(rmixl_pcie_lnktab_t
*ltp
, uint32_t grcr
)
427 static const rmixl_pcie_lnkcfg_t lnktab_408Lite
[4][2] = {
428 {{ LCFG_EP
, 4}, {LCFG_NO
, 0}},
429 {{ LCFG_RC
, 4}, {LCFG_NO
, 0}},
430 {{ LCFG_EP
, 1}, {LCFG_RC
, 1}},
431 {{ LCFG_RC
, 1}, {LCFG_RC
, 1}},
433 static const char *lnkstr_408Lite
[4] = {
440 index
= (grcr
>> 20) & 3;
442 ltp
->cfg
= lnktab_408Lite
[index
];
443 ltp
->str
= lnkstr_408Lite
[index
];
447 * rmixl_pcie_lnkcfg_2xx - link configs for XLS2xx
448 * use IO_AD[10], observable in Bit[20] of the
449 * GPIO Reset Configuration register
452 rmixl_pcie_lnkcfg_2xx(rmixl_pcie_lnktab_t
*ltp
, uint32_t grcr
)
455 static const rmixl_pcie_lnkcfg_t lnktab_2xx
[2][4] = {
456 {{ LCFG_EP
, 1}, {LCFG_RC
, 1}, {LCFG_RC
, 1}, {LCFG_RC
, 1}},
457 {{ LCFG_RC
, 1}, {LCFG_RC
, 1}, {LCFG_RC
, 1}, {LCFG_RC
, 1}}
459 static const char *lnkstr_2xx
[2] = {
464 index
= (grcr
>> 20) & 1;
466 ltp
->cfg
= lnktab_2xx
[index
];
467 ltp
->str
= lnkstr_2xx
[index
];
471 * rmixl_pcie_lnkcfg_1xx - link configs for XLS1xx
472 * use IO_AD[10], observable in Bit[20] of the
473 * GPIO Reset Configuration register
476 rmixl_pcie_lnkcfg_1xx(rmixl_pcie_lnktab_t
*ltp
, uint32_t grcr
)
479 static const rmixl_pcie_lnkcfg_t lnktab_1xx
[2][2] = {
480 {{ LCFG_EP
, 1}, {LCFG_RC
, 1}},
481 {{ LCFG_RC
, 1}, {LCFG_RC
, 1}}
483 static const char *lnkstr_1xx
[2] = {
488 index
= (grcr
>> 20) & 1;
490 ltp
->cfg
= lnktab_1xx
[index
];
491 ltp
->str
= lnkstr_1xx
[index
];
495 * rmixl_pcie_lnkcfg - determine PCI Express Link Configuration
498 rmixl_pcie_lnkcfg(struct rmixl_pcie_softc
*sc
)
502 /* read GPIO Reset Configuration register */
503 r
= RMIXL_IOREG_READ(RMIXL_IO_DEV_GPIO
+ RMIXL_GPIO_RESET_CFG
);
504 DPRINTF(("%s: GPIO RCR %#x\n", __func__
, r
));
506 switch (MIPS_PRID_IMPL(cpu_id
)) {
509 rmixl_pcie_lnkcfg_1xx(&sc
->sc_pcie_lnktab
, r
);
513 rmixl_pcie_lnkcfg_2xx(&sc
->sc_pcie_lnktab
, r
);
515 case MIPS_XLS404LITE
:
516 case MIPS_XLS408LITE
:
517 rmixl_pcie_lnkcfg_408Lite(&sc
->sc_pcie_lnktab
, r
);
524 /* 6xx uses same table as 4xx */
525 rmixl_pcie_lnkcfg_4xx(&sc
->sc_pcie_lnktab
, r
);
528 panic("%s: unknown RMI PRID IMPL", __func__
);
531 aprint_normal("%s: link config %s\n",
532 device_xname(sc
->sc_dev
), sc
->sc_pcie_lnktab
.str
);
536 rmixl_pcie_errata(struct rmixl_pcie_softc
*sc
)
543 * 3.9.1 PCIe Link-0 Registers Reset to Incorrect Values
544 * check if it allies to this CPU implementation and revision
546 rev
= MIPS_PRID_REV(cpu_id
);
547 switch (MIPS_PRID_IMPL(cpu_id
)) {
553 /* stepping A0 is affected */
557 case MIPS_XLS404LITE
:
558 case MIPS_XLS408LITE
:
563 /* steppings A0 and A1 are affected */
564 if ((rev
== 0) || (rev
== 1))
571 panic("unknown RMI PRID IMPL");
575 * for XLS we only need to check entry #0
576 * this may need to change for later XL family chips
578 lanes
= sc
->sc_pcie_lnktab
.cfg
[0].lanes
;
580 if ((e391
!= false) && ((lanes
== 2) || (lanes
== 4))) {
582 * attempt work around for errata 3.9.1
583 * "PCIe Link-0 Registers Reset to Incorrect Values"
584 * the registers are write-once: if the firmware already wrote,
585 * then our writes are ignored; hope they did it right.
593 aprint_normal("%s: attempt work around for errata 3.9.1",
594 device_xname(sc
->sc_dev
));
596 queuectrl
= 0x00018074;
597 bufdepth
= 0x001901D1;
599 queuectrl
= 0x00018036;
600 bufdepth
= 0x001900D9;
603 RMIXL_IOREG_WRITE(RMIXL_IO_DEV_PCIE_BE
+
604 RMIXL_VC0_POSTED_RX_QUEUE_CTRL
, queuectrl
);
605 RMIXL_IOREG_WRITE(RMIXL_IO_DEV_PCIE_BE
+
606 RMIXL_VC0_POSTED_BUFFER_DEPTH
, bufdepth
);
609 r
= RMIXL_IOREG_READ(RMIXL_IO_DEV_PCIE_BE
+
610 RMIXL_VC0_POSTED_RX_QUEUE_CTRL
);
611 printf("\nVC0_POSTED_RX_QUEUE_CTRL %#x\n", r
);
613 r
= RMIXL_IOREG_READ(RMIXL_IO_DEV_PCIE_BE
+
614 RMIXL_VC0_POSTED_BUFFER_DEPTH
);
615 printf("VC0_POSTED_BUFFER_DEPTH %#x\n", r
);
621 rmixl_pcie_init(struct rmixl_pcie_softc
*sc
)
623 pci_chipset_tag_t pc
= &sc
->sc_pci_chipset
;
624 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
625 struct extent
*ioext
, *memext
;
628 pc
->pc_conf_v
= (void *)sc
;
629 pc
->pc_attach_hook
= rmixl_pcie_attach_hook
;
630 pc
->pc_bus_maxdevs
= rmixl_pcie_bus_maxdevs
;
631 pc
->pc_make_tag
= rmixl_pcie_make_tag
;
632 pc
->pc_decompose_tag
= rmixl_pcie_decompose_tag
;
633 pc
->pc_conf_read
= rmixl_pcie_conf_read
;
634 pc
->pc_conf_write
= rmixl_pcie_conf_write
;
636 pc
->pc_intr_v
= (void *)sc
;
637 pc
->pc_intr_map
= rmixl_pcie_intr_map
;
638 pc
->pc_intr_string
= rmixl_pcie_intr_string
;
639 pc
->pc_intr_evcnt
= rmixl_pcie_intr_evcnt
;
640 pc
->pc_intr_establish
= rmixl_pcie_intr_establish
;
641 pc
->pc_intr_disestablish
= rmixl_pcie_intr_disestablish
;
642 pc
->pc_conf_interrupt
= rmixl_conf_interrupt
;
644 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
646 * Configure the PCI bus.
648 struct rmixl_config
*rcp
= &rmixl_configuration
;
650 aprint_normal("%s: configuring PCI bus\n",
651 device_xname(sc
->sc_dev
));
653 ioext
= extent_create("pciio",
654 rcp
->rc_pci_io_pbase
,
655 rcp
->rc_pci_io_pbase
+ rcp
->rc_pci_io_size
- 1,
656 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
658 memext
= extent_create("pcimem",
659 rcp
->rc_pci_mem_pbase
,
660 rcp
->rc_pci_mem_pbase
+ rcp
->rc_pci_mem_size
- 1,
661 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
663 pci_configure_bus(pc
, ioext
, memext
, NULL
, 0, mips_dcache_align
);
665 extent_destroy(ioext
);
666 extent_destroy(memext
);
671 rmixl_pcie_init_ecfg(struct rmixl_pcie_softc
*sc
)
678 tag
= rmixl_pcie_make_tag(v
, 0, 0, 0);
682 static const int offtab
[] =
683 { 0, 4, 8, 0xc, 0x10, 0x14, 0x18, 0x1c,
685 for (i
=0; i
< sizeof(offtab
)/sizeof(offtab
[0]); i
++) {
686 offset
= 0x100 + offtab
[i
];
687 r
= rmixl_pcie_conf_read(v
, tag
, offset
);
688 printf("%s: %#x: %#x\n", __func__
, offset
, r
);
691 r
= rmixl_pcie_conf_read(v
, tag
, 0x100);
693 return; /* cannot access */
695 /* check pre-existing uncorrectable errs */
696 r
= rmixl_pcie_conf_read(v
, tag
, RMIXL_PCIE_ECFG_UESR
);
697 r
&= ~PCIE_ECFG_UExR_RESV
;
699 panic("%s: Uncorrectable Error Status: %#x\n",
702 /* unmask all uncorrectable errs */
703 r
= rmixl_pcie_conf_read(v
, tag
, RMIXL_PCIE_ECFG_UEMR
);
704 r
&= ~PCIE_ECFG_UExR_RESV
;
705 rmixl_pcie_conf_write(v
, tag
, RMIXL_PCIE_ECFG_UEMR
, r
);
707 /* ensure default uncorrectable err severity confniguration */
708 r
= rmixl_pcie_conf_read(v
, tag
, RMIXL_PCIE_ECFG_UEVR
);
709 r
&= ~PCIE_ECFG_UExR_RESV
;
710 r
|= PCIE_ECFG_UEVR_DFLT
;
711 rmixl_pcie_conf_write(v
, tag
, RMIXL_PCIE_ECFG_UEVR
, r
);
713 /* check pre-existing correctable errs */
714 r
= rmixl_pcie_conf_read(v
, tag
, RMIXL_PCIE_ECFG_CESR
);
715 r
&= ~PCIE_ECFG_CExR_RESV
;
718 aprint_normal("%s: Correctable Error Status: %#x\n",
719 device_xname(sc
->sc_dev
), r
);
722 /* unmask all correctable errs */
723 r
= rmixl_pcie_conf_read(v
, tag
, RMIXL_PCIE_ECFG_CEMR
);
724 r
&= ~PCIE_ECFG_CExR_RESV
;
725 rmixl_pcie_conf_write(v
, tag
, RMIXL_PCIE_ECFG_UEMR
, r
);
727 /* check pre-existing Root Error Status */
728 r
= rmixl_pcie_conf_read(v
, tag
, RMIXL_PCIE_ECFG_RESR
);
729 r
&= ~PCIE_ECFG_RESR_RESV
;
731 panic("%s: Root Error Status: %#x\n", __func__
, r
);
734 /* enable all Root errs */
735 r
= (pcireg_t
)(~PCIE_ECFG_RECR_RESV
);
736 rmixl_pcie_conf_write(v
, tag
, RMIXL_PCIE_ECFG_RECR
, r
);
739 if (MIPS_PRID_IMPL(cpu_id
) == MIPS_XLS408LITE
) {
741 * establish ISR for PCIE Fatal Error interrupt
742 * XXX for XLS408Lite, XLS2xx, XLS1xx only
743 * tested on XLS408Lite only
745 (void)rmixl_intr_establish(29, IPL_HIGH
,
746 RMIXL_INTR_LEVEL
, RMIXL_INTR_HIGH
,
747 rmixl_pcie_error_intr
, v
);
749 #if defined(DEBUG) || defined(DDB)
755 rmixl_conf_interrupt(void *v
, int bus
, int dev
, int ipin
, int swiz
, int *iline
)
757 DPRINTF(("%s: %p, %d, %d, %d, %d, %p\n",
758 __func__
, v
, bus
, dev
, ipin
, swiz
, iline
));
762 rmixl_pcie_attach_hook(struct device
*parent
, struct device
*self
,
763 struct pcibus_attach_args
*pba
)
765 DPRINTF(("%s: pba_bus %d, pba_bridgetag %p, pc_conf_v %p\n",
766 __func__
, pba
->pba_bus
, pba
->pba_bridgetag
,
767 pba
->pba_pc
->pc_conf_v
));
771 rmixl_pcie_bus_maxdevs(void *v
, int busno
)
773 return (32); /* XXX depends on the family of XLS SoC */
777 * rmixl_tag_to_ecfg - convert cfg address (generic tag) to ecfg address
780 * 28 Swap (0=little, 1=big endian)
782 * 19:15 Device number
783 * 14:12 Function number
784 * 11:8 Extended Register number
785 * 7:0 Register number
788 rmixl_tag_to_ecfg(pcitag_t tag
)
790 KASSERT((tag
& __BITS(7,0)) == 0);
795 * XLS pci tag is a 40 bit address composed thusly:
797 * 24 Swap (0=little, 1=big endian)
799 * 15:11 Device number
800 * 10:8 Function number
801 * 7:0 Register number
803 * Note: this is the "native" composition for addressing CFG space, but not for ECFG space.
806 rmixl_pcie_make_tag(void *v
, int bus
, int dev
, int fun
)
808 return ((bus
<< 16) | (dev
<< 11) | (fun
<< 8));
812 rmixl_pcie_decompose_tag(void *v
, pcitag_t tag
, int *bp
, int *dp
, int *fp
)
815 *bp
= (tag
>> 16) & 0xff;
817 *dp
= (tag
>> 11) & 0x1f;
819 *fp
= (tag
>> 8) & 0x7;
823 rmixl_pcie_tag_print(const char *restrict s
, void *v
, pcitag_t tag
, int offset
,
824 vaddr_t va
, u_long r
)
828 rmixl_pcie_decompose_tag(v
, tag
, &bus
, &dev
, &fun
);
829 printf("%s: %d/%d/%d/%d - %#" PRIxVADDR
":%#lx\n",
830 s
, bus
, dev
, fun
, offset
, va
, r
);
834 rmixl_pcie_conf_setup(struct rmixl_pcie_softc
*sc
,
835 pcitag_t tag
, int *offp
, bus_space_tag_t
*bstp
,
836 bus_space_handle_t
*bshp
)
838 struct rmixl_config
*rcp
= &rmixl_configuration
;
840 bus_space_handle_t bsh
;
845 static bus_space_handle_t cfg_bsh
;
846 static bus_addr_t cfg_oba
= -1;
847 static bus_space_handle_t ecfg_bsh
;
848 static bus_addr_t ecfg_oba
= -1;
851 * bus space depends on offset
853 if ((*offp
>= 0) && (*offp
< 0x100)) {
855 bst
= sc
->sc_pcie_cfg_memt
;
856 ba
= rcp
->rc_pcie_cfg_pbase
;
858 *offp
+= (tag
& mask
);
860 size
= (bus_size_t
)(mask
+ 1);
862 bus_space_unmap(bst
, cfg_bsh
, size
);
863 err
= bus_space_map(bst
, ba
, size
, 0, &cfg_bsh
);
866 panic("%s: bus_space_map err %d, CFG space",
867 __func__
, err
); /* XXX */
874 } else if ((*offp
>= 0x100) && (*offp
<= 0x700)) {
876 tag
= rmixl_tag_to_ecfg(tag
); /* convert to ECFG format */
877 bst
= sc
->sc_pcie_ecfg_memt
;
878 ba
= rcp
->rc_pcie_ecfg_pbase
;
880 *offp
+= (tag
& mask
);
881 if (ba
!= ecfg_oba
) {
882 size
= (bus_size_t
)(mask
+ 1);
884 bus_space_unmap(bst
, ecfg_bsh
, size
);
885 err
= bus_space_map(bst
, ba
, size
, 0, &ecfg_bsh
);
888 panic("%s: bus_space_map err %d, ECFG space",
889 __func__
, err
); /* XXX */
898 panic("%s: offset %#x: unknown", __func__
, *offp
);
910 rmixl_pcie_conf_read(void *v
, pcitag_t tag
, int offset
)
912 struct rmixl_pcie_softc
*sc
= v
;
913 static bus_space_handle_t bsh
;
921 if (rmixl_pcie_conf_setup(sc
, tag
, &offset
, &bst
, &bsh
) == 0) {
922 cfg0
= rmixl_cache_err_dis();
923 rv
= bus_space_read_4(bst
, bsh
, (bus_size_t
)offset
);
924 if (rmixl_cache_err_check() != 0) {
928 rmixl_pcie_decompose_tag(v
, tag
, &bus
, &dev
, &fun
);
929 printf("%s: %d/%d/%d, offset %#x: bad address\n",
930 __func__
, bus
, dev
, fun
, offset
);
934 rmixl_cache_err_restore(cfg0
);
944 rmixl_pcie_conf_write(void *v
, pcitag_t tag
, int offset
, pcireg_t val
)
946 struct rmixl_pcie_softc
*sc
= v
;
947 static bus_space_handle_t bsh
;
954 if (rmixl_pcie_conf_setup(sc
, tag
, &offset
, &bst
, &bsh
) == 0) {
955 cfg0
= rmixl_cache_err_dis();
956 bus_space_write_4(bst
, bsh
, (bus_size_t
)offset
, val
);
957 if (rmixl_cache_err_check() != 0) {
961 rmixl_pcie_decompose_tag(v
, tag
, &bus
, &dev
, &fun
);
962 printf("%s: %d/%d/%d, offset %#x: bad address\n",
963 __func__
, bus
, dev
, fun
, offset
);
966 rmixl_cache_err_restore(cfg0
);
973 rmixl_pcie_intr_map(struct pci_attach_args
*pa
, pci_intr_handle_t
*pih
)
978 DPRINTF(("%s: ps_bus %d, pa_intrswiz %#x, pa_intrtag %#lx,"
979 " pa_intrpin %d, pa_intrline %d, pa_rawintrpin %d\n",
980 __func__
, pa
->pa_bus
, pa
->pa_intrswiz
, pa
->pa_intrtag
,
981 pa
->pa_intrpin
, pa
->pa_intrline
, pa
->pa_rawintrpin
));
985 * XXX cpu implementation specific
987 switch (MIPS_PRID_IMPL(cpu_id
)) {
988 case MIPS_XLS408LITE
:
989 switch (pa
->pa_bus
) {
997 panic("%s: bad bus %d\n", __func__
, pa
->pa_bus
);
1002 switch (pa
->pa_bus
) {
1016 panic("%s: bad bus %d\n", __func__
, pa
->pa_bus
);
1020 panic("%s: cpu IMPL %#x not supported\n",
1021 __func__
, MIPS_PRID_IMPL(cpu_id
));
1030 rmixl_pcie_intr_string(void *v
, pci_intr_handle_t pih
)
1032 const char *name
= "(illegal)";
1035 switch (MIPS_PRID_IMPL(cpu_id
)) {
1036 case MIPS_XLS408LITE
:
1040 name
= rmixl_intr_string(irq
);
1050 name
= rmixl_intr_string(irq
);
1059 const struct evcnt
*
1060 rmixl_pcie_intr_evcnt(void *v
, pci_intr_handle_t pih
)
1066 rmixl_pcie_irq(pci_intr_handle_t pih
)
1072 rmixl_pcie_intr_establish(void *v
, pci_intr_handle_t pih
, int ipl
,
1073 int (*func
)(void *), void *arg
)
1075 return rmixl_intr_establish(rmixl_pcie_irq((int)pih
), ipl
,
1076 RMIXL_INTR_LEVEL
, RMIXL_INTR_HIGH
, func
, arg
);
1080 rmixl_pcie_intr_disestablish(void *v
, void *ih
)
1082 rmixl_intr_disestablish(ih
);
1085 #if defined(DEBUG) || defined(DDB)
1086 /* this function exists to facilitate call from ddb */
1088 rmixl_pcie_error_check(void)
1090 if (rmixl_pcie_v
!= 0)
1091 return _rmixl_pcie_error_check(rmixl_pcie_v
);
1097 _rmixl_pcie_error_check(void *v
)
1104 pcireg_t regs
[PCIE_ECFG_ERRS_OFFTAB_NENTRIES
];
1107 tag
= rmixl_pcie_make_tag(v
, 0, 0, 0); /* XXX */
1109 for (i
=0; i
< PCIE_ECFG_ERRS_OFFTAB_NENTRIES
; i
++) {
1110 offset
= pcie_ecfg_errs_tab
[i
].offset
;
1111 r
= rmixl_pcie_conf_read(v
, tag
, offset
);
1116 pcireg_t rw1c
= r
& pcie_ecfg_errs_tab
[i
].rw1c
;
1118 /* attempt to clear the error */
1119 rmixl_pcie_conf_write(v
, tag
, offset
, rw1c
);
1121 if (offset
== RMIXL_PCIE_ECFG_CESR
)
1122 err
|= 1; /* correctable */
1124 err
|= 2; /* uncorrectable */
1129 for (i
=0; i
< PCIE_ECFG_ERRS_OFFTAB_NENTRIES
; i
++) {
1130 offset
= pcie_ecfg_errs_tab
[i
].offset
;
1131 printf("%s: %#x: %#x\n", __func__
, offset
, regs
[i
]);
1140 rmixl_pcie_error_intr(void *v
)
1142 if (_rmixl_pcie_error_check(v
) < 2)
1143 return 0; /* correctable */
1150 /* XXX reset and recover? */
1152 panic("%s\n", __func__
);