rmixl_obio.c revision 1.3 1 1.3 matt /* $NetBSD: rmixl_obio.c,v 1.3 2011/02/20 07:48:37 matt Exp $ */
2 1.2 matt
3 1.2 matt /*
4 1.2 matt * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
5 1.2 matt * All rights reserved.
6 1.2 matt *
7 1.2 matt * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 1.2 matt *
9 1.2 matt * Redistribution and use in source and binary forms, with or without
10 1.2 matt * modification, are permitted provided that the following conditions
11 1.2 matt * are met:
12 1.2 matt * 1. Redistributions of source code must retain the above copyright
13 1.2 matt * notice, this list of conditions and the following disclaimer.
14 1.2 matt * 2. Redistributions in binary form must reproduce the above copyright
15 1.2 matt * notice, this list of conditions and the following disclaimer in the
16 1.2 matt * documentation and/or other materials provided with the distribution.
17 1.2 matt * 3. All advertising materials mentioning features or use of this software
18 1.2 matt * must display the following acknowledgement:
19 1.2 matt * This product includes software developed for the NetBSD Project by
20 1.2 matt * Wasabi Systems, Inc.
21 1.2 matt * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 1.2 matt * or promote products derived from this software without specific prior
23 1.2 matt * written permission.
24 1.2 matt *
25 1.2 matt * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 1.2 matt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 1.2 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 1.2 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 1.2 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 1.2 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 1.2 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 1.2 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 1.2 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 1.2 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 1.2 matt * POSSIBILITY OF SUCH DAMAGE.
36 1.2 matt */
37 1.2 matt
38 1.2 matt /*
39 1.2 matt * On-board device autoconfiguration support for RMI {XLP, XLR, XLS} chips
40 1.2 matt */
41 1.2 matt
42 1.2 matt #include <sys/cdefs.h>
43 1.3 matt __KERNEL_RCSID(0, "$NetBSD: rmixl_obio.c,v 1.3 2011/02/20 07:48:37 matt Exp $");
44 1.2 matt
45 1.2 matt #include "locators.h"
46 1.2 matt #include "pci.h"
47 1.2 matt
48 1.2 matt #include <sys/param.h>
49 1.2 matt #include <sys/systm.h>
50 1.2 matt #include <sys/device.h>
51 1.2 matt #include <sys/extent.h>
52 1.2 matt #include <sys/malloc.h>
53 1.2 matt
54 1.2 matt #define _MIPS_BUS_DMA_PRIVATE
55 1.2 matt #include <machine/bus.h>
56 1.2 matt
57 1.2 matt #include <machine/int_fmtio.h>
58 1.2 matt
59 1.2 matt #include <mips/rmi/rmixlreg.h>
60 1.2 matt #include <mips/rmi/rmixlvar.h>
61 1.3 matt #include <mips/rmi/rmixl_intr.h>
62 1.2 matt #include <mips/rmi/rmixl_obiovar.h>
63 1.2 matt #include <mips/rmi/rmixl_pcievar.h>
64 1.2 matt
65 1.3 matt #include <evbmips/rmixl/autoconf.h>
66 1.3 matt
67 1.2 matt #ifdef OBIO_DEBUG
68 1.3 matt int obio_rmixl_debug = OBIO_DEBUG;
69 1.3 matt # define DPRINTF(x) do { if (obio_rmixl_debug) printf x ; } while (0)
70 1.2 matt #else
71 1.2 matt # define DPRINTF(x)
72 1.2 matt #endif
73 1.2 matt
74 1.2 matt static int obio_match(device_t, cfdata_t, void *);
75 1.2 matt static void obio_attach(device_t, device_t, void *);
76 1.2 matt static int obio_print(void *, const char *);
77 1.2 matt static int obio_search(device_t, cfdata_t, const int *, void *);
78 1.2 matt static void obio_bus_init(struct obio_softc *);
79 1.3 matt static void obio_dma_init_64(bus_dma_tag_t);
80 1.2 matt static int rmixl_addr_error_intr(void *);
81 1.2 matt
82 1.2 matt
83 1.3 matt CFATTACH_DECL_NEW(obio_rmixl, sizeof(struct obio_softc),
84 1.2 matt obio_match, obio_attach, NULL, NULL);
85 1.2 matt
86 1.2 matt int obio_found;
87 1.2 matt
88 1.2 matt static int
89 1.2 matt obio_match(device_t parent, cfdata_t cf, void *aux)
90 1.2 matt {
91 1.3 matt struct mainbus_attach_args *aa = aux;
92 1.3 matt
93 1.3 matt if (obio_found == 0)
94 1.3 matt if (strncmp(aa->ma_name, cf->cf_name, strlen(cf->cf_name)) == 0)
95 1.3 matt return 1;
96 1.3 matt
97 1.3 matt return 0;
98 1.2 matt }
99 1.2 matt
100 1.2 matt static void
101 1.2 matt obio_attach(device_t parent, device_t self, void *aux)
102 1.2 matt {
103 1.2 matt struct obio_softc *sc = device_private(self);
104 1.2 matt bus_addr_t ba;
105 1.2 matt
106 1.2 matt obio_found = 1;
107 1.2 matt sc->sc_dev = self;
108 1.2 matt
109 1.2 matt ba = (bus_addr_t)rmixl_configuration.rc_io_pbase;
110 1.2 matt KASSERT(ba != 0);
111 1.2 matt
112 1.2 matt obio_bus_init(sc);
113 1.2 matt
114 1.2 matt aprint_normal(" addr %#"PRIxBUSADDR" size %#"PRIxBUSSIZE"\n",
115 1.2 matt ba, (bus_size_t)RMIXL_IO_DEV_SIZE);
116 1.2 matt aprint_naive("\n");
117 1.2 matt
118 1.2 matt /*
119 1.2 matt * Attach on-board devices as specified in the kernel config file.
120 1.2 matt */
121 1.2 matt config_search_ia(obio_search, self, "obio", NULL);
122 1.2 matt
123 1.2 matt }
124 1.2 matt
125 1.2 matt static int
126 1.2 matt obio_print(void *aux, const char *pnp)
127 1.2 matt {
128 1.2 matt struct obio_attach_args *obio = aux;
129 1.2 matt
130 1.2 matt if (obio->obio_addr != OBIOCF_ADDR_DEFAULT) {
131 1.2 matt aprint_normal(" addr %#"PRIxBUSADDR, obio->obio_addr);
132 1.2 matt if (obio->obio_size != OBIOCF_SIZE_DEFAULT)
133 1.2 matt aprint_normal("-%#"PRIxBUSADDR,
134 1.2 matt obio->obio_addr + (obio->obio_size - 1));
135 1.2 matt }
136 1.2 matt if (obio->obio_mult != OBIOCF_MULT_DEFAULT)
137 1.2 matt aprint_normal(" mult %d", obio->obio_mult);
138 1.2 matt if (obio->obio_intr != OBIOCF_INTR_DEFAULT)
139 1.2 matt aprint_normal(" intr %d", obio->obio_intr);
140 1.3 matt if (obio->obio_tmsk != OBIOCF_TMSK_DEFAULT)
141 1.3 matt aprint_normal(" tmsk %d", obio->obio_tmsk);
142 1.2 matt
143 1.2 matt return (UNCONF);
144 1.2 matt }
145 1.2 matt
146 1.2 matt static int
147 1.2 matt obio_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
148 1.2 matt {
149 1.2 matt struct obio_softc *sc = device_private(parent);
150 1.2 matt struct obio_attach_args obio;
151 1.2 matt
152 1.3 matt obio.obio_eb_bst = sc->sc_eb_bst;
153 1.3 matt obio.obio_el_bst = sc->sc_el_bst;
154 1.2 matt obio.obio_addr = cf->cf_loc[OBIOCF_ADDR];
155 1.2 matt obio.obio_size = cf->cf_loc[OBIOCF_SIZE];
156 1.2 matt obio.obio_mult = cf->cf_loc[OBIOCF_MULT];
157 1.2 matt obio.obio_intr = cf->cf_loc[OBIOCF_INTR];
158 1.3 matt obio.obio_tmsk = cf->cf_loc[OBIOCF_TMSK];
159 1.2 matt obio.obio_29bit_dmat = sc->sc_29bit_dmat;
160 1.2 matt obio.obio_32bit_dmat = sc->sc_32bit_dmat;
161 1.2 matt obio.obio_64bit_dmat = sc->sc_64bit_dmat;
162 1.2 matt
163 1.2 matt if (config_match(parent, cf, &obio) > 0)
164 1.2 matt config_attach(parent, cf, &obio, obio_print);
165 1.2 matt
166 1.2 matt return 0;
167 1.2 matt }
168 1.2 matt
169 1.2 matt static void
170 1.2 matt obio_bus_init(struct obio_softc *sc)
171 1.2 matt {
172 1.2 matt struct rmixl_config *rcp = &rmixl_configuration;
173 1.2 matt static int done = 0;
174 1.3 matt int error;
175 1.2 matt
176 1.2 matt if (done)
177 1.2 matt return;
178 1.2 matt done = 1;
179 1.2 matt
180 1.3 matt /* obio (devio) space, Big Endian */
181 1.3 matt if (rcp->rc_obio_eb_memt.bs_cookie == 0)
182 1.3 matt rmixl_obio_eb_bus_mem_init(&rcp->rc_obio_eb_memt, rcp);
183 1.3 matt
184 1.3 matt /* obio (devio) space, Little Endian */
185 1.3 matt if (rcp->rc_obio_el_memt.bs_cookie == 0)
186 1.3 matt rmixl_obio_el_bus_mem_init(&rcp->rc_obio_el_memt, rcp);
187 1.3 matt
188 1.3 matt /* dma space for all memory, including >= 4GB */
189 1.3 matt if (rcp->rc_dma_tag._cookie == 0)
190 1.3 matt obio_dma_init_64(&rcp->rc_dma_tag);
191 1.3 matt rcp->rc_64bit_dmat = &rcp->rc_dma_tag;
192 1.3 matt
193 1.3 matt /* dma space for addr < 4GB */
194 1.3 matt if (rcp->rc_32bit_dmat == NULL) {
195 1.3 matt error = bus_dmatag_subregion(rcp->rc_64bit_dmat,
196 1.3 matt 0, (bus_addr_t)1 << 32, &rcp->rc_32bit_dmat, 0);
197 1.3 matt if (error)
198 1.3 matt panic("%s: failed to create 32bit dma tag: %d",
199 1.3 matt __func__, error);
200 1.3 matt }
201 1.2 matt
202 1.2 matt /* dma space for addr < 512MB */
203 1.3 matt if (rcp->rc_29bit_dmat == NULL) {
204 1.3 matt error = bus_dmatag_subregion(rcp->rc_32bit_dmat,
205 1.3 matt 0, (bus_addr_t)1 << 29, &rcp->rc_29bit_dmat, 0);
206 1.3 matt if (error)
207 1.3 matt panic("%s: failed to create 29bit dma tag: %d",
208 1.3 matt __func__, error);
209 1.3 matt }
210 1.2 matt
211 1.2 matt sc->sc_base = (bus_addr_t)rcp->rc_io_pbase;
212 1.2 matt sc->sc_size = (bus_size_t)RMIXL_IO_DEV_SIZE;
213 1.3 matt sc->sc_eb_bst = (bus_space_tag_t)&rcp->rc_obio_eb_memt;
214 1.3 matt sc->sc_el_bst = (bus_space_tag_t)&rcp->rc_obio_el_memt;
215 1.3 matt sc->sc_29bit_dmat = rcp->rc_29bit_dmat;
216 1.3 matt sc->sc_32bit_dmat = rcp->rc_32bit_dmat;
217 1.3 matt sc->sc_64bit_dmat = rcp->rc_64bit_dmat;
218 1.2 matt }
219 1.2 matt
220 1.2 matt static void
221 1.3 matt obio_dma_init_64(bus_dma_tag_t t)
222 1.2 matt {
223 1.2 matt t->_cookie = t;
224 1.2 matt t->_wbase = 0;
225 1.3 matt t->_bounce_alloc_lo = 0;
226 1.3 matt t->_bounce_alloc_hi = 0;
227 1.3 matt t->_dmamap_ops = mips_bus_dmamap_ops;
228 1.3 matt t->_dmamem_ops = mips_bus_dmamem_ops;
229 1.3 matt t->_dmatag_ops = mips_bus_dmatag_ops;
230 1.2 matt }
231 1.2 matt
232 1.2 matt void
233 1.2 matt rmixl_addr_error_init(void)
234 1.2 matt {
235 1.2 matt uint32_t r;
236 1.2 matt
237 1.2 matt /*
238 1.2 matt * activate error addr detection on all (configurable) devices
239 1.2 matt * preserve reserved bit fields
240 1.2 matt * note some of these bits are read-only (writes are ignored)
241 1.2 matt */
242 1.2 matt r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_DEVICE_MASK);
243 1.2 matt r |= ~(__BITS(19,16) | __BITS(10,9) | __BITS(7,5));
244 1.2 matt RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_DEVICE_MASK, r);
245 1.2 matt
246 1.2 matt /*
247 1.2 matt * enable the address error interrupts
248 1.2 matt * "upgrade" cache and CPU errors to A1
249 1.2 matt */
250 1.2 matt #define _ADDR_ERR_DEVSTAT_A1 (__BIT(8) | __BIT(1) | __BIT(0))
251 1.2 matt #define _ADDR_ERR_RESV \
252 1.2 matt (__BITS(31,21) | __BITS(15,14) | __BITS(10,9) | __BITS(7,2))
253 1.2 matt #define _BITERR_INT_EN_RESV (__BITS(31,8) | __BIT(4))
254 1.2 matt
255 1.2 matt r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_EN);
256 1.2 matt r &= _ADDR_ERR_RESV;
257 1.2 matt r |= ~_ADDR_ERR_RESV;
258 1.2 matt RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR0_EN, r);
259 1.2 matt
260 1.2 matt r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_UPG);
261 1.2 matt r &= _ADDR_ERR_RESV;
262 1.2 matt r |= _ADDR_ERR_DEVSTAT_A1;
263 1.2 matt RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR0_UPG, r);
264 1.2 matt
265 1.2 matt /*
266 1.2 matt * clear the log regs and the dev stat (interrupt status) regs
267 1.2 matt * "Write any value to bit[0] to clear"
268 1.2 matt */
269 1.2 matt r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_CLEAR);
270 1.2 matt RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_AERR1_CLEAR, r);
271 1.2 matt
272 1.2 matt /*
273 1.2 matt * enable the double bit error interrupts
274 1.2 matt * (assume reserved bits, which are read-only, are ignored)
275 1.2 matt */
276 1.2 matt r = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_BITERR_INT_EN);
277 1.2 matt r &= _BITERR_INT_EN_RESV;
278 1.2 matt r |= __BITS(7,5);
279 1.2 matt RMIXL_IOREG_WRITE(RMIXL_ADDR_ERR_BITERR_INT_EN, r);
280 1.2 matt
281 1.2 matt /*
282 1.2 matt * establish address error ISR
283 1.3 matt * XXX assuming "int 16 (bridge_tb)" is our irq
284 1.3 matt * XXX is true for XLS family only
285 1.2 matt */
286 1.3 matt if (cpu_rmixls(mips_options.mips_cpu))
287 1.3 matt rmixl_intr_establish(16, 1, IPL_HIGH,
288 1.3 matt RMIXL_TRIG_LEVEL, RMIXL_POLR_HIGH,
289 1.3 matt rmixl_addr_error_intr, NULL, false);
290 1.2 matt }
291 1.2 matt
292 1.2 matt int
293 1.2 matt rmixl_addr_error_check(void)
294 1.2 matt {
295 1.2 matt uint32_t aerr0_devstat;
296 1.2 matt uint32_t aerr0_log1;
297 1.2 matt uint32_t aerr0_log2;
298 1.2 matt uint32_t aerr0_log3;
299 1.2 matt uint32_t aerr1_devstat;
300 1.2 matt uint32_t aerr1_log1;
301 1.2 matt uint32_t aerr1_log2;
302 1.2 matt uint32_t aerr1_log3;
303 1.2 matt uint32_t sbe_counts;
304 1.2 matt uint32_t dbe_counts;
305 1.2 matt
306 1.2 matt aerr0_devstat = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_DEVSTAT);
307 1.2 matt aerr0_log1 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG1);
308 1.2 matt aerr0_log2 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG2);
309 1.2 matt aerr0_log3 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR0_LOG3);
310 1.2 matt
311 1.2 matt aerr1_devstat = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_DEVSTAT);
312 1.2 matt aerr1_log1 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG1);
313 1.2 matt aerr1_log2 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG2);
314 1.2 matt aerr1_log3 = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_AERR1_LOG3);
315 1.2 matt
316 1.2 matt sbe_counts = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_SBE_COUNTS);
317 1.2 matt dbe_counts = RMIXL_IOREG_READ(RMIXL_ADDR_ERR_DBE_COUNTS);
318 1.2 matt
319 1.2 matt if (aerr0_log1|aerr0_log2|aerr0_log3
320 1.2 matt |aerr1_log1|aerr1_log2|aerr1_log3
321 1.2 matt |dbe_counts) {
322 1.2 matt printf("aerr0: stat %#x, logs: %#x, %#x, %#x\n",
323 1.2 matt aerr0_devstat, aerr0_log1, aerr0_log2, aerr0_log2);
324 1.2 matt printf("aerr1: stat %#x, logs: %#x, %#x, %#x\n",
325 1.2 matt aerr1_devstat, aerr1_log1, aerr1_log2, aerr1_log2);
326 1.2 matt printf("1-bit errors: %#x, 2-bit errors: %#x\n",
327 1.2 matt sbe_counts, dbe_counts);
328 1.2 matt return 1;
329 1.2 matt }
330 1.2 matt return 0;
331 1.2 matt }
332 1.2 matt
333 1.2 matt static int
334 1.2 matt rmixl_addr_error_intr(void *arg)
335 1.2 matt {
336 1.2 matt int err;
337 1.2 matt
338 1.2 matt err = rmixl_addr_error_check();
339 1.2 matt if (err != 0) {
340 1.2 matt #if DDB
341 1.2 matt printf("%s\n", __func__);
342 1.2 matt Debugger();
343 1.2 matt #endif
344 1.2 matt panic("Address Error");
345 1.2 matt }
346 1.2 matt return 1;
347 1.2 matt }
348