1 /* $NetBSD: imc.c,v 1.28 2007/02/19 20:14:30 rumble Exp $ */
4 * Copyright (c) 2001 Rafal K. Boni
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: imc.c,v 1.28 2007/02/19 20:14:30 rumble Exp $");
33 #include <sys/param.h>
34 #include <sys/device.h>
35 #include <sys/systm.h>
37 #include <machine/cpu.h>
38 #include <machine/locore.h>
39 #include <machine/autoconf.h>
40 #include <machine/bus.h>
41 #include <machine/machtype.h>
42 #include <machine/sysconf.h>
44 #include <sgimips/dev/imcreg.h>
45 #include <sgimips/dev/imcvar.h>
47 #include <sgimips/gio/giovar.h>
55 bus_space_handle_t ioh
;
60 static int imc_match(struct device
*, struct cfdata
*, void *);
61 static void imc_attach(struct device
*, struct device
*, void *);
62 static int imc_print(void *, const char *);
63 static void imc_bus_reset(void);
64 static void imc_bus_error(uint32_t, uint32_t, uint32_t, uint32_t);
65 static void imc_watchdog_reset(void);
66 static void imc_watchdog_disable(void);
67 static void imc_watchdog_enable(void);
69 CFATTACH_DECL(imc
, sizeof(struct imc_softc
),
70 imc_match
, imc_attach
, NULL
, NULL
);
72 struct imc_attach_args
{
75 bus_space_tag_t iaa_st
;
76 bus_space_handle_t iaa_sh
;
86 int imc_gio64_arb_config(int, uint32_t);
91 imc_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
94 if ((mach_type
== MACH_SGI_IP22
) || (mach_type
== MACH_SGI_IP20
))
101 imc_attach(struct device
*parent
, struct device
*self
, void *aux
)
104 struct imc_attach_args iaa
;
105 struct mainbus_attach_args
*ma
= aux
;
108 isc
.iot
= SGIMIPS_BUS_SPACE_HPC
;
109 if (bus_space_map(isc
.iot
, ma
->ma_addr
, 0,
110 BUS_SPACE_MAP_LINEAR
, &isc
.ioh
))
111 panic("imc_attach: could not allocate memory\n");
113 platform
.bus_reset
= imc_bus_reset
;
114 platform
.watchdog_reset
= imc_watchdog_reset
;
115 platform
.watchdog_disable
= imc_watchdog_disable
;
116 platform
.watchdog_enable
= imc_watchdog_enable
;
118 sysid
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_SYSID
);
120 /* EISA exists on IP22 only */
121 if (mach_subtype
== MACH_SGI_IP22_FULLHOUSE
)
122 isc
.eisa_present
= (sysid
& IMC_SYSID_HAVEISA
);
124 isc
.eisa_present
= 0;
126 printf(": revision %d", (sysid
& IMC_SYSID_REVMASK
));
128 if (isc
.eisa_present
)
129 printf(", EISA bus present");
133 /* Clear CPU/GIO error status registers to clear any leftover bits. */
136 /* Hook the bus error handler into the ISR */
137 platform
.intr4
= imc_bus_error
;
140 * Enable parity reporting on GIO/main memory transactions.
141 * Disable parity checking on CPU bus transactions (as turning
142 * it on seems to cause spurious bus errors), but enable parity
143 * checking on CPU reads from main memory (note that this bit
144 * has the opposite sense... Turning it on turns the checks off!).
145 * Finally, turn on interrupt writes to the CPU from the MC.
147 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
);
148 reg
&= ~IMC_CPUCTRL0_NCHKMEMPAR
;
149 reg
|= (IMC_CPUCTRL0_GPR
| IMC_CPUCTRL0_MPR
| IMC_CPUCTRL0_INTENA
);
150 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
, reg
);
152 /* Setup the MC write buffer depth */
153 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL1
);
154 reg
= (reg
& ~IMC_CPUCTRL1_MCHWMSK
) | 13;
157 * Force endianness on the onboard HPC and both slots.
158 * This should be safe for Fullhouse, but leave it conditional
161 if (mach_type
== MACH_SGI_IP20
|| (mach_type
== MACH_SGI_IP22
&&
162 mach_subtype
== MACH_SGI_IP22_GUINNESS
)) {
163 reg
|= IMC_CPUCTRL1_HPCFX
;
164 reg
|= IMC_CPUCTRL1_EXP0FX
;
165 reg
|= IMC_CPUCTRL1_EXP1FX
;
166 reg
&= ~IMC_CPUCTRL1_HPCLITTLE
;
167 reg
&= ~IMC_CPUCTRL1_EXP0LITTLE
;
168 reg
&= ~IMC_CPUCTRL1_EXP1LITTLE
;
170 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL1
, reg
);
174 * Set GIO64 arbitrator configuration register:
176 * Preserve PROM-set graphics-related bits, as they seem to depend
177 * on the graphics variant present and I'm not sure how to figure
178 * that out or 100% sure what the correct settings are for each.
180 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_GIO64ARB
);
181 reg
&= (IMC_GIO64ARB_GRX64
| IMC_GIO64ARB_GRXRT
| IMC_GIO64ARB_GRXMST
);
183 /* Rest of settings are machine/board dependant */
184 if (mach_type
== MACH_SGI_IP20
) {
185 reg
|= IMC_GIO64ARB_ONEGIO
;
186 reg
|= (IMC_GIO64ARB_EXP0RT
| IMC_GIO64ARB_EXP1RT
);
187 reg
|= (IMC_GIO64ARB_EXP0MST
| IMC_GIO64ARB_EXP1MST
);
188 reg
&= ~(IMC_GIO64ARB_HPC64
|
189 IMC_GIO64ARB_HPCEXP64
| IMC_GIO64ARB_EISA64
|
190 IMC_GIO64ARB_EXP064
| IMC_GIO64ARB_EXP164
|
191 IMC_GIO64ARB_EXP0PIPE
| IMC_GIO64ARB_EXP1PIPE
);
194 * GIO64 invariant for all IP22 platforms: one GIO bus,
197 reg
|= IMC_GIO64ARB_ONEGIO
| IMC_GIO64ARB_HPC64
;
199 switch (mach_subtype
) {
200 case MACH_SGI_IP22_GUINNESS
:
201 /* XXX is MST mutually exclusive? */
202 reg
|= (IMC_GIO64ARB_EXP0RT
| IMC_GIO64ARB_EXP1RT
);
203 reg
|= (IMC_GIO64ARB_EXP0MST
| IMC_GIO64ARB_EXP1MST
);
205 /* EISA can bus-master, is 64-bit */
206 reg
|= (IMC_GIO64ARB_EISAMST
| IMC_GIO64ARB_EISA64
);
209 case MACH_SGI_IP22_FULLHOUSE
:
211 * All Fullhouse boards have a 64-bit HPC2 and pipelined
214 reg
|= (IMC_GIO64ARB_HPCEXP64
| IMC_GIO64ARB_EXP0PIPE
);
216 if (mach_boardrev
< 2) {
217 /* EXP0 realtime, EXP1 can master */
218 reg
|= (IMC_GIO64ARB_EXP0RT
|
219 IMC_GIO64ARB_EXP1MST
);
221 /* EXP1 pipelined as well, EISA masters */
222 reg
|= (IMC_GIO64ARB_EXP1PIPE
|
223 IMC_GIO64ARB_EISAMST
);
229 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_GIO64ARB
, reg
);
231 if (isc
.eisa_present
) {
233 memset(&iaa
, 0, sizeof(iaa
));
235 config_found_ia(self
, "eisabus", (void*)&iaa
, eisabusprint
);
239 memset(&iaa
, 0, sizeof(iaa
));
241 config_found_ia(self
, "giobus", (void*)&iaa
, imc_print
);
243 imc_watchdog_enable();
248 imc_print(void *aux
, const char *name
)
252 aprint_normal("gio at %s", name
);
261 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_CPU_ERRSTAT
, 0);
262 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_GIO_ERRSTAT
, 0);
266 imc_bus_error(uint32_t status
, uint32_t cause
, uint32_t pc
, uint32_t ipending
)
269 printf("bus error: cpu_stat %08x addr %08x, gio_stat %08x addr %08x\n",
270 bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPU_ERRSTAT
),
271 bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPU_ERRADDR
),
272 bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_GIO_ERRSTAT
),
273 bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_GIO_ERRADDR
) );
278 imc_watchdog_reset(void)
281 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_WDOG
, 0);
285 imc_watchdog_disable(void)
289 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_WDOG
, 0);
290 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
);
291 reg
&= ~(IMC_CPUCTRL0_WDOG
);
292 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
, reg
);
296 imc_watchdog_enable(void)
300 /* enable watchdog and clear it */
301 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
);
302 reg
|= IMC_CPUCTRL0_WDOG
;
303 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
, reg
);
304 imc_watchdog_reset();
307 /* intended to be called from gio/gio.c only */
309 imc_gio64_arb_config(int slot
, uint32_t flags
)
313 /* GIO_SLOT_EXP1 is unusable on Fullhouse */
314 if (slot
== GIO_SLOT_EXP1
&& mach_subtype
== MACH_SGI_IP22_FULLHOUSE
)
317 /* GIO_SLOT_GFX is only usable on Fullhouse */
318 if (slot
== GIO_SLOT_GFX
&& mach_subtype
!= MACH_SGI_IP22_FULLHOUSE
)
321 /* GIO_SLOT_GFX is always pipelined */
322 if (slot
== GIO_SLOT_GFX
&& (flags
& GIO_ARB_NOPIPE
))
325 /* IP20 does not support pipelining (XXX what about Indy?) */
326 if (((flags
& GIO_ARB_PIPE
) || (flags
& GIO_ARB_NOPIPE
)) &&
327 mach_type
== MACH_SGI_IP20
)
330 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_GIO64ARB
);
332 if (flags
& GIO_ARB_RT
) {
333 if (slot
== GIO_SLOT_EXP0
)
334 reg
|= IMC_GIO64ARB_EXP0RT
;
335 else if (slot
== GIO_SLOT_EXP1
)
336 reg
|= IMC_GIO64ARB_EXP1RT
;
337 else if (slot
== GIO_SLOT_GFX
)
338 reg
|= IMC_GIO64ARB_GRXRT
;
341 if (flags
& GIO_ARB_MST
) {
342 if (slot
== GIO_SLOT_EXP0
)
343 reg
|= IMC_GIO64ARB_EXP0MST
;
344 else if (slot
== GIO_SLOT_EXP1
)
345 reg
|= IMC_GIO64ARB_EXP1MST
;
346 else if (slot
== GIO_SLOT_GFX
)
347 reg
|= IMC_GIO64ARB_GRXMST
;
350 if (flags
& GIO_ARB_PIPE
) {
351 if (slot
== GIO_SLOT_EXP0
)
352 reg
|= IMC_GIO64ARB_EXP0PIPE
;
353 else if (slot
== GIO_SLOT_EXP1
)
354 reg
|= IMC_GIO64ARB_EXP1PIPE
;
357 if (flags
& GIO_ARB_LB
) {
358 if (slot
== GIO_SLOT_EXP0
)
359 reg
&= ~IMC_GIO64ARB_EXP0RT
;
360 else if (slot
== GIO_SLOT_EXP1
)
361 reg
&= ~IMC_GIO64ARB_EXP1RT
;
362 else if (slot
== GIO_SLOT_GFX
)
363 reg
&= ~IMC_GIO64ARB_GRXRT
;
366 if (flags
& GIO_ARB_SLV
) {
367 if (slot
== GIO_SLOT_EXP0
)
368 reg
&= ~IMC_GIO64ARB_EXP0MST
;
369 else if (slot
== GIO_SLOT_EXP1
)
370 reg
&= ~IMC_GIO64ARB_EXP1MST
;
371 else if (slot
== GIO_SLOT_GFX
)
372 reg
&= ~IMC_GIO64ARB_GRXMST
;
375 if (flags
& GIO_ARB_NOPIPE
) {
376 if (slot
== GIO_SLOT_EXP0
)
377 reg
&= ~IMC_GIO64ARB_EXP0PIPE
;
378 else if (slot
== GIO_SLOT_EXP1
)
379 reg
&= ~IMC_GIO64ARB_EXP1PIPE
;
382 if (flags
& GIO_ARB_32BIT
) {
383 if (slot
== GIO_SLOT_EXP0
)
384 reg
&= ~IMC_GIO64ARB_EXP064
;
385 else if (slot
== GIO_SLOT_EXP1
)
386 reg
&= ~IMC_GIO64ARB_EXP164
;
389 if (flags
& GIO_ARB_64BIT
) {
390 if (slot
== GIO_SLOT_EXP0
)
391 reg
|= IMC_GIO64ARB_EXP064
;
392 else if (slot
== GIO_SLOT_EXP1
)
393 reg
|= IMC_GIO64ARB_EXP164
;
396 if (flags
& GIO_ARB_HPC2_32BIT
)
397 reg
&= ~IMC_GIO64ARB_HPCEXP64
;
399 if (flags
& GIO_ARB_HPC2_64BIT
)
400 reg
|= IMC_GIO64ARB_HPCEXP64
;
402 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_GIO64ARB
, reg
);
408 * According to chapter 19 of the "IRIX Device Driver Programmer's Guide",
409 * some GIO devices, which do not drive all data lines, may cause false
410 * memory read parity errors on the SysAD bus. The workaround is to disable
414 imc_disable_sysad_parity(void)
418 if (mach_type
!= MACH_SGI_IP20
&& mach_type
!= MACH_SGI_IP22
)
421 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
);
422 reg
|= IMC_CPUCTRL0_NCHKMEMPAR
;
423 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
, reg
);
427 imc_enable_sysad_parity(void)
431 if (mach_type
!= MACH_SGI_IP20
&& mach_type
!= MACH_SGI_IP22
)
434 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
);
435 reg
&= ~IMC_CPUCTRL0_NCHKMEMPAR
;
436 bus_space_write_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
, reg
);
440 imc_is_sysad_parity_enabled(void)
444 if (mach_type
!= MACH_SGI_IP20
&& mach_type
!= MACH_SGI_IP22
)
447 reg
= bus_space_read_4(isc
.iot
, isc
.ioh
, IMC_CPUCTRL0
);
449 return reg
& IMC_CPUCTRL0_NCHKMEMPAR
;