1 /* $NetBSD: hpc.c,v 1.62 2009/05/14 01:10:19 macallan Exp $ */
4 * Copyright (c) 2000 Soren S. Jorvang
5 * Copyright (c) 2001 Rafal K. Boni
6 * Copyright (c) 2001 Jason R. Thorpe
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
20 * NetBSD Project. See http://www.NetBSD.org/ for
21 * information about NetBSD.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.62 2009/05/14 01:10:19 macallan Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
44 #include <sys/reboot.h>
45 #include <sys/callout.h>
47 #define _SGIMIPS_BUS_DMA_PRIVATE
48 #include <machine/bus.h>
49 #include <machine/machtype.h>
50 #include <machine/sysconf.h>
52 #include <sgimips/gio/gioreg.h>
53 #include <sgimips/gio/giovar.h>
55 #include <sgimips/hpc/hpcvar.h>
56 #include <sgimips/hpc/hpcreg.h>
57 #include <sgimips/ioc/iocreg.h>
59 #include <dev/ic/smc93cx6var.h>
72 static const struct hpc_device hpc1_devices
[] = {
73 /* probe order is important for IP20 zsc */
75 { "zsc", /* Personal Iris/Indigo serial 0/1 duart 1 */
79 HPCDEV_IP12
| HPCDEV_IP20
},
81 { "zsc", /* Personal Iris/Indigo kbd/ms duart 0 */
85 HPCDEV_IP12
| HPCDEV_IP20
},
87 { "sq", /* Personal Iris/Indigo onboard ethernet */
89 HPC1_ENET_DEVREGS
, HPC1_ENET_REGS
,
91 HPCDEV_IP12
| HPCDEV_IP20
},
93 { "sq", /* E++ GIO adapter slot 0 (Indigo) */
95 HPC1_ENET_DEVREGS
, HPC1_ENET_REGS
,
97 HPCDEV_IP12
| HPCDEV_IP20
},
99 { "sq", /* E++ GIO adapter slot 0 (Indy) */
101 HPC1_ENET_DEVREGS
, HPC1_ENET_REGS
,
105 { "sq", /* E++ GIO adapter slot 1 (Indigo) */
107 HPC1_ENET_DEVREGS
, HPC1_ENET_REGS
,
109 HPCDEV_IP12
| HPCDEV_IP20
},
111 { "sq", /* E++ GIO adapter slot 1 (Indy/Challenge S) */
113 HPC1_ENET_DEVREGS
, HPC1_ENET_REGS
,
117 { "wdsc", /* Personal Iris/Indigo onboard SCSI */
119 HPC1_SCSI0_DEVREGS
, HPC1_SCSI0_REGS
,
120 2, /* XXX 1 = IRQ_LOCAL0 + 2 */
121 HPCDEV_IP12
| HPCDEV_IP20
},
123 { "wdsc", /* GIO32 SCSI adapter slot 0 (Indigo) */
125 HPC1_SCSI0_DEVREGS
, HPC1_SCSI0_REGS
,
127 HPCDEV_IP12
| HPCDEV_IP20
},
129 { "wdsc", /* GIO32 SCSI adapter slot 0 (Indy) */
131 HPC1_SCSI0_DEVREGS
, HPC1_SCSI0_REGS
,
135 { "wdsc", /* GIO32 SCSI adapter slot 1 (Indigo) */
137 HPC1_SCSI0_DEVREGS
, HPC1_SCSI0_REGS
,
139 HPCDEV_IP12
| HPCDEV_IP20
},
141 { "wdsc", /* GIO32 SCSI adapter slot 1 (Indy/Challenge S) */
143 HPC1_SCSI0_DEVREGS
, HPC1_SCSI0_REGS
,
155 static const struct hpc_device hpc3_devices
[] = {
156 { "zsc", /* serial 0/1 duart 0 */
158 /* XXX Magic numbers */
159 HPC3_PBUS_CH6_DEVREGS
+ IOC_SERIAL_REGS
, 0,
161 HPCDEV_IP22
| HPCDEV_IP24
},
163 { "pckbc", /* Indigo2/Indy ps2 keyboard/mouse controller */
165 HPC3_PBUS_CH6_DEVREGS
+ IOC_KB_REGS
, 0,
167 HPCDEV_IP22
| HPCDEV_IP24
},
169 { "sq", /* Indigo2/Indy/Challenge S/Challenge M onboard enet */
171 HPC3_ENET_DEVREGS
, HPC3_ENET_REGS
,
173 HPCDEV_IP22
| HPCDEV_IP24
},
175 { "sq", /* Challenge S IOPLUS secondary ethernet */
177 HPC3_ENET_DEVREGS
, HPC3_ENET_REGS
,
181 { "wdsc", /* Indigo2/Indy/Challenge S/Challenge M onboard SCSI */
183 HPC3_SCSI0_DEVREGS
, HPC3_SCSI0_REGS
,
184 1, /* XXX 1 = IRQ_LOCAL0 + 1 */
185 HPCDEV_IP22
| HPCDEV_IP24
},
187 { "wdsc", /* Indigo2/Challenge M secondary onboard SCSI */
189 HPC3_SCSI1_DEVREGS
, HPC3_SCSI1_REGS
,
190 2, /* XXX 2 = IRQ_LOCAL0 + 2 */
193 { "haltwo", /* Indigo2/Indy onboard audio */
195 HPC3_PBUS_CH0_DEVREGS
, HPC3_PBUS_DMAREGS
,
196 8 + 4, /* XXX IRQ_LOCAL1 + 4 */
197 HPCDEV_IP22
| HPCDEV_IP24
},
199 { "pi1ppc", /* Indigo2/Indy/Challenge S/Challenge M onboard pport */
201 HPC3_PBUS_CH6_DEVREGS
+ IOC_PLP_REGS
, 0,
203 HPCDEV_IP22
| HPCDEV_IP24
},
205 { "panel", /* Indy front panel */
207 HPC3_PBUS_CH6_DEVREGS
+ IOC_PANEL
, 0,
220 struct device sc_dev
;
224 bus_space_tag_t sc_ct
;
225 bus_space_handle_t sc_ch
;
228 static struct hpc_values hpc1_values
= {
230 .scsi0_regs
= HPC1_SCSI0_REGS
,
231 .scsi0_regs_size
= HPC1_SCSI0_REGS_SIZE
,
232 .scsi0_cbp
= HPC1_SCSI0_CBP
,
233 .scsi0_ndbp
= HPC1_SCSI0_NDBP
,
234 .scsi0_bc
= HPC1_SCSI0_BC
,
235 .scsi0_ctl
= HPC1_SCSI0_CTL
,
236 .scsi0_gio
= HPC1_SCSI0_GIO
,
237 .scsi0_dev
= HPC1_SCSI0_DEV
,
238 .scsi0_dmacfg
= HPC1_SCSI0_DMACFG
,
239 .scsi0_piocfg
= HPC1_SCSI0_PIOCFG
,
241 .scsi1_regs_size
= 0,
250 .enet_regs
= HPC1_ENET_REGS
,
251 .enet_regs_size
= HPC1_ENET_REGS_SIZE
,
252 .enet_intdelay
= HPC1_ENET_INTDELAY
,
253 .enet_intdelayval
= HPC1_ENET_INTDELAY_OFF
,
254 .enetr_cbp
= HPC1_ENETR_CBP
,
255 .enetr_ndbp
= HPC1_ENETR_NDBP
,
256 .enetr_bc
= HPC1_ENETR_BC
,
257 .enetr_ctl
= HPC1_ENETR_CTL
,
258 .enetr_ctl_active
= HPC1_ENETR_CTL_ACTIVE
,
259 .enetr_reset
= HPC1_ENETR_RESET
,
262 .enetx_cbp
= HPC1_ENETX_CBP
,
263 .enetx_ndbp
= HPC1_ENETX_NDBP
,
264 .enetx_bc
= HPC1_ENETX_BC
,
265 .enetx_ctl
= HPC1_ENETX_CTL
,
266 .enetx_ctl_active
= HPC1_ENETX_CTL_ACTIVE
,
268 .enetr_fifo
= HPC1_ENETR_FIFO
,
269 .enetr_fifo_size
= HPC1_ENETR_FIFO_SIZE
,
270 .enetx_fifo
= HPC1_ENETX_FIFO
,
271 .enetx_fifo_size
= HPC1_ENETX_FIFO_SIZE
,
272 .scsi0_devregs_size
= HPC1_SCSI0_DEVREGS_SIZE
,
273 .scsi1_devregs_size
= 0,
274 .enet_devregs
= HPC1_ENET_DEVREGS
,
275 .enet_devregs_size
= HPC1_ENET_DEVREGS_SIZE
,
279 #define MAX_SCSI_XFER (512*1024)
280 .scsi_max_xfer
= MAX_SCSI_XFER
,
281 .scsi_dma_segs
= (MAX_SCSI_XFER
/ 4096),
282 .scsi_dma_segs_size
= 4096,
283 .scsi_dma_datain_cmd
= (HPC1_SCSI_DMACTL_ACTIVE
| HPC1_SCSI_DMACTL_DIR
),
284 .scsi_dma_dataout_cmd
= HPC1_SCSI_DMACTL_ACTIVE
,
285 .scsi_dmactl_flush
= HPC1_SCSI_DMACTL_FLUSH
,
286 .scsi_dmactl_active
= HPC1_SCSI_DMACTL_ACTIVE
,
287 .scsi_dmactl_reset
= HPC1_SCSI_DMACTL_RESET
290 static struct hpc_values hpc3_values
= {
292 .scsi0_regs
= HPC3_SCSI0_REGS
,
293 .scsi0_regs_size
= HPC3_SCSI0_REGS_SIZE
,
294 .scsi0_cbp
= HPC3_SCSI0_CBP
,
295 .scsi0_ndbp
= HPC3_SCSI0_NDBP
,
296 .scsi0_bc
= HPC3_SCSI0_BC
,
297 .scsi0_ctl
= HPC3_SCSI0_CTL
,
298 .scsi0_gio
= HPC3_SCSI0_GIO
,
299 .scsi0_dev
= HPC3_SCSI0_DEV
,
300 .scsi0_dmacfg
= HPC3_SCSI0_DMACFG
,
301 .scsi0_piocfg
= HPC3_SCSI0_PIOCFG
,
302 .scsi1_regs
= HPC3_SCSI1_REGS
,
303 .scsi1_regs_size
= HPC3_SCSI1_REGS_SIZE
,
304 .scsi1_cbp
= HPC3_SCSI1_CBP
,
305 .scsi1_ndbp
= HPC3_SCSI1_NDBP
,
306 .scsi1_bc
= HPC3_SCSI1_BC
,
307 .scsi1_ctl
= HPC3_SCSI1_CTL
,
308 .scsi1_gio
= HPC3_SCSI1_GIO
,
309 .scsi1_dev
= HPC3_SCSI1_DEV
,
310 .scsi1_dmacfg
= HPC3_SCSI1_DMACFG
,
311 .scsi1_piocfg
= HPC3_SCSI1_PIOCFG
,
312 .enet_regs
= HPC3_ENET_REGS
,
313 .enet_regs_size
= HPC3_ENET_REGS_SIZE
,
315 .enet_intdelayval
= 0,
316 .enetr_cbp
= HPC3_ENETR_CBP
,
317 .enetr_ndbp
= HPC3_ENETR_NDBP
,
318 .enetr_bc
= HPC3_ENETR_BC
,
319 .enetr_ctl
= HPC3_ENETR_CTL
,
320 .enetr_ctl_active
= HPC3_ENETR_CTL_ACTIVE
,
321 .enetr_reset
= HPC3_ENETR_RESET
,
322 .enetr_dmacfg
= HPC3_ENETR_DMACFG
,
323 .enetr_piocfg
= HPC3_ENETR_PIOCFG
,
324 .enetx_cbp
= HPC3_ENETX_CBP
,
325 .enetx_ndbp
= HPC3_ENETX_NDBP
,
326 .enetx_bc
= HPC3_ENETX_BC
,
327 .enetx_ctl
= HPC3_ENETX_CTL
,
328 .enetx_ctl_active
= HPC3_ENETX_CTL_ACTIVE
,
329 .enetx_dev
= HPC3_ENETX_DEV
,
330 .enetr_fifo
= HPC3_ENETR_FIFO
,
331 .enetr_fifo_size
= HPC3_ENETR_FIFO_SIZE
,
332 .enetx_fifo
= HPC3_ENETX_FIFO
,
333 .enetx_fifo_size
= HPC3_ENETX_FIFO_SIZE
,
334 .scsi0_devregs_size
= HPC3_SCSI0_DEVREGS_SIZE
,
335 .scsi1_devregs_size
= HPC3_SCSI1_DEVREGS_SIZE
,
336 .enet_devregs
= HPC3_ENET_DEVREGS
,
337 .enet_devregs_size
= HPC3_ENET_DEVREGS_SIZE
,
338 .pbus_fifo
= HPC3_PBUS_FIFO
,
339 .pbus_fifo_size
= HPC3_PBUS_FIFO_SIZE
,
340 .pbus_bbram
= HPC3_PBUS_BBRAM
,
341 .scsi_max_xfer
= MAX_SCSI_XFER
,
342 .scsi_dma_segs
= (MAX_SCSI_XFER
/ 8192),
343 .scsi_dma_segs_size
= 8192,
344 .scsi_dma_datain_cmd
= HPC3_SCSI_DMACTL_ACTIVE
,
345 .scsi_dma_dataout_cmd
=(HPC3_SCSI_DMACTL_ACTIVE
| HPC3_SCSI_DMACTL_DIR
),
346 .scsi_dmactl_flush
= HPC3_SCSI_DMACTL_FLUSH
,
347 .scsi_dmactl_active
= HPC3_SCSI_DMACTL_ACTIVE
,
348 .scsi_dmactl_reset
= HPC3_SCSI_DMACTL_RESET
352 static int powerintr_established
;
354 static int hpc_match(struct device
*, struct cfdata
*, void *);
355 static void hpc_attach(struct device
*, struct device
*, void *);
356 static int hpc_print(void *, const char *);
358 static int hpc_revision(struct hpc_softc
*, struct gio_attach_args
*);
360 static int hpc_submatch(struct device
*, struct cfdata
*,
361 const int *, void *);
363 //static int hpc_power_intr(void *);
366 static callout_t hpc_blink_ch
;
367 static void hpc_blink(void *);
370 static int hpc_read_eeprom(int, bus_space_tag_t
, bus_space_handle_t
,
373 CFATTACH_DECL(hpc
, sizeof(struct hpc_softc
),
374 hpc_match
, hpc_attach
, NULL
, NULL
);
377 hpc_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
379 struct gio_attach_args
* ga
= aux
;
381 if (mach_type
== MACH_SGI_IP12
|| mach_type
== MACH_SGI_IP20
||
382 mach_type
== MACH_SGI_IP22
) {
383 /* Make sure it's actually there and readable */
384 if (!platform
.badaddr((void*)MIPS_PHYS_TO_KSEG1(ga
->ga_addr
),
393 hpc_attach(struct device
*parent
, struct device
*self
, void *aux
)
395 struct hpc_softc
*sc
= (struct hpc_softc
*)self
;
396 struct gio_attach_args
* ga
= aux
;
397 struct hpc_attach_args ha
;
398 const struct hpc_device
*hd
;
405 callout_init(&hpc_blink_ch
, 0);
410 sysmask
= HPCDEV_IP12
;
414 sysmask
= HPCDEV_IP20
;
418 if (mach_subtype
== MACH_SGI_IP22_FULLHOUSE
)
419 sysmask
= HPCDEV_IP22
;
421 sysmask
= HPCDEV_IP24
;
425 panic("hpc_attach: can't handle HPC on an IP%d", mach_type
);
428 if ((hpctype
= hpc_revision(sc
, ga
)) == 0)
429 panic("hpc_attach: could not identify HPC revision\n");
431 /* force big-endian mode */
433 *(uint32_t *)MIPS_PHYS_TO_KSEG1(ga
->ga_addr
+HPC1_BIGENDIAN
) = 0;
436 * All machines have only one HPC on the mainboard itself. ''Extra''
437 * HPCs require bus arbiter and other magic to run happily.
439 isonboard
= (ga
->ga_addr
== HPC_BASE_ADDRESS_0
);
440 isioplus
= (ga
->ga_addr
== HPC_BASE_ADDRESS_1
&& hpctype
== 3 &&
441 sysmask
== HPCDEV_IP24
);
443 printf(": SGI HPC%d%s (%s)\n", (hpctype
== 3) ? 3 : 1,
444 (hpctype
== 15) ? ".5" : "", (isonboard
) ? "onboard" :
445 (isioplus
) ? "IOPLUS mezzanine" : "GIO slot");
448 * Configure the bus arbiter appropriately.
450 * In the case of Challenge S, we must tell the IOPLUS board which
451 * DMA channel to use (we steal it from one of the slots). SGI permits
452 * an HPC1.5 in slot 1, in which case IOPLUS must use EXP0, or any
453 * other DMA-capable board in slot 0, which leaves us to use EXP1. Of
454 * course, this means that only one GIO board may use DMA.
456 * Note that this never happens on Indigo2.
461 if (platform
.badaddr(
462 (void *)MIPS_PHYS_TO_KSEG1(HPC_BASE_ADDRESS_2
), 4))
463 arb_slot
= GIO_SLOT_EXP1
;
465 arb_slot
= GIO_SLOT_EXP0
;
467 if (gio_arb_config(arb_slot
, GIO_ARB_LB
| GIO_ARB_MST
|
468 GIO_ARB_64BIT
| GIO_ARB_HPC2_64BIT
)) {
469 printf("%s: failed to configure GIO bus arbiter\n",
470 sc
->sc_dev
.dv_xname
);
474 printf("%s: using EXP%d's DMA channel\n", sc
->sc_dev
.dv_xname
,
475 (arb_slot
== GIO_SLOT_EXP0
) ? 0 : 1);
477 bus_space_write_4(ga
->ga_iot
, ga
->ga_ioh
,
478 HPC3_PBUS_CFGPIO_REGS
, 0x0003ffff);
480 if (arb_slot
== GIO_SLOT_EXP0
)
481 bus_space_write_4(ga
->ga_iot
, ga
->ga_ioh
,
482 HPC3_PBUS_CH0_DEVREGS
, 0x20202020);
484 bus_space_write_4(ga
->ga_iot
, ga
->ga_ioh
,
485 HPC3_PBUS_CH0_DEVREGS
, 0x30303030);
486 } else if (!isonboard
) {
489 arb_slot
= (ga
->ga_addr
== HPC_BASE_ADDRESS_1
) ?
490 GIO_SLOT_EXP0
: GIO_SLOT_EXP1
;
492 if (gio_arb_config(arb_slot
, GIO_ARB_RT
| GIO_ARB_MST
)) {
493 printf("%s: failed to configure GIO bus arbiter\n",
494 sc
->sc_dev
.dv_xname
);
499 sc
->sc_ct
= SGIMIPS_BUS_SPACE_HPC
;
500 sc
->sc_ch
= ga
->ga_ioh
;
502 sc
->sc_base
= ga
->ga_addr
;
504 hpc_read_eeprom(hpctype
, SGIMIPS_BUS_SPACE_HPC
,
505 MIPS_PHYS_TO_KSEG1(sc
->sc_base
), ha
.hpc_eeprom
,
506 sizeof(ha
.hpc_eeprom
));
508 hd
= (hpctype
== 3) ? hpc3_devices
: hpc1_devices
;
509 for (; hd
->hd_name
!= NULL
; hd
++) {
510 if (!(hd
->hd_sysmask
& sysmask
) || hd
->hd_base
!= sc
->sc_base
)
513 ha
.ha_name
= hd
->hd_name
;
514 ha
.ha_devoff
= hd
->hd_devoff
;
515 ha
.ha_dmaoff
= hd
->hd_dmaoff
;
516 ha
.ha_irq
= hd
->hd_irq
;
518 /* XXX This is disgusting. */
519 ha
.ha_st
= SGIMIPS_BUS_SPACE_HPC
;
520 ha
.ha_sh
= MIPS_PHYS_TO_KSEG1(sc
->sc_base
);
521 ha
.ha_dmat
= &sgimips_default_bus_dma_tag
;
523 ha
.hpc_regs
= &hpc3_values
;
525 ha
.hpc_regs
= &hpc1_values
;
526 ha
.hpc_regs
->revision
= hpctype
;
528 /* XXXgross! avoid complaining in E++ and GIO32 SCSI cases */
529 if (hpctype
!= 3 && sc
->sc_base
!= HPC_BASE_ADDRESS_0
) {
530 (void)config_found_sm_loc(self
, "hpc", NULL
, &ha
,
533 (void)config_found_sm_loc(self
, "hpc", NULL
, &ha
,
534 hpc_print
, hpc_submatch
);
539 * XXX: Only attach the powerfail interrupt once, since the
540 * interrupt code doesn't let you share interrupt just yet.
542 * Since the powerfail interrupt is hardcoded to read from
543 * a specific register anyway (XXX#2!), we don't care when
544 * it gets attached, as long as it only happens once.
546 if (mach_type
== MACH_SGI_IP22
&& !powerintr_established
) {
547 // cpu_intr_establish(9, IPL_NONE, hpc_power_intr, sc);
548 powerintr_established
++;
552 if (mach_type
== MACH_SGI_IP12
|| mach_type
== MACH_SGI_IP20
)
558 * HPC revision detection isn't as simple as it should be. Devices probe
559 * differently depending on their slots, but luckily there is only one
560 * instance in which we have to decide the major revision (HPC1 vs HPC3).
562 * The HPC is found in the following configurations:
563 * o Personal Iris 4D/3x:
564 * One on-board HPC1 or HPC1.5.
567 * One on-board HPC1 or HPC1.5.
568 * Up to two additional HPC1.5's in GIO slots 0 and 1.
572 * Up to two additional HPC1.5's in GIO slots 0 and 1.
576 * Up to one additional HPC3 on the IOPLUS board (if installed).
577 * Up to one additional HPC1.5 in slot 1 of the IOPLUS board.
579 * o Indigo2, Challenge M
582 * All we really have to worry about is the IP22 case.
585 hpc_revision(struct hpc_softc
*sc
, struct gio_attach_args
*ga
)
588 /* No hardware ever supported the last hpc base address. */
589 if (ga
->ga_addr
== HPC_BASE_ADDRESS_3
)
592 if (mach_type
== MACH_SGI_IP12
|| mach_type
== MACH_SGI_IP20
) {
595 if (!platform
.badaddr((void *)MIPS_PHYS_TO_KSEG1(ga
->ga_addr
+
596 HPC1_BIGENDIAN
), 4)) {
597 reg
= *(uint32_t *)MIPS_PHYS_TO_KSEG1(ga
->ga_addr
+
600 if (((reg
>> HPC1_REVSHIFT
) & HPC1_REVMASK
) ==
611 * If IP22, probe slot 0 to determine if HPC1.5 or HPC3. Slot 1 must
614 if (mach_type
== MACH_SGI_IP22
) {
615 if (ga
->ga_addr
== HPC_BASE_ADDRESS_0
)
618 if (ga
->ga_addr
== HPC_BASE_ADDRESS_2
)
622 * Probe for it. We use one of the PBUS registers. Note
623 * that this probe succeeds with my E++ adapter in slot 1
624 * (bad), but it appears to always do the right thing in
625 * slot 0 (good!) and we're only worried about that one
628 if (platform
.badaddr((void *)MIPS_PHYS_TO_KSEG1(ga
->ga_addr
+
629 HPC3_PBUS_CH7_BP
), 4))
639 hpc_submatch(struct device
*parent
, struct cfdata
*cf
,
640 const int *ldesc
, void *aux
)
642 struct hpc_attach_args
*ha
= aux
;
644 if (cf
->cf_loc
[HPCCF_OFFSET
] != HPCCF_OFFSET_DEFAULT
&&
645 (bus_addr_t
) cf
->cf_loc
[HPCCF_OFFSET
] != ha
->ha_devoff
)
648 return (config_match(parent
, cf
, aux
));
652 hpc_print(void *aux
, const char *pnp
)
654 struct hpc_attach_args
*ha
= aux
;
657 printf("%s at %s", ha
->ha_name
, pnp
);
659 printf(" offset %#" PRIxVADDR
, (vaddr_t
)ha
->ha_devoff
);
666 hpc_power_intr(void *arg
)
670 pwr_reg
= *((volatile u_int32_t
*)MIPS_PHYS_TO_KSEG1(0x1fbd9850));
671 *((volatile u_int32_t
*)MIPS_PHYS_TO_KSEG1(0x1fbd9850)) = pwr_reg
;
673 printf("hpc_power_intr: panel reg = %08x\n", pwr_reg
);
676 cpu_reboot(RB_HALT
, NULL
);
684 hpc_blink(void *self
)
686 struct hpc_softc
*sc
= (struct hpc_softc
*) self
;
692 value
= *(volatile uint8_t *)MIPS_PHYS_TO_KSEG1(HPC_BASE_ADDRESS_0
+
694 value
^= HPC1_AUX_CONSLED
;
695 *(volatile u_int8_t
*)MIPS_PHYS_TO_KSEG1(HPC_BASE_ADDRESS_0
+
696 HPC1_AUX_REGS
) = value
;
701 * full cycle every second if completely idle (loadav = 0)
702 * full cycle every 2 seconds if loadav = 1
703 * full cycle every 3 seconds if loadav = 2
706 s
= (((averunnable
.ldavg
[0] + FSCALE
) * hz
) >> (FSHIFT
+ 1));
707 callout_reset(&hpc_blink_ch
, s
, hpc_blink
, sc
);
712 * Read the eeprom associated with one of the HPC's.
714 * NB: An eeprom is not always present, but the HPC should be able to
715 * handle this gracefully. Any consumers should validate the data to
716 * ensure it's reasonable.
719 hpc_read_eeprom(int hpctype
, bus_space_tag_t t
, bus_space_handle_t h
,
720 uint8_t *buf
, size_t len
)
722 struct seeprom_descriptor sd
;
723 bus_space_handle_t bsh
;
727 if (!len
|| len
& 0x1)
730 offset
= (hpctype
== 3) ? HPC3_EEPROM_DATA
: HPC1_AUX_REGS
;
732 tag
= SGIMIPS_BUS_SPACE_NORMAL
;
733 if (bus_space_subregion(t
, h
, offset
, 1, &bsh
) != 0)
740 sd
.sd_control_offset
= 0;
741 sd
.sd_status_offset
= 0;
742 sd
.sd_dataout_offset
= 0;
743 sd
.sd_DI
= 0x10; /* EEPROM -> CPU */
744 sd
.sd_DO
= 0x08; /* CPU -> EEPROM */
750 if (read_seeprom(&sd
, (uint16_t *)buf
, 0, len
/ 2) != 1)
753 bus_space_unmap(t
, bsh
, 1);