diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-01-06 19:28:07 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-01-06 19:28:07 +0000 |
commit | 90fba37c49479ed4e5233dc0d348cdf7d24c9ee1 (patch) | |
tree | 58af9e3b3204308a2b7853127331f4d693e1b744 /target/linux/brcm-2.4/files | |
parent | b59f896089edf83ce4cd1951001b6cc889bdd287 (diff) |
update brcm-2.4 to 2.4.35.4, integrate new broadcom system code, update broadcom-wl to a contributed version (v4.150.10.5) - no bcm57xx support yet, will follow shortly
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10137 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/brcm-2.4/files')
53 files changed, 8528 insertions, 4182 deletions
diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/Makefile b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/Makefile index 55e1757efc..f2096137e4 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/Makefile +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/Makefile @@ -9,8 +9,8 @@ O_TARGET := bcm947xx.o export-objs := export.o obj-y := prom.o setup.o time.o sbmips.o gpio.o -obj-y += nvram.o nvram_linux.o sflash.o -obj-y += sbutils.o bcmutils.o bcmsrom.o hndchipc.o +obj-y += nvram.o nvram_linux.o cfe_env.o hndpmu.o +obj-y += sbutils.o utils.o bcmsrom.o hndchipc.o obj-$(CONFIG_PCI) += sbpci.o pcibios.o obj-y += export.o diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c index 1d08218a42..d5737d72fc 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c @@ -1,509 +1,1048 @@ /* - * Misc useful routines to access NIC SROM/OTP . + * Routines to access SPROM and to parse SROM/CIS variables. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * $Id: bcmsrom.c,v 1.1.1.14 2006/04/15 01:28:25 michael Exp $ + * $Id$ */ #include <typedefs.h> #include <bcmdefs.h> #include <osl.h> -#include <bcmutils.h> -#include <bcmsrom.h> +#include <stdarg.h> +#include <sbchipc.h> #include <bcmdevs.h> #include <bcmendian.h> #include <sbpcmcia.h> #include <pcicfg.h> +#include <sbconfig.h> #include <sbutils.h> +#include <bcmsrom.h> #include <bcmnvram.h> +#include "utils.h" /* debug/trace */ #if defined(WLTEST) #define BS_ERROR(args) printf args #else #define BS_ERROR(args) -#endif /* BCMDBG_ERR || WLTEST */ - -#define VARS_MAX 4096 /* should be reduced */ +#endif #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ -static int initvars_srom_pci(void *sbh, void *curmap, char **vars, uint *count); -static int initvars_cis_pcmcia(void *sbh, osl_t *osh, char **vars, uint *count); -static int initvars_flash_sb(void *sbh, char **vars, uint *count); -static int srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, char **vars, uint *count); -static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd); -static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data); -static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data); -static int sprom_read_pci(osl_t *osh, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, - bool check_crc); +typedef struct varbuf +{ + char *buf; /* pointer to current position */ + unsigned int size; /* current (residual) size in bytes */ +} varbuf_t; + +static int initvars_srom_sb (sb_t * sbh, osl_t * osh, void *curmap, + char **vars, uint * count); +static void _initvars_srom_pci (uint8 sromrev, uint16 * srom, uint off, + varbuf_t * b); +static int initvars_srom_pci (sb_t * sbh, void *curmap, char **vars, + uint * count); +static int initvars_cis_pcmcia (sb_t * sbh, osl_t * osh, char **vars, + uint * count); +#if !defined(BCMUSBDEV) && !defined(BCMSDIODEV) +static int initvars_flash_sb (sb_t * sbh, char **vars, uint * count); +#endif /* !BCMUSBDEV && !BCMSDIODEV */ +static int sprom_cmd_pcmcia (osl_t * osh, uint8 cmd); +static int sprom_read_pcmcia (osl_t * osh, uint16 addr, uint16 * data); +static int sprom_write_pcmcia (osl_t * osh, uint16 addr, uint16 data); +static int sprom_read_pci (osl_t * osh, uint16 * sprom, uint wordoff, + uint16 * buf, uint nwords, bool check_crc); + +static int initvars_table (osl_t * osh, char *start, char *end, char **vars, + uint * count); +static int initvars_flash (sb_t * sbh, osl_t * osh, char **vp, uint len); + +#ifdef BCMUSBDEV +static int get_sb_pcmcia_srom (sb_t * sbh, osl_t * osh, uint8 * pcmregs, + uint boff, uint16 * srom, uint bsz); +static int set_sb_pcmcia_srom (sb_t * sbh, osl_t * osh, uint8 * pcmregs, + uint boff, uint16 * srom, uint bsz); +static uint srom_size (sb_t * sbh, osl_t * osh); +#endif /* def BCMUSBDEV */ + +/* Initialization of varbuf structure */ +static void +varbuf_init (varbuf_t * b, char *buf, uint size) +{ + b->size = size; + b->buf = buf; +} -static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count); -static int initvars_flash(osl_t *osh, char **vp, uint len, char *devpath); +/* append a null terminated var=value string */ +static int +varbuf_append (varbuf_t * b, const char *fmt, ...) +{ + va_list ap; + int r; + + if (b->size < 2) + return 0; + + va_start (ap, fmt); + r = vsnprintf (b->buf, b->size, fmt, ap); + va_end (ap); + + /* C99 snprintf behavior returns r >= size on overflow, + * others return -1 on overflow. + * All return -1 on format error. + * We need to leave room for 2 null terminations, one for the current var + * string, and one for final null of the var table. So check that the + * strlen written, r, leaves room for 2 chars. + */ + if ((r == -1) || (r > (int) (b->size - 2))) + { + b->size = 0; + return 0; + } + + /* skip over this string's null termination */ + r++; + b->size -= r; + b->buf += r; + + return r; +} /* * Initialize local vars from the right source for this platform. * Return 0 on success, nonzero on error. */ int -srom_var_init(void *sbh, uint bustype, void *curmap, osl_t *osh, char **vars, uint *count) +BCMINITFN (srom_var_init) (sb_t * sbh, uint bustype, void *curmap, + osl_t * osh, char **vars, uint * count) { - ASSERT(bustype == BUSTYPE(bustype)); - if (vars == NULL || count == NULL) - return (0); + ASSERT (bustype == BUSTYPE (bustype)); + if (vars == NULL || count == NULL) + return (0); - switch (BUSTYPE(bustype)) { - case SB_BUS: - case JTAG_BUS: - return initvars_flash_sb(sbh, vars, count); + *vars = NULL; + *count = 0; - case PCI_BUS: - ASSERT(curmap); /* can not be NULL */ - return initvars_srom_pci(sbh, curmap, vars, count); + switch (BUSTYPE (bustype)) + { + case SB_BUS: + case JTAG_BUS: + return initvars_srom_sb (sbh, osh, curmap, vars, count); - case PCMCIA_BUS: - return initvars_cis_pcmcia(sbh, osh, vars, count); + case PCI_BUS: + ASSERT (curmap); /* can not be NULL */ + return initvars_srom_pci (sbh, curmap, vars, count); + case PCMCIA_BUS: + return initvars_cis_pcmcia (sbh, osh, vars, count); - default: - ASSERT(0); - } - return (-1); + + default: + ASSERT (0); + } + return (-1); } /* support only 16-bit word read from srom */ int -srom_read(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf) +srom_read (sb_t * sbh, uint bustype, void *curmap, osl_t * osh, + uint byteoff, uint nbytes, uint16 * buf) { - void *srom; - uint i, off, nw; - - ASSERT(bustype == BUSTYPE(bustype)); - - /* check input - 16-bit access only */ - if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2)) - return 1; - - off = byteoff / 2; - nw = nbytes / 2; - - if (BUSTYPE(bustype) == PCI_BUS) { - if (!curmap) - return 1; - srom = (uchar*)curmap + PCI_BAR0_SPROM_OFFSET; - if (sprom_read_pci(osh, srom, off, buf, nw, FALSE)) - return 1; - } else if (BUSTYPE(bustype) == PCMCIA_BUS) { - for (i = 0; i < nw; i++) { - if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16*)(buf + i))) - return 1; - } - } else { - return 1; + void *srom; + uint i, off, nw; + + ASSERT (bustype == BUSTYPE (bustype)); + + /* check input - 16-bit access only */ + if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2)) + return 1; + + off = byteoff / 2; + nw = nbytes / 2; + + if (BUSTYPE (bustype) == PCI_BUS) + { + if (!curmap) + return 1; + srom = (uchar *) curmap + PCI_BAR0_SPROM_OFFSET; + if (sprom_read_pci (osh, srom, off, buf, nw, FALSE)) + return 1; + } + else if (BUSTYPE (bustype) == PCMCIA_BUS) + { + for (i = 0; i < nw; i++) + { + if (sprom_read_pcmcia + (osh, (uint16) (off + i), (uint16 *) (buf + i))) + return 1; } + } + else if (BUSTYPE (bustype) == SB_BUS) + { +#ifdef BCMUSBDEV + if (SPROMBUS == PCMCIA_BUS) + { + uint origidx; + void *regs; + int rc; + bool wasup; + + origidx = sb_coreidx (sbh); + regs = sb_setcore (sbh, SB_PCMCIA, 0); + ASSERT (regs != NULL); + + if (!(wasup = sb_iscoreup (sbh))) + sb_core_reset (sbh, 0, 0); + + rc = get_sb_pcmcia_srom (sbh, osh, regs, byteoff, buf, nbytes); + + if (!wasup) + sb_core_disable (sbh, 0); + + sb_setcoreidx (sbh, origidx); + return rc; + } +#endif /* def BCMUSBDEV */ - return 0; + return 1; + } + else + { + return 1; + } + + return 0; } /* support only 16-bit word write into srom */ int -srom_write(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf) +srom_write (sb_t * sbh, uint bustype, void *curmap, osl_t * osh, + uint byteoff, uint nbytes, uint16 * buf) { - uint16 *srom; - uint i, nw, crc_range; - uint16 image[SPROM_SIZE]; - uint8 crc; - volatile uint32 val32; - - ASSERT(bustype == BUSTYPE(bustype)); - - /* check input - 16-bit access only */ - if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2)) - return 1; - - /* Are we writing the whole thing at once? */ - if ((byteoff == 0) && - ((nbytes == SPROM_SIZE) || - (nbytes == (SPROM_CRC_RANGE * 2)) || - (nbytes == (SROM4_WORDS * 2)))) { - crc_range = nbytes; - bcopy((void*)buf, (void*)image, nbytes); - nw = nbytes / 2; - } else { - if ((BUSTYPE(bustype) == PCMCIA_BUS) || (BUSTYPE(bustype) == SDIO_BUS)) - crc_range = SPROM_SIZE; - else - crc_range = SPROM_CRC_RANGE * 2; /* Tentative */ - - nw = crc_range / 2; - /* read first 64 words from srom */ - if (srom_read(bustype, curmap, osh, 0, crc_range, image)) - return 1; - if (image[SROM4_SIGN] == SROM4_SIGNATURE) { - crc_range = SROM4_WORDS; - nw = crc_range / 2; - if (srom_read(bustype, curmap, osh, 0, crc_range, image)) - return 1; - } - /* make changes */ - bcopy((void*)buf, (void*)&image[byteoff / 2], nbytes); + uint16 *srom; + uint i, nw, crc_range; + uint16 image[SPROM_SIZE]; + uint8 crc; + volatile uint32 val32; + + ASSERT (bustype == BUSTYPE (bustype)); + + /* check input - 16-bit access only */ + if ((byteoff & 1) || (nbytes & 1)) + return 1; + + if (byteoff == 0x55aa) + { + /* Erase request */ + crc_range = 0; + memset ((void *) image, 0xff, nbytes); + nw = nbytes / 2; + } + else if ((byteoff == 0) && + ((nbytes == SPROM_SIZE * 2) || + (nbytes == (SPROM_CRC_RANGE * 2)) || + (nbytes == (SROM4_WORDS * 2)))) + { + /* Are we writing the whole thing at once? */ + crc_range = nbytes; + bcopy ((void *) buf, (void *) image, nbytes); + nw = nbytes / 2; + } + else + { + if ((byteoff + nbytes) > (SPROM_SIZE * 2)) + return 1; + + if (BUSTYPE (bustype) == PCMCIA_BUS) + { + crc_range = SPROM_SIZE * 2; + } + else + { + crc_range = SPROM_CRC_RANGE * 2; /* Tentative */ } - /* calculate crc */ - htol16_buf(image, crc_range); - crc = ~hndcrc8((uint8 *)image, crc_range - 1, CRC8_INIT_VALUE); - ltoh16_buf(image, crc_range); - image[(crc_range / 2) - 1] = (crc << 8) | (image[(crc_range / 2) - 1] & 0xff); - - if (BUSTYPE(bustype) == PCI_BUS) { - srom = (uint16*)((uchar*)curmap + PCI_BAR0_SPROM_OFFSET); - /* enable writes to the SPROM */ - val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); - val32 |= SPROM_WRITEEN; - OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32); - bcm_mdelay(WRITE_ENABLE_DELAY); - /* write srom */ - for (i = 0; i < nw; i++) { - W_REG(osh, &srom[i], image[i]); - bcm_mdelay(WRITE_WORD_DELAY); - } - /* disable writes to the SPROM */ - OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & - ~SPROM_WRITEEN); - } else if (BUSTYPE(bustype) == PCMCIA_BUS) { - /* enable writes to the SPROM */ - if (sprom_cmd_pcmcia(osh, SROM_WEN)) - return 1; - bcm_mdelay(WRITE_ENABLE_DELAY); - /* write srom */ - for (i = 0; i < nw; i++) { - sprom_write_pcmcia(osh, (uint16)(i), image[i]); - bcm_mdelay(WRITE_WORD_DELAY); - } - /* disable writes to the SPROM */ - if (sprom_cmd_pcmcia(osh, SROM_WDS)) - return 1; - } else { - return 1; + nw = crc_range / 2; + /* read first 64 words from srom */ + if (srom_read (sbh, bustype, curmap, osh, 0, crc_range, image)) + return 1; + if (image[SROM4_SIGN] == SROM4_SIGNATURE) + { + nw = SROM4_WORDS; + crc_range = nw * 2; + if (srom_read (sbh, bustype, curmap, osh, 0, crc_range, image)) + return 1; + } + /* make changes */ + bcopy ((void *) buf, (void *) &image[byteoff / 2], nbytes); + } + + if (crc_range) + { + /* calculate crc */ + htol16_buf (image, crc_range); + crc = ~hndcrc8 ((uint8 *) image, crc_range - 1, 0xff); + ltoh16_buf (image, crc_range); + image[nw - 1] = (crc << 8) | (image[nw - 1] & 0xff); + } + + if (BUSTYPE (bustype) == PCI_BUS) + { + srom = (uint16 *) ((uchar *) curmap + PCI_BAR0_SPROM_OFFSET); + /* enable writes to the SPROM */ + val32 = OSL_PCI_READ_CONFIG (osh, PCI_SPROM_CONTROL, sizeof (uint32)); + val32 |= SPROM_WRITEEN; + OSL_PCI_WRITE_CONFIG (osh, PCI_SPROM_CONTROL, sizeof (uint32), val32); + bcm_mdelay (WRITE_ENABLE_DELAY); + /* write srom */ + for (i = 0; i < nw; i++) + { + W_REG (osh, &srom[i], image[i]); + bcm_mdelay (WRITE_WORD_DELAY); + } + /* disable writes to the SPROM */ + OSL_PCI_WRITE_CONFIG (osh, PCI_SPROM_CONTROL, sizeof (uint32), val32 & + ~SPROM_WRITEEN); + } + else if (BUSTYPE (bustype) == PCMCIA_BUS) + { + /* enable writes to the SPROM */ + if (sprom_cmd_pcmcia (osh, SROM_WEN)) + return 1; + bcm_mdelay (WRITE_ENABLE_DELAY); + /* write srom */ + for (i = 0; i < nw; i++) + { + sprom_write_pcmcia (osh, (uint16) (i), image[i]); + bcm_mdelay (WRITE_WORD_DELAY); } + /* disable writes to the SPROM */ + if (sprom_cmd_pcmcia (osh, SROM_WDS)) + return 1; + } + else if (BUSTYPE (bustype) == SB_BUS) + { +#ifdef BCMUSBDEV + if (SPROMBUS == PCMCIA_BUS) + { + uint origidx; + void *regs; + int rc; + bool wasup; + + origidx = sb_coreidx (sbh); + regs = sb_setcore (sbh, SB_PCMCIA, 0); + ASSERT (regs != NULL); + + if (!(wasup = sb_iscoreup (sbh))) + sb_core_reset (sbh, 0, 0); + + rc = set_sb_pcmcia_srom (sbh, osh, regs, byteoff, buf, nbytes); + + if (!wasup) + sb_core_disable (sbh, 0); + + sb_setcoreidx (sbh, origidx); + return rc; + } +#endif /* def BCMUSBDEV */ + return 1; + } + else + { + return 1; + } + + bcm_mdelay (WRITE_ENABLE_DELAY); + return 0; +} + +#ifdef BCMUSBDEV +#define SB_PCMCIA_READ(osh, regs, fcr) \ + R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2) +#define SB_PCMCIA_WRITE(osh, regs, fcr, v) \ + W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v) + +/* set PCMCIA srom command register */ +static int +srom_cmd_sb_pcmcia (osl_t * osh, uint8 * pcmregs, uint8 cmd) +{ + uint8 status = 0; + uint wait_cnt = 0; + + /* write srom command register */ + SB_PCMCIA_WRITE (osh, pcmregs, SROM_CS, cmd); - bcm_mdelay(WRITE_ENABLE_DELAY); + /* wait status */ + while (++wait_cnt < 1000000) + { + status = SB_PCMCIA_READ (osh, pcmregs, SROM_CS); + if (status & SROM_DONE) return 0; + OSL_DELAY (1); + } + + BS_ERROR (("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt, + status)); + return 1; } +/* read a word from the PCMCIA srom over SB */ +static int +srom_read_sb_pcmcia (osl_t * osh, uint8 * pcmregs, uint16 addr, uint16 * data) +{ + uint8 addr_l, addr_h, data_l, data_h; + + addr_l = (uint8) ((addr * 2) & 0xff); + addr_h = (uint8) (((addr * 2) >> 8) & 0xff); + + /* set address */ + SB_PCMCIA_WRITE (osh, pcmregs, SROM_ADDRH, addr_h); + SB_PCMCIA_WRITE (osh, pcmregs, SROM_ADDRL, addr_l); + /* do read */ + if (srom_cmd_sb_pcmcia (osh, pcmregs, SROM_READ)) + return 1; + + /* read data */ + data_h = SB_PCMCIA_READ (osh, pcmregs, SROM_DATAH); + data_l = SB_PCMCIA_READ (osh, pcmregs, SROM_DATAL); + *data = ((uint16) data_h << 8) | data_l; + + return 0; +} + +/* write a word to the PCMCIA srom over SB */ static int -srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, char **vars, uint *count) +srom_write_sb_pcmcia (osl_t * osh, uint8 * pcmregs, uint16 addr, uint16 data) { - char eabuf[32]; - char *vp, *base; - uint8 *cis, tup, tlen, sromrev = 1; - int i, j; - uint varsize; - bool ag_init = FALSE; - uint32 w32; - - ASSERT(vars); - ASSERT(count); - - base = vp = MALLOC(osh, VARS_MAX); - ASSERT(vp); - if (!vp) - return -2; - - while (ciscnt--) { - cis = *pcis++; - i = 0; - do { - tup = cis[i++]; - tlen = cis[i++]; - if ((i + tlen) >= CIS_SIZE) - break; - - switch (tup) { - case CISTPL_MANFID: - vp += sprintf(vp, "manfid=%d", (cis[i + 1] << 8) + cis[i]); - vp++; - vp += sprintf(vp, "prodid=%d", (cis[i + 3] << 8) + cis[i + 2]); - vp++; - break; - - case CISTPL_FUNCE: - switch (cis[i]) { - case LAN_NID: - ASSERT(cis[i + 1] == 6); - bcm_ether_ntoa((struct ether_addr *)&cis[i + 2], eabuf); - vp += sprintf(vp, "il0macaddr=%s", eabuf); - vp++; - break; - case 1: /* SDIO Extended Data */ - vp += sprintf(vp, "sdmaxblk=%d", - (cis[i + 13] << 8) | cis[i + 12]); - vp++; - break; - } - break; - - case CISTPL_CFTABLE: - vp += sprintf(vp, "regwindowsz=%d", (cis[i + 7] << 8) | cis[i + 6]); - vp++; - break; - - case CISTPL_BRCM_HNBU: - switch (cis[i]) { - case HNBU_SROMREV: - sromrev = cis[i + 1]; - break; - - case HNBU_CHIPID: - vp += sprintf(vp, "vendid=%d", (cis[i + 2] << 8) + - cis[i + 1]); - vp++; - vp += sprintf(vp, "devid=%d", (cis[i + 4] << 8) + - cis[i + 3]); - vp++; - if (tlen == 7) { - vp += sprintf(vp, "chiprev=%d", - (cis[i + 6] << 8) + cis[i + 5]); - vp++; - } - break; - - case HNBU_BOARDREV: - vp += sprintf(vp, "boardrev=%d", cis[i + 1]); - vp++; - break; - - case HNBU_AA: - vp += sprintf(vp, "aa2g=%d", cis[i + 1]); - vp++; - break; - - case HNBU_AG: - vp += sprintf(vp, "ag0=%d", cis[i + 1]); - vp++; - ag_init = TRUE; - break; - - case HNBU_CC: - ASSERT(sromrev == 1); - vp += sprintf(vp, "cc=%d", cis[i + 1]); - vp++; - break; - - case HNBU_PAPARMS: - if (tlen == 2) { - ASSERT(sromrev == 1); - vp += sprintf(vp, "pa0maxpwr=%d", cis[i + 1]); - vp++; - } else if (tlen >= 9) { - if (tlen == 10) { - ASSERT(sromrev == 2); - vp += sprintf(vp, "opo=%d", cis[i + 9]); - vp++; - } else - ASSERT(tlen == 9); - - for (j = 0; j < 3; j++) { - vp += sprintf(vp, "pa0b%d=%d", j, - (cis[i + (j * 2) + 2] << 8) + - cis[i + (j * 2) + 1]); - vp++; - } - vp += sprintf(vp, "pa0itssit=%d", cis[i + 7]); - vp++; - vp += sprintf(vp, "pa0maxpwr=%d", cis[i + 8]); - vp++; - } else - ASSERT(tlen >= 9); - break; - - case HNBU_OEM: - ASSERT(sromrev == 1); - vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x", - cis[i + 1], cis[i + 2], - cis[i + 3], cis[i + 4], - cis[i + 5], cis[i + 6], - cis[i + 7], cis[i + 8]); - vp++; - break; - - case HNBU_BOARDFLAGS: - w32 = (cis[i + 2] << 8) + cis[i + 1]; - if (tlen == 5) - w32 |= (cis[i + 4] << 24) + (cis[i + 3] << 16); - vp += sprintf(vp, "boardflags=0x%x", w32); - vp++; - break; - - case HNBU_LEDS: - if (cis[i + 1] != 0xff) { - vp += sprintf(vp, "ledbh0=%d", cis[i + 1]); - vp++; - } - if (cis[i + 2] != 0xff) { - vp += sprintf(vp, "ledbh1=%d", cis[i + 2]); - vp++; - } - if (cis[i + 3] != 0xff) { - vp += sprintf(vp, "ledbh2=%d", cis[i + 3]); - vp++; - } - if (cis[i + 4] != 0xff) { - vp += sprintf(vp, "ledbh3=%d", cis[i + 4]); - vp++; - } - break; - - case HNBU_CCODE: - { - char str[3]; - ASSERT(sromrev > 1); - str[0] = cis[i + 1]; - str[1] = cis[i + 2]; - str[2] = 0; - vp += sprintf(vp, "ccode=%s", str); - vp++; - vp += sprintf(vp, "cctl=0x%x", cis[i + 3]); - vp++; - break; - } - - case HNBU_CCKPO: - ASSERT(sromrev > 2); - vp += sprintf(vp, "cckpo=0x%x", - (cis[i + 2] << 8) | cis[i + 1]); - vp++; - break; - - case HNBU_OFDMPO: - ASSERT(sromrev > 2); - vp += sprintf(vp, "ofdmpo=0x%x", - (cis[i + 4] << 24) | - (cis[i + 3] << 16) | - (cis[i + 2] << 8) | - cis[i + 1]); - vp++; - break; - } - break; + uint8 addr_l, addr_h, data_l, data_h; + int rc; - } - i += tlen; - } while (tup != 0xff); + addr_l = (uint8) ((addr * 2) & 0xff); + addr_h = (uint8) (((addr * 2) >> 8) & 0xff); + + /* set address */ + SB_PCMCIA_WRITE (osh, pcmregs, SROM_ADDRH, addr_h); + SB_PCMCIA_WRITE (osh, pcmregs, SROM_ADDRL, addr_l); + + data_l = (uint8) (data & 0xff); + data_h = (uint8) ((data >> 8) & 0xff); + + /* write data */ + SB_PCMCIA_WRITE (osh, pcmregs, SROM_DATAH, data_h); + SB_PCMCIA_WRITE (osh, pcmregs, SROM_DATAL, data_l); + + /* do write */ + rc = srom_cmd_sb_pcmcia (osh, pcmregs, SROM_WRITE); + OSL_DELAY (20000); + return rc; +} + +/* + * Read the srom for the pcmcia-srom over sb case. + * Return 0 on success, nonzero on error. + */ +static int +get_sb_pcmcia_srom (sb_t * sbh, osl_t * osh, uint8 * pcmregs, + uint boff, uint16 * srom, uint bsz) +{ + uint i, nw, woff, wsz; + int err = 0; + + /* read must be at word boundary */ + ASSERT ((boff & 1) == 0 && (bsz & 1) == 0); + + /* read sprom size and validate the parms */ + if ((nw = srom_size (sbh, osh)) == 0) + { + BS_ERROR (("get_sb_pcmcia_srom: sprom size unknown\n")); + err = -1; + goto out; + } + if (boff + bsz > 2 * nw) + { + BS_ERROR (("get_sb_pcmcia_srom: sprom size exceeded\n")); + err = -2; + goto out; + } + + /* read in sprom contents */ + for (woff = boff / 2, wsz = bsz / 2, i = 0; + woff < nw && i < wsz; woff++, i++) + { + if (srom_read_sb_pcmcia (osh, pcmregs, (uint16) woff, &srom[i])) + { + BS_ERROR (("get_sb_pcmcia_srom: sprom read failed\n")); + err = -3; + goto out; } + } - /* Set the srom version */ - vp += sprintf(vp, "sromrev=%d", sromrev); - vp++; +out: + return err; +} - /* if there is no antenna gain field, set default */ - if (ag_init == FALSE) { - ASSERT(sromrev == 1); - vp += sprintf(vp, "ag0=%d", 0xff); - vp++; +/* + * Write the srom for the pcmcia-srom over sb case. + * Return 0 on success, nonzero on error. + */ +static int +set_sb_pcmcia_srom (sb_t * sbh, osl_t * osh, uint8 * pcmregs, + uint boff, uint16 * srom, uint bsz) +{ + uint i, nw, woff, wsz; + uint16 word; + uint8 crc; + int err = 0; + + /* write must be at word boundary */ + ASSERT ((boff & 1) == 0 && (bsz & 1) == 0); + + /* read sprom size and validate the parms */ + if ((nw = srom_size (sbh, osh)) == 0) + { + BS_ERROR (("set_sb_pcmcia_srom: sprom size unknown\n")); + err = -1; + goto out; + } + if (boff + bsz > 2 * nw) + { + BS_ERROR (("set_sb_pcmcia_srom: sprom size exceeded\n")); + err = -2; + goto out; + } + + /* enable write */ + if (srom_cmd_sb_pcmcia (osh, pcmregs, SROM_WEN)) + { + BS_ERROR (("set_sb_pcmcia_srom: sprom wen failed\n")); + err = -3; + goto out; + } + + /* write buffer to sprom */ + for (woff = boff / 2, wsz = bsz / 2, i = 0; + woff < nw && i < wsz; woff++, i++) + { + if (srom_write_sb_pcmcia (osh, pcmregs, (uint16) woff, srom[i])) + { + BS_ERROR (("set_sb_pcmcia_srom: sprom write failed\n")); + err = -4; + goto out; + } + } + + /* fix crc */ + crc = 0xff; + for (woff = 0; woff < nw; woff++) + { + if (srom_read_sb_pcmcia (osh, pcmregs, (uint16) woff, &word)) + { + BS_ERROR (("set_sb_pcmcia_srom: sprom fix crc read failed\n")); + err = -5; + goto out; } + word = htol16 (word); + crc = hndcrc8 ((uint8 *) & word, woff != nw - 1 ? 2 : 1, crc); + } + word = (~crc << 8) + (ltoh16 (word) & 0xff); + if (srom_write_sb_pcmcia (osh, pcmregs, (uint16) (woff - 1), word)) + { + BS_ERROR (("set_sb_pcmcia_srom: sprom fix crc write failed\n")); + err = -6; + goto out; + } + + /* disable write */ + if (srom_cmd_sb_pcmcia (osh, pcmregs, SROM_WDS)) + { + BS_ERROR (("set_sb_pcmcia_srom: sprom wds failed\n")); + err = -7; + goto out; + } + +out: + return err; +} +#endif /* def BCMUSBDEV */ - /* final nullbyte terminator */ - *vp++ = '\0'; - varsize = (uint)(vp - base); - - ASSERT((vp - base) < VARS_MAX); - - if (varsize == VARS_MAX) { - *vars = base; - } else { - vp = MALLOC(osh, varsize); - ASSERT(vp); - if (vp) - bcopy(base, vp, varsize); - MFREE(osh, base, VARS_MAX); - *vars = vp; - if (!vp) { - *count = 0; - return -2; +int +srom_parsecis (osl_t * osh, uint8 * pcis[], uint ciscnt, char **vars, + uint * count) +{ + char eabuf[32]; + char *base; + varbuf_t b; + uint8 *cis, tup, tlen, sromrev = 1; + int i, j; + uint varsize; + bool ag_init = FALSE; + uint32 w32; + uint funcid; + uint cisnum; + int32 boardnum = -1; + + ASSERT (vars); + ASSERT (count); + + base = MALLOC (osh, MAXSZ_NVRAM_VARS); + ASSERT (base); + if (!base) + return -2; + + varbuf_init (&b, base, MAXSZ_NVRAM_VARS); + + eabuf[0] = '\0'; + for (cisnum = 0; cisnum < ciscnt; cisnum++) + { + cis = *pcis++; + i = 0; + funcid = 0; + do + { + tup = cis[i++]; + tlen = cis[i++]; + if ((i + tlen) >= CIS_SIZE) + break; + + switch (tup) + { + case CISTPL_VERS_1: + /* assume the strings are good if the version field checks out */ + if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) + { + varbuf_append (&b, "manf=%s", &cis[i + 2]); + varbuf_append (&b, "productname=%s", + &cis[i + 3 + strlen ((char *) &cis[i + 2])]); + break; } + + case CISTPL_MANFID: + varbuf_append (&b, "manfid=0x%x", (cis[i + 1] << 8) + cis[i]); + varbuf_append (&b, "prodid=0x%x", + (cis[i + 3] << 8) + cis[i + 2]); + break; + + case CISTPL_FUNCID: + funcid = cis[i]; + break; + + case CISTPL_FUNCE: + switch (funcid) + { + default: + /* set macaddr if HNBU_MACADDR not seen yet */ + if (eabuf[0] == '\0' && cis[i] == LAN_NID) + { + ASSERT (cis[i + 1] == ETHER_ADDR_LEN); + bcm_ether_ntoa ((struct ether_addr *) &cis[i + 2], + eabuf); + } + /* set boardnum if HNBU_BOARDNUM not seen yet */ + if (boardnum == -1) + boardnum = (cis[i + 6] << 8) + cis[i + 7]; + break; + } + break; + + case CISTPL_CFTABLE: + varbuf_append (&b, "regwindowsz=%d", + (cis[i + 7] << 8) | cis[i + 6]); + break; + + case CISTPL_BRCM_HNBU: + switch (cis[i]) + { + case HNBU_SROMREV: + sromrev = cis[i + 1]; + varbuf_append (&b, "sromrev=%d", sromrev); + break; + + case HNBU_CHIPID: + varbuf_append (&b, "vendid=0x%x", (cis[i + 2] << 8) + + cis[i + 1]); + varbuf_append (&b, "devid=0x%x", (cis[i + 4] << 8) + + cis[i + 3]); + if (tlen >= 7) + { + varbuf_append (&b, "chiprev=%d", + (cis[i + 6] << 8) + cis[i + 5]); + } + if (tlen >= 9) + { + varbuf_append (&b, "subvendid=0x%x", + (cis[i + 8] << 8) + cis[i + 7]); + } + if (tlen >= 11) + { + varbuf_append (&b, "subdevid=0x%x", + (cis[i + 10] << 8) + cis[i + 9]); + /* subdevid doubles for boardtype */ + varbuf_append (&b, "boardtype=0x%x", + (cis[i + 10] << 8) + cis[i + 9]); + } + break; + + case HNBU_BOARDREV: + varbuf_append (&b, "boardrev=0x%x", cis[i + 1]); + break; + + case HNBU_AA: + varbuf_append (&b, "aa2g=%d", cis[i + 1]); + break; + + case HNBU_AG: + varbuf_append (&b, "ag0=%d", cis[i + 1]); + ag_init = TRUE; + break; + + case HNBU_ANT5G: + varbuf_append (&b, "aa5g=%d", cis[i + 1]); + varbuf_append (&b, "ag1=%d", cis[i + 2]); + break; + + case HNBU_CC: + ASSERT (sromrev == 1); + varbuf_append (&b, "cc=%d", cis[i + 1]); + break; + + case HNBU_PAPARMS: + if (tlen == 2) + { + ASSERT (sromrev == 1); + varbuf_append (&b, "pa0maxpwr=%d", cis[i + 1]); + } + else if (tlen >= 9) + { + if (tlen == 10) + { + ASSERT (sromrev >= 2); + varbuf_append (&b, "opo=%d", cis[i + 9]); + } + else + ASSERT (tlen == 9); + + for (j = 0; j < 3; j++) + { + varbuf_append (&b, "pa0b%d=%d", j, + (cis[i + (j * 2) + 2] << 8) + + cis[i + (j * 2) + 1]); + } + varbuf_append (&b, "pa0itssit=%d", cis[i + 7]); + varbuf_append (&b, "pa0maxpwr=%d", cis[i + 8]); + } + else + ASSERT (tlen >= 9); + break; + + case HNBU_PAPARMS5G: + ASSERT ((sromrev == 2) || (sromrev == 3)); + for (j = 0; j < 3; j++) + { + varbuf_append (&b, "pa1b%d=%d", j, + (cis[i + (j * 2) + 2] << 8) + + cis[i + (j * 2) + 1]); + } + for (j = 3; j < 6; j++) + { + varbuf_append (&b, "pa1lob%d=%d", j - 3, + (cis[i + (j * 2) + 2] << 8) + + cis[i + (j * 2) + 1]); + } + for (j = 6; j < 9; j++) + { + varbuf_append (&b, "pa1hib%d=%d", j - 6, + (cis[i + (j * 2) + 2] << 8) + + cis[i + (j * 2) + 1]); + } + varbuf_append (&b, "pa1itssit=%d", cis[i + 19]); + varbuf_append (&b, "pa1maxpwr=%d", cis[i + 20]); + varbuf_append (&b, "pa1lomaxpwr=%d", cis[i + 21]); + varbuf_append (&b, "pa1himaxpwr=%d", cis[i + 22]); + break; + + case HNBU_OEM: + ASSERT (sromrev == 1); + varbuf_append (&b, "oem=%02x%02x%02x%02x%02x%02x%02x%02x", + cis[i + 1], cis[i + 2], + cis[i + 3], cis[i + 4], + cis[i + 5], cis[i + 6], + cis[i + 7], cis[i + 8]); + break; + + case HNBU_BOARDFLAGS: + w32 = (cis[i + 2] << 8) + cis[i + 1]; + if (tlen == 5) + w32 |= (cis[i + 4] << 24) + (cis[i + 3] << 16); + varbuf_append (&b, "boardflags=0x%x", w32); + break; + + case HNBU_LEDS: + if (cis[i + 1] != 0xff) + { + varbuf_append (&b, "ledbh0=%d", cis[i + 1]); + } + if (cis[i + 2] != 0xff) + { + varbuf_append (&b, "ledbh1=%d", cis[i + 2]); + } + if (cis[i + 3] != 0xff) + { + varbuf_append (&b, "ledbh2=%d", cis[i + 3]); + } + if (cis[i + 4] != 0xff) + { + varbuf_append (&b, "ledbh3=%d", cis[i + 4]); + } + break; + + case HNBU_CCODE: + ASSERT (sromrev > 1); + if ((cis[i + 1] == 0) || (cis[i + 2] == 0)) + varbuf_append (&b, "ccode="); + else + varbuf_append (&b, "ccode=%c%c", cis[i + 1], cis[i + 2]); + varbuf_append (&b, "cctl=0x%x", cis[i + 3]); + break; + + case HNBU_CCKPO: + ASSERT (sromrev > 2); + varbuf_append (&b, "cckpo=0x%x", + (cis[i + 2] << 8) | cis[i + 1]); + break; + + case HNBU_OFDMPO: + ASSERT (sromrev > 2); + varbuf_append (&b, "ofdmpo=0x%x", + (cis[i + 4] << 24) | + (cis[i + 3] << 16) | + (cis[i + 2] << 8) | cis[i + 1]); + break; + + case HNBU_RDLID: + varbuf_append (&b, "rdlid=0x%x", + (cis[i + 2] << 8) | cis[i + 1]); + break; + + case HNBU_RDLRNDIS: + varbuf_append (&b, "rdlrndis=%d", cis[i + 1]); + break; + + case HNBU_RDLRWU: + varbuf_append (&b, "rdlrwu=%d", cis[i + 1]); + break; + + case HNBU_RDLSN: + varbuf_append (&b, "rdlsn=%d", + (cis[i + 2] << 8) | cis[i + 1]); + break; + + case HNBU_XTALFREQ: + varbuf_append (&b, "xtalfreq=%d", + (cis[i + 4] << 24) | + (cis[i + 3] << 16) | + (cis[i + 2] << 8) | cis[i + 1]); + break; + + case HNBU_RSSISMBXA2G: + ASSERT (sromrev == 3); + varbuf_append (&b, "rssismf2g=%d", cis[i + 1] & 0xf); + varbuf_append (&b, "rssismc2g=%d", (cis[i + 1] >> 4) & 0xf); + varbuf_append (&b, "rssisav2g=%d", cis[i + 2] & 0x7); + varbuf_append (&b, "bxa2g=%d", (cis[i + 2] >> 3) & 0x3); + break; + + case HNBU_RSSISMBXA5G: + ASSERT (sromrev == 3); + varbuf_append (&b, "rssismf5g=%d", cis[i + 1] & 0xf); + varbuf_append (&b, "rssismc5g=%d", (cis[i + 1] >> 4) & 0xf); + varbuf_append (&b, "rssisav5g=%d", cis[i + 2] & 0x7); + varbuf_append (&b, "bxa5g=%d", (cis[i + 2] >> 3) & 0x3); + break; + + case HNBU_TRI2G: + ASSERT (sromrev == 3); + varbuf_append (&b, "tri2g=%d", cis[i + 1]); + break; + + case HNBU_TRI5G: + ASSERT (sromrev == 3); + varbuf_append (&b, "tri5gl=%d", cis[i + 1]); + varbuf_append (&b, "tri5g=%d", cis[i + 2]); + varbuf_append (&b, "tri5gh=%d", cis[i + 3]); + break; + + case HNBU_RXPO2G: + ASSERT (sromrev == 3); + varbuf_append (&b, "rxpo2g=%d", cis[i + 1]); + break; + + case HNBU_RXPO5G: + ASSERT (sromrev == 3); + varbuf_append (&b, "rxpo5g=%d", cis[i + 1]); + break; + + case HNBU_BOARDNUM: + boardnum = (cis[i + 2] << 8) + cis[i + 1]; + break; + + case HNBU_MACADDR: + bcm_ether_ntoa ((struct ether_addr *) &cis[i + 1], eabuf); + break; + + case HNBU_BOARDTYPE: + varbuf_append (&b, "boardtype=0x%x", + (cis[i + 2] << 8) + cis[i + 1]); + break; + +#if defined(BCMCCISSR3) + case HNBU_SROM3SWRGN: + { + uint16 srom[35]; + uint8 srev = cis[i + 1 + 70]; + ASSERT (srev == 3); + /* make tuple value 16-bit aligned and parse it */ + bcopy (&cis[i + 1], srom, sizeof (srom)); + _initvars_srom_pci (srev, srom, SROM3_SWRGN_OFF, &b); + /* create extra variables */ + varbuf_append (&b, "vendid=0x%x", + (cis[i + 1 + 73] << 8) + cis[i + 1 + 72]); + varbuf_append (&b, "devid=0x%x", + (cis[i + 1 + 75] << 8) + cis[i + 1 + 74]); + varbuf_append (&b, "xtalfreq=%d", + (cis[i + 1 + 77] << 8) + cis[i + 1 + 76]); + /* 2.4G antenna gain is included in SROM */ + ag_init = TRUE; + /* Ethernet MAC address is included in SROM */ + eabuf[0] = 0; + boardnum = -1; + break; + } +#endif + } + break; + } + i += tlen; } - *count = varsize; + while (tup != CISTPL_END); + } + + if (boardnum != -1) + { + varbuf_append (&b, "boardnum=%d", boardnum); + } + + if (eabuf[0]) + { + varbuf_append (&b, "macaddr=%s", eabuf); + } + + /* if there is no antenna gain field, set default */ + if (ag_init == FALSE) + { + varbuf_append (&b, "ag0=%d", 0xff); + } + + /* final nullbyte terminator */ + ASSERT (b.size >= 1); + *b.buf++ = '\0'; + varsize = (uint) (b.buf - base); + ASSERT (varsize < MAXSZ_NVRAM_VARS); + if (varsize < MAXSZ_NVRAM_VARS) + { + char *new_buf; + new_buf = (char *) MALLOC (osh, varsize); + ASSERT (new_buf); + if (new_buf) + { + bcopy (base, new_buf, varsize); + MFREE (osh, base, MAXSZ_NVRAM_VARS); + base = new_buf; + } + } + + *vars = base; + *count = varsize; - return (0); + return (0); } /* set PCMCIA sprom command register */ static int -sprom_cmd_pcmcia(osl_t *osh, uint8 cmd) +sprom_cmd_pcmcia (osl_t * osh, uint8 cmd) { - uint8 status = 0; - uint wait_cnt = 1000; + uint8 status = 0; + uint wait_cnt = 1000; - /* write sprom command register */ - OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1); + /* write sprom command register */ + OSL_PCMCIA_WRITE_ATTR (osh, SROM_CS, &cmd, 1); - /* wait status */ - while (wait_cnt--) { - OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1); - if (status & SROM_DONE) - return 0; - } + /* wait status */ + while (wait_cnt--) + { + OSL_PCMCIA_READ_ATTR (osh, SROM_CS, &status, 1); + if (status & SROM_DONE) + return 0; + } - return 1; + return 1; } /* read a word from the PCMCIA srom */ static int -sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data) +sprom_read_pcmcia (osl_t * osh, uint16 addr, uint16 * data) { - uint8 addr_l, addr_h, data_l, data_h; + uint8 addr_l, addr_h, data_l, data_h; - addr_l = (uint8)((addr * 2) & 0xff); - addr_h = (uint8)(((addr * 2) >> 8) & 0xff); + addr_l = (uint8) ((addr * 2) & 0xff); + addr_h = (uint8) (((addr * 2) >> 8) & 0xff); - /* set address */ - OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); - OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); + /* set address */ + OSL_PCMCIA_WRITE_ATTR (osh, SROM_ADDRH, &addr_h, 1); + OSL_PCMCIA_WRITE_ATTR (osh, SROM_ADDRL, &addr_l, 1); - /* do read */ - if (sprom_cmd_pcmcia(osh, SROM_READ)) - return 1; + /* do read */ + if (sprom_cmd_pcmcia (osh, SROM_READ)) + return 1; - /* read data */ - data_h = data_l = 0; - OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1); - OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1); + /* read data */ + data_h = data_l = 0; + OSL_PCMCIA_READ_ATTR (osh, SROM_DATAH, &data_h, 1); + OSL_PCMCIA_READ_ATTR (osh, SROM_DATAL, &data_l, 1); - *data = (data_h << 8) | data_l; - return 0; + *data = (data_h << 8) | data_l; + return 0; } /* write a word to the PCMCIA srom */ static int -sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data) +sprom_write_pcmcia (osl_t * osh, uint16 addr, uint16 data) { - uint8 addr_l, addr_h, data_l, data_h; + uint8 addr_l, addr_h, data_l, data_h; - addr_l = (uint8)((addr * 2) & 0xff); - addr_h = (uint8)(((addr * 2) >> 8) & 0xff); - data_l = (uint8)(data & 0xff); - data_h = (uint8)((data >> 8) & 0xff); + addr_l = (uint8) ((addr * 2) & 0xff); + addr_h = (uint8) (((addr * 2) >> 8) & 0xff); + data_l = (uint8) (data & 0xff); + data_h = (uint8) ((data >> 8) & 0xff); - /* set address */ - OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); - OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); + /* set address */ + OSL_PCMCIA_WRITE_ATTR (osh, SROM_ADDRH, &addr_h, 1); + OSL_PCMCIA_WRITE_ATTR (osh, SROM_ADDRL, &addr_l, 1); - /* write data */ - OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1); - OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1); + /* write data */ + OSL_PCMCIA_WRITE_ATTR (osh, SROM_DATAH, &data_h, 1); + OSL_PCMCIA_WRITE_ATTR (osh, SROM_DATAL, &data_l, 1); - /* do write */ - return sprom_cmd_pcmcia(osh, SROM_WRITE); + /* do write */ + return sprom_cmd_pcmcia (osh, SROM_WRITE); } /* @@ -511,25 +1050,43 @@ sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data) * Return 0 on success, nonzero on error. */ static int -sprom_read_pci(osl_t *osh, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc) +sprom_read_pci (osl_t * osh, uint16 * sprom, uint wordoff, uint16 * buf, + uint nwords, bool check_crc) { - int err = 0; - uint i; - - /* read the sprom */ - for (i = 0; i < nwords; i++) - buf[i] = R_REG(osh, &sprom[wordoff + i]); - - if (check_crc) { - /* fixup the endianness so crc8 will pass */ - htol16_buf(buf, nwords * 2); - if (hndcrc8((uint8*)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) - err = 1; - /* now correct the endianness of the byte array */ - ltoh16_buf(buf, nwords * 2); + int err = 0; + uint i; + + /* read the sprom */ + for (i = 0; i < nwords; i++) + { +#ifdef BCMQT + buf[i] = R_REG (osh, &sprom[wordoff + i]); +#endif + buf[i] = R_REG (osh, &sprom[wordoff + i]); + } + + if (check_crc) + { + if (buf[0] == 0xffff) + { + /* The hardware thinks that an srom that starts with 0xffff + * is blank, regardless of the rest of the content, so declare + * it bad. + */ + BS_ERROR (("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, + buf[0])); + return 1; } - return err; + /* fixup the endianness so crc8 will pass */ + htol16_buf (buf, nwords * 2); + if (hndcrc8 ((uint8 *) buf, nwords * 2, 0xff) != 0x9f) + err = 1; + /* now correct the endianness of the byte array */ + ltoh16_buf (buf, nwords * 2); + } + + return err; } /* @@ -537,26 +1094,29 @@ sprom_read_pci(osl_t *osh, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords * Return 0 on success, nonzero on error. */ static int -initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count) +BCMINITFN (initvars_table) (osl_t * osh, char *start, char *end, char **vars, + uint * count) { - int c = (int)(end - start); - - /* do it only when there is more than just the null string */ - if (c > 1) { - char *vp = MALLOC(osh, c); - ASSERT(vp); - if (!vp) - return BCME_NOMEM; - bcopy(start, vp, c); - *vars = vp; - *count = c; - } - else { - *vars = NULL; - *count = 0; - } - - return 0; + int c = (int) (end - start); + + /* do it only when there is more than just the null string */ + if (c > 1) + { + char *vp = MALLOC (osh, c); + ASSERT (vp); + if (!vp) + return BCME_NOMEM; + bcopy (start, vp, c); + *vars = vp; + *count = c; + } + else + { + *vars = NULL; + *count = 0; + } + + return 0; } /* @@ -565,617 +1125,763 @@ initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count) * Return 0 on success, nonzero on error. */ static int -initvars_flash(osl_t *osh, char **base, uint len, char *devpath) +initvars_flash (sb_t * sbh, osl_t * osh, char **base, uint len) { - char *vp = *base; - char *flash; - int err; - char *s; - uint l, dl, copy_len; - - /* allocate memory and read in flash */ - if (!(flash = MALLOC(osh, NVRAM_SPACE))) - return BCME_NOMEM; - if ((err = nvram_getall(flash, NVRAM_SPACE))) - goto exit; - - /* grab vars with the <devpath> prefix in name */ - dl = strlen(devpath); - for (s = flash; s && *s; s += l + 1) { - l = strlen(s); - - /* skip non-matching variable */ - if (strncmp(s, devpath, dl)) - continue; - - /* is there enough room to copy? */ - copy_len = l - dl + 1; - if (len < copy_len) { - err = BCME_BUFTOOSHORT; - goto exit; - } - - /* no prefix, just the name=value */ - strcpy(vp, &s[dl]); - vp += copy_len; - len -= copy_len; + char *vp = *base; + char *flash; + int err; + char *s; + uint l, dl, copy_len; + char devpath[SB_DEVPATH_BUFSZ]; + + /* allocate memory and read in flash */ + if (!(flash = MALLOC (osh, NVRAM_SPACE))) + return BCME_NOMEM; + if ((err = nvram_getall (flash, NVRAM_SPACE))) + goto exit; + + sb_devpath (sbh, devpath, sizeof (devpath)); + + /* grab vars with the <devpath> prefix in name */ + dl = strlen (devpath); + for (s = flash; s && *s; s += l + 1) + { + l = strlen (s); + + /* skip non-matching variable */ + if (strncmp (s, devpath, dl)) + continue; + + /* is there enough room to copy? */ + copy_len = l - dl + 1; + if (len < copy_len) + { + err = BCME_BUFTOOSHORT; + goto exit; } - /* add null string as terminator */ - if (len < 1) { - err = BCME_BUFTOOSHORT; - goto exit; - } - *vp++ = '\0'; + /* no prefix, just the name=value */ + strncpy (vp, &s[dl], copy_len); + vp += copy_len; + len -= copy_len; + } + + /* add null string as terminator */ + if (len < 1) + { + err = BCME_BUFTOOSHORT; + goto exit; + } + *vp++ = '\0'; - *base = vp; + *base = vp; -exit: MFREE(osh, flash, NVRAM_SPACE); - return err; +exit:MFREE (osh, flash, NVRAM_SPACE); + return err; } +#if !defined(BCMUSBDEV) && !defined(BCMSDIODEV) /* * Initialize nonvolatile variable table from flash. * Return 0 on success, nonzero on error. */ static int -initvars_flash_sb(void *sbh, char **vars, uint *count) +initvars_flash_sb (sb_t * sbh, char **vars, uint * count) { - osl_t *osh = sb_osh(sbh); - char devpath[SB_DEVPATH_BUFSZ]; - char *vp, *base; - int err; + osl_t *osh = sb_osh (sbh); + char *vp, *base; + int err; - ASSERT(vars); - ASSERT(count); + ASSERT (vars); + ASSERT (count); - if ((err = sb_devpath(sbh, devpath, sizeof(devpath)))) - return err; + base = vp = MALLOC (osh, MAXSZ_NVRAM_VARS); + ASSERT (vp); + if (!vp) + return BCME_NOMEM; - base = vp = MALLOC(osh, VARS_MAX); - ASSERT(vp); - if (!vp) - return BCME_NOMEM; + if ((err = initvars_flash (sbh, osh, &vp, MAXSZ_NVRAM_VARS)) == 0) + err = initvars_table (osh, base, vp, vars, count); - if ((err = initvars_flash(osh, &vp, VARS_MAX, devpath))) - goto err; + MFREE (osh, base, MAXSZ_NVRAM_VARS); - err = initvars_table(osh, base, vp, vars, count); - -err: MFREE(osh, base, VARS_MAX); - return err; + return err; } +#endif /* !BCMUSBDEV && !BCMSDIODEV */ #ifdef WLTEST char mfgsromvars[256]; char *defaultsromvars = "il0macaddr=00:11:22:33:44:51\0" - "et0macaddr=00:11:22:33:44:52\0" - "et1macaddr=00:11:22:33:44:53\0" - "boardtype=0xffff\0" - "boardrev=0x10\0" - "boardflags=8\0" - "sromrev=2\0" - "aa2g=3"; -#define MFGSROM_DEFVARSLEN 147 /* default srom len */ + "et0macaddr=00:11:22:33:44:52\0" + "et1macaddr=00:11:22:33:44:53\0" + "boardtype=0xffff\0" + "boardrev=0x10\0" "boardflags=8\0" "sromrev=2\0" "aa2g=3\0" "\0"; +#define MFGSROM_DEFVARSLEN 149 /* default srom len */ #endif /* WL_TEST */ /* * Initialize nonvolatile variable table from sprom. * Return 0 on success, nonzero on error. */ -static int -initvars_srom_pci(void *sbh, void *curmap, char **vars, uint *count) -{ - uint16 w, *b; - uint8 sromrev = 0; - struct ether_addr ea; - char eabuf[32]; - uint32 w32; - int woff, i; - char *vp, *base; - osl_t *osh = sb_osh(sbh); - bool flash = FALSE; - char name[SB_DEVPATH_BUFSZ+16], *value; - char devpath[SB_DEVPATH_BUFSZ]; - int err; - - /* - * Apply CRC over SROM content regardless SROM is present or not, - * and use variable <devpath>sromrev's existance in flash to decide - * if we should return an error when CRC fails or read SROM variables - * from flash. - */ - b = MALLOC(osh, SROM_MAX); - ASSERT(b); - if (!b) - return -2; - - err = sprom_read_pci(osh, (void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b, - 64, TRUE); - if (b[SROM4_SIGN] == SROM4_SIGNATURE) { - /* sromrev >= 4, read more */ - err = sprom_read_pci(osh, (void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b, SROM4_WORDS, TRUE); - sromrev = b[SROM4_WORDS - 1] & 0xff; - } else if (err == 0) { - /* srom is good and is rev < 4 */ - /* top word of sprom contains version and crc8 */ - sromrev = b[63] & 0xff; - /* bcm4401 sroms misprogrammed */ - if (sromrev == 0x10) - sromrev = 1; - } - - if (err) { -#ifdef WLTEST - BS_ERROR(("SROM Crc Error, so see if we could use a default\n")); - w32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); - if (w32 & SPROM_OTPIN_USE) { - BS_ERROR(("srom crc failed with OTP, use default vars....\n")); - vp = base = mfgsromvars; - if (sb_chip(sbh) == BCM4311_CHIP_ID) { - BS_ERROR(("setting the devid to be 4311\n")); - vp += sprintf(vp, "devid=0x4311"); - vp++; - } - bcopy(defaultsromvars, vp, MFGSROM_DEFVARSLEN); - vp += MFGSROM_DEFVARSLEN; - goto varsdone; - } else { - BS_ERROR(("srom crc failed with SPROM....\n")); -#endif /* WLTEST */ - if ((err = sb_devpath(sbh, devpath, sizeof(devpath)))) - return err; - sprintf(name, "%ssromrev", devpath); - if (!(value = getvar(NULL, name))) - return (-1); - sromrev = (uint8)bcm_strtoul(value, NULL, 0); - flash = TRUE; -#ifdef WLTEST - } -#endif /* WLTEST */ - } - /* srom version check */ - if (sromrev > 4) - return (-2); - - ASSERT(vars); - ASSERT(count); - - base = vp = MALLOC(osh, VARS_MAX); - ASSERT(vp); - if (!vp) - return -2; - - /* read variables from flash */ - if (flash) { - if ((err = initvars_flash(osh, &vp, VARS_MAX, devpath))) - goto err; - goto varsdone; - } - - vp += sprintf(vp, "sromrev=%d", sromrev); - vp++; - - if (sromrev >= 4) { - uint path, pathbase; - const uint pathbases[MAX_PATH] = {SROM4_PATH0, SROM4_PATH1, - SROM4_PATH2, SROM4_PATH3}; - - vp += sprintf(vp, "boardrev=%d", b[SROM4_BREV]); - vp++; - - vp += sprintf(vp, "boardflags=%d", (b[SROM4_BFL1] << 16) | b[SROM4_BFL0]); - vp++; - - vp += sprintf(vp, "boardflags2=%d", (b[SROM4_BFL3] << 16) | b[SROM4_BFL2]); - vp++; - - /* The macaddr */ - ea.octet[0] = (b[SROM4_MACHI] >> 8) & 0xff; - ea.octet[1] = b[SROM4_MACHI] & 0xff; - ea.octet[2] = (b[SROM4_MACMID] >> 8) & 0xff; - ea.octet[3] = b[SROM4_MACMID] & 0xff; - ea.octet[4] = (b[SROM4_MACLO] >> 8) & 0xff; - ea.octet[5] = b[SROM4_MACLO] & 0xff; - bcm_ether_ntoa(&ea, eabuf); - vp += sprintf(vp, "macaddr=%s", eabuf); - vp++; - - w = b[SROM4_CCODE]; - if (w == 0) - vp += sprintf(vp, "ccode="); - else - vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff)); - vp++; - vp += sprintf(vp, "regrev=%d", b[SROM4_REGREV]); - vp++; - - w = b[SROM4_LEDBH10]; - if ((w != 0) && (w != 0xffff)) { - /* ledbh0 */ - vp += sprintf(vp, "ledbh0=%d", (w & 0xff)); - vp++; - - /* ledbh1 */ - vp += sprintf(vp, "ledbh1=%d", (w >> 8) & 0xff); - vp++; - } - w = b[SROM4_LEDBH32]; - if ((w != 0) && (w != 0xffff)) { - /* ledbh2 */ - vp += sprintf(vp, "ledbh2=%d", w & 0xff); - vp++; - - /* ledbh3 */ - vp += sprintf(vp, "ledbh3=%d", (w >> 8) & 0xff); - vp++; - } - /* LED Powersave duty cycle (oncount >> 24) (offcount >> 8) */ - if (w != 0xffff) { - w = b[SROM4_LEDDC]; - w32 = ((uint32)((unsigned char)(w >> 8) & 0xff) << 24) | /* oncount */ - ((uint32)((unsigned char)(w & 0xff)) << 8); /* offcount */ - vp += sprintf(vp, "leddc=%d", w32); - vp++; - } - - w = b[SROM4_AA]; - vp += sprintf(vp, "aa2g=%d", w & SROM4_AA2G_MASK); - vp++; - vp += sprintf(vp, "aa5g=%d", w >> SROM4_AA5G_SHIFT); - vp++; - - w = b[SROM4_AG10]; - vp += sprintf(vp, "ag0=%d", w & 0xff); - vp++; - vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff); - vp++; - w = b[SROM4_AG32]; - vp += sprintf(vp, "ag2=%d", w & 0xff); - vp++; - vp += sprintf(vp, "ag3=%d", (w >> 8) & 0xff); - vp++; - - /* Fixed power indices when power control is disabled */ - for (i = 0; i < 2; i++) { - w = b[SROM4_TXPID2G + i]; - vp += sprintf(vp, "txpid2ga%d=%d", 2 * i, w & 0xff); - vp++; - vp += sprintf(vp, "txpid2ga%d=%d", (2 * i) + 1, (w >> 8) & 0xff); - vp++; - w = b[SROM4_TXPID5G + i]; - vp += sprintf(vp, "txpid5ga%d=%d", 2 * i, w & 0xff); - vp++; - vp += sprintf(vp, "txpid5ga%d=%d", (2 * i) + 1, (w >> 8) & 0xff); - vp++; - w = b[SROM4_TXPID5GL + i]; - vp += sprintf(vp, "txpid5gla%d=%d", 2 * i, w & 0xff); - vp++; - vp += sprintf(vp, "txpid5gla%d=%d", (2 * i) + 1, (w >> 8) & 0xff); - vp++; - w = b[SROM4_TXPID5GH + i]; - vp += sprintf(vp, "txpid5gha%d=%d", 2 * i, w & 0xff); - vp++; - vp += sprintf(vp, "txpid5gha%d=%d", (2 * i) + 1, (w >> 8) & 0xff); - vp++; - } +typedef struct +{ + const char *name; + uint32 revmask; + uint32 flags; + uint16 off; + uint16 mask; +} sromvar_t; + +#define SRFL_MORE 1 /* value continues as described by the next entry */ +#define SRFL_NOFFS 2 /* value bits can't be all one's */ +#define SRFL_PRHEX 4 /* value is in hexdecimal format */ +#define SRFL_PRSIGN 8 /* value is in signed decimal format */ +#define SRFL_CCODE 0x10 /* value is in country code format */ +#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ +#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ + +/* Assumptions: + * - Ethernet address spins across 3 consective words + * + * Table rules: + * - Add multiple entries next to each other if a value spins across multiple words + * (even multiple fields in the same word) with each entry except the last having + * it's SRFL_MORE bit set. + * - Ethernet address entry does not follow above rule and must not have SRFL_MORE + * bit set. Its SRFL_ETHADDR bit implies it takes multiple words. + * - The last entry's name field must be NULL to indicate the end of the table. Other + * entries must have non-NULL name. + */ - /* Per path variables */ - for (path = 0; path < MAX_PATH; path++) { - pathbase = pathbases[path]; - w = b[pathbase + SROM4_2G_ITT_MAXP]; - vp += sprintf(vp, "itt2ga%d=%d", path, w >> B2G_ITT_SHIFT); - vp++; - vp += sprintf(vp, "maxp2ga%d=%d", path, w & B2G_MAXP_MASK); - vp++; - - for (i = 0; i < 4; i++) { - vp += sprintf(vp, "pa2gw%da%d=%d", i, path, - b[pathbase + SROM4_2G_PA + i]); - vp++; - } +static const sromvar_t pci_sromvars[] = { + {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK}, + {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, + {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, + {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, + {"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff}, + {"", 0, 0, SROM_BFL2, 0xffff}, + {"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff}, + {"", 0, 0, SROM3_BFL2, 0xffff}, + {"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff}, + {"", 0, 0, SROM4_BFL1, 0xffff}, + {"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff}, + {"", 0, 0, SROM5_BFL1, 0xffff}, + {"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff}, + {"", 0, 0, SROM8_BFL1, 0xffff}, + {"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff}, + {"", 0, 0, SROM4_BFL3, 0xffff}, + {"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff}, + {"", 0, 0, SROM5_BFL3, 0xffff}, + {"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff}, + {"", 0, 0, SROM8_BFL3, 0xffff}, + {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, + {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, + {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff}, + {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff}, + {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff}, + {"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff}, + {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, + {"regrev", 0x00000008, 0, SROM_OPO, 0xff00}, + {"regrev", 0x00000010, 0, SROM4_REGREV, 0xff}, + {"regrev", 0x000000e0, 0, SROM5_REGREV, 0xff}, + {"regrev", 0xffffff00, 0, SROM8_REGREV, 0xff}, + {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff}, + {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, + {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff}, + {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, + {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff}, + {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, + {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff}, + {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, + {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff}, + {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, + {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff}, + {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, + {"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff}, + {"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, + {"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff}, + {"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, + {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, + {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, + {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, + {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0xff}, + {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff}, + {"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, + {"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, + {"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, + {"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, + {"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff}, + {"opo", 0x0000000c, 0, SROM_OPO, 0xff}, + {"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0xff}, + {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, + {"aa2g", 0x000000f0, 0, SROM4_AA, 0xff}, + {"aa2g", 0xffffff00, 0, SROM8_AA, 0xff}, + {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, + {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00}, + {"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00}, + {"ag0", 0x0000000e, 0, SROM_AG10, 0xff}, + {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00}, + {"ag0", 0x000000f0, 0, SROM4_AG10, 0xff}, + {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00}, + {"ag2", 0x000000f0, 0, SROM4_AG32, 0xff}, + {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00}, + {"ag0", 0xffffff00, 0, SROM8_AG10, 0xff}, + {"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00}, + {"ag2", 0xffffff00, 0, SROM8_AG32, 0xff}, + {"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00}, + {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, + {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, + {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, + {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, + {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, + {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, + {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, + {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, + {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, + {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00}, + {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, + {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, + {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff}, + {"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, + {"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, + {"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, + {"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, + {"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, + {"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, + {"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, + {"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, + {"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, + {"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, + {"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff}, + {"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, + {"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff}, + {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, + {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, + {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, + {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, + {"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, + {"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, + {"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, + {"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, + {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, + {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, + {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, + {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, + {"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, + {"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, + {"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, + {"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, + {"tri2g", 0x00000008, 0, SROM_TRI52G, 0xff}, + {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00}, + {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0xff}, + {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00}, + {"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0xff}, + {"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00}, + {"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0xff}, + {"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, + {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff}, + {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, + {"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff}, + {"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, + {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK}, + {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK}, + {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK}, + {"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK}, + {"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK}, + {"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK}, + {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0xff}, + {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, + {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff}, + {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00}, + {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0xff}, + {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, + {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff}, + {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00}, + {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0xff}, + {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, + {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff}, + {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00}, + {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0xff}, + {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, + {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff}, + {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00}, + {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, + {"cck2gpo", 0xffffff00, 0, SROM8_2G_CCKPO, 0xffff}, + {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, + {"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff}, + {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, + {"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff}, + {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, + {"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff}, + {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, + {"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff}, + {"ofdm2gpo", 0xffffff00, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, + {"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, + {"ofdm5gpo", 0xffffff00, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, + {"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, + {"ofdm5glpo", 0xffffff00, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, + {"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, + {"ofdm5ghpo", 0xffffff00, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, + {"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, + {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, + {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff}, + {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff}, + {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff}, + {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff}, + {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff}, + {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff}, + {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff}, + {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, + {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff}, + {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff}, + {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff}, + {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff}, + {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff}, + {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff}, + {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff}, + {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, + {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff}, + {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff}, + {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff}, + {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff}, + {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff}, + {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff}, + {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff}, + {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, + {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff}, + {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff}, + {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff}, + {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff}, + {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff}, + {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff}, + {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff}, + {"mcs2gpo0", 0xffffff00, 0, SROM8_2G_MCSPO, 0xffff}, + {"mcs2gpo1", 0xffffff00, 0, SROM8_2G_MCSPO + 1, 0xffff}, + {"mcs2gpo2", 0xffffff00, 0, SROM8_2G_MCSPO + 2, 0xffff}, + {"mcs2gpo3", 0xffffff00, 0, SROM8_2G_MCSPO + 3, 0xffff}, + {"mcs2gpo4", 0xffffff00, 0, SROM8_2G_MCSPO + 4, 0xffff}, + {"mcs2gpo5", 0xffffff00, 0, SROM8_2G_MCSPO + 5, 0xffff}, + {"mcs2gpo6", 0xffffff00, 0, SROM8_2G_MCSPO + 6, 0xffff}, + {"mcs2gpo7", 0xffffff00, 0, SROM8_2G_MCSPO + 7, 0xffff}, + {"mcs5gpo0", 0xffffff00, 0, SROM8_5G_MCSPO, 0xffff}, + {"mcs5gpo1", 0xffffff00, 0, SROM8_5G_MCSPO + 1, 0xffff}, + {"mcs5gpo2", 0xffffff00, 0, SROM8_5G_MCSPO + 2, 0xffff}, + {"mcs5gpo3", 0xffffff00, 0, SROM8_5G_MCSPO + 3, 0xffff}, + {"mcs5gpo4", 0xffffff00, 0, SROM8_5G_MCSPO + 4, 0xffff}, + {"mcs5gpo5", 0xffffff00, 0, SROM8_5G_MCSPO + 5, 0xffff}, + {"mcs5gpo6", 0xffffff00, 0, SROM8_5G_MCSPO + 6, 0xffff}, + {"mcs5gpo7", 0xffffff00, 0, SROM8_5G_MCSPO + 7, 0xffff}, + {"mcs5glpo0", 0xffffff00, 0, SROM8_5GL_MCSPO, 0xffff}, + {"mcs5glpo1", 0xffffff00, 0, SROM8_5GL_MCSPO + 1, 0xffff}, + {"mcs5glpo2", 0xffffff00, 0, SROM8_5GL_MCSPO + 2, 0xffff}, + {"mcs5glpo3", 0xffffff00, 0, SROM8_5GL_MCSPO + 3, 0xffff}, + {"mcs5glpo4", 0xffffff00, 0, SROM8_5GL_MCSPO + 4, 0xffff}, + {"mcs5glpo5", 0xffffff00, 0, SROM8_5GL_MCSPO + 5, 0xffff}, + {"mcs5glpo6", 0xffffff00, 0, SROM8_5GL_MCSPO + 6, 0xffff}, + {"mcs5glpo7", 0xffffff00, 0, SROM8_5GL_MCSPO + 7, 0xffff}, + {"mcs5ghpo0", 0xffffff00, 0, SROM8_5GH_MCSPO, 0xffff}, + {"mcs5ghpo1", 0xffffff00, 0, SROM8_5GH_MCSPO + 1, 0xffff}, + {"mcs5ghpo2", 0xffffff00, 0, SROM8_5GH_MCSPO + 2, 0xffff}, + {"mcs5ghpo3", 0xffffff00, 0, SROM8_5GH_MCSPO + 3, 0xffff}, + {"mcs5ghpo4", 0xffffff00, 0, SROM8_5GH_MCSPO + 4, 0xffff}, + {"mcs5ghpo5", 0xffffff00, 0, SROM8_5GH_MCSPO + 5, 0xffff}, + {"mcs5ghpo6", 0xffffff00, 0, SROM8_5GH_MCSPO + 6, 0xffff}, + {"mcs5ghpo7", 0xffffff00, 0, SROM8_5GH_MCSPO + 7, 0xffff}, + {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff}, + {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff}, + {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff}, + {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, + {"cddpo", 0xffffff00, 0, SROM8_CDDPO, 0xffff}, + {"stbcpo", 0xffffff00, 0, SROM8_STBCPO, 0xffff}, + {"bw40po", 0xffffff00, 0, SROM8_BW40PO, 0xffff}, + {"bwduppo", 0xffffff00, 0, SROM8_BWDUPPO, 0xffff}, + {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, + {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, + {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, + {"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, + {"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, + {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, + {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, + {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, + {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff}, + {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff}, + {"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff}, + {"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff}, + {"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff}, + {"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff}, + {NULL, 0, 0, 0, 0} +}; + +static const sromvar_t perpath_pci_sromvars[] = { + {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff}, + {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, + {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, + {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, + {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff}, + {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff}, + {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff}, + {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff}, + {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff}, + {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, + {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, + {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff}, + {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff}, + {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff}, + {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, + {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff}, + {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff}, + {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff}, + {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, + {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff}, + {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff}, + {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff}, + {"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff}, + {"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, + {"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, + {"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, + {"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, + {"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, + {"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff}, + {"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff}, + {"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, + {"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, + {"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, + {"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, + {"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, + {"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff}, + {"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff}, + {"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, + {"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff}, + {"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff}, + {NULL, 0, 0, 0, 0} +}; + +/* Parse SROM and create name=value pairs. 'srom' points to + * the SROM word array. 'off' specifies the offset of the + * first word 'srom' points to, which should be either 0 or + * SROM3_SWRG_OFF (full SROM or software region). + */ - w = b[pathbase + SROM4_5G_ITT_MAXP]; - vp += sprintf(vp, "itt5ga%d=%d", path, w >> B5G_ITT_SHIFT); - vp++; - vp += sprintf(vp, "maxp5ga%d=%d", path, w & B5G_MAXP_MASK); - vp++; - - w = b[pathbase + SROM4_5GLH_MAXP]; - vp += sprintf(vp, "maxp5lga%d=%d", path, w >> B5GL_MAXP_SHIFT); - vp++; - vp += sprintf(vp, "maxp5gha%d=%d", path, w & B5GH_MAXP_MASK); - vp++; - - for (i = 0; i < 4; i++) { - vp += sprintf(vp, "pa5gw%da%d=%d", i, path, - b[pathbase + SROM4_5G_PA + i]); - vp++; - vp += sprintf(vp, "pa5glw%da%d=%d", i, path, - b[pathbase + SROM4_5GL_PA + i]); - vp++; - vp += sprintf(vp, "pa5hgw%da%d=%d", i, path, - b[pathbase + SROM4_5GH_PA + i]); - vp++; - } - } +static uint +mask_shift (uint16 mask) +{ + uint i; + for (i = 0; i < (sizeof (mask) << 3); i++) + { + if (mask & (1 << i)) + return i; + } + ASSERT (mask); + return 0; +} - vp += sprintf(vp, "cck2gpo=%d", b[SROM4_2G_CCKPO]); - vp++; - - w32 = ((uint32)b[SROM4_2G_OFDMPO + 1] << 16) | b[SROM4_2G_OFDMPO]; - vp += sprintf(vp, "ofdm2gpo=%d", w32); - vp++; - - w32 = ((uint32)b[SROM4_5G_OFDMPO + 1] << 16) | b[SROM4_5G_OFDMPO]; - vp += sprintf(vp, "ofdm5gpo=%d", w32); - vp++; - - w32 = ((uint32)b[SROM4_5GL_OFDMPO + 1] << 16) | b[SROM4_5GL_OFDMPO]; - vp += sprintf(vp, "ofdm5glpo=%d", w32); - vp++; - - w32 = ((uint32)b[SROM4_5GH_OFDMPO + 1] << 16) | b[SROM4_5GH_OFDMPO]; - vp += sprintf(vp, "ofdm5ghpo=%d", w32); - vp++; - - for (i = 0; i < 8; i++) { - vp += sprintf(vp, "mcs2gpo%d=%d", i, b[SROM4_2G_MCSPO]); - vp++; - vp += sprintf(vp, "mcs5gpo%d=%d", i, b[SROM4_5G_MCSPO]); - vp++; - vp += sprintf(vp, "mcs5glpo%d=%d", i, b[SROM4_5GL_MCSPO]); - vp++; - vp += sprintf(vp, "mcs5ghpo%d=%d", i, b[SROM4_5GH_MCSPO]); - vp++; - } +static uint +mask_width (uint16 mask) +{ + int i; + for (i = (sizeof (mask) << 3) - 1; i >= 0; i--) + { + if (mask & (1 << i)) + return (uint) (i - mask_shift (mask) + 1); + } + ASSERT (mask); + return 0; +} - vp += sprintf(vp, "ccdpo%d=%d", i, b[SROM4_CCDPO]); - vp++; - vp += sprintf(vp, "stbcpo%d=%d", i, b[SROM4_STBCPO]); - vp++; - vp += sprintf(vp, "bw40po%d=%d", i, b[SROM4_BW40PO]); - vp++; - vp += sprintf(vp, "bwduppo%d=%d", i, b[SROM4_BWDUPPO]); - vp++; +#ifdef BCMDBG_ASSERT +static bool +mask_valid (uint16 mask) +{ + uint shift = mask_shift (mask); + uint width = mask_width (mask); + return mask == ((~0 << shift) & ~(~0 << (shift + width))); +} +#endif - goto done; +static void +_initvars_srom_pci (uint8 sromrev, uint16 * srom, uint off, varbuf_t * b) +{ + uint16 w; + uint32 val; + const sromvar_t *srv; + uint width; + uint flags; + uint32 sr = (1 << sromrev); + + varbuf_append (b, "sromrev=%d", sromrev); + + for (srv = pci_sromvars; srv->name != NULL; srv++) + { + const char *name; + + if ((srv->revmask & sr) == 0) + continue; + + if (srv->off < off) + continue; + + flags = srv->flags; + name = srv->name; + + if (flags & SRFL_ETHADDR) + { + char eabuf[ETHER_ADDR_STR_LEN]; + struct ether_addr ea; + + ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff; + ea.octet[1] = srom[srv->off - off] & 0xff; + ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff; + ea.octet[3] = srom[srv->off + 1 - off] & 0xff; + ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff; + ea.octet[5] = srom[srv->off + 2 - off] & 0xff; + bcm_ether_ntoa (&ea, eabuf); + + varbuf_append (b, "%s=%s", name, eabuf); } - if (sromrev >= 3) { - /* New section takes over the 3th hardware function space */ - - /* Words 22+23 are 11a (mid) ofdm power offsets */ - w32 = ((uint32)b[23] << 16) | b[22]; - vp += sprintf(vp, "ofdmapo=%d", w32); - vp++; - - /* Words 24+25 are 11a (low) ofdm power offsets */ - w32 = ((uint32)b[25] << 16) | b[24]; - vp += sprintf(vp, "ofdmalpo=%d", w32); - vp++; - - /* Words 26+27 are 11a (high) ofdm power offsets */ - w32 = ((uint32)b[27] << 16) | b[26]; - vp += sprintf(vp, "ofdmahpo=%d", w32); - vp++; - - /* LED Powersave duty cycle (oncount >> 24) (offcount >> 8) */ - w32 = ((uint32)((unsigned char)(b[21] >> 8) & 0xff) << 24) | /* oncount */ - ((uint32)((unsigned char)(b[21] & 0xff)) << 8); /* offcount */ - vp += sprintf(vp, "leddc=%d", w32); - - vp++; + else + { + ASSERT (mask_valid (srv->mask)); + ASSERT (mask_width (srv->mask)); + + w = srom[srv->off - off]; + val = (w & srv->mask) >> mask_shift (srv->mask); + width = mask_width (srv->mask); + + while (srv->flags & SRFL_MORE) + { + srv++; + ASSERT (srv->name); + + if (srv->off == 0 || srv->off < off) + continue; + + ASSERT (mask_valid (srv->mask)); + ASSERT (mask_width (srv->mask)); + + w = srom[srv->off - off]; + val += ((w & srv->mask) >> mask_shift (srv->mask)) << width; + width += mask_width (srv->mask); + } + + if ((flags & SRFL_NOFFS) && ((int) val == (1 << width) - 1)) + continue; + + if (flags & SRFL_CCODE) + { + if (val == 0) + varbuf_append (b, "ccode="); + else + varbuf_append (b, "ccode=%c%c", (val >> 8), (val & 0xff)); + } + /* LED Powersave duty cycle has to be scaled: + *(oncount >> 24) (offcount >> 8) + */ + else if (flags & SRFL_LEDDC) + { + uint32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */ + (((val & 0xff)) << 8); /* offcount */ + varbuf_append (b, "leddc=%d", w32); + } + else if (flags & SRFL_PRHEX) + varbuf_append (b, "%s=0x%x", name, val); + else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1)))) + varbuf_append (b, "%s=%d", name, (int) (val | (~0 << width))); + else + varbuf_append (b, "%s=%u", name, val); } + } - if (sromrev >= 2) { - /* New section takes over the 4th hardware function space */ - - /* Word 29 is max power 11a high/low */ - w = b[29]; - vp += sprintf(vp, "pa1himaxpwr=%d", w & 0xff); - vp++; - vp += sprintf(vp, "pa1lomaxpwr=%d", (w >> 8) & 0xff); - vp++; - - /* Words 30-32 set the 11alow pa settings, - * 33-35 are the 11ahigh ones. - */ - for (i = 0; i < 3; i++) { - vp += sprintf(vp, "pa1lob%d=%d", i, b[30 + i]); - vp++; - vp += sprintf(vp, "pa1hib%d=%d", i, b[33 + i]); - vp++; - } - w = b[59]; - if (w == 0) - vp += sprintf(vp, "ccode="); - else - vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff)); - vp++; + if (sromrev >= 4) + { + /* Do per-path variables */ + uint p, pb, psz; + if (sromrev >= 8) + { + pb = SROM8_PATH0; + psz = SROM8_PATH1 - SROM8_PATH0; } - - /* parameter section of sprom starts at byte offset 72 */ - woff = 72/2; - - /* first 6 bytes are il0macaddr */ - ea.octet[0] = (b[woff] >> 8) & 0xff; - ea.octet[1] = b[woff] & 0xff; - ea.octet[2] = (b[woff+1] >> 8) & 0xff; - ea.octet[3] = b[woff+1] & 0xff; - ea.octet[4] = (b[woff+2] >> 8) & 0xff; - ea.octet[5] = b[woff+2] & 0xff; - woff += 3; - bcm_ether_ntoa(&ea, eabuf); - vp += sprintf(vp, "il0macaddr=%s", eabuf); - vp++; - - /* next 6 bytes are et0macaddr */ - ea.octet[0] = (b[woff] >> 8) & 0xff; - ea.octet[1] = b[woff] & 0xff; - ea.octet[2] = (b[woff+1] >> 8) & 0xff; - ea.octet[3] = b[woff+1] & 0xff; - ea.octet[4] = (b[woff+2] >> 8) & 0xff; - ea.octet[5] = b[woff+2] & 0xff; - woff += 3; - bcm_ether_ntoa(&ea, eabuf); - vp += sprintf(vp, "et0macaddr=%s", eabuf); - vp++; - - /* next 6 bytes are et1macaddr */ - ea.octet[0] = (b[woff] >> 8) & 0xff; - ea.octet[1] = b[woff] & 0xff; - ea.octet[2] = (b[woff+1] >> 8) & 0xff; - ea.octet[3] = b[woff+1] & 0xff; - ea.octet[4] = (b[woff+2] >> 8) & 0xff; - ea.octet[5] = b[woff+2] & 0xff; - woff += 3; - bcm_ether_ntoa(&ea, eabuf); - vp += sprintf(vp, "et1macaddr=%s", eabuf); - vp++; - - /* - * Enet phy settings one or two singles or a dual - * Bits 4-0 : MII address for enet0 (0x1f for not there) - * Bits 9-5 : MII address for enet1 (0x1f for not there) - * Bit 14 : Mdio for enet0 - * Bit 15 : Mdio for enet1 - */ - w = b[woff]; - vp += sprintf(vp, "et0phyaddr=%d", (w & 0x1f)); - vp++; - vp += sprintf(vp, "et1phyaddr=%d", ((w >> 5) & 0x1f)); - vp++; - vp += sprintf(vp, "et0mdcport=%d", ((w >> 14) & 0x1)); - vp++; - vp += sprintf(vp, "et1mdcport=%d", ((w >> 15) & 0x1)); - vp++; - - /* Word 46 has board rev, antennas 0/1 & Country code/control */ - w = b[46]; - vp += sprintf(vp, "boardrev=%d", w & 0xff); - vp++; - - if (sromrev > 1) - vp += sprintf(vp, "cctl=%d", (w >> 8) & 0xf); - else - vp += sprintf(vp, "cc=%d", (w >> 8) & 0xf); - vp++; - - vp += sprintf(vp, "aa2g=%d", (w >> 12) & 0x3); - vp++; - - vp += sprintf(vp, "aa5g=%d", (w >> 14) & 0x3); - vp++; - - /* Words 47-49 set the (wl) pa settings */ - woff = 47; - - for (i = 0; i < 3; i++) { - vp += sprintf(vp, "pa0b%d=%d", i, b[woff+i]); - vp++; - vp += sprintf(vp, "pa1b%d=%d", i, b[woff+i+6]); - vp++; + else + { + pb = SROM4_PATH0; + psz = SROM4_PATH1 - SROM4_PATH0; } - /* - * Words 50-51 set the customer-configured wl led behavior. - * 8 bits/gpio pin. High bit: activehi=0, activelo=1; - * LED behavior values defined in wlioctl.h . - */ - w = b[50]; - if ((w != 0) && (w != 0xffff)) { - /* ledbh0 */ - vp += sprintf(vp, "ledbh0=%d", (w & 0xff)); - vp++; - - /* ledbh1 */ - vp += sprintf(vp, "ledbh1=%d", (w >> 8) & 0xff); - vp++; - } - w = b[51]; - if ((w != 0) && (w != 0xffff)) { - /* ledbh2 */ - vp += sprintf(vp, "ledbh2=%d", w & 0xff); - vp++; - - /* ledbh */ - vp += sprintf(vp, "ledbh3=%d", (w >> 8) & 0xff); - vp++; + for (p = 0; p < MAX_PATH; p++) + { + for (srv = perpath_pci_sromvars; srv->name != NULL; srv++) + { + if ((srv->revmask & sr) == 0) + continue; + + if (pb + srv->off < off) + continue; + + w = srom[pb + srv->off - off]; + ASSERT (mask_valid (srv->mask)); + val = (w & srv->mask) >> mask_shift (srv->mask); + width = mask_width (srv->mask); + + /* Cheating: no per-path var is more than 1 word */ + + if ((srv->flags & SRFL_NOFFS) + && ((int) val == (1 << width) - 1)) + continue; + + if (srv->flags & SRFL_PRHEX) + varbuf_append (b, "%s%d=0x%x", srv->name, p, val); + else + varbuf_append (b, "%s%d=%d", srv->name, p, val); + } + pb += psz; } + } +} - /* Word 52 is max power 0/1 */ - w = b[52]; - vp += sprintf(vp, "pa0maxpwr=%d", w & 0xff); - vp++; - vp += sprintf(vp, "pa1maxpwr=%d", (w >> 8) & 0xff); - vp++; - - /* Word 56 is idle tssi target 0/1 */ - w = b[56]; - vp += sprintf(vp, "pa0itssit=%d", w & 0xff); - vp++; - vp += sprintf(vp, "pa1itssit=%d", (w >> 8) & 0xff); - vp++; - - /* Word 57 is boardflags, if not programmed make it zero */ - w32 = (uint32)b[57]; - if (w32 == 0xffff) w32 = 0; - if (sromrev > 1) { - /* Word 28 is the high bits of boardflags */ - w32 |= (uint32)b[28] << 16; +static int +initvars_srom_pci (sb_t * sbh, void *curmap, char **vars, uint * count) +{ + uint16 *srom; + uint8 sromrev = 0; + uint32 sr; + varbuf_t b; + char *vp, *base = NULL; + osl_t *osh = sb_osh (sbh); + bool flash = FALSE; + char *value; + int err; + + /* + * Apply CRC over SROM content regardless SROM is present or not, + * and use variable <devpath>sromrev's existance in flash to decide + * if we should return an error when CRC fails or read SROM variables + * from flash. + */ + srom = MALLOC (osh, SROM_MAX); + ASSERT (srom); + if (!srom) + return -2; + + err = + sprom_read_pci (osh, (void *) ((int8 *) curmap + PCI_BAR0_SPROM_OFFSET), + 0, srom, SROM_WORDS, TRUE); + + if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || + ((sbh->buscoretype == SB_PCIE) && (sbh->buscorerev >= 6))) + { + /* sromrev >= 4, read more */ + err = + sprom_read_pci (osh, + (void *) ((int8 *) curmap + PCI_BAR0_SPROM_OFFSET), 0, + srom, SROM4_WORDS, TRUE); + sromrev = srom[SROM4_CRCREV] & 0xff; + } + else if (err == 0) + { + /* srom is good and is rev < 4 */ + /* top word of sprom contains version and crc8 */ + sromrev = srom[SROM_CRCREV] & 0xff; + /* bcm4401 sroms misprogrammed */ + if (sromrev == 0x10) + sromrev = 1; + } + + if (err) + { +#ifdef WLTEST + uint32 val; + + BS_ERROR (("SROM Crc Error, so see if we could use a default\n")); + val = OSL_PCI_READ_CONFIG (osh, PCI_SPROM_CONTROL, sizeof (uint32)); + if (val & SPROM_OTPIN_USE) + { + BS_ERROR (("srom crc failed with OTP, use default vars....\n")); + vp = base = mfgsromvars; + if (sb_chip (sbh) == BCM4311_CHIP_ID) + { + const char *devid = "devid=0x4311"; + const size_t devid_strlen = strlen (devid); + BS_ERROR (("setting the devid to be 4311\n")); + bcopy (devid, vp, devid_strlen + 1); + vp += devid_strlen + 1; + } + bcopy (defaultsromvars, vp, MFGSROM_DEFVARSLEN); + vp += MFGSROM_DEFVARSLEN; + goto varsdone; } - vp += sprintf(vp, "boardflags=%d", w32); - vp++; - - /* Word 58 is antenna gain 0/1 */ - w = b[58]; - vp += sprintf(vp, "ag0=%d", w & 0xff); - vp++; - - vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff); - vp++; - - if (sromrev == 1) { - /* set the oem string */ - vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x", - ((b[59] >> 8) & 0xff), (b[59] & 0xff), - ((b[60] >> 8) & 0xff), (b[60] & 0xff), - ((b[61] >> 8) & 0xff), (b[61] & 0xff), - ((b[62] >> 8) & 0xff), (b[62] & 0xff)); - vp++; - } else if (sromrev == 2) { - /* Word 60 OFDM tx power offset from CCK level */ - /* OFDM Power Offset - opo */ - vp += sprintf(vp, "opo=%d", b[60] & 0xff); - vp++; - } else { - /* Word 60: cck power offsets */ - vp += sprintf(vp, "cckpo=%d", b[60]); - vp++; - - /* Words 61+62: 11g ofdm power offsets */ - w32 = ((uint32)b[62] << 16) | b[61]; - vp += sprintf(vp, "ofdmgpo=%d", w32); - vp++; + else + { +#endif /* WLTEST */ + BS_ERROR (("srom crc failed with SPROM....\n")); + if (!(value = sb_getdevpathvar (sbh, "sromrev"))) + { + err = -1; + goto errout; + } + sromrev = (uint8) simple_strtoul (value, NULL, 0); + flash = TRUE; +#ifdef WLTEST } - - /* final nullbyte terminator */ -done: *vp++ = '\0'; - - ASSERT((vp - base) <= VARS_MAX); +#endif /* WLTEST */ + } + + /* Bitmask for the sromrev */ + sr = 1 << sromrev; + + /* srom version check + * Current valid versions: 1, 2, 3, 4, 5, 8 + */ + if ((sr & 0x13e) == 0) + { + err = -2; + goto errout; + } + + ASSERT (vars); + ASSERT (count); + + base = vp = MALLOC (osh, MAXSZ_NVRAM_VARS); + ASSERT (vp); + if (!vp) + { + err = -2; + goto errout; + } + + /* read variables from flash */ + if (flash) + { + if ((err = initvars_flash (sbh, osh, &vp, MAXSZ_NVRAM_VARS))) + goto errout; + goto varsdone; + } + + varbuf_init (&b, base, MAXSZ_NVRAM_VARS); + + /* parse SROM into name=value pairs. */ + _initvars_srom_pci (sromrev, srom, 0, &b); + + /* final nullbyte terminator */ + ASSERT (b.size >= 1); + vp = b.buf; + *vp++ = '\0'; + + ASSERT ((vp - base) <= MAXSZ_NVRAM_VARS); varsdone: - err = initvars_table(osh, base, vp, vars, count); + err = initvars_table (osh, base, vp, vars, count); -err: +errout: #ifdef WLTEST - if (base != mfgsromvars) + if (base && (base != mfgsromvars)) +#else + if (base) #endif - MFREE(osh, base, VARS_MAX); - MFREE(osh, b, SROM_MAX); - return err; + MFREE (osh, base, MAXSZ_NVRAM_VARS); + + MFREE (osh, srom, SROM_MAX); + return err; } /* @@ -1183,31 +1889,217 @@ err: * Return 0 on success, nonzero on error. */ static int -initvars_cis_pcmcia(void *sbh, osl_t *osh, char **vars, uint *count) +initvars_cis_pcmcia (sb_t * sbh, osl_t * osh, char **vars, uint * count) { - uint8 *cis = NULL; - int rc; - uint data_sz; + uint8 *cis = NULL; + int rc; + uint data_sz; + + data_sz = (sb_pcmciarev (sbh) == 1) ? (SPROM_SIZE * 2) : CIS_SIZE; + + if ((cis = MALLOC (osh, data_sz)) == NULL) + return (-2); + + if (sb_pcmciarev (sbh) == 1) + { + if (srom_read + (sbh, PCMCIA_BUS, (void *) NULL, osh, 0, data_sz, (uint16 *) cis)) + { + MFREE (osh, cis, data_sz); + return (-1); + } + /* fix up endianess for 16-bit data vs 8-bit parsing */ + htol16_buf ((uint16 *) cis, data_sz); + } + else + OSL_PCMCIA_READ_ATTR (osh, 0, cis, data_sz); + + rc = srom_parsecis (osh, &cis, 1, vars, count); - data_sz = (sb_pcmciarev(sbh) == 1) ? (SPROM_SIZE * 2) : CIS_SIZE; + MFREE (osh, cis, data_sz); - if ((cis = MALLOC(osh, data_sz)) == NULL) - return (-2); + return (rc); +} + + +static int +BCMINITFN (initvars_srom_sb) (sb_t * sbh, osl_t * osh, void *curmap, + char **vars, uint * varsz) +{ +#if defined(BCMSDIODEV) + /* CIS is read and supplied by the host */ + return BCME_OK; +#elif defined(BCMUSBDEV) + static bool srvars = FALSE; /* Use OTP/SPROM as global variables */ + + int sel = 0; /* where to read the srom. 0 - nowhere, 1 - otp, 2 - sprom */ + uint sz = 0; /* srom size in bytes */ + void *oh = NULL; + int rc = BCME_OK; + + /* Bail out if we've dealt with OTP/SPROM before! */ + if (srvars) + return 0; + +#if defined(BCM4328) + if (sbh->chip == BCM4328_CHIP_ID) + { + /* Access the SPROM if it is present */ + if ((sz = srom_size (sbh, osh)) != 0) + { + sz <<= 1; + sel = 2; + } + } +#endif +#if defined(BCM4325) + if (sbh->chip == BCM4325_CHIP_ID) + { + uint32 cst = sbh->chipst & CST4325_SPROM_OTP_SEL_MASK; + + /* Access OTP if it is present, powered on, and programmed */ + if ((oh = otp_init (sbh)) != NULL && (otp_status (oh) & OTPS_GUP_SW)) + { + sz = otp_size (oh); + sel = 1; + } + /* Access the SPROM if it is present and allow to be accessed */ + else if ((cst == CST4325_OTP_PWRDN || cst == CST4325_SPROM_SEL) && + (sz = srom_size (sbh, osh)) != 0) + { + sz <<= 1; + sel = 2; + } + } +#endif /* BCM4325 */ + + /* Read CIS in OTP/SPROM */ + if (sel != 0) + { + uint16 *srom; + uint8 *body = NULL; + + ASSERT (sz); + + /* Allocate memory */ + if ((srom = (uint16 *) MALLOC (osh, sz)) == NULL) + return BCME_NOMEM; + + /* Read CIS */ + switch (sel) + { + case 1: + rc = otp_read_region (oh, OTP_SW_RGN, srom, sz); + body = (uint8 *) srom; + break; + case 2: + rc = srom_read (sbh, SB_BUS, curmap, osh, 0, sz, srom); + /* sprom has 8 byte h/w header */ + body = (uint8 *) srom + SBSDIO_SPROM_CIS_OFFSET; + break; + default: + /* impossible to come here */ + ASSERT (0); + break; + } - if (sb_pcmciarev(sbh) == 1) { - if (srom_read(PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis)) { - MFREE(osh, cis, data_sz); - return (-1); + /* Parse CIS */ + if (rc == BCME_OK) + { + uint i, tpls = 0xffffffff; + /* # sdiod fns + common + extra */ + uint8 *cis[SBSDIO_NUM_FUNCTION + 2]; + uint ciss = 0; + + /* each word is in host endian */ + htol16_buf ((uint8 *) srom, sz); + + ASSERT (body); + + /* count cis tuple chains */ + for (i = 0; i < sz && ciss < ARRAYSIZE (cis) && tpls != 0; i++) + { + cis[ciss++] = &body[i]; + for (tpls = 0; i < sz - 1; tpls++) + { + if (body[i++] == CISTPL_END) + break; + i += body[i] + 1; } - /* fix up endianess for 16-bit data vs 8-bit parsing */ - ltoh16_buf((uint16 *)cis, data_sz); - } else - OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz); + } - rc = srom_parsecis(osh, &cis, 1, vars, count); + /* call parser routine only when there are tuple chains */ + if (ciss > 1) + rc = srom_parsecis (osh, cis, ciss, vars, varsz); + } + + /* Clean up */ + MFREE (osh, srom, sz); - MFREE(osh, cis, data_sz); + /* Make SROM variables global */ + if (rc == BCME_OK) + { + rc = nvram_append ((void *) sbh, *vars, *varsz); + srvars = TRUE; - return (rc); + /* Tell the caller there is no individual SROM variables */ + *vars = NULL; + *varsz = 0; + } + } + + return rc; +#else /* !BCMUSBDEV && !BCMSDIODEV */ + /* Search flash nvram section for srom variables */ + return initvars_flash_sb (sbh, vars, varsz); +#endif /* !BCMUSBDEV && !BCMSDIODEV */ } +#ifdef BCMUSBDEV +/* Return sprom size in 16-bit words */ +static uint +srom_size (sb_t * sbh, osl_t * osh) +{ + uint size = 0; + if (SPROMBUS == PCMCIA_BUS) + { + uint32 origidx; + sdpcmd_regs_t *pcmregs; + bool wasup; + + origidx = sb_coreidx (sbh); + pcmregs = sb_setcore (sbh, SB_PCMCIA, 0); + ASSERT (pcmregs); + + if (!(wasup = sb_iscoreup (sbh))) + sb_core_reset (sbh, 0, 0); + + /* not worry about earlier core revs */ + if (sb_corerev (sbh) < 8) + goto done; + + /* SPROM is accessible only in PCMCIA mode unless there is SDIO clock */ + if (!(R_REG (osh, &pcmregs->corestatus) & CS_PCMCIAMODE)) + goto done; + + switch (SB_PCMCIA_READ (osh, pcmregs, SROM_INFO) & SRI_SZ_MASK) + { + case 1: + size = 256; /* SROM_INFO == 1 means 4kbit */ + break; + case 2: + size = 1024; /* SROM_INFO == 2 means 16kbit */ + break; + default: + break; + } + + done: + if (!wasup) + sb_core_disable (sbh, 0); + + sb_setcoreidx (sbh, origidx); + } + return size; +} +#endif /* def BCMUSBDEV */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmutils.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmutils.c deleted file mode 100644 index c7b0b3d3c8..0000000000 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmutils.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Misc useful OS-independent routines. - * - * Copyright 2006, Broadcom Corporation - * All Rights Reserved. - * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * $Id: bcmutils.c,v 1.1.1.12 2006/02/27 03:43:16 honor Exp $ - */ - -#include <typedefs.h> -#include <bcmdefs.h> -#include <stdarg.h> -#include <bcmutils.h> -#include <osl.h> -#include <sbutils.h> -#include <bcmnvram.h> -#include <bcmendian.h> -#include <bcmdevs.h> - -unsigned char bcm_ctype[] = { - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ - _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 */ - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ - _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ - _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ - _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ - _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ - _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 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ - _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 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ - _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 */ - _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 */ - _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 */ - _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 */ - _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 */ - _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 */ -}; - - -ulong -bcm_strtoul(char *cp, char **endp, uint base) -{ - ulong result, value; - bool minus; - - minus = FALSE; - - while (bcm_isspace(*cp)) - cp++; - - if (cp[0] == '+') - cp++; - else if (cp[0] == '-') { - minus = TRUE; - cp++; - } - - if (base == 0) { - if (cp[0] == '0') { - if ((cp[1] == 'x') || (cp[1] == 'X')) { - base = 16; - cp = &cp[2]; - } else { - base = 8; - cp = &cp[1]; - } - } else - base = 10; - } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { - cp = &cp[2]; - } - - result = 0; - - while (bcm_isxdigit(*cp) && - (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - - if (minus) - result = (ulong)(result * -1); - - if (endp) - *endp = (char *)cp; - - return (result); -} - -uchar -bcm_toupper(uchar c) -{ - if (bcm_islower(c)) - c -= 'a'-'A'; - return (c); -} - -char* -bcm_ether_ntoa(struct ether_addr *ea, char *buf) -{ - sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", - ea->octet[0]&0xff, ea->octet[1]&0xff, ea->octet[2]&0xff, - ea->octet[3]&0xff, ea->octet[4]&0xff, ea->octet[5]&0xff); - return (buf); -} - - -/* - * Search the name=value vars for a specific one and return its value. - * Returns NULL if not found. - */ -char* -getvar(char *vars, char *name) -{ - char *s; - int len; - - len = strlen(name); - - /* first look in vars[] */ - for (s = vars; s && *s;) { - /* CSTYLED */ - if ((memcmp(s, name, len) == 0) && (s[len] == '=')) - return (&s[len+1]); - - while (*s++) - ; - } - - /* then query nvram */ - return (nvram_get(name)); -} - -/* - * Search the vars for a specific one and return its value as - * an integer. Returns 0 if not found. - */ -int -getintvar(char *vars, char *name) -{ - char *val; - - if ((val = getvar(vars, name)) == NULL) - return (0); - - return (bcm_strtoul(val, NULL, 0)); -} - - -/******************************************************************************* - * crc8 - * - * Computes a crc8 over the input data using the polynomial: - * - * x^8 + x^7 +x^6 + x^4 + x^2 + 1 - * - * The caller provides the initial value (either CRC8_INIT_VALUE - * or the previous returned value) to allow for processing of - * discontiguous blocks of data. When generating the CRC the - * caller is responsible for complementing the final return value - * and inserting it into the byte stream. When checking, a final - * return value of CRC8_GOOD_VALUE indicates a valid CRC. - * - * Reference: Dallas Semiconductor Application Note 27 - * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", - * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., - * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt - * - * **************************************************************************** - */ - -static uint8 crc8_table[256] = { - 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, - 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, - 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, - 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, - 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, - 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, - 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, - 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, - 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, - 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, - 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, - 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, - 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, - 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, - 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, - 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, - 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, - 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, - 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, - 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, - 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, - 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, - 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, - 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, - 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, - 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, - 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, - 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, - 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, - 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, - 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, - 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F -}; - -#define CRC_INNER_LOOP(n, c, x) \ - (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] - -uint8 -hndcrc8( - uint8 *pdata, /* pointer to array of data to process */ - uint nbytes, /* number of input data bytes to process */ - uint8 crc /* either CRC8_INIT_VALUE or previous return value */ -) -{ - /* hard code the crc loop instead of using CRC_INNER_LOOP macro - * to avoid the undefined and unnecessary (uint8 >> 8) operation. - */ - while (nbytes-- > 0) - crc = crc8_table[(crc ^ *pdata++) & 0xff]; - - return crc; -} - - diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/cfe_env.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/cfe_env.c new file mode 100644 index 0000000000..9dd4eeeb31 --- /dev/null +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/cfe_env.c @@ -0,0 +1,233 @@ +/* + * NVRAM variable manipulation (Linux kernel half) + * + * Copyright 2001-2003, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id$ + */ + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <asm/io.h> +#include <asm/uaccess.h> + +#include <typedefs.h> +#include <osl.h> +#include <bcmendian.h> + +#define NVRAM_SIZE (0x1ff0) +static char _nvdata[NVRAM_SIZE] __initdata; +static char _valuestr[256] __initdata; + +/* + * TLV types. These codes are used in the "type-length-value" + * encoding of the items stored in the NVRAM device (flash or EEPROM) + * + * The layout of the flash/nvram is as follows: + * + * <type> <length> <data ...> <type> <length> <data ...> <type_end> + * + * The type code of "ENV_TLV_TYPE_END" marks the end of the list. + * The "length" field marks the length of the data section, not + * including the type and length fields. + * + * Environment variables are stored as follows: + * + * <type_env> <length> <flags> <name> = <value> + * + * If bit 0 (low bit) is set, the length is an 8-bit value. + * If bit 0 (low bit) is clear, the length is a 16-bit value + * + * Bit 7 set indicates "user" TLVs. In this case, bit 0 still + * indicates the size of the length field. + * + * Flags are from the constants below: + * + */ +#define ENV_LENGTH_16BITS 0x00 /* for low bit */ +#define ENV_LENGTH_8BITS 0x01 + +#define ENV_TYPE_USER 0x80 + +#define ENV_CODE_SYS(n,l) (((n)<<1)|(l)) +#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER) + +/* + * The actual TLV types we support + */ + +#define ENV_TLV_TYPE_END 0x00 +#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS) + +/* + * Environment variable flags + */ + +#define ENV_FLG_NORMAL 0x00 /* normal read/write */ +#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */ +#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */ + +#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */ +#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */ + + +/* ********************************************************************* + * _nvram_read(buffer,offset,length) + * + * Read data from the NVRAM device + * + * Input parameters: + * buffer - destination buffer + * offset - offset of data to read + * length - number of bytes to read + * + * Return value: + * number of bytes read, or <0 if error occured + ********************************************************************* */ +static int +_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length) +{ + int i; + if (offset > NVRAM_SIZE) + return -1; + + for ( i = 0; i < length; i++) { + buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i]; + } + return length; +} + + +static char* +_strnchr(const char *dest,int c,size_t cnt) +{ + while (*dest && (cnt > 0)) { + if (*dest == c) return (char *) dest; + dest++; + cnt--; + } + return NULL; +} + + + +/* + * Core support API: Externally visible. + */ + +/* + * Get the value of an NVRAM variable + * @param name name of variable to get + * @return value of variable or NULL if undefined + */ + +char* +cfe_env_get(unsigned char *nv_buf, char* name) +{ + int size; + unsigned char *buffer; + unsigned char *ptr; + unsigned char *envval; + unsigned int reclen; + unsigned int rectype; + int offset; + int flg; + + size = NVRAM_SIZE; + buffer = &_nvdata[0]; + + ptr = buffer; + offset = 0; + + /* Read the record type and length */ + if (_nvram_read(nv_buf, ptr,offset,1) != 1) { + goto error; + } + + while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) { + + /* Adjust pointer for TLV type */ + rectype = *(ptr); + offset++; + size--; + + /* + * Read the length. It can be either 1 or 2 bytes + * depending on the code + */ + if (rectype & ENV_LENGTH_8BITS) { + /* Read the record type and length - 8 bits */ + if (_nvram_read(nv_buf, ptr,offset,1) != 1) { + goto error; + } + reclen = *(ptr); + size--; + offset++; + } + else { + /* Read the record type and length - 16 bits, MSB first */ + if (_nvram_read(nv_buf, ptr,offset,2) != 2) { + goto error; + } + reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1); + size -= 2; + offset += 2; + } + + if (reclen > size) + break; /* should not happen, bad NVRAM */ + + switch (rectype) { + case ENV_TLV_TYPE_ENV: + /* Read the TLV data */ + if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen) + goto error; + flg = *ptr++; + envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1)); + if (envval) { + *envval++ = '\0'; + memcpy(_valuestr,envval,(reclen-1)-(envval-ptr)); + _valuestr[(reclen-1)-(envval-ptr)] = '\0'; +#if 0 + printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr); +#endif + if(!strcmp(ptr, name)){ + return _valuestr; + } + if((strlen(ptr) > 1) && !strcmp(&ptr[1], name)) + return _valuestr; + } + break; + + default: + /* Unknown TLV type, skip it. */ + break; + } + + /* + * Advance to next TLV + */ + + size -= (int)reclen; + offset += reclen; + + /* Read the next record type */ + ptr = buffer; + if (_nvram_read(nv_buf, ptr,offset,1) != 1) + goto error; + } + +error: + return NULL; + +} + diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/compressed/Makefile b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/compressed/Makefile deleted file mode 100644 index 2942c8eb34..0000000000 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/compressed/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# Makefile for Broadcom BCM947XX boards -# -# Copyright 2001-2003, Broadcom Corporation -# All Rights Reserved. -# -# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -# -# $Id: Makefile,v 1.2 2005/04/02 12:12:57 wbx Exp $ -# - -OBJCOPY_ARGS = -O binary -R .reginfo -R .note -R .comment -R .mdebug -S -SYSTEM ?= $(TOPDIR)/vmlinux - -all: vmlinuz - -# Don't build dependencies, this may die if $(CC) isn't gcc -dep: - -# Create a gzipped version named vmlinuz for compatibility -vmlinuz: piggy - gzip -c9 $< > $@ - -piggy: $(SYSTEM) - $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ - -mrproper: clean - -clean: - rm -f vmlinuz piggy diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/export.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/export.c index 9da9572aba..ff3e031978 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/export.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/export.c @@ -6,8 +6,10 @@ _export(bcm947xx_sbh) +_export(sb_alp_clock) _export(sb_attach) _export(sb_kattach) +_export(sb_backplane64) _export(sb_boardtype) _export(sb_boardvendor) _export(sb_btcgpiowar) @@ -24,6 +26,7 @@ _export(sb_core_disable) _export(sb_core_reset) _export(sb_core_tofixup) _export(sb_coreflags) +_export(sb_coreflags_wo) _export(sb_coreflagshi) _export(sb_coreidx) _export(sb_coreregs) @@ -39,26 +42,30 @@ _export(sb_gpioled) _export(sb_gpioin) _export(sb_gpioout) _export(sb_gpioouten) +_export(sb_gpiopull) _export(sb_gpiotimerval) _export(sb_irq) _export(sb_iscoreup) _export(sb_pci_setup) +_export(sb_pci_sleep) +_export(sb_pci_down) +_export(sb_pci_up) _export(sb_pcirev) _export(sb_pcmcia_init) _export(sb_pcmciarev) +_export(sb_pmu_paref_ldo_enable) +_export(sb_pmu_rcal) +_export(sb_pmu_set_ldo_voltage) +_export(sb_deregister_intr_callback) _export(sb_register_intr_callback) _export(sb_setcore) _export(sb_setcoreidx) _export(sb_war16165) -_export(sb_war32414_forceHT) +_export(sb_war42780_clkreq) _export(sb_osh) - + _export(getvar) _export(getintvar) -_export(bcm_strtoul) -_export(bcm_ctype) -_export(bcm_toupper) -_export(bcm_ether_ntoa) _export(nvram_get) _export(nvram_getall) diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/gpio.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/gpio.c index c31f58bac6..37b41e1ec3 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/gpio.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/gpio.c @@ -20,7 +20,6 @@ #include <typedefs.h> #include <osl.h> -#include <bcmutils.h> #include <sbutils.h> #include <bcmdevs.h> @@ -122,7 +121,7 @@ gpio_init(void) { int i; - if (!(gpio_sbh = sb_kattach())) + if (!(gpio_sbh = sb_kattach(SB_OSH))) return -ENODEV; sb_gpiosetcore(gpio_sbh); diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c index 6502078de1..1f1dc10efa 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndchipc.c @@ -1,7 +1,7 @@ /* - * BCM47XX support code for some chipcommon (old extif) facilities (uart) + * BCM47XX support code for some chipcommon facilities (uart, jtagm) * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,28 +9,52 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: hndchipc.c,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #include <typedefs.h> #include <bcmdefs.h> #include <osl.h> -#include <bcmutils.h> #include <sbutils.h> #include <bcmdevs.h> #include <bcmnvram.h> #include <sbconfig.h> -#include <sbextif.h> #include <sbchipc.h> +#include <sbextif.h> +#include <hndchipc.h> #include <hndcpu.h> -/* - * Returns TRUE if an external UART exists at the given base - * register. +/* debug/trace */ +#define CC_ERROR(args) + +#ifdef BCMDBG +#define CC_MSG(args) printf args +#else +#define CC_MSG(args) +#endif /* BCMDBG */ + +/* interested chipcommon interrupt source + * - GPIO + * - EXTIF + * - ECI + * - PMU + * - UART */ -static bool -BCMINITFN(serial_exists)(osl_t *osh, uint8 *regs) -{ +#define MAX_CC_INT_SOURCE 5 + +/* chipc secondary isr info */ +typedef struct { + uint intmask; /* int mask */ + cc_isr_fn isr; /* secondary isr handler */ + void *cbdata; /* pointer to private data */ +} cc_isr_info_t; + +static cc_isr_info_t cc_isr_desc[MAX_CC_INT_SOURCE]; + +/* chip common intmask */ +static uint32 cc_intmask = 0; + +static bool BCMINITFN(serial_exists) (osl_t * osh, uint8 * regs) { uint8 save_mcr, status1; save_mcr = R_REG(osh, ®s[UART_MCR]); @@ -41,118 +65,276 @@ BCMINITFN(serial_exists)(osl_t *osh, uint8 *regs) return (status1 == 0x90); } +static void __init sb_extif_serial_init(sb_t * sbh, void *regs, + sb_serial_init_fn add) +{ + osl_t *osh = sb_osh(sbh); + extifregs_t *eir = (extifregs_t *) regs; + sbconfig_t *sb; + ulong base; + uint irq; + int i, n; + + /* Determine external UART register base */ + sb = (sbconfig_t *) ((ulong) eir + SBCONFIGOFF); + base = EXTIF_CFGIF_BASE(sb_base(R_REG(osh, &sb->sbadmatch1))); + + /* Determine IRQ */ + irq = sb_irq(sbh); + + /* Disable GPIO interrupt initially */ + W_REG(osh, &eir->gpiointpolarity, 0); + W_REG(osh, &eir->gpiointmask, 0); + + /* Search for external UARTs */ + n = 2; + for (i = 0; i < 2; i++) { + regs = (void *)REG_MAP(base + (i * 8), 8); + if (serial_exists(osh, regs)) { + /* Set GPIO 1 to be the external UART IRQ */ + W_REG(osh, &eir->gpiointmask, 2); + /* XXXDetermine external UART clock */ + if (add) + add(regs, irq, 13500000, 0); + } + } + + /* Add internal UART if enabled */ + if (R_REG(osh, &eir->corecontrol) & CC_UE) + if (add) + add((void *)&eir->uartdata, irq, sb_clock(sbh), 2); +} + /* * Initializes UART access. The callback function will be called once * per found UART. */ -void -BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, - uint reg_shift)) -{ +void BCMINITFN(sb_serial_init) (sb_t * sbh, sb_serial_init_fn add) { osl_t *osh; void *regs; - ulong base; + chipcregs_t *cc; + uint32 rev, cap, pll, baud_base, div; uint irq; int i, n; osh = sb_osh(sbh); - if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) { - extifregs_t *eir = (extifregs_t *) regs; - sbconfig_t *sb; - - /* Determine external UART register base */ - sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF); - base = EXTIF_CFGIF_BASE(sb_base(R_REG(osh, &sb->sbadmatch1))); - - /* Determine IRQ */ - irq = sb_irq(sbh); - - /* Disable GPIO interrupt initially */ - W_REG(osh, &eir->gpiointpolarity, 0); - W_REG(osh, &eir->gpiointmask, 0); - - /* Search for external UARTs */ - n = 2; - for (i = 0; i < 2; i++) { - regs = (void *) REG_MAP(base + (i * 8), 8); - if (serial_exists(osh, regs)) { - /* Set GPIO 1 to be the external UART IRQ */ - W_REG(osh, &eir->gpiointmask, 2); - /* XXXDetermine external UART clock */ - if (add) - add(regs, irq, 13500000, 0); - } - } + regs = sb_setcore(sbh, SB_EXTIF, 0); + if (regs) { + sb_extif_serial_init(sbh, regs, add); + return; + } - /* Add internal UART if enabled */ - if (R_REG(osh, &eir->corecontrol) & CC_UE) - if (add) - add((void *) &eir->uartdata, irq, sb_clock(sbh), 2); - } else if ((regs = sb_setcore(sbh, SB_CC, 0))) { - chipcregs_t *cc = (chipcregs_t *) regs; - uint32 rev, cap, pll, baud_base, div; + cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); + ASSERT(cc); - /* Determine core revision and capabilities */ - rev = sb_corerev(sbh); - cap = R_REG(osh, &cc->capabilities); - pll = cap & CAP_PLL_MASK; + /* Determine core revision and capabilities */ + rev = sbh->ccrev; + cap = sbh->cccaps; + pll = cap & CC_CAP_PLL_MASK; - /* Determine IRQ */ - irq = sb_irq(sbh); + /* Determine IRQ */ + irq = sb_irq(sbh); - if (pll == PLL_TYPE1) { - /* PLL clock */ - baud_base = sb_clock_rate(pll, - R_REG(osh, &cc->clockcontrol_n), - R_REG(osh, &cc->clockcontrol_m2)); - div = 1; - } else { + if (pll == PLL_TYPE1) { + /* PLL clock */ + baud_base = sb_clock_rate(pll, + R_REG(osh, &cc->clockcontrol_n), + R_REG(osh, &cc->clockcontrol_m2)); + div = 1; + } else { + /* 5354 chip common uart uses a constant clock + * frequency of 25MHz */ + if (sb_corerev(sbh) == 20) { + /* Set the override bit so we don't divide it */ + W_REG(osh, &cc->corecontrol, CC_UARTCLKO); + baud_base = 25000000; + } else if (rev >= 11 && rev != 15) { /* Fixed ALP clock */ - if (rev >= 11 && rev != 15) { - baud_base = 20000000; - div = 1; - /* Set the override bit so we don't divide it */ - W_REG(osh, &cc->corecontrol, CC_UARTCLKO); - } + baud_base = sb_alp_clock(sbh); + div = 1; + /* Turn off UART clock before switching clock source */ + if (rev >= 21) + AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN); + /* Set the override bit so we don't divide it */ + OR_REG(osh, &cc->corecontrol, CC_UARTCLKO); + if (rev >= 21) + OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN); + } else if (rev >= 3) { /* Internal backplane clock */ - else if (rev >= 3) { - baud_base = sb_clock(sbh); - div = 2; /* Minimum divisor */ - W_REG(osh, &cc->clkdiv, - ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div)); - } + baud_base = sb_clock(sbh); + div = 2; /* Minimum divisor */ + W_REG(osh, &cc->clkdiv, + ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div)); + } else { /* Fixed internal backplane clock */ - else { - baud_base = 88000000; - div = 48; - } + baud_base = 88000000; + div = 48; + } - /* Clock source depends on strapping if UartClkOverride is unset */ - if ((rev > 0) && - ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) { - if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) { - /* Internal divided backplane clock */ - baud_base /= div; - } else { - /* Assume external clock of 1.8432 MHz */ - baud_base = 1843200; - } + /* Clock source depends on strapping if UartClkOverride is unset */ + if ((rev > 0) + && ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) { + if ((cap & CC_CAP_UCLKSEL) == CC_CAP_UINTCLK) { + /* Internal divided backplane clock */ + baud_base /= div; + } else { + /* Assume external clock of 1.8432 MHz */ + baud_base = 1843200; } } + } - /* Add internal UARTs */ - n = cap & CAP_UARTS_MASK; - for (i = 0; i < n; i++) { - /* Register offset changed after revision 0 */ - if (rev) - regs = (void *)((ulong) &cc->uart0data + (i * 256)); - else - regs = (void *)((ulong) &cc->uart0data + (i * 8)); + /* Add internal UARTs */ + n = cap & CC_CAP_UARTS_MASK; + for (i = 0; i < n; i++) { + /* Register offset changed after revision 0 */ + if (rev) + regs = (void *)((ulong) & cc->uart0data + (i * 256)); + else + regs = (void *)((ulong) & cc->uart0data + (i * 8)); - if (add) - add(regs, irq, baud_base, 0); + if (add) + add(regs, irq, baud_base, 0); + } +} + +#if 0 +/* + * Initialize jtag master and return handle for + * jtag_rwreg. Returns NULL on failure. + */ +void *sb_jtagm_init(sb_t * sbh, uint clkd, bool exttap) +{ + void *regs; + + if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) { + chipcregs_t *cc = (chipcregs_t *) regs; + uint32 tmp; + + /* + * Determine jtagm availability from + * core revision and capabilities. + */ + + /* + * Corerev 10 has jtagm, but the only chip + * with it does not have a mips, and + * the layout of the jtagcmd register is + * different. We'll only accept >= 11. + */ + if (sbh->ccrev < 11) + return (NULL); + + if ((sbh->cccaps & CC_CAP_JTAGP) == 0) + return (NULL); + + /* Set clock divider if requested */ + if (clkd != 0) { + tmp = R_REG(osh, &cc->clkdiv); + tmp = + (tmp & ~CLKD_JTAG) | ((clkd << CLKD_JTAG_SHIFT) & + CLKD_JTAG); + W_REG(osh, &cc->clkdiv, tmp); } + + /* Enable jtagm */ + tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0); + W_REG(osh, &cc->jtagctrl, tmp); } + + return (regs); +} + +void sb_jtagm_disable(osl_t * osh, void *h) +{ + chipcregs_t *cc = (chipcregs_t *) h; + + W_REG(osh, &cc->jtagctrl, R_REG(osh, &cc->jtagctrl) & ~JCTRL_EN); } +/* + * Read/write a jtag register. Assumes a target with + * 8 bit IR and 32 bit DR. + */ +#define IRWIDTH 8 /* Default Instruction Register width */ +#define DRWIDTH 32 /* Default Data Register width */ + +uint32 jtag_rwreg(osl_t * osh, void *h, uint32 ir, uint32 dr) +{ + chipcregs_t *cc = (chipcregs_t *) h; + uint32 tmp; + + W_REG(osh, &cc->jtagir, ir); + W_REG(osh, &cc->jtagdr, dr); + tmp = JCMD_START | JCMD_ACC_IRDR | + ((IRWIDTH - 1) << JCMD_IRW_SHIFT) | (DRWIDTH - 1); + W_REG(osh, &cc->jtagcmd, tmp); + while (((tmp = R_REG(osh, &cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) { + /* OSL_DELAY(1); */ + } + + tmp = R_REG(osh, &cc->jtagdr); + return (tmp); +} +#endif + +/* + * Interface to register chipc secondary isr + */ +bool +BCMINITFN(sb_cc_register_isr) (sb_t * sbh, cc_isr_fn isr, uint32 ccintmask, + void *cbdata) { + bool done = FALSE; + chipcregs_t *regs; + uint origidx; + uint i; + + /* Save the current core index */ + origidx = sb_coreidx(sbh); + regs = sb_setcore(sbh, SB_CC, 0); + ASSERT(regs); + + for (i = 0; i < MAX_CC_INT_SOURCE; i++) { + if (cc_isr_desc[i].isr == NULL) { + cc_isr_desc[i].isr = isr; + cc_isr_desc[i].cbdata = cbdata; + cc_isr_desc[i].intmask = ccintmask; + done = TRUE; + break; + } + } + + if (done) { + cc_intmask = R_REG(sb_osh(sbh), ®s->intmask); + cc_intmask |= ccintmask; + W_REG(sb_osh(sbh), ®s->intmask, cc_intmask); + } + + /* restore original coreidx */ + sb_setcoreidx(sbh, origidx); + return done; +} + +/* + * chipc primary interrupt handler + */ +void sb_cc_isr(sb_t * sbh, chipcregs_t * regs) +{ + uint32 ccintstatus; + uint32 intstatus; + uint32 i; + + /* prior to rev 21 chipc interrupt means uart and gpio */ + if (sbh->ccrev >= 21) + ccintstatus = R_REG(sb_osh(sbh), ®s->intstatus) & cc_intmask; + else + ccintstatus = (CI_UART | CI_GPIO); + + for (i = 0; i < MAX_CC_INT_SOURCE; i++) { + if ((cc_isr_desc[i].isr != NULL) && + (intstatus = (cc_isr_desc[i].intmask & ccintstatus))) { + (cc_isr_desc[i].isr) (cc_isr_desc[i].cbdata, intstatus); + } + } +} diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndpmu.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndpmu.c new file mode 100644 index 0000000000..c7d7b3be75 --- /dev/null +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndpmu.c @@ -0,0 +1,1257 @@ +/* + * Misc utility routines for accessing PMU corerev specific features + * of the SiliconBackplane-based Broadcom chips. + * + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id$ + */ + +#include <typedefs.h> +#include <bcmdefs.h> +#include <osl.h> +#include <sbutils.h> +#include <bcmdevs.h> +#include <sbconfig.h> +#include <sbchipc.h> +#include <hndpmu.h> + +/* debug/trace */ +#define PMU_ERROR(args) + +#ifdef BCMDBG +#define PMU_MSG(args) printf args +#else +#define PMU_MSG(args) +#endif /* BCMDBG */ + +/* PMU & control */ +/* PMU rev 0 pll control for BCM4328 and BCM5354 */ +static void sb_pmu0_pllinit0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc, + uint32 xtal); +static uint32 sb_pmu0_alpclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc); +static uint32 sb_pmu0_cpuclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc); +/* PMU rev 0 pll control for BCM4325 BCM4329 */ +static void sb_pmu1_pllinit0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc, + uint32 xtal); +static uint32 sb_pmu1_cpuclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc); +static uint32 sb_pmu1_alpclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc); + +/* Setup switcher voltage */ +void +BCMINITFN (sb_pmu_set_switcher_voltage) (sb_t * sbh, osl_t * osh, + uint8 bb_voltage, uint8 rf_voltage) +{ + chipcregs_t *cc; + uint origidx; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + W_REG (osh, &cc->regcontrol_addr, 0x01); + W_REG (osh, &cc->regcontrol_data, (uint32) (bb_voltage & 0x1f) << 22); + + W_REG (osh, &cc->regcontrol_addr, 0x00); + W_REG (osh, &cc->regcontrol_data, (uint32) (rf_voltage & 0x1f) << 14); + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); +} + +void +sb_pmu_set_ldo_voltage (sb_t * sbh, osl_t * osh, uint8 ldo, uint8 voltage) +{ + uint8 sr_cntl_shift, rc_shift, shift, mask; + uint32 addr; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + switch (sbh->chip) + { + case BCM4328_CHIP_ID: + case BCM5354_CHIP_ID: + switch (ldo) + { + case SET_LDO_VOLTAGE_LDO1: + addr = 2; + sr_cntl_shift = 8; + rc_shift = 17; + mask = 0xf; + break; + case SET_LDO_VOLTAGE_LDO2: + addr = 3; + sr_cntl_shift = 0; + rc_shift = 1; + mask = 0xf; + break; + case SET_LDO_VOLTAGE_LDO3: + addr = 3; + sr_cntl_shift = 0; + rc_shift = 9; + mask = 0xf; + break; + case SET_LDO_VOLTAGE_PAREF: + addr = 3; + sr_cntl_shift = 0; + rc_shift = 17; + mask = 0x3f; + break; + default: + ASSERT (FALSE); + return; + } + break; + case BCM4312_CHIP_ID: + switch (ldo) + { + case SET_LDO_VOLTAGE_PAREF: + addr = 0; + sr_cntl_shift = 0; + rc_shift = 21; + mask = 0x3f; + break; + default: + ASSERT (FALSE); + return; + } + break; + default: + ASSERT (FALSE); + return; + } + + shift = sr_cntl_shift + rc_shift; + + sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, regcontrol_addr), + ~0, addr); + sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, regcontrol_data), + mask << shift, (voltage & mask) << shift); +} + +void +sb_pmu_paref_ldo_enable (sb_t * sbh, osl_t * osh, bool enable) +{ + uint ldo = 0; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + switch (sbh->chip) + { + case BCM4328_CHIP_ID: + ldo = RES4328_PA_REF_LDO; + break; + case BCM5354_CHIP_ID: + ldo = RES5354_PA_REF_LDO; + break; + case BCM4312_CHIP_ID: + ldo = RES4312_PA_REF_LDO; + break; + default: + return; + } + + sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, min_res_mask), + PMURES_BIT (ldo), enable ? PMURES_BIT (ldo) : 0); +} + +uint16 BCMINITFN (sb_pmu_fast_pwrup_delay) (sb_t * sbh, osl_t * osh) +{ + uint16 delay = PMU_MAX_TRANSITION_DLY; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + switch (sbh->chip) + { + case BCM4328_CHIP_ID: + delay = 7000; + break; + + case BCM4325_CHIP_ID: + case BCM4312_CHIP_ID: +#ifdef BCMQT + delay = 70; +#else + delay = 2800; +#endif + break; + + default: + PMU_MSG (("No PMU fast power up delay specified " + "for chip %x rev %d, using default %d us\n", + sbh->chip, sbh->chiprev, delay)); + break; + } + + return delay; +} + +uint32 BCMINITFN (sb_pmu_force_ilp) (sb_t * sbh, osl_t * osh, bool force) +{ + chipcregs_t *cc; + uint origidx; + uint32 oldpmucontrol; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + oldpmucontrol = R_REG (osh, &cc->pmucontrol); + if (force) + W_REG (osh, &cc->pmucontrol, oldpmucontrol & + ~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN)); + else + W_REG (osh, &cc->pmucontrol, oldpmucontrol | + (PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN)); + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); + + return oldpmucontrol; +} + +/* Setup min/max resources and up/down timers */ +typedef struct +{ + uint8 resnum; + uint16 updown; +} pmu_res_updown_t; + +typedef struct +{ + uint8 resnum; + int8 action; /* 0 - set, 1 - add, -1 - remove */ + uint32 depend_mask; +} pmu_res_depend_t; + +static const pmu_res_updown_t +BCMINITDATA (bcm4328a0_res_updown)[] = +{ + { + RES4328_EXT_SWITCHER_PWM, 0x0101}, + { + RES4328_BB_SWITCHER_PWM, 0x1f01}, + { + RES4328_BB_SWITCHER_BURST, 0x010f}, + { + RES4328_BB_EXT_SWITCHER_BURST, 0x0101}, + { + RES4328_ILP_REQUEST, 0x0202}, + { + RES4328_RADIO_SWITCHER_PWM, 0x0f01}, + { + RES4328_RADIO_SWITCHER_BURST, 0x0f01}, + { + RES4328_ROM_SWITCH, 0x0101}, + { + RES4328_PA_REF_LDO, 0x0f01}, + { + RES4328_RADIO_LDO, 0x0f01}, + { + RES4328_AFE_LDO, 0x0f01}, + { + RES4328_PLL_LDO, 0x0f01}, + { + RES4328_BG_FILTBYP, 0x0101}, + { + RES4328_TX_FILTBYP, 0x0101}, + { + RES4328_RX_FILTBYP, 0x0101}, + { + RES4328_XTAL_PU, 0x0101}, + { + RES4328_XTAL_EN, 0xa001}, + { + RES4328_BB_PLL_FILTBYP, 0x0101}, + { + RES4328_RF_PLL_FILTBYP, 0x0101}, + { + RES4328_BB_PLL_PU, 0x0701} +}; + +static const pmu_res_depend_t +BCMINITDATA (bcm4328a0_res_depend)[] = +{ + /* Adjust ILP request resource not to force ext/BB switchers into burst mode */ + { + RES4328_ILP_REQUEST, 0, + PMURES_BIT (RES4328_EXT_SWITCHER_PWM) | + PMURES_BIT (RES4328_BB_SWITCHER_PWM)} +}; + +#ifdef BCMQT /* for power save on slow QT/small beacon interval */ +static const pmu_res_updown_t +BCMINITDATA (bcm4325a0_res_updown_qt)[] = +{ + { + RES4325_HT_AVAIL, 0x0300}, + { + RES4325_BBPLL_PWRSW_PU, 0x0101}, + { + RES4325_RFPLL_PWRSW_PU, 0x0101}, + { + RES4325_ALP_AVAIL, 0x0100}, + { + RES4325_XTAL_PU, 0x1000}, + { + RES4325_LNLDO1_PU, 0x0800}, + { + RES4325_CLDO_CBUCK_PWM, 0x0101}, + { + RES4325_CBUCK_PWM, 0x0803} +}; +#else +static const pmu_res_updown_t +BCMINITDATA (bcm4325a0_res_updown)[] = +{ + { + RES4325_XTAL_PU, 0x1501} +}; +#endif /* !BCMQT */ + +static const pmu_res_depend_t +BCMINITDATA (bcm4325a0_res_depend)[] = +{ + /* Adjust HT Avail resource dependencies */ + { + RES4325_HT_AVAIL, 1, + PMURES_BIT (RES4325_RX_PWRSW_PU) | PMURES_BIT (RES4325_TX_PWRSW_PU) | + PMURES_BIT (RES4325_LOGEN_PWRSW_PU) | PMURES_BIT (RES4325_AFE_PWRSW_PU)} +}; + +void BCMINITFN (sb_pmu_res_init) (sb_t * sbh, osl_t * osh) +{ + chipcregs_t *cc; + uint origidx; + const pmu_res_updown_t *pmu_res_updown_table = NULL; + int pmu_res_updown_table_sz = 0; + const pmu_res_depend_t *pmu_res_depend_table = NULL; + int pmu_res_depend_table_sz = 0; + uint32 min_mask = 0, max_mask = 0; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + switch (sbh->chip) + { + case BCM4328_CHIP_ID: + /* Down to ILP request excluding ROM */ + min_mask = PMURES_BIT (RES4328_EXT_SWITCHER_PWM) | + PMURES_BIT (RES4328_BB_SWITCHER_PWM) | PMURES_BIT (RES4328_XTAL_EN); +#ifdef BCMROMOFFLOAD + /* Including ROM */ + min_mask |= PMURES_BIT (RES4328_ROM_SWITCH); +#endif + /* Allow (but don't require) PLL to turn on */ + max_mask = 0xfffff; + pmu_res_updown_table = bcm4328a0_res_updown; + pmu_res_updown_table_sz = ARRAYSIZE (bcm4328a0_res_updown); + pmu_res_depend_table = bcm4328a0_res_depend; + pmu_res_depend_table_sz = ARRAYSIZE (bcm4328a0_res_depend); + break; + case BCM4312_CHIP_ID: + /* keep default + * min_mask = 0xcbb; max_mask = 0x7ffff; + * pmu_res_updown_table_sz = 0; + * pmu_res_depend_table_sz = 0; + */ + break; + case BCM5354_CHIP_ID: + /* Allow (but don't require) PLL to turn on */ + max_mask = 0xfffff; + break; + + case BCM4325_CHIP_ID: + /* Leave OTP powered up and power it down later. */ + min_mask = + PMURES_BIT (RES4325_CBUCK_BURST) | PMURES_BIT (RES4325_LNLDO2_PU); + if (((sbh->chipst & CST4325_PMUTOP_2B_MASK) >> + CST4325_PMUTOP_2B_SHIFT) == 1) + min_mask |= PMURES_BIT (RES4325_CLDO_CBUCK_BURST); + /* Allow (but don't require) PLL to turn on */ + max_mask = 0x3fffff; +#ifdef BCMQT + pmu_res_updown_table = bcm4325a0_res_updown_qt; + pmu_res_updown_table_sz = ARRAYSIZE (bcm4325a0_res_updown_qt); +#else + pmu_res_updown_table = bcm4325a0_res_updown; + pmu_res_updown_table_sz = ARRAYSIZE (bcm4325a0_res_updown); + pmu_res_depend_table = bcm4325a0_res_depend; + pmu_res_depend_table_sz = ARRAYSIZE (bcm4325a0_res_depend); +#endif + break; + + default: + break; + } + + /* Program up/down timers */ + while (pmu_res_updown_table_sz--) + { + ASSERT (pmu_res_updown_table); + W_REG (osh, &cc->res_table_sel, + pmu_res_updown_table[pmu_res_updown_table_sz].resnum); + W_REG (osh, &cc->res_updn_timer, + pmu_res_updown_table[pmu_res_updown_table_sz].updown); + } + + /* Program resource dependencies table */ + while (pmu_res_depend_table_sz--) + { + ASSERT (pmu_res_depend_table); + W_REG (osh, &cc->res_table_sel, + pmu_res_depend_table[pmu_res_depend_table_sz].resnum); + switch (pmu_res_depend_table[pmu_res_depend_table_sz].action) + { + case 0: + W_REG (osh, &cc->res_dep_mask, + pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask); + break; + case 1: + OR_REG (osh, &cc->res_dep_mask, + pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask); + break; + case -1: + AND_REG (osh, &cc->res_dep_mask, + ~pmu_res_depend_table[pmu_res_depend_table_sz]. + depend_mask); + break; + default: + ASSERT (0); + break; + } + } + + /* program min resource mask */ + if (min_mask) + { + PMU_MSG (("Changing min_res_mask to 0x%x\n", min_mask)); + W_REG (osh, &cc->min_res_mask, min_mask); + } + /* program max resource mask */ + if (max_mask) + { + PMU_MSG (("Changing max_res_mask to 0x%x\n", max_mask)); + W_REG (osh, &cc->max_res_mask, max_mask); + } + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); +} + +/* setup pll and query clock speed */ +typedef struct +{ + uint16 freq; + uint8 xf; + uint8 wbint; + uint32 wbfrac; +} pmu0_xtaltab0_t; + +/* the following table is based on 880Mhz Fvco */ +#define PMU0_PLL0_FVCO 880000 /* Fvco 880Mhz */ +static const pmu0_xtaltab0_t +BCMINITDATA (pmu0_xtaltab0)[] = +{ + { + 12000, 1, 73, 349525}, + { + 13000, 2, 67, 725937}, + { + 14400, 3, 61, 116508}, + { + 15360, 4, 57, 305834}, + { + 16200, 5, 54, 336579}, + { + 16800, 6, 52, 399457}, + { + 19200, 7, 45, 873813}, + { + 19800, 8, 44, 466033}, + { + 20000, 9, 44, 0}, + { + 25000, 10, 70, 419430}, + { + 26000, 11, 67, 725937}, + { + 30000, 12, 58, 699050}, + { + 38400, 13, 45, 873813}, + { + 40000, 14, 45, 0}, + { + 0, 0, 0, 0} +}; + +#ifdef BCMUSBDEV +#define PMU0_XTAL0_DEFAULT 11 +#else +#define PMU0_XTAL0_DEFAULT 8 +#endif + +#ifdef BCMUSBDEV +/* + * Set new backplane PLL clock frequency + */ +static void BCMINITFN (sb_pmu0_sbclk4328) (sb_t * sbh, int freq) +{ + uint32 tmp, oldmax, oldmin, origidx; + chipcregs_t *cc; + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + /* Set new backplane PLL clock */ + W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0); + tmp = R_REG (osh, &cc->pllcontrol_data); + tmp &= ~(PMU0_PLL0_PC0_DIV_ARM_MASK); + tmp |= freq << PMU0_PLL0_PC0_DIV_ARM_SHIFT; + W_REG (osh, &cc->pllcontrol_data, tmp); + + /* Power cycle BB_PLL_PU by disabling/enabling it to take on new freq */ + /* Disable PLL */ + oldmin = R_REG (osh, &cc->min_res_mask); + oldmax = R_REG (osh, &cc->max_res_mask); + W_REG (osh, &cc->min_res_mask, oldmin & ~PMURES_BIT (RES4328_BB_PLL_PU)); + W_REG (osh, &cc->max_res_mask, oldmax & ~PMURES_BIT (RES4328_BB_PLL_PU)); + + /* It takes over several hundred usec to re-enable the PLL since the + * sequencer state machines run on ILP clock. Set delay at 450us to be safe. + * + * Be sure PLL is powered down first before re-enabling it. + */ + + OSL_DELAY (PLL_DELAY); + SPINWAIT ((R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU)), + PLL_DELAY * 3); + + if (R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU)) + { + /* If BB_PLL not powered down yet, new backplane PLL clock + * may not take effect. + * + * Still early during bootup so no serial output here. + */ + PMU_ERROR (("Fatal: BB_PLL not power down yet!\n")); + ASSERT (! + (R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU))); + } + + /* Enable PLL */ + W_REG (osh, &cc->max_res_mask, oldmax); + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); +} +#endif /* BCMUSBDEV */ + +/* Set up PLL registers in the PMU as per the crystal speed. + * Uses xtalfreq variable, or passed-in default. + */ +static void +BCMINITFN (sb_pmu0_pllinit0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc, + uint32 xtal) +{ + uint32 tmp; + const pmu0_xtaltab0_t *xt; + + if ((sb_chip (sbh) == BCM5354_CHIP_ID) && (xtal == 0)) + { + /* 5354 has xtal freq of 25MHz */ + xtal = 25000; + } + + /* Find the frequency in the table */ + for (xt = pmu0_xtaltab0; xt->freq; xt++) + if (xt->freq == xtal) + break; + if (xt->freq == 0) + xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT]; + + PMU_MSG (("XTAL %d (%d)\n", xtal, xt->xf)); + + /* Check current PLL state */ + tmp = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >> + PCTL_XTALFREQ_SHIFT; + if (tmp == xt->xf) + { + PMU_MSG (("PLL already programmed for %d.%d MHz\n", + (xt->freq / 1000), (xt->freq % 1000))); + +#ifdef BCMUSBDEV + if (sbh->chip == BCM4328_CHIP_ID) + sb_pmu0_sbclk4328 (sbh, PMU0_PLL0_PC0_DIV_ARM_88MHZ); +#endif + return; + } + + if (tmp) + { + PMU_MSG (("Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n", + (xt->freq / 1000), (xt->freq % 1000), + (pmu0_xtaltab0[tmp - 1].freq / 1000), + (pmu0_xtaltab0[tmp - 1].freq % 1000))); + } + else + { + PMU_MSG (("Programming PLL for %d.%d MHz\n", (xt->freq / 1000), + (xt->freq % 1000))); + } + + /* Make sure the PLL is off */ + switch (sbh->chip) + { + case BCM4328_CHIP_ID: + AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES4328_BB_PLL_PU)); + AND_REG (osh, &cc->max_res_mask, ~PMURES_BIT (RES4328_BB_PLL_PU)); + break; + case BCM5354_CHIP_ID: + AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES5354_BB_PLL_PU)); + AND_REG (osh, &cc->max_res_mask, ~PMURES_BIT (RES5354_BB_PLL_PU)); + break; + default: + ASSERT (0); + } + SPINWAIT (R_REG (osh, &cc->clk_ctl_st) & CCS0_HTAVAIL, + PMU_MAX_TRANSITION_DLY); + ASSERT (!(R_REG (osh, &cc->clk_ctl_st) & CCS0_HTAVAIL)); + + PMU_MSG (("Done masking\n")); + + /* Write PDIV in pllcontrol[0] */ + W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0); + tmp = R_REG (osh, &cc->pllcontrol_data); + if (xt->freq >= PMU0_PLL0_PC0_PDIV_FREQ) + tmp |= PMU0_PLL0_PC0_PDIV_MASK; + else + tmp &= ~PMU0_PLL0_PC0_PDIV_MASK; + W_REG (osh, &cc->pllcontrol_data, tmp); + + /* Write WILD in pllcontrol[1] */ + W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1); + tmp = R_REG (osh, &cc->pllcontrol_data); + tmp = + ((tmp & ~(PMU0_PLL0_PC1_WILD_INT_MASK | PMU0_PLL0_PC1_WILD_FRAC_MASK)) | + (((xt-> + wbint << PMU0_PLL0_PC1_WILD_INT_SHIFT) & PMU0_PLL0_PC1_WILD_INT_MASK) + | ((xt->wbfrac << PMU0_PLL0_PC1_WILD_FRAC_SHIFT) & + PMU0_PLL0_PC1_WILD_FRAC_MASK))); + if (xt->wbfrac == 0) + tmp |= PMU0_PLL0_PC1_STOP_MOD; + else + tmp &= ~PMU0_PLL0_PC1_STOP_MOD; + W_REG (osh, &cc->pllcontrol_data, tmp); + + /* Write WILD in pllcontrol[2] */ + W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2); + tmp = R_REG (osh, &cc->pllcontrol_data); + tmp = ((tmp & ~PMU0_PLL0_PC2_WILD_INT_MASK) | + ((xt->wbint >> PMU0_PLL0_PC2_WILD_INT_SHIFT) & + PMU0_PLL0_PC2_WILD_INT_MASK)); + W_REG (osh, &cc->pllcontrol_data, tmp); + + PMU_MSG (("Done pll\n")); + + /* Write XtalFreq. Set the divisor also. */ + tmp = R_REG (osh, &cc->pmucontrol); + tmp = ((tmp & ~PCTL_ILP_DIV_MASK) | + (((((xt->freq + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) & + PCTL_ILP_DIV_MASK)); + tmp = ((tmp & ~PCTL_XTALFREQ_MASK) | + ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK)); + W_REG (osh, &cc->pmucontrol, tmp); +} + +static uint32 +BCMINITFN (sb_pmu0_alpclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc) +{ + const pmu0_xtaltab0_t *xt; + uint32 xf; + + /* Find the frequency in the table */ + xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >> + PCTL_XTALFREQ_SHIFT; + for (xt = pmu0_xtaltab0; xt->freq; xt++) + if (xt->xf == xf) + break; + if (xt->freq == 0) + xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT]; + + return xt->freq * 1000; +} + +static uint32 +BCMINITFN (sb_pmu0_cpuclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc) +{ + const pmu0_xtaltab0_t *xt; + uint32 xf, tmp, divarm; +#ifdef BCMDBG + uint32 pdiv, wbint, wbfrac, fvco; +#endif + + if (sb_chip (sbh) == BCM5354_CHIP_ID) + { + /* 5354 gets sb clock of 120MHz from main pll */ + return 120000000; + } + + /* Find the xtal frequency in the table */ + xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >> + PCTL_XTALFREQ_SHIFT; + for (xt = pmu0_xtaltab0; xt->freq; xt++) + if (xt->xf == xf) + break; + if (xt->freq == 0) + xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT]; + + /* Read divarm from pllcontrol[0] */ + W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0); + tmp = R_REG (osh, &cc->pllcontrol_data); + divarm = (tmp & PMU0_PLL0_PC0_DIV_ARM_MASK) >> PMU0_PLL0_PC0_DIV_ARM_SHIFT; + +#ifdef BCMDBG + /* Calculate Fvco based on xtal freq, pdiv, and wild */ + pdiv = tmp & PMU0_PLL0_PC0_PDIV_MASK; + + W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1); + tmp = R_REG (osh, &cc->pllcontrol_data); + wbfrac = + (tmp & PMU0_PLL0_PC1_WILD_FRAC_MASK) >> PMU0_PLL0_PC1_WILD_FRAC_SHIFT; + wbint = (tmp & PMU0_PLL0_PC1_WILD_INT_MASK) >> PMU0_PLL0_PC1_WILD_INT_SHIFT; + + W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2); + tmp = R_REG (osh, &cc->pllcontrol_data); + wbint += + (tmp & PMU0_PLL0_PC2_WILD_INT_MASK) << PMU0_PLL0_PC2_WILD_INT_SHIFT; + + fvco = (xt->freq * wbint) << 8; + fvco += (xt->freq * (wbfrac >> 10)) >> 2; + fvco += (xt->freq * (wbfrac & 0x3ff)) >> 10; + fvco >>= 8; + fvco >>= pdiv; + fvco /= 1000; + fvco *= 1000; + + PMU_MSG (("sb_pmu0_cpuclk0: wbint %u wbfrac %u fvco %u\n", + wbint, wbfrac, fvco)); + ASSERT (fvco == PMU0_PLL0_FVCO); +#endif /* BCMDBG */ + + /* Return ARM/SB clock */ + return PMU0_PLL0_FVCO / (divarm + PMU0_PLL0_PC0_DIV_ARM_BASE) * 1000; +} + +/* PMU corerev 1 pll programming for BCM4325 */ +/* setup pll and query clock speed */ +typedef struct +{ + uint16 fref; + uint8 xf; + uint8 p1div; + uint8 p2div; + uint8 ndiv_int; + uint32 ndiv_frac; +} pmu1_xtaltab0_t; + +/* the following table is based on 880Mhz Fvco */ +#define PMU1_PLL0_FVCO 880000 /* Fvco 880Mhz */ +static const pmu1_xtaltab0_t +BCMINITDATA (pmu1_xtaltab0)[] = +{ + { + 12000, 1, 3, 22, 0x9, 0xFFFFEF}, + { + 13000, 2, 1, 6, 0xb, 0x483483}, + { + 14400, 3, 1, 10, 0xa, 0x1C71C7}, + { + 15360, 4, 1, 5, 0xb, 0x755555}, + { + 16200, 5, 1, 10, 0x5, 0x6E9E06}, + { + 16800, 6, 1, 10, 0x5, 0x3Cf3Cf}, + { + 19200, 7, 1, 9, 0x5, 0x17B425}, + { + 19800, 8, 1, 11, 0x4, 0xA57EB}, + { + 20000, 9, 1, 11, 0x4, 0x0}, + { + 24000, 10, 3, 11, 0xa, 0x0}, + { + 25000, 11, 5, 16, 0xb, 0x0}, + { + 26000, 12, 1, 2, 0x10, 0xEC4EC4}, + { + 30000, 13, 3, 8, 0xb, 0x0}, + { + 38400, 14, 1, 5, 0x4, 0x955555}, + { + 40000, 15, 1, 2, 0xb, 0}, + { + 0, 0, 0, 0, 0, 0} +}; + +/* Default to 15360Khz crystal */ +#define PMU1_XTAL0_DEFAULT 3 + +static uint32 +BCMINITFN (sb_pmu1_alpclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc) +{ + const pmu1_xtaltab0_t *xt; + uint32 xf; + + /* Find the frequency in the table */ + xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >> + PCTL_XTALFREQ_SHIFT; + for (xt = pmu1_xtaltab0; xt->fref; xt++) + if (xt->xf == xf) + break; + if (xt->fref == 0) + xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT]; + + return xt->fref * 1000; +} + +/* Set up PLL registers in the PMU as per the crystal speed. + * Uses xtalfreq variable, or passed-in default. + */ +static void +BCMINITFN (sb_pmu1_pllinit0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc, + uint32 xtal) +{ + const pmu1_xtaltab0_t *xt; + uint32 tmp; + uint32 buf_strength = 0; + + /* 4312: assume default works */ + if (sbh->chip == BCM4312_CHIP_ID) + return; + + /* Find the frequency in the table */ + for (xt = pmu1_xtaltab0; xt->fref; xt++) + if (xt->fref == xtal) + break; + if (xt->fref == 0) + xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT]; + + PMU_MSG (("XTAL %d (%d)\n", xtal, xt->xf)); + + /* Check current PLL state */ + if (((R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >> + PCTL_XTALFREQ_SHIFT) == xt->xf) + { + PMU_MSG (("PLL already programmed for %d.%d MHz\n", + (xt->fref / 1000), (xt->fref % 1000))); + return; + } + + PMU_MSG (("Programming PLL for %d.%d MHz\n", (xt->fref / 1000), + (xt->fref % 1000))); + + /* Make sure the PLL is off */ + switch (sbh->chip) + { + case BCM4325_CHIP_ID: + AND_REG (osh, &cc->min_res_mask, + ~(PMURES_BIT (RES4325_BBPLL_PWRSW_PU) | + PMURES_BIT (RES4325_HT_AVAIL))); + AND_REG (osh, &cc->max_res_mask, + ~(PMURES_BIT (RES4325_BBPLL_PWRSW_PU) | + PMURES_BIT (RES4325_HT_AVAIL))); + + /* Change the BBPLL drive strength to 2 for all channels */ + buf_strength = 0x222222; + break; + default: + ASSERT (0); + } + SPINWAIT (R_REG (osh, &cc->clk_ctl_st) & CCS_HTAVAIL, + PMU_MAX_TRANSITION_DLY); + ASSERT (!(R_REG (osh, &cc->clk_ctl_st) & CCS_HTAVAIL)); + + PMU_MSG (("Done masking\n")); + + /* Write p1div and p2div to pllcontrol[0] */ + W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); + tmp = R_REG (osh, &cc->pllcontrol_data) & + ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK); + tmp |= + ((xt-> + p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) | ((xt-> + p2div + << + PMU1_PLL0_PC0_P2DIV_SHIFT) + & + PMU1_PLL0_PC0_P2DIV_MASK); + W_REG (osh, &cc->pllcontrol_data, tmp); + + /* Write ndiv_int and ndiv_mode to pllcontrol[2] */ + W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); + tmp = R_REG (osh, &cc->pllcontrol_data) & + ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK); + tmp |= + ((xt-> + ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) & PMU1_PLL0_PC2_NDIV_INT_MASK) + | ((1 << PMU1_PLL0_PC2_NDIV_MODE_SHIFT) & PMU1_PLL0_PC2_NDIV_MODE_MASK); + W_REG (osh, &cc->pllcontrol_data, tmp); + + /* Write ndiv_frac to pllcontrol[3] */ + W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); + tmp = R_REG (osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK; + tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) & + PMU1_PLL0_PC3_NDIV_FRAC_MASK); + W_REG (osh, &cc->pllcontrol_data, tmp); + + if (buf_strength) + { + PMU_MSG (("Adjusting PLL buffer drive strength: %x\n", buf_strength)); + + W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); + tmp = R_REG (osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK; + tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT); + W_REG (osh, &cc->pllcontrol_data, tmp); + } + + PMU_MSG (("Done pll\n")); + + /* Write XtalFreq. Set the divisor also. */ + tmp = R_REG (osh, &cc->pmucontrol) & + ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK); + tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) & + PCTL_ILP_DIV_MASK) | + ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK); + W_REG (osh, &cc->pmucontrol, tmp); +} + + +static uint32 +BCMINITFN (sb_pmu1_cpuclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc) +{ + const pmu1_xtaltab0_t *xt; + uint32 xf, tmp, m1div; +#ifdef BCMDBG + uint32 ndiv_int, ndiv_frac, p2div, p1div, fvco; +#endif + + /* Find the xtal frequency in the table */ + xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >> + PCTL_XTALFREQ_SHIFT; + for (xt = pmu1_xtaltab0; xt->fref; xt++) + if (xt->xf == xf) + break; + if (xt->fref == 0) + xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT]; + + /* Read m1div from pllcontrol[1] */ + W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); + tmp = R_REG (osh, &cc->pllcontrol_data); + m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT; + +#ifdef BCMDBG + /* Read p2div/p1div from pllcontrol[0] */ + W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); + tmp = R_REG (osh, &cc->pllcontrol_data); + p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT; + p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT; + + /* Calculate Fvco based on xtal freq and ndiv and pdiv */ + W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); + tmp = R_REG (osh, &cc->pllcontrol_data); + ndiv_int = + (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT; + + W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); + tmp = R_REG (osh, &cc->pllcontrol_data); + ndiv_frac = + (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >> PMU1_PLL0_PC3_NDIV_FRAC_SHIFT; + + fvco = (xt->fref * ndiv_int) << 8; + fvco += (xt->fref * (ndiv_frac >> 12)) >> 4; + fvco += (xt->fref * (ndiv_frac & 0xfff)) >> 12; + fvco >>= 8; + fvco *= p2div; + fvco /= p1div; + fvco /= 1000; + fvco *= 1000; + + PMU_MSG (("sb_pmu0_cpuclk0: ndiv_int %u ndiv_frac %u " + "p2div %u p1div %u fvco %u\n", + ndiv_int, ndiv_frac, p2div, p1div, fvco)); + ASSERT (fvco == PMU1_PLL0_FVCO); +#endif /* BCMDBG */ + + /* Return ARM/SB clock */ + return PMU1_PLL0_FVCO / m1div * 1000; +} + +void BCMINITFN (sb_pmu_pll_init) (sb_t * sbh, osl_t * osh, uint xtalfreq) +{ + chipcregs_t *cc; + uint origidx; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + switch (sbh->chip) + { + case BCM4328_CHIP_ID: + sb_pmu0_pllinit0 (sbh, osh, cc, xtalfreq); + break; + case BCM5354_CHIP_ID: + sb_pmu0_pllinit0 (sbh, osh, cc, xtalfreq); + break; + case BCM4325_CHIP_ID: + sb_pmu1_pllinit0 (sbh, osh, cc, xtalfreq); + break; + case BCM4312_CHIP_ID: + sb_pmu1_pllinit0 (sbh, osh, cc, xtalfreq); + break; + default: + PMU_MSG (("No PLL init done for chip %x rev %d pmurev %d\n", + sbh->chip, sbh->chiprev, sbh->pmurev)); + break; + } + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); +} + +uint32 BCMINITFN (sb_pmu_alp_clock) (sb_t * sbh, osl_t * osh) +{ + chipcregs_t *cc; + uint origidx; + uint32 clock = ALP_CLOCK; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + switch (sbh->chip) + { + case BCM4328_CHIP_ID: + clock = sb_pmu0_alpclk0 (sbh, osh, cc); + break; + case BCM5354_CHIP_ID: + clock = sb_pmu0_alpclk0 (sbh, osh, cc); + break; + case BCM4325_CHIP_ID: + clock = sb_pmu1_alpclk0 (sbh, osh, cc); + break; + case BCM4312_CHIP_ID: + clock = sb_pmu1_alpclk0 (sbh, osh, cc); + /* always 20Mhz */ + clock = 20000 * 1000; + break; + default: + PMU_MSG (("No ALP clock specified " + "for chip %x rev %d pmurev %d, using default %d Hz\n", + sbh->chip, sbh->chiprev, sbh->pmurev, clock)); + break; + } + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); + return clock; +} + +uint BCMINITFN (sb_pmu_cpu_clock) (sb_t * sbh, osl_t * osh) +{ + chipcregs_t *cc; + uint origidx; + uint32 clock = HT_CLOCK; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + switch (sbh->chip) + { + case BCM4328_CHIP_ID: + clock = sb_pmu0_cpuclk0 (sbh, osh, cc); + break; + case BCM5354_CHIP_ID: + clock = sb_pmu0_cpuclk0 (sbh, osh, cc); + break; + case BCM4325_CHIP_ID: + clock = sb_pmu1_cpuclk0 (sbh, osh, cc); + break; + case BCM4312_CHIP_ID: + clock = sb_pmu1_cpuclk0 (sbh, osh, cc); + break; + default: + PMU_MSG (("No CPU clock specified " + "for chip %x rev %d pmurev %d, using default %d Hz\n", + sbh->chip, sbh->chiprev, sbh->pmurev, clock)); + break; + } + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); + return clock; +} + +void BCMINITFN (sb_pmu_init) (sb_t * sbh, osl_t * osh) +{ + chipcregs_t *cc; + uint origidx; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + if (sbh->pmurev >= 1) + { + if (sbh->chip == BCM4325_CHIP_ID && sbh->chiprev <= 1) + AND_REG (osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT); + else + OR_REG (osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT); + } + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); +} + +void BCMINITFN (sb_pmu_otp_power) (sb_t * sbh, osl_t * osh, bool on) +{ + chipcregs_t *cc; + uint origidx; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + switch (sbh->chip) + { + case BCM4325_CHIP_ID: + if (on) + { + OR_REG (osh, &cc->min_res_mask, PMURES_BIT (RES4325_LNLDO2_PU)); + if (sbh->boardflags & BFL_BUCKBOOST) + AND_REG (osh, &cc->min_res_mask, + ~PMURES_BIT (RES4325_BUCK_BOOST_PWM)); + OSL_DELAY (500); + } + else + { + if (sbh->boardflags & BFL_BUCKBOOST) + OR_REG (osh, &cc->min_res_mask, + PMURES_BIT (RES4325_BUCK_BOOST_PWM)); + AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES4325_LNLDO2_PU)); + } + break; + default: + break; + } + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); +} + +void +sb_pmu_rcal (sb_t * sbh, osl_t * osh) +{ + chipcregs_t *cc; + uint origidx; + + ASSERT (sbh->cccaps & CC_CAP_PMU); + + /* Remember original core before switch to chipc */ + origidx = sb_coreidx (sbh); + cc = sb_setcore (sbh, SB_CC, 0); + ASSERT (cc); + + switch (sbh->chip) + { + case BCM4325_CHIP_ID: + { + uint8 rcal_code; + uint32 val; + + /* Kick RCal */ + W_REG (osh, &cc->chipcontrol_addr, 1); + AND_REG (osh, &cc->chipcontrol_data, ~0x04); + OR_REG (osh, &cc->chipcontrol_data, 0x04); + + /* Wait for completion */ + SPINWAIT (0 == (R_REG (osh, &cc->chipstatus) & 0x08), + 10 * 1000 * 1000); + ASSERT (R_REG (osh, &cc->chipstatus) & 0x08); + + /* Drop the LSB to convert from 5 bit code to 4 bit code */ + rcal_code = (uint8) (R_REG (osh, &cc->chipstatus) >> 5) & 0x0f; + PMU_MSG (("RCal completed, status 0x%x, code 0x%x\n", + R_REG (osh, &cc->chipstatus), rcal_code)); + + /* Write RCal code into pmu_vreg_ctrl[32:29] */ + W_REG (osh, &cc->regcontrol_addr, 0); + val = R_REG (osh, &cc->regcontrol_data) & ~((uint32) 0x07 << 29); + val |= (uint32) (rcal_code & 0x07) << 29; + W_REG (osh, &cc->regcontrol_data, val); + W_REG (osh, &cc->regcontrol_addr, 1); + val = R_REG (osh, &cc->regcontrol_data) & ~(uint32) 0x01; + val |= (uint32) ((rcal_code >> 3) & 0x01); + W_REG (osh, &cc->regcontrol_data, val); + + /* Write RCal code into pmu_chip_ctrl[33:30] */ + W_REG (osh, &cc->chipcontrol_addr, 0); + val = R_REG (osh, &cc->chipcontrol_data) & ~((uint32) 0x03 << 30); + val |= (uint32) (rcal_code & 0x03) << 30; + W_REG (osh, &cc->chipcontrol_data, val); + W_REG (osh, &cc->chipcontrol_addr, 1); + val = R_REG (osh, &cc->chipcontrol_data) & ~(uint32) 0x03; + val |= (uint32) ((rcal_code >> 2) & 0x03); + W_REG (osh, &cc->chipcontrol_data, val); + + /* Set override in pmu_chip_ctrl[29] */ + W_REG (osh, &cc->chipcontrol_addr, 0); + OR_REG (osh, &cc->chipcontrol_data, (0x01 << 29)); + + /* Power off RCal block */ + W_REG (osh, &cc->chipcontrol_addr, 1); + AND_REG (osh, &cc->chipcontrol_data, ~0x04); + + break; + } + default: + break; + } + + /* Return to original core */ + sb_setcoreidx (sbh, origidx); +} diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmdefs.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmdefs.h index 8b5abe5d26..9cb669bd91 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmdefs.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmdefs.h @@ -101,6 +101,8 @@ extern bool bcmreclaimed; */ #define BCMDONGLEHDRSZ 8 +/* Max. nvram variable table size */ +#define MAXSZ_NVRAM_VARS 4096 #endif /* _bcmdefs_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmdevs.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmdevs.h index 2e80658da3..f03e0b6b1b 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmdevs.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmdevs.h @@ -1,22 +1,20 @@ /* * Broadcom device-specific manifest constants. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * $Id: bcmdevs.h,v 1.1.1.17 2006/04/15 01:29:08 michael Exp $ + * $Id$ */ #ifndef _BCMDEVS_H #define _BCMDEVS_H -#include "bcm4710.h" - -/* Known PCI vendor Id's */ +/* PCI vendor IDs */ #define VENDOR_EPIGRAM 0xfeda #define VENDOR_BROADCOM 0x14e4 #define VENDOR_3COM 0x10b7 @@ -25,24 +23,63 @@ #define VENDOR_DELL 0x1028 #define VENDOR_HP 0x0e11 #define VENDOR_APPLE 0x106b +#define VENDOR_SI_IMAGE 0x1095 /* Silicon Image, used by Arasan SDIO Host */ +#define VENDOR_BUFFALO 0x1154 /* Buffalo vendor id */ +#define VENDOR_TI 0x104c /* Texas Instruments */ + +/* PCMCIA vendor IDs */ +#define VENDOR_BROADCOM_PCMCIA 0x02d0 + +/* SDIO vendor IDs */ +#define VENDOR_BROADCOM_SDIO 0x00BF -/* PCI Device Id's */ +/* PCI Device IDs */ #define BCM4210_DEVICE_ID 0x1072 /* never used */ -#define BCM4211_DEVICE_ID 0x4211 #define BCM4230_DEVICE_ID 0x1086 /* never used */ +#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ +#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ +#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ +#define BCM4211_DEVICE_ID 0x4211 #define BCM4231_DEVICE_ID 0x4231 - +#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ +#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */ +#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */ +#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */ +#define BCM4328_D11DUAL_ID 0x4314 /* 4328 802.11a/g id */ +#define BCM4328_D11G_ID 0x4315 /* 4328 802.11g 2.4Ghz band id */ +#define BCM4328_D11A_ID 0x4316 /* 4328 802.11a 5Ghz band id */ +#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ +#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ +#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */ +#define BCM4325_D11DUAL_ID 0x431b /* 4325 802.11a/g id */ +#define BCM4325_D11G_ID 0x431c /* 4325 802.11g 2.4Ghz band id */ +#define BCM4325_D11A_ID 0x431d /* 4325 802.11a 5Ghz band id */ +#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ +#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ +#define BCM4306_UART_ID 0x4322 /* 4306 uart */ +#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ +#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ +#define BCM4306_D11G_ID2 0x4325 +#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */ +#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Ghz band id */ +#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */ +#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ +#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ +#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */ +#define BCM_JTAGM_ID 0x43f1 /* BCM jtagm device id */ +#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */ +#define BCM_SDIOH_ID 0x43f3 /* BCM sdio host id */ +#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */ +#define SPIH_FPGA_ID 0x43f5 /* PCI SPI Host Controller FPGA */ +#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */ +#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ +#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ #define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ -#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ #define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ +#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ #define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ - -#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ -#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ - -#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ -#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ - +#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ +#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ #define BCM47XX_ILINE_ID 0x4711 /* 47xx iline20 */ #define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ #define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ @@ -57,114 +94,83 @@ #define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */ #define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */ #define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */ - +#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ #define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */ #define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */ +#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ +#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ +#define JINVANI_SDIOH_ID 0x4743 /* Jinvani SDIO Gold Host */ +#define BCM27XX_SDIOH_ID 0x2702 /* BCM27xx Standard SDIO Host */ +#define PCIXX21_FLASHMEDIA_ID 0x803b /* TI PCI xx21 Standard Host Controller */ +#define PCIXX21_SDIOH_ID 0x803c /* TI PCI xx21 Standard Host Controller */ +/* Chip IDs */ #define BCM4710_CHIP_ID 0x4710 /* 4710 chipid returned by sb_chip() */ -#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ - #define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ -#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ -#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ -#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ - #define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */ -#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ -#define BCM4306_D11G_ID2 0x4325 -#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ -#define BCM4306_UART_ID 0x4322 /* 4306 uart */ -#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ -#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ - -#define BCM4309_PKG_ID 1 /* 4309 package id */ - #define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */ -#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */ -#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */ -#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */ - -#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ -#define BCM4303_PKG_ID 2 /* 4303 package id */ - -#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ -#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ - #define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ -#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ - +#define BCM4312_CHIP_ID 0x4312 /* 4312 chip common chipid */ #define BCM4318_CHIP_ID 0x4318 /* 4318 chip common chipid */ -#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ -#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ -#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */ - #define BCM4321_CHIP_ID 0x4321 /* 4321 chip common chipid */ -#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */ -#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Hgz band id */ -#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */ - -#define BCM4331_CHIP_ID 0x4331 /* 4331 chip common chipid */ -#define BCM4331_D11N2G_ID 0x4330 /* 4331 802.11n 2.4Ghz band id */ -#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ -#define BCM4331_D11N5G_ID 0x4332 /* 4331 802.11n 5Ghz band id */ - -#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ -#define HDLSIM_PKG_ID 14 /* HDL simulator package id */ -#define HWSIM_PKG_ID 15 /* Hardware simulator package id */ - +#define BCM4328_CHIP_ID 0x4328 /* 4328 chip common chipid */ +#define BCM4325_CHIP_ID 0x4325 /* 4325 chip common chipid */ #define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ -#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ -#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ -#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ -#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ - #define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */ #define BCM5350_CHIP_ID 0x5350 /* bcm5350 chipcommon chipid */ #define BCM5352_CHIP_ID 0x5352 /* bcm5352 chipcommon chipid */ - +#define BCM5354_CHIP_ID 0x5354 /* bcm5354 chipcommon chipid */ #define BCM4320_CHIP_ID 0x4320 /* bcm4320 chipcommon chipid */ - -#define BCM4328_CHIP_ID 0x4328 /* bcm4328 chipcommon chipid */ - -#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */ -#define BCM43XX_JTAGM_ID 0x43f1 /* 43xx jtagm device id */ -#define BCM43XXOLD_JTAGM_ID 0x4331 /* 43xx old jtagm device id */ - -#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */ -#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */ - -#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */ - #define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */ -/* PCMCIA vendor Id's */ - -#define VENDOR_BROADCOM_PCMCIA 0x02d0 - -/* SDIO vendor Id's */ -#define VENDOR_BROADCOM_SDIO 0x00BF - +/* Package IDs */ +#define BCM4303_PKG_ID 2 /* 4303 package id */ +#define BCM4309_PKG_ID 1 /* 4309 package id */ +#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ +#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ +#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ +#define BCM4328USBD11G_PKG_ID 2 /* 4328 802.11g USB package id */ +#define BCM4328USBDUAL_PKG_ID 3 /* 4328 802.11a/g USB package id */ +#define BCM4328SDIOD11G_PKG_ID 4 /* 4328 802.11g SDIO package id */ +#define BCM4328SDIODUAL_PKG_ID 5 /* 4328 802.11a/g SDIO package id */ +#define BCM5354E_PKG_ID 1 /* 5354E package id */ +#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ +#define HDLSIM_PKG_ID 14 /* HDL simulator package id */ +#define HWSIM_PKG_ID 15 /* Hardware simulator package id */ +#define PCIXX21_FLASHMEDIA0_ID 0x8033 /* TI PCI xx21 Standard Host Controller */ +#define PCIXX21_SDIOH0_ID 0x8034 /* TI PCI xx21 Standard Host Controller */ /* boardflags */ -#define BFL_BTCOEXIST 0x0001 /* This board implements Bluetooth coexistance */ -#define BFL_PACTRL 0x0002 /* This board has gpio 9 controlling the PA */ -#define BFL_AIRLINEMODE 0x0004 /* This board implements gpio13 radio disable indication */ -#define BFL_ENETROBO 0x0010 /* This board has robo switch or core */ -#define BFL_CCKHIPWR 0x0040 /* Can do high-power CCK transmission */ -#define BFL_ENETADM 0x0080 /* This board has ADMtek switch */ -#define BFL_ENETVLAN 0x0100 /* This board has vlan capability */ -#define BFL_AFTERBURNER 0x0200 /* This board supports Afterburner mode */ -#define BFL_NOPCI 0x0400 /* This board leaves PCI floating */ -#define BFL_FEM 0x0800 /* This board supports the Front End Module */ -#define BFL_EXTLNA 0x1000 /* This board has an external LNA */ -#define BFL_HGPA 0x2000 /* This board has a high gain PA */ -#define BFL_BTCMOD 0x4000 /* This board' BTCOEXIST is in the alternate gpios */ -#define BFL_ALTIQ 0x8000 /* Alternate I/Q settings */ - +#define BFL_BTCOEXIST 0x00000001 /* This board implements Bluetooth coexistance */ +#define BFL_PACTRL 0x00000002 /* This board has gpio 9 controlling the PA */ +#define BFL_AIRLINEMODE 0x00000004 /* This board implements gpio13 radio disable indication */ +#define BFL_ADCDIV 0x00000008 /* This board has the rssi ADC divider */ +#define BFL_ENETROBO 0x00000010 /* This board has robo switch or core */ +#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ +#define BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */ +#define BFL_ENETADM 0x00000080 /* This board has ADMtek switch */ +#define BFL_ENETVLAN 0x00000100 /* This board has vlan capability */ +#define BFL_AFTERBURNER 0x00000200 /* This board supports Afterburner mode */ +#define BFL_NOPCI 0x00000400 /* This board leaves PCI floating */ +#define BFL_FEM 0x00000800 /* This board supports the Front End Module */ +#define BFL_EXTLNA 0x00001000 /* This board has an external LNA */ +#define BFL_HGPA 0x00002000 /* This board has a high gain PA */ +#define BFL_BTCMOD 0x00004000 /* This board' BTCOEXIST is in the alternate gpios */ +#define BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */ +#define BFL_NOPA 0x00010000 /* This board has no PA */ +#define BFL_RSSIINV 0x00020000 /* This board's RSSI uses positive slope */ +#define BFL_PAREF 0x00040000 /* This board uses the PARef LDO */ +#define BFL_3TSWITCH 0x00080000 /* This board uses a triple throw switch shared with BT */ +#define BFL_PHASESHIFTER 0x00100000 /* This board can support phase shifter */ +#define BFL_BUCKBOOST 0x00200000 /* This board has buck/booster */ /* boardflags2 */ #define BFL2_RXBB_INT_REG_DIS 0x00000001 /* This board has an external rxbb regulator */ -#define BFL2_SSWITCH_AVAIL 0x00000002 /* This board has a superswitch for > 2 antennas */ -#define BFL2_TXPWRCTRL_EN 0x00000004 /* This board permits TX Power Control to be enabled */ +#define BFL2_DEPRECIATED_STUB 0x00000002 /* This board flag is depreciated */ +#define BFL2_TXPWRCTRL_EN 0x00000004 /* This board permits enabling TX Power Control */ +#define BFL2_2X4_DIV 0x00000008 /* This board supports the 2X4 diversity switch */ +#define BFL2_5G_PWRGAIN 0x00000010 /* This board supports 5G band power gain */ +#define BFL2_PCIEWAR_OVR 0x00000020 /* This board overrides ASPM and Clkreq settings */ +#define BFL2_CAESERS_BRD 0x00000040 /* This board is Dell Caeser's brd (unused by sw) */ /* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ #define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistance Input */ @@ -172,6 +178,9 @@ #define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistance Input */ #define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistance Out */ #define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ +#define BOARD_GPIO_ANT0_SEL 0x100 /* With BFL2_2X4_DIV */ +#define BOARD_GPIO_ANT1_SEL 0x200 /* With BFL2_2X4_DIV */ + #define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ #define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ #define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ @@ -184,7 +193,6 @@ #define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ /* Reference Board Types */ - #define BU4710_BOARD 0x0400 #define VSIM4710_BOARD 0x0401 #define QT4710_BOARD 0x0402 @@ -259,6 +267,7 @@ /* BCM63XX boards */ #define BCM96338_BOARD 0x6338 #define BCM96348_BOARD 0x6348 +#define BCM96358_BOARD 0x6358 /* Another mp4306 with SiGe */ #define BCM94306P_BOARD 0x044c @@ -333,6 +342,18 @@ #define CB2_4321_BOARD 0x046d #define MC4321_BOARD 0x046e +/* 4328 boards */ +#define BU4328_BOARD 0x0481 +#define BCM4328SDG_BOARD 0x0482 +#define BCM4328SDAG_BOARD 0x0483 +#define BCM4328UG_BOARD 0x0484 +#define BCM4328UAG_BOARD 0x0485 +#define BCM4328PC_BOARD 0x0486 +#define BCM4328CF_BOARD 0x0487 + +/* 4325 boards */ +#define BU4325_BOARD 0x0490 + /* # of GPIO pins */ #define GPIO_NUMPINS 16 @@ -358,6 +379,10 @@ #define BCM2062_IDCODE 0x02062000 #define BCM2062A0_IDCODE 0x0206217f +#define BCM2063_ID 0x2063 +#define BCM2063_IDCODE 0x02063000 +#define BCM2063A0_IDCODE 0x0206317f + /* parts of an idcode: */ #define IDCODE_MFG_MASK 0x00000fff #define IDCODE_MFG_SHIFT 0 diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmendian.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmendian.h index 906129c82e..0f68451132 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmendian.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmendian.h @@ -1,7 +1,7 @@ /* * local version of endian.h - byte order defines * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: bcmendian.h,v 1.1.1.10 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _BCMENDIAN_H_ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmnvram.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmnvram.h index c713b4be69..f6754b6fb3 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmnvram.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmnvram.h @@ -1,7 +1,7 @@ /* * NVRAM variable manipulation * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: bcmnvram.h,v 1.17 2006/03/02 12:33:44 honor Exp $ + * $Id$ */ #ifndef _bcmnvram_h_ @@ -35,10 +35,19 @@ struct nvram_tuple { }; /* - * Initialize NVRAM access. May be unnecessary or undefined on certain - * platforms. + * Get default value for an NVRAM variable + */ +extern char *nvram_default_get(const char *name); + +/* + * Append a chunk of nvram variables to the global list + */ +extern int nvram_append(void *sb, char *vars, uint varsz); + +/* + * Check for reset button press for restoring factory defaults. */ -extern int nvram_init(void *sbh); +extern bool nvram_reset(void *sbh); /* * Disable NVRAM access. May be unnecessary or undefined on certain @@ -59,8 +68,6 @@ extern char * nvram_get(const char *name); * as input */ extern int BCMINITFN(nvram_resetgpio_init)(void *sbh); -extern int BCMINITFN(nvram_gpio_init)(const char *name, void *sbh); -extern int BCMINITFN(nvram_gpio_set)(const char *name, void *sbh, int type); /* * Get the value of an NVRAM variable. @@ -69,16 +76,6 @@ extern int BCMINITFN(nvram_gpio_set)(const char *name, void *sbh, int type); */ #define nvram_safe_get(name) (nvram_get(name) ? : "") -#define nvram_safe_unset(name) ({ \ - if(nvram_get(name)) \ - nvram_unset(name); \ -}) - -#define nvram_safe_set(name, value) ({ \ - if(!nvram_get(name) || strcmp(nvram_get(name), value)) \ - nvram_set(name, value); \ -}) - /* * Match an NVRAM variable. * @param name name of variable to match @@ -139,15 +136,24 @@ extern int nvram_commit(void); * @param count size of buffer in bytes * @return 0 on success and errno on failure */ -extern int nvram_getall(char *buf, int count); +extern int nvram_getall(char *nvram_buf, int count); -extern int file2nvram(char *filename, char *varname); -extern int nvram2file(char *varname, char *filename); +/* + * returns the crc value of the nvram + * @param nvh nvram header pointer + */ +extern uint8 nvram_calc_crc(struct nvram_header * nvh); + +extern char* getvar(char *vars, const char *name); +extern int getintvar(char *vars, const char *name); #endif /* _LANGUAGE_ASSEMBLY */ +/* The NVRAM version number stored as an NVRAM variable */ +#define NVRAM_SOFTWARE_VERSION "1" + #define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ -#define NVRAM_CLEAR_MAGIC 0x0 +#define NVRAM_CLEAR_MAGIC 0x0 #define NVRAM_INVALID_MAGIC 0xFFFFFFFF #define NVRAM_VERSION 1 #define NVRAM_HEADER_SIZE 20 @@ -156,4 +162,7 @@ extern int nvram2file(char *varname, char *filename); #define NVRAM_MAX_VALUE_LEN 255 #define NVRAM_MAX_PARAM_LEN 64 +#define NVRAM_CRC_START_POSITION 9 /* magic, len, crc8 to be skipped */ +#define NVRAM_CRC_VER_MASK 0xffffff00 /* for crc_ver_init */ + #endif /* _bcmnvram_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmsrom.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmsrom.h index 4f99e95914..1db4fbd638 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmsrom.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmsrom.h @@ -1,7 +1,7 @@ /* * Misc useful routines to access NIC local SROM/OTP . * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,14 +9,93 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: bcmsrom.h,v 1.1.1.13 2006/04/15 01:29:08 michael Exp $ + * $Id$ */ #ifndef _bcmsrom_h_ #define _bcmsrom_h_ /* Maximum srom: 4 Kilobits == 512 bytes */ -#define SROM_MAX 512 +#define SROM_MAX 512 + + +#define SROM_WORDS 64 + +#define SROM3_SWRGN_OFF 28 /* s/w region offset in words */ + +#define SROM_SSID 2 + +#define SROM_WL1LHMAXP 29 + +#define SROM_WL1LPAB0 30 +#define SROM_WL1LPAB1 31 +#define SROM_WL1LPAB2 32 + +#define SROM_WL1HPAB0 33 +#define SROM_WL1HPAB1 34 +#define SROM_WL1HPAB2 35 + +#define SROM_MACHI_IL0 36 +#define SROM_MACMID_IL0 37 +#define SROM_MACLO_IL0 38 +#define SROM_MACHI_ET0 39 +#define SROM_MACMID_ET0 40 +#define SROM_MACLO_ET0 41 +#define SROM_MACHI_ET1 42 +#define SROM_MACMID_ET1 43 +#define SROM_MACLO_ET1 44 +#define SROM3_MACHI 37 +#define SROM3_MACMID 38 +#define SROM3_MACLO 39 + +#define SROM_BXARSSI2G 40 +#define SROM_BXARSSI5G 41 + +#define SROM_TRI52G 42 +#define SROM_TRI5GHL 43 + +#define SROM_RXPO52G 45 + +#define SROM2_ENETPHY 45 + +#define SROM_AABREV 46 +/* Fields in AABREV */ +#define SROM_BR_MASK 0x00ff +#define SROM_CC_MASK 0x0f00 +#define SROM_CC_SHIFT 8 +#define SROM_AA0_MASK 0x3000 +#define SROM_AA0_SHIFT 12 +#define SROM_AA1_MASK 0xc000 +#define SROM_AA1_SHIFT 14 + +#define SROM_WL0PAB0 47 +#define SROM_WL0PAB1 48 +#define SROM_WL0PAB2 49 + +#define SROM_LEDBH10 50 +#define SROM_LEDBH32 51 + +#define SROM_WL10MAXP 52 + +#define SROM_WL1PAB0 53 +#define SROM_WL1PAB1 54 +#define SROM_WL1PAB2 55 + +#define SROM_ITT 56 + +#define SROM_BFL 57 +#define SROM_BFL2 28 +#define SROM3_BFL2 61 + +#define SROM_AG10 58 + +#define SROM_CCODE 59 + +#define SROM_OPO 60 + +#define SROM3_LEDDC 62 + +#define SROM_CRCREV 63 /* SROM Rev 4: Reallocate the software part of the srom to accomodate * MIMO features. It assumes up to two PCIE functions and 440 bytes @@ -35,18 +114,30 @@ #define SROM4_BFL1 35 #define SROM4_BFL2 36 #define SROM4_BFL3 37 +#define SROM5_BFL0 37 +#define SROM5_BFL1 38 +#define SROM5_BFL2 39 +#define SROM5_BFL3 40 #define SROM4_MACHI 38 #define SROM4_MACMID 39 #define SROM4_MACLO 40 +#define SROM5_MACHI 41 +#define SROM5_MACMID 42 +#define SROM5_MACLO 43 #define SROM4_CCODE 41 #define SROM4_REGREV 42 +#define SROM5_CCODE 34 +#define SROM5_REGREV 35 #define SROM4_LEDBH10 43 #define SROM4_LEDBH32 44 +#define SROM5_LEDBH10 59 +#define SROM5_LEDBH32 60 #define SROM4_LEDDC 45 +#define SROM5_LEDDC 45 #define SROM4_AA 46 #define SROM4_AA2G_MASK 0x00ff @@ -62,6 +153,14 @@ #define SROM4_TXPID5GL 53 #define SROM4_TXPID5GH 55 +#define SROM4_TXRXC 61 +#define SROM4_TXCHAIN_MASK 0x000f +#define SROM4_TXCHAIN_SHIFT 0 +#define SROM4_RXCHAIN_MASK 0x00f0 +#define SROM4_RXCHAIN_SHIFT 4 +#define SROM4_SWITCH_MASK 0xff00 +#define SROM4_SWITCH_SHIFT 8 + /* Per-path fields */ #define MAX_PATH 4 #define SROM4_PATH0 64 @@ -95,14 +194,117 @@ #define SROM4_5G_MCSPO 173 #define SROM4_5GL_MCSPO 181 #define SROM4_5GH_MCSPO 189 -#define SROM4_CCDPO 197 +#define SROM4_CDDPO 197 #define SROM4_STBCPO 198 #define SROM4_BW40PO 199 #define SROM4_BWDUPPO 200 -extern int srom_var_init(void *sbh, uint bus, void *curmap, osl_t *osh, char **vars, uint *count); +#define SROM4_CRCREV 219 + + +/*SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. + * This is acombined srom for both MIMO and SISO boards, usable in + * the .130 4Kilobit OTP with hardware redundancy. + */ + +#define SROM8_SIGN 64 + +#define SROM8_BREV 65 + +#define SROM8_BFL0 66 +#define SROM8_BFL1 67 +#define SROM8_BFL2 68 +#define SROM8_BFL3 69 + +#define SROM8_MACHI 70 +#define SROM8_MACMID 71 +#define SROM8_MACLO 72 + +#define SROM8_CCODE 73 +#define SROM8_REGREV 74 + +#define SROM8_LEDBH10 75 +#define SROM8_LEDBH32 76 + +#define SROM8_LEDDC 77 + +#define SROM8_AA 78 + +#define SROM8_AG10 79 +#define SROM8_AG32 80 + +#define SROM8_TXRXC 81 + +#define SROM8_BXARSSI2G 82 +#define SROM8_BXARSSI5G 83 +#define SROM8_TRI52G 84 +#define SROM8_TRI5GHL 85 +#define SROM8_RXPO52G 86 + +/* Per-path offsets & fields */ +#define SROM8_PATH0 96 +#define SROM8_PATH1 112 +#define SROM8_PATH2 128 +#define SROM8_PATH3 144 + +#define SROM8_2G_ITT_MAXP 0 +#define SROM8_2G_PA 1 +#define SROM8_5G_ITT_MAXP 4 +#define SROM8_5GLH_MAXP 5 +#define SROM8_5G_PA 6 +#define SROM8_5GL_PA 9 +#define SROM8_5GH_PA 12 + +/* All the miriad power offsets */ +#define SROM8_2G_CCKPO 160 + +#define SROM8_2G_OFDMPO 161 +#define SROM8_5G_OFDMPO 163 +#define SROM8_5GL_OFDMPO 165 +#define SROM8_5GH_OFDMPO 167 + +#define SROM8_2G_MCSPO 169 +#define SROM8_5G_MCSPO 177 +#define SROM8_5GL_MCSPO 185 +#define SROM8_5GH_MCSPO 193 + +#define SROM8_CDDPO 201 +#define SROM8_STBCPO 202 +#define SROM8_BW40PO 203 +#define SROM8_BWDUPPO 204 + +/* SISO PA parameters are in the path0 spaces */ +#define SROM8_SISO 96 + +/* Legacy names for SISO PA paramters */ +#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) +#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) +#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) +#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) +#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) +#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) +#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) +#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) +#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) +#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) +#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) +#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) +#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) +#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) +#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) + +#define SROM8_CRCREV 219 + +/* Prototypes */ +extern int srom_var_init(sb_t *sbh, uint bus, void *curmap, osl_t *osh, + char **vars, uint *count); + +extern int srom_read(sb_t *sbh, uint bus, void *curmap, osl_t *osh, + uint byteoff, uint nbytes, uint16 *buf); +extern int srom_write(sb_t *sbh, uint bus, void *curmap, osl_t *osh, + uint byteoff, uint nbytes, uint16 *buf); -extern int srom_read(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf); -extern int srom_write(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf); +extern int srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, + char **vars, uint *count); #endif /* _bcmsrom_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmutils.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmutils.h deleted file mode 100644 index b200f62364..0000000000 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/bcmutils.h +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Misc useful os-independent macros and functions. - * - * Copyright 2006, Broadcom Corporation - * All Rights Reserved. - * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * $Id: bcmutils.h,v 1.1.1.16 2006/04/08 06:13:39 honor Exp $ - */ - -#ifndef _bcmutils_h_ -#define _bcmutils_h_ - -/* ** driver-only section ** */ -#ifdef BCMDRIVER - -#define _BCM_U 0x01 /* upper */ -#define _BCM_L 0x02 /* lower */ -#define _BCM_D 0x04 /* digit */ -#define _BCM_C 0x08 /* cntrl */ -#define _BCM_P 0x10 /* punct */ -#define _BCM_S 0x20 /* white space (space/lf/tab) */ -#define _BCM_X 0x40 /* hex digit */ -#define _BCM_SP 0x80 /* hard space (0x20) */ - -#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ - -extern unsigned char bcm_ctype[]; -#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) - -#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) -#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) -#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) -#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) -#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) -#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) -#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) -#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) -#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) -#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) -#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) - -/* - * Spin at most 'us' microseconds while 'exp' is true. - * Caller should explicitly test 'exp' when this completes - * and take appropriate error action if 'exp' is still true. - */ -#define SPINWAIT(exp, us) { \ - uint countdown = (us) + 9; \ - while ((exp) && (countdown >= 10)) {\ - OSL_DELAY(10); \ - countdown -= 10; \ - } \ -} - -struct ether_addr { - uint8 octet[6]; -} __attribute__((packed)); - -/* string */ -extern uchar bcm_toupper(uchar c); -extern ulong bcm_strtoul(char *cp, char **endp, uint base); -extern char *bcmstrstr(char *haystack, char *needle); -extern char *bcmstrcat(char *dest, const char *src); -extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); -/* ethernet address */ -extern char *bcm_ether_ntoa(struct ether_addr *ea, char *buf); -/* variable access */ -extern char *getvar(char *vars, char *name); -extern int getintvar(char *vars, char *name); -extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); -#ifdef BCMPERFSTATS -extern void bcm_perf_enable(void); -extern void bcmstats(char *fmt); -extern void bcmlog(char *fmt, uint a1, uint a2); -extern void bcmdumplog(char *buf, int size); -extern int bcmdumplogent(char *buf, uint idx); -#else -#define bcm_perf_enable() -#define bcmstats(fmt) -#define bcmlog(fmt, a1, a2) -#define bcmdumplog(buf, size) *buf = '\0' -#define bcmdumplogent(buf, idx) -1 -#endif /* BCMPERFSTATS */ -extern char *bcm_nvram_vars(uint *length); -extern int bcm_nvram_cache(void *sbh); - -/* Support for sharing code across in-driver iovar implementations. - * The intent is that a driver use this structure to map iovar names - * to its (private) iovar identifiers, and the lookup function to - * find the entry. Macros are provided to map ids and get/set actions - * into a single number space for a switch statement. - */ - -/* iovar structure */ -typedef struct bcm_iovar { - const char *name; /* name for lookup and display */ - uint16 varid; /* id for switch */ - uint16 flags; /* driver-specific flag bits */ - uint16 type; /* base type of argument */ - uint16 minlen; /* min length for buffer vars */ -} bcm_iovar_t; - -/* varid definitions are per-driver, may use these get/set bits */ - -/* IOVar action bits for id mapping */ -#define IOV_GET 0 /* Get an iovar */ -#define IOV_SET 1 /* Set an iovar */ - -/* Varid to actionid mapping */ -#define IOV_GVAL(id) ((id)*2) -#define IOV_SVAL(id) (((id)*2)+IOV_SET) -#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) - -/* flags are per-driver based on driver attributes */ - -/* Base type definitions */ -#define IOVT_VOID 0 /* no value (implictly set only) */ -#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ -#define IOVT_INT8 2 /* integer values are range-checked */ -#define IOVT_UINT8 3 /* unsigned int 8 bits */ -#define IOVT_INT16 4 /* int 16 bits */ -#define IOVT_UINT16 5 /* unsigned int 16 bits */ -#define IOVT_INT32 6 /* int 32 bits */ -#define IOVT_UINT32 7 /* unsigned int 32 bits */ -#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ - -extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); -extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); - -#endif /* #ifdef BCMDRIVER */ - -/* ** driver/apps-shared section ** */ - -#define BCME_STRLEN 64 /* Max string length for BCM errors */ -#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) - - -/* - * error codes could be added but the defined ones shouldn't be changed/deleted - * these error codes are exposed to the user code - * when ever a new error code is added to this list - * please update errorstring table with the related error string and - * update osl files with os specific errorcode map -*/ - -#define BCME_OK 0 /* Success */ -#define BCME_ERROR -1 /* Error generic */ -#define BCME_BADARG -2 /* Bad Argument */ -#define BCME_BADOPTION -3 /* Bad option */ -#define BCME_NOTUP -4 /* Not up */ -#define BCME_NOTDOWN -5 /* Not down */ -#define BCME_NOTAP -6 /* Not AP */ -#define BCME_NOTSTA -7 /* Not STA */ -#define BCME_BADKEYIDX -8 /* BAD Key Index */ -#define BCME_RADIOOFF -9 /* Radio Off */ -#define BCME_NOTBANDLOCKED -10 /* Not band locked */ -#define BCME_NOCLK -11 /* No Clock */ -#define BCME_BADRATESET -12 /* BAD Rate valueset */ -#define BCME_BADBAND -13 /* BAD Band */ -#define BCME_BUFTOOSHORT -14 /* Buffer too short */ -#define BCME_BUFTOOLONG -15 /* Buffer too long */ -#define BCME_BUSY -16 /* Busy */ -#define BCME_NOTASSOCIATED -17 /* Not Associated */ -#define BCME_BADSSIDLEN -18 /* Bad SSID len */ -#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ -#define BCME_BADCHAN -20 /* Bad Channel */ -#define BCME_BADADDR -21 /* Bad Address */ -#define BCME_NORESOURCE -22 /* Not Enough Resources */ -#define BCME_UNSUPPORTED -23 /* Unsupported */ -#define BCME_BADLEN -24 /* Bad length */ -#define BCME_NOTREADY -25 /* Not Ready */ -#define BCME_EPERM -26 /* Not Permitted */ -#define BCME_NOMEM -27 /* No Memory */ -#define BCME_ASSOCIATED -28 /* Associated */ -#define BCME_RANGE -29 /* Not In Range */ -#define BCME_NOTFOUND -30 /* Not Found */ -#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ -#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ -#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ -#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ -#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ -#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ -#define BCME_LAST BCME_DONGLE_DOWN - -/* These are collection of BCME Error strings */ -#define BCMERRSTRINGTABLE { \ - "OK", \ - "Undefined error", \ - "Bad Argument", \ - "Bad Option", \ - "Not up", \ - "Not down", \ - "Not AP", \ - "Not STA", \ - "Bad Key Index", \ - "Radio Off", \ - "Not band locked", \ - "No clock", \ - "Bad Rate valueset", \ - "Bad Band", \ - "Buffer too short", \ - "Buffer too long", \ - "Busy", \ - "Not Associated", \ - "Bad SSID len", \ - "Out of Range Channel", \ - "Bad Channel", \ - "Bad Address", \ - "Not Enough Resources", \ - "Unsupported", \ - "Bad length", \ - "Not Ready", \ - "Not Permitted", \ - "No Memory", \ - "Associated", \ - "Not In Range", \ - "Not Found", \ - "WME Not Enabled", \ - "TSPEC Not Found", \ - "ACM Not Supported", \ - "Not WME Association", \ - "SDIO Bus Error", \ - "Dongle Not Accessible" \ -} - -#ifndef ABS -#define ABS(a) (((a) < 0)?-(a):(a)) -#endif /* ABS */ - -#ifndef MIN -#define MIN(a, b) (((a) < (b))?(a):(b)) -#endif /* MIN */ - -#ifndef MAX -#define MAX(a, b) (((a) > (b))?(a):(b)) -#endif /* MAX */ - -#define CEIL(x, y) (((x) + ((y)-1)) / (y)) -#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) -#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0) -#define ISPOWEROF2(x) ((((x)-1)&(x)) == 0) -#define VALID_MASK(mask) !((mask) & ((mask) + 1)) -#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) -#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) - -/* bit map related macros */ -#ifndef setbit -#ifndef NBBY /* the BSD family defines NBBY */ -#define NBBY 8 /* 8 bits per byte */ -#endif /* #ifndef NBBY */ -#define setbit(a, i) (((uint8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) -#define clrbit(a, i) (((uint8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) -#define isset(a, i) (((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) -#define isclr(a, i) ((((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -#endif /* setbit */ - -#define NBITS(type) (sizeof(type) * 8) -#define NBITVAL(nbits) (1 << (nbits)) -#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) -#define NBITMASK(nbits) MAXBITVAL(nbits) -#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) - -/* basic mux operation - can be optimized on several architectures */ -#define MUX(pred, true, false) ((pred) ? (true) : (false)) - -/* modulo inc/dec - assumes x E [0, bound - 1] */ -#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) -#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) - -/* modulo inc/dec, bound = 2^k */ -#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) -#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) - -/* modulo add/sub - assumes x, y E [0, bound - 1] */ -#define MODADD(x, y, bound) \ - MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) -#define MODSUB(x, y, bound) \ - MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) - -/* module add/sub, bound = 2^k */ -#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) -#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) - -/* crc defines */ -#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ -#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ -#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ -#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ -#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ -#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ - -/* bcm_format_flags() bit description structure */ -typedef struct bcm_bit_desc { - uint32 bit; - char* name; -} bcm_bit_desc_t; - -/* tag_ID/length/value_buffer tuple */ -typedef struct bcm_tlv { - uint8 id; - uint8 len; - uint8 data[1]; -} bcm_tlv_t; - -/* Check that bcm_tlv_t fits into the given buflen */ -#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) - -/* buffer length for ethernet address from bcm_ether_ntoa() */ -#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ - -/* unaligned load and store macros */ -#ifdef IL_BIGENDIAN -static INLINE uint32 -load32_ua(uint8 *a) -{ - return ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]); -} - -static INLINE void -store32_ua(uint8 *a, uint32 v) -{ - a[0] = (v >> 24) & 0xff; - a[1] = (v >> 16) & 0xff; - a[2] = (v >> 8) & 0xff; - a[3] = v & 0xff; -} - -static INLINE uint16 -load16_ua(uint8 *a) -{ - return ((a[0] << 8) | a[1]); -} - -static INLINE void -store16_ua(uint8 *a, uint16 v) -{ - a[0] = (v >> 8) & 0xff; - a[1] = v & 0xff; -} - -#else - -static INLINE uint32 -load32_ua(uint8 *a) -{ - return ((a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]); -} - -static INLINE void -store32_ua(uint8 *a, uint32 v) -{ - a[3] = (v >> 24) & 0xff; - a[2] = (v >> 16) & 0xff; - a[1] = (v >> 8) & 0xff; - a[0] = v & 0xff; -} - -static INLINE uint16 -load16_ua(uint8 *a) -{ - return ((a[1] << 8) | a[0]); -} - -static INLINE void -store16_ua(uint8 *a, uint16 v) -{ - a[1] = (v >> 8) & 0xff; - a[0] = v & 0xff; -} - -#endif /* IL_BIGENDIAN */ - -/* externs */ -/* crc */ -extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc); -extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc); -extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); -/* format/print */ -extern void printfbig(char *buf); - -/* IE parsing */ -extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen); -extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); -extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key); - -/* bcmerror */ -extern const char *bcmerrorstr(int bcmerror); - -/* multi-bool data type: set of bools, mbool is true if any is set */ -typedef uint32 mbool; -#define mboolset(mb, bit) (mb |= bit) /* set one bool */ -#define mboolclr(mb, bit) (mb &= ~bit) /* clear one bool */ -#define mboolisset(mb, bit) ((mb & bit) != 0) /* TRUE if one bool is set */ -#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) - -/* power conversion */ -extern uint16 bcm_qdbm_to_mw(uint8 qdbm); -extern uint8 bcm_mw_to_qdbm(uint16 mw); - -/* generic datastruct to help dump routines */ -struct fielddesc { - char *nameandfmt; - uint32 offset; - uint32 len; -}; - -/* Buffer structure for collecting string-formatted data -* using bcm_bprintf() API. -* Use bcm_binit() to initialize before use -*/ -struct bcmstrbuf -{ - char *buf; /* pointer to current position in origbuf */ - uint size; /* current (residual) size in bytes */ - char *origbuf; /* unmodified pointer to orignal buffer */ - uint origsize; /* unmodified orignal buffer size in bytes */ -}; - -extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); -extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); - -typedef uint32 (*readreg_rtn)(void *arg0, void *arg1, uint32 offset); -extern uint bcmdumpfields(readreg_rtn func_ptr, void *arg0, void *arg1, struct fielddesc *str, - char *buf, uint32 bufsize); - -extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); -extern uint bcm_bitcount(uint8 *bitmap, uint bytelength); - -#endif /* _bcmutils_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndchipc.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndchipc.h new file mode 100644 index 0000000000..44423aafdf --- /dev/null +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndchipc.h @@ -0,0 +1,31 @@ +/* + * HND SiliconBackplane chipcommon support. + * + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id$ + */ + +#ifndef _hndchipc_h_ +#define _hndchipc_h_ + +typedef void (*sb_serial_init_fn)(void *regs, uint irq, uint baud_base, uint reg_shift); + +extern void sb_serial_init(sb_t *sbh, sb_serial_init_fn add); + +extern void *sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap); +extern void sb_jtagm_disable(osl_t *osh, void *h); +extern uint32 jtag_rwreg(osl_t *osh, void *h, uint32 ir, uint32 dr); + +typedef void (*cc_isr_fn)(void* cbdata, uint32 ccintst); + +extern bool sb_cc_register_isr(sb_t *sbh, cc_isr_fn isr, uint32 ccintmask, void *cbdata); +extern void sb_cc_isr(sb_t *sbh, chipcregs_t *regs); + +#endif /* _hndchipc_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndcpu.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndcpu.h index b9844b02e8..78afb5256c 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndcpu.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndcpu.h @@ -1,7 +1,7 @@ /* * HND SiliconBackplane MIPS/ARM cores software interface. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: hndcpu.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _hndcpu_h_ @@ -17,12 +17,14 @@ #if defined(mips) #include <hndmips.h> -#elif defined(__ARM_ARCH_4T__) +#elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__) #include <hndarm.h> #endif extern uint sb_irq(sb_t *sbh); extern uint32 sb_cpu_clock(sb_t *sbh); -extern void sb_cpu_wait(void); +extern void hnd_cpu_wait(sb_t *sbh); +extern void hnd_cpu_jumpto(void *addr); +extern void hnd_cpu_reset(sb_t *sbh); #endif /* _hndcpu_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndmips.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndmips.h index cd771cac3f..95dc68c633 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndmips.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndmips.h @@ -1,7 +1,7 @@ /* * HND SiliconBackplane MIPS core software interface. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: hndmips.h,v 1.1.1.8 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _hndmips_h_ @@ -22,6 +22,7 @@ extern uint32 sb_memc_get_ncdl(sb_t *sbh); #if defined(BCMPERFSTATS) /* enable counting - exclusive version. Only one set of counters allowed at a time */ +extern void hndmips_perf_cyclecount_enable(void); extern void hndmips_perf_instrcount_enable(void); extern void hndmips_perf_icachecount_enable(void); extern void hndmips_perf_dcachecount_enable(void); @@ -40,6 +41,6 @@ extern void hndmips_perf_icache_miss_enable(void); extern uint32 hndmips_perf_read_instrcount(void); extern uint32 hndmips_perf_read_cache_miss(void); extern uint32 hndmips_perf_read_cache_hit(void); -#endif /* defined(BCMINTERNAL) || defined (BCMPERFSTATS) */ +#endif #endif /* _hndmips_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndpci.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndpci.h index 6ae0efff48..d190ea99cd 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndpci.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndpci.h @@ -1,8 +1,8 @@ /* * HND SiliconBackplane PCI core software interface. * - * $Id: hndpci.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ - * Copyright 2006, Broadcom Corporation + * $Id$ + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -25,6 +25,9 @@ extern int extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint of extern void sbpci_ban(uint16 core); extern int sbpci_init(sb_t *sbh); extern int sbpci_init_pci(sb_t *sbh); -extern void sbpci_check(sb_t *sbh); +extern void sbpci_init_cores(sb_t *sbh); +extern void sbpci_arb_park(sb_t *sbh, uint parkid); + +#define PCI_PARK_NVRAM 0xff #endif /* _hndpci_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndpmu.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndpmu.h new file mode 100644 index 0000000000..1bd68728ca --- /dev/null +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/hndpmu.h @@ -0,0 +1,37 @@ +/* + * HND SiliconBackplane PMU support. + * + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id$ + */ + +#ifndef _hndpmu_h_ +#define _hndpmu_h_ + +#define SET_LDO_VOLTAGE_LDO1 1 +#define SET_LDO_VOLTAGE_LDO2 2 +#define SET_LDO_VOLTAGE_LDO3 3 +#define SET_LDO_VOLTAGE_PAREF 4 + +extern void sb_pmu_init(sb_t *sbh, osl_t *osh); +extern void sb_pmu_pll_init(sb_t *sbh, osl_t *osh, uint32 xtalfreq); +extern void sb_pmu_res_init(sb_t *sbh, osl_t *osh); +extern uint32 sb_pmu_force_ilp(sb_t *sbh, osl_t *osh, bool force); +extern uint32 sb_pmu_cpu_clock(sb_t *sbh, osl_t *osh); +extern uint32 sb_pmu_alp_clock(sb_t *sbh, osl_t *osh); + +extern void sb_pmu_set_switcher_voltage(sb_t *sbh, osl_t *osh, uint8 bb_voltage, uint8 rf_voltage); +extern void sb_pmu_set_ldo_voltage(sb_t *sbh, osl_t *osh, uint8 ldo, uint8 voltage); +extern void sb_pmu_paref_ldo_enable(sb_t *sbh, osl_t *osh, bool enable); +extern uint16 sb_pmu_fast_pwrup_delay(sb_t *sbh, osl_t *osh); +extern void sb_pmu_otp_power(sb_t *sbh, osl_t *osh, bool on); +extern void sb_pmu_rcal(sb_t *sbh, osl_t *osh); + +#endif /* _hndpmu_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/linux_gpio.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/linux_gpio.h new file mode 100644 index 0000000000..f74e92c64f --- /dev/null +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/linux_gpio.h @@ -0,0 +1,33 @@ +/* + * Linux Broadcom BCM47xx GPIO char driver + * + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id$ + */ + +#ifndef _linux_gpio_h_ +#define _linux_gpio_h_ + +struct gpio_ioctl { + uint32 mask; + uint32 val; +}; + +#define GPIO_IOC_MAGIC 'G' + +/* reserve/release a gpio to the caller */ +#define GPIO_IOC_RESERVE _IOWR(GPIO_IOC_MAGIC, 1, struct gpio_ioctl) +#define GPIO_IOC_RELEASE _IOWR(GPIO_IOC_MAGIC, 2, struct gpio_ioctl) +/* ioctls to read/write the gpio registers */ +#define GPIO_IOC_OUT _IOWR(GPIO_IOC_MAGIC, 3, struct gpio_ioctl) +#define GPIO_IOC_IN _IOWR(GPIO_IOC_MAGIC, 4, struct gpio_ioctl) +#define GPIO_IOC_OUTEN _IOWR(GPIO_IOC_MAGIC, 5, struct gpio_ioctl) + +#endif /* _linux_gpio_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/linuxver.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/linuxver.h index c6a12ae921..e1dac33c5d 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/linuxver.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/linuxver.h @@ -2,7 +2,7 @@ * Linux-specific abstractions to gain some independence from linux kernel versions. * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -10,14 +10,19 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: linuxver.h,v 1.1.1.10 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _linuxver_h_ #define _linuxver_h_ -#include <linux/config.h> #include <linux/version.h> +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) +#include <linux/config.h> +#else +#include <linux/autoconf.h> +#endif +#include <linux/module.h> #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) /* __NO_VERSION__ must be defined for all linkables except one in 2.2 */ @@ -28,15 +33,6 @@ #endif #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */ -#if defined(MODULE) && defined(MODVERSIONS) -#include <linux/modversions.h> -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) -#include <linux/moduleparam.h> -#endif - - #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) #define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") #define module_param_string(_name_, _string_, _size_, _perm_) \ @@ -77,6 +73,13 @@ #endif #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) +#define MY_INIT_WORK(_work, _func, _data) INIT_WORK(_work, _func) +#else +#define MY_INIT_WORK(_work, _func, _data) INIT_WORK(_work, _func, _data) +typedef void (*work_func_t)(void *work); +#endif /* < 2.6.20 */ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) /* Some distributions have their own 2.6.x compatibility layers */ #ifndef IRQ_NONE @@ -110,6 +113,12 @@ cs_error(client_handle_t handle, int func, int ret) } #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)) + +typedef struct pcmcia_device dev_link_t; + +#endif + #endif /* CONFIG_PCMCIA */ #ifndef __exit @@ -414,4 +423,11 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer) #define af_packet_priv data #endif +/* suspend args */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) +#define DRV_SUSPEND_STATE_TYPE pm_message_t +#else +#define DRV_SUSPEND_STATE_TYPE uint32 +#endif + #endif /* _linuxver_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/mipsinc.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/mipsinc.h index 2c87031fea..b291ea30b5 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/mipsinc.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/mipsinc.h @@ -1,7 +1,7 @@ /* * HND Run Time Environment for standalone MIPS programs. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: mipsinc.h,v 1.1.1.5 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _MISPINC_H @@ -69,6 +69,7 @@ #define C0_CTEXT $4 #define C0_PGMASK $5 #define C0_WIRED $6 +#define C0_INFO $7 #define C0_BADVADDR $8 #define C0_COUNT $9 #define C0_TLBHI $10 @@ -145,6 +146,7 @@ symbol: .frame sp, 0, ra #define C0_CTEXT 4 /* CP0: Context */ #define C0_PGMASK 5 /* CP0: TLB PageMask */ #define C0_WIRED 6 /* CP0: TLB Wired */ +#define C0_INFO 7 /* CP0: Info */ #define C0_BADVADDR 8 /* CP0: Bad Virtual Address */ #define C0_COUNT 9 /* CP0: Count */ #define C0_TLBHI 10 /* CP0: TLB EntryHi */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/osl.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/osl.h index 9be443215c..fddd1983e8 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/osl.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/osl.h @@ -4,26 +4,66 @@ #include <linux/delay.h> #include <typedefs.h> #include <linuxver.h> -#include <bcmutils.h> #include <pcicfg.h> #define ASSERT(n) +#ifndef ABS +#define ABS(a) (((a) < 0)?-(a):(a)) +#endif /* ABS */ + +#ifndef MIN +#define MIN(a, b) (((a) < (b))?(a):(b)) +#endif /* MIN */ + +#ifndef MAX +#define MAX(a, b) (((a) > (b))?(a):(b)) +#endif /* MAX */ + +#define CEIL(x, y) (((x) + ((y)-1)) / (y)) +#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) +#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0) +#define ISPOWEROF2(x) ((((x)-1)&(x)) == 0) +#define VALID_MASK(mask) !((mask) & ((mask) + 1)) +#ifndef OFFSETOF +#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) +#endif /* OFFSETOF */ +#ifndef ARRAYSIZE +#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) +#endif + +/* + * Spin at most 'us' microseconds while 'exp' is true. + * Caller should explicitly test 'exp' when this completes + * and take appropriate error action if 'exp' is still true. + */ +#define SPINWAIT(exp, us) { \ + uint countdown = (us) + 9; \ + while ((exp) && (countdown >= 10)) {\ + OSL_DELAY(10); \ + countdown -= 10; \ + } \ +} + + +typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); /* Pkttag flag should be part of public information */ typedef struct { bool pkttag; - uint pktalloced; /* Number of allocated packet buffers */ - void *tx_fn; - void *tx_ctx; + uint pktalloced; /* Number of allocated packet buffers */ + bool mmbus; /* Bus supports memory-mapped register accesses */ + pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ + void *tx_ctx; /* Context to the callback function */ } osl_pubinfo_t; struct osl_info { - osl_pubinfo_t pub; - uint magic; - void *pdev; - uint malloced; - uint failed; - void *dbgmem_list; + osl_pubinfo_t pub; + uint magic; + void *pdev; + uint malloced; + uint failed; + uint bustype; + void *dbgmem_list; }; typedef struct osl_info osl_t; @@ -101,8 +141,8 @@ typedef struct osl_info osl_t; #define MFREE(osh, addr, size) kfree((addr)) #define MALLOCED(osh) (0) -#define osl_delay OSL_DELAY -static inline void OSL_DELAY(uint usec) +#define OSL_DELAY _osl_delay +static inline void _osl_delay(uint usec) { uint d; @@ -128,10 +168,10 @@ bcm_mdelay(uint ms) #define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) #define OSL_PCI_READ_CONFIG(osh, offset, size) \ - osl_pci_read_config((osh), (offset), (size)) + _osl_pci_read_config((osh), (offset), (size)) static inline uint32 -osl_pci_read_config(osl_t *osh, uint offset, uint size) +_osl_pci_read_config(osl_t *osh, uint offset, uint size) { uint val; uint retry = PCI_CFG_RETRY; @@ -146,9 +186,9 @@ osl_pci_read_config(osl_t *osh, uint offset, uint size) } #define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ - osl_pci_write_config((osh), (offset), (size), (val)) + _osl_pci_write_config((osh), (offset), (size), (val)) static inline void -osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) +_osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) { uint retry = PCI_CFG_RETRY; @@ -156,24 +196,24 @@ osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) pci_write_config_dword(osh->pdev, offset, val); if (offset != PCI_BAR0_WIN) break; - if (osl_pci_read_config(osh, offset, size) == val) + if (_osl_pci_read_config(osh, offset, size) == val) break; } while (retry--); } /* return bus # for the pci device pointed by osh->pdev */ -#define OSL_PCI_BUS(osh) osl_pci_bus(osh) +#define OSL_PCI_BUS(osh) _osl_pci_bus(osh) static inline uint -osl_pci_bus(osl_t *osh) +_osl_pci_bus(osl_t *osh) { return ((struct pci_dev *)osh->pdev)->bus->number; } /* return slot # for the pci device pointed by osh->pdev */ -#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) +#define OSL_PCI_SLOT(osh) _osl_pci_slot(osh) static inline uint -osl_pci_slot(osl_t *osh) +_osl_pci_slot(osl_t *osh) { return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); } diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/pcicfg.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/pcicfg.h index 8bb45957a7..dd468db76c 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/pcicfg.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/pcicfg.h @@ -1,7 +1,7 @@ /* * pcicfg.h: PCI configuration constants and structures. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: pcicfg.h,v 1.1.1.11 2006/04/08 06:13:40 honor Exp $ + * $Id$ */ #ifndef _h_pcicfg_ @@ -170,6 +170,14 @@ typedef struct _pci_config_regs { #undef PCI_CLASS_DOCK #endif /* __NetBSD__ */ +#ifdef EFI +#undef PCI_CLASS_BRIDGE +#undef PCI_CLASS_OLD +#undef PCI_CLASS_DISPLAY +#undef PCI_CLASS_SERIAL +#undef PCI_CLASS_SATELLITE +#endif /* EFI */ + /* Classes and subclasses */ typedef enum { @@ -406,6 +414,11 @@ typedef struct _pciconfig_cap_pwrmgmt { unsigned char data; } pciconfig_cap_pwrmgmt; +#define PME_CAP_PM_STATES (0x1f << 27) /* Bits 31:27 states that can generate PME */ +#define PME_CSR_OFFSET 0x4 /* 4-bytes offset */ +#define PME_CSR_PME_EN (1 << 8) /* Bit 8 Enable generating of PME */ +#define PME_CSR_PME_STAT (1 << 15) /* Bit 15 PME got asserted */ + /* Data structure to define the PCIE capability */ typedef struct _pciconfig_cap_pcie { unsigned char capID; @@ -463,7 +476,7 @@ typedef struct _pcie_enhanced_caphdr { * 8KB window, so their address is the "regular" * address plus 4K */ -#define PCI_BAR0_WINSZ 8192 /* bar0 window size */ +#define PCI_BAR0_WINSZ (16 * 1024) /* bar0 window size Match with corerev 13 */ /* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ #define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbchipc.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbchipc.h index 03c5cf19a0..c3d4c6110e 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbchipc.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbchipc.h @@ -5,8 +5,8 @@ * jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer, * gpio interface, extbus, and support for serial and parallel flashes. * - * $Id: sbchipc.h,v 1.1.1.14 2006/04/15 01:29:08 michael Exp $ - * Copyright 2006, Broadcom Corporation + * $Id$ + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -19,7 +19,6 @@ #ifndef _SBCHIPC_H #define _SBCHIPC_H - #ifndef _LANGUAGE_ASSEMBLY /* cpp contortions to concatenate w/arg prescan */ @@ -29,6 +28,7 @@ #define PAD _XSTR(__LINE__) #endif /* PAD */ + typedef volatile struct { uint32 chipid; /* 0x0 */ uint32 capabilities; @@ -62,20 +62,26 @@ typedef volatile struct { /* Silicon backplane configuration broadcast control */ uint32 broadcastaddress; /* 0x50 */ uint32 broadcastdata; - uint32 PAD[2]; /* gpio - cleared only by power-on-reset */ + uint32 gpiopullup; /* 0x58, corerev >= 20 */ + uint32 gpiopulldown; /* 0x5c, corerev >= 20 */ uint32 gpioin; /* 0x60 */ uint32 gpioout; uint32 gpioouten; uint32 gpiocontrol; uint32 gpiointpolarity; uint32 gpiointmask; - uint32 PAD[2]; + + /* GPIO events corerev >= 11 */ + uint32 gpioevent; + uint32 gpioeventintmask; /* Watchdog timer */ uint32 watchdog; /* 0x80 */ - uint32 PAD[1]; + + /* GPIO events corerev >= 11 */ + uint32 gpioeventintpolarity; /* GPIO based LED powersave registers corerev >= 16 */ uint32 gpiotimerval; /* 0x88 */ @@ -114,10 +120,31 @@ typedef volatile struct { uint32 prog_waitcount; uint32 flash_config; uint32 flash_waitcount; - uint32 PAD[44]; - - /* Clock control and hardware workarounds */ - uint32 clk_ctl_st; + uint32 PAD[4]; + + /* Enhanced Coexistance Interface (ECI) registers (corerev >= 21) */ + uint32 eci_output; /* 0x140 */ + uint32 eci_control; + uint32 eci_inputlo; + uint32 eci_inputmi; + uint32 eci_inputhi; + uint32 eci_inputintpolaritylo; + uint32 eci_inputintpolaritymi; + uint32 eci_inputintpolarityhi; + uint32 eci_intmasklo; + uint32 eci_intmaskmi; + uint32 eci_intmaskhi; + uint32 eci_eventlo; + uint32 eci_eventmi; + uint32 eci_eventhi; + uint32 eci_eventmasklo; + uint32 eci_eventmaskmi; + uint32 eci_eventmaskhi; + uint32 PAD[23]; + + + /* Clock control and hardware workarounds (corerev >= 20) */ + uint32 clk_ctl_st; /* 0x1e0 */ uint32 hw_war; uint32 PAD[70]; @@ -140,12 +167,47 @@ typedef volatile struct { uint8 uart1lsr; uint8 uart1msr; uint8 uart1scratch; + uint32 PAD[126]; + + /* PMU registers (corerev >= 20) */ + uint32 pmucontrol; /* 0x600 */ + uint32 pmucapabilities; + uint32 pmustatus; + uint32 res_state; + uint32 res_pending; + uint32 pmutimer; + uint32 min_res_mask; + uint32 max_res_mask; + uint32 res_table_sel; + uint32 res_dep_mask; + uint32 res_updn_timer; + uint32 res_timer; + uint32 clkstretch; + uint32 pmuwatchdog; + uint32 PAD[2]; + uint32 res_req_timer_sel; + uint32 res_req_timer; + uint32 res_req_mask; + uint32 PAD; + uint32 chipcontrol_addr; + uint32 chipcontrol_data; + uint32 regcontrol_addr; + uint32 regcontrol_data; + uint32 pllcontrol_addr; + uint32 pllcontrol_data; + uint32 PAD[102]; + uint16 otp[512]; } chipcregs_t; #endif /* _LANGUAGE_ASSEMBLY */ +/* corecontrol */ +#define CC_UE (1 << 0) /* uart enable */ + #define CC_CHIPID 0 #define CC_CAPABILITIES 4 +#define CC_OTPST 0x10 +#define CC_CHIPST 0x2c #define CC_JTAGCMD 0x30 #define CC_JTAGIR 0x34 #define CC_JTAGDR 0x38 @@ -158,7 +220,18 @@ typedef volatile struct { #define CC_CLKC_M3 0xa0 #define CC_CLKDIV 0xa4 #define CC_SYS_CLK_CTL 0xc0 -#define CC_OTP 0x800 +#define CC_CLK_CTL_ST SB_CLK_CTL_ST +#define PMU_CTL 0x600 +#define PMU_CAP 0x604 +#define PMU_ST 0x608 +#define PMU_TIMER 0x614 +#define PMU_MIN_RES_MASK 0x618 +#define PMU_MAX_RES_MASK 0x61c +#define PMU_REG_CONTROL_ADDR 0x658 +#define PMU_REG_CONTROL_DATA 0x65C +#define PMU_PLL_CONTROL_ADDR 0x660 +#define PMU_PLL_CONTROL_DATA 0x664 +#define CC_OTP 0x800 /* OTP address space */ /* chipid */ #define CID_ID_MASK 0x0000ffff /* Chip Id mask */ @@ -170,24 +243,26 @@ typedef volatile struct { #define CID_CC_SHIFT 24 /* capabilities */ -#define CAP_UARTS_MASK 0x00000003 /* Number of uarts */ -#define CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ -#define CAP_UCLKSEL 0x00000018 /* UARTs clock select */ -#define CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ -#define CAP_UARTGPIO 0x00000020 /* UARTs own Gpio's 15:12 */ -#define CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ -#define CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ -#define CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ -#define CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ -#define CAP_FLASH_MASK 0x00000700 /* Type of flash */ -#define CAP_PLL_MASK 0x00038000 /* Type of PLL */ -#define CAP_PWR_CTL 0x00040000 /* Power control */ -#define CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ -#define CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ -#define CAP_OTPSIZE_BASE 5 /* OTP Size base */ -#define CAP_JTAGP 0x00400000 /* JTAG Master Present */ -#define CAP_ROM 0x00800000 /* Internal boot rom active */ -#define CAP_BKPLN64 0x08000000 /* 64-bit backplane */ +#define CC_CAP_UARTS_MASK 0x00000003 /* Number of uarts */ +#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ +#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ +#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ +#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own Gpio's 15:12 */ +#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ +#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ +#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ +#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ +#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ +#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ +#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ +#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ +#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ +#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ +#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ +#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ +#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ +#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ +#define CC_CAP_ECI 0x20000000 /* ECI Present, rev >= 21 */ /* PLL type */ #define PLL_NONE 0x00000000 @@ -199,39 +274,72 @@ typedef volatile struct { #define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */ #define PLL_TYPE7 0x00038000 /* 25Mhz, 4 dividers */ +/* ALP clock on pre-PMU chips */ +#define ALP_CLOCK 20000000 + +/* HT clock */ +#define HT_CLOCK 80000000 + +/* watchdog clock */ +#define WATCHDOG_CLOCK_5354 32000 /* Hz */ + /* corecontrol */ #define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */ #define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ +#define CC_UARTCLKEN 0x00000008 /* enable UART Clock (corerev > = 21 */ /* chipcontrol */ #define CHIPCTRL_4321A0_DEFAULT 0x3a4 #define CHIPCTRL_4321A1_DEFAULT 0x0a4 -/* Fields in the otpstatus register */ -#define OTPS_PROGFAIL 0x80000000 -#define OTPS_PROTECT 0x00000007 -#define OTPS_HW_PROTECT 0x00000001 -#define OTPS_SW_PROTECT 0x00000002 -#define OTPS_CID_PROTECT 0x00000004 - -/* Fields in the otpcontrol register */ -#define OTPC_RECWAIT 0xff000000 -#define OTPC_PROGWAIT 0x00ffff00 -#define OTPC_PRW_SHIFT 8 -#define OTPC_MAXFAIL 0x00000038 -#define OTPC_VSEL 0x00000006 -#define OTPC_SELVL 0x00000001 - -/* Fields in otpprog */ -#define OTPP_COL_MASK 0x000000ff -#define OTPP_ROW_MASK 0x0000ff00 -#define OTPP_ROW_SHIFT 8 -#define OTPP_READERR 0x10000000 -#define OTPP_VALUE 0x20000000 -#define OTPP_VALUE_SHIFT 29 -#define OTPP_READ 0x40000000 -#define OTPP_START 0x80000000 -#define OTPP_BUSY 0x80000000 +/* Fields in the otpstatus register in rev >= 21 */ +#define OTPS_OL_MASK 0x000000ff +#define OTPS_OL_MFG 0x00000001 /* manuf row is locked */ +#define OTPS_OL_OR1 0x00000002 /* otp redundancy row 1 is locked */ +#define OTPS_OL_OR2 0x00000004 /* otp redundancy row 2 is locked */ +#define OTPS_OL_GU 0x00000008 /* general use region is locked */ +#define OTPS_GUP_MASK 0x00000f00 +#define OTPS_GUP_SHIFT 8 +#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */ +#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */ +#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */ +#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */ +#define OTPS_READY 0x00001000 +#define OTPS_RV(x) (1 << (16 + (x))) + +/* Fields in the otpcontrol register in rev >= 21 */ +#define OTPC_PROGSEL 0x00000001 +#define OTPC_PCOUNT_MASK 0x0000000e +#define OTPC_PCOUNT_SHIFT 1 +#define OTPC_VSEL_MASK 0x000000f0 +#define OTPC_VSEL_SHIFT 4 +#define OTPC_TMM_MASK 0x00000700 +#define OTPC_TMM_SHIFT 8 +#define OTPC_ODM 0x00000800 +#define OTPC_PROGEN 0x80000000 + +/* Fields in otpprog in rev >= 21 */ +#define OTPP_COL_MASK 0x000000ff +#define OTPP_COL_SHIFT 0 +#define OTPP_ROW_MASK 0x0000ff00 +#define OTPP_ROW_SHIFT 8 +#define OTPP_OC_MASK 0x0f000000 +#define OTPP_OC_SHIFT 24 +#define OTPP_READERR 0x10000000 +#define OTPP_VALUE_MASK 0x20000000 +#define OTPP_VALUE_SHIFT 29 +#define OTPP_START_BUSY 0x80000000 + +/* Opcodes for OTPP_OC field */ +#define OTPPOC_READ 0 +#define OTPPOC_BIT_PROG 1 +#define OTPPOC_VERIFY 3 +#define OTPPOC_INIT 4 +#define OTPPOC_SET 5 +#define OTPPOC_RESET 6 +#define OTPPOC_OCST 7 +#define OTPPOC_ROW_LOCK 8 +#define OTPPOC_PRESCN_TEST 9 /* jtagcmd */ #define JCMD_START 0x80000000 @@ -272,7 +380,12 @@ typedef volatile struct { /* intstatus/intmask */ #define CI_GPIO 0x00000001 /* gpio intr */ -#define CI_EI 0x00000002 /* ro: ext intr pin (corerev >= 3) */ +#define CI_EI 0x00000002 /* extif intr (corerev >= 3) */ +#define CI_TEMP 0x00000004 /* temp. ctrl intr (corerev >= 15) */ +#define CI_SIRQ 0x00000008 /* serial IRQ intr (corerev >= 15) */ +#define CI_ECI 0x00000010 /* eci intr (corerev >= 21) */ +#define CI_PMU 0x00000020 /* pmu intr (corerev >= 21) */ +#define CI_UART 0x00000040 /* uart intr (corerev >= 21) */ #define CI_WDRESET 0x80000000 /* watchdog reset occurred */ /* slow_clk_ctl */ @@ -306,6 +419,43 @@ typedef volatile struct { #define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ #define SYCC_CD_SHIFT 16 +/* pcmcia_iowait */ +#define PI_W0_MASK 0x0000003f /* waitcount0 */ +#define PI_W1_MASK 0x00001f00 /* waitcount1 */ +#define PI_W1_SHIFT 8 +#define PI_W2_MASK 0x001f0000 /* waitcount2 */ +#define PI_W2_SHIFT 16 +#define PI_W3_MASK 0x1f000000 /* waitcount3 */ +#define PI_W3_SHIFT 24 + +/* prog_waitcount */ +#define PW_W0_MASK 0x0000001f /* waitcount0 */ +#define PW_W1_MASK 0x00001f00 /* waitcount1 */ +#define PW_W1_SHIFT 8 +#define PW_W2_MASK 0x001f0000 /* waitcount2 */ +#define PW_W2_SHIFT 16 +#define PW_W3_MASK 0x1f000000 /* waitcount3 */ +#define PW_W3_SHIFT 24 + +#define PW_W0 0x0000000c +#define PW_W1 0x00000a00 +#define PW_W2 0x00020000 +#define PW_W3 0x01000000 + +/* watchdog */ +#define WATCHDOG_CLOCK 48000000 /* Hz */ + +/* Fields in pmucontrol */ +#define PCTL_ILP_DIV_MASK 0xffff0000 +#define PCTL_ILP_DIV_SHIFT 16 +#define PCTL_NOILP_ON_WAIT 0x00000200 +#define PCTL_HT_REQ_EN 0x00000100 +#define PCTL_ALP_REQ_EN 0x00000080 +#define PCTL_XTALFREQ_MASK 0x0000007c +#define PCTL_XTALFREQ_SHIFT 2 +#define PCTL_ILP_DIV_EN 0x00000002 +#define PCTL_LPO_SEL 0x00000001 + /* gpiotimerval */ #define GPIO_ONTIME_SHIFT 16 @@ -377,9 +527,10 @@ typedef volatile struct { #define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */ #define CC_CFG_EM_IDE 0x0006 /* IDE */ #define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ -#define CC_CFG_CD_MASK 0x0060 /* Sync: Clock divisor */ -#define CC_CFG_CE 0x0080 /* Sync: Clock enable */ -#define CC_CFG_SB 0x0100 /* Sync: Size/Bytestrobe */ +#define CC_CFG_CD_MASK 0x00e0 /* Sync: Clock divisor, rev >= 20 */ +#define CC_CFG_CE 0x0100 /* Sync: Clock enable, rev >= 20 */ +#define CC_CFG_SB 0x0200 /* Sync: Size/Bytestrobe, rev >= 20 */ +#define CC_CFG_IS 0x0400 /* Extif Sync Clk Select, rev >= 20 */ /* ExtBus address space */ #define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */ @@ -396,6 +547,7 @@ typedef volatile struct { /* Start/busy bit in flashcontrol */ #define SFLASH_OPCODE 0x000000ff #define SFLASH_ACTION 0x00000700 +#define SFLASH_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */ #define SFLASH_START 0x80000000 #define SFLASH_BUSY SFLASH_START @@ -419,6 +571,7 @@ typedef volatile struct { #define SFLASH_ST_BE 0x00c7 /* Bulk Erase */ #define SFLASH_ST_DP 0x00b9 /* Deep Power-down */ #define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */ +#define SFLASH_ST_CSA 0x1000 /* Keep chip select asserted */ /* Status register bits for ST flashes */ #define SFLASH_ST_WIP 0x01 /* Write In Progress */ @@ -456,31 +609,6 @@ typedef volatile struct { #define SFLASH_AT_ID_MASK 0x38 #define SFLASH_AT_ID_SHIFT 3 -/* OTP regions */ -#define OTP_HW_REGION OTPS_HW_PROTECT -#define OTP_SW_REGION OTPS_SW_PROTECT -#define OTP_CID_REGION OTPS_CID_PROTECT - -/* OTP regions (Byte offsets from otp size) */ -#define OTP_SWLIM_OFF (-8) -#define OTP_CIDBASE_OFF 0 -#define OTP_CIDLIM_OFF 8 - -/* Predefined OTP words (Word offset from otp size) */ -#define OTP_BOUNDARY_OFF (-4) -#define OTP_HWSIGN_OFF (-3) -#define OTP_SWSIGN_OFF (-2) -#define OTP_CIDSIGN_OFF (-1) - -#define OTP_CID_OFF 0 -#define OTP_PKG_OFF 1 -#define OTP_FID_OFF 2 -#define OTP_RSV_OFF 3 -#define OTP_LIM_OFF 4 - -#define OTP_SIGNATURE 0x578a -#define OTP_MAGIC 0x4e56 - /* * These are the UART port assignments, expressed as offsets from the base * register. These assignments should hold for any serial port based on @@ -507,10 +635,223 @@ typedef volatile struct { #define UART_LSR_RXRDY 0x01 /* Receiver ready */ #define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */ +/* Interrupt Identity Register (IIR) bits */ +#define UART_IIR_FIFO_MASK 0xc0 /* IIR FIFO disable/enabled mask */ +#define UART_IIR_INT_MASK 0xf /* IIR interrupt ID source */ +#define UART_IIR_MDM_CHG 0x0 /* Modem status changed */ +#define UART_IIR_NOINT 0x1 /* No interrupt pending */ +#define UART_IIR_THRE 0x2 /* THR empty */ +#define UART_IIR_RCVD_DATA 0x4 /* Received data available */ +#define UART_IIR_RCVR_STATUS 0x6 /* Receiver status */ +#define UART_IIR_CHAR_TIME 0xc /* Character time */ + /* Interrupt Enable Register (IER) bits */ #define UART_IER_EDSSI 8 /* enable modem status interrupt */ #define UART_IER_ELSI 4 /* enable receiver line status interrupt */ #define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */ #define UART_IER_ERBFI 1 /* enable data available interrupt */ +/* pmustatus */ +#define PST_INTPEND 0x0040 +#define PST_SBCLKST 0x0030 +#define PST_ALPAVAIL 0x0008 +#define PST_HTAVAIL 0x0004 +#define PST_RESINIT 0x0003 + +/* pmucapabilities */ +#define PCAP_REV_MASK 0x000000ff + +/* PMU Resource Request Timer registers */ +/* This is based on PmuRev0 */ +#define PRRT_TIME_MASK 0x03ff +#define PRRT_INTEN 0x0400 +#define PRRT_REQ_ACTIVE 0x0800 +#define PRRT_ALP_REQ 0x1000 +#define PRRT_HT_REQ 0x2000 + +/* PMU resource bit position */ +#define PMURES_BIT(bit) (1 << (bit)) + +/* PMU corerev and chip specific PLL controls. + * PMU<rev>_PLL<num>_XXXX where <rev> is PMU corerev and <num> is an arbitary number + * to differentiate different PLLs controlled by the same PMU rev. + */ +/* pllcontrol registers */ +/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */ +#define PMU0_PLL0_PLLCTL0 0 +#define PMU0_PLL0_PC0_PDIV_MASK 1 +#define PMU0_PLL0_PC0_PDIV_FREQ 25000 +#define PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038 +#define PMU0_PLL0_PC0_DIV_ARM_SHIFT 3 +#define PMU0_PLL0_PC0_DIV_ARM_BASE 8 + +/* PC0_DIV_ARM for PLLOUT_ARM */ +#define PMU0_PLL0_PC0_DIV_ARM_110MHZ 0 +#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1 +#define PMU0_PLL0_PC0_DIV_ARM_88MHZ 2 +#define PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */ +#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4 +#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5 +#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6 +#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7 + +/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */ +#define PMU0_PLL0_PLLCTL1 1 +#define PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000 +#define PMU0_PLL0_PC1_WILD_INT_SHIFT 28 +#define PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00 +#define PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8 +#define PMU0_PLL0_PC1_STOP_MOD 0x00000040 + +/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */ +#define PMU0_PLL0_PLLCTL2 2 +#define PMU0_PLL0_PC2_WILD_INT_MASK 0xf +#define PMU0_PLL0_PC2_WILD_INT_SHIFT 4 + +/* Chip specific PMU resources. */ +#define RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */ +#define RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */ +#define RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */ +#define RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ +#define RES4328_ILP_REQUEST 4 /* 0x00010 */ +#define RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */ +#define RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */ +#define RES4328_ROM_SWITCH 7 /* 0x00080 */ +#define RES4328_PA_REF_LDO 8 /* 0x00100 */ +#define RES4328_RADIO_LDO 9 /* 0x00200 */ +#define RES4328_AFE_LDO 10 /* 0x00400 */ +#define RES4328_PLL_LDO 11 /* 0x00800 */ +#define RES4328_BG_FILTBYP 12 /* 0x01000 */ +#define RES4328_TX_FILTBYP 13 /* 0x02000 */ +#define RES4328_RX_FILTBYP 14 /* 0x04000 */ +#define RES4328_XTAL_PU 15 /* 0x08000 */ +#define RES4328_XTAL_EN 16 /* 0x10000 */ +#define RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */ +#define RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */ +#define RES4328_BB_PLL_PU 19 /* 0x80000 */ + +#define RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */ +#define RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */ +#define RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */ +#define RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ +#define RES5354_ILP_REQUEST 4 /* 0x00010 */ +#define RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */ +#define RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */ +#define RES5354_ROM_SWITCH 7 /* 0x00080 */ +#define RES5354_PA_REF_LDO 8 /* 0x00100 */ +#define RES5354_RADIO_LDO 9 /* 0x00200 */ +#define RES5354_AFE_LDO 10 /* 0x00400 */ +#define RES5354_PLL_LDO 11 /* 0x00800 */ +#define RES5354_BG_FILTBYP 12 /* 0x01000 */ +#define RES5354_TX_FILTBYP 13 /* 0x02000 */ +#define RES5354_RX_FILTBYP 14 /* 0x04000 */ +#define RES5354_XTAL_PU 15 /* 0x08000 */ +#define RES5354_XTAL_EN 16 /* 0x10000 */ +#define RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */ +#define RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */ +#define RES5354_BB_PLL_PU 19 /* 0x80000 */ + +/* pllcontrol registers */ +/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypsss_sdmod */ +#define PMU1_PLL0_PLLCTL0 0 +#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 +#define PMU1_PLL0_PC0_P1DIV_SHIFT 20 +#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000 +#define PMU1_PLL0_PC0_P2DIV_SHIFT 24 + +/* m<x>div */ +#define PMU1_PLL0_PLLCTL1 1 +#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff +#define PMU1_PLL0_PC1_M1DIV_SHIFT 0 +#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00 +#define PMU1_PLL0_PC1_M2DIV_SHIFT 8 +#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000 +#define PMU1_PLL0_PC1_M3DIV_SHIFT 16 +#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000 +#define PMU1_PLL0_PC1_M4DIV_SHIFT 24 + +/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */ +#define PMU1_PLL0_PLLCTL2 2 +#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff +#define PMU1_PLL0_PC2_M5DIV_SHIFT 0 +#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00 +#define PMU1_PLL0_PC2_M6DIV_SHIFT 8 +#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000 +#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17 +#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000 +#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20 + +/* ndiv_frac */ +#define PMU1_PLL0_PLLCTL3 3 +#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff +#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0 + +/* pll_ctrl */ +#define PMU1_PLL0_PLLCTL4 4 + +/* pll_ctrl, vco_rng, clkdrive_ch<x> */ +#define PMU1_PLL0_PLLCTL5 5 +#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00 +#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8 + +#define RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */ +#define RES4325_CBUCK_BURST 1 /* 0x00000002 */ +#define RES4325_CBUCK_PWM 2 /* 0x00000004 */ +#define RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */ +#define RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */ +#define RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */ +#define RES4325_ILP_REQUEST 6 /* 0x00000040 */ +#define RES4325_ABUCK_BURST 7 /* 0x00000080 */ +#define RES4325_ABUCK_PWM 8 /* 0x00000100 */ +#define RES4325_LNLDO1_PU 9 /* 0x00000200 */ +#define RES4325_LNLDO2_PU 10 /* 0x00000400 */ +#define RES4325_LNLDO3_PU 11 /* 0x00000800 */ +#define RES4325_LNLDO4_PU 12 /* 0x00001000 */ +#define RES4325_XTAL_PU 13 /* 0x00002000 */ +#define RES4325_ALP_AVAIL 14 /* 0x00004000 */ +#define RES4325_RX_PWRSW_PU 15 /* 0x00008000 */ +#define RES4325_TX_PWRSW_PU 16 /* 0x00010000 */ +#define RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */ +#define RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */ +#define RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */ +#define RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */ +#define RES4325_HT_AVAIL 21 /* 0x00200000 */ + +/* Chip specific ChipStatus register bits */ +#define CST4325_SPROM_OTP_SEL_MASK 0x00000003 +#define CST4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ +#define CST4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ +#define CST4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ +#define CST4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ +#define CST4325_SDIO_USB_MODE_MASK 0x00000004 +#define CST4325_SDIO_USB_MODE_SHIFT 2 +#define CST4325_RCAL_VALID_MASK 0x00000008 +#define CST4325_RCAL_VALID_SHIFT 3 +#define CST4325_RCAL_VALUE_MASK 0x000001f0 +#define CST4325_RCAL_VALUE_SHIFT 4 +#define CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */ +#define CST4325_PMUTOP_2B_SHIFT 9 + +#define RES4312_SWITCHER_BURST 0 /* 0x00000001 */ +#define RES4312_SWITCHER_PWM 1 /* 0x00000002 */ +#define RES4312_PA_REF_LDO 2 /* 0x00000004 */ +#define RES4312_CORE_LDO_BURST 3 /* 0x00000008 */ +#define RES4312_CORE_LDO_PWM 4 /* 0x00000010 */ +#define RES4312_RADIO_LDO 5 /* 0x00000020 */ +#define RES4312_ILP_REQUEST 6 /* 0x00000040 */ +#define RES4312_BG_FILTBYP 7 /* 0x00000080 */ +#define RES4312_TX_FILTBYP 8 /* 0x00000100 */ +#define RES4312_RX_FILTBYP 9 /* 0x00000200 */ +#define RES4312_XTAL_PU 10 /* 0x00000400 */ +#define RES4312_ALP_AVAIL 11 /* 0x00000800 */ +#define RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */ +#define RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */ +#define RES4312_HT_AVAIL 14 /* 0x00004000 */ + +/* +* Maximum delay for the PMU state transition. +* This is an upper bound intended for spinwaits etc. +*/ +#define PMU_MAX_TRANSITION_DLY 15000 + #endif /* _SBCHIPC_H */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbconfig.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbconfig.h index 7a44e5fbaa..f609f3c2eb 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbconfig.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbconfig.h @@ -1,7 +1,7 @@ /* * Broadcom SiliconBackplane hardware register definitions. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,11 +9,12 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbconfig.h,v 1.1.1.11 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _SBCONFIG_H #define _SBCONFIG_H +#include "linuxver.h" /* cpp contortions to concatenate w/arg prescan */ #ifndef PAD @@ -36,13 +37,13 @@ #define SB_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ #define SB_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ - #define SB_EXTIF_BASE 0x1f000000 /* External Interface region base address */ +#define SB_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ #define SB_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ #define SB_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ - -#define SB_ROM 0x20000000 /* ARM ROM */ -#define SB_SRAM2 0x80000000 /* ARM SRAM Region 2 */ +#define SB_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ +#define SB_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ +#define SB_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */ #define SB_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ #define SB_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ @@ -196,7 +197,7 @@ typedef volatile struct _sbconfig { #define SBTMH_INT 0x2 /* interrupt */ #define SBTMH_BUSY 0x4 /* busy */ #define SBTMH_TO 0x00000020 /* timeout (sonics >= 2.3) */ -#define SBTMH_FL_MASK 0x1fff0000 /* core-specific flags */ +#define SBTMH_FL_MASK 0x0fff0000 /* core-specific flags */ #define SBTMH_DMA64 0x10000000 /* supports DMA with 64-bit addresses */ #define SBTMH_GCR 0x20000000 /* gated clock request */ #define SBTMH_BISTF 0x40000000 /* bist failed */ @@ -323,7 +324,6 @@ typedef volatile struct _sbconfig { #define SB_ILINE100 0x80a /* iline100 core */ #define SB_IPSEC 0x80b /* ipsec core */ #define SB_PCMCIA 0x80d /* pcmcia core */ -#define SB_SDIOD SB_PCMCIA /* pcmcia core has sdio device */ #define SB_SOCRAM 0x80e /* internal memory core */ #define SB_MEMC 0x80f /* memc sdram core */ #define SB_EXTIF 0x811 /* external interface core */ @@ -342,11 +342,32 @@ typedef volatile struct _sbconfig { #define SB_MIMO 0x821 /* MIMO phy core */ #define SB_SRAMC 0x822 /* SRAM controller core */ #define SB_MINIMAC 0x823 /* MINI MAC/phy core */ -#define SB_ARM11 0x824 /* ARM 1176 core */ -#define SB_ARM7 0x825 /* ARM 7tdmi core */ +#define SB_ARM7S 0x825 /* ARM7tdmi-s core */ +#define SB_SDIOD 0x829 /* SDIO device core */ +#define SB_ARMCM3 0x82a /* ARM Cortex M3 core */ +#define SB_OCP 0x830 /* OCP2OCP bridge core */ +#define SB_SC 0x831 /* shared common core */ +#define SB_AHB 0x832 /* OCP2AHB bridge core */ #define SB_CC_IDX 0 /* chipc, when present, is always core 0 */ +/* Not an enumeration space register, but common to all cores to + * communicate w/PMU regarding Silicon Backplane clocking. + */ +#define SB_CLK_CTL_ST 0x1e0 /* clock control and status */ + +/* clk_ctl_st register */ +#define CCS_FORCEALP 0x00000001 /* force ALP request */ +#define CCS_FORCEHT 0x00000002 /* force HT request */ +#define CCS_FORCEILP 0x00000004 /* force ILP request */ +#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ +#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ +#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ +#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ +#define CCS_HTAVAIL 0x00020000 /* HT is available */ +#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */ +#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */ + /* Not really related to Silicon Backplane, but a couple of software * conventions for the use the flash space: */ @@ -359,11 +380,11 @@ typedef volatile struct _sbconfig { #define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ #define BISZ_MAGIC_IDX 0 /* Word 0: magic */ #define BISZ_TXTST_IDX 1 /* 1: text start */ -#define BISZ_TXTEND_IDX 2 /* 2: text start */ -#define BISZ_DATAST_IDX 3 /* 3: text start */ -#define BISZ_DATAEND_IDX 4 /* 4: text start */ -#define BISZ_BSSST_IDX 5 /* 5: text start */ -#define BISZ_BSSEND_IDX 6 /* 6: text start */ +#define BISZ_TXTEND_IDX 2 /* 2: text end */ +#define BISZ_DATAST_IDX 3 /* 3: data start */ +#define BISZ_DATAEND_IDX 4 /* 4: data end */ +#define BISZ_BSSST_IDX 5 /* 5: bss start */ +#define BISZ_BSSEND_IDX 6 /* 6: bss end */ #define BISZ_SIZE 7 /* descriptor size in 32-bit intergers */ #endif /* _SBCONFIG_H */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbextif.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbextif.h index 7c3f2a0d6c..078d7b2344 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbextif.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbextif.h @@ -161,15 +161,6 @@ typedef volatile struct { #define PA_W3_MASK 0x1f000000 /* waitcount3 */ #define PA_W3_SHIFT 24 -/* pcmcia_iowait */ -#define PI_W0_MASK 0x3f /* waitcount0 */ -#define PI_W1_MASK 0x1f00 /* waitcount1 */ -#define PI_W1_SHIFT 8 -#define PI_W2_MASK 0x1f0000 /* waitcount2 */ -#define PI_W2_SHIFT 16 -#define PI_W3_MASK 0x1f000000 /* waitcount3 */ -#define PI_W3_SHIFT 24 - /* prog_waitcount */ #define PW_W0_MASK 0x0000001f /* waitcount0 */ #define PW_W1_MASK 0x00001f00 /* waitcount1 */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbhndmips.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbhndmips.h index 93f5ace8b8..3fc442ee2b 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbhndmips.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbhndmips.h @@ -7,7 +7,7 @@ * interface. The core revision is stored in the SB ID register in SB * configuration space. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -15,7 +15,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbhndmips.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _sbhndmips_h_ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbmemc.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbmemc.h index 74af8e1693..f20cdf77f2 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbmemc.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbmemc.h @@ -1,7 +1,7 @@ /* * BCM47XX Sonics SiliconBackplane DDR/SDRAM controller core hardware definitions. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbmemc.h,v 1.6 2006/03/02 12:33:44 honor Exp $ + * $Id$ */ #ifndef _SBMEMC_H diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpci.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpci.h index 761e5b4513..f35ed910e3 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpci.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpci.h @@ -1,7 +1,7 @@ /* * HND SiliconBackplane PCI core hardware definitions. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbpci.h,v 1.1.1.11 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _sbpci_h_ @@ -68,8 +68,11 @@ typedef struct sbpciregs { #define PCI_PARKID_EXT0 0 /* External master 0 */ #define PCI_PARKID_EXT1 1 /* External master 1 */ #define PCI_PARKID_EXT2 2 /* External master 2 */ -#define PCI_PARKID_INT 3 /* Internal master */ -#define PCI_PARKID_LAST 4 /* Last active master */ +#define PCI_PARKID_EXT3 3 /* External master 3 (rev >= 11) */ +#define PCI_PARKID_INT 3 /* Internal master (rev < 11) */ +#define PCI11_PARKID_INT 4 /* Internal master (rev >= 11) */ +#define PCI_PARKID_LAST 4 /* Last active master (rev < 11) */ +#define PCI11_PARKID_LAST 5 /* Last active master (rev >= 11) */ /* Interrupt status/mask */ #define PCI_INTA 0x01 /* PCI INTA# is asserted */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpcie.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpcie.h index 58990c9774..9819c0c41a 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpcie.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpcie.h @@ -1,7 +1,7 @@ /* * BCM43XX SiliconBackplane PCIE core hardware definitions. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbpcie.h,v 1.1.1.2 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _SBPCIE_H @@ -38,11 +38,17 @@ #define PCIE_BAR0_PCIECORE_OFFSET 0x2000 #define PCIE_BAR0_CCCOREREG_OFFSET 0x3000 +/* different register spaces to access thr'u pcie indirect access */ +#define PCIE_CONFIGREGS 1 /* Access to config space */ +#define PCIE_PCIEREGS 2 /* Access to pcie registers */ + /* SB side: PCIE core and host control registers */ typedef struct sbpcieregs { uint32 PAD[3]; uint32 biststatus; /* bist Status: 0x00C */ - uint32 PAD[6]; + uint32 gpiosel; /* PCIE gpio sel: 0x010 */ + uint32 gpioouten; /* PCIE gpio outen: 0x14 */ + uint32 PAD[4]; uint32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ uint32 PAD[54]; uint32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ @@ -58,11 +64,12 @@ typedef struct sbpcieregs { uint32 mdiocontrol; /* controls the mdio access: 0x128 */ uint32 mdiodata; /* Data to the mdio access: 0x12c */ - /* pcie protocol phy/dllp/tlp register access mechanism */ - uint32 pcieaddr; /* address of the internal registeru: 0x130 */ - uint32 pciedata; /* Data to/from the internal regsiter: 0x134 */ + /* pcie protocol phy/dllp/tlp register indirect access mechanism */ + uint32 pcieindaddr; /* indirect access to the internal register: 0x130 */ + uint32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */ - uint32 PAD[434]; + uint32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */ + uint32 PAD[433]; uint16 sprom[36]; /* SPROM shadow Area */ } sbpcieregs_t; @@ -136,6 +143,7 @@ typedef struct sbpcieregs { #define PCIE_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter */ #define PCIE_DLLP_TESTREG 0x14C /* Test */ #define PCIE_DLLP_PKTBIST 0x150 /* Packet BIST */ +#define PCIE_DLLP_PCIE11 0x154 /* DLLP PCIE 1.1 reg */ /* PCIE protocol TLP diagnostic registers */ #define PCIE_TLP_CONFIGREG 0x000 /* Configuration */ @@ -192,9 +200,38 @@ typedef struct sbpcieregs { #define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ #define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ -/* SERDES registers */ +/* SERDES RX registers */ +#define SERDES_RX_CTRL 1 /* Rx cntrl */ #define SERDES_RX_TIMER1 2 /* Rx Timer1 */ #define SERDES_RX_CDR 6 /* CDR */ #define SERDES_RX_CDRBW 7 /* CDR BW */ +/* SERDES RX control register */ +#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ +#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ + +/* SERDES PLL registers */ +#define SERDES_PLL_CTRL 1 /* PLL control reg */ +#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ + +#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */ +#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */ +#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */ + +/* SPROM offsets */ +#define SRSH_ASPM_OFFSET 4 /* word 4 */ +#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */ +#define SRSH_CLKREQ_OFFSET 20 /* word 20 */ +#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */ + +/* Linkcontrol reg offset in PCIE Cap */ +#define PCIE_CAP_LINKCTRL_OFFSET 16 /* linkctrl offset in pcie cap */ +#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */ +#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */ +#define PCIE_ASPM_ENAB 0x03 /* ASPM L0s & L1 in linkctrl */ +#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */ + +/* Status reg PCIE_PLP_STATUSREG */ +#define PCIE_PLP_POLARITYINV_STAT 0x10 + #endif /* _SBPCIE_H */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpcmcia.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpcmcia.h index 08fd453f49..651bc139f4 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpcmcia.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbpcmcia.h @@ -1,7 +1,7 @@ /* * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbpcmcia.h,v 1.1.1.9 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _SBPCMCIA_H @@ -75,6 +75,8 @@ #define SROM_DATAH (0x073a / 2) #define SROM_ADDRL (0x073c / 2) #define SROM_ADDRH (0x073e / 2) +#define SROM_INFO2 (0x0772 / 2) /* Corerev >= 2 && <= 5 */ +#define SROM_INFO (0x07be / 2) /* Corerev >= 6 */ /* Values for srom_cs: */ #define SROM_IDLE 0 @@ -84,16 +86,30 @@ #define SROM_WDS 7 #define SROM_DONE 8 +/* Fields in srom_info: */ +#define SRI_SZ_MASK 0x03 +#define SRI_BLANK 0x04 +#define SRI_OTP 0x80 + /* CIS stuff */ /* The CIS stops where the FCRs start */ #define CIS_SIZE PCMCIA_FCR +/* CIS tuple length field max */ +#define CIS_TUPLE_LEN_MAX 0xff + /* Standard tuples we know about */ +#define CISTPL_VERS_1 0x15 /* CIS ver, manf, dev & ver strings */ #define CISTPL_MANFID 0x20 /* Manufacturer and device id */ +#define CISTPL_FUNCID 0x21 /* Function identification */ #define CISTPL_FUNCE 0x22 /* Function extensions */ #define CISTPL_CFTABLE 0x1b /* Config table entry */ +#define CISTPL_END 0xff /* End of the CIS tuple chain */ + +/* Function identifier provides context for the function extentions tuple */ + /* Function extensions for LANs */ @@ -135,7 +151,29 @@ #define HNBU_CCKPO 0x0b /* 2 byte cck power offsets in rev 3 */ #define HNBU_OFDMPO 0x0c /* 4 byte 11g ofdm power offsets in rev 3 */ #define HNBU_GPIOTIMER 0x0d /* 2 bytes with on/off values in rev 3 */ - +#define HNBU_PAPARMS5G 0x0e /* 5G PA params */ +#define HNBU_ANT5G 0x0f /* 4328 5G antennas available/gain */ +#define HNBU_RDLID 0x10 /* 2 byte USB remote downloader (RDL) product Id */ +#define HNBU_RSSISMBXA2G 0x11 /* 4328 2G RSSI mid pt sel & board switch arch, + * 2 bytes, rev 3. + */ +#define HNBU_RSSISMBXA5G 0x12 /* 4328 5G RSSI mid pt sel & board switch arch, + * 2 bytes, rev 3. + */ +#define HNBU_XTALFREQ 0x13 /* 4 byte Crystal frequency in kilohertz */ +#define HNBU_TRI2G 0x14 /* 4328 2G TR isolation, 1 byte */ +#define HNBU_TRI5G 0x15 /* 4328 5G TR isolation, 3 bytes */ +#define HNBU_RXPO2G 0x16 /* 4328 2G RX power offset, 1 byte */ +#define HNBU_RXPO5G 0x17 /* 4328 5G RX power offset, 1 byte */ +#define HNBU_BOARDNUM 0x18 /* board serial number, independent of mac addr */ +#define HNBU_MACADDR 0x19 /* mac addr override for the standard CIS LAN_NID */ +#define HNBU_RDLSN 0x1a /* 2 bytes; serial # advertised in USB descriptor */ +#define HNBU_BOARDTYPE 0x1b /* 2 bytes; boardtype */ +#define HNBU_RDLRNDIS 0x20 /* 1 byte; 1 = RDL advertises RNDIS config */ +#define HNBU_RDLRWU 0x30 /* 1 byte; 1 = RDL advertises Remote Wake-up */ +#define HNBU_SROM3SWRGN 0x80 /* 78 bytes; srom rev 3 s/w region without crc8 + * plus extra info appended. + */ /* sbtmstatelow */ #define SBTML_INT_ACK 0x40000 /* ack the sb interrupt */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsdram.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsdram.h index dec6c29289..615edabb8e 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsdram.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsdram.h @@ -1,7 +1,7 @@ /* * BCM47XX Sonics SiliconBackplane SDRAM controller core hardware definitions. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbsdram.h,v 1.1.1.9 2006/03/02 13:03:52 honor Exp $ + * $Id$ */ #ifndef _SBSDRAM_H @@ -26,16 +26,7 @@ typedef volatile struct sbsdramregs { uint32 pad2; } sbsdramregs_t; -/* SDRAM simulation */ -#ifdef RAMSZ -#define SDRAMSZ RAMSZ -#else -#define SDRAMSZ (4 * 1024 * 1024) -#endif - -extern uchar sdrambuf[SDRAMSZ]; - -#endif /* _LANGUAGE_ASSEMBLY */ +#endif /* !_LANGUAGE_ASSEMBLY */ /* SDRAM initialization control (initcontrol) register bits */ #define SDRAM_CBR 0x0001 /* Writing 1 generates refresh cycle and toggles bit */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsocram.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsocram.h index f13bc2e408..6dd49b7632 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsocram.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsocram.h @@ -1,7 +1,7 @@ /* * BCM47XX Sonics SiliconBackplane embedded ram core * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,21 +9,21 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbsocram.h,v 1.1.1.3 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _SBSOCRAM_H #define _SBSOCRAM_H -#define SR_COREINFO 0x00 -#define SR_BWALLOC 0x04 -#define SR_BISTSTAT 0x0c -#define SR_BANKINDEX 0x10 -#define SR_BANKSTBYCTL 0x14 - - #ifndef _LANGUAGE_ASSEMBLY +/* cpp contortions to concatenate w/arg prescan */ +#ifndef PAD +#define _PADLINE(line) pad ## line +#define _XSTR(line) _PADLINE(line) +#define PAD _XSTR(__LINE__) +#endif /* PAD */ + /* Memcsocram core registers */ typedef volatile struct sbsocramregs { uint32 coreinfo; @@ -32,13 +32,28 @@ typedef volatile struct sbsocramregs { uint32 biststat; uint32 bankidx; uint32 standbyctrl; + uint32 PAD[116]; + uint32 pwrctl; /* corerev >= 2 */ } sbsocramregs_t; -#endif +#endif /* _LANGUAGE_ASSEMBLY */ + +/* Register offsets */ +#define SR_COREINFO 0x00 +#define SR_BWALLOC 0x04 +#define SR_BISTSTAT 0x0c +#define SR_BANKINDEX 0x10 +#define SR_BANKSTBYCTL 0x14 +#define SR_PWRCTL 0x1e8 /* Coreinfo register */ -#define SRCI_PT_MASK 0x30000 +#define SRCI_PT_MASK 0x00030000 #define SRCI_PT_SHIFT 16 +/* corerev >= 3 */ +#define SRCI_LSS_MASK 0x00f00000 +#define SRCI_LSS_SHIFT 20 +#define SRCI_LRS_MASK 0x0f000000 +#define SRCI_LRS_SHIFT 24 /* In corerev 0, the memory size is 2 to the power of the * base plus 16 plus to the contents of the memsize field plus 1. @@ -61,4 +76,11 @@ typedef volatile struct sbsocramregs { #define SRCI_SRBSZ_SHIFT 0 #define SR_BSZ_BASE 14 + +/* Standby control register */ +#define SRSC_SBYOVR_MASK 0x80000000 +#define SRSC_SBYOVR_SHIFT 31 +#define SRSC_SBYOVRVAL_MASK 0x60000000 +#define SRSC_SBYOVRVAL_SHIFT 29 + #endif /* _SBSOCRAM_H */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsprom.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsprom.h new file mode 100644 index 0000000000..042ef04412 --- /dev/null +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbsprom.h @@ -0,0 +1,277 @@ +/* + * SPROM format definitions for the Broadcom 47xx and 43xx chip family. + * + * $Id$ + * Copyright(c) 2002 Broadcom Corporation + */ + +#ifndef _SBSPROM_H +#define _SBSPROM_H + +#include "typedefs.h" +#include "bcmdevs.h" + +/* A word is this many bytes */ +#define SRW 2 + +/* offset into PCI config space for write enable bit */ +#define CFG_SROM_WRITABLE_OFFSET 0x88 +#define SROM_WRITEABLE 0x10 + +/* enumeration space consists of N contiguous 4Kbyte core register sets */ +#define SBCORES_BASE 0x18000000 +#define SBCORES_EACH 0x1000 + +/* offset from BAR0 for srom space */ +#define SROM_BASE 4096 + +/* number of 2-byte words in srom */ +#define SROM_SIZE 64 + +#define SROM_BYTES (SROM_SIZE * SRW) + +#define MAX_FN 4 + +/* Word 0, Hardware control */ +#define SROM_HWCTL 0 +#define HW_FUNMSK 0x000f +#define HW_FCLK 0x0200 +#define HW_CBM 0x0400 +#define HW_PIMSK 0xf000 +#define HW_PISHIFT 12 +#define HW_4301PISHIFT 13 +#define HW_PI4402 0x2 +#define HW_FUN4401 0x0001 +#define HW_FCLK4402 0x0000 + +/* Word 1, common-power/boot-rom */ +#define SROM_COMMPW 1 +/* boot rom present bit */ +#define BR_PRESSHIFT 8 +/* 15:9 for n; boot rom size is 2^(14 + n) bytes */ +#define BR_SIZESHIFT 9 + +/* Word 2, SubsystemId */ +#define SROM_SSID 2 + +/* Word 3, VendorId */ +#define SROM_VID 3 + +/* Function 0 info, function info length */ +#define SROM_FN0 4 +#define SROM_FNSZ 8 + +/* Within each function: */ +/* Word 0, deviceID */ +#define SRFN_DID 0 + +/* Words 1-2, ClassCode */ +#define SRFN_CCL 1 +/* Word 2, D0 Power */ +#define SRFN_CCHD0 2 + +/* Word 3, PME and D1D2D3 power */ +#define SRFN_PMED123 3 + +#define PME_IL 0 +#define PME_ENET0 1 +#define PME_ENET1 2 +#define PME_CODEC 3 + +#define PME_4402_ENET 0 +#define PME_4402_CODEC 1 +#define PME_4301_WL 2 +#define PMEREP_4402_ENET (PMERD3CV | PMERD3CA | PMERD3H | PMERD2 | PMERD1 | PMERD0 | PME) + +/* Word 4, Bar1 enable, pme reports */ +#define SRFN_B1PMER 4 +#define B1E 1 +#define B1SZMSK 0xe +#define B1SZSH 1 +#define PMERMSK 0x0ff0 +#define PME 0x0010 +#define PMERD0 0x0020 +#define PMERD1 0x0040 +#define PMERD2 0x0080 +#define PMERD3H 0x0100 +#define PMERD3CA 0x0200 +#define PMERD3CV 0x0400 +#define IGNCLKRR 0x0800 +#define B0LMSK 0xf000 + +/* Words 4-5, Bar0 Sonics value */ +#define SRFN_B0H 5 +/* Words 6-7, CIS Pointer */ +#define SRFN_CISL 6 +#define SRFN_CISH 7 + +/* Words 36-38: iLine MAC address */ +#define SROM_I_MACHI 36 +#define SROM_I_MACMID 37 +#define SROM_I_MACLO 38 + +/* Words 36-38: wireless0 MAC address on 43xx */ +#define SROM_W0_MACHI 36 +#define SROM_W0_MACMID 37 +#define SROM_W0_MACLO 38 + +/* Words 39-41: enet0 MAC address */ +#define SROM_E0_MACHI 39 +#define SROM_E0_MACMID 40 +#define SROM_E0_MACLO 41 + +/* Words 42-44: enet1 MAC address */ +#define SROM_E1_MACHI 42 +#define SROM_E1_MACMID 43 +#define SROM_E1_MACLO 44 + +/* Words 42-44: wireless1 MAC address on 4309 */ +#define SROM_W1_MACHI 42 +#define SROM_W1_MACMID 43 +#define SROM_W1_MACLO 44 + +#define SROM_EPHY 45 + +/* Word 46: BdRev & Antennas0/1 & ccLock for 430x */ +#define SROM_REV_AA_LOCK 46 + +/* Words 47-51 wl0 PA bx */ +#define SROM_WL0_PAB0 47 +#define SROM_WL0_PAB1 48 +#define SROM_WL0_PAB2 49 +#define SROM_WL0_PAB3 50 +#define SROM_WL0_PAB4 51 + +/* Word 52: wl0/wl1 MaxPower */ +#define SROM_WL_MAXPWR 52 + +/* Words 53-55 wl1 PA bx */ +#define SROM_WL1_PAB0 53 +#define SROM_WL1_PAB1 54 +#define SROM_WL1_PAB2 55 + +/* Woprd 56: itt */ +#define SROM_ITT 56 + +/* Words 59-62: OEM Space */ +#define SROM_WL_OEM 59 +#define SROM_OEM_SIZE 4 + +/* Contents for the srom */ + +#define BU4710_SSID 0x0400 +#define VSIM4710_SSID 0x0401 +#define QT4710_SSID 0x0402 + +#define BU4610_SSID 0x0403 +#define VSIM4610_SSID 0x0404 + +#define BU4307_SSID 0x0405 +#define BCM94301CB_SSID 0x0406 +#define BCM94301MP_SSID 0x0407 +#define BCM94307MP_SSID 0x0408 +#define AP4307_SSID 0x0409 + +#define BU4309_SSID 0x040a +#define BCM94309CB_SSID 0x040b +#define BCM94309MP_SSID 0x040c +#define AP4309_SSID 0x040d + +#define BU4402_SSID 0x4402 + +#define CLASS_OTHER 0x8000 +#define CLASS_ETHER 0x0000 +#define CLASS_NET 0x0002 +#define CLASS_COMM 0x0007 +#define CLASS_MODEM 0x0300 +#define CLASS_MIPS 0x3000 +#define CLASS_PROC 0x000b +#define CLASS_FLASH 0x0100 +#define CLASS_MEM 0x0005 +#define CLASS_SERIALBUS 0x000c +#define CLASS_OHCI 0x0310 + +/* Broadcom IEEE MAC addresses are 00:90:4c:xx:xx:xx */ +#define MACHI 0x90 + +#define MACMID_BU4710I 0x4c17 +#define MACMID_BU4710E0 0x4c18 +#define MACMID_BU4710E1 0x4c19 + +#define MACMID_94710R1I 0x4c1a +#define MACMID_94710R1E0 0x4c1b +#define MACMID_94710R1E1 0x4c1c + +#define MACMID_94710R4I 0x4c1d +#define MACMID_94710R4E0 0x4c1e +#define MACMID_94710R4E1 0x4c1f + +#define MACMID_94710DEVI 0x4c20 +#define MACMID_94710DEVE0 0x4c21 +#define MACMID_94710DEVE1 0x4c22 + +#define MACMID_BU4402 0x4c23 + +#define MACMID_BU4610I 0x4c24 +#define MACMID_BU4610E0 0x4c25 +#define MACMID_BU4610E1 0x4c26 + +#define MACMID_BU4307W 0x4c27 +#define MACMID_BU4307E 0x4c28 + +#define MACMID_94301CB 0x4c29 + +#define MACMID_94301MP 0x4c2a + +#define MACMID_94307MPW 0x4c2b +#define MACMID_94307MPE 0x4c2c + +#define MACMID_AP4307W 0x4c2d +#define MACMID_AP4307E 0x4c2e + +#define MACMID_BU4309W0 0x4c2f +#define MACMID_BU4309W1 0x4c30 +#define MACMID_BU4309E 0x4c31 + +#define MACMID_94309CBW0 0x4c32 +#define MACMID_94309CBW1 0x4c33 + +#define MACMID_94309MPW0 0x4c34 +#define MACMID_94309MPW1 0x4c35 +#define MACMID_94309MPE 0x4c36 + +#define MACMID_BU4401 0x4c37 + +/* Enet phy settings one or two singles or a dual */ +/* Bits 4-0 : MII address for enet0 (0x1f for not there */ +/* Bits 9-5 : MII address for enet1 (0x1f for not there */ +/* Bit 14 : Mdio for enet0 */ +/* Bit 15 : Mdio for enet1 */ + +/* bu4710 with only one phy on enet1 with address 7: */ +#define SROM_EPHY_ONE 0x80ff + +/* bu4710 with two individual phys, at 6 and 7, */ +/* each mdio connected to its own mac: */ +#define SROM_EPHY_TWO 0x80e6 + +/* bu4710 with a dual phy addresses 0 & 1, mdio-connected to enet0 */ +#define SROM_EPHY_DUAL 0x0001 + +/* r1 board with a dual phy at 0, 1 (NOT swapped and mdc0 */ +#define SROM_EPHY_R1 0x0010 + +/* r4 board with a single phy on enet0 at address 5 and a switch */ +/* chip on enet1 (speciall case: 0x1e */ +#define SROM_EPHY_R4 0x83e5 + +/* 4402 uses an internal phy at phyaddr 1; want mdcport == coreunit == 0 */ +#define SROM_EPHY_INTERNAL 0x0001 + +/* 4307 uses an external phy at phyaddr 0; want mdcport == coreunit == 0 */ +#define SROM_EPHY_ZERO 0x0000 + +#define SROM_VERS 0x0001 + + +#endif /* _SBSPROM_H */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbutils.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbutils.h index db4d27136f..ed95cb3815 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbutils.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sbutils.h @@ -2,7 +2,7 @@ * Misc utility routines for accessing chip-specific features * of Broadcom HNBU SiliconBackplane-based chips. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -10,14 +10,14 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sbutils.h,v 1.4 2006/04/08 07:12:42 honor Exp $ + * $Id$ */ #ifndef _sbutils_h_ #define _sbutils_h_ /* - * Datastructure to export all chip specific common variables + * Data structure to export all chip specific common variables * public (read-only) portion of sbutils handle returned by * sb_attach()/sb_kattach() */ @@ -29,15 +29,22 @@ struct sb_pub { uint buscorerev; /* buscore rev */ uint buscoreidx; /* buscore index */ int ccrev; /* chip common core rev */ + uint32 cccaps; /* chip common capabilities */ + int pmurev; /* pmu core rev */ + uint32 pmucaps; /* pmu capabilities */ uint boardtype; /* board type */ uint boardvendor; /* board vendor */ + uint boardflags; /* board flags */ uint chip; /* chip number */ uint chiprev; /* chip revision */ uint chippkg; /* chip package option */ + uint32 chipst; /* chip status */ uint sonicsrev; /* sonics backplane rev */ + bool pr42780; /* whether PCIE 42780 WAR applies to this chip */ + bool pr32414; /* whether 432414 WAR applis to the chip */ }; -typedef const struct sb_pub sb_t; +typedef const struct sb_pub sb_t; /* * Many of the routines below take an 'sbh' handle as their first arg. @@ -48,10 +55,11 @@ typedef const struct sb_pub sb_t; */ #define SB_OSH NULL /* Use for sb_kattach when no osh is available */ + /* exported externs */ extern sb_t *sb_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, void *sdh, char **vars, uint *varsz); -extern sb_t *sb_kattach(void); +extern sb_t *sb_kattach(osl_t *osh); extern void sb_detach(sb_t *sbh); extern uint sb_chip(sb_t *sbh); extern uint sb_chiprev(sb_t *sbh); @@ -67,16 +75,20 @@ extern uint sb_buscoretype(sb_t *sbh); extern uint sb_buscorerev(sb_t *sbh); extern uint sb_corelist(sb_t *sbh, uint coreid[]); extern uint sb_coreid(sb_t *sbh); +extern uint sb_flag(sb_t *sbh); extern uint sb_coreidx(sb_t *sbh); extern uint sb_coreunit(sb_t *sbh); extern uint sb_corevendor(sb_t *sbh); extern uint sb_corerev(sb_t *sbh); extern void *sb_osh(sb_t *sbh); extern void sb_setosh(sb_t *sbh, osl_t *osh); +extern uint sb_corereg(sb_t *sbh, uint coreidx, uint regoff, uint mask, uint val); extern void *sb_coreregs(sb_t *sbh); extern uint32 sb_coreflags(sb_t *sbh, uint32 mask, uint32 val); +extern void sb_coreflags_wo(sb_t *sbh, uint32 mask, uint32 val); extern uint32 sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val); extern bool sb_iscoreup(sb_t *sbh); +extern uint sb_findcoreidx(sb_t *sbh, uint coreid, uint coreunit); extern void *sb_setcoreidx(sb_t *sbh, uint coreidx); extern void *sb_setcore(sb_t *sbh, uint coreid, uint coreunit); extern int sb_corebist(sb_t *sbh); @@ -88,6 +100,7 @@ extern void sb_core_tofixup(sb_t *sbh); extern void sb_core_disable(sb_t *sbh, uint32 bits); extern uint32 sb_clock_rate(uint32 pll_type, uint32 n, uint32 m); extern uint32 sb_clock(sb_t *sbh); +extern uint32 sb_alp_clock(sb_t *sbh); extern void sb_pci_setup(sb_t *sbh, uint coremask); extern void sb_pcmcia_init(sb_t *sbh); extern void sb_watchdog(sb_t *sbh, uint ticks); @@ -101,6 +114,17 @@ extern uint32 sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) extern uint32 sb_gpioled(sb_t *sbh, uint32 mask, uint32 val); extern uint32 sb_gpioreserve(sb_t *sbh, uint32 gpio_num, uint8 priority); extern uint32 sb_gpiorelease(sb_t *sbh, uint32 gpio_num, uint8 priority); +extern uint32 sb_gpiopull(sb_t *sbh, bool updown, uint32 mask, uint32 val); +extern uint32 sb_gpioevent(sb_t *sbh, uint regtype, uint32 mask, uint32 val); +extern uint32 sb_gpio_int_enable(sb_t *sbh, bool enable); + +/* GPIO event handlers */ +typedef void (*gpio_handler_t)(uint32 stat, void *arg); + +extern void *sb_gpio_handler_register(sb_t *sbh, uint32 event, + bool level, gpio_handler_t cb, void *arg); +extern void sb_gpio_handler_unregister(sb_t *sbh, void* gpioh); +extern void sb_gpio_handler_process(sb_t *sbh); extern void sb_clkctl_init(sb_t *sbh); extern uint16 sb_clkctl_fast_pwrup_delay(sb_t *sbh); @@ -108,7 +132,9 @@ extern bool sb_clkctl_clk(sb_t *sbh, uint mode); extern int sb_clkctl_xtal(sb_t *sbh, uint what, bool on); extern void sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn, void *intrsenabled_fn, void *intr_arg); -extern uint32 sb_set_initiator_to(sb_t *sbh, uint32 to); +extern void sb_deregister_intr_callback(sb_t *sbh); +extern uint32 sb_set_initiator_to(sb_t *sbh, uint32 to, uint idx); +extern uint16 sb_d11_devid(sb_t *sbh); extern int sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, uint8 *pciheader); @@ -119,7 +145,19 @@ extern bool sb_backplane64(sb_t *sbh); extern void sb_btcgpiowar(sb_t *sbh); +#if defined(BCMDBG_ASSERT) +extern bool sb_taclear(sb_t *sbh); +#endif +#ifdef BCMDBG +extern void sb_dump(sb_t *sbh, struct bcmstrbuf *b); +extern void sb_dumpregs(sb_t *sbh, struct bcmstrbuf *b); +extern void sb_view(sb_t *sbh); +extern void sb_viewall(sb_t *sbh); +extern void sb_clkctl_dump(sb_t *sbh, struct bcmstrbuf *b); +extern uint8 sb_pcieL1plldown(sb_t *sbh); +extern uint32 sb_pcielcreg(sb_t *sbh, uint32 mask, uint32 val); +#endif extern bool sb_deviceremoved(sb_t *sbh); extern uint32 sb_socram_size(sb_t *sbh); @@ -130,6 +168,20 @@ extern uint32 sb_socram_size(sb_t *sbh); * Return 0 on success, nonzero otherwise. */ extern int sb_devpath(sb_t *sbh, char *path, int size); +/* Read variable with prepending the devpath to the name */ +extern char *sb_getdevpathvar(sb_t *sbh, const char *name); +extern int sb_getdevpathintvar(sb_t *sbh, const char *name); + +extern uint8 sb_pcieclkreq(sb_t *sbh, uint32 mask, uint32 val); +extern void sb_war42780_clkreq(sb_t *sbh, bool clkreq); +extern void sb_pci_sleep(sb_t *sbh); +extern void sb_pci_down(sb_t *sbh); +extern void sb_pci_up(sb_t *sbh); + +/* Wake-on-wireless-LAN (WOWL) */ +extern bool sb_pci_pmecap(sb_t *sbh); +extern bool sb_pci_pmeclr(sb_t *sbh); +extern void sb_pci_pmeen(sb_t *sbh); /* clkctl xtal what flags */ #define XTAL 0x1 /* primary crystal oscillator (2050) */ @@ -143,7 +195,16 @@ extern int sb_devpath(sb_t *sbh, char *path, int size); /* GPIO usage priorities */ #define GPIO_DRV_PRIORITY 0 /* Driver */ #define GPIO_APP_PRIORITY 1 /* Application */ -#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO reservation */ +#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO reservation */ + +/* GPIO pull up/down */ +#define GPIO_PULLUP 0 +#define GPIO_PULLDN 1 + +/* GPIO event regtype */ +#define GPIO_REGEVT 0 /* GPIO register event */ +#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ +#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ /* device path */ #define SB_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sflash.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sflash.h index 21a6788fb2..2bdd5fc13c 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sflash.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/sflash.h @@ -1,7 +1,7 @@ /* * Broadcom SiliconBackplane chipcommon serial flash interface * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sflash.h,v 1.1.1.8 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #ifndef _sflash_h_ @@ -17,6 +17,7 @@ #include <typedefs.h> #include <sbchipc.h> +#include <sbutils.h> struct sflash { uint blocksize; /* Block size */ @@ -26,11 +27,14 @@ struct sflash { }; /* Utility functions */ -extern int sflash_poll(chipcregs_t *cc, uint offset); -extern int sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf); -extern int sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf); -extern int sflash_erase(chipcregs_t *cc, uint offset); -extern int sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf); -extern struct sflash * sflash_init(chipcregs_t *cc); +extern int sflash_poll(sb_t *sbh, chipcregs_t *cc, uint offset); +extern int sflash_read(sb_t *sbh, chipcregs_t *cc, + uint offset, uint len, uchar *buf); +extern int sflash_write(sb_t *sbh, chipcregs_t *cc, + uint offset, uint len, const uchar *buf); +extern int sflash_erase(sb_t *sbh, chipcregs_t *cc, uint offset); +extern int sflash_commit(sb_t *sbh, chipcregs_t *cc, + uint offset, uint len, const uchar *buf); +extern struct sflash *sflash_init(sb_t *sbh, chipcregs_t *cc); #endif /* _sflash_h_ */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/trxhdr.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/trxhdr.h index 4b48dfd2fe..4620725f89 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/trxhdr.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/trxhdr.h @@ -1,7 +1,7 @@ /* * TRX image file header format. * - * Copyright 2005, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -10,16 +10,16 @@ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id$ - */ + */ #include <typedefs.h> #define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 -#define TRX_MAX_LEN 0x3A0000 -#define TRX_NO_HEADER 1 /* Do not write TRX header */ +#define TRX_VERSION 1 /* Version 1 */ +#define TRX_MAX_LEN 0x7A0000 /* Max length */ +#define TRX_NO_HEADER 1 /* Do not write TRX header */ #define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ -#define TRX_MAX_OFFSET 3 +#define TRX_MAX_OFFSET 3 /* Max number of individual files */ struct trx_header { uint32 magic; /* "HDR0" */ diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/typedefs.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/typedefs.h index 9c91e2cc57..adb6b1589d 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/typedefs.h +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/include/typedefs.h @@ -1,12 +1,12 @@ /* - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * $Id: typedefs.h,v 1.1.1.12 2006/04/08 06:13:40 honor Exp $ + * $Id$ */ #ifndef _TYPEDEFS_H_ @@ -69,10 +69,13 @@ typedef unsigned char bool; /* consistent w/BOOL */ #endif /* ! __cplusplus */ /* use the Windows ULONG_PTR type when compiling for 64 bit */ -#if defined(_WIN64) +#if defined(_WIN64) && !defined(EFI) #include <basetsd.h> #define TYPEDEF_UINTPTR -typedef ULONG_PTR uintptr; +typedef ULONG_PTR uintptr; +#elif defined(__x86_64__) +#define TYPEDEF_UINTPTR +typedef unsigned long long int uintptr; #endif @@ -80,6 +83,10 @@ typedef ULONG_PTR uintptr; #define _NEED_SIZE_T_ #endif +#if defined(EFI) && !defined(_WIN64) +#define _NEED_SIZE_T_ +#endif + #if defined(_NEED_SIZE_T_) typedef long unsigned int size_t; #endif @@ -104,14 +111,20 @@ typedef unsigned __int64 uint64; #endif -#if defined(linux) +#ifdef linux #define TYPEDEF_UINT #define TYPEDEF_USHORT #define TYPEDEF_ULONG -#endif +#ifdef __KERNEL__ +#include <linux/version.h> +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) +#define TYPEDEF_BOOL +#endif /* >= 2.6.19 */ +#endif /* __KERNEL__ */ +#endif /* linux */ #if !defined(linux) && !defined(_WIN32) && !defined(_CFE_) && \ - !defined(_HNDRTE_) && !defined(_MINOSL_) && !defined(__DJGPP__) + !defined(_HNDRTE_) && !defined(_MINOSL_) && !defined(__DJGPP__) && !defined(__IOPOS__) #define TYPEDEF_UINT #define TYPEDEF_USHORT #endif @@ -137,7 +150,7 @@ typedef unsigned __int64 uint64; #endif /* __ICL */ #if !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && \ - !defined(__DJGPP__) + !defined(__DJGPP__) && !defined(__IOPOS__) /* pick up ushort & uint from standard types.h */ #if defined(linux) && defined(__KERNEL__) @@ -150,7 +163,7 @@ typedef unsigned __int64 uint64; #endif -#endif /* !_WIN32 && !PMON && !_CFE_ && !_HNDRTE_ && !_MINOSL_ && !__DJGPP__ */ +#endif #if defined(MACOSX) @@ -320,7 +333,7 @@ typedef float64 float_t; #define INLINE __inline -#elif __GNUC__ +#elif defined(__GNUC__) #define INLINE __inline__ @@ -353,8 +366,8 @@ typedef float64 float_t; #endif /* USE_TYPEDEF_DEFAULTS */ /* - * Including the bcmdefs.h here, to make sure everyone including typedefs.h - * gets this automatically + * Including the bcmdefs.h here, to make sure everyone including typedefs.h + * gets this automatically */ #include "bcmdefs.h" diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c index d9af5ff8f8..c37023bce7 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c @@ -15,7 +15,6 @@ #include <osl.h> #include <bcmendian.h> #include <bcmnvram.h> -#include <bcmutils.h> #include <sbsdram.h> extern struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value); @@ -244,10 +243,10 @@ BCMINITFN(_nvram_commit)(struct nvram_header *header) header->config_refresh |= SDRAM_REFRESH << 16; header->config_ncdl = 0; } else { - header->crc_ver_init |= (bcm_strtoul(init, NULL, 0) & 0xffff) << 16; - header->config_refresh = bcm_strtoul(config, NULL, 0) & 0xffff; - header->config_refresh |= (bcm_strtoul(refresh, NULL, 0) & 0xffff) << 16; - header->config_ncdl = bcm_strtoul(ncdl, NULL, 0); + header->crc_ver_init |= (simple_strtoul(init, NULL, 0) & 0xffff) << 16; + header->config_refresh = simple_strtoul(config, NULL, 0) & 0xffff; + header->config_refresh |= (simple_strtoul(refresh, NULL, 0) & 0xffff) << 16; + header->config_ncdl = simple_strtoul(ncdl, NULL, 0); } /* Clear data area */ @@ -276,7 +275,7 @@ BCMINITFN(_nvram_commit)(struct nvram_header *header) tmp.crc_ver_init = htol32(header->crc_ver_init); tmp.config_refresh = htol32(header->config_refresh); tmp.config_ncdl = htol32(header->config_ncdl); - crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, CRC8_INIT_VALUE); + crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, 0xff); /* Continue CRC8 over data bytes */ crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc); @@ -313,3 +312,46 @@ BCMINITFN(_nvram_exit)(void) { BCMINIT(nvram_free)(); } + +/* + * Search the name=value vars for a specific one and return its value. + * Returns NULL if not found. + */ +char* +getvar(char *vars, const char *name) +{ + char *s; + int len; + + len = strlen(name); + + /* first look in vars[] */ + for (s = vars; s && *s;) { + /* CSTYLED */ + if ((memcmp(s, name, len) == 0) && (s[len] == '=')) + return (&s[len+1]); + + while (*s++) + ; + } + + /* then query nvram */ + return (nvram_get(name)); +} + +/* + * Search the vars for a specific one and return its value as + * an integer. Returns 0 if not found. + */ +int +getintvar(char *vars, const char *name) +{ + char *val; + + if ((val = getvar(vars, name)) == NULL) + return (0); + + return (simple_strtoul(val, NULL, 0)); +} + + diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram_linux.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram_linux.c index 25104786d5..32278b3778 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram_linux.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram_linux.c @@ -33,7 +33,6 @@ #include <osl.h> #include <bcmendian.h> #include <bcmnvram.h> -#include <bcmutils.h> #include <sbconfig.h> #include <sbchipc.h> #include <sbutils.h> @@ -53,6 +52,9 @@ static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE))); extern void *bcm947xx_sbh; extern spinlock_t bcm947xx_sbh_lock; +static int cfe_env; +extern char *cfe_env_get(char *nv_buf, const char *name); + /* Convenience */ #define sbh bcm947xx_sbh #define sbh_lock bcm947xx_sbh_lock @@ -72,14 +74,14 @@ early_nvram_init(void) if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { base = KSEG1ADDR(SB_FLASH2); - switch (readl(&cc->capabilities) & CAP_FLASH_MASK) { + switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) { case PFLASH: lim = SB_FLASH2_SZ; break; case SFLASH_ST: case SFLASH_AT: - if ((info = sflash_init(cc)) == NULL) + if ((info = sflash_init(sbh,cc)) == NULL) return; lim = info->size; break; @@ -105,6 +107,7 @@ early_nvram_init(void) break; *dst++ = *src++; } + cfe_env = 1; return; } @@ -154,6 +157,9 @@ early_nvram_get(const char *name) if (!nvram_buf[0]) early_nvram_init(); + if (cfe_env) + return cfe_env_get(nvram_buf, name); + /* Look for name=value and return value */ var = &nvram_buf[sizeof(struct nvram_header)]; end = nvram_buf + sizeof(nvram_buf) - 2; diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/pcibios.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/pcibios.c index 8c8f6aab59..2d8549623a 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/pcibios.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/pcibios.c @@ -25,7 +25,6 @@ #include <typedefs.h> #include <osl.h> -#include <bcmutils.h> #include <sbconfig.h> #include <sbutils.h> #include <hndpci.h> @@ -134,7 +133,7 @@ pcibios_init(void) { ulong flags; - if (!(sbh = sb_kattach())) + if (!(sbh = sb_kattach(SB_OSH))) panic("sb_kattach failed"); spin_lock_init(&sbh_lock); @@ -312,6 +311,25 @@ pcibios_enable_device(struct pci_dev *dev, int mask) writel(0x7FF, (ulong)regs + 0x200); udelay(1); } + /* PRxxxx: War for 5354 failures. */ + if (sb_corerev(sbh) == 1) { + uint32 tmp; + + /* Change Flush control reg */ + tmp = readl((uintptr)regs + 0x400); + tmp &= ~8; + writel(tmp, (uintptr)regs + 0x400); + tmp = readl((uintptr)regs + 0x400); + printk("USB20H fcr: 0x%x\n", tmp); + + /* Change Shim control reg */ + tmp = readl((uintptr)regs + 0x304); + tmp &= ~0x100; + writel(tmp, (uintptr)regs + 0x304); + tmp = readl((uintptr)regs + 0x304); + printk("USB20H shim cr: 0x%x\n", tmp); + } + } else sb_core_reset(sbh, 0, 0); diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbmips.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbmips.c index 4a18bb9563..86e2970d24 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbmips.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbmips.c @@ -1,7 +1,7 @@ /* * BCM47XX Sonics SiliconBackplane MIPS core routines * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,27 +9,27 @@ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: hndmips.c,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ + * $Id$ */ #include <typedefs.h> #include <bcmdefs.h> #include <osl.h> -#include <bcmutils.h> #include <sbutils.h> #include <bcmdevs.h> #include <bcmnvram.h> #include <sbconfig.h> -#include <sbextif.h> #include <sbchipc.h> +#include <sbextif.h> #include <sbmemc.h> #include <mipsinc.h> #include <sbhndmips.h> #include <hndcpu.h> +#include <hndmips.h> /* sbipsflag register format, indexed by irq. */ static const uint32 sbips_int_mask[] = { - 0, /* placeholder */ + 0, /* placeholder */ SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, @@ -37,7 +37,7 @@ static const uint32 sbips_int_mask[] = { }; static const uint32 sbips_int_shift[] = { - 0, /* placeholder */ + 0, /* placeholder */ SBIPS_INT1_SHIFT, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, @@ -54,8 +54,7 @@ static const uint32 sbips_int_shift[] = { static uint shirq_map_base = 0; /* Returns the SB interrupt flag of the current core. */ -static uint32 -sb_getflag(sb_t *sbh) +static uint32 sb_getflag(sb_t * sbh) { osl_t *osh; void *regs; @@ -63,7 +62,7 @@ sb_getflag(sb_t *sbh) osh = sb_osh(sbh); regs = sb_coreregs(sbh); - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF); return (R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK); } @@ -72,8 +71,7 @@ sb_getflag(sb_t *sbh) * Returns the MIPS IRQ assignment of the current core. If unassigned, * 0 is returned. */ -uint -sb_irq(sb_t *sbh) +uint sb_irq(sb_t * sbh) { osl_t *osh; uint idx; @@ -89,12 +87,13 @@ sb_irq(sb_t *sbh) if ((regs = sb_setcore(sbh, SB_MIPS, 0)) || (regs = sb_setcore(sbh, SB_MIPS33, 0))) { - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF); /* sbipsflag specifies which core is routed to interrupts 1 to 4 */ sbipsflag = R_REG(osh, &sb->sbipsflag); for (irq = 1; irq <= 4; irq++) { - if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag) + if (((sbipsflag & sbips_int_mask[irq]) >> + sbips_int_shift[irq]) == flag) break; } if (irq == 5) @@ -107,9 +106,7 @@ sb_irq(sb_t *sbh) } /* Clears the specified MIPS IRQ. */ -static void -BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq) -{ +static void BCMINITFN(sb_clearirq) (sb_t * sbh, uint irq) { osl_t *osh; void *regs; sbconfig_t *sb; @@ -119,7 +116,7 @@ BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq) if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) && !(regs = sb_setcore(sbh, SB_MIPS33, 0))) ASSERT(regs); - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF); if (irq == 0) W_REG(osh, &sb->sbintvec, 0); @@ -134,8 +131,7 @@ BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq) * The old assignment to the specified core is removed first. */ static void -BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit) -{ +BCMINITFN(sb_setirq) (sb_t * sbh, uint irq, uint coreid, uint coreunit) { osl_t *osh; void *regs; sbconfig_t *sb; @@ -154,7 +150,7 @@ BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit) if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) && !(regs = sb_setcore(sbh, SB_MIPS33, 0))) ASSERT(regs); - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF); if (!oldirq) AND_REG(osh, &sb->sbintvec, ~(1 << flag)); @@ -175,9 +171,7 @@ BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit) * * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero. */ -void -BCMINITFN(sb_mips_init)(sb_t *sbh, uint shirqmap) -{ +void BCMINITFN(sb_mips_init) (sb_t * sbh, uint shirqmap) { osl_t *osh; ulong hz, ns, tmp; extifregs_t *eir; @@ -199,28 +193,27 @@ BCMINITFN(sb_mips_init)(sb_t *sbh, uint shirqmap) /* Set timing for the flash */ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ - tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */ - tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ + tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */ + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ W_REG(osh, &eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ /* Set programmable interface timing for external uart */ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ - tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */ - tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */ - tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ + tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */ + tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */ + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ W_REG(osh, &eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ } else if ((cc = sb_setcore(sbh, SB_CC, 0))) { /* Set timing for the flash */ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */ - tmp |= CEIL(120, ns); /* W0 = 120nS */ - if ((sb_corerev(sbh) < 9) || - (BCMINIT(sb_chip)(sbh) == 0x5365)) + tmp |= CEIL(120, ns); /* W0 = 120nS */ + if ((sb_corerev(sbh) < 9) || (sb_chip(sbh) == 0x5365)) W_REG(osh, &cc->flash_waitcount, tmp); if ((sb_corerev(sbh) < 9) || - ((sb_chip(sbh) == BCM5350_CHIP_ID) && sb_chiprev(sbh) == 0) || - (BCMINIT(sb_chip)(sbh) == 0x5365)) { + ((sb_chip(sbh) == BCM5350_CHIP_ID) && sb_chiprev(sbh) == 0) + || (sb_chip(sbh) == 0x5365)) { W_REG(osh, &cc->pcmcia_memwait, tmp); } @@ -290,18 +283,21 @@ BCMINITFN(sb_cpu_clock)(sb_t *sbh) n = R_REG(osh, &eir->clockcontrol_n); m = R_REG(osh, &eir->clockcontrol_sb); } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { - pll_type = R_REG(osh, &cc->capabilities) & CAP_PLL_MASK; + /* 5354 chip uses a non programmable PLL of frequency 240MHz */ + if (sb_chip(sbh) == BCM5354_CHIP_ID) { + rate = 240000000; + goto out; + } + pll_type = R_REG(osh, &cc->capabilities) & CC_CAP_PLL_MASK; n = R_REG(osh, &cc->clockcontrol_n); if ((pll_type == PLL_TYPE2) || (pll_type == PLL_TYPE4) || - (pll_type == PLL_TYPE6) || - (pll_type == PLL_TYPE7)) + (pll_type == PLL_TYPE6) || (pll_type == PLL_TYPE7)) m = R_REG(osh, &cc->clockcontrol_m3); else if (pll_type == PLL_TYPE5) { rate = 200000000; goto out; - } - else if (pll_type == PLL_TYPE3) { + } else if (pll_type == PLL_TYPE3) { if (sb_chip(sbh) == BCM5365_CHIP_ID) { rate = 200000000; goto out; @@ -314,9 +310,8 @@ BCMINITFN(sb_cpu_clock)(sb_t *sbh) } else goto out; - /* calculate rate */ - if (BCMINIT(sb_chip)(sbh) == 0x5365) + if (sb_chip(sbh) == 0x5365) rate = 100000000; else rate = sb_clock_rate(pll_type, n, m); @@ -324,7 +319,7 @@ BCMINITFN(sb_cpu_clock)(sb_t *sbh) if (pll_type == PLL_TYPE6) rate = SB2MIPS_T6(rate); -out: + out: /* switch back to previous core */ sb_setcoreidx(sbh, idx); @@ -333,30 +328,20 @@ out: #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) -static void -BCMINITFN(handler)(void) -{ - __asm__( - ".set\tmips32\n\t" - "ssnop\n\t" - "ssnop\n\t" - /* Disable interrupts */ - /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */ +static void BCMINITFN(handler) (void) { + __asm__(".set\tmips32\n\t" "ssnop\n\t" "ssnop\n\t" + /* Disable interrupts */ + /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */ "mfc0 $15, $12\n\t" - /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */ + /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */ "li $14, -31746\n\t" "and $15, $15, $14\n\t" - "mtc0 $15, $12\n\t" - "eret\n\t" - "nop\n\t" - "nop\n\t" + "mtc0 $15, $12\n\t" "eret\n\t" "nop\n\t" "nop\n\t" ".set\tmips0"); } /* The following MUST come right after handler() */ -static void -BCMINITFN(afterhandler)(void) -{ +static void BCMINITFN(afterhandler) (void) { } /* @@ -366,13 +351,15 @@ BCMINITFN(afterhandler)(void) * core rev. 15 to a DLL inside the MIPS core in 4785. */ bool -BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock) -{ +BCMINITFN(sb_mips_setclock) (sb_t * sbh, uint32 mipsclock, uint32 sbclock, + uint32 pciclock) { extifregs_t *eir = NULL; chipcregs_t *cc = NULL; mipsregs_t *mipsr = NULL; - volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2; - uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg; + volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, + *clockcontrol_m2; + uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, + orig_ratio_cfg; uint32 pll_type, sync_mode; uint ic_size, ic_lsize; uint idx, i; @@ -387,63 +374,83 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 } n3m_table_t; static n3m_table_t BCMINITDATA(type1_table)[] = { /* 96.000 32.000 24.000 */ - { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, - /* 100.000 33.333 25.000 */ - { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, - /* 104.000 31.200 24.960 */ - { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, - /* 108.000 32.400 24.923 */ - { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, - /* 112.000 32.000 24.889 */ - { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, - /* 115.200 32.000 24.000 */ - { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, - /* 120.000 30.000 24.000 */ - { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, - /* 124.800 31.200 24.960 */ - { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, - /* 128.000 32.000 24.000 */ - { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, - /* 132.000 33.000 24.750 */ - { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, - /* 136.000 32.640 24.727 */ - { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, - /* 140.000 30.000 24.706 */ - { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, - /* 144.000 30.857 24.686 */ - { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, - /* 150.857 33.000 24.000 */ - { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, - /* 152.000 32.571 24.000 */ - { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, - /* 156.000 31.200 24.960 */ - { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, - /* 160.000 32.000 24.000 */ - { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, - /* 163.200 32.640 24.727 */ - { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, - /* 168.000 32.000 24.889 */ - { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, - /* 176.000 33.000 24.000 */ - { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, - }; + { + 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011}, + /* 100.000 33.333 25.000 */ + { + 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011}, + /* 104.000 31.200 24.960 */ + { + 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009}, + /* 108.000 32.400 24.923 */ + { + 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802}, + /* 112.000 32.000 24.889 */ + { + 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403}, + /* 115.200 32.000 24.000 */ + { + 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011}, + /* 120.000 30.000 24.000 */ + { + 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011}, + /* 124.800 31.200 24.960 */ + { + 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009}, + /* 128.000 32.000 24.000 */ + { + 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305}, + /* 132.000 33.000 24.750 */ + { + 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305}, + /* 136.000 32.640 24.727 */ + { + 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603}, + /* 140.000 30.000 24.706 */ + { + 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02}, + /* 144.000 30.857 24.686 */ + { + 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021}, + /* 150.857 33.000 24.000 */ + { + 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605}, + /* 152.000 32.571 24.000 */ + { + 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02}, + /* 156.000 31.200 24.960 */ + { + 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009}, + /* 160.000 32.000 24.000 */ + { + 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309}, + /* 163.200 32.640 24.727 */ + { + 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603}, + /* 168.000 32.000 24.889 */ + { + 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403}, + /* 176.000 33.000 24.000 */ + { + 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602},}; /* PLL configuration: type 3 */ typedef struct { uint32 mipsclock; uint16 n; - uint32 m2; /* that is the clockcontrol_m2 */ + uint32 m2; /* that is the clockcontrol_m2 */ } type3_table_t; static type3_table_t type3_table[] = { /* for 5350, mips clock is always double sb clock */ - { 150000000, 0x311, 0x4020005 }, - { 200000000, 0x311, 0x4020003 }, - }; + {150000000, 0x311, 0x4020005}, + {200000000, 0x311, 0x4020003}, + }; /* PLL configuration: type 2, 4, 7 */ typedef struct { uint32 mipsclock; uint32 sbclock; + uint32 pciclock; uint16 n; uint32 sb; uint32 pci33; @@ -455,142 +462,252 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 uint32 d11_r2; } n4m_table_t; static n4m_table_t BCMINITDATA(type2_table)[] = { - { 120000000, 60000000, 0x0303, 0x01000200, 0x01000600, 0x01000200, 0x05000200, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 150000000, 75000000, 0x0303, 0x01000100, 0x01000600, 0x01000100, 0x05000100, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, - 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, - 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, - 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, - 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, - 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01010100, 0x05000100, 8, - 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01010100, 0x05000100, 11, - 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 330000000, 132000000, 0x0903, 0x01000200, 0x00020200, 0x01010100, 0x05000100, 0, - 0, 10 /* ratio 4/10 */, 0x02520129 }, - { 330000000, 146666666, 0x0903, 0x01010000, 0x00020200, 0x01010100, 0x05000100, 0, - 0, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 330000000, 165000000, 0x0903, 0x01000100, 0x00020200, 0x01010100, 0x05000100, 0, - 0, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 360000000, 120000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200, 0x05000100, 0, - 0, 12 /* ratio 4/12 */, 0x04920492 }, - { 360000000, 144000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200, 0x05000100, 0, - 0, 10 /* ratio 4/10 */, 0x02520129 }, - { 360000000, 160000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200, 0x05000100, 0, - 0, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 360000000, 180000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200, 0x05000100, 0, - 0, 8 /* ratio 4/8 */, 0x00aa0055 }, - { 390000000, 130000000, 0x0b03, 0x01010100, 0x00020101, 0x01020100, 0x05000100, 0, - 0, 12 /* ratio 4/12 */, 0x04920492 }, - { 390000000, 156000000, 0x0b03, 0x01000200, 0x00020101, 0x01020100, 0x05000100, 0, - 0, 10 /* ratio 4/10 */, 0x02520129 }, - { 390000000, 173000000, 0x0b03, 0x01010000, 0x00020101, 0x01020100, 0x05000100, 0, - 0, 9 /* ratio 4/9 */, 0x012a00a9 }, - { 390000000, 195000000, 0x0b03, 0x01000100, 0x00020101, 0x01020100, 0x05000100, 0, - 0, 8 /* ratio 4/8 */, 0x00aa0055 }, + { + 120000000, 60000000, 32000000, 0x0303, 0x01000200, + 0x01000600, 0x01000200, 0x05000200, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 150000000, 75000000, 33333333, 0x0303, 0x01000100, + 0x01000600, 0x01000100, 0x05000100, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 180000000, 80000000, 30000000, 0x0403, 0x01010000, + 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 180000000, 90000000, 30000000, 0x0403, 0x01000100, + 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 200000000, 100000000, 33333333, 0x0303, 0x02010000, + 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 211200000, 105600000, 30171428, 0x0902, 0x01000200, + 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 220800000, 110400000, 31542857, 0x1500, 0x01000200, + 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 230400000, 115200000, 32000000, 0x0604, 0x01000200, + 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 234000000, 104000000, 31200000, 0x0b01, 0x01010000, + 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 240000000, 120000000, 33333333, 0x0803, 0x01000200, + 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 252000000, 126000000, 33333333, 0x0504, 0x01000100, + 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 264000000, 132000000, 33000000, 0x0903, 0x01000200, + 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 270000000, 120000000, 30000000, 0x0703, 0x01010000, + 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 276000000, 122666666, 31542857, 0x1500, 0x01010000, + 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 280000000, 140000000, 31111111, 0x0503, 0x01000000, + 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 288000000, 128000000, 32914285, 0x0604, 0x01010000, + 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 288000000, 144000000, 32000000, 0x0404, 0x01000000, + 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 300000000, 133333333, 33333333, 0x0803, 0x01010000, + 0x01020600, 0x01010100, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 300000000, 133333333, 37500000, 0x0803, 0x01010000, + 0x01020500, 0x01010100, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 300000000, 133333333, 42857142, 0x0803, 0x01010000, + 0x01020400, 0x01010100, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 300000000, 133333333, 50000000, 0x0803, 0x01010000, + 0x01020300, 0x01010100, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 300000000, 133333333, 60000000, 0x0803, 0x01010000, + 0x01020200, 0x01010100, 0x05000100, 8, 0x012a00a9, + 9 /* ratio 4/9 */ , + 0x012a00a9}, { + 300000000, 150000000, 33333333, 0x0803, 0x01000100, + 0x01020600, 0x01010100, 0x05000100, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 300000000, 150000000, 37500000, 0x0803, 0x01000100, + 0x01020500, 0x01010100, 0x05000100, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 300000000, 150000000, 42857142, 0x0803, 0x01000100, + 0x01020400, 0x01010100, 0x05000100, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 300000000, 150000000, 50000000, 0x0803, 0x01000100, + 0x01020300, 0x01010100, 0x05000100, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 300000000, 150000000, 60000000, 0x0803, 0x01000100, + 0x01020200, 0x01010100, 0x05000100, 11, 0x0aaa0555, + 8 /* ratio 4/8 */ , + 0x00aa0055}, { + 330000000, 132000000, 33000000, 0x0903, 0x01000200, + 0x00020200, 0x01010100, 0x05000100, 0, 0, + 10 /* ratio 4/10 */ , 0x02520129}, + { + 330000000, 146666666, 33000000, 0x0903, 0x01010000, + 0x00020200, 0x01010100, 0x05000100, 0, 0, + 9 /* ratio 4/9 */ , 0x012a00a9}, + { + 330000000, 165000000, 33000000, 0x0903, 0x01000100, + 0x00020200, 0x01010100, 0x05000100, 0, 0, + 8 /* ratio 4/8 */ , 0x00aa0055}, + { + 330000000, 165000000, 41250000, 0x0903, 0x01000100, + 0x00020100, 0x01010100, 0x05000100, 0, 0, + 8 /* ratio 4/8 */ , 0x00aa0055}, + { + 330000000, 165000000, 55000000, 0x0903, 0x01000100, + 0x00020000, 0x01010100, 0x05000100, 0, 0, + 8 /* ratio 4/8 */ , 0x00aa0055}, + { + 360000000, 120000000, 32000000, 0x0a03, 0x01000300, + 0x00010201, 0x01010200, 0x05000100, 0, 0, + 12 /* ratio 4/12 */ , 0x04920492}, + { + 360000000, 144000000, 32000000, 0x0a03, 0x01000200, + 0x00010201, 0x01010200, 0x05000100, 0, 0, + 10 /* ratio 4/10 */ , 0x02520129}, + { + 360000000, 160000000, 32000000, 0x0a03, 0x01010000, + 0x00010201, 0x01010200, 0x05000100, 0, 0, + 9 /* ratio 4/9 */ , 0x012a00a9}, + { + 360000000, 180000000, 32000000, 0x0a03, 0x01000100, + 0x00010201, 0x01010200, 0x05000100, 0, 0, + 8 /* ratio 4/8 */ , 0x00aa0055}, + { + 360000000, 180000000, 40000000, 0x0a03, 0x01000100, + 0x00010101, 0x01010200, 0x05000100, 0, 0, + 8 /* ratio 4/8 */ , 0x00aa0055}, + { + 360000000, 180000000, 53333333, 0x0a03, 0x01000100, + 0x00010001, 0x01010200, 0x05000100, 0, 0, + 8 /* ratio 4/8 */ , 0x00aa0055}, + { + 390000000, 130000000, 32500000, 0x0b03, 0x01010100, + 0x00020101, 0x01020100, 0x05000100, 0, 0, + 12 /* ratio 4/12 */ , 0x04920492}, + { + 390000000, 156000000, 32500000, 0x0b03, 0x01000200, + 0x00020101, 0x01020100, 0x05000100, 0, 0, + 10 /* ratio 4/10 */ , 0x02520129}, + { + 390000000, 173000000, 32500000, 0x0b03, 0x01010000, + 0x00020101, 0x01020100, 0x05000100, 0, 0, + 9 /* ratio 4/9 */ , 0x012a00a9}, + { + 390000000, 195000000, 32500000, 0x0b03, 0x01000100, + 0x00020101, 0x01020100, 0x05000100, 0, 0, + 8 /* ratio 4/8 */ , 0x00aa0055}, }; static n4m_table_t BCMINITDATA(type4_table)[] = { - { 120000000, 60000000, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009, 11, - 0x0aaa0555 }, - { 150000000, 75000000, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005, 11, - 0x0aaa0555 }, - { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, - 0x0aaa0555 }, - { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, - 0x0aaa0555 }, - { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, - 0x0aaa0555 }, - { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, - 0x0aaa0555 }, - { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, - 0x012a00a9 }, - { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, - 0x254a14a9 }, - { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, - 0x0aaa0555 }, - { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, - 0x02520129 }, - { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, - 0x0aaa0555 }, - { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, - 0x0aaa0555 }, - { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, - 0x254a14a9 }, - { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, - 0x254a14a9 }, - { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, - 0x254a14a9 }, - { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, - 0x02520129 }, - { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, - 0x0aaa0555 } + { + 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203, + 0x11020009, 0x04000009, 11, 0x0aaa0555}, { + 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203, + 0x11050002, 0x04000005, 11, 0x0aaa0555}, { + 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011, + 0x04000011, 0x04000003, 11, 0x0aaa0555}, { + 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011, + 0x04020011, 0x04020003, 11, 0x0aaa0555}, { + 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005, + 0x11030002, 0x04000003, 11, 0x0aaa0555}, { + 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103, + 0x11030002, 0x04000003, 11, 0x0aaa0555}, { + 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005, + 0x01030305, 0x04000005, 8, 0x012a00a9}, { + 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203, + 0x11030021, 0x04000003, 13, 0x254a14a9}, { + 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203, + 0x11030002, 0x04000003, 11, 0x0aaa0555}, { + 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005, + 0x02000209, 0x04000002, 9, 0x02520129}, { + 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005, + 0x04000005, 0x04000002, 11, 0x0aaa0555}, { + 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005, + 0x04000005, 0x04000002, 11, 0x0aaa0555}, { + 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909, + 0x02000221, 0x04000003, 13, 0x254a14a9}, { + 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303, + 0x02000221, 0x04000003, 13, 0x254a14a9}, { + 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303, + 0x02000221, 0x04000003, 13, 0x254a14a9}, { + 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203, + 0x02000902, 0x04000002, 9, 0x02520129}, { + 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203, + 0x04000005, 0x04000002, 11, 0x0aaa0555} }; static n4m_table_t BCMINITDATA(type7_table)[] = { - { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, - 0x0aaa0555 }, - { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, - 0x0aaa0555 }, - { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, - 0x0aaa0555 }, - { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, - 0x0aaa0555 }, - { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, - 0x0aaa0555 }, - { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, - 0x0aaa0555 }, - { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, - 0x0aaa0555 }, - { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, - 0x0aaa0555 }, - { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, - 0x0aaa0555 }, - { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, - 0x0aaa0555 } + { + 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011, + 0x04000011, 0x04000003, 11, 0x0aaa0555}, { + 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011, + 0x04000011, 0x04000003, 11, 0x0aaa0555}, { + 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011, + 0x04000009, 0x04000003, 11, 0x0aaa0555}, { + 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011, + 0x04020011, 0x04020003, 11, 0x0aaa0555}, { + 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011, + 0x11020003, 0x04000003, 11, 0x0aaa0555}, { + 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011, + 0x11020003, 0x04000003, 11, 0x0aaa0555}, { + 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011, + 0x11020003, 0x04000003, 11, 0x0aaa0555}, { + 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005, + 0x11020005, 0x04000005, 11, 0x0aaa0555}, { + 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009, + 0x11020009, 0x04000009, 11, 0x0aaa0555}, { + 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003, + 0x11020003, 0x04000003, 11, 0x0aaa0555} }; ulong start, end, dst; @@ -604,6 +721,7 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 idx = sb_coreidx(sbh); clockcontrol_m2 = NULL; + /* switch to chipc core */ /* switch to extif or chipc core */ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { pll_type = PLL_TYPE1; @@ -612,7 +730,15 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 clockcontrol_pci = &eir->clockcontrol_pci; clockcontrol_m2 = &cc->clockcontrol_m2; } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { - pll_type = R_REG(osh, &cc->capabilities) & CAP_PLL_MASK; + /* 5354 chipcommon pll setting can't be changed. + * The PMU on power up comes up with the default clk frequency + * of 240MHz + */ + if (sb_chip(sbh) == BCM5354_CHIP_ID) { + ret = TRUE; + goto done; + } + pll_type = R_REG(osh, &cc->capabilities) & CC_CAP_PLL_MASK; if (pll_type == PLL_TYPE6) { clockcontrol_n = NULL; clockcontrol_sb = NULL; @@ -639,8 +765,9 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 if (pll_type == PLL_TYPE1) { /* Keep the current PCI clock if not specified */ if (pciclock == 0) { - pciclock = sb_clock_rate(pll_type, R_REG(osh, clockcontrol_n), - R_REG(osh, clockcontrol_pci)); + pciclock = + sb_clock_rate(pll_type, R_REG(osh, clockcontrol_n), + R_REG(osh, clockcontrol_pci)); pciclock = (pciclock <= 25000000) ? 25000000 : 33000000; } @@ -648,7 +775,7 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 for (i = 0; i < ARRAYSIZE(type1_table); i++) { ASSERT(type1_table[i].mipsclock == sb_clock_rate(pll_type, type1_table[i].n, - type1_table[i].sb)); + type1_table[i].sb)); if (type1_table[i].mipsclock > mipsclock) break; } @@ -677,7 +804,7 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 /* Reset */ sb_watchdog(sbh, 1); - while (1); + while (1) ; } else if (pll_type == PLL_TYPE3) { /* 5350 */ if (sb_chip(sbh) != BCM5365_CHIP_ID) { @@ -700,8 +827,8 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 /* No PLL change */ orig_m2 = R_REG(osh, &cc->clockcontrol_m2); - if ((orig_n == type3_table[i].n) && - (orig_m2 == type3_table[i].m2)) { + if ((orig_n == type3_table[i].n) + && (orig_m2 == type3_table[i].m2)) { goto done; } @@ -711,12 +838,11 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 /* Reset */ sb_watchdog(sbh, 1); - while (1); + while (1) ; } } else if ((pll_type == PLL_TYPE2) || - (pll_type == PLL_TYPE4) || - (pll_type == PLL_TYPE6) || - (pll_type == PLL_TYPE7)) { + (pll_type == PLL_TYPE4) || + (pll_type == PLL_TYPE6) || (pll_type == PLL_TYPE7)) { n4m_table_t *table = NULL, *te; uint tabsz = 0; @@ -725,19 +851,20 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 orig_mips = R_REG(osh, &cc->clockcontrol_m3); switch (pll_type) { - case PLL_TYPE6: { - uint32 new_mips = 0; + case PLL_TYPE6: + { + uint32 new_mips = 0; - ret = TRUE; - if (mipsclock <= SB2MIPS_T6(CC_T6_M1)) - new_mips = CC_T6_MMASK; + ret = TRUE; + if (mipsclock <= SB2MIPS_T6(CC_T6_M1)) + new_mips = CC_T6_MMASK; - if (orig_mips == new_mips) - goto done; + if (orig_mips == new_mips) + goto done; - W_REG(osh, &cc->clockcontrol_m3, new_mips); - goto end_fill; - } + W_REG(osh, &cc->clockcontrol_m3, new_mips); + goto end_fill; + } case PLL_TYPE2: table = type2_table; tabsz = ARRAYSIZE(type2_table); @@ -765,8 +892,8 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 if ((orig_n == table[i].n) && (orig_sb == table[i].sb) && (orig_pci == table[i].pci33) && - (orig_m2 == table[i].m2) && - (orig_mips == table[i].m3)) { + (orig_m2 == table[i].m2) + && (orig_mips == table[i].m3)) { orig_ratio_parm = table[i].ratio_parm; orig_ratio_cfg = table[i].ratio_cfg; break; @@ -776,9 +903,12 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 /* Search for the closest MIPS clock greater or equal to a preferred value */ for (i = 0; i < tabsz; i++) { ASSERT(table[i].mipsclock == - sb_clock_rate(pll_type, table[i].n, table[i].m3)); - if ((mipsclock <= table[i].mipsclock) && - ((sbclock == 0) || (sbclock <= table[i].sbclock))) + sb_clock_rate(pll_type, table[i].n, + table[i].m3)); + if ((mipsclock <= table[i].mipsclock) + && ((sbclock == 0) || (sbclock <= table[i].sbclock)) + && ((pciclock == 0) + || (pciclock <= table[i].pciclock))) break; } if (i == tabsz) { @@ -793,8 +923,7 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 if ((orig_n == te->n) && (orig_sb == te->sb) && (orig_pci == te->pci33) && - (orig_m2 == te->m2) && - (orig_mips == te->m3)) + (orig_m2 == te->m2) && (orig_mips == te->m3)) goto done; /* Set the PLL controls */ @@ -819,38 +948,23 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 /* Preload the code into the cache */ icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); if (sb_chip(sbh) == BCM4785_CHIP_ID) { - start = ((ulong) &&start_fill_4785) & ~(ic_lsize - 1); - end = ((ulong) &&end_fill_4785 + (ic_lsize - 1)) & ~(ic_lsize - 1); - } - else { - start = ((ulong) &&start_fill) & ~(ic_lsize - 1); - end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1); + start = ((ulong) && start_fill_4785) & ~(ic_lsize - 1); + end = ((ulong) + && end_fill_4785 + (ic_lsize - 1)) & ~(ic_lsize - + 1); + } else { + start = ((ulong) && start_fill) & ~(ic_lsize - 1); + end = ((ulong) + && end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1); } while (start < end) { cache_op(start, Fill_I); start += ic_lsize; } - /* Copy the handler */ - start = (ulong) &handler; - end = (ulong) &afterhandler; - dst = KSEG1ADDR(0x180); - for (i = 0; i < (end - start); i += 4) - *((ulong *)(dst + i)) = *((ulong *)(start + i)); - - /* Preload the handler into the cache one line at a time */ - for (i = 0; i < (end - start); i += ic_lsize) - cache_op(dst + i, Fill_I); - - /* Clear BEV bit */ - MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV); - - /* Enable interrupts */ - MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE)); - /* 4785 clock freq change procedures */ if (sb_chip(sbh) == BCM4785_CHIP_ID) { - start_fill_4785: + start_fill_4785: /* Switch to async */ MTC0(C0_BROADCOM, 4, (1 << 22)); @@ -862,7 +976,8 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 *dll_r1 = *dll_r1 | 0xc0000000; /* Set active cfg */ - MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) | (1 << 3) | 1); + MTC0(C0_BROADCOM, 2, + MFC0(C0_BROADCOM, 2) | (1 << 3) | 1); /* Fake soft reset (clock cfg registers not reset) */ MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2)); @@ -872,33 +987,50 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 /* set watchdog timer */ W_REG(osh, &cc->watchdog, 20); - (void) R_REG(osh, &cc->chipid); + (void)R_REG(osh, &cc->chipid); /* wait for timer interrupt */ - __asm__ __volatile__( - ".set\tmips3\n\t" - "sync\n\t" - "wait\n\t" - ".set\tmips0"); - end_fill_4785: - while (1); + __asm__ __volatile__(".set\tmips3\n\t" + "sync\n\t" "wait\n\t" + ".set\tmips0"); + end_fill_4785: + while (1) ; } /* Generic clock freq change procedures */ else { + /* Copy the handler */ + start = (ulong) & handler; + end = (ulong) & afterhandler; + dst = KSEG1ADDR(0x180); + for (i = 0; i < (end - start); i += 4) + *((ulong *) (dst + i)) = + *((ulong *) (start + i)); + + /* Preload the handler into the cache one line at a time */ + for (i = 0; i < (end - start); i += ic_lsize) + cache_op(dst + i, Fill_I); + + /* Clear BEV bit */ + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV); + + /* Enable interrupts */ + MTC0(C0_STATUS, 0, + MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE)); + /* Enable MIPS timer interrupt */ if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) && !(mipsr = sb_setcore(sbh, SB_MIPS33, 0))) ASSERT(mipsr); W_REG(osh, &mipsr->intmask, 1); - start_fill: + start_fill: /* step 1, set clock ratios */ MTC0(C0_BROADCOM, 3, te->ratio_parm); MTC0(C0_BROADCOM, 1, te->ratio_cfg); /* step 2: program timer intr */ W_REG(osh, &mipsr->timer, 100); - (void) R_REG(osh, &mipsr->timer); + (void)R_REG(osh, &mipsr->timer); /* step 3, switch to async */ sync_mode = MFC0(C0_BROADCOM, 4); @@ -908,10 +1040,8 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 MTC0(C0_BROADCOM, 2, (1 << 3) | 1); /* steps 5 & 6 */ - __asm__ __volatile__( - ".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); + __asm__ __volatile__(".set\tmips3\n\t" "wait\n\t" + ".set\tmips0"); /* step 7, clear cfg active */ MTC0(C0_BROADCOM, 2, 0); @@ -922,22 +1052,20 @@ BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 /* step 8, fake soft reset */ MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2)); - end_fill: + end_fill: /* set watchdog timer */ W_REG(osh, &cc->watchdog, 20); - (void) R_REG(osh, &cc->chipid); + (void)R_REG(osh, &cc->chipid); /* wait for timer interrupt */ - __asm__ __volatile__( - ".set\tmips3\n\t" - "sync\n\t" - "wait\n\t" - ".set\tmips0"); - while (1); + __asm__ __volatile__(".set\tmips3\n\t" + "sync\n\t" "wait\n\t" + ".set\tmips0"); + while (1) ; } } -done: + done: /* Enable 4785 DLL */ if (sb_chip(sbh) == BCM4785_CHIP_ID) { uint32 tmp; @@ -949,7 +1077,7 @@ done: *dll_ctrl |= 0x00000080; /* wait for lock flag to clear */ - while ((*dll_ctrl & 0x2) == 0); + while ((*dll_ctrl & 0x2) == 0) ; /* clear sticky flags (clear on write 1) */ tmp = *dll_ctrl; @@ -969,9 +1097,7 @@ done: return ret; } -void -BCMINITFN(enable_pfc)(uint32 mode) -{ +void BCMINITFN(enable_pfc) (uint32 mode) { ulong start, end; uint ic_size, ic_lsize; @@ -985,8 +1111,9 @@ BCMINITFN(enable_pfc)(uint32 mode) /* enable prefetch cache if available */ if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) { - start = ((ulong) &&setpfc_start) & ~(ic_lsize - 1); - end = ((ulong) &&setpfc_end + (ic_lsize - 1)) & ~(ic_lsize - 1); + start = ((ulong) && setpfc_start) & ~(ic_lsize - 1); + end = ((ulong) + && setpfc_end + (ic_lsize - 1)) & ~(ic_lsize - 1); /* Preload setpfc code into the cache one line at a time */ while (start < end) { @@ -995,22 +1122,20 @@ BCMINITFN(enable_pfc)(uint32 mode) } /* Now set the pfc */ - setpfc_start: + setpfc_start: /* write range */ *(volatile uint32 *)PFC_CR1 = 0xffff0000; /* enable */ *(volatile uint32 *)PFC_CR0 = mode; - setpfc_end: + setpfc_end: /* Compiler foder */ ic_size = 0; } } /* returns the ncdl value to be programmed into sdram_ncdl for calibration */ -uint32 -BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh) -{ +uint32 BCMINITFN(sb_memc_get_ncdl) (sb_t * sbh) { osl_t *osh; sbmemcregs_t *memc; uint32 ret = 0; @@ -1021,7 +1146,7 @@ BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh) idx = sb_coreidx(sbh); - memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0); + memc = (sbmemcregs_t *) sb_setcore(sbh, SB_MEMC, 0); if (memc == 0) goto out; @@ -1043,19 +1168,33 @@ BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh) if (rev > 0) cd = rd; else - cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD); + cd = (rd == + MEMC_CD_THRESHOLD) ? rd : (wr + + MEMC_CD_THRESHOLD); sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT; sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT; ret = (sm << 16) | (sd << 8) | cd; } -out: + out: /* switch back to previous core */ sb_setcoreidx(sbh, idx); return ret; } +void hnd_cpu_reset(sb_t * sbh) +{ + if (sb_chip(sbh) == BCM4785_CHIP_ID) + MTC0(C0_BROADCOM, 4, (1 << 22)); + sb_watchdog(sbh, 1); + if (sb_chip(sbh) == BCM4785_CHIP_ID) { + __asm__ __volatile__(".set\tmips3\n\t" + "sync\n\t" "wait\n\t" ".set\tmips0"); + } + while (1) ; +} + #if defined(BCMPERFSTATS) /* * CP0 Register 25 supports 4 semi-independent 32bit performance counters. @@ -1065,68 +1204,64 @@ out: */ /* enable and start instruction counting */ -void -hndmips_perf_instrcount_enable() +void hndmips_perf_cyclecount_enable(void) { MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */ - MTC0(C0_PERFORMANCE, 4, - 0x8044 | MFC0(C0_PERFORMANCE, 4)); /* enable instruction counting for counter 0 */ - MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */ + MTC0(C0_PERFORMANCE, 4, 0x8048 | MFC0(C0_PERFORMANCE, 4)); /* enable cycles counting for counter 0 */ + MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */ +} + +void hndmips_perf_instrcount_enable(void) +{ + MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */ + MTC0(C0_PERFORMANCE, 4, 0x8044 | MFC0(C0_PERFORMANCE, 4)); /* enable instructions counting for counter 0 */ + MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */ } /* enable and start I$ hit and I$ miss counting */ -void -hndmips_perf_icachecount_enable(void) +void hndmips_perf_icachecount_enable(void) { MTC0(C0_PERFORMANCE, 6, 0x80000218); /* enable I$ counting */ MTC0(C0_PERFORMANCE, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */ - MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # I$ hits */ - MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # I$ misses */ + MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # I$ hits */ + MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # I$ misses */ } /* enable and start D$ hit and I$ miss counting */ -void -hndmips_perf_dcachecount_enable(void) +void hndmips_perf_dcachecount_enable(void) { MTC0(C0_PERFORMANCE, 6, 0x80000211); /* enable D$ counting */ MTC0(C0_PERFORMANCE, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */ - MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # D$ hits */ - MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # D$ misses */ + MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # D$ hits */ + MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # D$ misses */ } -void -hndmips_perf_icache_miss_enable() +void hndmips_perf_icache_miss_enable() { - MTC0(C0_PERFORMANCE, 4, - 0x80140000 | MFC0(C0_PERFORMANCE, 4)); /* enable cache misses counting for counter 1 */ - MTC0(C0_PERFORMANCE, 1, 0); /* zero counter one */ + MTC0(C0_PERFORMANCE, 4, 0x80140000 | MFC0(C0_PERFORMANCE, 4)); /* enable cache misses counting for counter 1 */ + MTC0(C0_PERFORMANCE, 1, 0); /* zero counter one */ } - -void -hndmips_perf_icache_hit_enable() +void hndmips_perf_icache_hit_enable() { MTC0(C0_PERFORMANCE, 5, 0x8018 | MFC0(C0_PERFORMANCE, 5)); /* enable cache hits counting for counter 2 */ - MTC0(C0_PERFORMANCE, 2, 0); /* zero counter 2 */ + MTC0(C0_PERFORMANCE, 2, 0); /* zero counter 2 */ } -uint32 -hndmips_perf_read_instrcount() +uint32 hndmips_perf_read_instrcount() { return -(long)(MFC0(C0_PERFORMANCE, 0)); } -uint32 -hndmips_perf_read_cache_miss() +uint32 hndmips_perf_read_cache_miss() { return -(long)(MFC0(C0_PERFORMANCE, 1)); } -uint32 -hndmips_perf_read_cache_hit() +uint32 hndmips_perf_read_cache_hit() { return -(long)(MFC0(C0_PERFORMANCE, 2)); } -#endif /* BCMINTERNAL | BCMPERFSTATS */ +#endif diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbpci.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbpci.c index 2738efaa88..f841ad119d 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbpci.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbpci.c @@ -17,7 +17,6 @@ #include <pcicfg.h> #include <bcmdevs.h> #include <sbconfig.h> -#include <bcmutils.h> #include <sbutils.h> #include <sbpci.h> #include <bcmendian.h> @@ -31,7 +30,7 @@ #define PCI_MSG(args) printf args #else #define PCI_MSG(args) -#endif /* BCMDBG_PCI */ +#endif /* BCMDBG_PCI */ /* Can free sbpci_init() memory after boot */ #ifndef linux @@ -40,11 +39,11 @@ /* Emulated configuration space */ typedef struct { - int n; - uint size0; - uint size1; - uint size2; - uint size3; + int n; + uint size0; + uint size1; + uint size2; + uint size3; } sb_bar_cfg_t; static pci_config_regs sb_config_regs[SB_MAXCORES]; static sb_bar_cfg_t sb_bar_cfg[SB_MAXCORES]; @@ -86,10 +85,9 @@ static uint8 pci_hbslot = 0; */ /* Assume one-hot slot wiring */ -#define PCI_SLOT_MAX 16 /* Max. PCI Slots */ +#define PCI_SLOT_MAX 16 /* Max. PCI Slots */ -static uint32 -config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off) +static uint32 config_cmd(sb_t * sbh, uint bus, uint dev, uint func, uint off) { uint coreidx; sbpciregs_t *regs; @@ -112,21 +110,21 @@ config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off) uint32 win; /* Slide the PCI window to the appropriate slot */ - win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); + win = + (SBTOPCI_CFG0 | + ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); W_REG(osh, ®s->sbtopci1, win); addr = SB_PCI_CFG | - ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | - (func << PCICFG_FUN_SHIFT) | - (off & ~3); + ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | + (func << PCICFG_FUN_SHIFT) | (off & ~3); } } else { /* Type 1 transaction */ W_REG(osh, ®s->sbtopci1, SBTOPCI_CFG1); addr = SB_PCI_CFG | - (bus << PCICFG_BUS_SHIFT) | - (dev << PCICFG_SLOT_SHIFT) | - (func << PCICFG_FUN_SHIFT) | - (off & ~3); + (bus << PCICFG_BUS_SHIFT) | + (dev << PCICFG_SLOT_SHIFT) | + (func << PCICFG_FUN_SHIFT) | (off & ~3); } sb_setcoreidx(sbh, coreidx); @@ -145,8 +143,8 @@ config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off) * the register address where value in 'val' is read. */ static bool -sb_pcihb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, - uint32 **addr, uint32 *val) +sb_pcihb_read_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, + uint32 ** addr, uint32 * val) { sbpciregs_t *regs; osl_t *osh; @@ -162,9 +160,9 @@ sb_pcihb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, /* read pci config when core rev >= 8 */ coreidx = sb_coreidx(sbh); - regs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0); + regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0); if (regs && sb_corerev(sbh) >= PCI_HBSBCFG_REV) { - *addr = (uint32 *)®s->pcicfg[func][off >> 2]; + *addr = (uint32 *) & regs->pcicfg[func][off >> 2]; *val = R_REG(osh, *addr); ret = TRUE; } @@ -174,30 +172,30 @@ sb_pcihb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, } int -extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +extpci_read_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, + void *buf, int len) { uint32 addr = 0, *reg = NULL, val; int ret = 0; /* * Set value to -1 when: - * flag 'pci_disabled' is true; - * value of 'addr' is zero; - * REG_MAP() fails; - * BUSPROBE() fails; + * flag 'pci_disabled' is true; + * value of 'addr' is zero; + * REG_MAP() fails; + * BUSPROBE() fails; */ if (pci_disabled) val = 0xffffffff; else if (bus == 1 && dev == pci_hbslot && func == 0 && - sb_pcihb_read_config(sbh, bus, dev, func, off, ®, &val)) - ; + sb_pcihb_read_config(sbh, bus, dev, func, off, ®, &val)) ; else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) || - ((reg = (uint32 *)REG_MAP(addr, len)) == 0) || - (BUSPROBE(val, reg) != 0)) + ((reg = (uint32 *) REG_MAP(addr, len)) == 0) || + (BUSPROBE(val, reg) != 0)) val = 0xffffffff; PCI_MSG(("%s: 0x%x <= 0x%p(0x%x), len %d, off 0x%x, buf 0x%p\n", - __FUNCTION__, val, reg, addr, len, off, buf)); + __FUNCTION__, val, reg, addr, len, off, buf)); val >>= 8 * (off & 3); if (len == 4) @@ -216,7 +214,8 @@ extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf } int -extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +extpci_write_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, + void *buf, int len) { osl_t *osh; uint32 addr = 0, *reg = NULL, val; @@ -226,19 +225,18 @@ extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *bu /* * Ignore write attempt when: - * flag 'pci_disabled' is true; - * value of 'addr' is zero; - * REG_MAP() fails; - * BUSPROBE() fails; + * flag 'pci_disabled' is true; + * value of 'addr' is zero; + * REG_MAP() fails; + * BUSPROBE() fails; */ if (pci_disabled) return 0; else if (bus == 1 && dev == pci_hbslot && func == 0 && - sb_pcihb_read_config(sbh, bus, dev, func, off, ®, &val)) - ; + sb_pcihb_read_config(sbh, bus, dev, func, off, ®, &val)) ; else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) || - ((reg = (uint32 *) REG_MAP(addr, len)) == 0) || - (BUSPROBE(val, reg) != 0)) + ((reg = (uint32 *) REG_MAP(addr, len)) == 0) || + (BUSPROBE(val, reg) != 0)) goto done; if (len == 4) @@ -258,7 +256,7 @@ extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *bu W_REG(osh, reg, val); -done: + done: if (reg && addr) REG_UNMAP(reg); @@ -287,8 +285,8 @@ done: /* Sync the emulation registers and the real PCI config registers. */ static void -sb_pcid_read_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, - uint off, uint len) +sb_pcid_read_config(sb_t * sbh, uint coreidx, sb_pci_cfg_t * cfg, + uint off, uint len) { osl_t *osh; uint oldidx; @@ -308,21 +306,23 @@ sb_pcid_read_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, sb_setcoreidx(sbh, coreidx); if (sb_iscoreup(sbh)) { if (len == 4) - *(uint32 *)((ulong)cfg->emu + off) = - htol32(R_REG(osh, (uint32 *)((ulong)cfg->pci + off))); + *(uint32 *) ((ulong) cfg->emu + off) = + htol32(R_REG + (osh, (uint32 *) ((ulong) cfg->pci + off))); else if (len == 2) - *(uint16 *)((ulong)cfg->emu + off) = - htol16(R_REG(osh, (uint16 *)((ulong)cfg->pci + off))); + *(uint16 *) ((ulong) cfg->emu + off) = + htol16(R_REG + (osh, (uint16 *) ((ulong) cfg->pci + off))); else if (len == 1) - *(uint8 *)((ulong)cfg->emu + off) = - R_REG(osh, (uint8 *)((ulong)cfg->pci + off)); + *(uint8 *) ((ulong) cfg->emu + off) = + R_REG(osh, (uint8 *) ((ulong) cfg->pci + off)); } sb_setcoreidx(sbh, oldidx); } static void -sb_pcid_write_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, - uint off, uint len) +sb_pcid_write_config(sb_t * sbh, uint coreidx, sb_pci_cfg_t * cfg, + uint off, uint len) { osl_t *osh; uint oldidx; @@ -342,14 +342,14 @@ sb_pcid_write_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, sb_setcoreidx(sbh, coreidx); if (sb_iscoreup(sbh)) { if (len == 4) - W_REG(osh, (uint32 *)((ulong)cfg->pci + off), - ltoh32(*(uint32 *)((ulong)cfg->emu + off))); + W_REG(osh, (uint32 *) ((ulong) cfg->pci + off), + ltoh32(*(uint32 *) ((ulong) cfg->emu + off))); else if (len == 2) - W_REG(osh, (uint16 *)((ulong)cfg->pci + off), - ltoh16(*(uint16 *)((ulong)cfg->emu + off))); + W_REG(osh, (uint16 *) ((ulong) cfg->pci + off), + ltoh16(*(uint16 *) ((ulong) cfg->emu + off))); else if (len == 1) - W_REG(osh, (uint8 *)((ulong)cfg->pci + off), - *(uint8 *)((ulong)cfg->emu + off)); + W_REG(osh, (uint8 *) ((ulong) cfg->pci + off), + *(uint8 *) ((ulong) cfg->emu + off)); } sb_setcoreidx(sbh, oldidx); } @@ -358,16 +358,18 @@ sb_pcid_write_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, * Functions for accessing translated SB configuration space */ static int -sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +sb_read_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, void *buf, + int len) { pci_config_regs *cfg; - if (dev >= SB_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs)) + if (dev >= SB_MAXCORES || func >= MAXFUNCS + || (off + len) > sizeof(pci_config_regs)) return -1; cfg = sb_pci_cfg[dev][func].emu; ASSERT(ISALIGNED(off, len)); - ASSERT(ISALIGNED((uintptr)buf, len)); + ASSERT(ISALIGNED((uintptr) buf, len)); /* use special config space if the device does not exist */ if (!cfg) @@ -377,11 +379,11 @@ sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, in sb_pcid_read_config(sbh, dev, &sb_pci_cfg[dev][func], off, len); if (len == 4) - *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off))); + *((uint32 *) buf) = ltoh32(*((uint32 *) ((ulong) cfg + off))); else if (len == 2) - *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off))); + *((uint16 *) buf) = ltoh16(*((uint16 *) ((ulong) cfg + off))); else if (len == 1) - *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off)); + *((uint8 *) buf) = *((uint8 *) ((ulong) cfg + off)); else return -1; @@ -389,7 +391,8 @@ sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, in } static int -sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +sb_write_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, void *buf, + int len) { uint coreidx; void *regs; @@ -397,14 +400,15 @@ sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, i osl_t *osh; sb_bar_cfg_t *bar; - if (dev >= SB_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs)) + if (dev >= SB_MAXCORES || func >= MAXFUNCS + || (off + len) > sizeof(pci_config_regs)) return -1; cfg = sb_pci_cfg[dev][func].emu; if (!cfg) return -1; ASSERT(ISALIGNED(off, len)); - ASSERT(ISALIGNED((uintptr)buf, len)); + ASSERT(ISALIGNED((uintptr) buf, len)); osh = sb_osh(sbh); @@ -418,33 +422,37 @@ sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, i /* Highest numbered address match register */ if (off == OFFSETOF(pci_config_regs, base[0])) cfg->base[0] = ~(bar->size0 - 1); - else if (off == OFFSETOF(pci_config_regs, base[1]) && bar->n >= 1) + else if (off == OFFSETOF(pci_config_regs, base[1]) + && bar->n >= 1) cfg->base[1] = ~(bar->size1 - 1); - else if (off == OFFSETOF(pci_config_regs, base[2]) && bar->n >= 2) + else if (off == OFFSETOF(pci_config_regs, base[2]) + && bar->n >= 2) cfg->base[2] = ~(bar->size2 - 1); - else if (off == OFFSETOF(pci_config_regs, base[3]) && bar->n >= 3) + else if (off == OFFSETOF(pci_config_regs, base[3]) + && bar->n >= 3) cfg->base[3] = ~(bar->size3 - 1); } sb_setcoreidx(sbh, coreidx); - } - else if (len == 4) - *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf)); + } else if (len == 4) + *((uint32 *) ((ulong) cfg + off)) = htol32(*((uint32 *) buf)); else if (len == 2) - *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf)); + *((uint16 *) ((ulong) cfg + off)) = htol16(*((uint16 *) buf)); else if (len == 1) - *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf); + *((uint8 *) ((ulong) cfg + off)) = *((uint8 *) buf); else return -1; /* sync emulation with real PCI config if necessary */ if (sb_pci_cfg[dev][func].pci) - sb_pcid_write_config(sbh, dev, &sb_pci_cfg[dev][func], off, len); + sb_pcid_write_config(sbh, dev, &sb_pci_cfg[dev][func], off, + len); return 0; } int -sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +sbpci_read_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, + void *buf, int len) { if (bus == 0) return sb_read_config(sbh, bus, dev, func, off, buf, len); @@ -453,7 +461,8 @@ sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, } int -sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +sbpci_write_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, + void *buf, int len) { if (bus == 0) return sb_write_config(sbh, bus, dev, func, off, buf, len); @@ -461,8 +470,7 @@ sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf return extpci_write_config(sbh, bus, dev, func, off, buf, len); } -void -sbpci_ban(uint16 core) +void sbpci_ban(uint16 core) { if (pci_banned < ARRAYSIZE(pci_ban)) pci_ban[pci_banned++] = core; @@ -473,8 +481,7 @@ sbpci_ban(uint16 core) * Otherwise return -1 to indicate there is no PCI core and return 1 * to indicate PCI core is disabled. */ -int __init -sbpci_init_pci(sb_t *sbh) +int __init sbpci_init_pci(sb_t * sbh) { uint chip, chiprev, chippkg, host; uint32 boardflags; @@ -499,8 +506,8 @@ sbpci_init_pci(sb_t *sbh) if ((chip == 0x4310) && (chiprev == 0)) pci_disabled = TRUE; - - sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF); + + sb = (sbconfig_t *) ((ulong) pci + SBCONFIGOFF); boardflags = (uint32) getintvar(NULL, "boardflags"); @@ -511,8 +518,7 @@ sbpci_init_pci(sb_t *sbh) */ if (((chip == BCM4712_CHIP_ID) && ((chippkg == BCM4712SMALL_PKG_ID) || - (chippkg == BCM4712MID_PKG_ID))) || - (boardflags & BFL_NOPCI)) + (chippkg == BCM4712MID_PKG_ID))) || (boardflags & BFL_NOPCI)) pci_disabled = TRUE; /* Enable the core */ @@ -550,13 +556,13 @@ sbpci_init_pci(sb_t *sbh) } /* Reset the external PCI bus and enable the clock */ - W_REG(osh, &pci->control, 0x5); /* enable the tristate drivers */ - W_REG(osh, &pci->control, 0xd); /* enable the PCI clock */ - OSL_DELAY(150); /* delay > 100 us */ - W_REG(osh, &pci->control, 0xf); /* deassert PCI reset */ + W_REG(osh, &pci->control, 0x5); /* enable the tristate drivers */ + W_REG(osh, &pci->control, 0xd); /* enable the PCI clock */ + OSL_DELAY(150); /* delay > 100 us */ + W_REG(osh, &pci->control, 0xf); /* deassert PCI reset */ /* Use internal arbiter and park REQ/GRNT at external master 0 */ W_REG(osh, &pci->arbcontrol, PCI_INT_ARB); - OSL_DELAY(1); /* delay 1 us */ + OSL_DELAY(1); /* delay 1 us */ if (sb_corerev(sbh) >= 8) { val = getintvar(NULL, "parkid"); ASSERT(val <= PCI_PARKID_LAST); @@ -571,7 +577,8 @@ sbpci_init_pci(sb_t *sbh) /* GPIO 1 resets the CardBus device on bcm94710ap */ sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY); sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY); - W_REG(osh, &pci->sprom[0], R_REG(osh, &pci->sprom[0]) | 0x400); + W_REG(osh, &pci->sprom[0], + R_REG(osh, &pci->sprom[0]) | 0x400); } /* 64 MB I/O access window */ @@ -583,13 +590,14 @@ sbpci_init_pci(sb_t *sbh) /* Host bridge slot # nvram overwrite */ if ((hbslot = nvram_get("pcihbslot"))) { - pci_hbslot = bcm_strtoul(hbslot, NULL, 0); + pci_hbslot = simple_strtoul(hbslot, NULL, 0); ASSERT(pci_hbslot < PCI_MAX_DEVICES); } /* Enable PCI bridge BAR0 prefetch and burst */ val = 6; - sbpci_write_config(sbh, 1, pci_hbslot, 0, PCI_CFG_CMD, &val, sizeof(val)); + sbpci_write_config(sbh, 1, pci_hbslot, 0, PCI_CFG_CMD, &val, + sizeof(val)); /* Enable PCI interrupts */ W_REG(osh, &pci->intmask, PCI_INTA); @@ -602,7 +610,8 @@ sbpci_init_pci(sb_t *sbh) * Get the PCI region address and size information. */ static void __init -sbpci_init_regions(sb_t *sbh, uint func, pci_config_regs *cfg, sb_bar_cfg_t *bar) +sbpci_init_regions(sb_t * sbh, uint func, pci_config_regs * cfg, + sb_bar_cfg_t * bar) { osl_t *osh; uint16 coreid; @@ -610,26 +619,26 @@ sbpci_init_regions(sb_t *sbh, uint func, pci_config_regs *cfg, sb_bar_cfg_t *bar sbconfig_t *sb; uint32 base; - osh = sb_osh(sbh); - coreid = sb_coreid(sbh); - regs = sb_coreregs(sbh); - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + osh = sb_osh(sbh); + coreid = sb_coreid(sbh); + regs = sb_coreregs(sbh); + sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF); switch (coreid) { case SB_USB20H: base = htol32(sb_base(R_REG(osh, &sb->sbadmatch0))); - cfg->base[0] = func == 0 ? base : base + 0x800; /* OHCI/EHCI */ + cfg->base[0] = func == 0 ? base : base + 0x800; /* OHCI/EHCI */ cfg->base[1] = 0; cfg->base[2] = 0; cfg->base[3] = 0; cfg->base[4] = 0; cfg->base[5] = 0; - bar->n = 1; - bar->size0 = func == 0 ? 0x200 : 0x100; /* OHCI/EHCI */ - bar->size1 = 0; - bar->size2 = 0; - bar->size3 = 0; + bar->n = 1; + bar->size0 = func == 0 ? 0x200 : 0x100; /* OHCI/EHCI */ + bar->size1 = 0; + bar->size2 = 0; + bar->size3 = 0; break; default: cfg->base[0] = htol32(sb_base(R_REG(osh, &sb->sbadmatch0))); @@ -638,11 +647,13 @@ sbpci_init_regions(sb_t *sbh, uint func, pci_config_regs *cfg, sb_bar_cfg_t *bar cfg->base[3] = htol32(sb_base(R_REG(osh, &sb->sbadmatch3))); cfg->base[4] = 0; cfg->base[5] = 0; - bar->n = (R_REG(osh, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT; - bar->size0 = sb_size(R_REG(osh, &sb->sbadmatch0)); - bar->size1 = sb_size(R_REG(osh, &sb->sbadmatch1)); - bar->size2 = sb_size(R_REG(osh, &sb->sbadmatch2)); - bar->size3 = sb_size(R_REG(osh, &sb->sbadmatch3)); + bar->n = + (R_REG(osh, &sb->sbidlow) & SBIDL_AR_MASK) >> + SBIDL_AR_SHIFT; + bar->size0 = sb_size(R_REG(osh, &sb->sbadmatch0)); + bar->size1 = sb_size(R_REG(osh, &sb->sbadmatch1)); + bar->size2 = sb_size(R_REG(osh, &sb->sbadmatch2)); + bar->size3 = sb_size(R_REG(osh, &sb->sbadmatch3)); break; } } @@ -651,8 +662,7 @@ sbpci_init_regions(sb_t *sbh, uint func, pci_config_regs *cfg, sb_bar_cfg_t *bar * Construct PCI config spaces for SB cores so that they * can be accessed as if they were PCI devices. */ -static void __init -sbpci_init_cores(sb_t *sbh) +static void __init sbpci_init_cores(sb_t * sbh) { uint chiprev, coreidx, i; sbconfig_t *sb; @@ -679,11 +689,11 @@ sbpci_init_cores(sb_t *sbh) memset(&sb_pci_null, -1, sizeof(sb_pci_null)); cfg = sb_config_regs; bar = sb_bar_cfg; - for (dev = 0; dev < SB_MAXCORES; dev ++) { + for (dev = 0; dev < SB_MAXCORES; dev++) { /* Check if the core exists */ if (!(regs = sb_setcoreidx(sbh, dev))) continue; - sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF); /* Check if this core is banned */ coreid = sb_coreid(sbh); @@ -701,8 +711,9 @@ sbpci_init_cores(sb_t *sbh) } /* Convert core id to pci id */ - if (sb_corepciid(sbh, func, &vendor, &device, &class, &subclass, - &progif, &header)) + if (sb_corepciid + (sbh, func, &vendor, &device, &class, &subclass, + &progif, &header)) continue; /* @@ -712,13 +723,16 @@ sbpci_init_cores(sb_t *sbh) */ switch (device) { case BCM47XX_GIGETH_ID: - pci = (pci_config_regs *)((uint32)regs + 0x800); + pci = + (pci_config_regs *) ((uint32) regs + 0x800); break; case BCM47XX_SATAXOR_ID: - pci = (pci_config_regs *)((uint32)regs + 0x400); + pci = + (pci_config_regs *) ((uint32) regs + 0x400); break; case BCM47XX_ATA100_ID: - pci = (pci_config_regs *)((uint32)regs + 0x800); + pci = + (pci_config_regs *) ((uint32) regs + 0x800); break; default: pci = NULL; @@ -734,22 +748,23 @@ sbpci_init_cores(sb_t *sbh) cfg->header_type = header; sbpci_init_regions(sbh, func, cfg, bar); /* Save core interrupt flag */ - cfg->int_pin = R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK; + cfg->int_pin = + R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK; /* Save core interrupt assignment */ cfg->int_line = sb_irq(sbh); /* Indicate there is no SROM */ - *((uint32 *) &cfg->sprom_control) = 0xffffffff; + *((uint32 *) & cfg->sprom_control) = 0xffffffff; /* Point to the PCI config spaces */ sb_pci_cfg[dev][func].emu = cfg; sb_pci_cfg[dev][func].pci = pci; sb_pci_cfg[dev][func].bar = bar; - cfg ++; - bar ++; + cfg++; + bar++; } } -done: + done: sb_setcoreidx(sbh, coreidx); } @@ -758,11 +773,9 @@ done: * Must propagate sbpci_init_pci() return value to the caller to let * them know the PCI core initialization status. */ -int __init -sbpci_init(sb_t *sbh) +int __init sbpci_init(sb_t * sbh) { int status = sbpci_init_pci(sbh); sbpci_init_cores(sbh); return status; } - diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c index 672e027d88..244a1324f6 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c @@ -2,87 +2,123 @@ * Misc utility routines for accessing chip-specific features * of the SiliconBackplane-based Broadcom chips. * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * $Id: sbutils.c,v 1.10 2006/04/08 07:12:42 honor Exp $ + * $Id$ */ #include <typedefs.h> #include <bcmdefs.h> #include <osl.h> -#include <bcmutils.h> #include <sbutils.h> #include <bcmdevs.h> #include <sbconfig.h> #include <sbchipc.h> +#include <sbextif.h> #include <sbpci.h> #include <sbpcie.h> #include <pcicfg.h> #include <sbpcmcia.h> -#include <sbextif.h> #include <sbsocram.h> +#include <bcmnvram.h> #include <bcmsrom.h> -#ifdef __mips__ -#include <mipsinc.h> -#endif /* __mips__ */ +#include <hndpmu.h> /* debug/trace */ #define SB_ERROR(args) -typedef uint32 (*sb_intrsoff_t)(void *intr_arg); -typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg); -typedef bool (*sb_intrsenabled_t)(void *intr_arg); +#ifdef BCMDBG +#define SB_MSG(args) printf args +#else +#define SB_MSG(args) +#endif /* BCMDBG */ + +typedef uint32(*sb_intrsoff_t) (void *intr_arg); +typedef void (*sb_intrsrestore_t) (void *intr_arg, uint32 arg); +typedef bool(*sb_intrsenabled_t) (void *intr_arg); + +typedef struct gpioh_item { + void *arg; + bool level; + gpio_handler_t handler; + uint32 event; + struct gpioh_item *next; +} gpioh_item_t; /* misc sb info needed by some of the routines */ typedef struct sb_info { - struct sb_pub sb; /* back plane public state (must be first field) */ + struct sb_pub sb; /* back plane public state (must be first field) */ + + void *osh; /* osl os handle */ + void *sdh; /* bcmsdh handle */ + + void *curmap; /* current regs va */ + void *regs[SB_MAXCORES]; /* other regs va */ - void *osh; /* osl os handle */ - void *sdh; /* bcmsdh handle */ + uint curidx; /* current core index */ + uint dev_coreid; /* the core provides driver functions */ - void *curmap; /* current regs va */ - void *regs[SB_MAXCORES]; /* other regs va */ + bool memseg; /* flag to toggle MEM_SEG register */ - uint curidx; /* current core index */ - uint dev_coreid; /* the core provides driver functions */ + uint gpioidx; /* gpio control core index */ + uint gpioid; /* gpio control coretype */ - bool memseg; /* flag to toggle MEM_SEG register */ + uint numcores; /* # discovered cores */ + uint coreid[SB_MAXCORES]; /* id of each core */ - uint gpioidx; /* gpio control core index */ - uint gpioid; /* gpio control coretype */ + void *intr_arg; /* interrupt callback function arg */ + sb_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ + sb_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ + sb_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ - uint numcores; /* # discovered cores */ - uint coreid[SB_MAXCORES]; /* id of each core */ + uint8 pciecap_lcreg_offset; /* PCIE capability LCreg offset in the config space */ + bool pr42767_war; + uint8 pcie_polarity; + bool pcie_war_ovr; /* Override ASPM/Clkreq settings */ - void *intr_arg; /* interrupt callback function arg */ - sb_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ - sb_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ - sb_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ + uint8 pmecap_offset; /* PM Capability offset in the config space */ + bool pmecap; /* Capable of generating PME */ + gpioh_item_t *gpioh_head; /* GPIO event handlers list */ + + char *vars; + uint varsz; } sb_info_t; /* local prototypes */ -static sb_info_t * sb_doattach(sb_info_t *si, uint devid, osl_t *osh, void *regs, - uint bustype, void *sdh, char **vars, uint *varsz); -static void sb_scan(sb_info_t *si); -static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val); -static uint _sb_coreidx(sb_info_t *si); -static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit); +static sb_info_t *sb_doattach(sb_info_t * si, uint devid, osl_t * osh, + void *regs, uint bustype, void *sdh, + char **vars, uint * varsz); +static void sb_scan(sb_info_t * si); +static uint _sb_coreidx(sb_info_t * si); static uint sb_pcidev2chip(uint pcidev); static uint sb_chip2numcores(uint chip); -static bool sb_ispcie(sb_info_t *si); -static bool sb_find_pci_capability(sb_info_t *si, uint8 req_cap_id, uchar *buf, uint32 *buflen); -static int sb_pci_fixcfg(sb_info_t *si); - +static bool sb_ispcie(sb_info_t * si); +static uint8 sb_find_pci_capability(sb_info_t * si, uint8 req_cap_id, + uchar * buf, uint32 * buflen); +static int sb_pci_fixcfg(sb_info_t * si); /* routines to access mdio slave device registers */ -static int sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint readdr, uint val); -static void sb_war30841(sb_info_t *si); +static int sb_pcie_mdiowrite(sb_info_t * si, uint physmedia, uint readdr, + uint val); +static int sb_pcie_mdioread(sb_info_t * si, uint physmedia, uint readdr, + uint * ret_val); + +/* dev path concatenation util */ +static char *sb_devpathvar(sb_t * sbh, char *var, int len, const char *name); + +/* WARs */ +static void sb_war43448(sb_t * sbh); +static void sb_war43448_aspm(sb_t * sbh); +static void sb_war32414_forceHT(sb_t * sbh, bool forceHT); +static void sb_war30841(sb_info_t * si); +static void sb_war42767(sb_t * sbh); +static void sb_war42767_clkreq(sb_t * sbh); /* delay needed between the mdio control/ mdiodata register data access */ #define PR28829_DELAY() OSL_DELAY(10) @@ -93,19 +129,24 @@ static void sb_war30841(sb_info_t *si); /* global variable to indicate reservation/release of gpio's */ static uint32 sb_gpioreservation = 0; -#define SB_INFO(sbh) (sb_info_t*)sbh +/* global flag to prevent shared resources from being initialized multiple times in sb_attach() */ +static bool sb_onetimeinit = FALSE; + +#define SB_INFO(sbh) (sb_info_t*)(uintptr)sbh #define SET_SBREG(si, r, mask, val) \ W_SBREG((si), (r), ((R_SBREG((si), (r)) & ~(mask)) | (val))) -#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && \ +#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && \ ISALIGNED((x), SB_CORE_SIZE)) #define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE)) #define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF) +#define BADCOREADDR 0 #define GOODIDX(idx) (((uint)idx) < SB_MAXCORES) #define BADIDX (SB_MAXCORES+1) -#define NOREV -1 /* Invalid rev */ +#define NOREV -1 /* Invalid rev */ #define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI)) #define PCIE(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCIE)) +#define PCMCIA(si) ((BUSTYPE(si->sb.bustype) == PCMCIA_BUS) && (si->memseg == TRUE)) /* sonicsrev */ #define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT) @@ -128,54 +169,51 @@ static uint32 sb_gpioreservation = 0; (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } /* dynamic clock control defines */ -#define LPOMINFREQ 25000 /* low power oscillator min */ -#define LPOMAXFREQ 43000 /* low power oscillator max */ +#define LPOMINFREQ 25000 /* low power oscillator min */ +#define LPOMAXFREQ 43000 /* low power oscillator max */ #define XTALMINFREQ 19800000 /* 20 MHz - 1% */ #define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ #define PCIMINFREQ 25000000 /* 25 MHz */ #define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ -#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ -#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ - -/* different register spaces to access thr'u pcie indirect access */ -#define PCIE_CONFIGREGS 1 /* Access to config space */ -#define PCIE_PCIEREGS 2 /* Access to pcie registers */ +#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ +#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ /* force HT war check */ -#define FORCEHT_WAR32414(si) \ - ((PCIE(si)) && (((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev == 1)) || \ - ((si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev <= 3)))) +#define FORCEHT_WAR32414(si) \ + (((PCIE(si)) && (si->sb.chip == BCM4311_CHIP_ID) && ((si->sb.chiprev <= 1))) || \ + ((PCI(si) || PCIE(si)) && (si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev <= 3))) + +#define PCIE_ASPMWARS(si) \ + ((PCIE(si)) && ((si->sb.buscorerev >= 3) && (si->sb.buscorerev <= 5))) /* GPIO Based LED powersave defines */ -#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ -#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ +#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ +#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ #define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) -static uint32 -sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr) +static uint32 sb_read_sbreg(sb_info_t * si, volatile uint32 * sbr) { uint8 tmp; uint32 val, intr_val = 0; - /* * compact flash only has 11 bits address, while we needs 12 bits address. * MEM_SEG will be OR'd with other 11 bits address in hardware, * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special */ - if (si->memseg) { + if (PCMCIA(si)) { INTR_OFF(si, intr_val); tmp = 1; OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); - sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ + sbr = (volatile uint32 *)((uintptr) sbr & ~(1 << 11)); /* mask out bit 11 */ } val = R_REG(si->osh, sbr); - if (si->memseg) { + if (PCMCIA(si)) { tmp = 0; OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); INTR_RESTORE(si, intr_val); @@ -184,43 +222,43 @@ sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr) return (val); } -static void -sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v) +static void sb_write_sbreg(sb_info_t * si, volatile uint32 * sbr, uint32 v) { uint8 tmp; volatile uint32 dummy; uint32 intr_val = 0; - /* * compact flash only has 11 bits address, while we needs 12 bits address. * MEM_SEG will be OR'd with other 11 bits address in hardware, * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special */ - if (si->memseg) { + if (PCMCIA(si)) { INTR_OFF(si, intr_val); tmp = 1; OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); - sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ + sbr = (volatile uint32 *)((uintptr) sbr & ~(1 << 11)); /* mask out bit 11 */ } if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { #ifdef IL_BIGENDIAN dummy = R_REG(si->osh, sbr); - W_REG(si->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); + W_REG(si->osh, ((volatile uint16 *)sbr + 1), + (uint16) ((v >> 16) & 0xffff)); dummy = R_REG(si->osh, sbr); - W_REG(si->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); + W_REG(si->osh, (volatile uint16 *)sbr, (uint16) (v & 0xffff)); #else dummy = R_REG(si->osh, sbr); - W_REG(si->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); + W_REG(si->osh, (volatile uint16 *)sbr, (uint16) (v & 0xffff)); dummy = R_REG(si->osh, sbr); - W_REG(si->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); -#endif /* IL_BIGENDIAN */ + W_REG(si->osh, ((volatile uint16 *)sbr + 1), + (uint16) ((v >> 16) & 0xffff)); +#endif /* IL_BIGENDIAN */ } else W_REG(si->osh, sbr, v); - if (si->memseg) { + if (PCMCIA(si)) { tmp = 0; OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); INTR_RESTORE(si, intr_val); @@ -236,24 +274,27 @@ sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v) * vars - pointer to a pointer area for "environment" variables * varsz - pointer to int to return the size of the vars */ -sb_t * -BCMINITFN(sb_attach)(uint devid, osl_t *osh, void *regs, - uint bustype, void *sdh, char **vars, uint *varsz) -{ +sb_t *sb_attach(uint devid, osl_t * osh, void *regs, + uint bustype, void *sdh, char **vars, + uint * varsz) { sb_info_t *si; /* alloc sb_info_t */ - if ((si = MALLOC(osh, sizeof (sb_info_t))) == NULL) { - SB_ERROR(("sb_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); + if ((si = MALLOC(osh, sizeof(sb_info_t))) == NULL) { + SB_ERROR(("sb_attach: malloc failed! malloced %d bytes\n", + MALLOCED(osh))); return (NULL); } - if (sb_doattach(si, devid, osh, regs, bustype, sdh, vars, (uint*)varsz) == NULL) { + if (sb_doattach(si, devid, osh, regs, bustype, sdh, vars, varsz) == + NULL) { MFREE(osh, si, sizeof(sb_info_t)); return (NULL); } + si->vars = vars ? *vars : NULL; + si->varsz = varsz ? *varsz : 0; - return (sb_t *)si; + return (sb_t *) si; } /* Using sb_kattach depends on SB_BUS support, either implicit */ @@ -262,74 +303,55 @@ BCMINITFN(sb_attach)(uint devid, osl_t *osh, void *regs, /* global kernel resource */ static sb_info_t ksi; -static bool ksi_attached = FALSE; /* generic kernel variant of sb_attach() */ -sb_t * -BCMINITFN(sb_kattach)(void) -{ - osl_t *osh = NULL; +sb_t *BCMINITFN(sb_kattach) (osl_t * osh) { + static bool ksi_attached = FALSE; uint32 *regs; if (!ksi_attached) { uint32 cid; - regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE); - cid = R_REG(osh, (uint32 *)regs); + regs = (uint32 *) REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE); + cid = R_REG(osh, (uint32 *) regs); if (((cid & CID_ID_MASK) == BCM4712_CHIP_ID) && ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) && ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) { uint32 *scc, val; - scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl)); + scc = + (uint32 *) ((uchar *) regs + + OFFSETOF(chipcregs_t, slow_clk_ctl)); val = R_REG(osh, scc); SB_ERROR((" initial scc = 0x%x\n", val)); val |= SCC_SS_XTAL; W_REG(osh, scc, val); } - if (sb_doattach(&ksi, BCM4710_DEVICE_ID, osh, (void*)regs, - SB_BUS, NULL, NULL, NULL) == NULL) { + if (sb_doattach(&ksi, BCM4710_DEVICE_ID, osh, (void *)regs, SB_BUS, NULL, + osh != SB_OSH ? &ksi.vars : NULL, + osh != SB_OSH ? &ksi.varsz : NULL) == NULL) return NULL; - } - else - ksi_attached = TRUE; + ksi_attached = TRUE; } - return (sb_t *)&ksi; + return &ksi.sb; } -#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */ +#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */ -void -BCMINITFN(sb_war32414_forceHT)(sb_t *sbh, bool forceHT) -{ - sb_info_t *si; - - si = SB_INFO(sbh); - - - if (FORCEHT_WAR32414(si)) { - uint32 val = 0; - if (forceHT) - val = SYCC_HR; - sb_corereg((void*)si, SB_CC_IDX, OFFSETOF(chipcregs_t, system_clk_ctl), - SYCC_HR, val); - } -} - -static sb_info_t * -BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, - uint bustype, void *sdh, char **vars, uint *varsz) -{ +static sb_info_t *BCMINITFN(sb_doattach) (sb_info_t * si, uint devid, + osl_t * osh, void *regs, + uint bustype, void *sdh, + char **vars, uint * varsz) { uint origidx; chipcregs_t *cc; sbconfig_t *sb; uint32 w; + char *pvars; ASSERT(GOODREGS(regs)); - bzero((uchar*)si, sizeof(sb_info_t)); - + bzero((uchar *) si, sizeof(sb_info_t)); si->sb.buscoreidx = si->gpioidx = BADIDX; si->curmap = regs; @@ -338,17 +360,16 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, /* check to see if we are a sb core mimic'ing a pci core */ if (bustype == PCI_BUS) { - if (OSL_PCI_READ_CONFIG(si->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff) { - SB_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SB " - "devid:0x%x\n", __FUNCTION__, devid)); + if (OSL_PCI_READ_CONFIG + (si->osh, PCI_SPROM_CONTROL, + sizeof(uint32)) == 0xffffffff) { + SB_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SB " "devid:0x%x\n", __FUNCTION__, devid)); bustype = SB_BUS; } } - si->sb.bustype = bustype; if (si->sb.bustype != BUSTYPE(si->sb.bustype)) { - SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n", - si->sb.bustype, BUSTYPE(si->sb.bustype))); + SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n", si->sb.bustype, BUSTYPE(si->sb.bustype))); return NULL; } @@ -357,13 +378,14 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, si->memseg = TRUE; /* kludge to enable the clock on the 4306 which lacks a slowclock */ - if (BUSTYPE(si->sb.bustype) == PCI_BUS) - sb_clkctl_xtal(&si->sb, XTAL|PLL, ON); + if (BUSTYPE(si->sb.bustype) == PCI_BUS && !sb_ispcie(si)) + sb_clkctl_xtal(&si->sb, XTAL | PLL, ON); if (BUSTYPE(si->sb.bustype) == PCI_BUS) { w = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32)); if (!GOODCOREADDR(w)) - OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32), SB_ENUM_BASE); + OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, + sizeof(uint32), SB_ENUM_BASE); } /* initialize current core index value */ @@ -375,9 +397,9 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, } /* get sonics backplane revision */ - sb = REGS2SB(si->curmap); - si->sb.sonicsrev = (R_SBREG(si, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT; - + sb = REGS2SB(regs); + si->sb.sonicsrev = + (R_SBREG(si, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT; /* keep and reuse the initial register mapping */ origidx = si->curidx; if (BUSTYPE(si->sb.bustype) == SB_BUS) @@ -385,7 +407,7 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, /* is core-0 a chipcommon core? */ si->numcores = 1; - cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0); + cc = (chipcregs_t *) sb_setcoreidx(&si->sb, 0); if (sb_coreid(&si->sb) != SB_CC) cc = NULL; @@ -393,8 +415,12 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, if (cc) { /* chip common core found! */ si->sb.chip = R_REG(si->osh, &cc->chipid) & CID_ID_MASK; - si->sb.chiprev = (R_REG(si->osh, &cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT; - si->sb.chippkg = (R_REG(si->osh, &cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT; + si->sb.chiprev = + (R_REG(si->osh, &cc->chipid) & CID_REV_MASK) >> + CID_REV_SHIFT; + si->sb.chippkg = + (R_REG(si->osh, &cc->chipid) & CID_PKG_MASK) >> + CID_PKG_SHIFT; } else { /* no chip common core -- must convert device id to chip id */ if ((si->sb.chip = sb_pcidev2chip(devid)) == 0) { @@ -407,9 +433,13 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, /* get chipcommon rev */ si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV; + /* get chipcommon capabilites */ + si->sb.cccaps = cc ? R_REG(si->osh, &cc->capabilities) : 0; + /* determine numcores */ if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6))) - si->numcores = (R_REG(si->osh, &cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT; + si->numcores = + (R_REG(si->osh, &cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT; else si->numcores = sb_chip2numcores(si->sb.chip); @@ -423,19 +453,27 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, sb_scan(si); /* fixup necessary chip/core configurations */ - if (BUSTYPE(si->sb.bustype) == PCI_BUS) { - if (sb_pci_fixcfg(si)) { - SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n")); - return NULL; - } + if (BUSTYPE(si->sb.bustype) == PCI_BUS && sb_pci_fixcfg(si)) { + SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n")); + return NULL; } - /* srom_var_init() depends on sb_scan() info */ - if (srom_var_init(si, si->sb.bustype, si->curmap, si->osh, vars, varsz)) { + /* Init nvram from sprom/otp if they exist */ + if (srom_var_init + (&si->sb, BUSTYPE(si->sb.bustype), regs, si->osh, vars, varsz)) { SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n")); return (NULL); } - + pvars = vars ? *vars : NULL; + + /* PMU specific initializations */ + if ((si->sb.cccaps & CC_CAP_PMU) && !sb_onetimeinit) { + sb_pmu_init(&si->sb, si->osh); + /* Find out Crystal frequency and init PLL */ + sb_pmu_pll_init(&si->sb, si->osh, getintvar(pvars, "xtalfreq")); + /* Initialize PMU resources (up/dn timers, dep masks, etc.) */ + sb_pmu_res_init(&si->sb, si->osh); + } if (cc == NULL) { /* * The chip revision number is hardwired into all @@ -448,17 +486,17 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, ASSERT(vars); si->sb.chiprev = getintvar(*vars, "chiprev"); } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) { - w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_REV, sizeof(uint32)); + w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_REV, + sizeof(uint32)); si->sb.chiprev = w & 0xff; } else si->sb.chiprev = 0; } if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { - w = getintvar(*vars, "regwindowsz"); + w = getintvar(pvars, "regwindowsz"); si->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE; } - /* gpio control core is required */ if (!GOODIDX(si->gpioidx)) { SB_ERROR(("sb_doattach: gpio control core not found\n")); @@ -470,21 +508,32 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, case PCI_BUS: /* do a pci config read to get subsystem id and subvendor id */ w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_SVID, sizeof(uint32)); - si->sb.boardvendor = w & 0xffff; - si->sb.boardtype = (w >> 16) & 0xffff; + /* Let nvram variables override subsystem Vend/ID */ + if ((si->sb.boardvendor = + (uint16) sb_getdevpathintvar(&si->sb, "boardvendor")) == 0) + si->sb.boardvendor = w & 0xffff; + else + SB_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", si->sb.boardvendor, w & 0xffff)); + if ((si->sb.boardtype = + (uint16) sb_getdevpathintvar(&si->sb, "boardtype")) == 0) + si->sb.boardtype = (w >> 16) & 0xffff; + else + SB_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", si->sb.boardtype, (w >> 16) & 0xffff)); break; case PCMCIA_BUS: - case SDIO_BUS: - si->sb.boardvendor = getintvar(*vars, "manfid"); - si->sb.boardtype = getintvar(*vars, "prodid"); + si->sb.boardvendor = getintvar(pvars, "manfid"); + si->sb.boardtype = getintvar(pvars, "prodid"); break; case SB_BUS: case JTAG_BUS: si->sb.boardvendor = VENDOR_BROADCOM; - if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0) - si->sb.boardtype = 0xffff; + if (pvars == NULL + || ((si->sb.boardtype = getintvar(pvars, "prodid")) == 0)) + if ((si->sb.boardtype = + getintvar(NULL, "boardtype")) == 0) + si->sb.boardtype = 0xffff; break; } @@ -493,25 +542,147 @@ BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, ASSERT(si->sb.boardtype); } + si->sb.boardflags = getintvar(pvars, "boardflags"); + /* setup the GPIO based LED powersave register */ if (si->sb.ccrev >= 16) { - if ((vars == NULL) || ((w = getintvar(*vars, "leddc")) == 0)) + if ((pvars == NULL) || ((w = getintvar(pvars, "leddc")) == 0)) w = DEFAULT_GPIOTIMERVAL; - sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); + sb_corereg(&si->sb, SB_CC_IDX, + OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); + } + + /* Determine if this board needs override */ + if (PCIE(si) && (si->sb.chip == BCM4321_CHIP_ID)) + si->pcie_war_ovr = ((si->sb.boardvendor == VENDOR_APPLE) && + ((uint8) getintvar(pvars, "sromrev") == 4) + && ((uint8) getintvar(pvars, "boardrev") <= + 0x71)) + || ((uint32) getintvar(pvars, "boardflags2") & + BFL2_PCIEWAR_OVR); + + if (PCIE_ASPMWARS(si)) { + sb_war43448_aspm((void *)si); + sb_war42767_clkreq((void *)si); } + if (FORCEHT_WAR32414(si)) { - /* set proper clk setup delays before forcing HT */ - sb_clkctl_init((void *)si); - sb_war32414_forceHT((void *)si, 1); + si->sb.pr32414 = TRUE; + sb_clkctl_init(&si->sb); + sb_war32414_forceHT(&si->sb, 1); + } + + if (PCIE(si) && ((si->sb.buscorerev == 6) || (si->sb.buscorerev == 7))) + si->sb.pr42780 = TRUE; + + if (PCIE_ASPMWARS(si)) + sb_pcieclkreq(&si->sb, 1, 0); + + if (PCIE(si) && + (((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev == 2)) || + ((si->sb.chip == BCM4312_CHIP_ID) && (si->sb.chiprev == 0)))) + sb_set_initiator_to(&si->sb, 0x3, + sb_findcoreidx(&si->sb, SB_D11, 0)); + + /* Disable gpiopullup and gpiopulldown */ + if (!sb_onetimeinit && si->sb.ccrev >= 20) { + cc = (chipcregs_t *) sb_setcore(&si->sb, SB_CC, 0); + W_REG(osh, &cc->gpiopullup, 0); + W_REG(osh, &cc->gpiopulldown, 0); + sb_setcoreidx(&si->sb, origidx); } +#ifdef BCMDBG + /* clear any previous epidiag-induced target abort */ + sb_taclear(&si->sb); +#endif /* BCMDBG */ +#ifdef HNDRTE + sb_onetimeinit = TRUE; +#endif return (si); } +/* Enable/Disable clkreq for PCIE (4311B0/4321B1) */ +void sb_war42780_clkreq(sb_t * sbh, bool clkreq) { + sb_info_t *si; -uint -sb_coreid(sb_t *sbh) + si = SB_INFO(sbh); + + /* Don't change clkreq value if serdespll war has not yet been applied */ + if (!si->pr42767_war && PCIE_ASPMWARS(si)) + return; + + sb_pcieclkreq(sbh, 1, (int32) clkreq); +} + +static void BCMINITFN(sb_war43448) (sb_t * sbh) { + sb_info_t *si; + + si = SB_INFO(sbh); + + /* if not pcie bus, we're done */ + if (!PCIE(si) || !PCIE_ASPMWARS(si)) + return; + + /* Restore the polarity */ + if (si->pcie_polarity != 0) + sb_pcie_mdiowrite((void *)(uintptr) & si->sb, MDIODATA_DEV_RX, + SERDES_RX_CTRL, si->pcie_polarity); +} + +static void BCMINITFN(sb_war43448_aspm) (sb_t * sbh) { + uint32 w; + uint16 val16, *reg16; + sbpcieregs_t *pcieregs; + sb_info_t *si; + + si = SB_INFO(sbh); + + /* if not pcie bus, we're done */ + if (!PCIE(si) || !PCIE_ASPMWARS(si)) + return; + + /* no ASPM stuff on QT or VSIM */ + if (si->sb.chippkg == HDLSIM_PKG_ID || si->sb.chippkg == HWSIM_PKG_ID) + return; + + pcieregs = (sbpcieregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx); + + /* Enable ASPM in the shadow SROM and Link control */ + reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET]; + val16 = R_REG(si->osh, reg16); + if (!si->pcie_war_ovr) + val16 |= SRSH_ASPM_ENB; + else + val16 &= ~SRSH_ASPM_ENB; + W_REG(si->osh, reg16, val16); + + w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset, + sizeof(uint32)); + if (!si->pcie_war_ovr) + w |= PCIE_ASPM_ENAB; + else + w &= ~PCIE_ASPM_ENAB; + OSL_PCI_WRITE_CONFIG(si->osh, si->pciecap_lcreg_offset, sizeof(uint32), + w); +} + +static void BCMINITFN(sb_war32414_forceHT) (sb_t * sbh, bool forceHT) { + sb_info_t *si; + uint32 val = 0; + + si = SB_INFO(sbh); + + ASSERT(FORCEHT_WAR32414(si)); + + if (forceHT) + val = SYCC_HR; + sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, system_clk_ctl), + SYCC_HR, val); +} + +uint sb_coreid(sb_t * sbh) { sb_info_t *si; sbconfig_t *sb; @@ -522,8 +693,18 @@ sb_coreid(sb_t *sbh) return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT); } -uint -sb_coreidx(sb_t *sbh) +uint sb_flag(sb_t * sbh) +{ + sb_info_t *si; + sbconfig_t *sb; + + si = SB_INFO(sbh); + sb = REGS2SB(si->curmap); + + return R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK; +} + +uint sb_coreidx(sb_t * sbh) { sb_info_t *si; @@ -531,10 +712,9 @@ sb_coreidx(sb_t *sbh) return (si->curidx); } -/* return current index of core */ -static uint -_sb_coreidx(sb_info_t *si) +static uint _sb_coreidx(sb_info_t * si) { + sbconfig_t *sb; uint32 sbaddr = 0; @@ -547,26 +727,27 @@ _sb_coreidx(sb_info_t *si) break; case PCI_BUS: - sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32)); + sbaddr = + OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32)); break; - case PCMCIA_BUS: { - uint8 tmp = 0; + case PCMCIA_BUS:{ + uint8 tmp = 0; - OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1); - sbaddr = (uint)tmp << 12; - OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1); - sbaddr |= (uint)tmp << 16; - OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1); - sbaddr |= (uint)tmp << 24; - break; - } + OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1); + sbaddr = (uint) tmp << 12; + OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1); + sbaddr |= (uint) tmp << 16; + OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1); + sbaddr |= (uint) tmp << 24; + break; + } #ifdef BCMJTAG case JTAG_BUS: - sbaddr = (uint32)si->curmap; + sbaddr = (uint32) si->curmap; break; -#endif /* BCMJTAG */ +#endif /* BCMJTAG */ default: ASSERT(0); @@ -578,8 +759,7 @@ _sb_coreidx(sb_info_t *si) return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE); } -uint -sb_corevendor(sb_t *sbh) +uint sb_corevendor(sb_t * sbh) { sb_info_t *si; sbconfig_t *sb; @@ -590,8 +770,7 @@ sb_corevendor(sb_t *sbh) return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT); } -uint -sb_corerev(sb_t *sbh) +uint sb_corerev(sb_t * sbh) { sb_info_t *si; sbconfig_t *sb; @@ -604,8 +783,7 @@ sb_corerev(sb_t *sbh) return (SBCOREREV(sbidh)); } -void * -sb_osh(sb_t *sbh) +void *sb_osh(sb_t * sbh) { sb_info_t *si; @@ -613,8 +791,7 @@ sb_osh(sb_t *sbh) return si->osh; } -void -sb_setosh(sb_t *sbh, osl_t *osh) +void sb_setosh(sb_t * sbh, osl_t * osh) { sb_info_t *si; @@ -626,9 +803,25 @@ sb_setosh(sb_t *sbh, osl_t *osh) si->osh = osh; } +/* set sbtmstatelow core-specific flags */ +void sb_coreflags_wo(sb_t * sbh, uint32 mask, uint32 val) +{ + sb_info_t *si; + sbconfig_t *sb; + uint32 w; + + si = SB_INFO(sbh); + sb = REGS2SB(si->curmap); + + ASSERT((val & ~mask) == 0); + + /* mask and set */ + w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val; + W_SBREG(si, &sb->sbtmstatelow, w); +} + /* set/clear sbtmstatelow core-specific flags */ -uint32 -sb_coreflags(sb_t *sbh, uint32 mask, uint32 val) +uint32 sb_coreflags(sb_t * sbh, uint32 mask, uint32 val) { sb_info_t *si; sbconfig_t *sb; @@ -645,13 +838,14 @@ sb_coreflags(sb_t *sbh, uint32 mask, uint32 val) W_SBREG(si, &sb->sbtmstatelow, w); } - /* return the new value */ + /* return the new value + * for write operation, the following readback ensures the completion of write opration. + */ return (R_SBREG(si, &sb->sbtmstatelow)); } /* set/clear sbtmstatehigh core-specific flags */ -uint32 -sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val) +uint32 sb_coreflagshi(sb_t * sbh, uint32 mask, uint32 val) { sb_info_t *si; sbconfig_t *sb; @@ -670,12 +864,11 @@ sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val) } /* return the new value */ - return (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_FL_MASK); + return (R_SBREG(si, &sb->sbtmstatehigh)); } /* Run bist on current core. Caller needs to take care of core-specific bist hazards */ -int -sb_corebist(sb_t *sbh) +int sb_corebist(sb_t * sbh) { uint32 sblo; sb_info_t *si; @@ -688,18 +881,18 @@ sb_corebist(sb_t *sbh) sblo = R_SBREG(si, &sb->sbtmstatelow); W_SBREG(si, &sb->sbtmstatelow, (sblo | SBTML_FGC | SBTML_BE)); - SPINWAIT(((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTD) == 0), 100000); + SPINWAIT(((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTD) == 0), + 100000); if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTF) - result = BCME_ERROR; + result = -1; W_SBREG(si, &sb->sbtmstatelow, sblo); return result; } -bool -sb_iscoreup(sb_t *sbh) +bool sb_iscoreup(sb_t * sbh) { sb_info_t *si; sbconfig_t *sb; @@ -708,7 +901,7 @@ sb_iscoreup(sb_t *sbh) sb = REGS2SB(si->curmap); return ((R_SBREG(si, &sb->sbtmstatelow) & - (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK); + (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK); } /* @@ -720,51 +913,62 @@ sb_iscoreup(sb_t *sbh) * Also, when using pci/pcie, we can optimize away the core switching for pci registers * and (on newer pci cores) chipcommon registers. */ -static uint -sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val) +uint sb_corereg(sb_t * sbh, uint coreidx, uint regoff, uint mask, uint val) { uint origidx = 0; uint32 *r = NULL; uint w; uint intr_val = 0; bool fast = FALSE; + sb_info_t *si; + + si = SB_INFO(sbh); ASSERT(GOODIDX(coreidx)); ASSERT(regoff < SB_CORE_SIZE); ASSERT((val & ~mask) == 0); -#ifdef notyet - if (si->sb.bustype == SB_BUS) { +#if 0 + if (BUSTYPE(si->sb.bustype) == SB_BUS) { /* If internal bus, we can always get at everything */ fast = TRUE; - r = (uint32 *)((uchar *)si->regs[coreidx] + regoff); - } else if (si->sb.bustype == PCI_BUS) { + /* map if does not exist */ + if (!si->regs[coreidx]) { + si->regs[coreidx] = + (void *)REG_MAP(si->coresba[coreidx], SB_CORE_SIZE); + ASSERT(GOODREGS(si->regs[coreidx])); + } + r = (uint32 *) ((uchar *) si->regs[coreidx] + regoff); + } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) { /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ if ((si->coreid[coreidx] == SB_CC) && - ((si->sb.buscoretype == SB_PCIE) || - (si->sb.buscorerev >= 13))) { + ((si->sb.buscoretype == SB_PCIE) + || (si->sb.buscorerev >= 13))) { /* Chipc registers are mapped at 12KB */ fast = TRUE; - r = (uint32 *)((char *)si->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); + r = (uint32 *) ((char *)si->curmap + + PCI_16KB0_CCREGS_OFFSET + regoff); } else if (si->sb.buscoreidx == coreidx) { /* pci registers are at either in the last 2KB of an 8KB window * or, in pcie and pci rev 13 at 8KB */ fast = TRUE; - if ((si->sb.buscoretype == SB_PCIE) || - (si->sb.buscorerev >= 13)) - r = (uint32 *)((char *)si->curmap + - PCI_16KB0_PCIREGS_OFFSET + regoff); + if ((si->sb.buscoretype == SB_PCIE) + || (si->sb.buscorerev >= 13)) + r = (uint32 *) ((char *)si->curmap + + PCI_16KB0_PCIREGS_OFFSET + + regoff); else - r = (uint32 *)((char *)si->curmap + - ((regoff >= SBCONFIGOFF) ? - PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + - regoff); + r = (uint32 *) ((char *)si->curmap + + ((regoff >= SBCONFIGOFF) ? + PCI_BAR0_PCISBR_OFFSET : + PCI_BAR0_PCIREGS_OFFSET) + + regoff); } } -#endif /* notyet */ +#endif if (!fast) { INTR_OFF(si, intr_val); @@ -773,7 +977,8 @@ sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val) origidx = sb_coreidx(&si->sb); /* switch core */ - r = (uint32*) ((uchar*) sb_setcoreidx(&si->sb, coreidx) + regoff); + r = (uint32 *) ((uchar *) sb_setcoreidx(&si->sb, coreidx) + + regoff); } ASSERT(r); @@ -791,8 +996,14 @@ sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val) /* readback */ if (regoff >= SBCONFIGOFF) w = R_SBREG(si, r); - else - w = R_REG(si->osh, r); + else { + if ((si->sb.chip == BCM5354_CHIP_ID) && + (coreidx == SB_CC_IDX) && + (regoff == OFFSETOF(chipcregs_t, watchdog))) { + w = val; + } else + w = R_REG(si->osh, r); + } if (!fast) { /* restore core index */ @@ -821,78 +1032,290 @@ sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val) #define read_pci_cfg_word(a) \ (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff) - -/* return TRUE if requested capability exists in the PCI config space */ -static bool -sb_find_pci_capability(sb_info_t *si, uint8 req_cap_id, uchar *buf, uint32 *buflen) +/* return cap_offset if requested capability exists in the PCI config space */ +static uint8 +sb_find_pci_capability(sb_info_t * si, uint8 req_cap_id, uchar * buf, + uint32 * buflen) { uint8 cap_id; - uint8 cap_ptr; - uint32 bufsize; + uint8 cap_ptr = 0; + uint32 bufsize; uint8 byte_val; if (BUSTYPE(si->sb.bustype) != PCI_BUS) - return FALSE; + goto end; /* check for Header type 0 */ byte_val = read_pci_cfg_byte(PCI_CFG_HDR); if ((byte_val & 0x7f) != PCI_HEADER_NORMAL) - return FALSE; + goto end; /* check if the capability pointer field exists */ byte_val = read_pci_cfg_byte(PCI_CFG_STAT); if (!(byte_val & PCI_CAPPTR_PRESENT)) - return FALSE; + goto end; cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR); /* check if the capability pointer is 0x00 */ if (cap_ptr == 0x00) - return FALSE; - + goto end; /* loop thr'u the capability list and see if the pcie capabilty exists */ cap_id = read_pci_cfg_byte(cap_ptr); while (cap_id != req_cap_id) { - cap_ptr = read_pci_cfg_byte((cap_ptr+1)); - if (cap_ptr == 0x00) break; + cap_ptr = read_pci_cfg_byte((cap_ptr + 1)); + if (cap_ptr == 0x00) + break; cap_id = read_pci_cfg_byte(cap_ptr); } if (cap_id != req_cap_id) { - return FALSE; + goto end; } /* found the caller requested capability */ if ((buf != NULL) && (buflen != NULL)) { + uint8 cap_data; + bufsize = *buflen; - if (!bufsize) goto end; + if (!bufsize) + goto end; *buflen = 0; /* copy the cpability data excluding cap ID and next ptr */ - cap_ptr += 2; - if ((bufsize + cap_ptr) > SZPCR) - bufsize = SZPCR - cap_ptr; + cap_data = cap_ptr + 2; + if ((bufsize + cap_data) > SZPCR) + bufsize = SZPCR - cap_data; *buflen = bufsize; while (bufsize--) { - *buf = read_pci_cfg_byte(cap_ptr); - cap_ptr++; + *buf = read_pci_cfg_byte(cap_data); + cap_data++; buf++; } } -end: + end: + return cap_ptr; +} + +uint8 sb_pcieclkreq(sb_t * sbh, uint32 mask, uint32 val) +{ + sb_info_t *si; + uint32 reg_val; + uint8 offset; + + si = SB_INFO(sbh); + + offset = si->pciecap_lcreg_offset; + if (!offset) + return 0; + + reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32)); + /* set operation */ + if (mask) { + if (val) + reg_val |= PCIE_CLKREQ_ENAB; + else + reg_val &= ~PCIE_CLKREQ_ENAB; + OSL_PCI_WRITE_CONFIG(si->osh, offset, sizeof(uint32), reg_val); + reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32)); + } + if (reg_val & PCIE_CLKREQ_ENAB) + return 1; + else + return 0; +} + +#ifdef BCMDBG + +uint32 sb_pcielcreg(sb_t * sbh, uint32 mask, uint32 val) +{ + sb_info_t *si; + uint32 reg_val; + uint8 offset; + + si = SB_INFO(sbh); + + if (!PCIE(si)) + return 0; + + offset = si->pciecap_lcreg_offset; + if (!offset) + return 0; + + /* set operation */ + if (mask) + OSL_PCI_WRITE_CONFIG(si->osh, offset, sizeof(uint32), val); + + reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32)); + + return reg_val; +} + +uint8 sb_pcieL1plldown(sb_t * sbh) +{ + sb_info_t *si; + uint intr_val = 0; + uint origidx; + uint32 reg_val; + + si = SB_INFO(sbh); + + if (!PCIE(si)) + return 0; + if (!((si->sb.buscorerev == 3) || (si->sb.buscorerev == 4))) + return 0; + + if (!sb_pcieclkreq((void *)(uintptr) sbh, 0, 0)) { + SB_ERROR(("PCIEL1PLLDOWN requires Clkreq be enabled, so enable it\n")); + sb_pcieclkreq((void *)(uintptr) sbh, 1, 1); + } + reg_val = sb_pcielcreg((void *)(uintptr) sbh, 0, 0); + if (reg_val & PCIE_CAP_LCREG_ASPML0s) { + SB_ERROR(("PCIEL1PLLDOWN requires L0s to be disabled\n")); + reg_val &= ~PCIE_CAP_LCREG_ASPML0s; + sb_pcielcreg((void *)(uintptr) sbh, 1, reg_val); + } else + SB_ERROR(("PCIEL1PLLDOWN: L0s is already disabled\n")); + + /* turnoff intrs, change core, set original back, turn on intrs back on */ + origidx = si->curidx; + INTR_OFF(si, intr_val); + sb_setcore(sbh, SB_PCIE, 0); + + sb_pcie_writereg((void *)(uintptr) sbh, (void *)PCIE_PCIEREGS, + PCIE_DLLP_PCIE11, 0); + + sb_setcoreidx(sbh, origidx); + INTR_RESTORE(si, intr_val); + return 1; +} +#endif /* BCMDBG */ + +/* return TRUE if PCIE capability exists in the pci config space */ +static bool sb_ispcie(sb_info_t * si) +{ + uint8 cap_ptr; + + cap_ptr = sb_find_pci_capability(si, PCI_CAP_PCIECAP_ID, NULL, NULL); + if (!cap_ptr) + return FALSE; + + si->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; + return TRUE; } -/* return TRUE if PCIE capability exists the pci config space */ -static inline bool -sb_ispcie(sb_info_t *si) +/* Wake-on-wireless-LAN (WOWL) support functions */ +/* return TRUE if PM capability exists in the pci config space */ +bool sb_pci_pmecap(sb_t * sbh) { - return (sb_find_pci_capability(si, PCI_CAP_PCIECAP_ID, NULL, NULL)); + uint8 cap_ptr; + uint32 pmecap; + sb_info_t *si; + + si = SB_INFO(sbh); + + if (si == NULL || !(PCI(si) || PCIE(si))) + return FALSE; + + if (!si->pmecap_offset) { + cap_ptr = + sb_find_pci_capability(si, PCI_CAP_POWERMGMTCAP_ID, NULL, + NULL); + if (!cap_ptr) + return FALSE; + + si->pmecap_offset = cap_ptr; + + pmecap = + OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset, + sizeof(uint32)); + + /* At least one state can generate PME */ + si->pmecap = (pmecap & PME_CAP_PM_STATES) != 0; + } + + return (si->pmecap); } -/* scan the sb enumerated space to identify all cores */ -static void -BCMINITFN(sb_scan)(sb_info_t *si) +/* Enable PME generation and disable clkreq */ +void sb_pci_pmeen(sb_t * sbh) { + sb_info_t *si; + uint32 w; + si = SB_INFO(sbh); + + /* if not pmecapable return */ + if (!sb_pci_pmecap(sbh)) + return; + + w = OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET, + sizeof(uint32)); + w |= (PME_CSR_PME_EN); + OSL_PCI_WRITE_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET, + sizeof(uint32), w); + + /* Disable clkreq */ + if (si->pr42767_war) { + sb_pcieclkreq(sbh, 1, 0); + si->pr42767_war = FALSE; + } else if (si->sb.pr42780) { + sb_pcieclkreq(sbh, 1, 1); + } +} + +/* Disable PME generation, clear the PME status bit if set and + * return TRUE if PME status set + */ +bool sb_pci_pmeclr(sb_t * sbh) +{ + sb_info_t *si; + uint32 w; + bool ret = FALSE; + + si = SB_INFO(sbh); + + if (!sb_pci_pmecap(sbh)) + return ret; + + w = OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET, + sizeof(uint32)); + + SB_ERROR(("sb_pci_pmeclr PMECSR : 0x%x\n", w)); + ret = (w & PME_CSR_PME_STAT) == PME_CSR_PME_STAT; + + /* PMESTAT is cleared by writing 1 to it */ + w &= ~(PME_CSR_PME_EN); + + OSL_PCI_WRITE_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET, + sizeof(uint32), w); + + return ret; +} + +/* use pci dev id to determine chip id for chips not having a chipcommon core */ +static uint BCMINITFN(sb_pcidev2chip) (uint pcidev) { + if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID)) + return (BCM4710_CHIP_ID); + if ((pcidev >= BCM4402_ENET_ID) && (pcidev <= BCM4402_V90_ID)) + return (BCM4402_CHIP_ID); + if (pcidev == BCM4401_ENET_ID) + return (BCM4402_CHIP_ID); + if (pcidev == SDIOH_FPGA_ID) + return (SDIOH_FPGA_ID); + + return (0); +} + +/* Scan the enumeration space to find all cores starting from the given + * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba' + * is the default core address at chip POR time and 'regs' is the virtual + * address that the default core is mapped at. 'ncores' is the number of + * cores expected on bus 'sbba'. It returns the total number of cores + * starting from bus 'sbba', inclusive. + */ + +static void BCMINITFN(sb_scan) (sb_info_t * si) { + sb_t *sbh; uint origidx; uint i; bool pci; @@ -902,6 +1325,7 @@ BCMINITFN(sb_scan)(sb_info_t *si) uint pcirev; uint pcierev; + sbh = (sb_t *) si; /* numcores should already be set */ ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES)); @@ -959,14 +1383,14 @@ BCMINITFN(sb_scan)(sb_info_t *si) * - else if there's a pci core (rev >= 2) - use that * - else there had better be an extif core (4710 only) */ - if (GOODIDX(sb_findcoreidx(si, SB_CC, 0))) { - si->gpioidx = sb_findcoreidx(si, SB_CC, 0); + if (GOODIDX(sb_findcoreidx(sbh, SB_CC, 0))) { + si->gpioidx = sb_findcoreidx(sbh, SB_CC, 0); si->gpioid = SB_CC; } else if (PCI(si) && (si->sb.buscorerev >= 2)) { si->gpioidx = si->sb.buscoreidx; si->gpioid = SB_PCI; - } else if (sb_findcoreidx(si, SB_EXTIF, 0)) { - si->gpioidx = sb_findcoreidx(si, SB_EXTIF, 0); + } else if (sb_findcoreidx(sbh, SB_EXTIF, 0)) { + si->gpioidx = sb_findcoreidx(sbh, SB_EXTIF, 0); si->gpioid = SB_EXTIF; } else ASSERT(si->gpioidx != BADIDX); @@ -976,8 +1400,7 @@ BCMINITFN(sb_scan)(sb_info_t *si) } /* may be called with core in reset */ -void -sb_detach(sb_t *sbh) +void sb_detach(sb_t * sbh) { sb_info_t *si; uint idx; @@ -995,29 +1418,13 @@ sb_detach(sb_t *sbh) } #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS) if (si != &ksi) -#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */ +#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */ MFREE(si->osh, si, sizeof(sb_info_t)); - } -/* use pci dev id to determine chip id for chips not having a chipcommon core */ -static uint -BCMINITFN(sb_pcidev2chip)(uint pcidev) -{ - if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID)) - return (BCM4710_CHIP_ID); - if ((pcidev >= BCM4402_ENET_ID) && (pcidev <= BCM4402_V90_ID)) - return (BCM4402_CHIP_ID); - if (pcidev == BCM4401_ENET_ID) - return (BCM4402_CHIP_ID); - - return (0); -} /* convert chip number to number of i/o cores */ -static uint -BCMINITFN(sb_chip2numcores)(uint chip) -{ +static uint BCMINITFN(sb_chip2numcores) (uint chip) { if (chip == BCM4710_CHIP_ID) return (9); if (chip == BCM4402_CHIP_ID) @@ -1028,6 +1435,8 @@ BCMINITFN(sb_chip2numcores)(uint chip) return (9); if (chip == BCM5365_CHIP_ID) return (7); + if (chip == SDIOH_FPGA_ID) + return (2); SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip)); ASSERT(0); @@ -1035,12 +1444,14 @@ BCMINITFN(sb_chip2numcores)(uint chip) } /* return index of coreid or BADIDX if not found */ -static uint -sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit) +uint sb_findcoreidx(sb_t * sbh, uint coreid, uint coreunit) { + sb_info_t *si; uint found; uint i; + si = SB_INFO(sbh); + found = 0; for (i = 0; i < si->numcores; i++) @@ -1058,8 +1469,7 @@ sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit) * must be called with interrupt off. * Moreover, callers should keep interrupts off during switching out of and back to d11 core */ -void* -sb_setcoreidx(sb_t *sbh, uint coreidx) +void *sb_setcoreidx(sb_t * sbh, uint coreidx) { sb_info_t *si; uint32 sbaddr; @@ -1074,7 +1484,8 @@ sb_setcoreidx(sb_t *sbh, uint coreidx) * If the user has provided an interrupt mask enabled function, * then assert interrupts are disabled before switching the core. */ - ASSERT((si->intrsenabled_fn == NULL) || !(*(si)->intrsenabled_fn)((si)->intr_arg)); + ASSERT((si->intrsenabled_fn == NULL) + || !(*(si)->intrsenabled_fn) ((si)->intr_arg)); sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE); @@ -1082,7 +1493,8 @@ sb_setcoreidx(sb_t *sbh, uint coreidx) case SB_BUS: /* map new one */ if (!si->regs[coreidx]) { - si->regs[coreidx] = (void*)REG_MAP(sbaddr, SB_CORE_SIZE); + si->regs[coreidx] = + (void *)REG_MAP(sbaddr, SB_CORE_SIZE); ASSERT(GOODREGS(si->regs[coreidx])); } si->curmap = si->regs[coreidx]; @@ -1110,7 +1522,7 @@ sb_setcoreidx(sb_t *sbh, uint coreidx) } si->curmap = si->regs[coreidx]; break; -#endif /* BCMJTAG */ +#endif /* BCMJTAG */ } si->curidx = coreidx; @@ -1123,14 +1535,11 @@ sb_setcoreidx(sb_t *sbh, uint coreidx) * must be called with interrupt off. * Moreover, callers should keep interrupts off during switching out of and back to d11 core */ -void* -sb_setcore(sb_t *sbh, uint coreid, uint coreunit) +void *sb_setcore(sb_t * sbh, uint coreid, uint coreunit) { - sb_info_t *si; uint idx; - si = SB_INFO(sbh); - idx = sb_findcoreidx(si, coreid, coreunit); + idx = sb_findcoreidx(sbh, coreid, coreunit); if (!GOODIDX(idx)) return (NULL); @@ -1138,9 +1547,7 @@ sb_setcore(sb_t *sbh, uint coreid, uint coreunit) } /* return chip number */ -uint -sb_chip(sb_t *sbh) -{ +uint BCMINITFN(sb_chip) (sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); @@ -1148,9 +1555,7 @@ sb_chip(sb_t *sbh) } /* return chip revision number */ -uint -sb_chiprev(sb_t *sbh) -{ +uint BCMINITFN(sb_chiprev) (sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); @@ -1158,9 +1563,7 @@ sb_chiprev(sb_t *sbh) } /* return chip common revision number */ -uint -sb_chipcrev(sb_t *sbh) -{ +uint BCMINITFN(sb_chipcrev) (sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); @@ -1168,9 +1571,7 @@ sb_chipcrev(sb_t *sbh) } /* return chip package option */ -uint -sb_chippkg(sb_t *sbh) -{ +uint BCMINITFN(sb_chippkg) (sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); @@ -1178,18 +1579,14 @@ sb_chippkg(sb_t *sbh) } /* return PCI core rev. */ -uint -sb_pcirev(sb_t *sbh) -{ +uint BCMINITFN(sb_pcirev) (sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); return (si->sb.buscorerev); } -bool -BCMINITFN(sb_war16165)(sb_t *sbh) -{ +bool BCMINITFN(sb_war16165) (sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); @@ -1197,18 +1594,14 @@ BCMINITFN(sb_war16165)(sb_t *sbh) return (PCI(si) && (si->sb.buscorerev <= 10)); } -static void -BCMINITFN(sb_war30841)(sb_info_t *si) -{ +static void BCMINITFN(sb_war30841) (sb_info_t * si) { sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); } /* return PCMCIA core rev. */ -uint -BCMINITFN(sb_pcmciarev)(sb_t *sbh) -{ +uint BCMINITFN(sb_pcmciarev) (sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); @@ -1216,9 +1609,7 @@ BCMINITFN(sb_pcmciarev)(sb_t *sbh) } /* return board vendor id */ -uint -sb_boardvendor(sb_t *sbh) -{ +uint BCMINITFN(sb_boardvendor) (sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); @@ -1226,9 +1617,7 @@ sb_boardvendor(sb_t *sbh) } /* return boardtype */ -uint -sb_boardtype(sb_t *sbh) -{ +uint BCMINITFN(sb_boardtype) (sb_t * sbh) { sb_info_t *si; char *var; @@ -1239,7 +1628,8 @@ sb_boardtype(sb_t *sbh) si->sb.boardtype = getintvar(NULL, "boardtype"); /* backward compatibility for older boardtype string format */ - if ((si->sb.boardtype == 0) && (var = getvar(NULL, "boardtype"))) { + if ((si->sb.boardtype == 0) + && (var = getvar(NULL, "boardtype"))) { if (!strcmp(var, "bcm94710dev")) si->sb.boardtype = BCM94710D_BOARD; else if (!strcmp(var, "bcm94710ap")) @@ -1263,8 +1653,7 @@ sb_boardtype(sb_t *sbh) } /* return bus type of sbh device */ -uint -sb_bus(sb_t *sbh) +uint sb_bus(sb_t * sbh) { sb_info_t *si; @@ -1273,8 +1662,7 @@ sb_bus(sb_t *sbh) } /* return bus core type */ -uint -sb_buscoretype(sb_t *sbh) +uint sb_buscoretype(sb_t * sbh) { sb_info_t *si; @@ -1284,8 +1672,7 @@ sb_buscoretype(sb_t *sbh) } /* return bus core revision */ -uint -sb_buscorerev(sb_t *sbh) +uint sb_buscorerev(sb_t * sbh) { sb_info_t *si; si = SB_INFO(sbh); @@ -1294,20 +1681,19 @@ sb_buscorerev(sb_t *sbh) } /* return list of found cores */ -uint -sb_corelist(sb_t *sbh, uint coreid[]) +uint sb_corelist(sb_t * sbh, uint coreid[]) { sb_info_t *si; si = SB_INFO(sbh); - bcopy((uchar*)si->coreid, (uchar*)coreid, (si->numcores * sizeof(uint))); + bcopy((uchar *) si->coreid, (uchar *) coreid, + (si->numcores * sizeof(uint))); return (si->numcores); } /* return current register mapping */ -void * -sb_coreregs(sb_t *sbh) +void *sb_coreregs(sb_t * sbh) { sb_info_t *si; @@ -1317,10 +1703,166 @@ sb_coreregs(sb_t *sbh) return (si->curmap); } +#if defined(BCMDBG_ASSERT) +/* traverse all cores to find and clear source of serror */ +static void sb_serr_clear(sb_info_t * si) +{ + sbconfig_t *sb; + uint origidx; + uint i, intr_val = 0; + void *corereg = NULL; + + INTR_OFF(si, intr_val); + origidx = sb_coreidx(&si->sb); + + for (i = 0; i < si->numcores; i++) { + corereg = sb_setcoreidx(&si->sb, i); + if (NULL != corereg) { + sb = REGS2SB(corereg); + if ((R_SBREG(si, &sb->sbtmstatehigh)) & SBTMH_SERR) { + AND_SBREG(si, &sb->sbtmstatehigh, ~SBTMH_SERR); + SB_ERROR(("sb_serr_clear: SError at core 0x%x\n", sb_coreid(&si->sb))); + } + } + } + + sb_setcoreidx(&si->sb, origidx); + INTR_RESTORE(si, intr_val); +} + +/* + * Check if any inband, outband or timeout errors has happened and clear them. + * Must be called with chip clk on ! + */ +bool sb_taclear(sb_t * sbh) +{ + sb_info_t *si; + sbconfig_t *sb; + uint origidx; + uint intr_val = 0; + bool rc = FALSE; + uint32 inband = 0, serror = 0, timeout = 0; + void *corereg = NULL; + volatile uint32 imstate, tmstate; + + si = SB_INFO(sbh); + + if (BUSTYPE(si->sb.bustype) == PCI_BUS) { + volatile uint32 stcmd; + + /* inband error is Target abort for PCI */ + stcmd = + OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_CMD, sizeof(uint32)); + inband = stcmd & PCI_CFG_CMD_STAT_TA; + if (inband) { +#ifdef BCMDBG + SB_ERROR(("inband:\n")); + sb_viewall((void *)si); +#endif + OSL_PCI_WRITE_CONFIG(si->osh, PCI_CFG_CMD, + sizeof(uint32), stcmd); + } + + /* serror */ + stcmd = + OSL_PCI_READ_CONFIG(si->osh, PCI_INT_STATUS, + sizeof(uint32)); + serror = stcmd & PCI_SBIM_STATUS_SERR; + if (serror) { +#ifdef BCMDBG + SB_ERROR(("serror:\n")); + sb_viewall((void *)si); +#endif + sb_serr_clear(si); + OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_STATUS, + sizeof(uint32), stcmd); + } + + /* timeout */ + imstate = sb_corereg(sbh, si->sb.buscoreidx, + SBCONFIGOFF + OFFSETOF(sbconfig_t, + sbimstate), 0, 0); + if ((imstate != 0xffffffff) && (imstate & (SBIM_IBE | SBIM_TO))) { + sb_corereg(sbh, si->sb.buscoreidx, + SBCONFIGOFF + OFFSETOF(sbconfig_t, + sbimstate), ~0, + (imstate & ~(SBIM_IBE | SBIM_TO))); + /* inband = imstate & SBIM_IBE; same as TA above */ + timeout = imstate & SBIM_TO; + if (timeout) { +#ifdef BCMDBG + SB_ERROR(("timeout:\n")); + sb_viewall((void *)si); +#endif + } + } + + if (inband) { + /* dump errlog for sonics >= 2.3 */ + if (si->sb.sonicsrev == SONICS_2_2) ; + else { + uint32 imerrlog, imerrloga; + imerrlog = + sb_corereg(sbh, si->sb.buscoreidx, + SBIMERRLOG, 0, 0); + if (imerrlog & SBTMEL_EC) { + imerrloga = + sb_corereg(sbh, si->sb.buscoreidx, + SBIMERRLOGA, 0, 0); + /* clear errlog */ + sb_corereg(sbh, si->sb.buscoreidx, + SBIMERRLOG, ~0, 0); + SB_ERROR(("sb_taclear: ImErrLog 0x%x, ImErrLogA 0x%x\n", imerrlog, imerrloga)); + } + } + } + + } else if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { + + INTR_OFF(si, intr_val); + origidx = sb_coreidx(sbh); + + corereg = sb_setcore(sbh, SB_PCMCIA, 0); + if (NULL != corereg) { + sb = REGS2SB(corereg); + + imstate = R_SBREG(si, &sb->sbimstate); + /* handle surprise removal */ + if ((imstate != 0xffffffff) + && (imstate & (SBIM_IBE | SBIM_TO))) { + AND_SBREG(si, &sb->sbimstate, + ~(SBIM_IBE | SBIM_TO)); + inband = imstate & SBIM_IBE; + timeout = imstate & SBIM_TO; + } + tmstate = R_SBREG(si, &sb->sbtmstatehigh); + if ((tmstate != 0xffffffff) + && (tmstate & SBTMH_INT_STATUS)) { + if (!inband) { + serror = 1; + sb_serr_clear(si); + } + OR_SBREG(si, &sb->sbtmstatelow, SBTML_INT_ACK); + AND_SBREG(si, &sb->sbtmstatelow, + ~SBTML_INT_ACK); + } + } + sb_setcoreidx(sbh, origidx); + INTR_RESTORE(si, intr_val); + + } + + if (inband | timeout | serror) { + rc = TRUE; + SB_ERROR(("sb_taclear: inband 0x%x, serror 0x%x, timeout 0x%x!\n", inband, serror, timeout)); + } + + return (rc); +} +#endif /* BCMDBG */ /* do buffered registers update */ -void -sb_commit(sb_t *sbh) +void sb_commit(sb_t * sbh) { sb_info_t *si; uint origidx; @@ -1335,13 +1877,14 @@ sb_commit(sb_t *sbh) /* switch over to chipcommon core if there is one, else use pci */ if (si->sb.ccrev != NOREV) { - chipcregs_t *ccregs = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0); + chipcregs_t *ccregs = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); /* do the buffer registers update */ W_REG(si->osh, &ccregs->broadcastaddress, SB_COMMIT); W_REG(si->osh, &ccregs->broadcastdata, 0x0); } else if (PCI(si)) { - sbpciregs_t *pciregs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0); + sbpciregs_t *pciregs = + (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0); /* do the buffer registers update */ W_REG(si->osh, &pciregs->bcastaddr, SB_COMMIT); @@ -1359,8 +1902,7 @@ sb_commit(sb_t *sbh) * bits - core specific bits that are set during and after reset sequence * resetbits - core specific bits that are set only during reset sequence */ -void -sb_core_reset(sb_t *sbh, uint32 bits, uint32 resetbits) +void sb_core_reset(sb_t * sbh, uint32 bits, uint32 resetbits) { sb_info_t *si; sbconfig_t *sb; @@ -1380,7 +1922,8 @@ sb_core_reset(sb_t *sbh, uint32 bits, uint32 resetbits) */ /* set reset while enabling the clock and forcing them on throughout the core */ - W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | SBTML_RESET | bits | resetbits)); + W_SBREG(si, &sb->sbtmstatelow, + (SBTML_FGC | SBTML_CLK | SBTML_RESET | bits | resetbits)); dummy = R_SBREG(si, &sb->sbtmstatelow); OSL_DELAY(1); @@ -1402,8 +1945,7 @@ sb_core_reset(sb_t *sbh, uint32 bits, uint32 resetbits) OSL_DELAY(1); } -void -sb_core_tofixup(sb_t *sbh) +void sb_core_tofixup(sb_t * sbh) { sb_info_t *si; sbconfig_t *sb; @@ -1419,15 +1961,16 @@ sb_core_tofixup(sb_t *sbh) if (BUSTYPE(si->sb.bustype) == SB_BUS) { SET_SBREG(si, &sb->sbimconfiglow, - SBIMCL_RTO_MASK | SBIMCL_STO_MASK, - (0x5 << SBIMCL_RTO_SHIFT) | 0x3); + SBIMCL_RTO_MASK | SBIMCL_STO_MASK, + (0x5 << SBIMCL_RTO_SHIFT) | 0x3); } else { if (sb_coreid(sbh) == SB_PCI) { SET_SBREG(si, &sb->sbimconfiglow, - SBIMCL_RTO_MASK | SBIMCL_STO_MASK, - (0x3 << SBIMCL_RTO_SHIFT) | 0x2); + SBIMCL_RTO_MASK | SBIMCL_STO_MASK, + (0x3 << SBIMCL_RTO_SHIFT) | 0x2); } else { - SET_SBREG(si, &sb->sbimconfiglow, (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0); + SET_SBREG(si, &sb->sbimconfiglow, + (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0); } } @@ -1458,11 +2001,10 @@ sb_core_tofixup(sb_t *sbh) #define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK) -uint32 -sb_set_initiator_to(sb_t *sbh, uint32 to) +uint32 sb_set_initiator_to(sb_t * sbh, uint32 to, uint idx) { sb_info_t *si; - uint origidx, idx; + uint origidx; uint intr_val = 0; uint32 tmp, ret = 0xffffffff; sbconfig_t *sb; @@ -1473,27 +2015,28 @@ sb_set_initiator_to(sb_t *sbh, uint32 to) return ret; /* Figure out the master core */ - idx = BADIDX; - switch (BUSTYPE(si->sb.bustype)) { - case PCI_BUS: - idx = si->sb.buscoreidx; - break; - case JTAG_BUS: - idx = SB_CC_IDX; - break; - case PCMCIA_BUS: - case SDIO_BUS: - idx = sb_findcoreidx(si, SB_PCMCIA, 0); - break; - case SB_BUS: - if ((idx = sb_findcoreidx(si, SB_MIPS33, 0)) == BADIDX) - idx = sb_findcoreidx(si, SB_MIPS, 0); - break; - default: - ASSERT(0); + if (idx == BADIDX) { + switch (BUSTYPE(si->sb.bustype)) { + case PCI_BUS: + idx = si->sb.buscoreidx; + break; + case JTAG_BUS: + idx = SB_CC_IDX; + break; + case PCMCIA_BUS: + case SDIO_BUS: + idx = sb_findcoreidx(sbh, SB_PCMCIA, 0); + break; + case SB_BUS: + if ((idx = sb_findcoreidx(sbh, SB_MIPS33, 0)) == BADIDX) + idx = sb_findcoreidx(sbh, SB_MIPS, 0); + break; + default: + ASSERT(0); + } + if (idx == BADIDX) + return ret; } - if (idx == BADIDX) - return ret; INTR_OFF(si, intr_val); origidx = sb_coreidx(sbh); @@ -1510,8 +2053,7 @@ sb_set_initiator_to(sb_t *sbh, uint32 to) return ret; } -void -sb_core_disable(sb_t *sbh, uint32 bits) +void sb_core_disable(sb_t * sbh, uint32 bits) { sb_info_t *si; volatile uint32 dummy; @@ -1553,7 +2095,8 @@ sb_core_disable(sb_t *sbh, uint32 bits) } /* set reset and reject while enabling the clocks */ - W_SBREG(si, &sb->sbtmstatelow, (bits | SBTML_FGC | SBTML_CLK | rej | SBTML_RESET)); + W_SBREG(si, &sb->sbtmstatelow, + (bits | SBTML_FGC | SBTML_CLK | rej | SBTML_RESET)); dummy = R_SBREG(si, &sb->sbtmstatelow); OSL_DELAY(10); @@ -1561,50 +2104,43 @@ sb_core_disable(sb_t *sbh, uint32 bits) if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ); -disable: + disable: /* leave reset and reject asserted */ W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET)); OSL_DELAY(1); } /* set chip watchdog reset timer to fire in 'ticks' backplane cycles */ -void -sb_watchdog(sb_t *sbh, uint ticks) +void sb_watchdog(sb_t * sbh, uint ticks) { sb_info_t *si = SB_INFO(sbh); - /* make sure we come up in fast clock mode */ - sb_clkctl_clk(sbh, CLK_FAST); + /* make sure we come up in fast clock mode; or if clearing, clear clock */ + if (ticks) + sb_clkctl_clk(sbh, CLK_FAST); + else + sb_clkctl_clk(sbh, CLK_DYNAMIC); + + if (sbh->chip == BCM4328_CHIP_ID && ticks != 0) + sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask), + PMURES_BIT(RES4328_ROM_SWITCH), + PMURES_BIT(RES4328_ROM_SWITCH)); /* instant NMI */ switch (si->gpioid) { case SB_CC: -#ifdef __mips__ - if (sb_chip(sbh) == BCM4785_CHIP_ID && ticks <= 1) - MTC0(C0_BROADCOM, 4, (1 << 22)); -#endif /* __mips__ */ - sb_corereg(si, 0, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); -#ifdef __mips__ - if (sb_chip(sbh) == BCM4785_CHIP_ID && ticks <= 1) { - __asm__ __volatile__ ( - ".set\tmips3\n\t" - "sync\n\t" - "wait\n\t" - ".set\tmips0" - ); - while (1); - } -#endif /* __mips__ */ + sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, + ticks); break; case SB_EXTIF: - sb_corereg(si, si->gpioidx, OFFSETOF(extifregs_t, watchdog), ~0, ticks); + sb_corereg(sbh, si->gpioidx, OFFSETOF(extifregs_t, watchdog), + ~0, ticks); break; } } /* initialize the pcmcia core */ -void -sb_pcmcia_init(sb_t *sbh) +void sb_pcmcia_init(sb_t * sbh) { sb_info_t *si; uint8 cor = 0; @@ -1618,21 +2154,120 @@ sb_pcmcia_init(sb_t *sbh) } +void BCMINITFN(sb_pci_up) (sb_t * sbh) { + sb_info_t *si = SB_INFO(sbh); + if (si->gpioid == SB_EXTIF) + return; + + /* if not pci bus, we're done */ + if (BUSTYPE(si->sb.bustype) != PCI_BUS) + return; + + if (FORCEHT_WAR32414(si)) + sb_war32414_forceHT(sbh, 1); + + if (PCIE_ASPMWARS(si) || si->sb.pr42780) + sb_pcieclkreq(sbh, 1, 0); + + if (PCIE(si) && + (((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev == 2)) || + ((si->sb.chip == BCM4312_CHIP_ID) && (si->sb.chiprev == 0)))) + sb_set_initiator_to((void *)si, 0x3, + sb_findcoreidx((void *)si, SB_D11, 0)); +} + +/* Unconfigure and/or apply various WARs when system is going to sleep mode */ +void BCMUNINITFN(sb_pci_sleep) (sb_t * sbh) { + sb_info_t *si = SB_INFO(sbh); + if (si->gpioid == SB_EXTIF) + return; + uint32 w; + + /* if not pci bus, we're done */ + if (!PCIE(si) || !PCIE_ASPMWARS(si)) + return; + + w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset, + sizeof(uint32)); + w &= ~PCIE_CAP_LCREG_ASPML1; + OSL_PCI_WRITE_CONFIG(si->osh, si->pciecap_lcreg_offset, sizeof(uint32), + w); +} + +/* Unconfigure and/or apply various WARs when going down */ +void BCMINITFN(sb_pci_down) (sb_t * sbh) { + sb_info_t *si = SB_INFO(sbh); + if (si->gpioid == SB_EXTIF) + return; + + /* if not pci bus, we're done */ + if (BUSTYPE(si->sb.bustype) != PCI_BUS) + return; + + if (FORCEHT_WAR32414(si)) + sb_war32414_forceHT(sbh, 0); + + if (si->pr42767_war) { + sb_pcieclkreq(sbh, 1, 1); + si->pr42767_war = FALSE; + } else if (si->sb.pr42780) { + sb_pcieclkreq(sbh, 1, 1); + } +} + +static void BCMINITFN(sb_war42767_clkreq) (sb_t * sbh) { + sbpcieregs_t *pcieregs; + uint16 val16, *reg16; + sb_info_t *si; + + si = SB_INFO(sbh); + + /* if not pcie bus, we're done */ + if (!PCIE(si) || !PCIE_ASPMWARS(si)) + return; + + pcieregs = (sbpcieregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx); + reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET]; + val16 = R_REG(si->osh, reg16); + /* if clockreq is not advertized advertize it */ + if (!si->pcie_war_ovr) { + val16 |= SRSH_CLKREQ_ENB; + si->pr42767_war = TRUE; + + si->sb.pr42780 = TRUE; + } else + val16 &= ~SRSH_CLKREQ_ENB; + W_REG(si->osh, reg16, val16); +} + +static void BCMINITFN(sb_war42767) (sb_t * sbh) { + uint32 w = 0; + sb_info_t *si; + + si = SB_INFO(sbh); + + /* if not pcie bus, we're done */ + if (!PCIE(si) || !PCIE_ASPMWARS(si)) + return; + + sb_pcie_mdioread(si, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); + if (w & PLL_CTRL_FREQDET_EN) { + w &= ~PLL_CTRL_FREQDET_EN; + sb_pcie_mdiowrite(si, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); + } +} /* * Configure the pci core for pci client (NIC) action * coremask is the bitvec of cores by index to be enabled. */ -void -BCMINITFN(sb_pci_setup)(sb_t *sbh, uint coremask) -{ +void BCMINITFN(sb_pci_setup) (sb_t * sbh, uint coremask) { sb_info_t *si; sbconfig_t *sb; sbpciregs_t *pciregs; uint32 sbflag; uint32 w; uint idx; - int reg_val; si = SB_INFO(sbh); @@ -1652,7 +2287,7 @@ BCMINITFN(sb_pci_setup)(sb_t *sbh, uint coremask) sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK; /* switch over to pci core */ - pciregs = (sbpciregs_t*) sb_setcoreidx(sbh, si->sb.buscoreidx); + pciregs = (sbpciregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx); sb = REGS2SB(pciregs); /* @@ -1670,45 +2305,69 @@ BCMINITFN(sb_pci_setup)(sb_t *sbh, uint coremask) } if (PCI(si)) { - OR_REG(si->osh, &pciregs->sbtopci2, (SBTOPCI_PREF|SBTOPCI_BURST)); + OR_REG(si->osh, &pciregs->sbtopci2, + (SBTOPCI_PREF | SBTOPCI_BURST)); if (si->sb.buscorerev >= 11) - OR_REG(si->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI); + OR_REG(si->osh, &pciregs->sbtopci2, + SBTOPCI_RC_READMULTI); if (si->sb.buscorerev < 5) { - SET_SBREG(si, &sb->sbimconfiglow, SBIMCL_RTO_MASK | SBIMCL_STO_MASK, - (0x3 << SBIMCL_RTO_SHIFT) | 0x2); + SET_SBREG(si, &sb->sbimconfiglow, + SBIMCL_RTO_MASK | SBIMCL_STO_MASK, + (0x3 << SBIMCL_RTO_SHIFT) | 0x2); sb_commit(sbh); } } -#ifdef PCIE_SUPPOER /* PCIE workarounds */ if (PCIE(si)) { if ((si->sb.buscorerev == 0) || (si->sb.buscorerev == 1)) { - reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS, - PCIE_TLP_WORKAROUNDSREG); - reg_val |= 0x8; - sb_pcie_writereg((void *)sbh, (void *)PCIE_PCIEREGS, - PCIE_TLP_WORKAROUNDSREG, reg_val); + w = sb_pcie_readreg((void *)(uintptr) sbh, + (void *)(uintptr) PCIE_PCIEREGS, + PCIE_TLP_WORKAROUNDSREG); + w |= 0x8; + sb_pcie_writereg((void *)(uintptr) sbh, + (void *)(uintptr) PCIE_PCIEREGS, + PCIE_TLP_WORKAROUNDSREG, w); } if (si->sb.buscorerev == 1) { - reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS, - PCIE_DLLP_LCREG); - reg_val |= (0x40); - sb_pcie_writereg(sbh, (void *)PCIE_PCIEREGS, PCIE_DLLP_LCREG, reg_val); + w = sb_pcie_readreg((void *)(uintptr) sbh, + (void *)(uintptr) PCIE_PCIEREGS, + PCIE_DLLP_LCREG); + w |= (0x40); + sb_pcie_writereg((void *)(uintptr) sbh, + (void *)(uintptr) PCIE_PCIEREGS, + PCIE_DLLP_LCREG, w); } if (si->sb.buscorerev == 0) sb_war30841(si); + + if ((si->sb.buscorerev >= 3) && (si->sb.buscorerev <= 5)) { + w = sb_pcie_readreg((void *)(uintptr) sbh, + (void *)(uintptr) PCIE_PCIEREGS, + PCIE_DLLP_PMTHRESHREG); + w &= ~(PCIE_L1THRESHOLDTIME_MASK); + w |= (PCIE_L1THRESHOLD_WARVAL << + PCIE_L1THRESHOLDTIME_SHIFT); + sb_pcie_writereg((void *)(uintptr) sbh, + (void *)(uintptr) PCIE_PCIEREGS, + PCIE_DLLP_PMTHRESHREG, w); + + sb_war43448(sbh); + + sb_war42767(sbh); + + sb_war43448_aspm(sbh); + sb_war42767_clkreq(sbh); + } } -#endif /* switch back to previous core */ sb_setcoreidx(sbh, idx); } -uint32 -sb_base(uint32 admatch) +uint32 sb_base(uint32 admatch) { uint32 base; uint type; @@ -1731,8 +2390,7 @@ sb_base(uint32 admatch) return (base); } -uint32 -sb_size(uint32 admatch) +uint32 sb_size(uint32 admatch) { uint32 size; uint type; @@ -1743,21 +2401,26 @@ sb_size(uint32 admatch) size = 0; if (type == 0) { - size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1); + size = + 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + + 1); } else if (type == 1) { ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ - size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1); + size = + 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + + 1); } else if (type == 2) { ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ - size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1); + size = + 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + + 1); } return (size); } /* return the core-type instantiation # of the current core */ -uint -sb_coreunit(sb_t *sbh) +uint sb_coreunit(sb_t * sbh) { sb_info_t *si; uint idx; @@ -1781,24 +2444,27 @@ sb_coreunit(sb_t *sbh) return (coreunit); } -static INLINE uint32 -factor6(uint32 x) -{ +static uint32 BCMINITFN(factor6) (uint32 x) { switch (x) { - case CC_F6_2: return 2; - case CC_F6_3: return 3; - case CC_F6_4: return 4; - case CC_F6_5: return 5; - case CC_F6_6: return 6; - case CC_F6_7: return 7; - default: return 0; + case CC_F6_2: + return 2; + case CC_F6_3: + return 3; + case CC_F6_4: + return 4; + case CC_F6_5: + return 5; + case CC_F6_6: + return 6; + case CC_F6_7: + return 7; + default: + return 0; } } /* calculate the speed the SB would run at given a set of clockcontrol values */ -uint32 -sb_clock_rate(uint32 pll_type, uint32 n, uint32 m) -{ +uint32 BCMINITFN(sb_clock_rate) (uint32 pll_type, uint32 n, uint32 m) { uint32 n1, n2, clock, m1, m2, m3, mc; n1 = n & CN_N1_MASK; @@ -1810,9 +2476,8 @@ sb_clock_rate(uint32 pll_type, uint32 n, uint32 m) else return CC_T6_M0; } else if ((pll_type == PLL_TYPE1) || - (pll_type == PLL_TYPE3) || - (pll_type == PLL_TYPE4) || - (pll_type == PLL_TYPE7)) { + (pll_type == PLL_TYPE3) || + (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) { n1 = factor6(n1); n2 += CC_F5_BIAS; } else if (pll_type == PLL_TYPE2) { @@ -1825,9 +2490,8 @@ sb_clock_rate(uint32 pll_type, uint32 n, uint32 m) } else ASSERT(0); /* PLL types 3 and 7 use BASE2 (25Mhz) */ - if ((pll_type == PLL_TYPE3) || - (pll_type == PLL_TYPE7)) { - clock = CC_CLOCK_BASE2 * n1 * n2; + if ((pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE7)) { + clock = CC_CLOCK_BASE2 * n1 * n2; } else clock = CC_CLOCK_BASE1 * n1 * n2; @@ -1841,8 +2505,7 @@ sb_clock_rate(uint32 pll_type, uint32 n, uint32 m) if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3) || - (pll_type == PLL_TYPE4) || - (pll_type == PLL_TYPE7)) { + (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) { m1 = factor6(m1); if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) m2 += CC_F5_BIAS; @@ -1851,12 +2514,18 @@ sb_clock_rate(uint32 pll_type, uint32 n, uint32 m) m3 = factor6(m3); switch (mc) { - case CC_MC_BYPASS: return (clock); - case CC_MC_M1: return (clock / m1); - case CC_MC_M1M2: return (clock / (m1 * m2)); - case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); - case CC_MC_M1M3: return (clock / (m1 * m3)); - default: return (0); + case CC_MC_BYPASS: + return (clock); + case CC_MC_M1: + return (clock / m1); + case CC_MC_M1M2: + return (clock / (m1 * m2)); + case CC_MC_M1M2M3: + return (clock / (m1 * m2 * m3)); + case CC_MC_M1M3: + return (clock / (m1 * m3)); + default: + return (0); } } else { ASSERT(pll_type == PLL_TYPE2); @@ -1880,15 +2549,13 @@ sb_clock_rate(uint32 pll_type, uint32 n, uint32 m) } /* returns the current speed the SB is running at */ -uint32 -sb_clock(sb_t *sbh) -{ +uint32 BCMINITFN(sb_clock) (sb_t * sbh) { sb_info_t *si; extifregs_t *eir; chipcregs_t *cc; uint32 n, m; uint idx; - uint32 pll_type, rate; + uint32 cap, pll_type, rate; uint intr_val = 0; si = SB_INFO(sbh); @@ -1902,7 +2569,24 @@ sb_clock(sb_t *sbh) n = R_REG(si->osh, &eir->clockcontrol_n); m = R_REG(si->osh, &eir->clockcontrol_sb); } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { - pll_type = R_REG(si->osh, &cc->capabilities) & CAP_PLL_MASK; + + cap = R_REG(si->osh, &cc->capabilities); + + if (cap & CC_CAP_PMU) { + + if (sb_chip(sbh) == BCM5354_CHIP_ID) { + /* 5354 has a constant sb clock of 120MHz */ + rate = 120000000; + goto end; + } else + if (sb_chip(sbh) == BCM4328_CHIP_ID) { + rate = 80000000; + goto end; + } else + ASSERT(0); + } + + pll_type = cap & CC_CAP_PLL_MASK; if (pll_type == PLL_NONE) { INTR_RESTORE(si, intr_val); return 80000000; @@ -1910,7 +2594,8 @@ sb_clock(sb_t *sbh) n = R_REG(si->osh, &cc->clockcontrol_n); if (pll_type == PLL_TYPE6) m = R_REG(si->osh, &cc->clockcontrol_m3); - else if ((pll_type == PLL_TYPE3) && !(BCMINIT(sb_chip)(sbh) == 0x5365)) + else if (pll_type == PLL_TYPE3 + && !(BCMINIT(sb_chip) (sbh) == 0x5365)) m = R_REG(si->osh, &cc->clockcontrol_m2); else m = R_REG(si->osh, &cc->clockcontrol_sb); @@ -1920,7 +2605,7 @@ sb_clock(sb_t *sbh) } /* calculate rate */ - if (BCMINIT(sb_chip)(sbh) == 0x5365) + if (BCMINIT(sb_chip) (sbh) == 0x5365) rate = 100000000; else { rate = sb_clock_rate(pll_type, n, m); @@ -1929,6 +2614,7 @@ sb_clock(sb_t *sbh) rate = rate / 2; } + end: /* switch back to previous core */ sb_setcoreidx(sbh, idx); @@ -1937,9 +2623,17 @@ sb_clock(sb_t *sbh) return rate; } +uint32 BCMINITFN(sb_alp_clock) (sb_t * sbh) { + uint32 clock = ALP_CLOCK; + + if (sbh->cccaps & CC_CAP_PMU) + clock = sb_pmu_alp_clock(sbh, sb_osh(sbh)); + + return clock; +} + /* change logical "focus" to the gpio core for optimized access */ -void* -sb_gpiosetcore(sb_t *sbh) +void *sb_gpiosetcore(sb_t * sbh) { sb_info_t *si; @@ -1949,8 +2643,7 @@ sb_gpiosetcore(sb_t *sbh) } /* mask&set gpiocontrol bits */ -uint32 -sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +uint32 sb_gpiocontrol(sb_t * sbh, uint32 mask, uint32 val, uint8 priority) { sb_info_t *si; uint regoff; @@ -1958,12 +2651,13 @@ sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) si = SB_INFO(sbh); regoff = 0; - priority = GPIO_DRV_PRIORITY; /* compatibility hack */ - - /* gpios could be shared on router platforms */ - if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { + /* gpios could be shared on router platforms + * ignore reservation if it's high priority (e.g., test apps) + */ + if ((priority != GPIO_HI_PRIORITY) && + (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : - ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); + ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } @@ -1980,12 +2674,11 @@ sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) return (0); } - return (sb_corereg(si, si->gpioidx, regoff, mask, val)); + return (sb_corereg(sbh, si->gpioidx, regoff, mask, val)); } /* mask&set gpio output enable bits */ -uint32 -sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +uint32 sb_gpioouten(sb_t * sbh, uint32 mask, uint32 val, uint8 priority) { sb_info_t *si; uint regoff; @@ -1993,12 +2686,13 @@ sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) si = SB_INFO(sbh); regoff = 0; - priority = GPIO_DRV_PRIORITY; /* compatibility hack */ - - /* gpios could be shared on router platforms */ - if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { + /* gpios could be shared on router platforms + * ignore reservation if it's high priority (e.g., test apps) + */ + if ((priority != GPIO_HI_PRIORITY) && + (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : - ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); + ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } @@ -2016,12 +2710,11 @@ sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) break; } - return (sb_corereg(si, si->gpioidx, regoff, mask, val)); + return (sb_corereg(sbh, si->gpioidx, regoff, mask, val)); } /* mask&set gpio output bits */ -uint32 -sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +uint32 sb_gpioout(sb_t * sbh, uint32 mask, uint32 val, uint8 priority) { sb_info_t *si; uint regoff; @@ -2029,12 +2722,13 @@ sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) si = SB_INFO(sbh); regoff = 0; - priority = GPIO_DRV_PRIORITY; /* compatibility hack */ - - /* gpios could be shared on router platforms */ - if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { + /* gpios could be shared on router platforms + * ignore reservation if it's high priority (e.g., test apps) + */ + if ((priority != GPIO_HI_PRIORITY) && + (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : - ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); + ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } @@ -2052,29 +2746,27 @@ sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) break; } - return (sb_corereg(si, si->gpioidx, regoff, mask, val)); + return (sb_corereg(sbh, si->gpioidx, regoff, mask, val)); } /* reserve one gpio */ -uint32 -sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) +uint32 sb_gpioreserve(sb_t * sbh, uint32 gpio_bitmask, uint8 priority) { sb_info_t *si; si = SB_INFO(sbh); - priority = GPIO_DRV_PRIORITY; /* compatibility hack */ - /* only cores on SB_BUS share GPIO's and only applcation users need to * reserve/release GPIO */ - if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { + if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority)); return -1; } /* make sure only one bit is set */ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { - ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); + ASSERT((gpio_bitmask) + && !((gpio_bitmask) & (gpio_bitmask - 1))); return -1; } @@ -2093,25 +2785,23 @@ sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) * persists till some one overwrites it */ -uint32 -sb_gpiorelease(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) +uint32 sb_gpiorelease(sb_t * sbh, uint32 gpio_bitmask, uint8 priority) { sb_info_t *si; si = SB_INFO(sbh); - priority = GPIO_DRV_PRIORITY; /* compatibility hack */ - /* only cores on SB_BUS share GPIO's and only applcation users need to * reserve/release GPIO */ - if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { + if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority)); return -1; } /* make sure only one bit is set */ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { - ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); + ASSERT((gpio_bitmask) + && !((gpio_bitmask) & (gpio_bitmask - 1))); return -1; } @@ -2126,8 +2816,7 @@ sb_gpiorelease(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) } /* return the current gpioin register value */ -uint32 -sb_gpioin(sb_t *sbh) +uint32 sb_gpioin(sb_t * sbh) { sb_info_t *si; uint regoff; @@ -2149,12 +2838,11 @@ sb_gpioin(sb_t *sbh) break; } - return (sb_corereg(si, si->gpioidx, regoff, 0, 0)); + return (sb_corereg(sbh, si->gpioidx, regoff, 0, 0)); } /* mask&set gpio interrupt polarity bits */ -uint32 -sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +uint32 sb_gpiointpolarity(sb_t * sbh, uint32 mask, uint32 val, uint8 priority) { sb_info_t *si; uint regoff; @@ -2162,12 +2850,10 @@ sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) si = SB_INFO(sbh); regoff = 0; - priority = GPIO_DRV_PRIORITY; /* compatibility hack */ - /* gpios could be shared on router platforms */ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : - ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); + ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } @@ -2186,12 +2872,11 @@ sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) break; } - return (sb_corereg(si, si->gpioidx, regoff, mask, val)); + return (sb_corereg(sbh, si->gpioidx, regoff, mask, val)); } /* mask&set gpio interrupt mask bits */ -uint32 -sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +uint32 sb_gpiointmask(sb_t * sbh, uint32 mask, uint32 val, uint8 priority) { sb_info_t *si; uint regoff; @@ -2199,12 +2884,10 @@ sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) si = SB_INFO(sbh); regoff = 0; - priority = GPIO_DRV_PRIORITY; /* compatibility hack */ - /* gpios could be shared on router platforms */ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : - ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); + ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } @@ -2223,12 +2906,11 @@ sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) break; } - return (sb_corereg(si, si->gpioidx, regoff, mask, val)); + return (sb_corereg(sbh, si->gpioidx, regoff, mask, val)); } /* assign the gpio to an led */ -uint32 -sb_gpioled(sb_t *sbh, uint32 mask, uint32 val) +uint32 sb_gpioled(sb_t * sbh, uint32 mask, uint32 val) { sb_info_t *si; @@ -2237,12 +2919,13 @@ sb_gpioled(sb_t *sbh, uint32 mask, uint32 val) return -1; /* gpio led powersave reg */ - return (sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); + return (sb_corereg + (sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, + val)); } -/* mask & set gpio timer val */ -uint32 -sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval) +/* mask&set gpio timer val */ +uint32 sb_gpiotimerval(sb_t * sbh, uint32 mask, uint32 gpiotimerval) { sb_info_t *si; si = SB_INFO(sbh); @@ -2250,78 +2933,318 @@ sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval) if (si->sb.ccrev < 16) return -1; - return (sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); + return (sb_corereg(sbh, SB_CC_IDX, + OFFSETOF(chipcregs_t, gpiotimerval), mask, + gpiotimerval)); +} + +uint32 sb_gpiopull(sb_t * sbh, bool updown, uint32 mask, uint32 val) +{ + sb_info_t *si; + uint offs; + + si = SB_INFO(sbh); + if (si->sb.ccrev < 20) + return -1; + + offs = + (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : + OFFSETOF(chipcregs_t, gpiopullup)); + return (sb_corereg(sbh, SB_CC_IDX, offs, mask, val)); +} + +uint32 sb_gpioevent(sb_t * sbh, uint regtype, uint32 mask, uint32 val) +{ + sb_info_t *si; + uint offs; + + si = SB_INFO(sbh); + if (si->sb.ccrev < 11) + return -1; + + if (regtype == GPIO_REGEVT) + offs = OFFSETOF(chipcregs_t, gpioevent); + else if (regtype == GPIO_REGEVT_INTMSK) + offs = OFFSETOF(chipcregs_t, gpioeventintmask); + else if (regtype == GPIO_REGEVT_INTPOL) + offs = OFFSETOF(chipcregs_t, gpioeventintpolarity); + else + return -1; + + return (sb_corereg(sbh, SB_CC_IDX, offs, mask, val)); +} + +void *BCMINITFN(sb_gpio_handler_register) (sb_t * sbh, uint32 event, + bool level, gpio_handler_t cb, + void *arg) { + sb_info_t *si; + gpioh_item_t *gi; + + ASSERT(event); + ASSERT(cb); + + si = SB_INFO(sbh); + if (si->sb.ccrev < 11) + return NULL; + + if ((gi = MALLOC(si->osh, sizeof(gpioh_item_t))) == NULL) + return NULL; + + bzero(gi, sizeof(gpioh_item_t)); + gi->event = event; + gi->handler = cb; + gi->arg = arg; + gi->level = level; + + gi->next = si->gpioh_head; + si->gpioh_head = gi; + + return (void *)(gi); +} + +void BCMINITFN(sb_gpio_handler_unregister) (sb_t * sbh, void *gpioh) { + sb_info_t *si; + gpioh_item_t *p, *n; + + si = SB_INFO(sbh); + if (si->sb.ccrev < 11) + return; + + ASSERT(si->gpioh_head); + if ((void *)si->gpioh_head == gpioh) { + si->gpioh_head = si->gpioh_head->next; + MFREE(si->osh, gpioh, sizeof(gpioh_item_t)); + return; + } else { + p = si->gpioh_head; + n = p->next; + while (n) { + if ((void *)n == gpioh) { + p->next = n->next; + MFREE(si->osh, gpioh, sizeof(gpioh_item_t)); + return; + } + p = n; + n = n->next; + } + } + + ASSERT(0); /* Not found in list */ +} + +void sb_gpio_handler_process(sb_t * sbh) +{ + sb_info_t *si; + gpioh_item_t *h; + uint32 status; + uint32 level = sb_gpioin(sbh); + uint32 edge = sb_gpioevent(sbh, GPIO_REGEVT, 0, 0); + + si = SB_INFO(sbh); + for (h = si->gpioh_head; h != NULL; h = h->next) { + if (h->handler) { + status = (h->level ? level : edge); + + if (status & h->event) + h->handler(status, h->arg); + } + } + + sb_gpioevent(sbh, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */ +} + +uint32 sb_gpio_int_enable(sb_t * sbh, bool enable) +{ + sb_info_t *si; + uint offs; + + si = SB_INFO(sbh); + if (si->sb.ccrev < 11) + return -1; + + offs = OFFSETOF(chipcregs_t, intmask); + return (sb_corereg + (sbh, SB_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0))); } +#ifdef BCMDBG +void sb_dump(sb_t * sbh, struct bcmstrbuf *b) +{ + sb_info_t *si; + uint i; + + si = SB_INFO(sbh); + + bcm_bprintf(b, + "si %p chip 0x%x chiprev 0x%x boardtype 0x%x boardvendor 0x%x bus %d\n", + si, si->sb.chip, si->sb.chiprev, si->sb.boardtype, + si->sb.boardvendor, si->sb.bustype); + bcm_bprintf(b, "osh %p curmap %p\n", si->osh, si->curmap); + bcm_bprintf(b, + "sonicsrev %d ccrev %d buscoretype 0x%x buscorerev %d curidx %d\n", + si->sb.sonicsrev, si->sb.ccrev, si->sb.buscoretype, + si->sb.buscorerev, si->curidx); + + bcm_bprintf(b, "forceHT %d ASPM overflowPR42780 %d pcie_polarity %d\n", + si->sb.pr32414, si->sb.pr42780, si->pcie_polarity); + + bcm_bprintf(b, "cores: "); + for (i = 0; i < si->numcores; i++) + bcm_bprintf(b, "0x%x ", si->coreid[i]); + bcm_bprintf(b, "\n"); +} + +/* print interesting sbconfig registers */ +void sb_dumpregs(sb_t * sbh, struct bcmstrbuf *b) +{ + sb_info_t *si; + sbconfig_t *sb; + uint origidx; + uint curidx, i, intr_val = 0; + + si = SB_INFO(sbh); + origidx = si->curidx; + + INTR_OFF(si, intr_val); + curidx = si->curidx; + + for (i = 0; i < si->numcores; i++) { + sb = REGS2SB(sb_setcoreidx(sbh, i)); + + bcm_bprintf(b, "core 0x%x: \n", si->coreid[i]); + bcm_bprintf(b, + "sbtmstatelow 0x%x sbtmstatehigh 0x%x sbidhigh 0x%x " + "sbimstate 0x%x\n sbimconfiglow 0x%x sbimconfighigh 0x%x\n", + R_SBREG(si, &sb->sbtmstatelow), R_SBREG(si, + &sb-> + sbtmstatehigh), + R_SBREG(si, &sb->sbidhigh), R_SBREG(si, + &sb->sbimstate), + R_SBREG(si, &sb->sbimconfiglow), R_SBREG(si, + &sb-> + sbimconfighigh)); + } + + sb_setcoreidx(sbh, origidx); + INTR_RESTORE(si, intr_val); +} + +void sb_view(sb_t * sbh) +{ + sb_info_t *si; + sbconfig_t *sb; + + si = SB_INFO(sbh); + sb = REGS2SB(si->curmap); + + if (si->sb.sonicsrev > SONICS_2_2) + SB_ERROR(("sbimerrlog 0x%x sbimerrloga 0x%x\n", + sb_corereg(sbh, sb_coreidx(&si->sb), SBIMERRLOG, 0, + 0), sb_corereg(sbh, sb_coreidx(&si->sb), + SBIMERRLOGA, 0, 0))); + + SB_ERROR(("sbipsflag 0x%x sbtpsflag 0x%x sbtmerrloga 0x%x sbtmerrlog 0x%x\n", R_SBREG(si, &sb->sbipsflag), R_SBREG(si, &sb->sbtpsflag), R_SBREG(si, &sb->sbtmerrloga), R_SBREG(si, &sb->sbtmerrlog))); + SB_ERROR(("sbadmatch3 0x%x sbadmatch2 0x%x sbadmatch1 0x%x\n", + R_SBREG(si, &sb->sbadmatch3), R_SBREG(si, &sb->sbadmatch2), + R_SBREG(si, &sb->sbadmatch1))); + SB_ERROR(("sbimstate 0x%x sbintvec 0x%x sbtmstatelow 0x%x sbtmstatehigh 0x%x\n", R_SBREG(si, &sb->sbimstate), R_SBREG(si, &sb->sbintvec), R_SBREG(si, &sb->sbtmstatelow), R_SBREG(si, &sb->sbtmstatehigh))); + SB_ERROR(("sbbwa0 0x%x sbimconfiglow 0x%x sbimconfighigh 0x%x sbadmatch0 0x%x\n", R_SBREG(si, &sb->sbbwa0), R_SBREG(si, &sb->sbimconfiglow), R_SBREG(si, &sb->sbimconfighigh), R_SBREG(si, &sb->sbadmatch0))); + SB_ERROR(("sbtmconfiglow 0x%x sbtmconfighigh 0x%x sbbconfig 0x%x sbbstate 0x%x\n", R_SBREG(si, &sb->sbtmconfiglow), R_SBREG(si, &sb->sbtmconfighigh), R_SBREG(si, &sb->sbbconfig), R_SBREG(si, &sb->sbbstate))); + SB_ERROR(("sbactcnfg 0x%x sbflagst 0x%x sbidlow 0x%x sbidhigh 0x%x\n", + R_SBREG(si, &sb->sbactcnfg), R_SBREG(si, &sb->sbflagst), + R_SBREG(si, &sb->sbidlow), R_SBREG(si, &sb->sbidhigh))); +} + +void sb_viewall(sb_t * sbh) +{ + sb_info_t *si; + uint curidx, i; + uint intr_val = 0; + + si = SB_INFO(sbh); + curidx = si->curidx; + + for (i = 0; i < si->numcores; i++) { + INTR_OFF(si, intr_val); + sb_setcoreidx(sbh, i); + sb_view(sbh); + INTR_RESTORE(si, intr_val); + } + + sb_setcoreidx(sbh, curidx); +} +#endif /* BCMDBG */ /* return the slow clock source - LPO, XTAL, or PCI */ -static uint -sb_slowclk_src(sb_info_t *si) +static uint sb_slowclk_src(sb_info_t * si) { chipcregs_t *cc; - ASSERT(sb_coreid(&si->sb) == SB_CC); if (si->sb.ccrev < 6) { if ((BUSTYPE(si->sb.bustype) == PCI_BUS) && - (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32)) & - PCI_CFG_GPIO_SCS)) + (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32)) + & PCI_CFG_GPIO_SCS)) return (SCC_SS_PCI); else return (SCC_SS_XTAL); } else if (si->sb.ccrev < 10) { - cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); + cc = (chipcregs_t *) sb_setcoreidx(&si->sb, si->curidx); return (R_REG(si->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); - } else /* Insta-clock */ + } else /* Insta-clock */ return (SCC_SS_XTAL); } /* return the ILP (slowclock) min or max frequency */ -static uint -sb_slowclk_freq(sb_info_t *si, bool max) +static uint sb_slowclk_freq(sb_info_t * si, bool max_freq) { chipcregs_t *cc; uint32 slowclk; uint div; - ASSERT(sb_coreid(&si->sb) == SB_CC); - cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); + cc = (chipcregs_t *) sb_setcoreidx(&si->sb, si->curidx); /* shouldn't be here unless we've established the chip has dynamic clk control */ - ASSERT(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL); + ASSERT(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL); slowclk = sb_slowclk_src(si); if (si->sb.ccrev < 6) { if (slowclk == SCC_SS_PCI) - return (max? (PCIMAXFREQ/64) : (PCIMINFREQ/64)); + return (max_freq ? (PCIMAXFREQ / 64) + : (PCIMINFREQ / 64)); else - return (max? (XTALMAXFREQ/32) : (XTALMINFREQ/32)); + return (max_freq ? (XTALMAXFREQ / 32) + : (XTALMINFREQ / 32)); } else if (si->sb.ccrev < 10) { - div = 4 * (((R_REG(si->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); + div = + 4 * + (((R_REG(si->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> + SCC_CD_SHIFT) + + 1); if (slowclk == SCC_SS_LPO) - return (max? LPOMAXFREQ : LPOMINFREQ); + return (max_freq ? LPOMAXFREQ : LPOMINFREQ); else if (slowclk == SCC_SS_XTAL) - return (max? (XTALMAXFREQ/div) : (XTALMINFREQ/div)); + return (max_freq ? (XTALMAXFREQ / div) + : (XTALMINFREQ / div)); else if (slowclk == SCC_SS_PCI) - return (max? (PCIMAXFREQ/div) : (PCIMINFREQ/div)); + return (max_freq ? (PCIMAXFREQ / div) + : (PCIMINFREQ / div)); else ASSERT(0); } else { /* Chipc rev 10 is InstaClock */ div = R_REG(si->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; div = 4 * (div + 1); - return (max ? XTALMAXFREQ : (XTALMINFREQ/div)); + return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); } return (0); } -static void -BCMINITFN(sb_clkctl_setdelay)(sb_info_t *si, void *chipcregs) -{ - chipcregs_t * cc; +static void BCMINITFN(sb_clkctl_setdelay) (sb_info_t * si, void *chipcregs) { + chipcregs_t *cc; uint slowmaxfreq, pll_delay, slowclk; uint pll_on_delay, fref_sel_delay; @@ -2341,15 +3264,13 @@ BCMINITFN(sb_clkctl_setdelay)(sb_info_t *si, void *chipcregs) pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; - cc = (chipcregs_t *)chipcregs; + cc = (chipcregs_t *) chipcregs; W_REG(si->osh, &cc->pll_on_delay, pll_on_delay); W_REG(si->osh, &cc->fref_sel_delay, fref_sel_delay); } /* initialize power control delay registers */ -void -BCMINITFN(sb_clkctl_init)(sb_t *sbh) -{ +void BCMINITFN(sb_clkctl_init) (sb_t * sbh) { sb_info_t *si; uint origidx; chipcregs_t *cc; @@ -2358,31 +3279,30 @@ BCMINITFN(sb_clkctl_init)(sb_t *sbh) origidx = si->curidx; - if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) + if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL) return; if ((si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev < 2)) W_REG(si->osh, &cc->chipcontrol, - (si->sb.chiprev == 0) ? CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT); + (si->sb.chiprev == + 0) ? CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT); - if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL)) + if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL)) goto done; /* set all Instaclk chip ILP to 1 MHz */ - else if (si->sb.ccrev >= 10) + if (si->sb.ccrev >= 10) SET_REG(si->osh, &cc->system_clk_ctl, SYCC_CD_MASK, - (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); + (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); - sb_clkctl_setdelay(si, (void *)cc); + sb_clkctl_setdelay(si, (void *)(uintptr) cc); -done: + done: sb_setcoreidx(sbh, origidx); } /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */ -uint16 -sb_clkctl_fast_pwrup_delay(sb_t *sbh) -{ +uint16 BCMINITFN(sb_clkctl_fast_pwrup_delay) (sb_t * sbh) { sb_info_t *si; uint origidx; chipcregs_t *cc; @@ -2396,25 +3316,29 @@ sb_clkctl_fast_pwrup_delay(sb_t *sbh) INTR_OFF(si, intr_val); - if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) + if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL) goto done; - if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL)) + if (sbh->cccaps & CC_CAP_PMU) { + fpdelay = sb_pmu_fast_pwrup_delay(sbh, si->osh); + goto done; + } + + if (!(sbh->cccaps & CC_CAP_PWR_CTL)) goto done; slowminfreq = sb_slowclk_freq(si, FALSE); fpdelay = (((R_REG(si->osh, &cc->pll_on_delay) + 2) * 1000000) + - (slowminfreq - 1)) / slowminfreq; + (slowminfreq - 1)) / slowminfreq; -done: + done: sb_setcoreidx(sbh, origidx); INTR_RESTORE(si, intr_val); return (fpdelay); } /* turn primary xtal and/or pll off/on */ -int -sb_clkctl_xtal(sb_t *sbh, uint what, bool on) +int sb_clkctl_xtal(sb_t * sbh, uint what, bool on) { sb_info_t *si; uint32 in, out, outen; @@ -2423,66 +3347,68 @@ sb_clkctl_xtal(sb_t *sbh, uint what, bool on) switch (BUSTYPE(si->sb.bustype)) { + case PCMCIA_BUS: + return (0); - case PCMCIA_BUS: - return (0); - - - case PCI_BUS: + case PCI_BUS: - /* pcie core doesn't have any mapping to control the xtal pu */ - if (PCIE(si)) - return -1; + /* pcie core doesn't have any mapping to control the xtal pu */ + if (PCIE(si)) + return -1; - in = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_IN, sizeof(uint32)); - out = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32)); - outen = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof(uint32)); + in = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_IN, sizeof(uint32)); + out = + OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32)); + outen = + OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN, + sizeof(uint32)); - /* - * Avoid glitching the clock if GPRS is already using it. - * We can't actually read the state of the PLLPD so we infer it - * by the value of XTAL_PU which *is* readable via gpioin. - */ - if (on && (in & PCI_CFG_GPIO_XTAL)) - return (0); + /* + * Avoid glitching the clock if GPRS is already using it. + * We can't actually read the state of the PLLPD so we infer it + * by the value of XTAL_PU which *is* readable via gpioin. + */ + if (on && (in & PCI_CFG_GPIO_XTAL)) + return (0); - if (what & XTAL) - outen |= PCI_CFG_GPIO_XTAL; - if (what & PLL) - outen |= PCI_CFG_GPIO_PLL; - - if (on) { - /* turn primary xtal on */ - if (what & XTAL) { - out |= PCI_CFG_GPIO_XTAL; - if (what & PLL) - out |= PCI_CFG_GPIO_PLL; - OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, - sizeof(uint32), out); - OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, - sizeof(uint32), outen); - OSL_DELAY(XTAL_ON_DELAY); - } + if (what & XTAL) + outen |= PCI_CFG_GPIO_XTAL; + if (what & PLL) + outen |= PCI_CFG_GPIO_PLL; - /* turn pll on */ - if (what & PLL) { - out &= ~PCI_CFG_GPIO_PLL; - OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, - sizeof(uint32), out); - OSL_DELAY(2000); - } - } else { - if (what & XTAL) - out &= ~PCI_CFG_GPIO_XTAL; + if (on) { + /* turn primary xtal on */ + if (what & XTAL) { + out |= PCI_CFG_GPIO_XTAL; if (what & PLL) out |= PCI_CFG_GPIO_PLL; - OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32), out); - OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof(uint32), - outen); + OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, + sizeof(uint32), out); + OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, + sizeof(uint32), outen); + OSL_DELAY(XTAL_ON_DELAY); } - default: - return (-1); + /* turn pll on */ + if (what & PLL) { + out &= ~PCI_CFG_GPIO_PLL; + OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, + sizeof(uint32), out); + OSL_DELAY(2000); + } + } else { + if (what & XTAL) + out &= ~PCI_CFG_GPIO_XTAL; + if (what & PLL) + out |= PCI_CFG_GPIO_PLL; + OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, + sizeof(uint32), out); + OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, + sizeof(uint32), outen); + } + + default: + return (-1); } return (0); @@ -2490,8 +3416,7 @@ sb_clkctl_xtal(sb_t *sbh, uint what, bool on) /* set dynamic clk control mode (forceslow, forcefast, dynamic) */ /* returns true if we are forcing fast clock */ -bool -sb_clkctl_clk(sb_t *sbh, uint mode) +bool sb_clkctl_clk(sb_t * sbh, uint mode) { sb_info_t *si; uint origidx; @@ -2505,7 +3430,6 @@ sb_clkctl_clk(sb_t *sbh, uint mode) if (si->sb.ccrev < 6) return (FALSE); - /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */ ASSERT(si->sb.ccrev != 10); @@ -2517,31 +3441,41 @@ sb_clkctl_clk(sb_t *sbh, uint mode) (BUSTYPE(si->sb.bustype) == SB_BUS) && (si->sb.ccrev >= 10)) goto done; - /* PR32414WAR "Force HT clock on" all the time, no dynamic clk ctl */ - if ((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev <= 1)) + if (FORCEHT_WAR32414(si)) goto done; - cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0); + cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); ASSERT(cc != NULL); - if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL)) + if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL) + && (si->sb.ccrev < 20)) goto done; switch (mode) { - case CLK_FAST: /* force fast (pll) clock */ + case CLK_FAST: /* force fast (pll) clock */ if (si->sb.ccrev < 10) { /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */ sb_clkctl_xtal(&si->sb, XTAL, ON); - SET_REG(si->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); - } else + SET_REG(si->osh, &cc->slow_clk_ctl, + (SCC_XC | SCC_FS | SCC_IP), SCC_IP); + } else if (si->sb.ccrev < 20) { OR_REG(si->osh, &cc->system_clk_ctl, SYCC_HR); + } else { + OR_REG(si->osh, &cc->clk_ctl_st, CCS_FORCEHT); + } + /* wait for the PLL */ - OSL_DELAY(PLL_DELAY); + if (R_REG(si->osh, &cc->capabilities) & CC_CAP_PMU) { + SPINWAIT(((R_REG(si->osh, &cc->clk_ctl_st) & + CCS_HTAVAIL) == 0), PMU_MAX_TRANSITION_DLY); + ASSERT(R_REG(si->osh, &cc->clk_ctl_st) & CCS_HTAVAIL); + } else { + OSL_DELAY(PLL_DELAY); + } break; case CLK_DYNAMIC: /* enable dynamic clock control */ - if (si->sb.ccrev < 10) { scc = R_REG(si->osh, &cc->slow_clk_ctl); scc &= ~(SCC_FS | SCC_IP | SCC_XC); @@ -2552,9 +3486,11 @@ sb_clkctl_clk(sb_t *sbh, uint mode) /* for dynamic control, we have to release our xtal_pu "force on" */ if (scc & SCC_XC) sb_clkctl_xtal(&si->sb, XTAL, OFF); - } else { + } else if (si->sb.ccrev < 20) { /* Instaclock */ AND_REG(si->osh, &cc->system_clk_ctl, ~SYCC_HR); + } else { + AND_REG(si->osh, &cc->clk_ctl_st, ~CCS_FORCEHT); } break; @@ -2562,7 +3498,7 @@ sb_clkctl_clk(sb_t *sbh, uint mode) ASSERT(0); } -done: + done: sb_setcoreidx(sbh, origidx); INTR_RESTORE(si, intr_val); return (mode == CLK_FAST); @@ -2570,50 +3506,124 @@ done: /* register driver interrupt disabling and restoring callback functions */ void -sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn, - void *intrsenabled_fn, void *intr_arg) +sb_register_intr_callback(sb_t * sbh, void *intrsoff_fn, + void *intrsrestore_fn, void *intrsenabled_fn, + void *intr_arg) { sb_info_t *si; si = SB_INFO(sbh); si->intr_arg = intr_arg; - si->intrsoff_fn = (sb_intrsoff_t)intrsoff_fn; - si->intrsrestore_fn = (sb_intrsrestore_t)intrsrestore_fn; - si->intrsenabled_fn = (sb_intrsenabled_t)intrsenabled_fn; + si->intrsoff_fn = (sb_intrsoff_t) intrsoff_fn; + si->intrsrestore_fn = (sb_intrsrestore_t) intrsrestore_fn; + si->intrsenabled_fn = (sb_intrsenabled_t) intrsenabled_fn; /* save current core id. when this function called, the current core * must be the core which provides driver functions(il, et, wl, etc.) */ si->dev_coreid = si->coreid[si->curidx]; } +void sb_deregister_intr_callback(sb_t * sbh) +{ + sb_info_t *si; -int -sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, - uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, - uint8 *pciheader) + si = SB_INFO(sbh); + si->intrsoff_fn = NULL; +} + +#ifdef BCMDBG +/* dump dynamic clock control related registers */ +void sb_clkctl_dump(sb_t * sbh, struct bcmstrbuf *b) { - uint16 vendor = 0xffff, device = 0xffff; - uint core, unit; - uint chip, chippkg; - uint nfunc; - char varname[SB_DEVPATH_BUFSZ + 8]; - uint8 class, subclass, progif; - char devpath[SB_DEVPATH_BUFSZ]; - uint8 header; + sb_info_t *si; + chipcregs_t *cc; + uint origidx; + uint intr_val = 0; - core = sb_coreid(sbh); - unit = sb_coreunit(sbh); + si = SB_INFO(sbh); - chip = sb_chip(sbh); - chippkg = sb_chippkg(sbh); + INTR_OFF(si, intr_val); - progif = 0; - header = PCI_HEADER_NORMAL; + origidx = si->curidx; + + if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL) { + INTR_RESTORE(si, intr_val); + return; + } + + if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL)) + goto done; + + bcm_bprintf(b, "pll_on_delay 0x%x fref_sel_delay 0x%x ", + cc->pll_on_delay, cc->fref_sel_delay); + if ((si->sb.ccrev >= 6) && (si->sb.ccrev < 10)) + bcm_bprintf(b, "slow_clk_ctl 0x%x ", cc->slow_clk_ctl); + if (si->sb.ccrev >= 10) { + bcm_bprintf(b, "system_clk_ctl 0x%x ", cc->system_clk_ctl); + bcm_bprintf(b, "clkstatestretch 0x%x ", cc->clkstatestretch); + } + if (BUSTYPE(si->sb.bustype) == PCI_BUS) + bcm_bprintf(b, "gpioout 0x%x gpioouten 0x%x ", + OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, + sizeof(uint32)), + OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN, + sizeof(uint32))); + bcm_bprintf(b, "\n"); + + done: + sb_setcoreidx(sbh, origidx); + INTR_RESTORE(si, intr_val); +} +#endif /* BCMDBG */ + +uint16 BCMINITFN(sb_d11_devid) (sb_t * sbh) { + sb_info_t *si = SB_INFO(sbh); + uint16 device; + +#if defined(BCM4328) + /* Fix device id for dual band BCM4328 */ + if (sbh->chip == BCM4328_CHIP_ID && + (sbh->chippkg == BCM4328USBDUAL_PKG_ID + || sbh->chippkg == BCM4328SDIODUAL_PKG_ID)) + device = BCM4328_D11DUAL_ID; + else +#endif /* BCM4328 */ + /* Let an nvram variable with devpath override devid */ + if ((device = (uint16) sb_getdevpathintvar(sbh, "devid")) != 0) ; + /* Get devid from OTP/SPROM depending on where the SROM is read */ + else if ((device = (uint16) getintvar(si->vars, "devid")) != 0) ; + /* + * no longer support wl0id, but keep the code + * here for backward compatibility. + */ + else if ((device = (uint16) getintvar(si->vars, "wl0id")) != 0) ; + /* Chip specific conversion */ + else if (sbh->chip == BCM4712_CHIP_ID) { + if (sbh->chippkg == BCM4712SMALL_PKG_ID) + device = BCM4306_D11G_ID; + else + device = BCM4306_D11DUAL_ID; + } + /* ignore it */ + else + device = 0xffff; + + return device; +} + +int +BCMINITFN(sb_corepciid) (sb_t * sbh, uint func, uint16 * pcivendor, + uint16 * pcidevice, uint8 * pciclass, + uint8 * pcisubclass, uint8 * pciprogif, + uint8 * pciheader) { + uint16 vendor = 0xffff, device = 0xffff; + uint8 class, subclass, progif = 0; + uint8 header = PCI_HEADER_NORMAL; + uint32 core = sb_coreid(sbh); /* Verify whether the function exists for the core */ - nfunc = (core == SB_USB20H) ? 2 : 1; - if (func >= nfunc) - return BCME_ERROR; + if (func >= (uint) (core == SB_USB20H ? 2 : 1)) + return -1; /* Known vendor translations */ switch (sb_corevendor(sbh)) { @@ -2621,7 +3631,7 @@ sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, vendor = VENDOR_BROADCOM; break; default: - return BCME_ERROR; + return -1; } /* Determine class based on known core codes */ @@ -2645,20 +3655,20 @@ sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, case SB_MEMC: class = PCI_CLASS_MEMORY; subclass = PCI_MEMORY_RAM; - device = (uint16)core; + device = (uint16) core; break; case SB_PCI: case SB_PCIE: class = PCI_CLASS_BRIDGE; subclass = PCI_BRIDGE_PCI; - device = (uint16)core; + device = (uint16) core; header = PCI_HEADER_BRIDGE; break; case SB_MIPS: case SB_MIPS33: class = PCI_CLASS_CPU; subclass = PCI_CPU_MIPS; - device = (uint16)core; + device = (uint16) core; break; case SB_CODEC: class = PCI_CLASS_COMM; @@ -2668,31 +3678,21 @@ sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, case SB_USB: class = PCI_CLASS_SERIAL; subclass = PCI_SERIAL_USB; - progif = 0x10; /* OHCI */ + progif = 0x10; /* OHCI */ device = BCM47XX_USB_ID; break; case SB_USB11H: class = PCI_CLASS_SERIAL; subclass = PCI_SERIAL_USB; - progif = 0x10; /* OHCI */ + progif = 0x10; /* OHCI */ device = BCM47XX_USBH_ID; break; case SB_USB20H: class = PCI_CLASS_SERIAL; subclass = PCI_SERIAL_USB; - progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */ + progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */ device = BCM47XX_USB20H_ID; - header = 0x80; /* multifunction */ - break; - case SB_USB11D: - class = PCI_CLASS_SERIAL; - subclass = PCI_SERIAL_USB; - device = BCM47XX_USBD_ID; - break; - case SB_USB20D: - class = PCI_CLASS_SERIAL; - subclass = PCI_SERIAL_USB; - device = BCM47XX_USB20D_ID; + header = 0x80; /* multifunction */ break; case SB_IPSEC: class = PCI_CLASS_CRYPT; @@ -2708,33 +3708,7 @@ sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, case SB_CC: class = PCI_CLASS_MEMORY; subclass = PCI_MEMORY_FLASH; - device = (uint16)core; - break; - case SB_D11: - class = PCI_CLASS_NET; - subclass = PCI_NET_OTHER; - /* Let nvram variable override core ID */ - sb_devpath(sbh, devpath, sizeof(devpath)); - sprintf(varname, "%sdevid", devpath); - if ((device = (uint16)getintvar(NULL, varname))) - break; - /* - * no longer support wl%did, but keep the code - * here for backward compatibility. - */ - sprintf(varname, "wl%did", unit); - if ((device = (uint16)getintvar(NULL, varname))) - break; - /* Chip specific conversion */ - if (chip == BCM4712_CHIP_ID) { - if (chippkg == BCM4712SMALL_PKG_ID) - device = BCM4306_D11G_ID; - else - device = BCM4306_D11DUAL_ID; - break; - } - /* ignore it */ - device = 0xffff; + device = (uint16) core; break; case SB_SATAXOR: class = PCI_CLASS_XOR; @@ -2746,10 +3720,25 @@ sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, subclass = PCI_DASDI_IDE; device = BCM47XX_ATA100_ID; break; + case SB_USB11D: + class = PCI_CLASS_SERIAL; + subclass = PCI_SERIAL_USB; + device = BCM47XX_USBD_ID; + break; + case SB_USB20D: + class = PCI_CLASS_SERIAL; + subclass = PCI_SERIAL_USB; + device = BCM47XX_USB20D_ID; + break; + case SB_D11: + class = PCI_CLASS_NET; + subclass = PCI_NET_OTHER; + device = sb_d11_devid(sbh); + break; default: class = subclass = progif = 0xff; - device = (uint16)core; + device = (uint16) core; break; } @@ -2763,25 +3752,69 @@ sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, return 0; } +/* use the mdio interface to read from mdio slaves */ +static int +sb_pcie_mdioread(sb_info_t * si, uint physmedia, uint regaddr, uint * regval) +{ + uint mdiodata; + uint i = 0; + sbpcieregs_t *pcieregs; + + pcieregs = (sbpcieregs_t *) sb_setcoreidx(&si->sb, si->sb.buscoreidx); + ASSERT(pcieregs); + /* enable mdio access to SERDES */ + W_REG(si->osh, (&pcieregs->mdiocontrol), + MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); + + mdiodata = MDIODATA_START | MDIODATA_READ | + (physmedia << MDIODATA_DEVADDR_SHF) | + (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA; + + W_REG(si->osh, &pcieregs->mdiodata, mdiodata); + + PR28829_DELAY(); + + /* retry till the transaction is complete */ + while (i < 10) { + if (R_REG(si->osh, &(pcieregs->mdiocontrol)) & + MDIOCTL_ACCESS_DONE) { + PR28829_DELAY(); + *regval = + (R_REG(si->osh, &(pcieregs->mdiodata)) & + MDIODATA_MASK); + /* Disable mdio access to SERDES */ + W_REG(si->osh, (&pcieregs->mdiocontrol), 0); + return 0; + } + OSL_DELAY(1000); + i++; + } + + SB_ERROR(("sb_pcie_mdioread: timed out\n")); + /* Disable mdio access to SERDES */ + W_REG(si->osh, (&pcieregs->mdiocontrol), 0); + return 1; +} /* use the mdio interface to write to mdio slaves */ static int -sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint regaddr, uint val) +sb_pcie_mdiowrite(sb_info_t * si, uint physmedia, uint regaddr, uint val) { uint mdiodata; uint i = 0; sbpcieregs_t *pcieregs; - pcieregs = (sbpcieregs_t*) sb_setcoreidx(&si->sb, si->sb.buscoreidx); + pcieregs = (sbpcieregs_t *) sb_setcoreidx(&si->sb, si->sb.buscoreidx); ASSERT(pcieregs); /* enable mdio access to SERDES */ - W_REG(si->osh, (&pcieregs->mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); + W_REG(si->osh, (&pcieregs->mdiocontrol), + MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); mdiodata = MDIODATA_START | MDIODATA_WRITE | - (physmedia << MDIODATA_DEVADDR_SHF) | - (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val; + (physmedia << MDIODATA_DEVADDR_SHF) | + (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val; W_REG(si->osh, (&pcieregs->mdiodata), mdiodata); @@ -2789,7 +3822,8 @@ sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint regaddr, uint val) /* retry till the transaction is complete */ while (i < 10) { - if (R_REG(si->osh, &(pcieregs->mdiocontrol)) & MDIOCTL_ACCESS_DONE) { + if (R_REG(si->osh, &(pcieregs->mdiocontrol)) & + MDIOCTL_ACCESS_DONE) { /* Disable mdio access to SERDES */ W_REG(si->osh, (&pcieregs->mdiocontrol), 0); return 0; @@ -2801,48 +3835,45 @@ sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint regaddr, uint val) SB_ERROR(("sb_pcie_mdiowrite: timed out\n")); /* Disable mdio access to SERDES */ W_REG(si->osh, (&pcieregs->mdiocontrol), 0); - ASSERT(0); return 1; } /* indirect way to read pcie config regs */ -uint -sb_pcie_readreg(void *sb, void* arg1, uint offset) +uint sb_pcie_readreg(void *sb, void *arg1, uint offset) { sb_info_t *si; - sb_t *sbh; + sb_t *sbh; uint retval = 0xFFFFFFFF; sbpcieregs_t *pcieregs; uint addrtype; - sbh = (sb_t *)sb; + sbh = (sb_t *) sb; si = SB_INFO(sbh); ASSERT(PCIE(si)); - pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); + pcieregs = (sbpcieregs_t *) sb_setcore(sbh, SB_PCIE, 0); ASSERT(pcieregs); - addrtype = (uint)((uintptr)arg1); + addrtype = (uint) ((uintptr) arg1); switch (addrtype) { - case PCIE_CONFIGREGS: - W_REG(si->osh, (&pcieregs->configaddr), offset); - retval = R_REG(si->osh, &(pcieregs->configdata)); - break; - case PCIE_PCIEREGS: - W_REG(si->osh, &(pcieregs->pcieaddr), offset); - retval = R_REG(si->osh, &(pcieregs->pciedata)); - break; - default: - ASSERT(0); - break; + case PCIE_CONFIGREGS: + W_REG(si->osh, (&pcieregs->configaddr), offset); + retval = R_REG(si->osh, &(pcieregs->configdata)); + break; + case PCIE_PCIEREGS: + W_REG(si->osh, &(pcieregs->pcieindaddr), offset); + retval = R_REG(si->osh, &(pcieregs->pcieinddata)); + break; + default: + ASSERT(0); + break; } return retval; } /* indirect way to write pcie config/mdio/pciecore regs */ -uint -sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val) +uint sb_pcie_writereg(sb_t * sbh, void *arg1, uint offset, uint val) { sb_info_t *si; sbpcieregs_t *pcieregs; @@ -2851,74 +3882,119 @@ sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val) si = SB_INFO(sbh); ASSERT(PCIE(si)); - pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); + pcieregs = (sbpcieregs_t *) sb_setcore(sbh, SB_PCIE, 0); ASSERT(pcieregs); - addrtype = (uint)((uintptr)arg1); + addrtype = (uint) ((uintptr) arg1); switch (addrtype) { - case PCIE_CONFIGREGS: - W_REG(si->osh, (&pcieregs->configaddr), offset); - W_REG(si->osh, (&pcieregs->configdata), val); - break; - case PCIE_PCIEREGS: - W_REG(si->osh, (&pcieregs->pcieaddr), offset); - W_REG(si->osh, (&pcieregs->pciedata), val); - break; - default: - ASSERT(0); - break; + case PCIE_CONFIGREGS: + W_REG(si->osh, (&pcieregs->configaddr), offset); + W_REG(si->osh, (&pcieregs->configdata), val); + break; + case PCIE_PCIEREGS: + W_REG(si->osh, (&pcieregs->pcieindaddr), offset); + W_REG(si->osh, (&pcieregs->pcieinddata), val); + break; + default: + ASSERT(0); + break; } return 0; } /* Build device path. Support SB, PCI, and JTAG for now. */ -int -sb_devpath(sb_t *sbh, char *path, int size) -{ +int BCMINITFN(sb_devpath) (sb_t * sbh, char *path, int size) { + int slen; ASSERT(path); ASSERT(size >= SB_DEVPATH_BUFSZ); + if (!path || size <= 0) + return -1; + switch (BUSTYPE((SB_INFO(sbh))->sb.bustype)) { case SB_BUS: case JTAG_BUS: - sprintf(path, "sb/%u/", sb_coreidx(sbh)); + slen = snprintf(path, (size_t) size, "sb/%u/", sb_coreidx(sbh)); break; case PCI_BUS: ASSERT((SB_INFO(sbh))->osh); - sprintf(path, "pci/%u/%u/", OSL_PCI_BUS((SB_INFO(sbh))->osh), - OSL_PCI_SLOT((SB_INFO(sbh))->osh)); + slen = snprintf(path, (size_t) size, "pci/%u/%u/", + OSL_PCI_BUS((SB_INFO(sbh))->osh), + OSL_PCI_SLOT((SB_INFO(sbh))->osh)); break; case PCMCIA_BUS: SB_ERROR(("sb_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n")); SB_ERROR(("sb_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n")); - sprintf(path, "pc/%u/%u/", 1, 1); - break; - case SDIO_BUS: - SB_ERROR(("sb_devpath: device 0 assumed\n")); - sprintf(path, "sd/%u/", sb_coreidx(sbh)); + slen = snprintf(path, (size_t) size, "pc/1/1/"); break; default: + slen = -1; ASSERT(0); break; } + if (slen < 0 || slen >= size) { + path[0] = '\0'; + return -1; + } + return 0; } +/* Get a variable, but only if it has a devpath prefix */ +char *BCMINITFN(sb_getdevpathvar) (sb_t * sbh, const char *name) { + char varname[SB_DEVPATH_BUFSZ + 32]; + + sb_devpathvar(sbh, varname, sizeof(varname), name); + + return (getvar(NULL, varname)); +} + +/* Get a variable, but only if it has a devpath prefix */ +int BCMINITFN(sb_getdevpathintvar) (sb_t * sbh, const char *name) { + char varname[SB_DEVPATH_BUFSZ + 32]; + + sb_devpathvar(sbh, varname, sizeof(varname), name); + + return (getintvar(NULL, varname)); +} + +/* Concatenate the dev path with a varname into the given 'var' buffer + * and return the 'var' pointer. + * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned. + * On overflow, the first char will be set to '\0'. + */ +static char *BCMINITFN(sb_devpathvar) (sb_t * sbh, char *var, int len, + const char *name) { + uint path_len; + + if (!var || len <= 0) + return var; + + if (sb_devpath(sbh, var, len) == 0) { + path_len = strlen(var); + + if (strlen(name) + 1 > (uint) (len - path_len)) + var[0] = '\0'; + else + strncpy(var + path_len, name, len - path_len - 1); + } + + return var; +} + /* * Fixup SROMless PCI device's configuration. * The current core may be changed upon return. */ -static int -sb_pci_fixcfg(sb_info_t *si) +static int sb_pci_fixcfg(sb_info_t * si) { uint origidx, pciidx; sbpciregs_t *pciregs; - sbpcieregs_t *pcieregs; + sbpcieregs_t *pcieregs = NULL; uint16 val16, *reg16; - char name[SB_DEVPATH_BUFSZ+16], *value; - char devpath[SB_DEVPATH_BUFSZ]; + uint32 w; ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS); @@ -2928,11 +4004,11 @@ sb_pci_fixcfg(sb_info_t *si) /* check 'pi' is correct and fix it if not */ if (si->sb.buscoretype == SB_PCIE) { - pcieregs = (sbpcieregs_t *)sb_setcore(&si->sb, SB_PCIE, 0); + pcieregs = (sbpcieregs_t *) sb_setcore(&si->sb, SB_PCIE, 0); ASSERT(pcieregs); reg16 = &pcieregs->sprom[SRSH_PI_OFFSET]; } else if (si->sb.buscoretype == SB_PCI) { - pciregs = (sbpciregs_t *)sb_setcore(&si->sb, SB_PCI, 0); + pciregs = (sbpciregs_t *) sb_setcore(&si->sb, SB_PCI, 0); ASSERT(pciregs); reg16 = &pciregs->sprom[SRSH_PI_OFFSET]; } else { @@ -2941,59 +4017,59 @@ sb_pci_fixcfg(sb_info_t *si) } pciidx = sb_coreidx(&si->sb); val16 = R_REG(si->osh, reg16); - if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) { - val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK); + if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16) pciidx) { + val16 = + (uint16) (pciidx << SRSH_PI_SHIFT) | (val16 & + ~SRSH_PI_MASK); W_REG(si->osh, reg16, val16); } - /* restore the original index */ - sb_setcoreidx(&si->sb, origidx); + if (PCIE_ASPMWARS(si)) { + w = sb_pcie_readreg((void *)(uintptr) & si->sb, + (void *)PCIE_PCIEREGS, PCIE_PLP_STATUSREG); - /* - * Fixup bar0window in PCI config space to make the core indicated - * by the nvram variable the current core. - * !Do it last, it may change the current core! - */ - if (sb_devpath(&si->sb, devpath, sizeof(devpath))) - return -1; - sprintf(name, "%sb0w", devpath); - if ((value = getvar(NULL, name))) { - OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32), - bcm_strtoul(value, NULL, 16)); - /* update curidx since the current core is changed */ - si->curidx = _sb_coreidx(si); - if (si->curidx == BADIDX) { - SB_ERROR(("sb_pci_fixcfg: bad core index\n")); - return -1; + /* Detect the current polarity at attach and force that polarity and + * disable changing the polarity + */ + if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) { + si->pcie_polarity = (SERDES_RX_CTRL_FORCE); + } else { + si->pcie_polarity = (SERDES_RX_CTRL_FORCE | + SERDES_RX_CTRL_POLARITY); } - } - return 0; -} + w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset, + sizeof(uint32)); + if (w & PCIE_CLKREQ_ENAB) { + reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET]; + val16 = R_REG(si->osh, reg16); + /* if clockreq is not advertized clkreq should not be enabled */ + if (!(val16 & SRSH_CLKREQ_ENB)) + SB_ERROR(("WARNING: CLK REQ enabled already 0x%x\n", w)); + } -static uint -sb_chipc_capability(sb_t *sbh) -{ - sb_info_t *si; + sb_war43448(&si->sb); - si = SB_INFO(sbh); + sb_war42767(&si->sb); + + } + + /* restore the original index */ + sb_setcoreidx(&si->sb, origidx); - /* Make sure that there is ChipCommon core present */ - if (si->coreid[SB_CC_IDX] == SB_CC) - return (sb_corereg(si, SB_CC_IDX, OFFSETOF(chipcregs_t, capabilities), - 0, 0)); return 0; } /* Return ADDR64 capability of the backplane */ -bool -sb_backplane64(sb_t *sbh) +bool sb_backplane64(sb_t * sbh) { - return ((sb_chipc_capability(sbh) & CAP_BKPLN64) != 0); + sb_info_t *si; + + si = SB_INFO(sbh); + return ((si->sb.cccaps & CC_CAP_BKPLN64) != 0); } -void -sb_btcgpiowar(sb_t *sbh) +void sb_btcgpiowar(sb_t * sbh) { sb_info_t *si; uint origidx; @@ -3004,7 +4080,7 @@ sb_btcgpiowar(sb_t *sbh) /* Make sure that there is ChipCommon core present && * UART_TX is strapped to 1 */ - if (!(sb_chipc_capability(sbh) & CAP_UARTGPIO)) + if (!(si->sb.cccaps & CC_CAP_UARTGPIO)) return; /* sb_corereg cannot be used as we have to guarantee 8-bit read/writes */ @@ -3012,13 +4088,11 @@ sb_btcgpiowar(sb_t *sbh) origidx = sb_coreidx(sbh); - cc = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0); - if (cc == NULL) - goto end; + cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); + ASSERT(cc); W_REG(si->osh, &cc->uart0mcr, R_REG(si->osh, &cc->uart0mcr) | 0x04); -end: /* restore the original index */ sb_setcoreidx(sbh, origidx); @@ -3026,8 +4100,7 @@ end: } /* check if the device is removed */ -bool -sb_deviceremoved(sb_t *sbh) +bool sb_deviceremoved(sb_t * sbh) { uint32 w; sb_info_t *si; @@ -3048,10 +4121,9 @@ sb_deviceremoved(sb_t *sbh) return FALSE; } +#if 0 /* Return the RAM size of the SOCRAM core */ -uint32 -sb_socram_size(sb_t *sbh) -{ +uint32 BCMINITFN(sb_socram_size) (sb_t * sbh) { sb_info_t *si; uint origidx; uint intr_val = 0; @@ -3080,24 +4152,29 @@ sb_socram_size(sb_t *sbh) coreinfo = R_REG(si->osh, ®s->coreinfo); /* Calculate size from coreinfo based on rev */ - switch (corerev) { - case 0: + if (corerev == 0) memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK)); - break; - default: /* rev >= 1 */ + else if (corerev < 3) { memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK)); memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; - break; + } else { + uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; + uint bsz = (coreinfo & SRCI_SRBSZ_MASK); + uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; + if (lss != 0) + nb--; + memsize = nb * (1 << (bsz + SR_BSZ_BASE)); + if (lss != 0) + memsize += (1 << ((lss - 1) + SR_BSZ_BASE)); } - /* Return to previous state and core */ if (!wasup) sb_core_disable(sbh, 0); sb_setcoreidx(sbh, origidx); -done: + done: INTR_RESTORE(si, intr_val); return memsize; } - +#endif diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/setup.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/setup.c index 819a48d255..00c4d9054c 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/setup.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/setup.c @@ -48,7 +48,6 @@ #include <typedefs.h> #include <osl.h> #include <sbutils.h> -#include <bcmutils.h> #include <bcmnvram.h> #include <sbhndmips.h> #include <hndmips.h> @@ -170,7 +169,7 @@ brcm_setup(void) char *value; /* Get global SB handle */ - sbh = sb_kattach(); + sbh = sb_kattach(SB_OSH); /* Initialize clocks and interrupts */ sb_mips_init(sbh, SBMIPS_VIRTIRQ_BASE); diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sflash.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sflash.c deleted file mode 100644 index c1a5ed551e..0000000000 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sflash.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Broadcom SiliconBackplane chipcommon serial flash interface - * - * Copyright 2006, Broadcom Corporation - * All Rights Reserved. - * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * - * $Id: sflash.c,v 1.1.1.13 2006/02/27 03:43:16 honor Exp $ - */ - -#include <osl.h> -#include <typedefs.h> -#include <sbconfig.h> -#include <sbchipc.h> -#include <mipsinc.h> -#include <bcmutils.h> -#include <bcmdevs.h> -#include <sflash.h> - -/* Private global state */ -static struct sflash sflash; - -/* Issue a serial flash command */ -static INLINE void -sflash_cmd(chipcregs_t *cc, uint opcode) -{ - W_REG(NULL, &cc->flashcontrol, SFLASH_START | opcode); - while (R_REG(NULL, &cc->flashcontrol) & SFLASH_BUSY); -} - -/* Initialize serial flash access */ -struct sflash * -sflash_init(chipcregs_t *cc) -{ - uint32 id, id2; - - bzero(&sflash, sizeof(sflash)); - - sflash.type = R_REG(NULL, &cc->capabilities) & CAP_FLASH_MASK; - - switch (sflash.type) { - case SFLASH_ST: - /* Probe for ST chips */ - sflash_cmd(cc, SFLASH_ST_DP); - sflash_cmd(cc, SFLASH_ST_RES); - id = R_REG(NULL, &cc->flashdata); - switch (id) { - case 0x11: - /* ST M25P20 2 Mbit Serial Flash */ - sflash.blocksize = 64 * 1024; - sflash.numblocks = 4; - break; - case 0x12: - /* ST M25P40 4 Mbit Serial Flash */ - sflash.blocksize = 64 * 1024; - sflash.numblocks = 8; - break; - case 0x13: - /* ST M25P80 8 Mbit Serial Flash */ - sflash.blocksize = 64 * 1024; - sflash.numblocks = 16; - break; - case 0x14: - /* ST M25P16 16 Mbit Serial Flash */ - sflash.blocksize = 64 * 1024; - sflash.numblocks = 32; - break; - case 0x15: - /* ST M25P32 32 Mbit Serial Flash */ - sflash.blocksize = 64 * 1024; - sflash.numblocks = 64; - break; - case 0x16: - /* ST M25P64 64 Mbit Serial Flash */ - sflash.blocksize = 64 * 1024; - sflash.numblocks = 128; - break; - case 0xbf: - W_REG(NULL, &cc->flashaddress, 1); - sflash_cmd(cc, SFLASH_ST_RES); - id2 = R_REG(NULL, &cc->flashdata); - if (id2 == 0x44) { - /* SST M25VF80 4 Mbit Serial Flash */ - sflash.blocksize = 64 * 1024; - sflash.numblocks = 8; - } - break; - } - break; - - case SFLASH_AT: - /* Probe for Atmel chips */ - sflash_cmd(cc, SFLASH_AT_STATUS); - id = R_REG(NULL, &cc->flashdata) & 0x3c; - switch (id) { - case 0xc: - /* Atmel AT45DB011 1Mbit Serial Flash */ - sflash.blocksize = 256; - sflash.numblocks = 512; - break; - case 0x14: - /* Atmel AT45DB021 2Mbit Serial Flash */ - sflash.blocksize = 256; - sflash.numblocks = 1024; - break; - case 0x1c: - /* Atmel AT45DB041 4Mbit Serial Flash */ - sflash.blocksize = 256; - sflash.numblocks = 2048; - break; - case 0x24: - /* Atmel AT45DB081 8Mbit Serial Flash */ - sflash.blocksize = 256; - sflash.numblocks = 4096; - break; - case 0x2c: - /* Atmel AT45DB161 16Mbit Serial Flash */ - sflash.blocksize = 512; - sflash.numblocks = 4096; - break; - case 0x34: - /* Atmel AT45DB321 32Mbit Serial Flash */ - sflash.blocksize = 512; - sflash.numblocks = 8192; - break; - case 0x3c: - /* Atmel AT45DB642 64Mbit Serial Flash */ - sflash.blocksize = 1024; - sflash.numblocks = 8192; - break; - } - break; - } - - sflash.size = sflash.blocksize * sflash.numblocks; - return sflash.size ? &sflash : NULL; -} - -/* Read len bytes starting at offset into buf. Returns number of bytes read. */ -int -sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf) -{ - int cnt; - uint32 *from, *to; - - if (!len) - return 0; - - if ((offset + len) > sflash.size) - return -22; - - if ((len >= 4) && (offset & 3)) - cnt = 4 - (offset & 3); - else if ((len >= 4) && ((uint32)buf & 3)) - cnt = 4 - ((uint32)buf & 3); - else - cnt = len; - - from = (uint32 *)KSEG1ADDR(SB_FLASH2 + offset); - to = (uint32 *)buf; - - if (cnt < 4) { - bcopy(from, to, cnt); - return cnt; - } - - while (cnt >= 4) { - *to++ = *from++; - cnt -= 4; - } - - return (len - cnt); -} - -/* Poll for command completion. Returns zero when complete. */ -int -sflash_poll(chipcregs_t *cc, uint offset) -{ - if (offset >= sflash.size) - return -22; - - switch (sflash.type) { - case SFLASH_ST: - /* Check for ST Write In Progress bit */ - sflash_cmd(cc, SFLASH_ST_RDSR); - return R_REG(NULL, &cc->flashdata) & SFLASH_ST_WIP; - case SFLASH_AT: - /* Check for Atmel Ready bit */ - sflash_cmd(cc, SFLASH_AT_STATUS); - return !(R_REG(NULL, &cc->flashdata) & SFLASH_AT_READY); - } - - return 0; -} - -/* Write len bytes starting at offset into buf. Returns number of bytes - * written. Caller should poll for completion. - */ -int -sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf) -{ - struct sflash *sfl; - int ret = 0; - bool is4712b0; - uint32 page, byte, mask; - - if (!len) - return 0; - - if ((offset + len) > sflash.size) - return -22; - - sfl = &sflash; - switch (sfl->type) { - case SFLASH_ST: - mask = R_REG(NULL, &cc->chipid); - is4712b0 = (((mask & CID_ID_MASK) == BCM4712_CHIP_ID) && - ((mask & CID_REV_MASK) == (3 << CID_REV_SHIFT))); - /* Enable writes */ - sflash_cmd(cc, SFLASH_ST_WREN); - if (is4712b0) { - mask = 1 << 14; - W_REG(NULL, &cc->flashaddress, offset); - W_REG(NULL, &cc->flashdata, *buf++); - /* Set chip select */ - OR_REG(NULL, &cc->gpioout, mask); - /* Issue a page program with the first byte */ - sflash_cmd(cc, SFLASH_ST_PP); - ret = 1; - offset++; - len--; - while (len > 0) { - if ((offset & 255) == 0) { - /* Page boundary, drop cs and return */ - AND_REG(NULL, &cc->gpioout, ~mask); - if (!sflash_poll(cc, offset)) { - /* Flash rejected command */ - return -11; - } - return ret; - } else { - /* Write single byte */ - sflash_cmd(cc, *buf++); - } - ret++; - offset++; - len--; - } - /* All done, drop cs if needed */ - if ((offset & 255) != 1) { - /* Drop cs */ - AND_REG(NULL, &cc->gpioout, ~mask); - if (!sflash_poll(cc, offset)) { - /* Flash rejected command */ - return -12; - } - } - } else { - ret = 1; - W_REG(NULL, &cc->flashaddress, offset); - W_REG(NULL, &cc->flashdata, *buf); - /* Page program */ - sflash_cmd(cc, SFLASH_ST_PP); - } - break; - case SFLASH_AT: - mask = sfl->blocksize - 1; - page = (offset & ~mask) << 1; - byte = offset & mask; - /* Read main memory page into buffer 1 */ - if (byte || (len < sfl->blocksize)) { - W_REG(NULL, &cc->flashaddress, page); - sflash_cmd(cc, SFLASH_AT_BUF1_LOAD); - /* 250 us for AT45DB321B */ - SPINWAIT(sflash_poll(cc, offset), 1000); - ASSERT(!sflash_poll(cc, offset)); - } - /* Write into buffer 1 */ - for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) { - W_REG(NULL, &cc->flashaddress, byte++); - W_REG(NULL, &cc->flashdata, *buf++); - sflash_cmd(cc, SFLASH_AT_BUF1_WRITE); - } - /* Write buffer 1 into main memory page */ - W_REG(NULL, &cc->flashaddress, page); - sflash_cmd(cc, SFLASH_AT_BUF1_PROGRAM); - break; - } - - return ret; -} - -/* Erase a region. Returns number of bytes scheduled for erasure. - * Caller should poll for completion. - */ -int -sflash_erase(chipcregs_t *cc, uint offset) -{ - struct sflash *sfl; - - if (offset >= sflash.size) - return -22; - - sfl = &sflash; - switch (sfl->type) { - case SFLASH_ST: - sflash_cmd(cc, SFLASH_ST_WREN); - W_REG(NULL, &cc->flashaddress, offset); - sflash_cmd(cc, SFLASH_ST_SE); - return sfl->blocksize; - case SFLASH_AT: - W_REG(NULL, &cc->flashaddress, offset << 1); - sflash_cmd(cc, SFLASH_AT_PAGE_ERASE); - return sfl->blocksize; - } - - return 0; -} - -/* - * writes the appropriate range of flash, a NULL buf simply erases - * the region of flash - */ -int -sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf) -{ - struct sflash *sfl; - uchar *block = NULL, *cur_ptr, *blk_ptr; - uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder; - uint blk_offset, blk_len, copied; - int bytes, ret = 0; - - /* Check address range */ - if (len <= 0) - return 0; - - sfl = &sflash; - if ((offset + len) > sfl->size) - return -1; - - blocksize = sfl->blocksize; - mask = blocksize - 1; - - /* Allocate a block of mem */ - if (!(block = MALLOC(NULL, blocksize))) - return -1; - - while (len) { - /* Align offset */ - cur_offset = offset & ~mask; - cur_length = blocksize; - cur_ptr = block; - - remainder = blocksize - (offset & mask); - if (len < remainder) - cur_retlen = len; - else - cur_retlen = remainder; - - /* buf == NULL means erase only */ - if (buf) { - /* Copy existing data into holding block if necessary */ - if ((offset & mask) || (len < blocksize)) { - blk_offset = cur_offset; - blk_len = cur_length; - blk_ptr = cur_ptr; - - /* Copy entire block */ - while (blk_len) { - copied = sflash_read(cc, blk_offset, blk_len, blk_ptr); - blk_offset += copied; - blk_len -= copied; - blk_ptr += copied; - } - } - - /* Copy input data into holding block */ - memcpy(cur_ptr + (offset & mask), buf, cur_retlen); - } - - /* Erase block */ - if ((ret = sflash_erase(cc, (uint) cur_offset)) < 0) - goto done; - while (sflash_poll(cc, (uint) cur_offset)); - - /* buf == NULL means erase only */ - if (!buf) { - offset += cur_retlen; - len -= cur_retlen; - continue; - } - - /* Write holding block */ - while (cur_length > 0) { - if ((bytes = sflash_write(cc, - (uint) cur_offset, - (uint) cur_length, - (uchar *) cur_ptr)) < 0) { - ret = bytes; - goto done; - } - while (sflash_poll(cc, (uint) cur_offset)); - cur_offset += bytes; - cur_length -= bytes; - cur_ptr += bytes; - } - - offset += cur_retlen; - len -= cur_retlen; - buf += cur_retlen; - } - - ret = len; -done: - if (block) - MFREE(NULL, block, blocksize); - return ret; -} diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/time.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/time.c index 9c502be580..03d5c85651 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/time.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/time.c @@ -23,11 +23,12 @@ #include <osl.h> #include <bcmnvram.h> #include <sbconfig.h> -#include <sbextif.h> #include <sbutils.h> +#include <sbchipc.h> #include <hndmips.h> #include <mipsinc.h> #include <hndcpu.h> +#include <bcmdevs.h> /* Global SB handle */ extern void *bcm947xx_sbh; @@ -39,13 +40,11 @@ extern spinlock_t bcm947xx_sbh_lock; extern int panic_timeout; static int watchdog = 0; -static u8 *mcr = NULL; void __init bcm947xx_time_init(void) { unsigned int hz; - extifregs_t *eir; /* * Use deterministic values for initial counter interrupt @@ -83,8 +82,13 @@ bcm947xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) timer_interrupt(irq, dev_id, regs); /* Set the watchdog timer to reset after the specified number of ms */ - if (watchdog > 0) - sb_watchdog(sbh, WATCHDOG_CLOCK / 1000 * watchdog); + if (watchdog > 0) { + if (sb_chip(sbh) == BCM5354_CHIP_ID) + sb_watchdog(sbh, WATCHDOG_CLOCK_5354 / 1000 * watchdog); + else + sb_watchdog(sbh, WATCHDOG_CLOCK / 1000 * watchdog); + } + } static struct irqaction bcm947xx_timer_irqaction = { diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/utils.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/utils.c new file mode 100644 index 0000000000..418671d7f3 --- /dev/null +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/utils.c @@ -0,0 +1,105 @@ +/* + * Driver O/S-independent utility routines + * + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id$ + */ + +#include <typedefs.h> +#include <bcmdefs.h> +#include <stdarg.h> +#include <osl.h> +#include <sbutils.h> +#include <bcmendian.h> +#include "utils.h" + +/******************************************************************************* + * crc8 + * + * Computes a crc8 over the input data using the polynomial: + * + * x^8 + x^7 +x^6 + x^4 + x^2 + 1 + * + * The caller provides the initial value (either CRC8_INIT_VALUE + * or the previous returned value) to allow for processing of + * discontiguous blocks of data. When generating the CRC the + * caller is responsible for complementing the final return value + * and inserting it into the byte stream. When checking, a final + * return value of CRC8_GOOD_VALUE indicates a valid CRC. + * + * Reference: Dallas Semiconductor Application Note 27 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt + * + * **************************************************************************** + */ + +static const uint8 crc8_table[256] = { + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F +}; + +#define CRC_INNER_LOOP(n, c, x) \ + (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] + + +uint8 hndcrc8 (uint8 * pdata, /* pointer to array of data to process */ + uint nbytes, /* number of input data bytes to process */ + uint8 crc /* either CRC8_INIT_VALUE or previous return value */ + ) +{ + /* hard code the crc loop instead of using CRC_INNER_LOOP macro + * to avoid the undefined and unnecessary (uint8 >> 8) operation. + */ + while (nbytes-- > 0) + crc = crc8_table[(crc ^ *pdata++) & 0xff]; + + return crc; +} + +char * +bcm_ether_ntoa (struct ether_addr *ea, char *buf) +{ + snprintf (buf, 18, "%02x:%02x:%02x:%02x:%02x:%02x", + ea->octet[0] & 0xff, ea->octet[1] & 0xff, ea->octet[2] & 0xff, + ea->octet[3] & 0xff, ea->octet[4] & 0xff, ea->octet[5] & 0xff); + return (buf); +} + diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/utils.h b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/utils.h new file mode 100644 index 0000000000..907c82c70d --- /dev/null +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/utils.h @@ -0,0 +1,65 @@ +#ifndef __bcm_utils_h +#define __bcm_utils_h + +#define BCME_STRLEN 64 /* Max string length for BCM errors */ +#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) + +/* + * error codes could be added but the defined ones shouldn't be changed/deleted + * these error codes are exposed to the user code + * when ever a new error code is added to this list + * please update errorstring table with the related error string and + * update osl files with os specific errorcode map +*/ + +#define BCME_OK 0 /* Success */ +#define BCME_ERROR -1 /* Error generic */ +#define BCME_BADARG -2 /* Bad Argument */ +#define BCME_BADOPTION -3 /* Bad option */ +#define BCME_NOTUP -4 /* Not up */ +#define BCME_NOTDOWN -5 /* Not down */ +#define BCME_NOTAP -6 /* Not AP */ +#define BCME_NOTSTA -7 /* Not STA */ +#define BCME_BADKEYIDX -8 /* BAD Key Index */ +#define BCME_RADIOOFF -9 /* Radio Off */ +#define BCME_NOTBANDLOCKED -10 /* Not band locked */ +#define BCME_NOCLK -11 /* No Clock */ +#define BCME_BADRATESET -12 /* BAD Rate valueset */ +#define BCME_BADBAND -13 /* BAD Band */ +#define BCME_BUFTOOSHORT -14 /* Buffer too short */ +#define BCME_BUFTOOLONG -15 /* Buffer too long */ +#define BCME_BUSY -16 /* Busy */ +#define BCME_NOTASSOCIATED -17 /* Not Associated */ +#define BCME_BADSSIDLEN -18 /* Bad SSID len */ +#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ +#define BCME_BADCHAN -20 /* Bad Channel */ +#define BCME_BADADDR -21 /* Bad Address */ +#define BCME_NORESOURCE -22 /* Not Enough Resources */ +#define BCME_UNSUPPORTED -23 /* Unsupported */ +#define BCME_BADLEN -24 /* Bad length */ +#define BCME_NOTREADY -25 /* Not Ready */ +#define BCME_EPERM -26 /* Not Permitted */ +#define BCME_NOMEM -27 /* No Memory */ +#define BCME_ASSOCIATED -28 /* Associated */ +#define BCME_RANGE -29 /* Not In Range */ +#define BCME_NOTFOUND -30 /* Not Found */ +#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ +#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ +#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ +#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ +#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ +#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ +#define BCME_VERSION -37 /* Incorrect version */ +#define BCME_LAST BCME_VERSION + +/* buffer length for ethernet address from bcm_ether_ntoa() */ +#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ + +struct ether_addr { + unsigned char octet[6]; +}; + +extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc); + +#endif /* __bcm_utils_h */ + diff --git a/target/linux/brcm-2.4/files/drivers/mtd/devices/sflash.c b/target/linux/brcm-2.4/files/drivers/mtd/devices/sflash.c index a987388ab2..62c7802221 100644 --- a/target/linux/brcm-2.4/files/drivers/mtd/devices/sflash.c +++ b/target/linux/brcm-2.4/files/drivers/mtd/devices/sflash.c @@ -1,298 +1,531 @@ /* * Broadcom SiliconBackplane chipcommon serial flash interface * - * Copyright 2001-2003, Broadcom Corporation - * All Rights Reserved. - * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * - * $Id: sflash.c,v 1.1.1.3 2003/11/10 17:43:38 hyin Exp $ + * $Id$ */ -#include <linux/config.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/mtd/compatmac.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <asm/io.h> - -#ifdef CONFIG_MTD_PARTITIONS -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/minix_fs.h> -#include <linux/ext2_fs.h> -#include <linux/romfs_fs.h> -#include <linux/cramfs_fs.h> -#include <linux/jffs2.h> -#endif - #include <typedefs.h> -#include <bcmdevs.h> -#include <bcmutils.h> #include <osl.h> -#include <bcmutils.h> -#include <bcmnvram.h> +#include <sbutils.h> #include <sbconfig.h> #include <sbchipc.h> +#include <bcmdevs.h> #include <sflash.h> -#include <trxhdr.h> - -#ifdef CONFIG_MTD_PARTITIONS -extern struct mtd_partition * init_mtd_partitions(struct mtd_info *mtd, size_t size); -#endif - -struct sflash_mtd { - chipcregs_t *cc; - struct semaphore lock; - struct mtd_info mtd; - struct mtd_erase_region_info regions[1]; -}; /* Private global state */ -static struct sflash_mtd sflash; +static struct sflash sflash; -static int -sflash_mtd_poll(struct sflash_mtd *sflash, unsigned int offset, int timeout) +/* Issue a serial flash command */ +static INLINE void +sflash_cmd (osl_t * osh, chipcregs_t * cc, uint opcode) { - int now = jiffies; - int ret = 0; + W_REG (osh, &cc->flashcontrol, SFLASH_START | opcode); + while (R_REG (osh, &cc->flashcontrol) & SFLASH_BUSY); +} - for (;;) { - if (!sflash_poll(sflash->cc, offset)) { - ret = 0; - break; - } - if (time_after(jiffies, now + timeout)) { - printk(KERN_ERR "sflash: timeout\n"); - ret = -ETIMEDOUT; - break; - } - if (current->need_resched) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout / 10); - } else - udelay(1); +/* Initialize serial flash access */ +struct sflash * +sflash_init (sb_t * sbh, chipcregs_t * cc) +{ + uint32 id, id2; + osl_t *osh; + + ASSERT (sbh); + + osh = sb_osh (sbh); + + bzero (&sflash, sizeof (sflash)); + + sflash.type = sbh->cccaps & CC_CAP_FLASH_MASK; + + switch (sflash.type) + { + case SFLASH_ST: + /* Probe for ST chips */ + sflash_cmd (osh, cc, SFLASH_ST_DP); + sflash_cmd (osh, cc, SFLASH_ST_RES); + id = R_REG (osh, &cc->flashdata); + switch (id) + { + case 0x11: + /* ST M25P20 2 Mbit Serial Flash */ + sflash.blocksize = 64 * 1024; + sflash.numblocks = 4; + break; + case 0x12: + /* ST M25P40 4 Mbit Serial Flash */ + sflash.blocksize = 64 * 1024; + sflash.numblocks = 8; + break; + case 0x13: + /* ST M25P80 8 Mbit Serial Flash */ + sflash.blocksize = 64 * 1024; + sflash.numblocks = 16; + break; + case 0x14: + /* ST M25P16 16 Mbit Serial Flash */ + sflash.blocksize = 64 * 1024; + sflash.numblocks = 32; + break; + case 0x15: + /* ST M25P32 32 Mbit Serial Flash */ + sflash.blocksize = 64 * 1024; + sflash.numblocks = 64; + break; + case 0x16: + /* ST M25P64 64 Mbit Serial Flash */ + sflash.blocksize = 64 * 1024; + sflash.numblocks = 128; + break; + case 0xbf: + W_REG (osh, &cc->flashaddress, 1); + sflash_cmd (osh, cc, SFLASH_ST_RES); + id2 = R_REG (osh, &cc->flashdata); + if (id2 == 0x44) + { + /* SST M25VF80 4 Mbit Serial Flash */ + sflash.blocksize = 64 * 1024; + sflash.numblocks = 8; + } + break; } + break; + + case SFLASH_AT: + /* Probe for Atmel chips */ + sflash_cmd (osh, cc, SFLASH_AT_STATUS); + id = R_REG (osh, &cc->flashdata) & 0x3c; + switch (id) + { + case 0xc: + /* Atmel AT45DB011 1Mbit Serial Flash */ + sflash.blocksize = 256; + sflash.numblocks = 512; + break; + case 0x14: + /* Atmel AT45DB021 2Mbit Serial Flash */ + sflash.blocksize = 256; + sflash.numblocks = 1024; + break; + case 0x1c: + /* Atmel AT45DB041 4Mbit Serial Flash */ + sflash.blocksize = 256; + sflash.numblocks = 2048; + break; + case 0x24: + /* Atmel AT45DB081 8Mbit Serial Flash */ + sflash.blocksize = 256; + sflash.numblocks = 4096; + break; + case 0x2c: + /* Atmel AT45DB161 16Mbit Serial Flash */ + sflash.blocksize = 512; + sflash.numblocks = 4096; + break; + case 0x34: + /* Atmel AT45DB321 32Mbit Serial Flash */ + sflash.blocksize = 512; + sflash.numblocks = 8192; + break; + case 0x3c: + /* Atmel AT45DB642 64Mbit Serial Flash */ + sflash.blocksize = 1024; + sflash.numblocks = 8192; + break; + } + break; + } - return ret; + sflash.size = sflash.blocksize * sflash.numblocks; + return sflash.size ? &sflash : NULL; } -static int -sflash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +/* Read len bytes starting at offset into buf. Returns number of bytes read. */ +int +sflash_read (sb_t * sbh, chipcregs_t * cc, uint offset, uint len, uchar * buf) { - struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; - int bytes, ret = 0; - - /* Check address range */ - if (!len) - return 0; - if ((from + len) > mtd->size) - return -EINVAL; - - down(&sflash->lock); - - *retlen = 0; - while (len) { - if ((bytes = sflash_read(sflash->cc, (uint) from, len, buf)) < 0) { - ret = bytes; - break; - } - from += (loff_t) bytes; - len -= bytes; - buf += bytes; - *retlen += bytes; - } + uint8 *from, *to; + int cnt, i; + osl_t *osh; - up(&sflash->lock); + ASSERT (sbh); - return ret; -} + if (!len) + return 0; -static int -sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; - int bytes, ret = 0; - - /* Check address range */ - if (!len) - return 0; - if ((to + len) > mtd->size) - return -EINVAL; - - down(&sflash->lock); - - *retlen = 0; - while (len) { - if ((bytes = sflash_write(sflash->cc, (uint) to, len, buf)) < 0) { - ret = bytes; - break; - } - if ((ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10))) - break; - to += (loff_t) bytes; - len -= bytes; - buf += bytes; - *retlen += bytes; - } + if ((offset + len) > sflash.size) + return -22; + + if ((len >= 4) && (offset & 3)) + cnt = 4 - (offset & 3); + else if ((len >= 4) && ((uintptr) buf & 3)) + cnt = 4 - ((uintptr) buf & 3); + else + cnt = len; + + osh = sb_osh (sbh); - up(&sflash->lock); + from = (uint8 *) (uintptr) OSL_UNCACHED (SB_FLASH2 + offset); + to = (uint8 *) buf; - return ret; + if (cnt < 4) + { + for (i = 0; i < cnt; i++) + { + *to = R_REG (osh, from); + from++; + to++; + } + return cnt; + } + + while (cnt >= 4) + { + *(uint32 *) to = R_REG (osh, (uint32 *) from); + from += 4; + to += 4; + cnt -= 4; + } + + return (len - cnt); } -static int -sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) +/* Poll for command completion. Returns zero when complete. */ +int +sflash_poll (sb_t * sbh, chipcregs_t * cc, uint offset) { - struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; - int i, j, ret = 0; - unsigned int addr, len; - - /* Check address range */ - if (!erase->len) - return 0; - if ((erase->addr + erase->len) > mtd->size) - return -EINVAL; - - addr = erase->addr; - len = erase->len; - - down(&sflash->lock); - - /* Ensure that requested region is aligned */ - for (i = 0; i < mtd->numeraseregions; i++) { - for (j = 0; j < mtd->eraseregions[i].numblocks; j++) { - if (addr == mtd->eraseregions[i].offset + mtd->eraseregions[i].erasesize * j && - len >= mtd->eraseregions[i].erasesize) { - if ((ret = sflash_erase(sflash->cc, addr)) < 0) - break; - if ((ret = sflash_mtd_poll(sflash, addr, 10 * HZ))) - break; - addr += mtd->eraseregions[i].erasesize; - len -= mtd->eraseregions[i].erasesize; - } - } - if (ret) - break; - } + osl_t *osh; - up(&sflash->lock); + ASSERT (sbh); - /* Set erase status */ - if (ret) - erase->state = MTD_ERASE_FAILED; - else - erase->state = MTD_ERASE_DONE; + osh = sb_osh (sbh); - /* Call erase callback */ - if (erase->callback) - erase->callback(erase); + if (offset >= sflash.size) + return -22; - return ret; -} + switch (sflash.type) + { + case SFLASH_ST: + /* Check for ST Write In Progress bit */ + sflash_cmd (osh, cc, SFLASH_ST_RDSR); + return R_REG (osh, &cc->flashdata) & SFLASH_ST_WIP; + case SFLASH_AT: + /* Check for Atmel Ready bit */ + sflash_cmd (osh, cc, SFLASH_AT_STATUS); + return !(R_REG (osh, &cc->flashdata) & SFLASH_AT_READY); + } -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define sflash_mtd_init init_module -#define sflash_mtd_exit cleanup_module -#endif + return 0; +} -mod_init_t -sflash_mtd_init(void) +/* Write len bytes starting at offset into buf. Returns number of bytes + * written. Caller should poll for completion. + */ +int +sflash_write (sb_t * sbh, chipcregs_t * cc, uint offset, uint len, + const uchar * buf) { - struct pci_dev *pdev; - int ret = 0; - struct sflash *info; - uint bank, i; -#ifdef CONFIG_MTD_PARTITIONS - struct mtd_partition *parts; -#endif - - if (!(pdev = pci_find_device(VENDOR_BROADCOM, SB_CC, NULL))) { - printk(KERN_ERR "sflash: chipcommon not found\n"); - return -ENODEV; + struct sflash *sfl; + int ret = 0; + bool is4712b0; + uint32 page, byte, mask; + osl_t *osh; + + ASSERT (sbh); + + osh = sb_osh (sbh); + + if (!len) + return 0; + + if ((offset + len) > sflash.size) + return -22; + + sfl = &sflash; + switch (sfl->type) + { + case SFLASH_ST: + is4712b0 = (sbh->chip == BCM4712_CHIP_ID) && (sbh->chiprev == 3); + /* Enable writes */ + sflash_cmd (osh, cc, SFLASH_ST_WREN); + if (is4712b0) + { + mask = 1 << 14; + W_REG (osh, &cc->flashaddress, offset); + W_REG (osh, &cc->flashdata, *buf++); + /* Set chip select */ + OR_REG (osh, &cc->gpioout, mask); + /* Issue a page program with the first byte */ + sflash_cmd (osh, cc, SFLASH_ST_PP); + ret = 1; + offset++; + len--; + while (len > 0) + { + if ((offset & 255) == 0) + { + /* Page boundary, drop cs and return */ + AND_REG (osh, &cc->gpioout, ~mask); + if (!sflash_poll (sbh, cc, offset)) + { + /* Flash rejected command */ + return -11; + } + return ret; + } + else + { + /* Write single byte */ + sflash_cmd (osh, cc, *buf++); + } + ret++; + offset++; + len--; + } + /* All done, drop cs if needed */ + if ((offset & 255) != 1) + { + /* Drop cs */ + AND_REG (osh, &cc->gpioout, ~mask); + if (!sflash_poll (sbh, cc, offset)) + { + /* Flash rejected command */ + return -12; + } + } + } + else if (sbh->ccrev >= 20) + { + W_REG (NULL, &cc->flashaddress, offset); + W_REG (NULL, &cc->flashdata, *buf++); + /* Issue a page program with CSA bit set */ + sflash_cmd (osh, cc, SFLASH_ST_CSA | SFLASH_ST_PP); + ret = 1; + offset++; + len--; + while (len > 0) + { + if ((offset & 255) == 0) + { + /* Page boundary, poll droping cs and return */ + W_REG (NULL, &cc->flashcontrol, 0); + if (!sflash_poll (sbh, cc, offset)) + { + /* Flash rejected command */ + return -11; + } + return ret; + } + else + { + /* Write single byte */ + sflash_cmd (osh, cc, SFLASH_ST_CSA | *buf++); + } + ret++; + offset++; + len--; + } + /* All done, drop cs if needed */ + if ((offset & 255) != 1) + { + /* Drop cs, poll */ + W_REG (NULL, &cc->flashcontrol, 0); + if (!sflash_poll (sbh, cc, offset)) + { + /* Flash rejected command */ + return -12; + } + } + } + else + { + ret = 1; + W_REG (osh, &cc->flashaddress, offset); + W_REG (osh, &cc->flashdata, *buf); + /* Page program */ + sflash_cmd (osh, cc, SFLASH_ST_PP); + } + break; + case SFLASH_AT: + mask = sfl->blocksize - 1; + page = (offset & ~mask) << 1; + byte = offset & mask; + /* Read main memory page into buffer 1 */ + if (byte || (len < sfl->blocksize)) + { + W_REG (osh, &cc->flashaddress, page); + sflash_cmd (osh, cc, SFLASH_AT_BUF1_LOAD); + /* 250 us for AT45DB321B */ + SPINWAIT (sflash_poll (sbh, cc, offset), 1000); + ASSERT (!sflash_poll (sbh, cc, offset)); } + /* Write into buffer 1 */ + for (ret = 0; (ret < (int) len) && (byte < sfl->blocksize); ret++) + { + W_REG (osh, &cc->flashaddress, byte++); + W_REG (osh, &cc->flashdata, *buf++); + sflash_cmd (osh, cc, SFLASH_AT_BUF1_WRITE); + } + /* Write buffer 1 into main memory page */ + W_REG (osh, &cc->flashaddress, page); + sflash_cmd (osh, cc, SFLASH_AT_BUF1_PROGRAM); + break; + } - memset(&sflash, 0, sizeof(struct sflash_mtd)); - init_MUTEX(&sflash.lock); + return ret; +} - /* Map registers and flash base */ - if (!(sflash.cc = ioremap_nocache(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)))) { - printk(KERN_ERR "sflash: error mapping registers\n"); - ret = -EIO; - goto fail; - } +/* Erase a region. Returns number of bytes scheduled for erasure. + * Caller should poll for completion. + */ +int +sflash_erase (sb_t * sbh, chipcregs_t * cc, uint offset) +{ + struct sflash *sfl; + osl_t *osh; + + ASSERT (sbh); + + osh = sb_osh (sbh); + + if (offset >= sflash.size) + return -22; + + sfl = &sflash; + switch (sfl->type) + { + case SFLASH_ST: + sflash_cmd (osh, cc, SFLASH_ST_WREN); + W_REG (osh, &cc->flashaddress, offset); + sflash_cmd (osh, cc, SFLASH_ST_SE); + return sfl->blocksize; + case SFLASH_AT: + W_REG (osh, &cc->flashaddress, offset << 1); + sflash_cmd (osh, cc, SFLASH_AT_PAGE_ERASE); + return sfl->blocksize; + } + + return 0; +} - /* Initialize serial flash access */ - info = sflash_init(sflash.cc); +/* + * writes the appropriate range of flash, a NULL buf simply erases + * the region of flash + */ +int +sflash_commit (sb_t * sbh, chipcregs_t * cc, uint offset, uint len, + const uchar * buf) +{ + struct sflash *sfl; + uchar *block = NULL, *cur_ptr, *blk_ptr; + uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder; + uint blk_offset, blk_len, copied; + int bytes, ret = 0; + osl_t *osh; + + ASSERT (sbh); + + osh = sb_osh (sbh); + + /* Check address range */ + if (len <= 0) + return 0; + + sfl = &sflash; + if ((offset + len) > sfl->size) + return -1; + + blocksize = sfl->blocksize; + mask = blocksize - 1; + + /* Allocate a block of mem */ + if (!(block = MALLOC (osh, blocksize))) + return -1; + + while (len) + { + /* Align offset */ + cur_offset = offset & ~mask; + cur_length = blocksize; + cur_ptr = block; + + remainder = blocksize - (offset & mask); + if (len < remainder) + cur_retlen = len; + else + cur_retlen = remainder; + + /* buf == NULL means erase only */ + if (buf) + { + /* Copy existing data into holding block if necessary */ + if ((offset & mask) || (len < blocksize)) + { + blk_offset = cur_offset; + blk_len = cur_length; + blk_ptr = cur_ptr; + + /* Copy entire block */ + while (blk_len) + { + copied = + sflash_read (sbh, cc, blk_offset, blk_len, blk_ptr); + blk_offset += copied; + blk_len -= copied; + blk_ptr += copied; + } + } - if (!info) { - printk(KERN_ERR "sflash: found no supported devices\n"); - ret = -ENODEV; - goto fail; + /* Copy input data into holding block */ + memcpy (cur_ptr + (offset & mask), buf, cur_retlen); } - /* Setup banks */ - sflash.regions[0].offset = 0; - sflash.regions[0].erasesize = info->blocksize; - sflash.regions[0].numblocks = info->numblocks; - if (sflash.regions[0].erasesize > sflash.mtd.erasesize) - sflash.mtd.erasesize = sflash.regions[0].erasesize; - if (sflash.regions[0].erasesize * sflash.regions[0].numblocks) { - sflash.mtd.size += sflash.regions[0].erasesize * sflash.regions[0].numblocks; - } - sflash.mtd.numeraseregions = 1; - ASSERT(sflash.mtd.size == info->size); - - /* Register with MTD */ - sflash.mtd.name = "sflash"; - sflash.mtd.type = MTD_NORFLASH; - sflash.mtd.flags = MTD_CAP_NORFLASH; - sflash.mtd.eraseregions = sflash.regions; - sflash.mtd.module = THIS_MODULE; - sflash.mtd.erase = sflash_mtd_erase; - sflash.mtd.read = sflash_mtd_read; - sflash.mtd.write = sflash_mtd_write; - sflash.mtd.priv = &sflash; - -#ifdef CONFIG_MTD_PARTITIONS - parts = init_mtd_partitions(&sflash.mtd, sflash.mtd.size); - for (i = 0; parts[i].name; i++); - ret = add_mtd_partitions(&sflash.mtd, parts, i); -#else - ret = add_mtd_device(&sflash.mtd); -#endif - if (ret) { - printk(KERN_ERR "sflash: add_mtd failed\n"); - goto fail; + /* Erase block */ + if ((ret = sflash_erase (sbh, cc, (uint) cur_offset)) < 0) + goto done; + while (sflash_poll (sbh, cc, (uint) cur_offset)); + + /* buf == NULL means erase only */ + if (!buf) + { + offset += cur_retlen; + len -= cur_retlen; + continue; } - return 0; + /* Write holding block */ + while (cur_length > 0) + { + if ((bytes = sflash_write (sbh, cc, + (uint) cur_offset, + (uint) cur_length, + (uchar *) cur_ptr)) < 0) + { + ret = bytes; + goto done; + } + while (sflash_poll (sbh, cc, (uint) cur_offset)); + cur_offset += bytes; + cur_length -= bytes; + cur_ptr += bytes; + } - fail: - if (sflash.cc) - iounmap((void *) sflash.cc); - return ret; -} + offset += cur_retlen; + len -= cur_retlen; + buf += cur_retlen; + } -mod_exit_t -sflash_mtd_exit(void) -{ -#ifdef CONFIG_MTD_PARTITIONS - del_mtd_partitions(&sflash.mtd); -#else - del_mtd_device(&sflash.mtd); -#endif - iounmap((void *) sflash.cc); + ret = len; +done: + if (block) + MFREE (osh, block, blocksize); + return ret; } - -module_init(sflash_mtd_init); -module_exit(sflash_mtd_exit); diff --git a/target/linux/brcm-2.4/files/drivers/mtd/maps/bcm947xx-flash.c b/target/linux/brcm-2.4/files/drivers/mtd/maps/bcm947xx-flash.c index 1641784681..eea7f137d7 100644 --- a/target/linux/brcm-2.4/files/drivers/mtd/maps/bcm947xx-flash.c +++ b/target/linux/brcm-2.4/files/drivers/mtd/maps/bcm947xx-flash.c @@ -56,7 +56,6 @@ #include <typedefs.h> #include <osl.h> #include <bcmnvram.h> -#include <bcmutils.h> #include <sbconfig.h> #include <sbchipc.h> #include <sbutils.h> @@ -470,7 +469,7 @@ mod_init_t init_bcm947xx_map(void) /* Check strapping option if chipcommon exists */ if ((cc = sb_setcore(sbh, SB_CC, 0))) { - fltype = readl(&cc->capabilities) & CAP_FLASH_MASK; + fltype = readl(&cc->capabilities) & CC_CAP_FLASH_MASK; if (fltype == PFLASH) { bcm947xx_map.map_priv_2 = 1; window_addr = 0x1c000000; |