rmixl_pcie.c revision 1.1.2.2 1 /* $NetBSD: rmixl_pcie.c,v 1.1.2.2 2009/11/13 05:22:19 cliff Exp $ */
2
3 /*
4 * Copyright (c) 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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
23 * written permission.
24 *
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.
36 */
37
38 /*
39 * PCI configuration support for RMI XLS SoC
40 */
41
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: rmixl_pcie.c,v 1.1.2.2 2009/11/13 05:22:19 cliff Exp $");
44
45 #include "opt_pci.h"
46 #include "pci.h"
47
48 #include <sys/cdefs.h>
49
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>
55
56 #include <uvm/uvm_extern.h>
57
58 #include <machine/bus.h>
59 #include <machine/intr.h>
60
61 #include <mips/rmi/rmixlreg.h>
62 #include <mips/rmi/rmixlvar.h>
63 #include <mips/rmi/rmixl_pcievar.h>
64
65 #include <mips/rmi/rmixl_obiovar.h>
66
67 #include <dev/pci/pcivar.h>
68 #include <dev/pci/pcidevs.h>
69 #include <dev/pci/pciconf.h>
70
71 #ifdef PCI_NETBSD_CONFIGURE
72 #include <mips/cache.h>
73 #endif
74
75 #include <machine/pci_machdep.h>
76
77 #ifdef PCI_DEBUG
78 int rmixl_pcie_debug = PCI_DEBUG;
79 # define DPRINTF(x) do { if (rmixl_pcie_debug) printf x ; } while (0)
80 #else
81 # define DPRINTF(x)
82 #endif
83
84 #ifndef DDB
85 # define STATIC static
86 #else
87 # define STATIC
88 #endif
89
90
91 /*
92 * use XKPHYS in order to accomodate XLS 40 bit PCIe bus address
93 * PCIe config space is all little endian for now
94 */
95 #define RMIXL_PCI_VADDR(ba) \
96 (volatile uint32_t *)MIPS_PHYS_TO_XKPHYS_UNCACHED(ba)
97 #define RMIXL_PCI_READ(o) le32toh(*RMIXL_PCI_VADDR(o))
98 #define RMIXL_PCI_WRITE(o,v) *RMIXL_PCI_VADDR(o) = htole32(v)
99
100
101 /*
102 * XLS PCIe Extended Configuration Registers
103 */
104 #define RMIXL_PCIE_ECFG_UESR 0x104 /* Uncorrectable Error Status Reg */
105 #define RMIXL_PCIE_ECFG_UEMR 0x108 /* Uncorrectable Error Mask Reg */
106 #define RMIXL_PCIE_ECFG_UEVR 0x10c /* Uncorrectable Error seVerity Reg */
107 #define PCIE_ECFG_UEVR_DFLT \
108 (__BITS(18,17) | __BIT(31) | __BITS(5,4) | __BIT(0))
109 #define PCIE_ECFG_UExR_RESV (__BITS(31,21) | __BITS(11,6) | __BITS(3,1))
110 #define RMIXL_PCIE_ECFG_CESR 0x110 /* Correctable Error Status Reg */
111 #define RMIXL_PCIE_ECFG_CEMR 0x114 /* Correctable Error Mask Reg */
112 #define PCIE_ECFG_CExR_RESV (__BITS(31,14) | __BITS(11,9) | __BITS(5,1))
113 #define RMIXL_PCIE_ECFG_ACCR 0x118 /* Adv. Capabilities Control Reg */
114 #define RMIXL_PCIE_ECFG_HLRn(n) (0x11c + ((n) * 4)) /* Header Log Regs */
115 #define RMIXL_PCIE_ECFG_RECR 0x12c /* Root Error Command Reg */
116 #define PCIE_ECFG_RECR_RESV __BITS(31,3)
117 #define RMIXL_PCIE_ECFG_RESR 0x130 /* Root Error Status Reg */
118 #define PCIE_ECFG_RESR_RESV __BITS(26,7)
119 #define RMIXL_PCIE_ECFG_ESI 0x134 /* Error Source Identification Reg */
120 #define RMIXL_PCIE_ECFG_DSNCR 0x140 /* Dev Serial Number Capability Regs */
121
122 static const struct {
123 u_int offset;
124 u_int32_t rw1c;
125 } pcie_ecfg_errs_tab[] = {
126 { RMIXL_PCIE_ECFG_UESR, (__BITS(20,12) | __BIT(4)) },
127 { RMIXL_PCIE_ECFG_CESR, (__BITS(20,12) | __BIT(4)) },
128 { RMIXL_PCIE_ECFG_HLRn(0), 0 },
129 { RMIXL_PCIE_ECFG_HLRn(1), 0 },
130 { RMIXL_PCIE_ECFG_HLRn(2), 0 },
131 { RMIXL_PCIE_ECFG_HLRn(3), 0 },
132 { RMIXL_PCIE_ECFG_RESR, __BITS(6,0) },
133 { RMIXL_PCIE_ECFG_ESI, 0 },
134 };
135 #define PCIE_ECFG_ERRS_OFFTAB_NENTRIES \
136 (sizeof(pcie_ecfg_errs_tab)/sizeof(pcie_ecfg_errs_tab[0]))
137
138 static int rmixl_pcie_match(device_t, cfdata_t, void *);
139 static void rmixl_pcie_attach(device_t, device_t, void *);
140 static void rmixl_pcie_init(struct rmixl_pcie_softc *);
141 static void rmixl_pcie_init_ecfg(struct rmixl_pcie_softc *);
142 static void rmixl_pcie_attach_hook(struct device *, struct device *,
143 struct pcibus_attach_args *);
144 static void rmixl_pcie_lnkcfg_4xx(rmixl_pcie_lnktab_t *, uint32_t);
145 static void rmixl_pcie_lnkcfg_408Lite(rmixl_pcie_lnktab_t *, uint32_t);
146 static void rmixl_pcie_lnkcfg_2xx(rmixl_pcie_lnktab_t *, uint32_t);
147 static void rmixl_pcie_lnkcfg_1xx(rmixl_pcie_lnktab_t *, uint32_t);
148 static void rmixl_pcie_lnkcfg(struct rmixl_pcie_softc *);
149 static void rmixl_pcie_errata(struct rmixl_pcie_softc *);
150 static void rmixl_conf_interrupt(void *, int, int, int, int, int *);
151 static int rmixl_pcie_bus_maxdevs(void *, int);
152 static pcitag_t rmixl_pcie_make_tag(void *, int, int, int);
153 static void rmixl_pcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
154 void rmixl_pcie_tag_print(const char *restrict, void *, pcitag_t, int, vaddr_t, u_long);
155 static pcireg_t rmixl_pcie_conf_read(void *, pcitag_t, int);
156 static void rmixl_pcie_conf_write(void *, pcitag_t, int, pcireg_t);
157
158 static int rmixl_pcie_intr_map(struct pci_attach_args *,
159 pci_intr_handle_t *);
160 static const char *
161 rmixl_pcie_intr_string(void *, pci_intr_handle_t);
162 static const struct evcnt *
163 rmixl_pcie_intr_evcnt(void *, pci_intr_handle_t);
164 static void *rmixl_pcie_intr_establish(void *, pci_intr_handle_t,
165 int, int (*)(void *), void *);
166 static void rmixl_pcie_intr_disestablish(void *, void *);
167 #if defined(DEBUG) || defined(DDB)
168 int rmixl_pcie_error_check(void);
169 #endif
170 static int _rmixl_pcie_error_check(void *);
171 static int rmixl_pcie_error_intr(void *);
172
173 /*
174 * XXX use locks
175 */
176 #define PCI_CONF_LOCK(s) (s) = splhigh()
177 #define PCI_CONF_UNLOCK(s) splx((s))
178
179
180 #define RMIXL_PCIE_CONCAT3(a,b,c) a ## b ## c
181 #define RMIXL_PCIE_BAR_INIT(reg, bar, size, align) { \
182 struct extent *ext = rmixl_configuration.rc_phys_ex; \
183 u_long region_start; \
184 uint64_t ba; \
185 int err; \
186 \
187 err = extent_alloc(ext, (size), (align), 0UL, EX_NOWAIT, \
188 ®ion_start); \
189 if (err != 0) \
190 panic("%s: extent_alloc(%p, %#lx, %#lx, %#lx, %#x, %p)",\
191 __func__, ext, size, align, 0UL, EX_NOWAIT, \
192 ®ion_start); \
193 ba = (uint64_t)region_start; \
194 ba *= (1024 * 1024); \
195 bar = RMIXL_PCIE_CONCAT3(RMIXL_PCIE_,reg,_BAR)(ba, 1); \
196 DPRINTF(("PCIE %s BAR was not enabled by firmware\n" \
197 "enabling %s at phys %" PRIx64 ", size %lu MB\n", \
198 __STRING(reg), __STRING(reg), ba, size)); \
199 RMIXL_IOREG_WRITE(RMIXL_IO_DEV_BRIDGE + \
200 RMIXL_PCIE_CONCAT3(RMIXL_SBC_PCIE_,reg,_BAR), bar); \
201 bar = RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE + \
202 RMIXL_PCIE_CONCAT3(RMIXL_SBC_PCIE_,reg,_BAR)); \
203 DPRINTF(("%s: %s BAR %#x\n", __func__, __STRING(reg), bar)); \
204 }
205
206
207 #if defined(DEBUG) || defined(DDB)
208 static void *rmixl_pcie_v;
209 #endif
210
211 CFATTACH_DECL_NEW(rmixl_pcie, sizeof(struct rmixl_pcie_softc),
212 rmixl_pcie_match, rmixl_pcie_attach, NULL, NULL);
213
214 static int rmixl_pcie_found;
215
216 /*
217 * rmixl_cache_err_dis:
218 * - disable Cache, Data ECC, Snoop Tag Parity, Tag Parity errors
219 * - clear the cache error log
220 * - return previous value from RMIXL_PCR_L1D_CONFIG0
221 */
222 static inline uint64_t
223 rmixl_cache_err_dis(void)
224 {
225 uint64_t r;
226
227 r = rmixl_mfcr(RMIXL_PCR_L1D_CONFIG0);
228 rmixl_mtcr(RMIXL_PCR_L1D_CONFIG0, r & ~0x2e);
229 rmixl_mtcr(RMIXL_PCR_L1D_CACHE_ERROR_LOG, 0);
230 return r;
231 }
232
233 /*
234 * rmixl_cache_err_restore:
235 * - clear the cache error log, cache error overflow log,
236 * and cache interrupt registers
237 * - restore previous value to RMIXL_PCR_L1D_CONFIG0
238 */
239 static inline void
240 rmixl_cache_err_restore(uint64_t r)
241 {
242 rmixl_mtcr(RMIXL_PCR_L1D_CACHE_ERROR_LOG, 0);
243 rmixl_mtcr(RMIXL_PCR_L1D_CACHE_ERROR_OVF_LO, 0);
244 rmixl_mtcr(RMIXL_PCR_L1D_CACHE_INTERRUPT, 0);
245 rmixl_mtcr(RMIXL_PCR_L1D_CONFIG0, r);
246 }
247
248 static inline uint64_t
249 rmixl_cache_err_check(void)
250 {
251 return rmixl_mfcr(RMIXL_PCR_L1D_CACHE_ERROR_LOG);
252 }
253
254 static int
255 rmixl_pcie_match(device_t parent, cfdata_t cf, void *aux)
256 {
257 uint32_t r;
258
259 /* XXX
260 * for now there is only one PCIe Interface on chip
261 * this could change with furture RMI XL family designs
262 */
263 if (rmixl_pcie_found)
264 return 0;
265
266 /* read GPIO Reset Configuration register */
267 /* XXX FIXME define the offset */
268 r = RMIXL_IOREG_READ(RMIXL_IO_DEV_GPIO + RMIXL_GPIO_RESET_CFG);
269 r >>= 26;
270 r &= 3;
271 if (r != 0)
272 return 0; /* strapped for SRIO */
273
274 return 1;
275 }
276
277 static void
278 rmixl_pcie_attach(device_t parent, device_t self, void *aux)
279 {
280 struct rmixl_pcie_softc *sc = device_private(self);
281 struct obio_attach_args *obio = aux;
282 struct rmixl_config *rcp = &rmixl_configuration;
283 struct pcibus_attach_args pba;
284 uint32_t bar;
285
286 rmixl_pcie_found = 1;
287 sc->sc_dev = self;
288
289 aprint_normal(" RMI XLS PCIe Interface\n");
290
291 rmixl_pcie_lnkcfg(sc);
292
293 rmixl_pcie_errata(sc);
294
295 sc->sc_29bit_dmat = obio->obio_29bit_dmat;
296 sc->sc_32bit_dmat = obio->obio_32bit_dmat;
297 sc->sc_64bit_dmat = obio->obio_64bit_dmat;
298
299 /*
300 * get PCI config space base addr from SBC PCIe CFG BAR
301 * initialize it if necessary
302 */
303 bar = RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE + RMIXL_SBC_PCIE_CFG_BAR);
304 DPRINTF(("%s: PCIE_CFG_BAR %#x\n", __func__, bar));
305 if ((bar & RMIXL_PCIE_CFG_BAR_ENB) == 0) {
306 u_long n = RMIXL_PCIE_CFG_SIZE / (1024 * 1024);
307 RMIXL_PCIE_BAR_INIT(CFG, bar, n, n);
308 }
309 sc->sc_pcie_cfg_pbase = RMIXL_PCIE_CFG_BAR_TO_BA(bar);
310
311 /*
312 * get PCIE Extended config space base addr from SBC PCIe ECFG BAR
313 * initialize it if necessary
314 */
315 bar = RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE + RMIXL_SBC_PCIE_ECFG_BAR);
316 DPRINTF(("%s: PCIE_ECFG_BAR %#x\n", __func__, bar));
317 if ((bar & RMIXL_PCIE_ECFG_BAR_ENB) == 0) {
318 u_long n = RMIXL_PCIE_ECFG_SIZE / (1024 * 1024);
319 RMIXL_PCIE_BAR_INIT(ECFG, bar, n, n);
320 }
321 sc->sc_pcie_ecfg_pbase = RMIXL_PCIE_ECFG_BAR_TO_BA(bar);
322
323 /*
324 * get PCI MEM space base [addr, size] from SBC PCIe MEM BAR
325 * initialize it if necessary
326 */
327 bar = RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE + RMIXL_SBC_PCIE_MEM_BAR);
328 DPRINTF(("%s: PCIE_MEM_BAR %#x\n", __func__, bar));
329 if ((bar & RMIXL_PCIE_MEM_BAR_ENB) == 0) {
330 u_long n = 256; /* 256 MB */
331 RMIXL_PCIE_BAR_INIT(MEM, bar, n, n);
332 }
333 rcp->rc_pci_mem_pbase = (bus_addr_t)RMIXL_PCIE_MEM_BAR_TO_BA(bar);
334 rcp->rc_pci_mem_size = (bus_size_t)RMIXL_PCIE_MEM_BAR_TO_SIZE(bar);
335
336 /*
337 * get PCI IO space base [addr, size] from SBC PCIe IO BAR
338 * initialize it if necessary
339 */
340 bar = RMIXL_IOREG_READ(RMIXL_IO_DEV_BRIDGE + RMIXL_SBC_PCIE_IO_BAR);
341 DPRINTF(("%s: PCIE_IO_BAR %#x\n", __func__, bar));
342 if ((bar & RMIXL_PCIE_IO_BAR_ENB) == 0) {
343 u_long n = 32; /* 32 MB */
344 RMIXL_PCIE_BAR_INIT(IO, bar, n, n);
345 }
346 rcp->rc_pci_io_pbase = (bus_addr_t)RMIXL_PCIE_IO_BAR_TO_BA(bar);
347 rcp->rc_pci_io_size = (bus_size_t)RMIXL_PCIE_IO_BAR_TO_SIZE(bar);
348
349 /*
350 * initialize the PCI bus spaces tag
351 */
352 rmixl_pcie_bus_mem_init(&rcp->rc_pci_memt, rcp);
353 rmixl_pcie_bus_io_init(&rcp->rc_pci_iot, rcp);
354
355 /*
356 * initialize the extended configuration regs
357 */
358 rmixl_pcie_init_ecfg(sc);
359
360 /*
361 * initialize the PCI chipset tag
362 */
363 rmixl_pcie_init(sc);
364
365 /*
366 * attach the PCI bus
367 */
368 memset(&pba, 0, sizeof(pba));
369 pba.pba_memt = &rcp->rc_pci_memt;
370 pba.pba_iot = &rcp->rc_pci_iot;
371 pba.pba_dmat = sc->sc_29bit_dmat; /* XXX */
372 #ifdef NOTYET
373 pba.pba_dmat64 = NULL;
374 #endif
375 pba.pba_pc = &sc->sc_pci_chipset;
376 pba.pba_bus = 0;
377 pba.pba_bridgetag = NULL;
378 pba.pba_intrswiz = 0;
379 pba.pba_intrtag = 0;
380 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
381 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY;
382
383 (void) config_found_ia(self, "pcibus", &pba, pcibusprint);
384 }
385
386 /*
387 * rmixl_pcie_lnkcfg_4xx - link configs for XLS4xx and XLS6xx
388 * use IO_AD[11] and IO_AD[10], observable in
389 * Bits[21:20] of the GPIO Reset Configuration register
390 */
391 static void
392 rmixl_pcie_lnkcfg_4xx(rmixl_pcie_lnktab_t *ltp, uint32_t grcr)
393 {
394 u_int index;
395 static const rmixl_pcie_lnkcfg_t lnktab_4xx[4][4] = {
396 {{ LCFG_EP, 4}, {LCFG_NO, 0}, {LCFG_NO, 0}, {LCFG_NO, 0}},
397 {{ LCFG_RC, 4}, {LCFG_NO, 0}, {LCFG_NO, 0}, {LCFG_NO, 0}},
398 {{ LCFG_EP, 1}, {LCFG_RC, 1}, {LCFG_RC, 1}, {LCFG_RC, 1}},
399 {{ LCFG_RC, 1}, {LCFG_RC, 1}, {LCFG_RC, 1}, {LCFG_RC, 1}},
400 };
401 static const char *lnkstr_4xx[4] = {
402 "EP 1x4",
403 "RC 1x4",
404 "EP 1x1, RC 4x1",
405 "RC 4x1"
406 };
407 index = (grcr >> 20) & 3;
408 ltp->ncfgs = 4;
409 ltp->cfg = lnktab_4xx[index];
410 ltp->str = lnkstr_4xx[index];
411 }
412
413 /*
414 * rmixl_pcie_lnkcfg_408Lite - link configs for XLS408Lite and XLS04A
415 * use IO_AD[11] and IO_AD[10], observable in
416 * Bits[21:20] of the GPIO Reset Configuration register
417 */
418 static void
419 rmixl_pcie_lnkcfg_408Lite(rmixl_pcie_lnktab_t *ltp, uint32_t grcr)
420 {
421 u_int index;
422 static const rmixl_pcie_lnkcfg_t lnktab_408Lite[4][2] = {
423 {{ LCFG_EP, 4}, {LCFG_NO, 0}},
424 {{ LCFG_RC, 4}, {LCFG_NO, 0}},
425 {{ LCFG_EP, 1}, {LCFG_RC, 1}},
426 {{ LCFG_RC, 1}, {LCFG_RC, 1}},
427 };
428 static const char *lnkstr_408Lite[4] = {
429 "EP 1x4",
430 "RC 1x4",
431 "EP 1x1, RC 1x1",
432 "RC 2x1"
433 };
434
435 index = (grcr >> 20) & 3;
436 ltp->ncfgs = 2;
437 ltp->cfg = lnktab_408Lite[index];
438 ltp->str = lnkstr_408Lite[index];
439 }
440
441 /*
442 * rmixl_pcie_lnkcfg_2xx - link configs for XLS2xx
443 * use IO_AD[10], observable in Bit[20] of the
444 * GPIO Reset Configuration register
445 */
446 static void
447 rmixl_pcie_lnkcfg_2xx(rmixl_pcie_lnktab_t *ltp, uint32_t grcr)
448 {
449 u_int index;
450 static const rmixl_pcie_lnkcfg_t lnktab_2xx[2][4] = {
451 {{ LCFG_EP, 1}, {LCFG_RC, 1}, {LCFG_RC, 1}, {LCFG_RC, 1}},
452 {{ LCFG_RC, 1}, {LCFG_RC, 1}, {LCFG_RC, 1}, {LCFG_RC, 1}}
453 };
454 static const char *lnkstr_2xx[2] = {
455 "EP 1x1, RC 3x1",
456 "RC 4x1",
457 };
458
459 index = (grcr >> 20) & 1;
460 ltp->ncfgs = 4;
461 ltp->cfg = lnktab_2xx[index];
462 ltp->str = lnkstr_2xx[index];
463 }
464
465 /*
466 * rmixl_pcie_lnkcfg_1xx - link configs for XLS1xx
467 * use IO_AD[10], observable in Bit[20] of the
468 * GPIO Reset Configuration register
469 */
470 static void
471 rmixl_pcie_lnkcfg_1xx(rmixl_pcie_lnktab_t *ltp, uint32_t grcr)
472 {
473 u_int index;
474 static const rmixl_pcie_lnkcfg_t lnktab_1xx[2][2] = {
475 {{ LCFG_EP, 1}, {LCFG_RC, 1}},
476 {{ LCFG_RC, 1}, {LCFG_RC, 1}}
477 };
478 static const char *lnkstr_1xx[2] = {
479 "EP 1x1, RC 1x1",
480 "RC 2x1",
481 };
482
483 index = (grcr >> 20) & 1;
484 ltp->ncfgs = 2;
485 ltp->cfg = lnktab_1xx[index];
486 ltp->str = lnkstr_1xx[index];
487 }
488
489 /*
490 * rmixl_pcie_lnkcfg - determine PCI Express Link Configuration
491 */
492 static void
493 rmixl_pcie_lnkcfg(struct rmixl_pcie_softc *sc)
494 {
495 uint32_t r;
496
497 /* read GPIO Reset Configuration register */
498 r = RMIXL_IOREG_READ(RMIXL_IO_DEV_GPIO + RMIXL_GPIO_RESET_CFG);
499 DPRINTF(("%s: GPIO RCR %#x\n", __func__, r));
500
501 switch (MIPS_PRID_IMPL(cpu_id)) {
502 case MIPS_XLS104:
503 case MIPS_XLS108:
504 rmixl_pcie_lnkcfg_1xx(&sc->sc_pcie_lnktab, r);
505 break;
506 case MIPS_XLS204:
507 case MIPS_XLS208:
508 rmixl_pcie_lnkcfg_2xx(&sc->sc_pcie_lnktab, r);
509 break;
510 case MIPS_XLS404LITE:
511 case MIPS_XLS408LITE:
512 rmixl_pcie_lnkcfg_408Lite(&sc->sc_pcie_lnktab, r);
513 break;
514 case MIPS_XLS404:
515 case MIPS_XLS408:
516 case MIPS_XLS416:
517 case MIPS_XLS608:
518 case MIPS_XLS616:
519 /* 6xx uses same table as 4xx */
520 rmixl_pcie_lnkcfg_4xx(&sc->sc_pcie_lnktab, r);
521 break;
522 default:
523 panic("%s: unknown RMI PRID IMPL", __func__);
524 }
525
526 aprint_normal("%s: link config %s\n",
527 device_xname(sc->sc_dev), sc->sc_pcie_lnktab.str);
528 }
529
530 static void
531 rmixl_pcie_errata(struct rmixl_pcie_softc *sc)
532 {
533 u_int rev;
534 u_int lanes;
535 bool e391 = false;
536
537 /*
538 * 3.9.1 PCIe Link-0 Registers Reset to Incorrect Values
539 * check if it allies to this CPU implementation and revision
540 */
541 rev = MIPS_PRID_REV(cpu_id);
542 switch (MIPS_PRID_IMPL(cpu_id)) {
543 case MIPS_XLS104:
544 case MIPS_XLS108:
545 break;
546 case MIPS_XLS204:
547 case MIPS_XLS208:
548 /* stepping A0 is affected */
549 if (rev == 0)
550 e391 = true;
551 break;
552 case MIPS_XLS404LITE:
553 case MIPS_XLS408LITE:
554 break;
555 case MIPS_XLS404:
556 case MIPS_XLS408:
557 case MIPS_XLS416:
558 /* steppings A0 and A1 are affected */
559 if ((rev == 0) || (rev == 1))
560 e391 = true;
561 break;
562 case MIPS_XLS608:
563 case MIPS_XLS616:
564 break;
565 default:
566 panic("unknown RMI PRID IMPL");
567 }
568
569 /*
570 * for XLS we only need to check entry #0
571 * this may need to change for later XL family chips
572 */
573 lanes = sc->sc_pcie_lnktab.cfg[0].lanes;
574
575 if ((e391 != false) && ((lanes == 2) || (lanes == 4))) {
576 /*
577 * attempt work around for errata 3.9.1
578 * "PCIe Link-0 Registers Reset to Incorrect Values"
579 * the registers are write-once: if the firmware already wrote,
580 * then our writes are ignored; hope they did it right.
581 */
582 uint32_t queuectrl;
583 uint32_t bufdepth;
584 #ifdef DIAGNOSTIC
585 uint32_t r;
586 #endif
587
588 aprint_normal("%s: attempt work around for errata 3.9.1",
589 device_xname(sc->sc_dev));
590 if (lanes == 4) {
591 queuectrl = 0x00018074;
592 bufdepth = 0x001901D1;
593 } else {
594 queuectrl = 0x00018036;
595 bufdepth = 0x001900D9;
596 }
597
598 RMIXL_IOREG_WRITE(RMIXL_IO_DEV_PCIE_BE +
599 RMIXL_VC0_POSTED_RX_QUEUE_CTRL, queuectrl);
600 RMIXL_IOREG_WRITE(RMIXL_IO_DEV_PCIE_BE +
601 RMIXL_VC0_POSTED_BUFFER_DEPTH, bufdepth);
602
603 #ifdef DIAGNOSTIC
604 r = RMIXL_IOREG_READ(RMIXL_IO_DEV_PCIE_BE +
605 RMIXL_VC0_POSTED_RX_QUEUE_CTRL);
606 printf("\nVC0_POSTED_RX_QUEUE_CTRL %#x\n", r);
607
608 r = RMIXL_IOREG_READ(RMIXL_IO_DEV_PCIE_BE +
609 RMIXL_VC0_POSTED_BUFFER_DEPTH);
610 printf("VC0_POSTED_BUFFER_DEPTH %#x\n", r);
611 #endif
612 }
613 }
614
615 static void
616 rmixl_pcie_init(struct rmixl_pcie_softc *sc)
617 {
618 pci_chipset_tag_t pc = &sc->sc_pci_chipset;
619 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
620 struct extent *ioext, *memext;
621 #endif
622
623 pc->pc_conf_v = (void *)sc;
624 pc->pc_attach_hook = rmixl_pcie_attach_hook;
625 pc->pc_bus_maxdevs = rmixl_pcie_bus_maxdevs;
626 pc->pc_make_tag = rmixl_pcie_make_tag;
627 pc->pc_decompose_tag = rmixl_pcie_decompose_tag;
628 pc->pc_conf_read = rmixl_pcie_conf_read;
629 pc->pc_conf_write = rmixl_pcie_conf_write;
630
631 pc->pc_intr_v = (void *)sc;
632 pc->pc_intr_map = rmixl_pcie_intr_map;
633 pc->pc_intr_string = rmixl_pcie_intr_string;
634 pc->pc_intr_evcnt = rmixl_pcie_intr_evcnt;
635 pc->pc_intr_establish = rmixl_pcie_intr_establish;
636 pc->pc_intr_disestablish = rmixl_pcie_intr_disestablish;
637 pc->pc_conf_interrupt = rmixl_conf_interrupt;
638
639 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
640 /*
641 * Configure the PCI bus.
642 */
643 struct rmixl_config *rcp = &rmixl_configuration;
644
645 aprint_normal("%s: configuring PCI bus\n",
646 device_xname(sc->sc_dev));
647
648 ioext = extent_create("pciio",
649 rcp->rc_pci_io_pbase,
650 rcp->rc_pci_io_pbase + rcp->rc_pci_io_size - 1,
651 M_DEVBUF, NULL, 0, EX_NOWAIT);
652
653 memext = extent_create("pcimem",
654 rcp->rc_pci_mem_pbase,
655 rcp->rc_pci_mem_pbase + rcp->rc_pci_mem_size - 1,
656 M_DEVBUF, NULL, 0, EX_NOWAIT);
657
658 pci_configure_bus(pc, ioext, memext, NULL, 0, mips_dcache_align);
659
660 extent_destroy(ioext);
661 extent_destroy(memext);
662 #endif
663 }
664
665 static void
666 rmixl_pcie_init_ecfg(struct rmixl_pcie_softc *sc)
667 {
668 void *v;
669 pcitag_t tag;
670 pcireg_t r;
671
672 v = sc;
673 tag = rmixl_pcie_make_tag(v, 0, 0, 0);
674
675 #ifdef PCI_DEBUG
676 int i, offset;
677 static const int offtab[] =
678 { 0, 4, 8, 0xc, 0x10, 0x14, 0x18, 0x1c,
679 0x2c, 0x30, 0x34 };
680 for (i=0; i < sizeof(offtab)/sizeof(offtab[0]); i++) {
681 offset = 0x100 + offtab[i];
682 r = rmixl_pcie_conf_read(v, tag, offset);
683 printf("%s: %#x: %#x\n", __func__, offset, r);
684 }
685 #endif
686 r = rmixl_pcie_conf_read(v, tag, 0x100);
687 if (r == -1)
688 return; /* cannot access */
689
690 /* check pre-existing uncorrectable errs */
691 r = rmixl_pcie_conf_read(v, tag, RMIXL_PCIE_ECFG_UESR);
692 r &= ~PCIE_ECFG_UExR_RESV;
693 if (r != 0)
694 panic("%s: Uncorrectable Error Status: %#x\n",
695 __func__, r);
696
697 /* unmask all uncorrectable errs */
698 r = rmixl_pcie_conf_read(v, tag, RMIXL_PCIE_ECFG_UEMR);
699 r &= ~PCIE_ECFG_UExR_RESV;
700 rmixl_pcie_conf_write(v, tag, RMIXL_PCIE_ECFG_UEMR, r);
701
702 /* ensure default uncorrectable err severity confniguration */
703 r = rmixl_pcie_conf_read(v, tag, RMIXL_PCIE_ECFG_UEVR);
704 r &= ~PCIE_ECFG_UExR_RESV;
705 r |= PCIE_ECFG_UEVR_DFLT;
706 rmixl_pcie_conf_write(v, tag, RMIXL_PCIE_ECFG_UEVR, r);
707
708 /* check pre-existing correctable errs */
709 r = rmixl_pcie_conf_read(v, tag, RMIXL_PCIE_ECFG_CESR);
710 r &= ~PCIE_ECFG_CExR_RESV;
711 #ifdef DIAGNOSTIC
712 if (r != 0)
713 aprint_normal("%s: Correctable Error Status: %#x\n",
714 device_xname(sc->sc_dev), r);
715 #endif
716
717 /* unmask all correctable errs */
718 r = rmixl_pcie_conf_read(v, tag, RMIXL_PCIE_ECFG_CEMR);
719 r &= ~PCIE_ECFG_CExR_RESV;
720 rmixl_pcie_conf_write(v, tag, RMIXL_PCIE_ECFG_UEMR, r);
721
722 /* check pre-existing Root Error Status */
723 r = rmixl_pcie_conf_read(v, tag, RMIXL_PCIE_ECFG_RESR);
724 r &= ~PCIE_ECFG_RESR_RESV;
725 if (r != 0)
726 panic("%s: Root Error Status: %#x\n", __func__, r);
727 /* XXX TMP FIXME */
728
729 /* enable all Root errs */
730 r = (pcireg_t)(~PCIE_ECFG_RECR_RESV);
731 rmixl_pcie_conf_write(v, tag, RMIXL_PCIE_ECFG_RECR, r);
732
733
734 if (MIPS_PRID_IMPL(cpu_id) == MIPS_XLS408LITE) {
735 /*
736 * establish ISR for PCIE Fatal Error interrupt
737 * XXX for XLS408Lite, XLS2xx, XLS1xx only
738 * tested on XLS408Lite only
739 */
740 (void)rmixl_intr_establish(29, IPL_HIGH,
741 RMIXL_INTR_LEVEL, RMIXL_INTR_HIGH,
742 rmixl_pcie_error_intr, v);
743 }
744 #if defined(DEBUG) || defined(DDB)
745 rmixl_pcie_v = v;
746 #endif
747 }
748
749 void
750 rmixl_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz, int *iline)
751 {
752 DPRINTF(("%s: %p, %d, %d, %d, %d, %p\n",
753 __func__, v, bus, dev, ipin, swiz, iline));
754 }
755
756 void
757 rmixl_pcie_attach_hook(struct device *parent, struct device *self,
758 struct pcibus_attach_args *pba)
759 {
760 DPRINTF(("%s: pba_bus %d, pba_bridgetag %p, pc_conf_v %p\n",
761 __func__, pba->pba_bus, pba->pba_bridgetag,
762 pba->pba_pc->pc_conf_v));
763 }
764
765 int
766 rmixl_pcie_bus_maxdevs(void *v, int busno)
767 {
768 return (32); /* XXX depends on the family of XLS SoC */
769 }
770
771 /*
772 * XLS pci tag is a 40 bit address composed thusly:
773 * 39:25 (reserved)
774 * 24 Swap (0=little, 1=big endian)
775 * 23:16 Bus number
776 * 15:11 Device number
777 * 10:8 Function number
778 * 0:7 Register number
779 */
780 pcitag_t
781 rmixl_pcie_make_tag(void *v, int b, int d, int f)
782 {
783 return ((b << 16) | (d << 11) | (f << 8));
784 }
785
786 void
787 rmixl_pcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
788 {
789 if (bp != NULL)
790 *bp = (tag >> 16) & 0xff;
791 if (dp != NULL)
792 *dp = (tag >> 11) & 0x1f;
793 if (fp != NULL)
794 *fp = (tag >> 8) & 0x7;
795 }
796
797 void
798 rmixl_pcie_tag_print(const char *restrict s, void *v, pcitag_t tag, int offset,
799 vaddr_t va, u_long r)
800 {
801 int bus, dev, fun;
802
803 rmixl_pcie_decompose_tag(v, tag, &bus, &dev, &fun);
804 printf("%s: %d/%d/%d/%d - %#lx:%#lx\n",
805 s, bus, dev, fun, offset, va, r);
806 }
807
808 pcireg_t
809 rmixl_pcie_conf_read(void *v, pcitag_t tag, int offset)
810 {
811 struct rmixl_pcie_softc *sc = v;
812 bus_addr_t ba;
813 vaddr_t va;
814 pcireg_t rv;
815 uint64_t cfg0;
816 u_int s;
817
818 PCI_CONF_LOCK(s);
819 cfg0 = rmixl_cache_err_dis();
820
821 /*
822 * base bus addr depends on offset
823 */
824 if ((offset >= 0) && ( offset < 0x100)) {
825 ba = sc->sc_pcie_cfg_pbase;
826 } else if ((offset >= 0x100) && (offset <= 0x700)) {
827 ba = sc->sc_pcie_ecfg_pbase;
828 if (ba == -1)
829 return -1;
830 } else {
831 panic("%s: offset %#x: unknown", __func__, offset);
832 }
833 ba += (tag + offset);
834 va = (vaddr_t)RMIXL_PCI_VADDR(ba);
835 rv = RMIXL_PCI_READ(va);
836 if (rmixl_cache_err_check() != 0) {
837 #ifdef DIAGNOSTIC
838 int bus, dev, fun;
839
840 rmixl_pcie_decompose_tag(v, tag, &bus, &dev, &fun);
841 printf("%s: %d/%d/%d, offset %#x: bad address\n",
842 __func__, bus, dev, fun, offset);
843 #endif
844 rv = (pcireg_t) -1;
845 }
846
847 rmixl_cache_err_restore(cfg0);
848 PCI_CONF_UNLOCK(s);
849 return rv;
850 }
851
852 void
853 rmixl_pcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
854 {
855 struct rmixl_pcie_softc *sc = v;
856 bus_addr_t ba;
857 vaddr_t va;
858 uint64_t cfg0;
859 u_int s;
860
861 PCI_CONF_LOCK(s);
862 cfg0 = rmixl_cache_err_dis();
863
864 /*
865 * base bus addr depends on offset
866 */
867 if ((offset >= 0) && ( offset < 0x100)) {
868 ba = sc->sc_pcie_cfg_pbase;
869 } else if ((offset >= 0x100) && (offset <= 0x700)) {
870 ba = sc->sc_pcie_ecfg_pbase;
871 if (ba == -1)
872 panic("%s: offset %#x: PCIe ECFG space not connfigured",
873 __func__, offset);
874 } else {
875 panic("%s: offset %#x: unknown", __func__, offset);
876 }
877 ba += (tag + offset);
878 va = (vaddr_t)RMIXL_PCI_VADDR(ba);
879 RMIXL_PCI_WRITE(ba, val);
880 #ifdef DIAGNOSTIC
881 if (rmixl_cache_err_check() != 0) {
882 int bus, dev, fun;
883
884 rmixl_pcie_decompose_tag(v, tag, &bus, &dev, &fun);
885 printf("%s: %d/%d/%d, offset %#x: bad address\n",
886 __func__, bus, dev, fun, offset);
887 }
888 #endif
889
890 rmixl_cache_err_restore(cfg0);
891 PCI_CONF_UNLOCK(s);
892 }
893
894 int
895 rmixl_pcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *pih)
896 {
897 u_int irq;
898
899 #ifdef DEBUG
900 DPRINTF(("%s: ps_bus %d, pa_intrswiz %#x, pa_intrtag %#lx,"
901 " pa_intrpin %d, pa_intrline %d, pa_rawintrpin %d\n",
902 __func__, pa->pa_bus, pa->pa_intrswiz, pa->pa_intrtag,
903 pa->pa_intrpin, pa->pa_intrline, pa->pa_rawintrpin));
904 #endif
905
906 /*
907 * XXX cpu implementation specific
908 */
909 switch (MIPS_PRID_IMPL(cpu_id)) {
910 case MIPS_XLS408LITE:
911 switch (pa->pa_bus) {
912 case 1:
913 irq = 26;
914 break;
915 case 2:
916 irq = 27;
917 break;
918 default:
919 panic("%s: bad bus %d\n", __func__, pa->pa_bus);
920 }
921 break;
922 case MIPS_XLS416:
923 case MIPS_XLS616:
924 switch (pa->pa_bus) {
925 case 1:
926 irq = 26;
927 break;
928 case 2:
929 irq = 27;
930 break;
931 case 3:
932 irq = 28;
933 break;
934 case 4:
935 irq = 29;
936 break;
937 default:
938 panic("%s: bad bus %d\n", __func__, pa->pa_bus);
939 }
940 break;
941 default:
942 panic("%s: cpu IMPL %#x not supported\n",
943 __func__, MIPS_PRID_IMPL(cpu_id));
944 }
945
946 *pih = irq;
947
948 return 0;
949 }
950
951 const char *
952 rmixl_pcie_intr_string(void *v, pci_intr_handle_t pih)
953 {
954 const char *name = "(illegal)";
955 int irq = (int)pih;
956
957 switch (MIPS_PRID_IMPL(cpu_id)) {
958 case MIPS_XLS408LITE:
959 switch (irq) {
960 case 26:
961 case 27:
962 name = rmixl_intr_string(irq);
963 break;
964 }
965 break;
966 case MIPS_XLS616:
967 switch (irq) {
968 case 26:
969 case 27:
970 case 28:
971 case 29:
972 name = rmixl_intr_string(irq);
973 break;
974 }
975 break;
976 }
977
978 return name;
979 }
980
981 const struct evcnt *
982 rmixl_pcie_intr_evcnt(void *v, pci_intr_handle_t pih)
983 {
984 return NULL;
985 }
986
987 static int
988 rmixl_pcie_irq(pci_intr_handle_t pih)
989 {
990 return (int)pih;
991 }
992
993 static void *
994 rmixl_pcie_intr_establish(void *v, pci_intr_handle_t pih, int ipl,
995 int (*func)(void *), void *arg)
996 {
997 return rmixl_intr_establish(rmixl_pcie_irq((int)pih), ipl,
998 RMIXL_INTR_LEVEL, RMIXL_INTR_HIGH, func, arg);
999 }
1000
1001 static void
1002 rmixl_pcie_intr_disestablish(void *v, void *ih)
1003 {
1004 rmixl_intr_disestablish(ih);
1005 }
1006
1007 #if defined(DEBUG) || defined(DDB)
1008 /* this function exists to facilitate call from ddb */
1009 int
1010 rmixl_pcie_error_check(void)
1011 {
1012 if (rmixl_pcie_v != 0)
1013 return _rmixl_pcie_error_check(rmixl_pcie_v);
1014 return -1;
1015 }
1016 #endif
1017
1018 STATIC int
1019 _rmixl_pcie_error_check(void *v)
1020 {
1021 int i, offset;
1022 pcireg_t r;
1023 pcitag_t tag;
1024 int err=0;
1025 #ifdef DIAGNOSTIC
1026 pcireg_t regs[PCIE_ECFG_ERRS_OFFTAB_NENTRIES];
1027 #endif
1028
1029 tag = rmixl_pcie_make_tag(v, 0, 0, 0); /* XXX */
1030
1031 for (i=0; i < PCIE_ECFG_ERRS_OFFTAB_NENTRIES; i++) {
1032 offset = pcie_ecfg_errs_tab[i].offset;
1033 r = rmixl_pcie_conf_read(v, tag, offset);
1034 #ifdef DIAGNOSTIC
1035 regs[i] = r;
1036 #endif
1037 if (r != 0) {
1038 pcireg_t rw1c = r & pcie_ecfg_errs_tab[i].rw1c;
1039 if (rw1c != 0) {
1040 /* attempt to clear the error */
1041 rmixl_pcie_conf_write(v, tag, offset, rw1c);
1042 };
1043 if (offset == RMIXL_PCIE_ECFG_CESR)
1044 err |= 1; /* correctable */
1045 else
1046 err |= 2; /* uncorrectable */
1047 }
1048 }
1049 #ifdef DIAGNOSTIC
1050 if (err != 0) {
1051 for (i=0; i < PCIE_ECFG_ERRS_OFFTAB_NENTRIES; i++) {
1052 offset = pcie_ecfg_errs_tab[i].offset;
1053 printf("%s: %#x: %#x\n", __func__, offset, regs[i]);
1054 }
1055 }
1056 #endif
1057
1058 return err;
1059 }
1060
1061 static int
1062 rmixl_pcie_error_intr(void *v)
1063 {
1064 if (_rmixl_pcie_error_check(v) < 2)
1065 return 0; /* correctable */
1066
1067 /* uncorrectable */
1068 #if DDB
1069 Debugger();
1070 #endif
1071
1072 /* XXX reset and recover? */
1073
1074 panic("%s\n", __func__);
1075 }
1076