1 diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig
2 --- linux.old/arch/mips/Kconfig 2006-01-12 00:25:32.203973000 +0100
3 +++ linux.dev/arch/mips/Kconfig 2006-01-12 00:20:30.697130000 +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 2006-01-12 00:25:32.223974250 +0100
24 +++ linux.dev/arch/mips/Makefile 2006-01-12 00:20:30.701130250 +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 2006-01-12 00:20:30.701130250 +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 2006-01-12 00:20:30.713131000 +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 2006-01-12 00:20:30.717131250 +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 2006-01-12 00:20:30.717131250 +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 2006-01-12 00:20:30.717131250 +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 2006-01-12 00:20:30.717131250 +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 2006-01-12 00:20:30.717131250 +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 early_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)
1418 +char *nvram_get(const char *name)
1420 + char *var, *value, *end, *eq;
1425 + if (!nvram_buf[0])
1428 + /* Look for name=value and return value */
1429 + var = &nvram_buf[sizeof(struct nvram_header)];
1430 + end = nvram_buf + sizeof(nvram_buf) - 2;
1431 + end[0] = end[1] = '\0';
1432 + for (; *var; var = value + strlen(value) + 1) {
1433 + if (!(eq = strchr(var, '=')))
1436 + if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
1443 +EXPORT_SYMBOL(nvram_get);
1444 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbmips.c linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c
1445 --- linux.old/arch/mips/bcm947xx/broadcom/sbmips.c 1970-01-01 01:00:00.000000000 +0100
1446 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c 2006-01-12 00:27:27.399172250 +0100
1449 + * BCM47XX Sonics SiliconBackplane MIPS core routines
1451 + * Copyright 2005, Broadcom Corporation
1452 + * All Rights Reserved.
1454 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1455 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1456 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1457 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1462 +#include <typedefs.h>
1464 +#include <sbutils.h>
1465 +#include <bcmdevs.h>
1466 +#include <bcmnvram.h>
1467 +#include <bcmutils.h>
1468 +#include <hndmips.h>
1469 +#include <sbconfig.h>
1470 +#include <sbextif.h>
1471 +#include <sbchipc.h>
1472 +#include <sbmemc.h>
1473 +#include <mipsinc.h>
1474 +#include <sbutils.h>
1477 + * Returns TRUE if an external UART exists at the given base
1481 +BCMINITFN(serial_exists)(uint8 *regs)
1483 + uint8 save_mcr, status1;
1485 + save_mcr = R_REG(®s[UART_MCR]);
1486 + W_REG(®s[UART_MCR], UART_MCR_LOOP | 0x0a);
1487 + status1 = R_REG(®s[UART_MSR]) & 0xf0;
1488 + W_REG(®s[UART_MCR], save_mcr);
1490 + return (status1 == 0x90);
1494 + * Initializes UART access. The callback function will be called once
1498 +BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift))
1505 + if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
1506 + extifregs_t *eir = (extifregs_t *) regs;
1509 + /* Determine external UART register base */
1510 + sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
1511 + base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
1513 + /* Determine IRQ */
1514 + irq = sb_irq(sbh);
1516 + /* Disable GPIO interrupt initially */
1517 + W_REG(&eir->gpiointpolarity, 0);
1518 + W_REG(&eir->gpiointmask, 0);
1520 + /* Search for external UARTs */
1522 + for (i = 0; i < 2; i++) {
1523 + regs = (void *) REG_MAP(base + (i * 8), 8);
1524 + if (BCMINIT(serial_exists)(regs)) {
1525 + /* Set GPIO 1 to be the external UART IRQ */
1526 + W_REG(&eir->gpiointmask, 2);
1528 + add(regs, irq, 13500000, 0);
1532 + /* Add internal UART if enabled */
1533 + if (R_REG(&eir->corecontrol) & CC_UE)
1535 + add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
1536 + } else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
1537 + chipcregs_t *cc = (chipcregs_t *) regs;
1538 + uint32 rev, cap, pll, baud_base, div;
1540 + /* Determine core revision and capabilities */
1541 + rev = sb_corerev(sbh);
1542 + cap = R_REG(&cc->capabilities);
1543 + pll = cap & CAP_PLL_MASK;
1545 + /* Determine IRQ */
1546 + irq = sb_irq(sbh);
1548 + if (pll == PLL_TYPE1) {
1550 + baud_base = sb_clock_rate(pll,
1551 + R_REG(&cc->clockcontrol_n),
1552 + R_REG(&cc->clockcontrol_m2));
1556 + /* Fixed ALP clock */
1557 + baud_base = 20000000;
1559 + /* Set the override bit so we don't divide it */
1560 + W_REG(&cc->corecontrol, CC_UARTCLKO);
1561 + } else if (rev >= 3) {
1562 + /* Internal backplane clock */
1563 + baud_base = sb_clock(sbh);
1564 + div = 2; /* Minimum divisor */
1565 + W_REG(&cc->clkdiv,
1566 + ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div));
1568 + /* Fixed internal backplane clock */
1569 + baud_base = 88000000;
1573 + /* Clock source depends on strapping if UartClkOverride is unset */
1575 + ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) {
1576 + if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
1577 + /* Internal divided backplane clock */
1580 + /* Assume external clock of 1.8432 MHz */
1581 + baud_base = 1843200;
1586 + /* Add internal UARTs */
1587 + n = cap & CAP_UARTS_MASK;
1588 + for (i = 0; i < n; i++) {
1589 + /* Register offset changed after revision 0 */
1591 + regs = (void *)((ulong) &cc->uart0data + (i * 256));
1593 + regs = (void *)((ulong) &cc->uart0data + (i * 8));
1596 + add(regs, irq, baud_base, 0);
1602 + * Initialize jtag master and return handle for
1603 + * jtag_rwreg. Returns NULL on failure.
1606 +sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap)
1610 + if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) {
1611 + chipcregs_t *cc = (chipcregs_t *) regs;
1615 + * Determine jtagm availability from
1616 + * core revision and capabilities.
1618 + tmp = sb_corerev(sbh);
1620 + * Corerev 10 has jtagm, but the only chip
1621 + * with it does not have a mips, and
1622 + * the layout of the jtagcmd register is
1623 + * different. We'll only accept >= 11.
1628 + tmp = R_REG(&cc->capabilities);
1629 + if ((tmp & CAP_JTAGP) == 0)
1632 + /* Set clock divider if requested */
1634 + tmp = R_REG(&cc->clkdiv);
1635 + tmp = (tmp & ~CLKD_JTAG) |
1636 + ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG);
1637 + W_REG(&cc->clkdiv, tmp);
1640 + /* Enable jtagm */
1641 + tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
1642 + W_REG(&cc->jtagctrl, tmp);
1649 +sb_jtagm_disable(void *h)
1651 + chipcregs_t *cc = (chipcregs_t *)h;
1653 + W_REG(&cc->jtagctrl, R_REG(&cc->jtagctrl) & ~JCTRL_EN);
1657 + * Read/write a jtag register. Assumes a target with
1658 + * 8 bit IR and 32 bit DR.
1663 +jtag_rwreg(void *h, uint32 ir, uint32 dr)
1665 + chipcregs_t *cc = (chipcregs_t *) h;
1668 + W_REG(&cc->jtagir, ir);
1669 + W_REG(&cc->jtagdr, dr);
1670 + tmp = JCMD_START | JCMD_ACC_IRDR |
1671 + ((IRWIDTH - 1) << JCMD_IRW_SHIFT) |
1673 + W_REG(&cc->jtagcmd, tmp);
1674 + while (((tmp = R_REG(&cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) {
1675 + /* OSL_DELAY(1); */
1678 + tmp = R_REG(&cc->jtagdr);
1682 +/* Returns the SB interrupt flag of the current core. */
1689 + regs = sb_coreregs(sbh);
1690 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1692 + return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
1695 +static const uint32 sbips_int_mask[] = {
1703 +static const uint32 sbips_int_shift[] = {
1712 + * Returns the MIPS IRQ assignment of the current core. If unassigned,
1721 + uint32 flag, sbipsflag;
1724 + flag = sb_flag(sbh);
1726 + idx = sb_coreidx(sbh);
1728 + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
1729 + (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
1730 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1732 + /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
1733 + sbipsflag = R_REG(&sb->sbipsflag);
1734 + for (irq = 1; irq <= 4; irq++) {
1735 + if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag)
1742 + sb_setcoreidx(sbh, idx);
1747 +/* Clears the specified MIPS IRQ. */
1749 +BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq)
1754 + if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
1755 + !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
1757 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1760 + W_REG(&sb->sbintvec, 0);
1762 + OR_REG(&sb->sbipsflag, sbips_int_mask[irq]);
1766 + * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
1767 + * IRQ 0 may be assigned more than once.
1770 +BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit)
1776 + regs = sb_setcore(sbh, coreid, coreunit);
1778 + flag = sb_flag(sbh);
1780 + if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
1781 + !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
1783 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1786 + OR_REG(&sb->sbintvec, 1 << flag);
1788 + flag <<= sbips_int_shift[irq];
1789 + ASSERT(!(flag & ~sbips_int_mask[irq]));
1790 + flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq];
1791 + W_REG(&sb->sbipsflag, flag);
1796 + * Initializes clocks and interrupts. SB and NVRAM access must be
1797 + * initialized prior to calling.
1800 +BCMINITFN(sb_mips_init)(sb_t *sbh)
1802 + ulong hz, ns, tmp;
1808 + /* Figure out current SB clock speed */
1809 + if ((hz = sb_clock(sbh)) == 0)
1811 + ns = 1000000000 / hz;
1813 + /* Setup external interface timing */
1814 + if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
1815 + /* Initialize extif so we can get to the LEDs and external UART */
1816 + W_REG(&eir->prog_config, CF_EN);
1818 + /* Set timing for the flash */
1819 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1820 + tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
1821 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1822 + W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1824 + /* Set programmable interface timing for external uart */
1825 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1826 + tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
1827 + tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
1828 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1829 + W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1830 + } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
1831 + /* set register for external IO to control LED. */
1832 + W_REG(&cc->prog_config, 0x11);
1833 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1834 + tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
1835 + tmp = tmp | CEIL(240, ns); /* W0 = 120nS */
1836 + W_REG(&cc->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1838 + /* Set timing for the flash */
1839 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1840 + tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
1841 + tmp |= CEIL(120, ns); /* W0 = 120nS */
1843 + // Added by Chen-I for 5365
1844 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
1846 + W_REG(&cc->flash_waitcount, tmp);
1847 + W_REG(&cc->pcmcia_memwait, tmp);
1851 + if (sb_corerev(sbh) < 9)
1852 + W_REG(&cc->flash_waitcount, tmp);
1854 + if ((sb_corerev(sbh) < 9) ||
1855 + ((BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID) && BCMINIT(sb_chiprev)(sbh) == 0)) {
1856 + W_REG(&cc->pcmcia_memwait, tmp);
1859 + // Added by Chen-I & Yen for enabling 5350 EXTIF
1860 + if (BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID)
1862 + /* Set programmable interface timing for external uart */
1863 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1864 + tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
1865 + tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
1866 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1867 + W_REG(&cc->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1871 + /* Chip specific initialization */
1872 + switch (BCMINIT(sb_chip)(sbh)) {
1873 + case BCM4710_DEVICE_ID:
1874 + /* Clear interrupt map */
1875 + for (irq = 0; irq <= 4; irq++)
1876 + BCMINIT(sb_clearirq)(sbh, irq);
1877 + BCMINIT(sb_setirq)(sbh, 0, SB_CODEC, 0);
1878 + BCMINIT(sb_setirq)(sbh, 0, SB_EXTIF, 0);
1879 + BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 1);
1880 + BCMINIT(sb_setirq)(sbh, 3, SB_ILINE20, 0);
1881 + BCMINIT(sb_setirq)(sbh, 4, SB_PCI, 0);
1883 + value = BCMINIT(early_nvram_get)("et0phyaddr");
1884 + if (value && !strcmp(value, "31")) {
1885 + /* Enable internal UART */
1886 + W_REG(&eir->corecontrol, CC_UE);
1887 + /* Give USB its own interrupt */
1888 + BCMINIT(sb_setirq)(sbh, 1, SB_USB, 0);
1890 + /* Disable internal UART */
1891 + W_REG(&eir->corecontrol, 0);
1892 + /* Give Ethernet its own interrupt */
1893 + BCMINIT(sb_setirq)(sbh, 1, SB_ENET, 0);
1894 + BCMINIT(sb_setirq)(sbh, 0, SB_USB, 0);
1897 + case BCM5350_DEVICE_ID:
1898 + /* Clear interrupt map */
1899 + for (irq = 0; irq <= 4; irq++)
1900 + BCMINIT(sb_clearirq)(sbh, irq);
1901 + BCMINIT(sb_setirq)(sbh, 0, SB_CC, 0);
1902 + BCMINIT(sb_setirq)(sbh, 1, SB_D11, 0);
1903 + BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 0);
1904 + BCMINIT(sb_setirq)(sbh, 3, SB_PCI, 0);
1905 + BCMINIT(sb_setirq)(sbh, 4, SB_USB, 0);
1911 +BCMINITFN(sb_mips_clock)(sb_t *sbh)
1917 + uint32 pll_type, rate = 0;
1919 + /* get index of the current core */
1920 + idx = sb_coreidx(sbh);
1921 + pll_type = PLL_TYPE1;
1923 + /* switch to extif or chipc core */
1924 + if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
1925 + n = R_REG(&eir->clockcontrol_n);
1926 + m = R_REG(&eir->clockcontrol_sb);
1927 + } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
1928 + pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
1929 + n = R_REG(&cc->clockcontrol_n);
1930 + if ((pll_type == PLL_TYPE2) ||
1931 + (pll_type == PLL_TYPE4) ||
1932 + (pll_type == PLL_TYPE6) ||
1933 + (pll_type == PLL_TYPE7))
1934 + m = R_REG(&cc->clockcontrol_mips);
1935 + else if (pll_type == PLL_TYPE5) {
1939 + else if (pll_type == PLL_TYPE3) {
1940 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) { /* 5365 is also type3 */
1944 + m = R_REG(&cc->clockcontrol_m2); /* 5350 uses m2 to control mips */
1946 + m = R_REG(&cc->clockcontrol_sb);
1950 + // Added by Chen-I for 5365
1951 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
1954 + /* calculate rate */
1955 + rate = sb_clock_rate(pll_type, n, m);
1957 + if (pll_type == PLL_TYPE6)
1958 + rate = SB2MIPS_T6(rate);
1961 + /* switch back to previous core */
1962 + sb_setcoreidx(sbh, idx);
1967 +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
1970 +BCMINITFN(handler)(void)
1974 + ".set\tmips32\n\t"
1977 + /* Disable interrupts */
1978 + /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
1979 + "mfc0 $15, $12\n\t"
1980 + /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
1981 + "li $14, -31746\n\t"
1982 + "and $15, $15, $14\n\t"
1983 + "mtc0 $15, $12\n\t"
1991 +/* The following MUST come right after handler() */
1993 +BCMINITFN(afterhandler)(void)
1998 + * Set the MIPS, backplane and PCI clocks as closely as possible.
2001 +BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock)
2003 + extifregs_t *eir = NULL;
2004 + chipcregs_t *cc = NULL;
2005 + mipsregs_t *mipsr = NULL;
2006 + volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2;
2007 + uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg;
2008 + uint32 pll_type, sync_mode;
2009 + uint ic_size, ic_lsize;
2018 + static n3m_table_t BCMINITDATA(type1_table)[] = {
2019 + { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /* 96.000 32.000 24.000 */
2020 + { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */
2021 + { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */
2022 + { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */
2023 + { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */
2024 + { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */
2025 + { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */
2026 + { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */
2027 + { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */
2028 + { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */
2029 + { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */
2030 + { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */
2031 + { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */
2032 + { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */
2033 + { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */
2034 + { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */
2035 + { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */
2036 + { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */
2037 + { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */
2038 + { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */
2043 + uint32 m2; /* that is the clockcontrol_m2 */
2045 + static type3_table_t type3_table[] = { /* for 5350, mips clock is always double sb clock */
2046 + { 150000000, 0x311, 0x4020005 },
2047 + { 200000000, 0x311, 0x4020003 },
2058 + uint32 ratio_parm;
2061 + static n4m_table_t BCMINITDATA(type2_table)[] = {
2062 + { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2063 + { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
2064 + { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555 },
2065 + { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2066 + { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2067 + { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2068 + { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2069 + { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2070 + { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
2071 + { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2072 + { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2073 + { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2074 + { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
2075 + { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2076 + { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
2077 + { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2078 + { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 11, 0x0aaa0555 }
2081 + static n4m_table_t BCMINITDATA(type4_table)[] = {
2082 + { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2083 + { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2084 + { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
2085 + { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2086 + { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2087 + { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2088 + { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2089 + { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2090 + { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, 0x012a00a9 },
2091 + { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2092 + { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, 0x254a14a9 },
2093 + { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2094 + { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, 0x02520129 },
2095 + { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
2096 + { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
2097 + { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2098 + { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2099 + { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2100 + { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, 0x02520129 },
2101 + { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, 0x0aaa0555 }
2104 + static n4m_table_t BCMINITDATA(type7_table)[] = {
2105 + { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2106 + { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2107 + { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2108 + { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, 0x0aaa0555 },
2109 + { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
2110 + { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2111 + { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2112 + { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2113 + { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2114 + { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2115 + { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2116 + { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2117 + { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, 0x0aaa0555 },
2118 + { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, 0x0aaa0555 }
2121 + ulong start, end, dst;
2124 + /* get index of the current core */
2125 + idx = sb_coreidx(sbh);
2126 + clockcontrol_m2 = NULL;
2128 + /* switch to extif or chipc core */
2129 + if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
2130 + pll_type = PLL_TYPE1;
2131 + clockcontrol_n = &eir->clockcontrol_n;
2132 + clockcontrol_sb = &eir->clockcontrol_sb;
2133 + clockcontrol_pci = &eir->clockcontrol_pci;
2134 + clockcontrol_m2 = &cc->clockcontrol_m2;
2135 + } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
2136 + pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
2137 + if (pll_type == PLL_TYPE6) {
2138 + clockcontrol_n = NULL;
2139 + clockcontrol_sb = NULL;
2140 + clockcontrol_pci = NULL;
2142 + clockcontrol_n = &cc->clockcontrol_n;
2143 + clockcontrol_sb = &cc->clockcontrol_sb;
2144 + clockcontrol_pci = &cc->clockcontrol_pci;
2145 + clockcontrol_m2 = &cc->clockcontrol_m2;
2150 + if (pll_type == PLL_TYPE6) {
2151 + /* Silence compilers */
2152 + orig_n = orig_sb = orig_pci = 0;
2154 + /* Store the current clock register values */
2155 + orig_n = R_REG(clockcontrol_n);
2156 + orig_sb = R_REG(clockcontrol_sb);
2157 + orig_pci = R_REG(clockcontrol_pci);
2160 + if (pll_type == PLL_TYPE1) {
2161 + /* Keep the current PCI clock if not specified */
2162 + if (pciclock == 0) {
2163 + pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci));
2164 + pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
2167 + /* Search for the closest MIPS clock less than or equal to a preferred value */
2168 + for (i = 0; i < ARRAYSIZE(BCMINIT(type1_table)); i++) {
2169 + ASSERT(BCMINIT(type1_table)[i].mipsclock ==
2170 + sb_clock_rate(pll_type, BCMINIT(type1_table)[i].n, BCMINIT(type1_table)[i].sb));
2171 + if (BCMINIT(type1_table)[i].mipsclock > mipsclock)
2181 + ASSERT(BCMINIT(type1_table)[i].mipsclock <= mipsclock);
2183 + /* No PLL change */
2184 + if ((orig_n == BCMINIT(type1_table)[i].n) &&
2185 + (orig_sb == BCMINIT(type1_table)[i].sb) &&
2186 + (orig_pci == BCMINIT(type1_table)[i].pci33))
2189 + /* Set the PLL controls */
2190 + W_REG(clockcontrol_n, BCMINIT(type1_table)[i].n);
2191 + W_REG(clockcontrol_sb, BCMINIT(type1_table)[i].sb);
2192 + if (pciclock == 25000000)
2193 + W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci25);
2195 + W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci33);
2198 + sb_watchdog(sbh, 1);
2201 + } else if ((pll_type == PLL_TYPE3) &&
2202 + (BCMINIT(sb_chip)(sbh) != BCM5365_DEVICE_ID)) {
2204 + /* Search for the closest MIPS clock less than or equal to a preferred value */
2206 + for (i = 0; i < ARRAYSIZE(type3_table); i++) {
2207 + if (type3_table[i].mipsclock > mipsclock)
2217 + ASSERT(type3_table[i].mipsclock <= mipsclock);
2219 + /* No PLL change */
2220 + orig_m2 = R_REG(&cc->clockcontrol_m2);
2221 + if ((orig_n == type3_table[i].n) &&
2222 + (orig_m2 == type3_table[i].m2)) {
2226 + /* Set the PLL controls */
2227 + W_REG(clockcontrol_n, type3_table[i].n);
2228 + W_REG(clockcontrol_m2, type3_table[i].m2);
2231 + sb_watchdog(sbh, 1);
2233 + } else if ((pll_type == PLL_TYPE2) ||
2234 + (pll_type == PLL_TYPE4) ||
2235 + (pll_type == PLL_TYPE6) ||
2236 + (pll_type == PLL_TYPE7)) {
2237 + n4m_table_t *table = NULL, *te;
2242 + orig_mips = R_REG(&cc->clockcontrol_mips);
2244 + if (pll_type == PLL_TYPE6) {
2245 + uint32 new_mips = 0;
2248 + if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
2249 + new_mips = CC_T6_MMASK;
2251 + if (orig_mips == new_mips)
2254 + W_REG(&cc->clockcontrol_mips, new_mips);
2258 + if (pll_type == PLL_TYPE2) {
2259 + table = BCMINIT(type2_table);
2260 + tabsz = ARRAYSIZE(BCMINIT(type2_table));
2261 + } else if (pll_type == PLL_TYPE4) {
2262 + table = BCMINIT(type4_table);
2263 + tabsz = ARRAYSIZE(BCMINIT(type4_table));
2264 + } else if (pll_type == PLL_TYPE7) {
2265 + table = BCMINIT(type7_table);
2266 + tabsz = ARRAYSIZE(BCMINIT(type7_table));
2268 + ASSERT("No table for plltype" == NULL);
2270 + /* Store the current clock register values */
2271 + orig_m2 = R_REG(&cc->clockcontrol_m2);
2272 + orig_ratio_parm = 0;
2273 + orig_ratio_cfg = 0;
2275 + /* Look up current ratio */
2276 + for (i = 0; i < tabsz; i++) {
2277 + if ((orig_n == table[i].n) &&
2278 + (orig_sb == table[i].sb) &&
2279 + (orig_pci == table[i].pci33) &&
2280 + (orig_m2 == table[i].m2) &&
2281 + (orig_mips == table[i].m3)) {
2282 + orig_ratio_parm = table[i].ratio_parm;
2283 + orig_ratio_cfg = table[i].ratio_cfg;
2288 + /* Search for the closest MIPS clock greater or equal to a preferred value */
2289 + for (i = 0; i < tabsz; i++) {
2290 + ASSERT(table[i].mipsclock ==
2291 + sb_clock_rate(pll_type, table[i].n, table[i].m3));
2292 + if ((mipsclock <= table[i].mipsclock) &&
2293 + ((sbclock == 0) || (sbclock <= table[i].sbclock)))
2304 + /* No PLL change */
2305 + if ((orig_n == te->n) &&
2306 + (orig_sb == te->sb) &&
2307 + (orig_pci == te->pci33) &&
2308 + (orig_m2 == te->m2) &&
2309 + (orig_mips == te->m3))
2312 + /* Set the PLL controls */
2313 + W_REG(clockcontrol_n, te->n);
2314 + W_REG(clockcontrol_sb, te->sb);
2315 + W_REG(clockcontrol_pci, te->pci33);
2316 + W_REG(&cc->clockcontrol_m2, te->m2);
2317 + W_REG(&cc->clockcontrol_mips, te->m3);
2319 + /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
2320 + if ((pll_type == PLL_TYPE7) &&
2321 + (te->sb != te->m2) &&
2322 + (sb_clock_rate(pll_type, te->n, te->m2) == 120000000))
2323 + W_REG(&cc->chipcontrol, R_REG(&cc->chipcontrol) | 0x100);
2325 + /* No ratio change */
2326 + if (orig_ratio_parm == te->ratio_parm)
2329 + icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
2331 + /* Preload the code into the cache */
2332 + start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
2333 + end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
2334 + while (start < end) {
2335 + cache_op(start, Fill_I);
2336 + start += ic_lsize;
2339 + /* Copy the handler */
2340 + start = (ulong) &BCMINIT(handler);
2341 + end = (ulong) &BCMINIT(afterhandler);
2342 + dst = KSEG1ADDR(0x180);
2343 + for (i = 0; i < (end - start); i += 4)
2344 + *((ulong *)(dst + i)) = *((ulong *)(start + i));
2346 + /* Preload handler into the cache one line at a time */
2347 + for (i = 0; i < (end - start); i += 4)
2348 + cache_op(dst + i, Fill_I);
2350 + /* Clear BEV bit */
2351 + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
2353 + /* Enable interrupts */
2354 + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
2356 + /* Enable MIPS timer interrupt */
2357 + if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
2358 + !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
2360 + W_REG(&mipsr->intmask, 1);
2363 + /* step 1, set clock ratios */
2364 + MTC0(C0_BROADCOM, 3, te->ratio_parm);
2365 + MTC0(C0_BROADCOM, 1, te->ratio_cfg);
2367 + /* step 2: program timer intr */
2368 + W_REG(&mipsr->timer, 100);
2369 + (void) R_REG(&mipsr->timer);
2371 + /* step 3, switch to async */
2372 + sync_mode = MFC0(C0_BROADCOM, 4);
2373 + MTC0(C0_BROADCOM, 4, 1 << 22);
2375 + /* step 4, set cfg active */
2376 + MTC0(C0_BROADCOM, 2, 0x9);
2380 + __asm__ __volatile__ (
2386 + /* step 7, clear cfg_active */
2387 + MTC0(C0_BROADCOM, 2, 0);
2389 + /* Additional Step: set back to orig sync mode */
2390 + MTC0(C0_BROADCOM, 4, sync_mode);
2392 + /* step 8, fake soft reset */
2393 + MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4);
2396 + /* step 9 set watchdog timer */
2397 + sb_watchdog(sbh, 20);
2398 + (void) R_REG(&cc->chipid);
2401 + __asm__ __volatile__ (
2411 + /* switch back to previous core */
2412 + sb_setcoreidx(sbh, idx);
2418 + * This also must be run from the cache on 47xx
2419 + * so there are no mips core BIU ops in progress
2420 + * when the PFC is enabled.
2424 +BCMINITFN(_enable_pfc)(uint32 mode)
2427 + *(volatile uint32 *)PFC_CR1 = 0xffff0000;
2430 + *(volatile uint32 *)PFC_CR0 = mode;
2434 +BCMINITFN(enable_pfc)(uint32 mode)
2439 + /* If auto then choose the correct mode for this
2440 + platform, currently we only ever select one mode */
2441 + if (mode == PFC_AUTO)
2444 + /* enable prefetch cache if available */
2445 + if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) {
2446 + start = (ulong) &BCMINIT(_enable_pfc);
2447 + end = (ulong) &BCMINIT(enable_pfc);
2449 + /* Preload handler into the cache one line at a time */
2450 + for (i = 0; i < (end - start); i += 4)
2451 + cache_op(start + i, Fill_I);
2453 + BCMINIT(_enable_pfc)(mode);
2457 +/* returns the ncdl value to be programmed into sdram_ncdl for calibration */
2459 +BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh)
2461 + sbmemcregs_t *memc;
2463 + uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
2466 + idx = sb_coreidx(sbh);
2468 + memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
2472 + rev = sb_corerev(sbh);
2474 + config = R_REG(&memc->config);
2475 + wr = R_REG(&memc->wrncdlcor);
2476 + rd = R_REG(&memc->rdncdlcor);
2477 + misc = R_REG(&memc->miscdlyctl);
2478 + dqsg = R_REG(&memc->dqsgatencdl);
2480 + rd &= MEMC_RDNCDLCOR_RD_MASK;
2481 + wr &= MEMC_WRNCDLCOR_WR_MASK;
2482 + dqsg &= MEMC_DQSGATENCDL_G_MASK;
2484 + if (config & MEMC_CONFIG_DDR) {
2485 + ret = (wr << 16) | (rd << 8) | dqsg;
2490 + cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
2491 + sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
2492 + sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
2493 + ret = (sm << 16) | (sd << 8) | cd;
2497 + /* switch back to previous core */
2498 + sb_setcoreidx(sbh, idx);
2503 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbpci.c linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c
2504 --- linux.old/arch/mips/bcm947xx/broadcom/sbpci.c 1970-01-01 01:00:00.000000000 +0100
2505 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c 2006-01-12 00:52:25.864820500 +0100
2508 + * Low-Level PCI and SB support for BCM47xx
2510 + * Copyright 2005, Broadcom Corporation
2511 + * All Rights Reserved.
2513 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
2514 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
2515 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
2516 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
2521 +#include <typedefs.h>
2522 +#include <pcicfg.h>
2523 +#include <bcmdevs.h>
2524 +#include <sbconfig.h>
2526 +#include <sbutils.h>
2528 +#include <bcmendian.h>
2529 +#include <bcmutils.h>
2530 +#include <bcmnvram.h>
2531 +#include <hndmips.h>
2533 +/* Can free sbpci_init() memory after boot */
2538 +/* Emulated configuration space */
2539 +static pci_config_regs sb_config_regs[SB_MAXCORES];
2542 +static uint16 pci_ban[32] = { 0 };
2543 +static uint pci_banned = 0;
2546 +static bool cardbus = FALSE;
2548 +/* Disable PCI host core */
2549 +static bool pci_disabled = FALSE;
2552 + * Functions for accessing external PCI configuration space
2555 +/* Assume one-hot slot wiring */
2556 +#define PCI_SLOT_MAX 16
2559 +config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off)
2562 + sbpciregs_t *regs;
2565 + /* CardBusMode supports only one device */
2566 + if (cardbus && dev > 1)
2569 + coreidx = sb_coreidx(sbh);
2570 + regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
2572 + /* Type 0 transaction */
2574 + /* Skip unwired slots */
2575 + if (dev < PCI_SLOT_MAX) {
2576 + /* Slide the PCI window to the appropriate slot */
2577 + W_REG(®s->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK));
2578 + addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) |
2579 + (func << 8) | (off & ~3);
2583 + /* Type 1 transaction */
2585 + W_REG(®s->sbtopci1, SBTOPCI_CFG1);
2586 + addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3);
2589 + sb_setcoreidx(sbh, coreidx);
2595 +extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2597 + uint32 addr, *reg = NULL, val;
2600 + if (pci_disabled ||
2601 + !(addr = config_cmd(sbh, bus, dev, func, off)) ||
2602 + !(reg = (uint32 *) REG_MAP(addr, len)) ||
2603 + BUSPROBE(val, reg))
2606 + val >>= 8 * (off & 3);
2608 + *((uint32 *) buf) = val;
2609 + else if (len == 2)
2610 + *((uint16 *) buf) = (uint16) val;
2611 + else if (len == 1)
2612 + *((uint8 *) buf) = (uint8) val;
2623 +extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2625 + uint32 addr, *reg = NULL, val;
2628 + if (pci_disabled ||
2629 + !(addr = config_cmd(sbh, bus, dev, func, off)) ||
2630 + !(reg = (uint32 *) REG_MAP(addr, len)) ||
2631 + BUSPROBE(val, reg))
2635 + val = *((uint32 *) buf);
2636 + else if (len == 2) {
2637 + val &= ~(0xffff << (8 * (off & 3)));
2638 + val |= *((uint16 *) buf) << (8 * (off & 3));
2639 + } else if (len == 1) {
2640 + val &= ~(0xff << (8 * (off & 3)));
2641 + val |= *((uint8 *) buf) << (8 * (off & 3));
2655 + * Functions for accessing translated SB configuration space
2659 +sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2661 + pci_config_regs *cfg;
2663 + if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
2665 + cfg = &sb_config_regs[dev];
2667 + ASSERT(ISALIGNED(off, len));
2668 + ASSERT(ISALIGNED((uintptr)buf, len));
2671 + *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
2672 + else if (len == 2)
2673 + *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
2674 + else if (len == 1)
2675 + *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off));
2683 +sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2688 + pci_config_regs *cfg;
2690 + if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
2692 + cfg = &sb_config_regs[dev];
2694 + ASSERT(ISALIGNED(off, len));
2695 + ASSERT(ISALIGNED((uintptr)buf, len));
2697 + /* Emulate BAR sizing */
2698 + if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) &&
2699 + len == 4 && *((uint32 *) buf) == ~0) {
2700 + coreidx = sb_coreidx(sbh);
2701 + if ((regs = sb_setcoreidx(sbh, dev))) {
2702 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2703 + /* Highest numbered address match register */
2704 + n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
2705 + if (off == OFFSETOF(pci_config_regs, base[0]))
2706 + cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
2708 + else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
2709 + cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
2710 + else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
2711 + cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
2712 + else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
2713 + cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
2716 + sb_setcoreidx(sbh, coreidx);
2721 + *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf));
2722 + else if (len == 2)
2723 + *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf));
2724 + else if (len == 1)
2725 + *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf);
2733 +sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2736 + return sb_read_config(sbh, bus, dev, func, off, buf, len);
2738 + return extpci_read_config(sbh, bus, dev, func, off, buf, len);
2742 +sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2745 + return sb_write_config(sbh, bus, dev, func, off, buf, len);
2747 + return extpci_write_config(sbh, bus, dev, func, off, buf, len);
2751 +sbpci_ban(uint16 core)
2753 + if (pci_banned < ARRAYSIZE(pci_ban))
2754 + pci_ban[pci_banned++] = core;
2758 +sbpci_init_pci(sb_t *sbh)
2760 + uint chip, chiprev, chippkg, host;
2761 + uint32 boardflags;
2766 + chip = sb_chip(sbh);
2767 + chiprev = sb_chiprev(sbh);
2768 + chippkg = sb_chippkg(sbh);
2770 + if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) {
2771 + printf("PCI: no core\n");
2772 + pci_disabled = TRUE;
2775 + sb_core_reset(sbh, 0);
2777 + boardflags = (uint32) getintvar(NULL, "boardflags");
2779 + if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0))
2780 + pci_disabled = TRUE;
2783 + * The 200-pin BCM4712 package does not bond out PCI. Even when
2784 + * PCI is bonded out, some boards may leave the pins
2787 + if (((chip == BCM4712_DEVICE_ID) &&
2788 + ((chippkg == BCM4712SMALL_PKG_ID) ||
2789 + (chippkg == BCM4712MID_PKG_ID))) ||
2790 + (chip == BCM5350_DEVICE_ID) ||
2791 + (boardflags & BFL_NOPCI))
2792 + pci_disabled = TRUE;
2795 + * If the PCI core should not be touched (disabled, not bonded
2796 + * out, or pins floating), do not even attempt to access core
2797 + * registers. Otherwise, try to determine if it is in host
2803 + host = !BUSPROBE(val, &pci->control);
2806 + /* Disable PCI interrupts in client mode */
2807 + sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
2808 + W_REG(&sb->sbintvec, 0);
2810 + /* Disable the PCI bridge in client mode */
2811 + sbpci_ban(SB_PCI);
2812 + printf("PCI: Disabled\n");
2814 + /* Reset the external PCI bus and enable the clock */
2815 + W_REG(&pci->control, 0x5); /* enable the tristate drivers */
2816 + W_REG(&pci->control, 0xd); /* enable the PCI clock */
2817 + OSL_DELAY(150); /* delay > 100 us */
2818 + W_REG(&pci->control, 0xf); /* deassert PCI reset */
2819 + W_REG(&pci->arbcontrol, PCI_INT_ARB); /* use internal arbiter */
2820 + OSL_DELAY(1); /* delay 1 us */
2822 + /* Enable CardBusMode */
2823 + cardbus = nvram_match("cardbus", "1");
2825 + printf("PCI: Enabling CardBus\n");
2826 + /* GPIO 1 resets the CardBus device on bcm94710ap */
2827 + sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY);
2828 + sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY);
2829 + W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400);
2832 + /* 64 MB I/O access window */
2833 + W_REG(&pci->sbtopci0, SBTOPCI_IO);
2834 + /* 64 MB configuration access window */
2835 + W_REG(&pci->sbtopci1, SBTOPCI_CFG0);
2836 + /* 1 GB memory access window */
2837 + W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
2839 + /* Enable PCI bridge BAR0 prefetch and burst */
2841 + sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val));
2843 + /* Enable PCI interrupts */
2844 + W_REG(&pci->intmask, PCI_INTA);
2851 +sbpci_init_cores(sb_t *sbh)
2853 + uint chip, chiprev, chippkg, coreidx, i;
2855 + pci_config_regs *cfg;
2859 + uint16 vendor, core;
2860 + uint8 class, subclass, progif;
2862 + uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK };
2863 + uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT };
2865 + chip = sb_chip(sbh);
2866 + chiprev = sb_chiprev(sbh);
2867 + chippkg = sb_chippkg(sbh);
2868 + coreidx = sb_coreidx(sbh);
2870 + /* Scan the SB bus */
2871 + bzero(sb_config_regs, sizeof(sb_config_regs));
2872 + for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) {
2873 + cfg->vendor = 0xffff;
2874 + if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs)))
2876 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2878 + /* Read ID register and parse vendor and core */
2879 + val = R_REG(&sb->sbidhigh);
2880 + vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT;
2881 + core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
2884 + /* Check if this core is banned */
2885 + for (i = 0; i < pci_banned; i++)
2886 + if (core == pci_ban[i])
2888 + if (i < pci_banned)
2891 + /* Known vendor translations */
2894 + vendor = VENDOR_BROADCOM;
2898 + /* Determine class based on known core codes */
2901 + class = PCI_CLASS_NET;
2902 + subclass = PCI_NET_ETHER;
2903 + core = BCM47XX_ILINE_ID;
2906 + class = PCI_CLASS_NET;
2907 + subclass = PCI_NET_ETHER;
2908 + core = BCM4610_ILINE_ID;
2911 + class = PCI_CLASS_NET;
2912 + subclass = PCI_NET_ETHER;
2913 + core = BCM47XX_ENET_ID;
2917 + class = PCI_CLASS_MEMORY;
2918 + subclass = PCI_MEMORY_RAM;
2922 + class = PCI_CLASS_BRIDGE;
2923 + subclass = PCI_BRIDGE_PCI;
2928 + class = PCI_CLASS_CPU;
2929 + subclass = PCI_CPU_MIPS;
2932 + class = PCI_CLASS_COMM;
2933 + subclass = PCI_COMM_MODEM;
2934 + core = BCM47XX_V90_ID;
2937 + class = PCI_CLASS_SERIAL;
2938 + subclass = PCI_SERIAL_USB;
2939 + progif = 0x10; /* OHCI */
2940 + core = BCM47XX_USB_ID;
2943 + class = PCI_CLASS_SERIAL;
2944 + subclass = PCI_SERIAL_USB;
2945 + progif = 0x10; /* OHCI */
2946 + core = BCM47XX_USBH_ID;
2949 + class = PCI_CLASS_SERIAL;
2950 + subclass = PCI_SERIAL_USB;
2951 + core = BCM47XX_USBD_ID;
2954 + class = PCI_CLASS_CRYPT;
2955 + subclass = PCI_CRYPT_NETWORK;
2956 + core = BCM47XX_IPSEC_ID;
2959 + class = PCI_CLASS_NET;
2960 + subclass = PCI_NET_OTHER;
2961 + core = BCM47XX_ROBO_ID;
2965 + class = PCI_CLASS_MEMORY;
2966 + subclass = PCI_MEMORY_FLASH;
2969 + class = PCI_CLASS_NET;
2970 + subclass = PCI_NET_OTHER;
2971 + /* Let an nvram variable override this */
2972 + sprintf(varname, "wl%did", wlidx);
2974 + if ((core = getintvar(NULL, varname)) == 0) {
2975 + if (chip == BCM4712_DEVICE_ID) {
2976 + if (chippkg == BCM4712SMALL_PKG_ID)
2977 + core = BCM4306_D11G_ID;
2979 + core = BCM4306_D11DUAL_ID;
2982 + core = BCM4310_D11B_ID;
2988 + class = subclass = progif = 0xff;
2992 + /* Supported translations */
2993 + cfg->vendor = htol16(vendor);
2994 + cfg->device = htol16(core);
2995 + cfg->rev_id = chiprev;
2996 + cfg->prog_if = progif;
2997 + cfg->sub_class = subclass;
2998 + cfg->base_class = class;
2999 + cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
3000 + cfg->base[1] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch1)));
3001 + cfg->base[2] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch2)));
3002 + cfg->base[3] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch3)));
3005 + if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
3006 + cfg->header_type = PCI_HEADER_BRIDGE;
3008 + cfg->header_type = PCI_HEADER_NORMAL;
3009 + /* Save core interrupt flag */
3010 + cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK;
3011 + /* Default to MIPS shared interrupt 0 */
3012 + cfg->int_line = 0;
3013 + /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */
3014 + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
3015 + (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
3016 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
3017 + val = R_REG(&sb->sbipsflag);
3018 + for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) {
3019 + if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin)
3022 + if (cfg->int_line > 4)
3023 + cfg->int_line = 0;
3025 + /* Emulated core */
3026 + *((uint32 *) &cfg->sprom_control) = 0xffffffff;
3029 + sb_setcoreidx(sbh, coreidx);
3034 +sbpci_init(sb_t *sbh)
3036 + sbpci_init_pci(sbh);
3037 + sbpci_init_cores(sbh);
3041 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbutils.c linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c
3042 --- linux.old/arch/mips/bcm947xx/broadcom/sbutils.c 1970-01-01 01:00:00.000000000 +0100
3043 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c 2006-01-12 00:20:30.725131750 +0100
3046 + * Misc utility routines for accessing chip-specific features
3047 + * of the SiliconBackplane-based Broadcom chips.
3049 + * Copyright 2005, Broadcom Corporation
3050 + * All Rights Reserved.
3052 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
3053 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
3054 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
3055 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
3059 +#include <typedefs.h>
3061 +#include <sbutils.h>
3062 +#include <bcmutils.h>
3063 +#include <bcmdevs.h>
3064 +#include <sbconfig.h>
3065 +#include <sbchipc.h>
3067 +#include <pcicfg.h>
3068 +#include <sbextif.h>
3069 +#include <bcmsrom.h>
3072 +#define SB_ERROR(args)
3075 +typedef uint32 (*sb_intrsoff_t)(void *intr_arg);
3076 +typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg);
3077 +typedef bool (*sb_intrsenabled_t)(void *intr_arg);
3079 +/* misc sb info needed by some of the routines */
3080 +typedef struct sb_info {
3082 + struct sb_pub sb; /* back plane public state(must be first field of sb_info */
3084 + void *osh; /* osl os handle */
3085 + void *sdh; /* bcmsdh handle */
3087 + void *curmap; /* current regs va */
3088 + void *regs[SB_MAXCORES]; /* other regs va */
3090 + uint curidx; /* current core index */
3091 + uint dev_coreid; /* the core provides driver functions */
3093 + uint gpioidx; /* gpio control core index */
3094 + uint gpioid; /* gpio control coretype */
3096 + uint numcores; /* # discovered cores */
3097 + uint coreid[SB_MAXCORES]; /* id of each core */
3099 + void *intr_arg; /* interrupt callback function arg */
3100 + sb_intrsoff_t intrsoff_fn; /* function turns chip interrupts off */
3101 + sb_intrsrestore_t intrsrestore_fn; /* function restore chip interrupts */
3102 + sb_intrsenabled_t intrsenabled_fn; /* function to check if chip interrupts are enabled */
3106 +/* local prototypes */
3107 +static sb_info_t * BCMINIT(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
3108 + uint bustype, void *sdh, char **vars, int *varsz);
3109 +static void BCMINIT(sb_scan)(sb_info_t *si);
3110 +static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val);
3111 +static uint _sb_coreidx(sb_info_t *si);
3112 +static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit);
3113 +static uint BCMINIT(sb_pcidev2chip)(uint pcidev);
3114 +static uint BCMINIT(sb_chip2numcores)(uint chip);
3115 +static int sb_pci_fixcfg(sb_info_t *si);
3117 +/* delay needed between the mdio control/ mdiodata register data access */
3118 +#define PR28829_DELAY() OSL_DELAY(10)
3121 +/* global variable to indicate reservation/release of gpio's*/
3122 +static uint32 sb_gpioreservation = 0;
3124 +#define SB_INFO(sbh) (sb_info_t*)sbh
3125 +#define SET_SBREG(sbh, r, mask, val) W_SBREG((sbh), (r), ((R_SBREG((sbh), (r)) & ~(mask)) | (val)))
3126 +#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && ISALIGNED((x), SB_CORE_SIZE))
3127 +#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE))
3128 +#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
3129 +#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
3130 +#define BADIDX (SB_MAXCORES+1)
3133 +#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI))
3136 +#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
3137 +#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
3139 +#define R_SBREG(sbh, sbr) sb_read_sbreg((sbh), (sbr))
3140 +#define W_SBREG(sbh, sbr, v) sb_write_sbreg((sbh), (sbr), (v))
3141 +#define AND_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) & (v)))
3142 +#define OR_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) | (v)))
3145 + * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
3146 + * after core switching to avoid invalid register accesss inside ISR.
3148 +#define INTR_OFF(si, intr_val) \
3149 + if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
3150 + intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
3151 +#define INTR_RESTORE(si, intr_val) \
3152 + if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
3153 + (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
3155 +/* dynamic clock control defines */
3156 +#define LPOMINFREQ 25000 /* low power oscillator min */
3157 +#define LPOMAXFREQ 43000 /* low power oscillator max */
3158 +#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
3159 +#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
3160 +#define PCIMINFREQ 25000000 /* 25 MHz */
3161 +#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
3163 +#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
3164 +#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
3166 +#define MIN_DUMPBUFLEN 32 /* debug */
3168 +/* GPIO Based LED powersave defines */
3169 +#define DEFAULT_GPIO_ONTIME 10
3170 +#define DEFAULT_GPIO_OFFTIME 90
3172 +#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
3175 +sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr)
3177 + uint32 val = R_REG(sbr);
3183 +sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v)
3188 +/* Using sb_kattach depends on SB_BUS support, either implicit */
3189 +/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */
3190 +#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
3192 +/* global kernel resource */
3193 +static sb_info_t ksi;
3195 +/* generic kernel variant of sb_attach() */
3197 +BCMINITFN(sb_kattach)()
3201 + if (ksi.curmap == NULL) {
3204 + regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE);
3205 + cid = R_REG((uint32 *)regs);
3206 + if (((cid & CID_ID_MASK) == BCM4712_DEVICE_ID) &&
3207 + ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) &&
3208 + ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) {
3211 + scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl));
3213 + SB_ERROR((" initial scc = 0x%x\n", val));
3214 + val |= SCC_SS_XTAL;
3218 + if (BCMINIT(sb_doattach)(&ksi, BCM4710_DEVICE_ID, NULL, (void*)regs,
3219 + SB_BUS, NULL, NULL, NULL) == NULL) {
3224 + return (sb_t *)&ksi;
3229 +BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
3230 + uint bustype, void *sdh, char **vars, int *varsz)
3237 + ASSERT(GOODREGS(regs));
3239 + bzero((uchar*)si, sizeof (sb_info_t));
3241 + si->sb.buscoreidx = si->gpioidx = BADIDX;
3244 + si->curmap = regs;
3247 + /* check to see if we are a sb core mimic'ing a pci core */
3248 + if (bustype == PCI_BUS) {
3249 + if (OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof (uint32)) == 0xffffffff)
3252 + bustype = PCI_BUS;
3255 + si->sb.bustype = bustype;
3256 + if (si->sb.bustype != BUSTYPE(si->sb.bustype)) {
3257 + SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n",
3258 + si->sb.bustype, BUSTYPE(si->sb.bustype)));
3262 + /* kludge to enable the clock on the 4306 which lacks a slowclock */
3263 + if (BUSTYPE(si->sb.bustype) == PCI_BUS)
3264 + sb_clkctl_xtal(&si->sb, XTAL|PLL, ON);
3266 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3267 + w = OSL_PCI_READ_CONFIG(osh, PCI_BAR0_WIN, sizeof (uint32));
3268 + if (!GOODCOREADDR(w))
3269 + OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32), SB_ENUM_BASE);
3272 + /* initialize current core index value */
3273 + si->curidx = _sb_coreidx(si);
3275 + if (si->curidx == BADIDX) {
3276 + SB_ERROR(("sb_doattach: bad core index\n"));
3280 + /* get sonics backplane revision */
3281 + sb = REGS2SB(si->curmap);
3282 + si->sb.sonicsrev = (R_SBREG(si, &(sb)->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
3284 + /* keep and reuse the initial register mapping */
3285 + origidx = si->curidx;
3286 + if (BUSTYPE(si->sb.bustype) == SB_BUS)
3287 + si->regs[origidx] = regs;
3289 + /* is core-0 a chipcommon core? */
3291 + cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0);
3292 + if (sb_coreid(&si->sb) != SB_CC)
3295 + /* determine chip id and rev */
3297 + /* chip common core found! */
3298 + si->sb.chip = R_REG(&cc->chipid) & CID_ID_MASK;
3299 + si->sb.chiprev = (R_REG(&cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT;
3300 + si->sb.chippkg = (R_REG(&cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT;
3302 + /* no chip common core -- must convert device id to chip id */
3303 + if ((si->sb.chip = BCMINIT(sb_pcidev2chip)(devid)) == 0) {
3304 + SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid));
3305 + sb_setcoreidx(&si->sb, origidx);
3310 + /* get chipcommon rev */
3311 + si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV;
3313 + /* determine numcores */
3314 + if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6)))
3315 + si->numcores = (R_REG(&cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT;
3317 + si->numcores = BCMINIT(sb_chip2numcores)(si->sb.chip);
3319 + /* return to original core */
3320 + sb_setcoreidx(&si->sb, origidx);
3322 + /* sanity checks */
3323 + ASSERT(si->sb.chip);
3325 + /* scan for cores */
3326 + BCMINIT(sb_scan)(si);
3328 + /* fixup necessary chip/core configurations */
3329 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3330 + if (sb_pci_fixcfg(si)) {
3331 + SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n"));
3336 + /* srom_var_init() depends on sb_scan() info */
3337 + if (srom_var_init(si, si->sb.bustype, si->curmap, osh, vars, varsz)) {
3338 + SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n"));
3344 + * The chip revision number is hardwired into all
3345 + * of the pci function config rev fields and is
3346 + * independent from the individual core revision numbers.
3347 + * For example, the "A0" silicon of each chip is chip rev 0.
3349 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3350 + w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_REV, sizeof (uint32));
3351 + si->sb.chiprev = w & 0xff;
3353 + si->sb.chiprev = 0;
3356 + /* gpio control core is required */
3357 + if (!GOODIDX(si->gpioidx)) {
3358 + SB_ERROR(("sb_doattach: gpio control core not found\n"));
3362 + /* get boardtype and boardrev */
3363 + switch (BUSTYPE(si->sb.bustype)) {
3365 + /* do a pci config read to get subsystem id and subvendor id */
3366 + w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_SVID, sizeof (uint32));
3367 + si->sb.boardvendor = w & 0xffff;
3368 + si->sb.boardtype = (w >> 16) & 0xffff;
3373 + si->sb.boardvendor = VENDOR_BROADCOM;
3374 + if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0)
3375 + si->sb.boardtype = 0xffff;
3379 + if (si->sb.boardtype == 0) {
3380 + SB_ERROR(("sb_doattach: unknown board type\n"));
3381 + ASSERT(si->sb.boardtype);
3384 + /* setup the GPIO based LED powersave register */
3385 + if (si->sb.ccrev >= 16) {
3386 + w = getintvar(*vars, "gpiotimerval");
3388 + w = DEFAULT_GPIOTIMERVAL;
3389 + sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
3397 +sb_coreid(sb_t *sbh)
3402 + si = SB_INFO(sbh);
3403 + sb = REGS2SB(si->curmap);
3405 + return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
3409 +sb_coreidx(sb_t *sbh)
3413 + si = SB_INFO(sbh);
3414 + return (si->curidx);
3417 +/* return current index of core */
3419 +_sb_coreidx(sb_info_t *si)
3422 + uint32 sbaddr = 0;
3426 + switch (BUSTYPE(si->sb.bustype)) {
3428 + sb = REGS2SB(si->curmap);
3429 + sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0));
3433 + sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32));
3438 + sbaddr = (uint32)si->curmap;
3440 +#endif /* BCMJTAG */
3446 + if (!GOODCOREADDR(sbaddr))
3449 + return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE);
3453 +sb_corevendor(sb_t *sbh)
3458 + si = SB_INFO(sbh);
3459 + sb = REGS2SB(si->curmap);
3461 + return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
3465 +sb_corerev(sb_t *sbh)
3471 + si = SB_INFO(sbh);
3472 + sb = REGS2SB(si->curmap);
3473 + sbidh = R_SBREG(si, &(sb)->sbidhigh);
3475 + return (SBCOREREV(sbidh));
3483 + si = SB_INFO(sbh);
3487 +#define SBTML_ALLOW (SBTML_PE | SBTML_FGC | SBTML_FL_MASK)
3489 +/* set/clear sbtmstatelow core-specific flags */
3491 +sb_coreflags(sb_t *sbh, uint32 mask, uint32 val)