4 * Copyright (c) 2001, 2002, 2003 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 * On-board device autoconfiguration support for RMI {XLP, XLR, XLS} chips
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD$");
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/device.h>
52 #include <sys/extent.h>
53 #include <sys/malloc.h>
55 #define _MIPS_BUS_DMA_PRIVATE
56 #include <machine/bus.h>
58 #include <machine/int_fmtio.h>
60 #include <mips/rmi/rmixlreg.h>
61 #include <mips/rmi/rmixlvar.h>
62 #include <mips/rmi/rmixl_obiovar.h>
63 #include <mips/rmi/rmixl_pcievar.h>
66 int obio_debug
= OBIO_DEBUG
;
67 # define DPRINTF(x) do { if (obio_debug) printf x ; } while (0)
72 static int obio_match(device_t
, cfdata_t
, void *);
73 static void obio_attach(device_t
, device_t
, void *);
74 static int obio_print(void *, const char *);
75 static int obio_search(device_t
, cfdata_t
, const int *, void *);
76 static void obio_bus_init(struct obio_softc
*);
77 static void obio_dma_init_29(bus_dma_tag_t
);
78 static int rmixl_addr_error_intr(void *);
81 CFATTACH_DECL_NEW(obio
, sizeof(struct obio_softc
),
82 obio_match
, obio_attach
, NULL
, NULL
);
87 obio_match(device_t parent
, cfdata_t cf
, void *aux
)
95 obio_attach(device_t parent
, device_t self
, void *aux
)
97 struct obio_softc
*sc
= device_private(self
);
103 ba
= (bus_addr_t
)rmixl_configuration
.rc_io_pbase
;
108 aprint_normal(" addr %#"PRIxBUSADDR
" size %#"PRIxBUSSIZE
"\n",
109 ba
, (bus_size_t
)RMIXL_IO_DEV_SIZE
);
113 * Attach on-board devices as specified in the kernel config file.
115 config_search_ia(obio_search
, self
, "obio", NULL
);
120 obio_print(void *aux
, const char *pnp
)
122 struct obio_attach_args
*obio
= aux
;
124 if (obio
->obio_addr
!= OBIOCF_ADDR_DEFAULT
) {
125 aprint_normal(" addr %#"PRIxBUSADDR
, obio
->obio_addr
);
126 if (obio
->obio_size
!= OBIOCF_SIZE_DEFAULT
)
127 aprint_normal("-%#"PRIxBUSADDR
,
128 obio
->obio_addr
+ (obio
->obio_size
- 1));
130 if (obio
->obio_mult
!= OBIOCF_MULT_DEFAULT
)
131 aprint_normal(" mult %d", obio
->obio_mult
);
132 if (obio
->obio_intr
!= OBIOCF_INTR_DEFAULT
)
133 aprint_normal(" intr %d", obio
->obio_intr
);
139 obio_search(device_t parent
, cfdata_t cf
, const int *ldesc
, void *aux
)
141 struct obio_softc
*sc
= device_private(parent
);
142 struct obio_attach_args obio
;
144 obio
.obio_bst
= sc
->sc_bst
;
145 obio
.obio_addr
= cf
->cf_loc
[OBIOCF_ADDR
];
146 obio
.obio_size
= cf
->cf_loc
[OBIOCF_SIZE
];
147 obio
.obio_mult
= cf
->cf_loc
[OBIOCF_MULT
];
148 obio
.obio_intr
= cf
->cf_loc
[OBIOCF_INTR
];
149 obio
.obio_29bit_dmat
= sc
->sc_29bit_dmat
;
150 obio
.obio_32bit_dmat
= sc
->sc_32bit_dmat
;
151 obio
.obio_64bit_dmat
= sc
->sc_64bit_dmat
;
153 if (config_match(parent
, cf
, &obio
) > 0)
154 config_attach(parent
, cf
, &obio
, obio_print
);
160 obio_bus_init(struct obio_softc
*sc
)
162 struct rmixl_config
*rcp
= &rmixl_configuration
;
169 /* obio (devio) space */
170 if (rcp
->rc_obio_memt
.bs_cookie
== 0)
171 rmixl_obio_bus_mem_init(&rcp
->rc_obio_memt
, rcp
);
173 /* dma space for addr < 512MB */
174 if (rcp
->rc_29bit_dmat
._cookie
== 0)
175 obio_dma_init_29(&rcp
->rc_29bit_dmat
);
177 /* dma space for addr < 4GB */
178 if (rcp
->rc_32bit_dmat
._cookie
== 0)
179 obio_dma_init_32(&rcp
->rc_32bit_dmat
);
180 /* dma space for all memory, including >= 4GB */
181 if (rcp
->rc_64bit_dmat
._cookie
== 0)
182 obio_dma_init_64(&rcp
->rc_64bit_dmat
);
185 sc
->sc_base
= (bus_addr_t
)rcp
->rc_io_pbase
;
186 sc
->sc_size
= (bus_size_t
)RMIXL_IO_DEV_SIZE
;
187 sc
->sc_bst
= (bus_space_tag_t
)&rcp
->rc_obio_memt
;
188 sc
->sc_29bit_dmat
= &rcp
->rc_29bit_dmat
;
190 sc
->sc_32bit_dmat
= &rcp
->rc_32bit_dmat
;
191 sc
->sc_64bit_dmat
= &rcp
->rc_64bit_dmat
;
193 sc
->sc_32bit_dmat
= NULL
;
194 sc
->sc_64bit_dmat
= NULL
;
199 obio_bus_dmamap_sync(bus_dma_tag_t t
, bus_dmamap_t map
, bus_addr_t offset
,
200 bus_size_t len
, int ops
)
206 obio_dma_init_29(bus_dma_tag_t t
)
214 t
->_wsize
= MIPS_KSEG1_START
- MIPS_KSEG0_START
;
216 t
->_dmamap_create
= _bus_dmamap_create
;
217 t
->_dmamap_destroy
= _bus_dmamap_destroy
;
218 t
->_dmamap_load
= _bus_dmamap_load
;
219 t
->_dmamap_load_mbuf
= _bus_dmamap_load_mbuf
;
220 t
->_dmamap_load_uio
= _bus_dmamap_load_uio
;
221 t
->_dmamap_load_raw
= _bus_dmamap_load_raw
;
222 t
->_dmamap_unload
= _bus_dmamap_unload
;
224 t
->_dmamap_sync
= obio_bus_dmamap_sync
;
226 t
->_dmamem_alloc
= _bus_dmamem_alloc
;
227 t
->_dmamem_free
= _bus_dmamem_free
;
228 t
->_dmamem_map
= _bus_dmamem_map
;
229 t
->_dmamem_unmap
= _bus_dmamem_unmap
;
230 t
->_dmamem_mmap
= _bus_dmamem_mmap
;
234 rmixl_addr_error_init(void)
239 * activate error addr detection on all (configurable) devices
240 * preserve reserved bit fields
241 * note some of these bits are read-only (writes are ignored)
243 r
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_DEVICE_MASK
);
244 r
|= ~(__BITS(19,16) | __BITS(10,9) | __BITS(7,5));
245 RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_DEVICE_MASK
, r
);
248 * enable the address error interrupts
249 * "upgrade" cache and CPU errors to A1
251 #define _ADDR_ERR_DEVSTAT_A1 (__BIT(8) | __BIT(1) | __BIT(0))
252 #define _ADDR_ERR_RESV \
253 (__BITS(31,21) | __BITS(15,14) | __BITS(10,9) | __BITS(7,2))
254 #define _BITERR_INT_EN_RESV (__BITS(31,8) | __BIT(4))
256 r
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_EN
);
258 r
|= ~_ADDR_ERR_RESV
;
259 RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR0_EN
, r
);
261 r
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_UPG
);
263 r
|= _ADDR_ERR_DEVSTAT_A1
;
264 RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR0_UPG
, r
);
267 * clear the log regs and the dev stat (interrupt status) regs
268 * "Write any value to bit[0] to clear"
270 r
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_CLEAR
);
271 RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR1_CLEAR
, r
);
274 * enable the double bit error interrupts
275 * (assume reserved bits, which are read-only, are ignored)
277 r
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_BITERR_INT_EN
);
278 r
&= _BITERR_INT_EN_RESV
;
280 RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_BITERR_INT_EN
, r
);
283 * establish address error ISR
284 * XXX assuming "int 16 (bridge_tb)" is out irq
286 rmixl_intr_establish(16, IPL_HIGH
, RMIXL_INTR_LEVEL
, RMIXL_INTR_HIGH
,
287 rmixl_addr_error_intr
, NULL
);
291 rmixl_addr_error_check(void)
293 uint32_t aerr0_devstat
;
297 uint32_t aerr1_devstat
;
304 aerr0_devstat
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_DEVSTAT
);
305 aerr0_log1
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG1
);
306 aerr0_log2
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG2
);
307 aerr0_log3
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG3
);
309 aerr1_devstat
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_DEVSTAT
);
310 aerr1_log1
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG1
);
311 aerr1_log2
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG2
);
312 aerr1_log3
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG3
);
314 sbe_counts
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_SBE_COUNTS
);
315 dbe_counts
= RMIXL_IOREG_READ(RMIXL_ADDR_ERR_DBE_COUNTS
);
317 if (aerr0_log1
|aerr0_log2
|aerr0_log3
318 |aerr1_log1
|aerr1_log2
|aerr1_log3
320 printf("aerr0: stat %#x, logs: %#x, %#x, %#x\n",
321 aerr0_devstat
, aerr0_log1
, aerr0_log2
, aerr0_log2
);
322 printf("aerr1: stat %#x, logs: %#x, %#x, %#x\n",
323 aerr1_devstat
, aerr1_log1
, aerr1_log2
, aerr1_log2
);
324 printf("1-bit errors: %#x, 2-bit errors: %#x\n",
325 sbe_counts
, dbe_counts
);
332 rmixl_addr_error_intr(void *arg
)
336 err
= rmixl_addr_error_check();
339 printf("%s\n", __func__
);
342 panic("Address Error");