1 diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig
2 --- linux.old/arch/mips/Kconfig 2005-12-15 13:26:49.758027500 +0100
3 +++ linux.dev/arch/mips/Kconfig 2005-12-15 12:57:27.889182500 +0100
5 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
6 Olivetti M700-10 workstations.
9 + bool "Support for BCM947xx based boards"
10 + select DMA_NONCOHERENT
13 + select SYS_HAS_CPU_MIPS32_R1
14 + select SYS_SUPPORTS_32BIT_KERNEL
15 + select SYS_SUPPORTS_LITTLE_ENDIAN
17 + Support for BCM947xx based boards
20 bool "Support for LASAT Networks platforms"
21 select DMA_NONCOHERENT
22 diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
23 --- linux.old/arch/mips/Makefile 2005-12-15 13:26:49.766024000 +0100
24 +++ linux.dev/arch/mips/Makefile 2005-12-15 12:57:27.921168500 +0100
26 load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000
29 +# Broadcom BCM47XX boards
31 +core-$(CONFIG_BCM947XX) += arch/mips/bcm947xx/ arch/mips/bcm947xx/broadcom/
32 +cflags-$(CONFIG_BCM947XX) += -Iarch/mips/bcm947xx/include
33 +load-$(CONFIG_BCM947XX) := 0xffffffff80001000
38 core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/
39 diff -urN linux.old/arch/mips/bcm947xx/Makefile linux.dev/arch/mips/bcm947xx/Makefile
40 --- linux.old/arch/mips/bcm947xx/Makefile 1970-01-01 01:00:00.000000000 +0100
41 +++ linux.dev/arch/mips/bcm947xx/Makefile 2005-12-15 14:32:03.580639500 +0100
44 +# Makefile for the BCM47xx specific kernel interface routines
48 +obj-y := irq.o int-handler.o prom.o setup.o time.o pci.o
49 diff -urN linux.old/arch/mips/bcm947xx/broadcom/Makefile linux.dev/arch/mips/bcm947xx/broadcom/Makefile
50 --- linux.old/arch/mips/bcm947xx/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100
51 +++ linux.dev/arch/mips/bcm947xx/broadcom/Makefile 2005-12-17 20:51:17.749271000 +0100
54 +# Makefile for the BCM47xx specific kernel interface routines
58 +obj-y := sbutils.o linux_osl.o bcmsrom.o bcmutils.o sbmips.o sbpci.o sflash.o nvram.o cfe_env.o
59 diff -urN linux.old/arch/mips/bcm947xx/broadcom/bcmsrom.c linux.dev/arch/mips/bcm947xx/broadcom/bcmsrom.c
60 --- linux.old/arch/mips/bcm947xx/broadcom/bcmsrom.c 1970-01-01 01:00:00.000000000 +0100
61 +++ linux.dev/arch/mips/bcm947xx/broadcom/bcmsrom.c 2005-12-17 01:21:23.007883000 +0100
64 + * Misc useful routines to access NIC SROM/OTP .
66 + * Copyright 2005, Broadcom Corporation
67 + * All Rights Reserved.
69 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
70 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
71 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
72 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
76 +#include <typedefs.h>
78 +#include <bcmutils.h>
81 +#include <bcmendian.h>
85 +#include <proto/ethernet.h> /* for sprom content groking */
87 +#define VARS_MAX 4096 /* should be reduced */
89 +#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
90 +#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
92 +static int initvars_srom_pci(void *sbh, void *curmap, char **vars, int *count);
93 +static int sprom_read_pci(uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc);
95 +static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count);
98 + * Initialize local vars from the right source for this platform.
99 + * Return 0 on success, nonzero on error.
102 +srom_var_init(void *sbh, uint bustype, void *curmap, osl_t *osh, char **vars, int *count)
104 + ASSERT(bustype == BUSTYPE(bustype));
105 + if (vars == NULL || count == NULL)
108 + switch (BUSTYPE(bustype)) {
111 + ASSERT(curmap); /* can not be NULL */
112 + return initvars_srom_pci(sbh, curmap, vars, count);
120 +/* support only 16-bit word read from srom */
122 +srom_read(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf)
127 + ASSERT(bustype == BUSTYPE(bustype));
129 + /* check input - 16-bit access only */
130 + if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2))
136 + if (BUSTYPE(bustype) == PCI_BUS) {
139 + srom = (uchar*)curmap + PCI_BAR0_SPROM_OFFSET;
140 + if (sprom_read_pci(srom, off, buf, nw, FALSE))
149 +/* support only 16-bit word write into srom */
151 +srom_write(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf)
154 + uint i, off, nw, crc_range;
155 + uint16 image[SPROM_SIZE], *p;
157 + volatile uint32 val32;
159 + ASSERT(bustype == BUSTYPE(bustype));
161 + /* check input - 16-bit access only */
162 + if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2))
165 + crc_range = (((BUSTYPE(bustype) == SDIO_BUS)) ? SPROM_SIZE : SPROM_CRC_RANGE) * 2;
167 + /* if changes made inside crc cover range */
168 + if (byteoff < crc_range) {
169 + nw = (((byteoff + nbytes) > crc_range) ? byteoff + nbytes : crc_range) / 2;
170 + /* read data including entire first 64 words from srom */
171 + if (srom_read(bustype, curmap, osh, 0, nw * 2, image))
174 + bcopy((void*)buf, (void*)&image[byteoff / 2], nbytes);
175 + /* calculate crc */
176 + htol16_buf(image, crc_range);
177 + crc = ~hndcrc8((uint8 *)image, crc_range - 1, CRC8_INIT_VALUE);
178 + ltoh16_buf(image, crc_range);
179 + image[(crc_range / 2) - 1] = (crc << 8) | (image[(crc_range / 2) - 1] & 0xff);
188 + if (BUSTYPE(bustype) == PCI_BUS) {
189 + srom = (uint16*)((uchar*)curmap + PCI_BAR0_SPROM_OFFSET);
190 + /* enable writes to the SPROM */
191 + val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
192 + val32 |= SPROM_WRITEEN;
193 + OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
194 + bcm_mdelay(WRITE_ENABLE_DELAY);
196 + for (i = 0; i < nw; i++) {
197 + W_REG(&srom[off + i], p[i]);
198 + bcm_mdelay(WRITE_WORD_DELAY);
200 + /* disable writes to the SPROM */
201 + OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & ~SPROM_WRITEEN);
206 + bcm_mdelay(WRITE_ENABLE_DELAY);
212 + * Read in and validate sprom.
213 + * Return 0 on success, nonzero on error.
216 +sprom_read_pci(uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc)
221 + /* read the sprom */
222 + for (i = 0; i < nwords; i++)
223 + buf[i] = R_REG(&sprom[wordoff + i]);
226 + /* fixup the endianness so crc8 will pass */
227 + htol16_buf(buf, nwords * 2);
228 + if (hndcrc8((uint8*)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE)
230 + /* now correct the endianness of the byte array */
231 + ltoh16_buf(buf, nwords * 2);
238 +* Create variable table from memory.
239 +* Return 0 on success, nonzero on error.
242 +initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count)
244 + int c = (int)(end - start);
246 + /* do it only when there is more than just the null string */
248 + char *vp = MALLOC(osh, c);
252 + bcopy(start, vp, c);
265 + * Initialize nonvolatile variable table from sprom.
266 + * Return 0 on success, nonzero on error.
269 +initvars_srom_pci(void *sbh, void *curmap, char **vars, int *count)
273 + struct ether_addr ea;
278 + osl_t *osh = sb_osh(sbh);
282 + * Apply CRC over SROM content regardless SROM is present or not,
283 + * and use variable <devpath>sromrev's existance in flash to decide
284 + * if we should return an error when CRC fails or read SROM variables
287 + sprom_read_pci((void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b, sizeof(b)/sizeof(b[0]), TRUE);
289 + /* top word of sprom contains version and crc8 */
290 + sromrev = b[63] & 0xff;
291 + /* bcm4401 sroms misprogrammed */
292 + if (sromrev == 0x10)
295 + /* srom version check */
302 + base = vp = MALLOC(osh, VARS_MAX);
307 + vp += sprintf(vp, "sromrev=%d", sromrev);
310 + if (sromrev >= 3) {
311 + /* New section takes over the 3th hardware function space */
313 + /* Words 22+23 are 11a (mid) ofdm power offsets */
314 + w32 = ((uint32)b[23] << 16) | b[22];
315 + vp += sprintf(vp, "ofdmapo=%d", w32);
318 + /* Words 24+25 are 11a (low) ofdm power offsets */
319 + w32 = ((uint32)b[25] << 16) | b[24];
320 + vp += sprintf(vp, "ofdmalpo=%d", w32);
323 + /* Words 26+27 are 11a (high) ofdm power offsets */
324 + w32 = ((uint32)b[27] << 16) | b[26];
325 + vp += sprintf(vp, "ofdmahpo=%d", w32);
328 + /*GPIO LED Powersave duty cycle (oncount >> 24) (offcount >> 8)*/
329 + w32 = ((uint32)b[43] << 24) | ((uint32)b[42] << 8);
330 + vp += sprintf(vp, "gpiotimerval=%d", w32);
332 + /*GPIO LED Powersave duty cycle (oncount >> 24) (offcount >> 8)*/
333 + w32 = ((uint32)((unsigned char)(b[21] >> 8) & 0xFF) << 24) | /* oncount*/
334 + ((uint32)((unsigned char)(b[21] & 0xFF)) << 8); /* offcount */
335 + vp += sprintf(vp, "gpiotimerval=%d", w32);
340 + if (sromrev >= 2) {
341 + /* New section takes over the 4th hardware function space */
343 + /* Word 29 is max power 11a high/low */
345 + vp += sprintf(vp, "pa1himaxpwr=%d", w & 0xff);
347 + vp += sprintf(vp, "pa1lomaxpwr=%d", (w >> 8) & 0xff);
350 + /* Words 30-32 set the 11alow pa settings,
351 + * 33-35 are the 11ahigh ones.
353 + for (i = 0; i < 3; i++) {
354 + vp += sprintf(vp, "pa1lob%d=%d", i, b[30 + i]);
356 + vp += sprintf(vp, "pa1hib%d=%d", i, b[33 + i]);
361 + vp += sprintf(vp, "ccode=");
363 + vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff));
368 + /* parameter section of sprom starts at byte offset 72 */
371 + /* first 6 bytes are il0macaddr */
372 + ea.octet[0] = (b[woff] >> 8) & 0xff;
373 + ea.octet[1] = b[woff] & 0xff;
374 + ea.octet[2] = (b[woff+1] >> 8) & 0xff;
375 + ea.octet[3] = b[woff+1] & 0xff;
376 + ea.octet[4] = (b[woff+2] >> 8) & 0xff;
377 + ea.octet[5] = b[woff+2] & 0xff;
378 + woff += ETHER_ADDR_LEN/2 ;
379 + bcm_ether_ntoa((uchar*)&ea, eabuf);
380 + vp += sprintf(vp, "il0macaddr=%s", eabuf);
383 + /* next 6 bytes are et0macaddr */
384 + ea.octet[0] = (b[woff] >> 8) & 0xff;
385 + ea.octet[1] = b[woff] & 0xff;
386 + ea.octet[2] = (b[woff+1] >> 8) & 0xff;
387 + ea.octet[3] = b[woff+1] & 0xff;
388 + ea.octet[4] = (b[woff+2] >> 8) & 0xff;
389 + ea.octet[5] = b[woff+2] & 0xff;
390 + woff += ETHER_ADDR_LEN/2 ;
391 + bcm_ether_ntoa((uchar*)&ea, eabuf);
392 + vp += sprintf(vp, "et0macaddr=%s", eabuf);
395 + /* next 6 bytes are et1macaddr */
396 + ea.octet[0] = (b[woff] >> 8) & 0xff;
397 + ea.octet[1] = b[woff] & 0xff;
398 + ea.octet[2] = (b[woff+1] >> 8) & 0xff;
399 + ea.octet[3] = b[woff+1] & 0xff;
400 + ea.octet[4] = (b[woff+2] >> 8) & 0xff;
401 + ea.octet[5] = b[woff+2] & 0xff;
402 + woff += ETHER_ADDR_LEN/2 ;
403 + bcm_ether_ntoa((uchar*)&ea, eabuf);
404 + vp += sprintf(vp, "et1macaddr=%s", eabuf);
408 + * Enet phy settings one or two singles or a dual
409 + * Bits 4-0 : MII address for enet0 (0x1f for not there)
410 + * Bits 9-5 : MII address for enet1 (0x1f for not there)
411 + * Bit 14 : Mdio for enet0
412 + * Bit 15 : Mdio for enet1
415 + vp += sprintf(vp, "et0phyaddr=%d", (w & 0x1f));
417 + vp += sprintf(vp, "et1phyaddr=%d", ((w >> 5) & 0x1f));
419 + vp += sprintf(vp, "et0mdcport=%d", ((w >> 14) & 0x1));
421 + vp += sprintf(vp, "et1mdcport=%d", ((w >> 15) & 0x1));
424 + /* Word 46 has board rev, antennas 0/1 & Country code/control */
426 + vp += sprintf(vp, "boardrev=%d", w & 0xff);
430 + vp += sprintf(vp, "cctl=%d", (w >> 8) & 0xf);
432 + vp += sprintf(vp, "cc=%d", (w >> 8) & 0xf);
435 + vp += sprintf(vp, "aa0=%d", (w >> 12) & 0x3);
438 + vp += sprintf(vp, "aa1=%d", (w >> 14) & 0x3);
441 + /* Words 47-49 set the (wl) pa settings */
444 + for (i = 0; i < 3; i++) {
445 + vp += sprintf(vp, "pa0b%d=%d", i, b[woff+i]);
447 + vp += sprintf(vp, "pa1b%d=%d", i, b[woff+i+6]);
452 + * Words 50-51 set the customer-configured wl led behavior.
453 + * 8 bits/gpio pin. High bit: activehi=0, activelo=1;
454 + * LED behavior values defined in wlioctl.h .
457 + if ((w != 0) && (w != 0xffff)) {
459 + vp += sprintf(vp, "wl0gpio0=%d", (w & 0xff));
463 + vp += sprintf(vp, "wl0gpio1=%d", (w >> 8) & 0xff);
467 + if ((w != 0) && (w != 0xffff)) {
469 + vp += sprintf(vp, "wl0gpio2=%d", w & 0xff);
473 + vp += sprintf(vp, "wl0gpio3=%d", (w >> 8) & 0xff);
477 + /* Word 52 is max power 0/1 */
479 + vp += sprintf(vp, "pa0maxpwr=%d", w & 0xff);
481 + vp += sprintf(vp, "pa1maxpwr=%d", (w >> 8) & 0xff);
484 + /* Word 56 is idle tssi target 0/1 */
486 + vp += sprintf(vp, "pa0itssit=%d", w & 0xff);
488 + vp += sprintf(vp, "pa1itssit=%d", (w >> 8) & 0xff);
491 + /* Word 57 is boardflags, if not programmed make it zero */
492 + w32 = (uint32)b[57];
493 + if (w32 == 0xffff) w32 = 0;
495 + /* Word 28 is the high bits of boardflags */
496 + w32 |= (uint32)b[28] << 16;
498 + vp += sprintf(vp, "boardflags=%d", w32);
501 + /* Word 58 is antenna gain 0/1 */
503 + vp += sprintf(vp, "ag0=%d", w & 0xff);
506 + vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff);
509 + if (sromrev == 1) {
510 + /* set the oem string */
511 + vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
512 + ((b[59] >> 8) & 0xff), (b[59] & 0xff),
513 + ((b[60] >> 8) & 0xff), (b[60] & 0xff),
514 + ((b[61] >> 8) & 0xff), (b[61] & 0xff),
515 + ((b[62] >> 8) & 0xff), (b[62] & 0xff));
517 + } else if (sromrev == 2) {
518 + /* Word 60 OFDM tx power offset from CCK level */
519 + /* OFDM Power Offset - opo */
520 + vp += sprintf(vp, "opo=%d", b[60] & 0xff);
523 + /* Word 60: cck power offsets */
524 + vp += sprintf(vp, "cckpo=%d", b[60]);
527 + /* Words 61+62: 11g ofdm power offsets */
528 + w32 = ((uint32)b[62] << 16) | b[61];
529 + vp += sprintf(vp, "ofdmgpo=%d", w32);
533 + /* final nullbyte terminator */
536 + ASSERT((vp - base) <= VARS_MAX);
538 + err = initvars_table(osh, base, vp, vars, count);
540 + MFREE(osh, base, VARS_MAX);
544 diff -urN linux.old/arch/mips/bcm947xx/broadcom/bcmutils.c linux.dev/arch/mips/bcm947xx/broadcom/bcmutils.c
545 --- linux.old/arch/mips/bcm947xx/broadcom/bcmutils.c 1970-01-01 01:00:00.000000000 +0100
546 +++ linux.dev/arch/mips/bcm947xx/broadcom/bcmutils.c 2005-12-17 17:53:52.387365000 +0100
549 + * Misc useful OS-independent routines.
551 + * Copyright 2005, Broadcom Corporation
552 + * All Rights Reserved.
554 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
555 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
556 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
557 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
561 +#include <typedefs.h>
563 +#include <sbutils.h>
564 +#include <bcmnvram.h>
565 +#include <bcmutils.h>
566 +#include <bcmendian.h>
567 +#include <bcmdevs.h>
569 +unsigned char bcm_ctype[] = {
570 + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */
571 + _BCM_C,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C,_BCM_C, /* 8-15 */
572 + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */
573 + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */
574 + _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */
575 + _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */
576 + _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */
577 + _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */
578 + _BCM_P,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U, /* 64-71 */
579 + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */
580 + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */
581 + _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */
582 + _BCM_P,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L, /* 96-103 */
583 + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
584 + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
585 + _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
586 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
587 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
588 + _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 160-175 */
589 + _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 176-191 */
590 + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 192-207 */
591 + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_L, /* 208-223 */
592 + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 224-239 */
593 + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L /* 240-255 */
597 +bcm_toupper(uchar c)
599 + if (bcm_islower(c))
605 +bcm_strtoul(char *cp, char **endp, uint base)
607 + ulong result, value;
612 + while (bcm_isspace(*cp))
617 + else if (cp[0] == '-') {
623 + if (cp[0] == '0') {
624 + if ((cp[1] == 'x') || (cp[1] == 'X')) {
633 + } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
639 + while (bcm_isxdigit(*cp) &&
640 + (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
641 + result = result*base + value;
646 + result = (ulong)(result * -1);
649 + *endp = (char *)cp;
661 + while (bcm_isdigit(*s))
662 + n = (n * 10) + *s++ - '0';
666 +/* return pointer to location of substring 'needle' in 'haystack' */
668 +bcmstrstr(char *haystack, char *needle)
673 + if ((haystack == NULL) || (needle == NULL))
676 + nlen = strlen(needle);
677 + len = strlen(haystack) - nlen + 1;
679 + for (i = 0; i < len; i++)
680 + if (bcmp(needle, &haystack[i], nlen) == 0)
681 + return (&haystack[i]);
686 +bcmstrcat(char *dest, const char *src)
688 + strcpy(&dest[strlen(dest)], src);
694 +bcm_ether_ntoa(char *ea, char *buf)
696 + sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x",
697 + (uchar)ea[0]&0xff, (uchar)ea[1]&0xff, (uchar)ea[2]&0xff,
698 + (uchar)ea[3]&0xff, (uchar)ea[4]&0xff, (uchar)ea[5]&0xff);
702 +/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
704 +bcm_ether_atoe(char *p, char *ea)
709 + ea[i++] = (char) bcm_strtoul(p, &p, 16);
710 + if (!*p++ || i == 6)
722 + for (i = 0; i < ms; i++) {
728 + * Search the name=value vars for a specific one and return its value.
729 + * Returns NULL if not found.
732 +getvar(char *vars, char *name)
737 + len = strlen(name);
739 + /* first look in vars[] */
740 + for (s = vars; s && *s; ) {
741 + if ((bcmp(s, name, len) == 0) && (s[len] == '='))
742 + return (&s[len+1]);
748 + /* then query nvram */
749 + return (BCMINIT(nvram_get)(name));
753 + * Search the vars for a specific one and return its value as
754 + * an integer. Returns 0 if not found.
757 +getintvar(char *vars, char *name)
761 + if ((val = getvar(vars, name)) == NULL)
764 + return (bcm_strtoul(val, NULL, 0));
768 +/* Search for token in comma separated token-string */
770 +findmatch(char *string, char *name)
775 + len = strlen(name);
776 + while ((c = strchr(string, ',')) != NULL) {
777 + if (len == (uint)(c - string) && !strncmp(string, name, len))
782 + return (!strcmp(string, name));
785 +/* Return gpio pin number assigned to the named pin */
787 +* Variable should be in format:
789 +* gpio<N>=pin_name,pin_name
791 +* This format allows multiple features to share the gpio with mutual
794 +* 'def_pin' is returned if a specific gpio is not defined for the requested functionality
795 +* and if def_pin is not used by others.
798 +getgpiopin(char *vars, char *pin_name, uint def_pin)
800 + char name[] = "gpioXXXX";
804 + /* Go thru all possibilities till a match in pin name */
805 + for (pin = 0; pin < GPIO_NUMPINS; pin ++) {
806 + sprintf(name, "gpio%d", pin);
807 + val = getvar(vars, name);
808 + if (val && findmatch(val, pin_name))
812 + if (def_pin != GPIO_PIN_NOTDEFINED) {
813 + /* make sure the default pin is not used by someone else */
814 + sprintf(name, "gpio%d", def_pin);
815 + if (getvar(vars, name)) {
816 + def_pin = GPIO_PIN_NOTDEFINED;
824 +/*******************************************************************************
827 + * Computes a crc8 over the input data using the polynomial:
829 + * x^8 + x^7 +x^6 + x^4 + x^2 + 1
831 + * The caller provides the initial value (either CRC8_INIT_VALUE
832 + * or the previous returned value) to allow for processing of
833 + * discontiguous blocks of data. When generating the CRC the
834 + * caller is responsible for complementing the final return value
835 + * and inserting it into the byte stream. When checking, a final
836 + * return value of CRC8_GOOD_VALUE indicates a valid CRC.
838 + * Reference: Dallas Semiconductor Application Note 27
839 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
840 + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
841 + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
843 + ******************************************************************************/
845 +static uint8 crc8_table[256] = {
846 + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
847 + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
848 + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
849 + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
850 + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
851 + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
852 + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
853 + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
854 + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
855 + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
856 + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
857 + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
858 + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
859 + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
860 + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
861 + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
862 + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
863 + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
864 + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
865 + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
866 + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
867 + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
868 + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
869 + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
870 + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
871 + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
872 + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
873 + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
874 + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
875 + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
876 + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
877 + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
880 +#define CRC_INNER_LOOP(n, c, x) \
881 + (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
885 + uint8 *pdata, /* pointer to array of data to process */
886 + uint nbytes, /* number of input data bytes to process */
887 + uint8 crc /* either CRC8_INIT_VALUE or previous return value */
890 + /* hard code the crc loop instead of using CRC_INNER_LOOP macro
891 + * to avoid the undefined and unnecessary (uint8 >> 8) operation. */
892 + while (nbytes-- > 0)
893 + crc = crc8_table[(crc ^ *pdata++) & 0xff];
900 +#define CBUFSIZ (CLEN+4)
904 diff -urN linux.old/arch/mips/bcm947xx/broadcom/cfe_env.c linux.dev/arch/mips/bcm947xx/broadcom/cfe_env.c
905 --- linux.old/arch/mips/bcm947xx/broadcom/cfe_env.c 1970-01-01 01:00:00.000000000 +0100
906 +++ linux.dev/arch/mips/bcm947xx/broadcom/cfe_env.c 2005-12-17 21:40:08.166726750 +0100
909 + * NVRAM variable manipulation (Linux kernel half)
911 + * Copyright 2001-2003, Broadcom Corporation
912 + * All Rights Reserved.
914 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
915 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
916 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
917 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
922 +#include <linux/config.h>
923 +#include <linux/init.h>
924 +#include <linux/module.h>
925 +#include <linux/kernel.h>
926 +#include <linux/string.h>
928 +#include <asm/uaccess.h>
930 +#include <typedefs.h>
932 +#include <bcmendian.h>
933 +#include <bcmutils.h>
935 +#define NVRAM_SIZE (0x1ff0)
936 +static char _nvdata[NVRAM_SIZE] __initdata;
937 +static char _valuestr[256] __initdata;
940 + * TLV types. These codes are used in the "type-length-value"
941 + * encoding of the items stored in the NVRAM device (flash or EEPROM)
943 + * The layout of the flash/nvram is as follows:
945 + * <type> <length> <data ...> <type> <length> <data ...> <type_end>
947 + * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
948 + * The "length" field marks the length of the data section, not
949 + * including the type and length fields.
951 + * Environment variables are stored as follows:
953 + * <type_env> <length> <flags> <name> = <value>
955 + * If bit 0 (low bit) is set, the length is an 8-bit value.
956 + * If bit 0 (low bit) is clear, the length is a 16-bit value
958 + * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
959 + * indicates the size of the length field.
961 + * Flags are from the constants below:
964 +#define ENV_LENGTH_16BITS 0x00 /* for low bit */
965 +#define ENV_LENGTH_8BITS 0x01
967 +#define ENV_TYPE_USER 0x80
969 +#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
970 +#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
973 + * The actual TLV types we support
976 +#define ENV_TLV_TYPE_END 0x00
977 +#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
980 + * Environment variable flags
983 +#define ENV_FLG_NORMAL 0x00 /* normal read/write */
984 +#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
985 +#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
987 +#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
988 +#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
991 +/* *********************************************************************
992 + * _nvram_read(buffer,offset,length)
994 + * Read data from the NVRAM device
996 + * Input parameters:
997 + * buffer - destination buffer
998 + * offset - offset of data to read
999 + * length - number of bytes to read
1002 + * number of bytes read, or <0 if error occured
1003 + ********************************************************************* */
1005 +_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
1008 + if (offset > NVRAM_SIZE)
1011 + for ( i = 0; i < length; i++) {
1012 + buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
1019 +_strnchr(const char *dest,int c,size_t cnt)
1021 + while (*dest && (cnt > 0)) {
1022 + if (*dest == c) return (char *) dest;
1032 + * Core support API: Externally visible.
1036 + * Get the value of an NVRAM variable
1037 + * @param name name of variable to get
1038 + * @return value of variable or NULL if undefined
1042 +cfe_env_get(unsigned char *nv_buf, char* name)
1045 + unsigned char *buffer;
1046 + unsigned char *ptr;
1047 + unsigned char *envval;
1048 + unsigned int reclen;
1049 + unsigned int rectype;
1053 + size = NVRAM_SIZE;
1054 + buffer = &_nvdata[0];
1059 + /* Read the record type and length */
1060 + if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
1064 + while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
1066 + /* Adjust pointer for TLV type */
1072 + * Read the length. It can be either 1 or 2 bytes
1073 + * depending on the code
1075 + if (rectype & ENV_LENGTH_8BITS) {
1076 + /* Read the record type and length - 8 bits */
1077 + if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
1085 + /* Read the record type and length - 16 bits, MSB first */
1086 + if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
1089 + reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
1094 + if (reclen > size)
1095 + break; /* should not happen, bad NVRAM */
1097 + switch (rectype) {
1098 + case ENV_TLV_TYPE_ENV:
1099 + /* Read the TLV data */
1100 + if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
1103 + envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
1106 + memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
1107 + _valuestr[(reclen-1)-(envval-ptr)] = '\0';
1109 + printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
1111 + if(!strcmp(ptr, name)){
1114 + if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
1120 + /* Unknown TLV type, skip it. */
1125 + * Advance to next TLV
1128 + size -= (int)reclen;
1131 + /* Read the next record type */
1133 + if (_nvram_read(nv_buf, ptr,offset,1) != 1)
1142 diff -urN linux.old/arch/mips/bcm947xx/broadcom/linux_osl.c linux.dev/arch/mips/bcm947xx/broadcom/linux_osl.c
1143 --- linux.old/arch/mips/bcm947xx/broadcom/linux_osl.c 1970-01-01 01:00:00.000000000 +0100
1144 +++ linux.dev/arch/mips/bcm947xx/broadcom/linux_osl.c 2005-12-15 17:11:05.818041750 +0100
1147 + * Linux OS Independent Layer
1149 + * Copyright 2005, Broadcom Corporation
1150 + * All Rights Reserved.
1152 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1153 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1154 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1155 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1162 +#include <typedefs.h>
1163 +#include <bcmendian.h>
1164 +#include <linux/module.h>
1165 +#include <linuxver.h>
1167 +#include <bcmutils.h>
1168 +#include <linux/delay.h>
1170 +#include <asm/paccess.h>
1172 +#include <pcicfg.h>
1174 +#define PCI_CFG_RETRY 10
1176 +#define OS_HANDLE_MAGIC 0x1234abcd
1177 +#define BCM_MEM_FILENAME_LEN 24
1179 +typedef struct bcm_mem_link {
1180 + struct bcm_mem_link *prev;
1181 + struct bcm_mem_link *next;
1184 + char file[BCM_MEM_FILENAME_LEN];
1192 + bcm_mem_link_t *dbgmem_list;
1196 +osl_pci_read_config(osl_t *osh, uint offset, uint size)
1199 + uint retry=PCI_CFG_RETRY;
1201 + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1203 + /* only 4byte access supported */
1204 + ASSERT(size == 4);
1207 + pci_read_config_dword(osh->pdev, offset, &val);
1208 + if (val != 0xffffffff)
1210 + } while (retry--);
1217 +osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
1219 + uint retry=PCI_CFG_RETRY;
1221 + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1223 + /* only 4byte access supported */
1224 + ASSERT(size == 4);
1227 + pci_write_config_dword(osh->pdev, offset, val);
1228 + if (offset!=PCI_BAR0_WIN)
1230 + if (osl_pci_read_config(osh,offset,size) == val)
1232 + } while (retry--);
1237 +osl_delay(uint usec)
1241 + while (usec > 0) {
1242 + d = MIN(usec, 1000);
1248 diff -urN linux.old/arch/mips/bcm947xx/broadcom/nvram.c linux.dev/arch/mips/bcm947xx/broadcom/nvram.c
1249 --- linux.old/arch/mips/bcm947xx/broadcom/nvram.c 1970-01-01 01:00:00.000000000 +0100
1250 +++ linux.dev/arch/mips/bcm947xx/broadcom/nvram.c 2005-12-18 04:59:36.185204500 +0100
1253 + * NVRAM variable manipulation (Linux kernel half)
1255 + * Copyright 2005, Broadcom Corporation
1256 + * All Rights Reserved.
1258 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1259 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1260 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1261 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1266 +#include <linux/config.h>
1267 +#include <linux/init.h>
1268 +#include <linux/module.h>
1269 +#include <linux/kernel.h>
1270 +#include <linux/string.h>
1271 +#include <linux/interrupt.h>
1272 +#include <linux/spinlock.h>
1273 +#include <linux/slab.h>
1274 +#include <asm/bootinfo.h>
1275 +#include <asm/addrspace.h>
1276 +#include <asm/io.h>
1277 +#include <asm/uaccess.h>
1279 +#include <typedefs.h>
1280 +#include <bcmendian.h>
1281 +#include <bcmnvram.h>
1282 +#include <bcmutils.h>
1283 +#include <sbconfig.h>
1284 +#include <sbchipc.h>
1285 +#include <sbutils.h>
1286 +#include <sbmips.h>
1287 +#include <sflash.h>
1289 +/* In BSS to minimize text size and page aligned so it can be mmap()-ed */
1290 +static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE)));
1292 +/* Global SB handle */
1294 +extern spinlock_t bcm947xx_sbh_lock;
1295 +static int cfe_env;
1297 +extern char *cfe_env_get(char *nv_buf, const char *name);
1301 +#define sbh_lock bcm947xx_sbh_lock
1303 +#define MB * 1024 * 1024
1305 +/* Probe for NVRAM header */
1307 +early_nvram_init(void)
1309 + struct nvram_header *header;
1311 + struct sflash *info = NULL;
1313 + uint32 base, off, lim;
1317 + if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) {
1318 + base = KSEG1ADDR(SB_FLASH2);
1319 + switch (readl(&cc->capabilities) & CAP_FLASH_MASK) {
1321 + lim = SB_FLASH2_SZ;
1326 + if ((info = sflash_init(cc)) == NULL)
1336 + /* extif assumed, Stop at 4 MB */
1337 + base = KSEG1ADDR(SB_FLASH1);
1338 + lim = SB_FLASH1_SZ;
1341 + /* XXX: hack for supporting the CFE environment stuff on WGT634U */
1342 + src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000);
1343 + dst = (u32 *) nvram_buf;
1344 + if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) {
1345 + printk("early_nvram_init: WGT634U NVRAM found.\n");
1347 + for (i = 0; i < 0x1ff0; i++) {
1348 + if (*src == 0xFFFFFFFF)
1357 + while (off <= lim) {
1358 + /* Windowed flash access */
1359 + header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
1360 + if (header->magic == NVRAM_MAGIC)
1365 + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
1366 + header = (struct nvram_header *) KSEG1ADDR(base + 4 KB);
1367 + if (header->magic == NVRAM_MAGIC)
1370 + header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
1371 + if (header->magic == NVRAM_MAGIC)
1377 + src = (u32 *) header;
1378 + dst = (u32 *) nvram_buf;
1379 + for (i = 0; i < sizeof(struct nvram_header); i += 4)
1381 + for (; i < header->len && i < NVRAM_SPACE; i += 4)
1382 + *dst++ = ltoh32(*src++);
1385 +/* Early (before mm or mtd) read-only access to NVRAM */
1386 +char * __init nvram_get(const char *name)
1388 + char *var, *value, *end, *eq;
1397 + if (!nvram_buf[0])
1398 + early_nvram_init();
1401 + return cfe_env_get(nvram_buf, name);
1403 + /* Look for name=value and return value */
1404 + var = &nvram_buf[sizeof(struct nvram_header)];
1405 + end = nvram_buf + sizeof(nvram_buf) - 2;
1406 + end[0] = end[1] = '\0';
1407 + for (; *var; var = value + strlen(value) + 1) {
1408 + if (!(eq = strchr(var, '=')))
1411 + if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
1417 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbmips.c linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c
1418 --- linux.old/arch/mips/bcm947xx/broadcom/sbmips.c 1970-01-01 01:00:00.000000000 +0100
1419 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c 2005-12-15 16:46:31.122961250 +0100
1422 + * BCM47XX Sonics SiliconBackplane MIPS core routines
1424 + * Copyright 2005, Broadcom Corporation
1425 + * All Rights Reserved.
1427 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1428 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1429 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1430 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1435 +#include <typedefs.h>
1437 +#include <sbutils.h>
1438 +#include <bcmdevs.h>
1439 +#include <bcmnvram.h>
1440 +#include <bcmutils.h>
1441 +#include <hndmips.h>
1442 +#include <sbconfig.h>
1443 +#include <sbextif.h>
1444 +#include <sbchipc.h>
1445 +#include <sbmemc.h>
1446 +#include <mipsinc.h>
1447 +#include <sbutils.h>
1450 + * Returns TRUE if an external UART exists at the given base
1454 +BCMINITFN(serial_exists)(uint8 *regs)
1456 + uint8 save_mcr, status1;
1458 + save_mcr = R_REG(®s[UART_MCR]);
1459 + W_REG(®s[UART_MCR], UART_MCR_LOOP | 0x0a);
1460 + status1 = R_REG(®s[UART_MSR]) & 0xf0;
1461 + W_REG(®s[UART_MCR], save_mcr);
1463 + return (status1 == 0x90);
1467 + * Initializes UART access. The callback function will be called once
1471 +BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift))
1478 + if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
1479 + extifregs_t *eir = (extifregs_t *) regs;
1482 + /* Determine external UART register base */
1483 + sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
1484 + base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
1486 + /* Determine IRQ */
1487 + irq = sb_irq(sbh);
1489 + /* Disable GPIO interrupt initially */
1490 + W_REG(&eir->gpiointpolarity, 0);
1491 + W_REG(&eir->gpiointmask, 0);
1493 + /* Search for external UARTs */
1495 + for (i = 0; i < 2; i++) {
1496 + regs = (void *) REG_MAP(base + (i * 8), 8);
1497 + if (BCMINIT(serial_exists)(regs)) {
1498 + /* Set GPIO 1 to be the external UART IRQ */
1499 + W_REG(&eir->gpiointmask, 2);
1501 + add(regs, irq, 13500000, 0);
1505 + /* Add internal UART if enabled */
1506 + if (R_REG(&eir->corecontrol) & CC_UE)
1508 + add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
1509 + } else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
1510 + chipcregs_t *cc = (chipcregs_t *) regs;
1511 + uint32 rev, cap, pll, baud_base, div;
1513 + /* Determine core revision and capabilities */
1514 + rev = sb_corerev(sbh);
1515 + cap = R_REG(&cc->capabilities);
1516 + pll = cap & CAP_PLL_MASK;
1518 + /* Determine IRQ */
1519 + irq = sb_irq(sbh);
1521 + if (pll == PLL_TYPE1) {
1523 + baud_base = sb_clock_rate(pll,
1524 + R_REG(&cc->clockcontrol_n),
1525 + R_REG(&cc->clockcontrol_m2));
1529 + /* Fixed ALP clock */
1530 + baud_base = 20000000;
1532 + /* Set the override bit so we don't divide it */
1533 + W_REG(&cc->corecontrol, CC_UARTCLKO);
1534 + } else if (rev >= 3) {
1535 + /* Internal backplane clock */
1536 + baud_base = sb_clock(sbh);
1537 + div = 2; /* Minimum divisor */
1538 + W_REG(&cc->clkdiv,
1539 + ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div));
1541 + /* Fixed internal backplane clock */
1542 + baud_base = 88000000;
1546 + /* Clock source depends on strapping if UartClkOverride is unset */
1548 + ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) {
1549 + if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
1550 + /* Internal divided backplane clock */
1553 + /* Assume external clock of 1.8432 MHz */
1554 + baud_base = 1843200;
1559 + /* Add internal UARTs */
1560 + n = cap & CAP_UARTS_MASK;
1561 + for (i = 0; i < n; i++) {
1562 + /* Register offset changed after revision 0 */
1564 + regs = (void *)((ulong) &cc->uart0data + (i * 256));
1566 + regs = (void *)((ulong) &cc->uart0data + (i * 8));
1569 + add(regs, irq, baud_base, 0);
1575 + * Initialize jtag master and return handle for
1576 + * jtag_rwreg. Returns NULL on failure.
1579 +sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap)
1583 + if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) {
1584 + chipcregs_t *cc = (chipcregs_t *) regs;
1588 + * Determine jtagm availability from
1589 + * core revision and capabilities.
1591 + tmp = sb_corerev(sbh);
1593 + * Corerev 10 has jtagm, but the only chip
1594 + * with it does not have a mips, and
1595 + * the layout of the jtagcmd register is
1596 + * different. We'll only accept >= 11.
1601 + tmp = R_REG(&cc->capabilities);
1602 + if ((tmp & CAP_JTAGP) == 0)
1605 + /* Set clock divider if requested */
1607 + tmp = R_REG(&cc->clkdiv);
1608 + tmp = (tmp & ~CLKD_JTAG) |
1609 + ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG);
1610 + W_REG(&cc->clkdiv, tmp);
1613 + /* Enable jtagm */
1614 + tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
1615 + W_REG(&cc->jtagctrl, tmp);
1622 +sb_jtagm_disable(void *h)
1624 + chipcregs_t *cc = (chipcregs_t *)h;
1626 + W_REG(&cc->jtagctrl, R_REG(&cc->jtagctrl) & ~JCTRL_EN);
1630 + * Read/write a jtag register. Assumes a target with
1631 + * 8 bit IR and 32 bit DR.
1636 +jtag_rwreg(void *h, uint32 ir, uint32 dr)
1638 + chipcregs_t *cc = (chipcregs_t *) h;
1641 + W_REG(&cc->jtagir, ir);
1642 + W_REG(&cc->jtagdr, dr);
1643 + tmp = JCMD_START | JCMD_ACC_IRDR |
1644 + ((IRWIDTH - 1) << JCMD_IRW_SHIFT) |
1646 + W_REG(&cc->jtagcmd, tmp);
1647 + while (((tmp = R_REG(&cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) {
1648 + /* OSL_DELAY(1); */
1651 + tmp = R_REG(&cc->jtagdr);
1655 +/* Returns the SB interrupt flag of the current core. */
1662 + regs = sb_coreregs(sbh);
1663 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1665 + return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
1668 +static const uint32 sbips_int_mask[] = {
1676 +static const uint32 sbips_int_shift[] = {
1685 + * Returns the MIPS IRQ assignment of the current core. If unassigned,
1694 + uint32 flag, sbipsflag;
1697 + flag = sb_flag(sbh);
1699 + idx = sb_coreidx(sbh);
1701 + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
1702 + (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
1703 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1705 + /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
1706 + sbipsflag = R_REG(&sb->sbipsflag);
1707 + for (irq = 1; irq <= 4; irq++) {
1708 + if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag)
1715 + sb_setcoreidx(sbh, idx);
1720 +/* Clears the specified MIPS IRQ. */
1722 +BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq)
1727 + if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
1728 + !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
1730 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1733 + W_REG(&sb->sbintvec, 0);
1735 + OR_REG(&sb->sbipsflag, sbips_int_mask[irq]);
1739 + * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
1740 + * IRQ 0 may be assigned more than once.
1743 +BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit)
1749 + regs = sb_setcore(sbh, coreid, coreunit);
1751 + flag = sb_flag(sbh);
1753 + if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
1754 + !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
1756 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1759 + OR_REG(&sb->sbintvec, 1 << flag);
1761 + flag <<= sbips_int_shift[irq];
1762 + ASSERT(!(flag & ~sbips_int_mask[irq]));
1763 + flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq];
1764 + W_REG(&sb->sbipsflag, flag);
1769 + * Initializes clocks and interrupts. SB and NVRAM access must be
1770 + * initialized prior to calling.
1773 +BCMINITFN(sb_mips_init)(sb_t *sbh)
1775 + ulong hz, ns, tmp;
1781 + /* Figure out current SB clock speed */
1782 + if ((hz = sb_clock(sbh)) == 0)
1784 + ns = 1000000000 / hz;
1786 + /* Setup external interface timing */
1787 + if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
1788 + /* Initialize extif so we can get to the LEDs and external UART */
1789 + W_REG(&eir->prog_config, CF_EN);
1791 + /* Set timing for the flash */
1792 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1793 + tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
1794 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1795 + W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1797 + /* Set programmable interface timing for external uart */
1798 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1799 + tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
1800 + tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
1801 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1802 + W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1803 + } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
1804 + /* Set timing for the flash */
1805 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1806 + tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
1807 + tmp |= CEIL(120, ns); /* W0 = 120nS */
1809 + // Added by Chen-I for 5365
1810 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
1812 + W_REG(&cc->flash_waitcount, tmp);
1813 + W_REG(&cc->pcmcia_memwait, tmp);
1817 + if (sb_corerev(sbh) < 9)
1818 + W_REG(&cc->flash_waitcount, tmp);
1820 + if ((sb_corerev(sbh) < 9) ||
1821 + ((BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID) && BCMINIT(sb_chiprev)(sbh) == 0)) {
1822 + W_REG(&cc->pcmcia_memwait, tmp);
1827 + /* Chip specific initialization */
1828 + switch (BCMINIT(sb_chip)(sbh)) {
1829 + case BCM4710_DEVICE_ID:
1830 + /* Clear interrupt map */
1831 + for (irq = 0; irq <= 4; irq++)
1832 + BCMINIT(sb_clearirq)(sbh, irq);
1833 + BCMINIT(sb_setirq)(sbh, 0, SB_CODEC, 0);
1834 + BCMINIT(sb_setirq)(sbh, 0, SB_EXTIF, 0);
1835 + BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 1);
1836 + BCMINIT(sb_setirq)(sbh, 3, SB_ILINE20, 0);
1837 + BCMINIT(sb_setirq)(sbh, 4, SB_PCI, 0);
1839 + value = BCMINIT(nvram_get)("et0phyaddr");
1840 + if (value && !strcmp(value, "31")) {
1841 + /* Enable internal UART */
1842 + W_REG(&eir->corecontrol, CC_UE);
1843 + /* Give USB its own interrupt */
1844 + BCMINIT(sb_setirq)(sbh, 1, SB_USB, 0);
1846 + /* Disable internal UART */
1847 + W_REG(&eir->corecontrol, 0);
1848 + /* Give Ethernet its own interrupt */
1849 + BCMINIT(sb_setirq)(sbh, 1, SB_ENET, 0);
1850 + BCMINIT(sb_setirq)(sbh, 0, SB_USB, 0);
1853 + case BCM5350_DEVICE_ID:
1854 + /* Clear interrupt map */
1855 + for (irq = 0; irq <= 4; irq++)
1856 + BCMINIT(sb_clearirq)(sbh, irq);
1857 + BCMINIT(sb_setirq)(sbh, 0, SB_CC, 0);
1858 + BCMINIT(sb_setirq)(sbh, 1, SB_D11, 0);
1859 + BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 0);
1860 + BCMINIT(sb_setirq)(sbh, 3, SB_PCI, 0);
1861 + BCMINIT(sb_setirq)(sbh, 4, SB_USB, 0);
1867 +BCMINITFN(sb_mips_clock)(sb_t *sbh)
1873 + uint32 pll_type, rate = 0;
1875 + /* get index of the current core */
1876 + idx = sb_coreidx(sbh);
1877 + pll_type = PLL_TYPE1;
1879 + /* switch to extif or chipc core */
1880 + if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
1881 + n = R_REG(&eir->clockcontrol_n);
1882 + m = R_REG(&eir->clockcontrol_sb);
1883 + } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
1884 + pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
1885 + n = R_REG(&cc->clockcontrol_n);
1886 + if ((pll_type == PLL_TYPE2) ||
1887 + (pll_type == PLL_TYPE4) ||
1888 + (pll_type == PLL_TYPE6) ||
1889 + (pll_type == PLL_TYPE7))
1890 + m = R_REG(&cc->clockcontrol_mips);
1891 + else if (pll_type == PLL_TYPE5) {
1895 + else if (pll_type == PLL_TYPE3) {
1896 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) { /* 5365 is also type3 */
1900 + m = R_REG(&cc->clockcontrol_m2); /* 5350 uses m2 to control mips */
1902 + m = R_REG(&cc->clockcontrol_sb);
1906 + // Added by Chen-I for 5365
1907 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
1910 + /* calculate rate */
1911 + rate = sb_clock_rate(pll_type, n, m);
1913 + if (pll_type == PLL_TYPE6)
1914 + rate = SB2MIPS_T6(rate);
1917 + /* switch back to previous core */
1918 + sb_setcoreidx(sbh, idx);
1923 +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
1926 +BCMINITFN(handler)(void)
1930 + ".set\tmips32\n\t"
1933 + /* Disable interrupts */
1934 + /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
1935 + "mfc0 $15, $12\n\t"
1936 + /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
1937 + "li $14, -31746\n\t"
1938 + "and $15, $15, $14\n\t"
1939 + "mtc0 $15, $12\n\t"
1947 +/* The following MUST come right after handler() */
1949 +BCMINITFN(afterhandler)(void)
1954 + * Set the MIPS, backplane and PCI clocks as closely as possible.
1957 +BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock)
1959 + extifregs_t *eir = NULL;
1960 + chipcregs_t *cc = NULL;
1961 + mipsregs_t *mipsr = NULL;
1962 + volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2;
1963 + uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg;
1964 + uint32 pll_type, sync_mode;
1965 + uint ic_size, ic_lsize;
1974 + static n3m_table_t BCMINITDATA(type1_table)[] = {
1975 + { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /* 96.000 32.000 24.000 */
1976 + { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */
1977 + { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */
1978 + { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */
1979 + { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */
1980 + { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */
1981 + { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */
1982 + { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */
1983 + { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */
1984 + { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */
1985 + { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */
1986 + { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */
1987 + { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */
1988 + { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */
1989 + { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */
1990 + { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */
1991 + { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */
1992 + { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */
1993 + { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */
1994 + { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */
1999 + uint32 m2; /* that is the clockcontrol_m2 */
2001 + static type3_table_t type3_table[] = { /* for 5350, mips clock is always double sb clock */
2002 + { 150000000, 0x311, 0x4020005 },
2003 + { 200000000, 0x311, 0x4020003 },
2014 + uint32 ratio_parm;
2017 + static n4m_table_t BCMINITDATA(type2_table)[] = {
2018 + { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2019 + { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
2020 + { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555 },
2021 + { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2022 + { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2023 + { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2024 + { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2025 + { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2026 + { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
2027 + { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2028 + { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2029 + { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2030 + { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
2031 + { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2032 + { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
2033 + { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2034 + { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 11, 0x0aaa0555 }
2037 + static n4m_table_t BCMINITDATA(type4_table)[] = {
2038 + { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2039 + { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2040 + { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
2041 + { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2042 + { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2043 + { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2044 + { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2045 + { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2046 + { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, 0x012a00a9 },
2047 + { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2048 + { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, 0x254a14a9 },
2049 + { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2050 + { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, 0x02520129 },
2051 + { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
2052 + { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
2053 + { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2054 + { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2055 + { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2056 + { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, 0x02520129 },
2057 + { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, 0x0aaa0555 }
2060 + static n4m_table_t BCMINITDATA(type7_table)[] = {
2061 + { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2062 + { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2063 + { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2064 + { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, 0x0aaa0555 },
2065 + { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
2066 + { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2067 + { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2068 + { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2069 + { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2070 + { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2071 + { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2072 + { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2073 + { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, 0x0aaa0555 },
2074 + { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, 0x0aaa0555 }
2077 + ulong start, end, dst;
2080 + /* get index of the current core */
2081 + idx = sb_coreidx(sbh);
2082 + clockcontrol_m2 = NULL;
2084 + /* switch to extif or chipc core */
2085 + if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
2086 + pll_type = PLL_TYPE1;
2087 + clockcontrol_n = &eir->clockcontrol_n;
2088 + clockcontrol_sb = &eir->clockcontrol_sb;
2089 + clockcontrol_pci = &eir->clockcontrol_pci;
2090 + clockcontrol_m2 = &cc->clockcontrol_m2;
2091 + } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
2092 + pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
2093 + if (pll_type == PLL_TYPE6) {
2094 + clockcontrol_n = NULL;
2095 + clockcontrol_sb = NULL;
2096 + clockcontrol_pci = NULL;
2098 + clockcontrol_n = &cc->clockcontrol_n;
2099 + clockcontrol_sb = &cc->clockcontrol_sb;
2100 + clockcontrol_pci = &cc->clockcontrol_pci;
2101 + clockcontrol_m2 = &cc->clockcontrol_m2;
2106 + if (pll_type == PLL_TYPE6) {
2107 + /* Silence compilers */
2108 + orig_n = orig_sb = orig_pci = 0;
2110 + /* Store the current clock register values */
2111 + orig_n = R_REG(clockcontrol_n);
2112 + orig_sb = R_REG(clockcontrol_sb);
2113 + orig_pci = R_REG(clockcontrol_pci);
2116 + if (pll_type == PLL_TYPE1) {
2117 + /* Keep the current PCI clock if not specified */
2118 + if (pciclock == 0) {
2119 + pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci));
2120 + pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
2123 + /* Search for the closest MIPS clock less than or equal to a preferred value */
2124 + for (i = 0; i < ARRAYSIZE(BCMINIT(type1_table)); i++) {
2125 + ASSERT(BCMINIT(type1_table)[i].mipsclock ==
2126 + sb_clock_rate(pll_type, BCMINIT(type1_table)[i].n, BCMINIT(type1_table)[i].sb));
2127 + if (BCMINIT(type1_table)[i].mipsclock > mipsclock)
2137 + ASSERT(BCMINIT(type1_table)[i].mipsclock <= mipsclock);
2139 + /* No PLL change */
2140 + if ((orig_n == BCMINIT(type1_table)[i].n) &&
2141 + (orig_sb == BCMINIT(type1_table)[i].sb) &&
2142 + (orig_pci == BCMINIT(type1_table)[i].pci33))
2145 + /* Set the PLL controls */
2146 + W_REG(clockcontrol_n, BCMINIT(type1_table)[i].n);
2147 + W_REG(clockcontrol_sb, BCMINIT(type1_table)[i].sb);
2148 + if (pciclock == 25000000)
2149 + W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci25);
2151 + W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci33);
2154 + sb_watchdog(sbh, 1);
2157 + } else if ((pll_type == PLL_TYPE3) &&
2158 + (BCMINIT(sb_chip)(sbh) != BCM5365_DEVICE_ID)) {
2160 + /* Search for the closest MIPS clock less than or equal to a preferred value */
2162 + for (i = 0; i < ARRAYSIZE(type3_table); i++) {
2163 + if (type3_table[i].mipsclock > mipsclock)
2173 + ASSERT(type3_table[i].mipsclock <= mipsclock);
2175 + /* No PLL change */
2176 + orig_m2 = R_REG(&cc->clockcontrol_m2);
2177 + if ((orig_n == type3_table[i].n) &&
2178 + (orig_m2 == type3_table[i].m2)) {
2182 + /* Set the PLL controls */
2183 + W_REG(clockcontrol_n, type3_table[i].n);
2184 + W_REG(clockcontrol_m2, type3_table[i].m2);
2187 + sb_watchdog(sbh, 1);
2189 + } else if ((pll_type == PLL_TYPE2) ||
2190 + (pll_type == PLL_TYPE4) ||
2191 + (pll_type == PLL_TYPE6) ||
2192 + (pll_type == PLL_TYPE7)) {
2193 + n4m_table_t *table = NULL, *te;
2198 + orig_mips = R_REG(&cc->clockcontrol_mips);
2200 + if (pll_type == PLL_TYPE6) {
2201 + uint32 new_mips = 0;
2204 + if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
2205 + new_mips = CC_T6_MMASK;
2207 + if (orig_mips == new_mips)
2210 + W_REG(&cc->clockcontrol_mips, new_mips);
2214 + if (pll_type == PLL_TYPE2) {
2215 + table = BCMINIT(type2_table);
2216 + tabsz = ARRAYSIZE(BCMINIT(type2_table));
2217 + } else if (pll_type == PLL_TYPE4) {
2218 + table = BCMINIT(type4_table);
2219 + tabsz = ARRAYSIZE(BCMINIT(type4_table));
2220 + } else if (pll_type == PLL_TYPE7) {
2221 + table = BCMINIT(type7_table);
2222 + tabsz = ARRAYSIZE(BCMINIT(type7_table));
2224 + ASSERT("No table for plltype" == NULL);
2226 + /* Store the current clock register values */
2227 + orig_m2 = R_REG(&cc->clockcontrol_m2);
2228 + orig_ratio_parm = 0;
2229 + orig_ratio_cfg = 0;
2231 + /* Look up current ratio */
2232 + for (i = 0; i < tabsz; i++) {
2233 + if ((orig_n == table[i].n) &&
2234 + (orig_sb == table[i].sb) &&
2235 + (orig_pci == table[i].pci33) &&
2236 + (orig_m2 == table[i].m2) &&
2237 + (orig_mips == table[i].m3)) {
2238 + orig_ratio_parm = table[i].ratio_parm;
2239 + orig_ratio_cfg = table[i].ratio_cfg;
2244 + /* Search for the closest MIPS clock greater or equal to a preferred value */
2245 + for (i = 0; i < tabsz; i++) {
2246 + ASSERT(table[i].mipsclock ==
2247 + sb_clock_rate(pll_type, table[i].n, table[i].m3));
2248 + if ((mipsclock <= table[i].mipsclock) &&
2249 + ((sbclock == 0) || (sbclock <= table[i].sbclock)))
2260 + /* No PLL change */
2261 + if ((orig_n == te->n) &&
2262 + (orig_sb == te->sb) &&
2263 + (orig_pci == te->pci33) &&
2264 + (orig_m2 == te->m2) &&
2265 + (orig_mips == te->m3))
2268 + /* Set the PLL controls */
2269 + W_REG(clockcontrol_n, te->n);
2270 + W_REG(clockcontrol_sb, te->sb);
2271 + W_REG(clockcontrol_pci, te->pci33);
2272 + W_REG(&cc->clockcontrol_m2, te->m2);
2273 + W_REG(&cc->clockcontrol_mips, te->m3);
2275 + /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
2276 + if ((pll_type == PLL_TYPE7) &&
2277 + (te->sb != te->m2) &&
2278 + (sb_clock_rate(pll_type, te->n, te->m2) == 120000000))
2279 + W_REG(&cc->chipcontrol, R_REG(&cc->chipcontrol) | 0x100);
2281 + /* No ratio change */
2282 + if (orig_ratio_parm == te->ratio_parm)
2285 + icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
2287 + /* Preload the code into the cache */
2288 + start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
2289 + end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
2290 + while (start < end) {
2291 + cache_op(start, Fill_I);
2292 + start += ic_lsize;
2295 + /* Copy the handler */
2296 + start = (ulong) &BCMINIT(handler);
2297 + end = (ulong) &BCMINIT(afterhandler);
2298 + dst = KSEG1ADDR(0x180);
2299 + for (i = 0; i < (end - start); i += 4)
2300 + *((ulong *)(dst + i)) = *((ulong *)(start + i));
2302 + /* Preload handler into the cache one line at a time */
2303 + for (i = 0; i < (end - start); i += 4)
2304 + cache_op(dst + i, Fill_I);
2306 + /* Clear BEV bit */
2307 + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
2309 + /* Enable interrupts */
2310 + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
2312 + /* Enable MIPS timer interrupt */
2313 + if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
2314 + !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
2316 + W_REG(&mipsr->intmask, 1);
2319 + /* step 1, set clock ratios */
2320 + MTC0(C0_BROADCOM, 3, te->ratio_parm);
2321 + MTC0(C0_BROADCOM, 1, te->ratio_cfg);
2323 + /* step 2: program timer intr */
2324 + W_REG(&mipsr->timer, 100);
2325 + (void) R_REG(&mipsr->timer);
2327 + /* step 3, switch to async */
2328 + sync_mode = MFC0(C0_BROADCOM, 4);
2329 + MTC0(C0_BROADCOM, 4, 1 << 22);
2331 + /* step 4, set cfg active */
2332 + MTC0(C0_BROADCOM, 2, 0x9);
2336 + __asm__ __volatile__ (
2342 + /* step 7, clear cfg_active */
2343 + MTC0(C0_BROADCOM, 2, 0);
2345 + /* Additional Step: set back to orig sync mode */
2346 + MTC0(C0_BROADCOM, 4, sync_mode);
2348 + /* step 8, fake soft reset */
2349 + MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4);
2352 + /* step 9 set watchdog timer */
2353 + sb_watchdog(sbh, 20);
2354 + (void) R_REG(&cc->chipid);
2357 + __asm__ __volatile__ (
2367 + /* switch back to previous core */
2368 + sb_setcoreidx(sbh, idx);
2374 + * This also must be run from the cache on 47xx
2375 + * so there are no mips core BIU ops in progress
2376 + * when the PFC is enabled.
2380 +BCMINITFN(_enable_pfc)(uint32 mode)
2383 + *(volatile uint32 *)PFC_CR1 = 0xffff0000;
2386 + *(volatile uint32 *)PFC_CR0 = mode;
2390 +BCMINITFN(enable_pfc)(uint32 mode)
2395 + /* If auto then choose the correct mode for this
2396 + platform, currently we only ever select one mode */
2397 + if (mode == PFC_AUTO)
2400 + /* enable prefetch cache if available */
2401 + if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) {
2402 + start = (ulong) &BCMINIT(_enable_pfc);
2403 + end = (ulong) &BCMINIT(enable_pfc);
2405 + /* Preload handler into the cache one line at a time */
2406 + for (i = 0; i < (end - start); i += 4)
2407 + cache_op(start + i, Fill_I);
2409 + BCMINIT(_enable_pfc)(mode);
2413 +/* returns the ncdl value to be programmed into sdram_ncdl for calibration */
2415 +BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh)
2417 + sbmemcregs_t *memc;
2419 + uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
2422 + idx = sb_coreidx(sbh);
2424 + memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
2428 + rev = sb_corerev(sbh);
2430 + config = R_REG(&memc->config);
2431 + wr = R_REG(&memc->wrncdlcor);
2432 + rd = R_REG(&memc->rdncdlcor);
2433 + misc = R_REG(&memc->miscdlyctl);
2434 + dqsg = R_REG(&memc->dqsgatencdl);
2436 + rd &= MEMC_RDNCDLCOR_RD_MASK;
2437 + wr &= MEMC_WRNCDLCOR_WR_MASK;
2438 + dqsg &= MEMC_DQSGATENCDL_G_MASK;
2440 + if (config & MEMC_CONFIG_DDR) {
2441 + ret = (wr << 16) | (rd << 8) | dqsg;
2446 + cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
2447 + sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
2448 + sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
2449 + ret = (sm << 16) | (sd << 8) | cd;
2453 + /* switch back to previous core */
2454 + sb_setcoreidx(sbh, idx);
2459 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbpci.c linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c
2460 --- linux.old/arch/mips/bcm947xx/broadcom/sbpci.c 1970-01-01 01:00:00.000000000 +0100
2461 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c 2005-12-18 05:36:53.351735500 +0100
2464 + * Low-Level PCI and SB support for BCM47xx
2466 + * Copyright 2005, Broadcom Corporation
2467 + * All Rights Reserved.
2469 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
2470 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
2471 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
2472 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
2477 +#include <typedefs.h>
2478 +#include <pcicfg.h>
2479 +#include <bcmdevs.h>
2480 +#include <sbconfig.h>
2482 +#include <sbutils.h>
2484 +#include <bcmendian.h>
2485 +#include <bcmutils.h>
2486 +#include <bcmnvram.h>
2487 +#include <hndmips.h>
2489 +/* Can free sbpci_init() memory after boot */
2494 +/* Emulated configuration space */
2495 +static pci_config_regs sb_config_regs[SB_MAXCORES];
2498 +static uint16 pci_ban[32] = { 0 };
2499 +static uint pci_banned = 0;
2502 +static bool cardbus = FALSE;
2504 +/* Disable PCI host core */
2505 +static bool pci_disabled = FALSE;
2508 + * Functions for accessing external PCI configuration space
2511 +/* Assume one-hot slot wiring */
2512 +#define PCI_SLOT_MAX 16
2515 +config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off)
2518 + sbpciregs_t *regs;
2521 + /* CardBusMode supports only one device */
2522 + if (cardbus && dev > 1)
2525 + coreidx = sb_coreidx(sbh);
2526 + regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
2528 + /* Type 0 transaction */
2530 + /* Skip unwired slots */
2531 + if (dev < PCI_SLOT_MAX) {
2532 + /* Slide the PCI window to the appropriate slot */
2533 + W_REG(®s->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK));
2534 + addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) |
2535 + (func << 8) | (off & ~3);
2539 + /* Type 1 transaction */
2541 + W_REG(®s->sbtopci1, SBTOPCI_CFG1);
2542 + addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3);
2545 + sb_setcoreidx(sbh, coreidx);
2551 +extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2553 + uint32 addr, *reg = NULL, val;
2556 + if (pci_disabled ||
2557 + !(addr = config_cmd(sbh, bus, dev, func, off)) ||
2558 + !(reg = (uint32 *) REG_MAP(addr, len)) ||
2559 + BUSPROBE(val, reg))
2562 + val >>= 8 * (off & 3);
2564 + *((uint32 *) buf) = val;
2565 + else if (len == 2)
2566 + *((uint16 *) buf) = (uint16) val;
2567 + else if (len == 1)
2568 + *((uint8 *) buf) = (uint8) val;
2579 +extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2581 + uint32 addr, *reg = NULL, val;
2584 + if (pci_disabled ||
2585 + !(addr = config_cmd(sbh, bus, dev, func, off)) ||
2586 + !(reg = (uint32 *) REG_MAP(addr, len)) ||
2587 + BUSPROBE(val, reg))
2591 + val = *((uint32 *) buf);
2592 + else if (len == 2) {
2593 + val &= ~(0xffff << (8 * (off & 3)));
2594 + val |= *((uint16 *) buf) << (8 * (off & 3));
2595 + } else if (len == 1) {
2596 + val &= ~(0xff << (8 * (off & 3)));
2597 + val |= *((uint8 *) buf) << (8 * (off & 3));
2611 + * Functions for accessing translated SB configuration space
2615 +sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2617 + pci_config_regs *cfg;
2619 + if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
2621 + cfg = &sb_config_regs[dev];
2623 + ASSERT(ISALIGNED(off, len));
2624 + ASSERT(ISALIGNED((uintptr)buf, len));
2627 + *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
2628 + else if (len == 2)
2629 + *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
2630 + else if (len == 1)
2631 + *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off));
2639 +sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2644 + pci_config_regs *cfg;
2646 + if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
2648 + cfg = &sb_config_regs[dev];
2650 + ASSERT(ISALIGNED(off, len));
2651 + ASSERT(ISALIGNED((uintptr)buf, len));
2653 + /* Emulate BAR sizing */
2654 + if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) &&
2655 + len == 4 && *((uint32 *) buf) == ~0) {
2656 + coreidx = sb_coreidx(sbh);
2657 + if ((regs = sb_setcoreidx(sbh, dev))) {
2658 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2659 + /* Highest numbered address match register */
2660 + n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
2661 + if (off == OFFSETOF(pci_config_regs, base[0]))
2662 + cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
2664 + else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
2665 + cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
2666 + else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
2667 + cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
2668 + else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
2669 + cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
2672 + sb_setcoreidx(sbh, coreidx);
2677 + *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf));
2678 + else if (len == 2)
2679 + *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf));
2680 + else if (len == 1)
2681 + *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf);
2689 +sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2692 + return sb_read_config(sbh, bus, dev, func, off, buf, len);
2694 + return extpci_read_config(sbh, bus, dev, func, off, buf, len);
2698 +sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2701 + return sb_write_config(sbh, bus, dev, func, off, buf, len);
2703 + return extpci_write_config(sbh, bus, dev, func, off, buf, len);
2707 +sbpci_ban(uint16 core)
2709 + if (pci_banned < ARRAYSIZE(pci_ban))
2710 + pci_ban[pci_banned++] = core;
2714 +sbpci_init_pci(sb_t *sbh)
2716 + uint chip, chiprev, chippkg, host;
2717 + uint32 boardflags;
2722 + chip = sb_chip(sbh);
2723 + chiprev = sb_chiprev(sbh);
2724 + chippkg = sb_chippkg(sbh);
2726 + if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) {
2727 + printf("PCI: no core\n");
2728 + pci_disabled = TRUE;
2731 + sb_core_reset(sbh, 0);
2733 + boardflags = (uint32) getintvar(NULL, "boardflags");
2735 + if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0))
2736 + pci_disabled = TRUE;
2739 + * The 200-pin BCM4712 package does not bond out PCI. Even when
2740 + * PCI is bonded out, some boards may leave the pins
2743 + if (((chip == BCM4712_DEVICE_ID) &&
2744 + ((chippkg == BCM4712SMALL_PKG_ID) ||
2745 + (chippkg == BCM4712MID_PKG_ID))) ||
2746 + (boardflags & BFL_NOPCI))
2747 + pci_disabled = TRUE;
2750 + * If the PCI core should not be touched (disabled, not bonded
2751 + * out, or pins floating), do not even attempt to access core
2752 + * registers. Otherwise, try to determine if it is in host
2758 + host = !BUSPROBE(val, &pci->control);
2761 + /* Disable PCI interrupts in client mode */
2762 + sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
2763 + W_REG(&sb->sbintvec, 0);
2765 + /* Disable the PCI bridge in client mode */
2766 + sbpci_ban(SB_PCI);
2767 + printf("PCI: Disabled\n");
2769 + /* Reset the external PCI bus and enable the clock */
2770 + W_REG(&pci->control, 0x5); /* enable the tristate drivers */
2771 + W_REG(&pci->control, 0xd); /* enable the PCI clock */
2772 + OSL_DELAY(150); /* delay > 100 us */
2773 + W_REG(&pci->control, 0xf); /* deassert PCI reset */
2774 + W_REG(&pci->arbcontrol, PCI_INT_ARB); /* use internal arbiter */
2775 + OSL_DELAY(1); /* delay 1 us */
2777 + /* Enable CardBusMode */
2778 + cardbus = nvram_match("cardbus", "1");
2780 + printf("PCI: Enabling CardBus\n");
2781 + /* GPIO 1 resets the CardBus device on bcm94710ap */
2782 + sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY);
2783 + sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY);
2784 + W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400);
2787 + /* 64 MB I/O access window */
2788 + W_REG(&pci->sbtopci0, SBTOPCI_IO);
2789 + /* 64 MB configuration access window */
2790 + W_REG(&pci->sbtopci1, SBTOPCI_CFG0);
2791 + /* 1 GB memory access window */
2792 + W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
2794 + /* Enable PCI bridge BAR0 prefetch and burst */
2796 + sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val));
2798 + /* Enable PCI interrupts */
2799 + W_REG(&pci->intmask, PCI_INTA);
2806 +sbpci_init_cores(sb_t *sbh)
2808 + uint chip, chiprev, chippkg, coreidx, i;
2810 + pci_config_regs *cfg;
2814 + uint16 vendor, core;
2815 + uint8 class, subclass, progif;
2817 + uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK };
2818 + uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT };
2820 + chip = sb_chip(sbh);
2821 + chiprev = sb_chiprev(sbh);
2822 + chippkg = sb_chippkg(sbh);
2823 + coreidx = sb_coreidx(sbh);
2825 + /* Scan the SB bus */
2826 + bzero(sb_config_regs, sizeof(sb_config_regs));
2827 + for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) {
2828 + cfg->vendor = 0xffff;
2829 + if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs)))
2831 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2833 + /* Read ID register and parse vendor and core */
2834 + val = R_REG(&sb->sbidhigh);
2835 + vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT;
2836 + core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
2839 + /* Check if this core is banned */
2840 + for (i = 0; i < pci_banned; i++)
2841 + if (core == pci_ban[i])
2843 + if (i < pci_banned)
2846 + /* Known vendor translations */
2849 + vendor = VENDOR_BROADCOM;
2853 + /* Determine class based on known core codes */
2856 + class = PCI_CLASS_NET;
2857 + subclass = PCI_NET_ETHER;
2858 + core = BCM47XX_ILINE_ID;
2861 + class = PCI_CLASS_NET;
2862 + subclass = PCI_NET_ETHER;
2863 + core = BCM4610_ILINE_ID;
2866 + class = PCI_CLASS_NET;
2867 + subclass = PCI_NET_ETHER;
2868 + core = BCM47XX_ENET_ID;
2872 + class = PCI_CLASS_MEMORY;
2873 + subclass = PCI_MEMORY_RAM;
2877 + class = PCI_CLASS_BRIDGE;
2878 + subclass = PCI_BRIDGE_PCI;
2883 + class = PCI_CLASS_CPU;
2884 + subclass = PCI_CPU_MIPS;
2887 + class = PCI_CLASS_COMM;
2888 + subclass = PCI_COMM_MODEM;
2889 + core = BCM47XX_V90_ID;
2892 + class = PCI_CLASS_SERIAL;
2893 + subclass = PCI_SERIAL_USB;
2894 + progif = 0x10; /* OHCI */
2895 + core = BCM47XX_USB_ID;
2898 + class = PCI_CLASS_SERIAL;
2899 + subclass = PCI_SERIAL_USB;
2900 + progif = 0x10; /* OHCI */
2901 + core = BCM47XX_USBH_ID;
2904 + class = PCI_CLASS_SERIAL;
2905 + subclass = PCI_SERIAL_USB;
2906 + core = BCM47XX_USBD_ID;
2909 + class = PCI_CLASS_CRYPT;
2910 + subclass = PCI_CRYPT_NETWORK;
2911 + core = BCM47XX_IPSEC_ID;
2914 + class = PCI_CLASS_NET;
2915 + subclass = PCI_NET_OTHER;
2916 + core = BCM47XX_ROBO_ID;
2920 + class = PCI_CLASS_MEMORY;
2921 + subclass = PCI_MEMORY_FLASH;
2924 + class = PCI_CLASS_NET;
2925 + subclass = PCI_NET_OTHER;
2926 + /* Let an nvram variable override this */
2927 + sprintf(varname, "wl%did", wlidx);
2929 + if ((core = getintvar(NULL, varname)) == 0) {
2930 + if (chip == BCM4712_DEVICE_ID) {
2931 + if (chippkg == BCM4712SMALL_PKG_ID)
2932 + core = BCM4306_D11G_ID;
2934 + core = BCM4306_D11DUAL_ID;
2937 + core = BCM4310_D11B_ID;
2943 + class = subclass = progif = 0xff;
2947 + /* Supported translations */
2948 + cfg->vendor = htol16(vendor);
2949 + cfg->device = htol16(core);
2950 + cfg->rev_id = chiprev;
2951 + cfg->prog_if = progif;
2952 + cfg->sub_class = subclass;
2953 + cfg->base_class = class;
2954 + cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
2955 + cfg->base[1] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch1)));
2956 + cfg->base[2] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch2)));
2957 + cfg->base[3] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch3)));
2960 + if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
2961 + cfg->header_type = PCI_HEADER_BRIDGE;
2963 + cfg->header_type = PCI_HEADER_NORMAL;
2964 + /* Save core interrupt flag */
2965 + cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK;
2966 + /* Default to MIPS shared interrupt 0 */
2967 + cfg->int_line = 0;
2968 + /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */
2969 + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
2970 + (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
2971 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2972 + val = R_REG(&sb->sbipsflag);
2973 + for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) {
2974 + if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin)
2977 + if (cfg->int_line > 4)
2978 + cfg->int_line = 0;
2980 + /* Emulated core */
2981 + *((uint32 *) &cfg->sprom_control) = 0xffffffff;
2984 + sb_setcoreidx(sbh, coreidx);
2989 +sbpci_init(sb_t *sbh)
2991 + sbpci_init_pci(sbh);
2992 + sbpci_init_cores(sbh);
2996 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbutils.c linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c
2997 --- linux.old/arch/mips/bcm947xx/broadcom/sbutils.c 1970-01-01 01:00:00.000000000 +0100
2998 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c 2005-12-17 01:21:12.951254500 +0100
3001 + * Misc utility routines for accessing chip-specific features
3002 + * of the SiliconBackplane-based Broadcom chips.
3004 + * Copyright 2005, Broadcom Corporation
3005 + * All Rights Reserved.
3007 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
3008 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
3009 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
3010 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
3014 +#include <typedefs.h>
3016 +#include <sbutils.h>
3017 +#include <bcmutils.h>
3018 +#include <bcmdevs.h>
3019 +#include <sbconfig.h>
3020 +#include <sbchipc.h>
3022 +#include <pcicfg.h>
3023 +#include <sbextif.h>
3024 +#include <bcmsrom.h>
3027 +#define SB_ERROR(args)
3030 +typedef uint32 (*sb_intrsoff_t)(void *intr_arg);
3031 +typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg);
3032 +typedef bool (*sb_intrsenabled_t)(void *intr_arg);
3034 +/* misc sb info needed by some of the routines */
3035 +typedef struct sb_info {
3037 + struct sb_pub sb; /* back plane public state(must be first field of sb_info */
3039 + void *osh; /* osl os handle */
3040 + void *sdh; /* bcmsdh handle */
3042 + void *curmap; /* current regs va */
3043 + void *regs[SB_MAXCORES]; /* other regs va */
3045 + uint curidx; /* current core index */
3046 + uint dev_coreid; /* the core provides driver functions */
3048 + uint gpioidx; /* gpio control core index */
3049 + uint gpioid; /* gpio control coretype */
3051 + uint numcores; /* # discovered cores */
3052 + uint coreid[SB_MAXCORES]; /* id of each core */
3054 + void *intr_arg; /* interrupt callback function arg */
3055 + sb_intrsoff_t intrsoff_fn; /* function turns chip interrupts off */
3056 + sb_intrsrestore_t intrsrestore_fn; /* function restore chip interrupts */
3057 + sb_intrsenabled_t intrsenabled_fn; /* function to check if chip interrupts are enabled */
3061 +/* local prototypes */
3062 +static sb_info_t * BCMINIT(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
3063 + uint bustype, void *sdh, char **vars, int *varsz);
3064 +static void BCMINIT(sb_scan)(sb_info_t *si);
3065 +static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val);
3066 +static uint _sb_coreidx(sb_info_t *si);
3067 +static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit);
3068 +static uint BCMINIT(sb_pcidev2chip)(uint pcidev);
3069 +static uint BCMINIT(sb_chip2numcores)(uint chip);
3070 +static int sb_pci_fixcfg(sb_info_t *si);
3072 +/* delay needed between the mdio control/ mdiodata register data access */
3073 +#define PR28829_DELAY() OSL_DELAY(10)
3076 +/* global variable to indicate reservation/release of gpio's*/
3077 +static uint32 sb_gpioreservation = 0;
3079 +#define SB_INFO(sbh) (sb_info_t*)sbh
3080 +#define SET_SBREG(sbh, r, mask, val) W_SBREG((sbh), (r), ((R_SBREG((sbh), (r)) & ~(mask)) | (val)))
3081 +#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && ISALIGNED((x), SB_CORE_SIZE))
3082 +#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE))
3083 +#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
3084 +#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
3085 +#define BADIDX (SB_MAXCORES+1)
3088 +#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI))
3091 +#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
3092 +#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
3094 +#define R_SBREG(sbh, sbr) sb_read_sbreg((sbh), (sbr))
3095 +#define W_SBREG(sbh, sbr, v) sb_write_sbreg((sbh), (sbr), (v))
3096 +#define AND_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) & (v)))
3097 +#define OR_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) | (v)))
3100 + * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
3101 + * after core switching to avoid invalid register accesss inside ISR.
3103 +#define INTR_OFF(si, intr_val) \
3104 + if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
3105 + intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
3106 +#define INTR_RESTORE(si, intr_val) \
3107 + if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
3108 + (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
3110 +/* dynamic clock control defines */
3111 +#define LPOMINFREQ 25000 /* low power oscillator min */
3112 +#define LPOMAXFREQ 43000 /* low power oscillator max */
3113 +#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
3114 +#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
3115 +#define PCIMINFREQ 25000000 /* 25 MHz */
3116 +#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
3118 +#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
3119 +#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
3121 +#define MIN_DUMPBUFLEN 32 /* debug */
3123 +/* GPIO Based LED powersave defines */
3124 +#define DEFAULT_GPIO_ONTIME 10
3125 +#define DEFAULT_GPIO_OFFTIME 90
3127 +#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
3130 +sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr)
3132 + uint32 val = R_REG(sbr);
3138 +sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v)
3143 +/* Using sb_kattach depends on SB_BUS support, either implicit */
3144 +/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */
3145 +#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
3147 +/* global kernel resource */
3148 +static sb_info_t ksi;
3150 +/* generic kernel variant of sb_attach() */
3152 +BCMINITFN(sb_kattach)()
3156 + if (ksi.curmap == NULL) {
3159 + regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE);
3160 + cid = R_REG((uint32 *)regs);
3161 + if (((cid & CID_ID_MASK) == BCM4712_DEVICE_ID) &&
3162 + ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) &&
3163 + ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) {
3166 + scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl));
3168 + SB_ERROR((" initial scc = 0x%x\n", val));
3169 + val |= SCC_SS_XTAL;
3173 + if (BCMINIT(sb_doattach)(&ksi, BCM4710_DEVICE_ID, NULL, (void*)regs,
3174 + SB_BUS, NULL, NULL, NULL) == NULL) {
3179 + return (sb_t *)&ksi;
3184 +BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
3185 + uint bustype, void *sdh, char **vars, int *varsz)
3192 + ASSERT(GOODREGS(regs));
3194 + bzero((uchar*)si, sizeof (sb_info_t));
3196 + si->sb.buscoreidx = si->gpioidx = BADIDX;
3199 + si->curmap = regs;
3202 + /* check to see if we are a sb core mimic'ing a pci core */
3203 + if (bustype == PCI_BUS) {
3204 + if (OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof (uint32)) == 0xffffffff)
3207 + bustype = PCI_BUS;
3210 + si->sb.bustype = bustype;
3211 + if (si->sb.bustype != BUSTYPE(si->sb.bustype)) {
3212 + SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n",
3213 + si->sb.bustype, BUSTYPE(si->sb.bustype)));
3217 + /* kludge to enable the clock on the 4306 which lacks a slowclock */
3218 + if (BUSTYPE(si->sb.bustype) == PCI_BUS)
3219 + sb_clkctl_xtal(&si->sb, XTAL|PLL, ON);
3221 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3222 + w = OSL_PCI_READ_CONFIG(osh, PCI_BAR0_WIN, sizeof (uint32));
3223 + if (!GOODCOREADDR(w))
3224 + OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32), SB_ENUM_BASE);
3227 + /* initialize current core index value */
3228 + si->curidx = _sb_coreidx(si);
3230 + if (si->curidx == BADIDX) {
3231 + SB_ERROR(("sb_doattach: bad core index\n"));
3235 + /* get sonics backplane revision */
3236 + sb = REGS2SB(si->curmap);
3237 + si->sb.sonicsrev = (R_SBREG(si, &(sb)->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
3239 + /* keep and reuse the initial register mapping */
3240 + origidx = si->curidx;
3241 + if (BUSTYPE(si->sb.bustype) == SB_BUS)
3242 + si->regs[origidx] = regs;
3244 + /* is core-0 a chipcommon core? */
3246 + cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0);
3247 + if (sb_coreid(&si->sb) != SB_CC)
3250 + /* determine chip id and rev */
3252 + /* chip common core found! */
3253 + si->sb.chip = R_REG(&cc->chipid) & CID_ID_MASK;
3254 + si->sb.chiprev = (R_REG(&cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT;
3255 + si->sb.chippkg = (R_REG(&cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT;
3257 + /* no chip common core -- must convert device id to chip id */
3258 + if ((si->sb.chip = BCMINIT(sb_pcidev2chip)(devid)) == 0) {
3259 + SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid));
3260 + sb_setcoreidx(&si->sb, origidx);
3265 + /* get chipcommon rev */
3266 + si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV;
3268 + /* determine numcores */
3269 + if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6)))
3270 + si->numcores = (R_REG(&cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT;
3272 + si->numcores = BCMINIT(sb_chip2numcores)(si->sb.chip);
3274 + /* return to original core */
3275 + sb_setcoreidx(&si->sb, origidx);
3277 + /* sanity checks */
3278 + ASSERT(si->sb.chip);
3280 + /* scan for cores */
3281 + BCMINIT(sb_scan)(si);
3283 + /* fixup necessary chip/core configurations */
3284 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3285 + if (sb_pci_fixcfg(si)) {
3286 + SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n"));
3291 + /* srom_var_init() depends on sb_scan() info */
3292 + if (srom_var_init(si, si->sb.bustype, si->curmap, osh, vars, varsz)) {
3293 + SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n"));
3299 + * The chip revision number is hardwired into all
3300 + * of the pci function config rev fields and is
3301 + * independent from the individual core revision numbers.
3302 + * For example, the "A0" silicon of each chip is chip rev 0.
3304 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3305 + w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_REV, sizeof (uint32));
3306 + si->sb.chiprev = w & 0xff;
3308 + si->sb.chiprev = 0;
3311 + /* gpio control core is required */
3312 + if (!GOODIDX(si->gpioidx)) {
3313 + SB_ERROR(("sb_doattach: gpio control core not found\n"));
3317 + /* get boardtype and boardrev */
3318 + switch (BUSTYPE(si->sb.bustype)) {
3320 + /* do a pci config read to get subsystem id and subvendor id */
3321 + w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_SVID, sizeof (uint32));
3322 + si->sb.boardvendor = w & 0xffff;
3323 + si->sb.boardtype = (w >> 16) & 0xffff;
3328 + si->sb.boardvendor = VENDOR_BROADCOM;
3329 + if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0)
3330 + si->sb.boardtype = 0xffff;
3334 + if (si->sb.boardtype == 0) {
3335 + SB_ERROR(("sb_doattach: unknown board type\n"));
3336 + ASSERT(si->sb.boardtype);
3339 + /* setup the GPIO based LED powersave register */
3340 + if (si->sb.ccrev >= 16) {
3341 + w = getintvar(*vars, "gpiotimerval");
3343 + w = DEFAULT_GPIOTIMERVAL;
3344 + sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
3352 +sb_coreid(sb_t *sbh)
3357 + si = SB_INFO(sbh);
3358 + sb = REGS2SB(si->curmap);
3360 + return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
3364 +sb_coreidx(sb_t *sbh)
3368 + si = SB_INFO(sbh);
3369 + return (si->curidx);
3372 +/* return current index of core */
3374 +_sb_coreidx(sb_info_t *si)
3377 + uint32 sbaddr = 0;
3381 + switch (BUSTYPE(si->sb.bustype)) {
3383 + sb = REGS2SB(si->curmap);
3384 + sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0));
3388 + sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32));
3393 + sbaddr = (uint32)si->curmap;
3395 +#endif /* BCMJTAG */
3401 + if (!GOODCOREADDR(sbaddr))
3404 + return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE);
3408 +sb_corevendor(sb_t *sbh)
3413 + si = SB_INFO(sbh);
3414 + sb = REGS2SB(si->curmap);
3416 + return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
3420 +sb_corerev(sb_t *sbh)