1 /* -*- mode: c; c-basic-offset: 8 -*- */
3 /* Copyright (C) 1999,2001
5 * Author: J.E.J.Bottomley@HansenPartnership.com
7 * linux/arch/i386/kernel/voyager_cat.c
9 * This file contains all the logic for manipulating the CAT bus
10 * in a level 5 machine.
12 * The CAT bus is a serial configuration and test bus. Its primary
13 * uses are to probe the initial configuration of the system and to
14 * diagnose error conditions when a system interrupt occurs. The low
15 * level interface is fairly primitive, so most of this file consists
16 * of bit shift manipulations to send and receive packets on the
19 #include <linux/types.h>
20 #include <linux/completion.h>
21 #include <linux/sched.h>
22 #include <asm/voyager.h>
24 #include <linux/ioport.h>
25 #include <linux/init.h>
26 #include <linux/slab.h>
27 #include <linux/delay.h>
30 #ifdef VOYAGER_CAT_DEBUG
31 #define CDEBUG(x) printk x
36 /* the CAT command port */
37 #define CAT_CMD (sspb + 0xe)
38 /* the CAT data port */
39 #define CAT_DATA (sspb + 0xd)
41 /* the internal cat functions */
42 static void cat_pack(__u8
* msg
, __u16 start_bit
, __u8
* data
, __u16 num_bits
);
43 static void cat_unpack(__u8
* msg
, __u16 start_bit
, __u8
* data
,
45 static void cat_build_header(__u8
* header
, const __u16 len
,
46 const __u16 smallest_reg_bits
,
47 const __u16 longest_reg_bits
);
48 static int cat_sendinst(voyager_module_t
* modp
, voyager_asic_t
* asicp
,
50 static int cat_getdata(voyager_module_t
* modp
, voyager_asic_t
* asicp
,
51 __u8 reg
, __u8
* value
);
52 static int cat_shiftout(__u8
* data
, __u16 data_bytes
, __u16 header_bytes
,
54 static int cat_write(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u8 reg
,
56 static int cat_read(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u8 reg
,
58 static int cat_subread(voyager_module_t
* modp
, voyager_asic_t
* asicp
,
59 __u16 offset
, __u16 len
, void *buf
);
60 static int cat_senddata(voyager_module_t
* modp
, voyager_asic_t
* asicp
,
61 __u8 reg
, __u8 value
);
62 static int cat_disconnect(voyager_module_t
* modp
, voyager_asic_t
* asicp
);
63 static int cat_connect(voyager_module_t
* modp
, voyager_asic_t
* asicp
);
65 static inline const char *cat_module_name(int module_id
)
69 return "Processor Slot 0";
71 return "Processor Slot 1";
73 return "Processor Slot 2";
75 return "Processor Slot 4";
77 return "Memory Slot 0";
79 return "Memory Slot 1";
81 return "Primary Microchannel";
83 return "Secondary Microchannel";
85 return "Power Supply Interface";
87 return "Processor Slot 5";
89 return "Processor Slot 6";
91 return "Processor Slot 7";
93 return "Processor Slot 8";
95 return "Unknown Module";
99 static int sspb
= 0; /* stores the super port location */
100 int voyager_8slot
= 0; /* set to true if a 51xx monster */
102 voyager_module_t
*voyager_cat_list
;
104 /* the I/O port assignments for the VIC and QIC */
105 static struct resource vic_res
= {
106 .name
= "Voyager Interrupt Controller",
110 static struct resource qic_res
= {
111 .name
= "Quad Interrupt Controller",
116 /* This function is used to pack a data bit stream inside a message.
117 * It writes num_bits of the data buffer in msg starting at start_bit.
118 * Note: This function assumes that any unused bit in the data stream
119 * is set to zero so that the ors will work correctly */
121 cat_pack(__u8
* msg
, const __u16 start_bit
, __u8
* data
, const __u16 num_bits
)
123 /* compute initial shift needed */
124 const __u16 offset
= start_bit
% BITS_PER_BYTE
;
125 __u16 len
= num_bits
/ BITS_PER_BYTE
;
126 __u16 byte
= start_bit
/ BITS_PER_BYTE
;
127 __u16 residue
= (num_bits
% BITS_PER_BYTE
) + offset
;
130 /* adjust if we have more than a byte of residue */
131 if (residue
>= BITS_PER_BYTE
) {
132 residue
-= BITS_PER_BYTE
;
136 /* clear out the bits. We assume here that if len==0 then
137 * residue >= offset. This is always true for the catbus
139 msg
[byte
] &= 0xff << (BITS_PER_BYTE
- offset
);
140 msg
[byte
++] |= data
[0] >> offset
;
143 for (i
= 1; i
< len
; i
++)
144 msg
[byte
++] = (data
[i
- 1] << (BITS_PER_BYTE
- offset
))
145 | (data
[i
] >> offset
);
147 __u8 mask
= 0xff >> residue
;
148 __u8 last_byte
= data
[i
- 1] << (BITS_PER_BYTE
- offset
)
149 | (data
[i
] >> offset
);
153 msg
[byte
] |= last_byte
;
158 /* unpack the data again (same arguments as cat_pack()). data buffer
159 * must be zero populated.
161 * Function: given a message string move to start_bit and copy num_bits into
162 * data (starting at bit 0 in data).
165 cat_unpack(__u8
* msg
, const __u16 start_bit
, __u8
* data
, const __u16 num_bits
)
167 /* compute initial shift needed */
168 const __u16 offset
= start_bit
% BITS_PER_BYTE
;
169 __u16 len
= num_bits
/ BITS_PER_BYTE
;
170 const __u8 last_bits
= num_bits
% BITS_PER_BYTE
;
171 __u16 byte
= start_bit
/ BITS_PER_BYTE
;
177 /* special case: want < 8 bits from msg and we can get it from
178 * a single byte of the msg */
179 if (len
== 0 && BITS_PER_BYTE
- offset
>= num_bits
) {
180 data
[0] = msg
[byte
] << offset
;
181 data
[0] &= 0xff >> (BITS_PER_BYTE
- num_bits
);
184 for (i
= 0; i
< len
; i
++) {
185 /* this annoying if has to be done just in case a read of
186 * msg one beyond the array causes a panic */
188 data
[i
] = msg
[byte
++] << offset
;
189 data
[i
] |= msg
[byte
] >> (BITS_PER_BYTE
- offset
);
191 data
[i
] = msg
[byte
++];
194 /* do we need to truncate the final byte */
195 if (last_bits
!= 0) {
196 data
[i
- 1] &= 0xff << (BITS_PER_BYTE
- last_bits
);
202 cat_build_header(__u8
* header
, const __u16 len
, const __u16 smallest_reg_bits
,
203 const __u16 longest_reg_bits
)
206 __u16 start_bit
= (smallest_reg_bits
- 1) % BITS_PER_BYTE
;
207 __u8
*last_byte
= &header
[len
- 1];
210 start_bit
= 1; /* must have at least one bit in the hdr */
212 for (i
= 0; i
< len
; i
++)
215 for (i
= start_bit
; i
> 0; i
--)
216 *last_byte
= ((*last_byte
) << 1) + 1;
221 cat_sendinst(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u8 reg
, __u8 op
)
223 __u8 parity
, inst
, inst_buf
[4] = { 0 };
224 __u8 iseq
[VOYAGER_MAX_SCAN_PATH
], hseq
[VOYAGER_MAX_REG_SIZE
];
225 __u16 ibytes
, hbytes
, padbits
;
229 * Parity is the parity of the register number + 1 (READ_REGISTER
230 * and WRITE_REGISTER always add '1' to the number of bits == 1)
232 parity
= (__u8
) (1 + (reg
& 0x01) +
233 ((__u8
) (reg
& 0x02) >> 1) +
234 ((__u8
) (reg
& 0x04) >> 2) +
235 ((__u8
) (reg
& 0x08) >> 3)) % 2;
237 inst
= ((parity
<< 7) | (reg
<< 2) | op
);
239 outb(VOYAGER_CAT_IRCYC
, CAT_CMD
);
240 if (!modp
->scan_path_connected
) {
241 if (asicp
->asic_id
!= VOYAGER_CAT_ID
) {
243 ("**WARNING***: cat_sendinst has disconnected scan path not to CAT asic\n");
246 outb(VOYAGER_CAT_HEADER
, CAT_DATA
);
247 outb(inst
, CAT_DATA
);
248 if (inb(CAT_DATA
) != VOYAGER_CAT_HEADER
) {
249 CDEBUG(("VOYAGER CAT: cat_sendinst failed to get CAT_HEADER\n"));
254 ibytes
= modp
->inst_bits
/ BITS_PER_BYTE
;
255 if ((padbits
= modp
->inst_bits
% BITS_PER_BYTE
) != 0) {
256 padbits
= BITS_PER_BYTE
- padbits
;
259 hbytes
= modp
->largest_reg
/ BITS_PER_BYTE
;
260 if (modp
->largest_reg
% BITS_PER_BYTE
)
262 CDEBUG(("cat_sendinst: ibytes=%d, hbytes=%d\n", ibytes
, hbytes
));
263 /* initialise the instruction sequence to 0xff */
264 for (i
= 0; i
< ibytes
+ hbytes
; i
++)
266 cat_build_header(hseq
, hbytes
, modp
->smallest_reg
, modp
->largest_reg
);
267 cat_pack(iseq
, modp
->inst_bits
, hseq
, hbytes
* BITS_PER_BYTE
);
269 inst_buf
[1] = 0xFF >> (modp
->largest_reg
% BITS_PER_BYTE
);
270 cat_pack(iseq
, asicp
->bit_location
, inst_buf
, asicp
->ireg_length
);
271 #ifdef VOYAGER_CAT_DEBUG
272 printk("ins = 0x%x, iseq: ", inst
);
273 for (i
= 0; i
< ibytes
+ hbytes
; i
++)
274 printk("0x%x ", iseq
[i
]);
277 if (cat_shiftout(iseq
, ibytes
, hbytes
, padbits
)) {
278 CDEBUG(("VOYAGER CAT: cat_sendinst: cat_shiftout failed\n"));
281 CDEBUG(("CAT SHIFTOUT DONE\n"));
286 cat_getdata(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u8 reg
,
289 if (!modp
->scan_path_connected
) {
290 if (asicp
->asic_id
!= VOYAGER_CAT_ID
) {
291 CDEBUG(("VOYAGER CAT: ERROR: cat_getdata to CAT asic with scan path connected\n"));
294 if (reg
> VOYAGER_SUBADDRHI
)
295 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
296 outb(VOYAGER_CAT_DRCYC
, CAT_CMD
);
297 outb(VOYAGER_CAT_HEADER
, CAT_DATA
);
298 *value
= inb(CAT_DATA
);
299 outb(0xAA, CAT_DATA
);
300 if (inb(CAT_DATA
) != VOYAGER_CAT_HEADER
) {
301 CDEBUG(("cat_getdata: failed to get VOYAGER_CAT_HEADER\n"));
306 __u16 sbits
= modp
->num_asics
- 1 + asicp
->ireg_length
;
307 __u16 sbytes
= sbits
/ BITS_PER_BYTE
;
309 __u8 string
[VOYAGER_MAX_SCAN_PATH
],
310 trailer
[VOYAGER_MAX_REG_SIZE
];
314 outb(VOYAGER_CAT_DRCYC
, CAT_CMD
);
316 if ((padbits
= sbits
% BITS_PER_BYTE
) != 0) {
317 padbits
= BITS_PER_BYTE
- padbits
;
320 tbytes
= asicp
->ireg_length
/ BITS_PER_BYTE
;
321 if (asicp
->ireg_length
% BITS_PER_BYTE
)
323 CDEBUG(("cat_getdata: tbytes = %d, sbytes = %d, padbits = %d\n",
324 tbytes
, sbytes
, padbits
));
325 cat_build_header(trailer
, tbytes
, 1, asicp
->ireg_length
);
327 for (i
= tbytes
- 1; i
>= 0; i
--) {
328 outb(trailer
[i
], CAT_DATA
);
329 string
[sbytes
+ i
] = inb(CAT_DATA
);
332 for (i
= sbytes
- 1; i
>= 0; i
--) {
333 outb(0xaa, CAT_DATA
);
334 string
[i
] = inb(CAT_DATA
);
338 padbits
+ (tbytes
* BITS_PER_BYTE
) +
339 asicp
->asic_location
, value
, asicp
->ireg_length
);
340 #ifdef VOYAGER_CAT_DEBUG
341 printk("value=0x%x, string: ", *value
);
342 for (i
= 0; i
< tbytes
+ sbytes
; i
++)
343 printk("0x%x ", string
[i
]);
347 /* sanity check the rest of the return */
348 for (i
= 0; i
< tbytes
; i
++) {
351 cat_unpack(string
, padbits
+ (i
* BITS_PER_BYTE
),
352 &input
, BITS_PER_BYTE
);
353 if (trailer
[i
] != input
) {
354 CDEBUG(("cat_getdata: failed to sanity check rest of ret(%d) 0x%x != 0x%x\n", i
, input
, trailer
[i
]));
358 CDEBUG(("cat_getdata DONE\n"));
364 cat_shiftout(__u8
* data
, __u16 data_bytes
, __u16 header_bytes
, __u8 pad_bits
)
368 for (i
= data_bytes
+ header_bytes
- 1; i
>= header_bytes
; i
--)
369 outb(data
[i
], CAT_DATA
);
371 for (i
= header_bytes
- 1; i
>= 0; i
--) {
375 outb(data
[i
], CAT_DATA
);
376 input
= inb(CAT_DATA
);
377 CDEBUG(("cat_shiftout: returned 0x%x\n", input
));
378 cat_unpack(data
, ((data_bytes
+ i
) * BITS_PER_BYTE
) - pad_bits
,
379 &header
, BITS_PER_BYTE
);
380 if (input
!= header
) {
381 CDEBUG(("VOYAGER CAT: cat_shiftout failed to return header 0x%x != 0x%x\n", input
, header
));
389 cat_senddata(voyager_module_t
* modp
, voyager_asic_t
* asicp
,
390 __u8 reg
, __u8 value
)
392 outb(VOYAGER_CAT_DRCYC
, CAT_CMD
);
393 if (!modp
->scan_path_connected
) {
394 if (asicp
->asic_id
!= VOYAGER_CAT_ID
) {
395 CDEBUG(("VOYAGER CAT: ERROR: scan path disconnected when asic != CAT\n"));
398 outb(VOYAGER_CAT_HEADER
, CAT_DATA
);
399 outb(value
, CAT_DATA
);
400 if (inb(CAT_DATA
) != VOYAGER_CAT_HEADER
) {
401 CDEBUG(("cat_senddata: failed to get correct header response to sent data\n"));
404 if (reg
> VOYAGER_SUBADDRHI
) {
405 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
406 outb(VOYAGER_CAT_END
, CAT_CMD
);
407 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
412 __u16 hbytes
= asicp
->ireg_length
/ BITS_PER_BYTE
;
414 (modp
->num_asics
- 1 + asicp
->ireg_length
) / BITS_PER_BYTE
;
415 __u8 padbits
, dseq
[VOYAGER_MAX_SCAN_PATH
],
416 hseq
[VOYAGER_MAX_REG_SIZE
];
419 if ((padbits
= (modp
->num_asics
- 1
420 + asicp
->ireg_length
) % BITS_PER_BYTE
) != 0) {
421 padbits
= BITS_PER_BYTE
- padbits
;
424 if (asicp
->ireg_length
% BITS_PER_BYTE
)
427 cat_build_header(hseq
, hbytes
, 1, asicp
->ireg_length
);
429 for (i
= 0; i
< dbytes
+ hbytes
; i
++)
431 CDEBUG(("cat_senddata: dbytes=%d, hbytes=%d, padbits=%d\n",
432 dbytes
, hbytes
, padbits
));
433 cat_pack(dseq
, modp
->num_asics
- 1 + asicp
->ireg_length
,
434 hseq
, hbytes
* BITS_PER_BYTE
);
435 cat_pack(dseq
, asicp
->asic_location
, &value
,
437 #ifdef VOYAGER_CAT_DEBUG
439 for (i
= 0; i
< hbytes
+ dbytes
; i
++) {
440 printk("0x%x ", dseq
[i
]);
444 return cat_shiftout(dseq
, dbytes
, hbytes
, padbits
);
449 cat_write(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u8 reg
, __u8 value
)
451 if (cat_sendinst(modp
, asicp
, reg
, VOYAGER_WRITE_CONFIG
))
453 return cat_senddata(modp
, asicp
, reg
, value
);
457 cat_read(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u8 reg
,
460 if (cat_sendinst(modp
, asicp
, reg
, VOYAGER_READ_CONFIG
))
462 return cat_getdata(modp
, asicp
, reg
, value
);
466 cat_subaddrsetup(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u16 offset
,
472 /* set auto increment */
475 if (cat_read(modp
, asicp
, VOYAGER_AUTO_INC_REG
, &val
)) {
476 CDEBUG(("cat_subaddrsetup: read of VOYAGER_AUTO_INC_REG failed\n"));
479 CDEBUG(("cat_subaddrsetup: VOYAGER_AUTO_INC_REG = 0x%x\n",
481 newval
= val
| VOYAGER_AUTO_INC
;
483 if (cat_write(modp
, asicp
, VOYAGER_AUTO_INC_REG
, val
)) {
484 CDEBUG(("cat_subaddrsetup: write to VOYAGER_AUTO_INC_REG failed\n"));
489 if (cat_write(modp
, asicp
, VOYAGER_SUBADDRLO
, (__u8
) (offset
& 0xff))) {
490 CDEBUG(("cat_subaddrsetup: write to SUBADDRLO failed\n"));
493 if (asicp
->subaddr
> VOYAGER_SUBADDR_LO
) {
495 (modp
, asicp
, VOYAGER_SUBADDRHI
, (__u8
) (offset
>> 8))) {
496 CDEBUG(("cat_subaddrsetup: write to SUBADDRHI failed\n"));
499 cat_read(modp
, asicp
, VOYAGER_SUBADDRHI
, &val
);
500 CDEBUG(("cat_subaddrsetup: offset = %d, hi = %d\n", offset
,
503 cat_read(modp
, asicp
, VOYAGER_SUBADDRLO
, &val
);
504 CDEBUG(("cat_subaddrsetup: offset = %d, lo = %d\n", offset
, val
));
509 cat_subwrite(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u16 offset
,
510 __u16 len
, void *buf
)
514 /* FIXME: need special actions for VOYAGER_CAT_ID here */
515 if (asicp
->asic_id
== VOYAGER_CAT_ID
) {
516 CDEBUG(("cat_subwrite: ATTEMPT TO WRITE TO CAT ASIC\n"));
517 /* FIXME -- This is supposed to be handled better
518 * There is a problem writing to the cat asic in the
519 * PSI. The 30us delay seems to work, though */
523 if ((retval
= cat_subaddrsetup(modp
, asicp
, offset
, len
)) != 0) {
524 printk("cat_subwrite: cat_subaddrsetup FAILED\n");
529 (modp
, asicp
, VOYAGER_SUBADDRDATA
, VOYAGER_WRITE_CONFIG
)) {
530 printk("cat_subwrite: cat_sendinst FAILED\n");
533 for (i
= 0; i
< len
; i
++) {
534 if (cat_senddata(modp
, asicp
, 0xFF, ((__u8
*) buf
)[i
])) {
536 ("cat_subwrite: cat_sendata element at %d FAILED\n",
544 cat_subread(voyager_module_t
* modp
, voyager_asic_t
* asicp
, __u16 offset
,
545 __u16 len
, void *buf
)
549 if ((retval
= cat_subaddrsetup(modp
, asicp
, offset
, len
)) != 0) {
550 CDEBUG(("cat_subread: cat_subaddrsetup FAILED\n"));
554 if (cat_sendinst(modp
, asicp
, VOYAGER_SUBADDRDATA
, VOYAGER_READ_CONFIG
)) {
555 CDEBUG(("cat_subread: cat_sendinst failed\n"));
558 for (i
= 0; i
< len
; i
++) {
559 if (cat_getdata(modp
, asicp
, 0xFF, &((__u8
*) buf
)[i
])) {
560 CDEBUG(("cat_subread: cat_getdata element %d failed\n",
568 /* buffer for storing EPROM data read in during initialisation */
569 static __initdata __u8 eprom_buf
[0xFFFF];
570 static voyager_module_t
*voyager_initial_module
;
572 /* Initialise the cat bus components. We assume this is called by the
573 * boot cpu *after* all memory initialisation has been done (so we can
574 * use kmalloc) but before smp initialisation, so we can probe the SMP
575 * configuration and pick up necessary information. */
576 void __init
voyager_cat_init(void)
578 voyager_module_t
**modpp
= &voyager_initial_module
;
579 voyager_asic_t
**asicpp
;
580 voyager_asic_t
*qabc_asic
= NULL
;
582 unsigned long qic_addr
= 0;
583 __u8 qabc_data
[0x20];
584 __u8 num_submodules
, val
;
585 voyager_eprom_hdr_t
*eprom_hdr
= (voyager_eprom_hdr_t
*) & eprom_buf
[0];
590 /* initiallise the SUS mailbox */
591 for (i
= 0; i
< sizeof(cmos
); i
++)
592 cmos
[i
] = voyager_extended_cmos_read(VOYAGER_DUMP_LOCATION
+ i
);
593 addr
= *(unsigned long *)cmos
;
594 if ((addr
& 0xff000000) != 0xff000000) {
596 "Voyager failed to get SUS mailbox (addr = 0x%lx\n",
599 static struct resource res
;
601 res
.name
= "voyager SUS";
603 res
.end
= addr
+ 0x3ff;
605 request_resource(&iomem_resource
, &res
);
606 voyager_SUS
= (struct voyager_SUS
*)
607 ioremap(addr
, 0x400);
608 printk(KERN_NOTICE
"Voyager SUS mailbox version 0x%x\n",
609 voyager_SUS
->SUS_version
);
610 voyager_SUS
->kernel_version
= VOYAGER_MAILBOX_VERSION
;
611 voyager_SUS
->kernel_flags
= VOYAGER_OS_HAS_SYSINT
;
614 /* clear the processor counts */
615 voyager_extended_vic_processors
= 0;
616 voyager_quad_processors
= 0;
618 printk("VOYAGER: beginning CAT bus probe\n");
619 /* set up the SuperSet Port Block which tells us where the
620 * CAT communication port is */
621 sspb
= inb(VOYAGER_SSPB_RELOCATION_PORT
) * 0x100;
622 VDEBUG(("VOYAGER DEBUG: sspb = 0x%x\n", sspb
));
624 /* now find out if were 8 slot or normal */
625 if ((inb(VIC_PROC_WHO_AM_I
) & EIGHT_SLOT_IDENTIFIER
)
626 == EIGHT_SLOT_IDENTIFIER
) {
629 "Voyager: Eight slot 51xx configuration detected\n");
632 for (i
= VOYAGER_MIN_MODULE
; i
<= VOYAGER_MAX_MODULE
; i
++) {
638 outb(VOYAGER_CAT_DESELECT
, VOYAGER_CAT_CONFIG_PORT
);
639 outb(i
, VOYAGER_CAT_CONFIG_PORT
);
641 /* check the presence of the module */
642 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
643 outb(VOYAGER_CAT_IRCYC
, CAT_CMD
);
644 outb(VOYAGER_CAT_HEADER
, CAT_DATA
);
645 /* stream series of alternating 1's and 0's to stimulate
647 outb(0xAA, CAT_DATA
);
648 input
= inb(CAT_DATA
);
649 outb(VOYAGER_CAT_END
, CAT_CMD
);
650 if (input
!= VOYAGER_CAT_HEADER
) {
653 CDEBUG(("VOYAGER DEBUG: found module id 0x%x, %s\n", i
,
654 cat_module_name(i
)));
655 *modpp
= kmalloc(sizeof(voyager_module_t
), GFP_KERNEL
); /*&voyager_module_storage[cat_count++]; */
656 if (*modpp
== NULL
) {
657 printk("**WARNING** kmalloc failure in cat_init\n");
660 memset(*modpp
, 0, sizeof(voyager_module_t
));
661 /* need temporary asic for cat_subread. It will be
662 * filled in correctly later */
663 (*modpp
)->asic
= kmalloc(sizeof(voyager_asic_t
), GFP_KERNEL
); /*&voyager_asic_storage[asic_count]; */
664 if ((*modpp
)->asic
== NULL
) {
665 printk("**WARNING** kmalloc failure in cat_init\n");
668 memset((*modpp
)->asic
, 0, sizeof(voyager_asic_t
));
669 (*modpp
)->asic
->asic_id
= VOYAGER_CAT_ID
;
670 (*modpp
)->asic
->subaddr
= VOYAGER_SUBADDR_HI
;
671 (*modpp
)->module_addr
= i
;
672 (*modpp
)->scan_path_connected
= 0;
673 if (i
== VOYAGER_PSI
) {
674 /* Exception leg for modules with no EEPROM */
675 printk("Module \"%s\"\n", cat_module_name(i
));
679 CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i
, VOYAGER_XSUM_END_OFFSET
));
680 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
681 cat_disconnect(*modpp
, (*modpp
)->asic
);
682 if (cat_subread(*modpp
, (*modpp
)->asic
,
683 VOYAGER_XSUM_END_OFFSET
, sizeof(eprom_size
),
686 ("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n",
688 outb(VOYAGER_CAT_END
, CAT_CMD
);
691 if (eprom_size
> sizeof(eprom_buf
)) {
693 ("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n",
695 outb(VOYAGER_CAT_END
, CAT_CMD
);
698 outb(VOYAGER_CAT_END
, CAT_CMD
);
699 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
700 CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i
,
703 (*modpp
, (*modpp
)->asic
, 0, eprom_size
, eprom_buf
)) {
704 outb(VOYAGER_CAT_END
, CAT_CMD
);
707 outb(VOYAGER_CAT_END
, CAT_CMD
);
708 printk("Module \"%s\", version 0x%x, tracer 0x%x, asics %d\n",
709 cat_module_name(i
), eprom_hdr
->version_id
,
710 *((__u32
*) eprom_hdr
->tracer
), eprom_hdr
->num_asics
);
711 (*modpp
)->ee_size
= eprom_hdr
->ee_size
;
712 (*modpp
)->num_asics
= eprom_hdr
->num_asics
;
713 asicpp
= &((*modpp
)->asic
);
714 sp_offset
= eprom_hdr
->scan_path_offset
;
715 /* All we really care about are the Quad cards. We
716 * identify them because they are in a processor slot
717 * and have only four asics */
718 if ((i
< 0x10 || (i
>= 0x14 && i
< 0x1c) || i
> 0x1f)) {
719 modpp
= &((*modpp
)->next
);
722 /* Now we know it's in a processor slot, does it have
723 * a quad baseboard submodule */
724 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
725 cat_read(*modpp
, (*modpp
)->asic
, VOYAGER_SUBMODPRESENT
,
727 /* lowest two bits, active low */
728 num_submodules
= ~(0xfc | num_submodules
);
729 CDEBUG(("VOYAGER CAT: %d submodules present\n",
731 if (num_submodules
== 0) {
732 /* fill in the dyadic extended processors */
735 printk("Module \"%s\": Dyadic Processor Card\n",
737 voyager_extended_vic_processors
|= (1 << cpu
);
739 voyager_extended_vic_processors
|= (1 << cpu
);
740 outb(VOYAGER_CAT_END
, CAT_CMD
);
744 /* now we want to read the asics on the first submodule,
745 * which should be the quad base board */
747 cat_read(*modpp
, (*modpp
)->asic
, VOYAGER_SUBMODSELECT
, &val
);
748 CDEBUG(("cat_init: SUBMODSELECT value = 0x%x\n", val
));
749 val
= (val
& 0x7c) | VOYAGER_QUAD_BASEBOARD
;
750 cat_write(*modpp
, (*modpp
)->asic
, VOYAGER_SUBMODSELECT
, val
);
752 outb(VOYAGER_CAT_END
, CAT_CMD
);
754 CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i
, VOYAGER_XSUM_END_OFFSET
));
755 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
756 cat_disconnect(*modpp
, (*modpp
)->asic
);
757 if (cat_subread(*modpp
, (*modpp
)->asic
,
758 VOYAGER_XSUM_END_OFFSET
, sizeof(eprom_size
),
761 ("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n",
763 outb(VOYAGER_CAT_END
, CAT_CMD
);
766 if (eprom_size
> sizeof(eprom_buf
)) {
768 ("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n",
770 outb(VOYAGER_CAT_END
, CAT_CMD
);
773 outb(VOYAGER_CAT_END
, CAT_CMD
);
774 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
775 CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i
,
778 (*modpp
, (*modpp
)->asic
, 0, eprom_size
, eprom_buf
)) {
779 outb(VOYAGER_CAT_END
, CAT_CMD
);
782 outb(VOYAGER_CAT_END
, CAT_CMD
);
783 /* Now do everything for the QBB submodule 1 */
784 (*modpp
)->ee_size
= eprom_hdr
->ee_size
;
785 (*modpp
)->num_asics
= eprom_hdr
->num_asics
;
786 asicpp
= &((*modpp
)->asic
);
787 sp_offset
= eprom_hdr
->scan_path_offset
;
788 /* get rid of the dummy CAT asic and read the real one */
789 kfree((*modpp
)->asic
);
790 for (asic
= 0; asic
< (*modpp
)->num_asics
; asic
++) {
792 voyager_asic_t
*asicp
= *asicpp
= kzalloc(sizeof(voyager_asic_t
), GFP_KERNEL
); /*&voyager_asic_storage[asic_count++]; */
793 voyager_sp_table_t
*sp_table
;
794 voyager_at_t
*asic_table
;
795 voyager_jtt_t
*jtag_table
;
799 ("**WARNING** kmalloc failure in cat_init\n");
802 asicpp
= &(asicp
->next
);
803 asicp
->asic_location
= asic
;
805 (voyager_sp_table_t
*) (eprom_buf
+ sp_offset
);
806 asicp
->asic_id
= sp_table
->asic_id
;
808 (voyager_at_t
*) (eprom_buf
+
809 sp_table
->asic_data_offset
);
810 for (j
= 0; j
< 4; j
++)
811 asicp
->jtag_id
[j
] = asic_table
->jtag_id
[j
];
813 (voyager_jtt_t
*) (eprom_buf
+
814 asic_table
->jtag_offset
);
815 asicp
->ireg_length
= jtag_table
->ireg_len
;
816 asicp
->bit_location
= (*modpp
)->inst_bits
;
817 (*modpp
)->inst_bits
+= asicp
->ireg_length
;
818 if (asicp
->ireg_length
> (*modpp
)->largest_reg
)
819 (*modpp
)->largest_reg
= asicp
->ireg_length
;
820 if (asicp
->ireg_length
< (*modpp
)->smallest_reg
||
821 (*modpp
)->smallest_reg
== 0)
822 (*modpp
)->smallest_reg
= asicp
->ireg_length
;
823 CDEBUG(("asic 0x%x, ireg_length=%d, bit_location=%d\n",
824 asicp
->asic_id
, asicp
->ireg_length
,
825 asicp
->bit_location
));
826 if (asicp
->asic_id
== VOYAGER_QUAD_QABC
) {
827 CDEBUG(("VOYAGER CAT: QABC ASIC found\n"));
830 sp_offset
+= sizeof(voyager_sp_table_t
);
832 CDEBUG(("Module inst_bits = %d, largest_reg = %d, smallest_reg=%d\n", (*modpp
)->inst_bits
, (*modpp
)->largest_reg
, (*modpp
)->smallest_reg
));
833 /* OK, now we have the QUAD ASICs set up, use them.
836 * 1. Find the Memory area for the Quad CPIs.
837 * 2. Find the Extended VIC processor
838 * 3. Configure a second extended VIC processor (This
839 * cannot be done for the 51xx.
841 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
842 cat_connect(*modpp
, (*modpp
)->asic
);
843 CDEBUG(("CAT CONNECTED!!\n"));
844 cat_subread(*modpp
, qabc_asic
, 0, sizeof(qabc_data
), qabc_data
);
845 qic_addr
= qabc_data
[5] << 8;
846 qic_addr
= (qic_addr
| qabc_data
[6]) << 8;
847 qic_addr
= (qic_addr
| qabc_data
[7]) << 8;
849 ("Module \"%s\": Quad Processor Card; CPI 0x%lx, SET=0x%x\n",
850 cat_module_name(i
), qic_addr
, qabc_data
[8]);
851 #if 0 /* plumbing fails---FIXME */
852 if ((qabc_data
[8] & 0xf0) == 0) {
853 /* FIXME: 32 way 8 CPU slot monster cannot be
854 * plumbed this way---need to check for it */
856 printk("Plumbing second Extended Quad Processor\n");
857 /* second VIC line hardwired to Quad CPU 1 */
858 qabc_data
[8] |= 0x20;
859 cat_subwrite(*modpp
, qabc_asic
, 8, 1, &qabc_data
[8]);
860 #ifdef VOYAGER_CAT_DEBUG
861 /* verify plumbing */
862 cat_subread(*modpp
, qabc_asic
, 8, 1, &qabc_data
[8]);
863 if ((qabc_data
[8] & 0xf0) == 0) {
864 CDEBUG(("PLUMBING FAILED: 0x%x\n",
872 struct resource
*res
=
873 kzalloc(sizeof(struct resource
), GFP_KERNEL
);
874 res
->name
= kmalloc(128, GFP_KERNEL
);
875 sprintf((char *)res
->name
, "Voyager %s Quad CPI",
877 res
->start
= qic_addr
;
878 res
->end
= qic_addr
+ 0x3ff;
879 request_resource(&iomem_resource
, res
);
882 qic_addr
= (unsigned long)ioremap(qic_addr
, 0x400);
884 for (j
= 0; j
< 4; j
++) {
888 /* 8 slot has a different mapping,
889 * each slot has only one vic line, so
890 * 1 cpu in each slot must be < 8 */
891 cpu
= (i
& 0x07) + j
* 8;
893 cpu
= (i
& 0x03) + j
* 4;
895 if ((qabc_data
[8] & (1 << j
))) {
896 voyager_extended_vic_processors
|= (1 << cpu
);
898 if (qabc_data
[8] & (1 << (j
+ 4))) {
899 /* Second SET register plumbed: Quad
900 * card has two VIC connected CPUs.
901 * Secondary cannot be booted as a VIC
903 voyager_extended_vic_processors
|= (1 << cpu
);
904 voyager_allowed_boot_processors
&=
908 voyager_quad_processors
|= (1 << cpu
);
909 voyager_quad_cpi_addr
[cpu
] = (struct voyager_qic_cpi
*)
910 (qic_addr
+ (j
<< 8));
911 CDEBUG(("CPU%d: CPI address 0x%lx\n", cpu
,
912 (unsigned long)voyager_quad_cpi_addr
[cpu
]));
914 outb(VOYAGER_CAT_END
, CAT_CMD
);
917 modpp
= &((*modpp
)->next
);
921 ("CAT Bus Initialisation finished: extended procs 0x%x, quad procs 0x%x, allowed vic boot = 0x%x\n",
922 voyager_extended_vic_processors
, voyager_quad_processors
,
923 voyager_allowed_boot_processors
);
924 request_resource(&ioport_resource
, &vic_res
);
925 if (voyager_quad_processors
)
926 request_resource(&ioport_resource
, &qic_res
);
927 /* set up the front power switch */
930 int voyager_cat_readb(__u8 module
, __u8 asic
, int reg
)
935 static int cat_disconnect(voyager_module_t
* modp
, voyager_asic_t
* asicp
)
940 if (!modp
->scan_path_connected
)
942 if (asicp
->asic_id
!= VOYAGER_CAT_ID
) {
943 CDEBUG(("cat_disconnect: ASIC is not CAT\n"));
946 err
= cat_read(modp
, asicp
, VOYAGER_SCANPATH
, &val
);
948 CDEBUG(("cat_disconnect: failed to read SCANPATH\n"));
951 val
&= VOYAGER_DISCONNECT_ASIC
;
952 err
= cat_write(modp
, asicp
, VOYAGER_SCANPATH
, val
);
954 CDEBUG(("cat_disconnect: failed to write SCANPATH\n"));
957 outb(VOYAGER_CAT_END
, CAT_CMD
);
958 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
959 modp
->scan_path_connected
= 0;
964 static int cat_connect(voyager_module_t
* modp
, voyager_asic_t
* asicp
)
969 if (modp
->scan_path_connected
)
971 if (asicp
->asic_id
!= VOYAGER_CAT_ID
) {
972 CDEBUG(("cat_connect: ASIC is not CAT\n"));
976 err
= cat_read(modp
, asicp
, VOYAGER_SCANPATH
, &val
);
978 CDEBUG(("cat_connect: failed to read SCANPATH\n"));
981 val
|= VOYAGER_CONNECT_ASIC
;
982 err
= cat_write(modp
, asicp
, VOYAGER_SCANPATH
, val
);
984 CDEBUG(("cat_connect: failed to write SCANPATH\n"));
987 outb(VOYAGER_CAT_END
, CAT_CMD
);
988 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
989 modp
->scan_path_connected
= 1;
994 void voyager_cat_power_off(void)
996 /* Power the machine off by writing to the PSI over the CAT
999 voyager_module_t psi
= { 0 };
1000 voyager_asic_t psi_asic
= { 0 };
1002 psi
.asic
= &psi_asic
;
1003 psi
.asic
->asic_id
= VOYAGER_CAT_ID
;
1004 psi
.asic
->subaddr
= VOYAGER_SUBADDR_HI
;
1005 psi
.module_addr
= VOYAGER_PSI
;
1006 psi
.scan_path_connected
= 0;
1008 outb(VOYAGER_CAT_END
, CAT_CMD
);
1009 /* Connect the PSI to the CAT Bus */
1010 outb(VOYAGER_CAT_DESELECT
, VOYAGER_CAT_CONFIG_PORT
);
1011 outb(VOYAGER_PSI
, VOYAGER_CAT_CONFIG_PORT
);
1012 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1013 cat_disconnect(&psi
, &psi_asic
);
1014 /* Read the status */
1015 cat_subread(&psi
, &psi_asic
, VOYAGER_PSI_GENERAL_REG
, 1, &data
);
1016 outb(VOYAGER_CAT_END
, CAT_CMD
);
1017 CDEBUG(("PSI STATUS 0x%x\n", data
));
1018 /* These two writes are power off prep and perform */
1020 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1021 cat_subwrite(&psi
, &psi_asic
, VOYAGER_PSI_GENERAL_REG
, 1, &data
);
1022 outb(VOYAGER_CAT_END
, CAT_CMD
);
1023 data
= PSI_POWER_DOWN
;
1024 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1025 cat_subwrite(&psi
, &psi_asic
, VOYAGER_PSI_GENERAL_REG
, 1, &data
);
1026 outb(VOYAGER_CAT_END
, CAT_CMD
);
1029 struct voyager_status voyager_status
= { 0 };
1031 void voyager_cat_psi(__u8 cmd
, __u16 reg
, __u8
* data
)
1033 voyager_module_t psi
= { 0 };
1034 voyager_asic_t psi_asic
= { 0 };
1036 psi
.asic
= &psi_asic
;
1037 psi
.asic
->asic_id
= VOYAGER_CAT_ID
;
1038 psi
.asic
->subaddr
= VOYAGER_SUBADDR_HI
;
1039 psi
.module_addr
= VOYAGER_PSI
;
1040 psi
.scan_path_connected
= 0;
1042 outb(VOYAGER_CAT_END
, CAT_CMD
);
1043 /* Connect the PSI to the CAT Bus */
1044 outb(VOYAGER_CAT_DESELECT
, VOYAGER_CAT_CONFIG_PORT
);
1045 outb(VOYAGER_PSI
, VOYAGER_CAT_CONFIG_PORT
);
1046 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1047 cat_disconnect(&psi
, &psi_asic
);
1049 case VOYAGER_PSI_READ
:
1050 cat_read(&psi
, &psi_asic
, reg
, data
);
1052 case VOYAGER_PSI_WRITE
:
1053 cat_write(&psi
, &psi_asic
, reg
, *data
);
1055 case VOYAGER_PSI_SUBREAD
:
1056 cat_subread(&psi
, &psi_asic
, reg
, 1, data
);
1058 case VOYAGER_PSI_SUBWRITE
:
1059 cat_subwrite(&psi
, &psi_asic
, reg
, 1, data
);
1062 printk(KERN_ERR
"Voyager PSI, unrecognised command %d\n", cmd
);
1065 outb(VOYAGER_CAT_END
, CAT_CMD
);
1068 void voyager_cat_do_common_interrupt(void)
1070 /* This is caused either by a memory parity error or something
1073 voyager_module_t psi
= { 0 };
1074 voyager_asic_t psi_asic
= { 0 };
1075 struct voyager_psi psi_reg
;
1078 psi
.asic
= &psi_asic
;
1079 psi
.asic
->asic_id
= VOYAGER_CAT_ID
;
1080 psi
.asic
->subaddr
= VOYAGER_SUBADDR_HI
;
1081 psi
.module_addr
= VOYAGER_PSI
;
1082 psi
.scan_path_connected
= 0;
1084 outb(VOYAGER_CAT_END
, CAT_CMD
);
1085 /* Connect the PSI to the CAT Bus */
1086 outb(VOYAGER_CAT_DESELECT
, VOYAGER_CAT_CONFIG_PORT
);
1087 outb(VOYAGER_PSI
, VOYAGER_CAT_CONFIG_PORT
);
1088 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1089 cat_disconnect(&psi
, &psi_asic
);
1090 /* Read the status. NOTE: Need to read *all* the PSI regs here
1091 * otherwise the cmn int will be reasserted */
1092 for (i
= 0; i
< sizeof(psi_reg
.regs
); i
++) {
1093 cat_read(&psi
, &psi_asic
, i
, &((__u8
*) & psi_reg
.regs
)[i
]);
1095 outb(VOYAGER_CAT_END
, CAT_CMD
);
1096 if ((psi_reg
.regs
.checkbit
& 0x02) == 0) {
1097 psi_reg
.regs
.checkbit
|= 0x02;
1098 cat_write(&psi
, &psi_asic
, 5, psi_reg
.regs
.checkbit
);
1099 printk("VOYAGER RE-READ PSI\n");
1102 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1103 for (i
= 0; i
< sizeof(psi_reg
.subregs
); i
++) {
1104 /* This looks strange, but the PSI doesn't do auto increment
1106 cat_subread(&psi
, &psi_asic
, VOYAGER_PSI_SUPPLY_REG
+ i
,
1107 1, &((__u8
*) & psi_reg
.subregs
)[i
]);
1109 outb(VOYAGER_CAT_END
, CAT_CMD
);
1110 #ifdef VOYAGER_CAT_DEBUG
1111 printk("VOYAGER PSI: ");
1112 for (i
= 0; i
< sizeof(psi_reg
.regs
); i
++)
1113 printk("%02x ", ((__u8
*) & psi_reg
.regs
)[i
]);
1115 for (i
= 0; i
< sizeof(psi_reg
.subregs
); i
++)
1116 printk("%02x ", ((__u8
*) & psi_reg
.subregs
)[i
]);
1119 if (psi_reg
.regs
.intstatus
& PSI_MON
) {
1120 /* switch off or power fail */
1122 if (psi_reg
.subregs
.supply
& PSI_SWITCH_OFF
) {
1123 if (voyager_status
.switch_off
) {
1125 "Voyager front panel switch turned off again---Immediate power off!\n");
1126 voyager_cat_power_off();
1130 "Voyager front panel switch turned off\n");
1131 voyager_status
.switch_off
= 1;
1132 voyager_status
.request_from_kernel
= 1;
1133 wake_up_process(voyager_thread
);
1135 /* Tell the hardware we're taking care of the
1136 * shutdown, otherwise it will power the box off
1137 * within 3 seconds of the switch being pressed and,
1138 * which is much more important to us, continue to
1139 * assert the common interrupt */
1140 data
= PSI_CLR_SWITCH_OFF
;
1141 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1142 cat_subwrite(&psi
, &psi_asic
, VOYAGER_PSI_SUPPLY_REG
,
1144 outb(VOYAGER_CAT_END
, CAT_CMD
);
1147 VDEBUG(("Voyager ac fail reg 0x%x\n",
1148 psi_reg
.subregs
.ACfail
));
1149 if ((psi_reg
.subregs
.ACfail
& AC_FAIL_STAT_CHANGE
) == 0) {
1150 /* No further update */
1154 /* Don't bother trying to find out who failed.
1155 * FIXME: This probably makes the code incorrect on
1156 * anything other than a 345x */
1157 for (i
= 0; i
< 5; i
++) {
1158 if (psi_reg
.subregs
.ACfail
& (1 << i
)) {
1162 printk(KERN_NOTICE
"AC FAIL IN SUPPLY %d\n", i
);
1164 /* DON'T do this: it shuts down the AC PSI
1165 outb(VOYAGER_CAT_RUN, CAT_CMD);
1166 data = PSI_MASK_MASK | i;
1167 cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_MASK,
1169 outb(VOYAGER_CAT_END, CAT_CMD);
1171 printk(KERN_ERR
"Voyager AC power failure\n");
1172 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1173 data
= PSI_COLD_START
;
1174 cat_subwrite(&psi
, &psi_asic
, VOYAGER_PSI_GENERAL_REG
,
1176 outb(VOYAGER_CAT_END
, CAT_CMD
);
1177 voyager_status
.power_fail
= 1;
1178 voyager_status
.request_from_kernel
= 1;
1179 wake_up_process(voyager_thread
);
1182 } else if (psi_reg
.regs
.intstatus
& PSI_FAULT
) {
1185 "Voyager PSI Detected major fault, immediate power off!\n");
1186 voyager_cat_power_off();
1188 } else if (psi_reg
.regs
.intstatus
& (PSI_DC_FAIL
| PSI_ALARM
1189 | PSI_CURRENT
| PSI_DVM
1190 | PSI_PSCFAULT
| PSI_STAT_CHG
)) {
1191 /* other psi fault */
1193 printk(KERN_WARNING
"Voyager PSI status 0x%x\n", data
);
1194 /* clear the PSI fault */
1195 outb(VOYAGER_CAT_RUN
, CAT_CMD
);
1196 cat_write(&psi
, &psi_asic
, VOYAGER_PSI_STATUS_REG
, 0);
1197 outb(VOYAGER_CAT_END
, CAT_CMD
);