bool BCMATTACHFN(si_cc_register_isr)(si_t *sih, cc_isr_fn isr, uint32 ccintmask, void *cbdata) { bool done = FALSE; chipcregs_t *regs; uint origidx; uint i; /* Save the current core index */ origidx = si_coreidx(sih); regs = si_setcoreidx(sih, SI_CC_IDX); 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(si_osh(sih), ®s->intmask); cc_intmask |= ccintmask; W_REG(si_osh(sih), ®s->intmask, cc_intmask); } /* restore original coreidx */ si_setcoreidx(sih, origidx); return done; }
/* Initialize nand flash access */ hndnand_t * hndnand_init(si_t *sih) { uint32 origidx; ASSERT(sih); /* Already initialized ? */ if (hndnand) return hndnand; origidx = si_coreidx(sih); #ifdef __mips__ if (!hndnand) hndnand = nflash_init(sih); #endif #ifdef __ARM_ARCH_7A__ if (!hndnand) hndnand = nandcore_init(sih); #endif si_setcoreidx(sih, origidx); return hndnand; }
/* initialize the sdio core */ void si_sdio_init(si_t *sih) { si_info_t *sii = SI_INFO(sih); if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) || (sih->buscoretype == SDIOD_CORE_ID)) { uint idx; sdpcmd_regs_t *sdpregs; /* get the current core index */ idx = sii->curidx; ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0)); /* switch to sdio core */ if (!(sdpregs = (sdpcmd_regs_t *)si_setcore(sih, PCMCIA_CORE_ID, 0))) sdpregs = (sdpcmd_regs_t *)si_setcore(sih, SDIOD_CORE_ID, 0); ASSERT(sdpregs); SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " "through SD core %d (%p)\n", sih->buscorerev, idx, sii->curidx, sdpregs)); /* enable backplane error and core interrupts */ W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT); W_REG(sii->osh, &sdpregs->sbintmask, (I_SB_SERR | I_SB_RESPERR | (1 << idx))); /* switch back to previous core */ si_setcoreidx(sih, idx); } /* enable interrupts */ bcmsdh_intr_enable(sii->sdh); }
/* Initialize nand flash access */ hndsflash_t * hndsflash_init(si_t *sih) { uint32 origidx; ASSERT(sih); /* Already initialized ? */ if (hndsflash) return hndsflash; /* spin lock here */ origidx = si_coreidx(sih); #ifdef __mips__ if (!hndsflash) hndsflash = ccsflash_init(sih); #endif /* __mips__ */ #ifdef __ARM_ARCH_7A__ if (!hndsflash) hndsflash = spiflash_init(sih); #endif /* __ARM_ARCH_7A__ */ si_setcoreidx(sih, origidx); return hndsflash; }
/* restore coreidx and restore interrupt */ void si_restore_core(si_t *sih, uint coreid, uint intr_val) { si_info_t *sii; sii = SI_INFO(sih); si_setcoreidx(sih, coreid); INTR_RESTORE(sii, intr_val); }
/* * We utilize chipcommon configuration register SBFlagSt to implement a * smart shared IRQ handling machenism through which only ISRs registered * for the SB cores that raised the interrupt are invoked. This machenism * relies on the SBFlagSt register's reliable recording of the SB cores * that raised the interrupt. */ void __init arch_init_irq(void) { int i; uint32 coreidx, mips_core_id; void *regs; if (BCM330X(current_cpu_data.processor_id)) mips_core_id = MIPS33_CORE_ID; else if (MIPS74K(current_cpu_data.processor_id)) mips_core_id = MIPS74K_CORE_ID; else { printk(KERN_ERR "MIPS CPU type %x unknown", current_cpu_data.processor_id); return; } /* Cache chipc and mips33 config registers */ ASSERT(bcm947xx_sih); coreidx = si_coreidx(bcm947xx_sih); regs = si_setcore(bcm947xx_sih, mips_core_id, 0); mipsirq = si_irq(bcm947xx_sih); if (bcm947xx_sih->socitype == SOCI_SB) { if (regs) mipssbr = (sbconfig_t *)((ulong)regs + SBCONFIGOFF); if ((regs = si_setcore(bcm947xx_sih, CC_CORE_ID, 0))) ccsbr = (sbconfig_t *)((ulong)regs + SBCONFIGOFF); } si_setcoreidx(bcm947xx_sih, coreidx); if (BCM330X(current_cpu_data.processor_id)) { /* Cache mips33 sbintvec register */ if (mipssbr) shints = R_REG(NULL, &mipssbr->sbintvec); } else { uint32 *intmask; /* Use intmask5 register to route the timer interrupt */ intmask = (uint32 *) &((mips74kregs_t *)regs)->intmask[5]; W_REG(NULL, intmask, 1 << 31); intmask = (uint32 *) &((mips74kregs_t *)regs)->intmask[0]; shints = R_REG(NULL, intmask); /* Save the pointer to mips core registers */ mips_corereg = regs; } /* Install interrupt controllers */ for (i = 0; i < NR_IRQS; i++) { set_irq_chip(i, (i < SBMIPS_NUMIRQS ? &brcm_irq_type : &brcm_irq2_type)); } }
LOCAL void flashAutoSelect(FLASH_TYPES *dev, FLASH_VENDORS *vendor) { /* * Check for serial flash. */ sih = si_kattach(SI_OSH); ASSERT(sih); cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); ASSERT(cc); *vendor = *dev = 0xFF; }
/* set the core to socram run bist and return bist status back */ int si_bist_socram(si_t *sih, uint32 *biststatus) { si_info_t *sii; uint origidx; uint intr_val = 0; sbsocramregs_t *regs; int error = 0; uint status = 0; SI_ERROR(("doing the bist on SOCRAM\n")); sii = SI_INFO(sih); /* Block ints and save current core */ INTR_OFF(sii, intr_val); origidx = si_coreidx(sih); /* Switch to SOCRAM core */ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) goto done; si_core_reset(sih, SICF_BIST_EN, SICF_BIST_EN); /* Wait for bist done */ SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); status = si_core_sflags(sih, 0, 0); if (status & SISF_BIST_DONE) { if (status & SISF_BIST_ERROR) { *biststatus = R_REG(sii->osh, ®s->biststat); /* hnd_bist gives errors for ROM bist test, so ignore it */ *biststatus &= 0xFFFF; if (!*biststatus) error = 0; else error = 1; } } si_core_reset(sih, 0, 0); /* Return to previous state and core */ si_setcoreidx(sih, origidx); done: INTR_RESTORE(sii, intr_val); return error; }
int si_bist_cc(si_t *sih, uint32 *biststatus) { si_info_t *sii; uint origidx; uint intr_val = 0; int error = 0; void *regs; int status; bool wasup; sii = SI_INFO(sih); SI_ERROR(("doing the bist on ChipC\n")); /* Block ints and save current core */ INTR_OFF(sii, intr_val); origidx = si_coreidx(sih); /* Switch to CC core */ if (!(regs = si_setcore(sih, CC_CORE_ID, 0))) goto done; /* Get info for determining size */ if (!(wasup = si_iscoreup(sih))) si_core_reset(sih, 0, 0); status = si_corebist(sih); if (status == BCME_ERROR) { *biststatus = si_corereg(sih, si_coreidx(&sii->pub), 12, 0, 0); /* XXX: OTP gives the BIST error */ *biststatus &= ~(0x1); if (*biststatus) error = 1; } /* Return to previous state and core */ if (!wasup) si_core_disable(sih, 0); /* Return to previous state and core */ si_setcoreidx(sih, origidx); *biststatus = 0; done: INTR_RESTORE(sii, intr_val); return error; }
void board_power_init(si_t *sih) { uint origidx; chipcregs_t *cc; int gpio; /* Drive gpio pin to HIGH to enable on-board switching regulator for COMA mode */ origidx = si_coreidx(sih); if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) != NULL) { gpio = getgpiopin(NULL, "coma_swreg", GPIO_PIN_NOTDEFINED); if (gpio != GPIO_PIN_NOTDEFINED) { gpio = 1 << gpio; si_gpioout(sih, gpio, gpio, GPIO_DRV_PRIORITY); si_gpioouten(sih, gpio, gpio, GPIO_DRV_PRIORITY); } } si_setcoreidx(sih, origidx); }
/* * Initialize jtag master and return handle for * jtag_rwreg. Returns NULL on failure. */ void * hnd_jtagm_init(si_t *sih, uint clkd, bool exttap) { void *regs; osl_t *osh; osh = si_osh(sih); if ((regs = si_setcoreidx(sih, SI_CC_IDX)) != 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 (sih->ccrev < 11) return (NULL); if ((sih->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 pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs) { uint32 val, i, lsc; uint16 cfg_offset[] = {PCIECFGREG_STATUS_CMD, PCIECFGREG_PM_CSR, PCIECFGREG_MSI_CAP, PCIECFGREG_MSI_ADDR_L, PCIECFGREG_MSI_ADDR_H, PCIECFGREG_MSI_DATA, PCIECFGREG_LINK_STATUS_CTRL2, PCIECFGREG_RBAR_CTRL, PCIECFGREG_PML1_SUB_CTRL1, PCIECFGREG_REG_BAR2_CONFIG, PCIECFGREG_REG_BAR3_CONFIG}; uint32 origidx = si_coreidx(sih); /* Disable/restore ASPM Control to protect the watchdog reset */ W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL); lsc = R_REG(osh, &sbpcieregs->configdata); val = lsc & (~PCIE_ASPM_ENAB); W_REG(osh, &sbpcieregs->configdata, val); si_setcore(sih, PCIE2_CORE_ID, 0); si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 4); OSL_DELAY(100000); #ifdef BCMQT OSL_DELAY(200000); #endif /* BCMQT */ W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL); W_REG(osh, &sbpcieregs->configdata, lsc); /* Write configuration registers back to the shadow registers * cause shadow registers are cleared out after watchdog reset. */ for (i = 0; i < ARRAYSIZE(cfg_offset); i++) { W_REG(osh, &sbpcieregs->configaddr, cfg_offset[i]); val = R_REG(osh, &sbpcieregs->configdata); W_REG(osh, &sbpcieregs->configdata, val); } si_setcoreidx(sih, origidx); }
static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, uint *origidx, void *regs) { bool pci, pcie, pcie_gen2 = FALSE; uint i; uint pciidx, pcieidx, pcirev, pcierev; cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ASSERT((uintptr)cc); /* get chipcommon rev */ sii->pub.ccrev = (int)si_corerev(&sii->pub); /* get chipcommon chipstatus */ if (sii->pub.ccrev >= 11) sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); /* get chipcommon capabilites */ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); /* get chipcommon extended capabilities */ if (sii->pub.ccrev >= 35) sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); /* get pmu rev and caps */ if (sii->pub.cccaps & CC_CAP_PMU) { sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; } SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, sii->pub.pmucaps)); /* figure out bus/orignal core idx */ sii->pub.buscoretype = NODEV_CORE_ID; sii->pub.buscorerev = (uint)NOREV; sii->pub.buscoreidx = BADIDX; pci = pcie = FALSE; pcirev = pcierev = (uint)NOREV; pciidx = pcieidx = BADIDX; for (i = 0; i < sii->numcores; i++) { uint cid, crev; si_setcoreidx(&sii->pub, i); cid = si_coreid(&sii->pub); crev = si_corerev(&sii->pub); /* Display cores found */ SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", i, cid, crev, sii->coresba[i], sii->regs[i])); if (BUSTYPE(bustype) == PCI_BUS) { if (cid == PCI_CORE_ID) { pciidx = i; pcirev = crev; pci = TRUE; } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) { pcieidx = i; pcierev = crev; pcie = TRUE; if (cid == PCIE2_CORE_ID) pcie_gen2 = TRUE; } } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && (cid == PCMCIA_CORE_ID)) { sii->pub.buscorerev = crev; sii->pub.buscoretype = cid; sii->pub.buscoreidx = i; } else if (((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) && ((cid == PCMCIA_CORE_ID) || (cid == SDIOD_CORE_ID))) { sii->pub.buscorerev = crev; sii->pub.buscoretype = cid; sii->pub.buscoreidx = i; } /* find the core idx before entering this func. */ if ((savewin && (savewin == sii->coresba[i])) || (regs == sii->regs[i])) *origidx = i; } if (pci) { sii->pub.buscoretype = PCI_CORE_ID; sii->pub.buscorerev = pcirev; sii->pub.buscoreidx = pciidx; } else if (pcie) { if (pcie_gen2) sii->pub.buscoretype = PCIE2_C
/* Read the flash ID and set the globals */ int sysFlashInit(char *flash_str) { osl_t *osh; uint32 fltype = PFLASH; uint16 flash_vendid = 0; uint16 flash_devid = 0; int idx; struct sflash *sflash; /* * Check for serial flash. */ sih = si_kattach(SI_OSH); ASSERT(sih); osh = si_osh(sih); cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); ASSERT(cc); flashutl_base = (void *)OSL_UNCACHED((uintptr)SI_FLASH2); /* Select SFLASH ? */ fltype = R_REG(osh, &cc->capabilities) & CC_CAP_FLASH_MASK; if (fltype == SFLASH_ST || fltype == SFLASH_AT) { if (sih->ccrev == 12) flashutl_base = (void *)OSL_UNCACHED((uintptr)SI_FLASH2); else flashutl_base = (void *)OSL_CACHED((uintptr)SI_FLASH2); sflash = sflash_init(sih, cc); flashutl_cmd = &sflash_cmd_t; flashutl_desc = &sflash_desc; flashutl_desc->size = sflash->size; if (flash_str) sprintf(flash_str, "SFLASH %d kB", sflash->size/1024); return (0); } flashutl_wsz = (R_REG(osh, &cc->flash_config) & CC_CFG_DS) ? sizeof(uint16) : sizeof(uint8); ASSERT(flashutl_wsz == sizeof(uint8) || flashutl_wsz == sizeof(uint16)); /* * Parallel flash support * Some flashes have different unlock addresses, try each it turn */ for (idx = 0; fltype == PFLASH && idx < ARRAYSIZE(flash_cmds); idx ++) { flashutl_cmd = &flash_cmds[idx]; if (flashutl_cmd->type == OLD) continue; if (flashutl_cmd->read_id) { cmd(flashutl_cmd->read_id, CMD_ADDR); /* Delay for turn around time */ OSL_DELAY(1); } #ifdef MIPSEB #ifdef BCMHND74K flash_vendid = flash_readword(FLASH_ADDR(0)^6); flash_devid = flash_readword(FLASH_ADDR(2)^6); #else /* !74K, bcm33xx */ flash_vendid = flash_readword(FLASH_ADDR(2)); flash_devid = flash_readword(FLASH_ADDR(0)); #endif /* BCMHND74K */ #else flash_vendid = flash_readword(FLASH_ADDR(0)); flash_devid = flash_readword(FLASH_ADDR(2)); #endif /* MIPSEB */ /* Funky AMD, uses 3 byte device ID so use first byte (4th addr) to * identify it is a 3-byte ID and use the next two bytes (5th & 6th addr) * to form a word for unique identification of format xxyy, where * xx = 5th addr and yy = 6th addr */ if ((flash_vendid == 1) && ((flash_devid == 0x227e && flashutl_wsz == sizeof(uint16)) || (flash_devid == 0x7e && flashutl_wsz == sizeof(uint8)))) { /* Get real devid */ uint16 flash_devid_5th; #ifdef MIPSEB #ifdef BCMHND74K flash_devid_5th = flash_readword(FLASH_ADDR(0x1c)^6) << 8; flash_devid = (flash_readword(FLASH_ADDR(0x1e)^6) & 0xff) | flash_devid_5th; #else /* !74K, bcm33xx */ flash_devid_5th = flash_readword(FLASH_ADDR(0x1e)) << 8; flash_devid = (flash_readword(FLASH_ADDR(0x1c)) & 0xff) | flash_devid_5th; #endif /* BCMHND74K */ #else flash_devid_5th = flash_readword(FLASH_ADDR(0x1c)) << 8; flash_devid = (flash_readword(FLASH_ADDR(0x1e)) & 0xff) | flash_devid_5th; #endif /* MIPSEB */ } flashutl_desc = flashes; while (flashutl_desc->mfgid != 0 && !(flashutl_desc->mfgid == flash_vendid && flashutl_desc->devid == flash_devid)) { flashutl_desc++; } if (flashutl_desc->mfgid != 0) break; } if (flashutl_desc->mfgid == 0) { flashutl_desc = NULL; flashutl_cmd = NULL; } else { flashutl_cmd = flash_cmds; while (flashutl_cmd->type != 0 && flashutl_cmd->type != flashutl_desc->type) flashutl_cmd++; if (flashutl_cmd->type == 0) flashutl_cmd = NULL; } if (flashutl_cmd != NULL) { flash_reset(); } if (flashutl_desc == NULL) { if (flash_str) sprintf(flash_str, "UNKNOWN 0x%x 0x%x", flash_vendid, flash_devid); DPRINT(("Flash type UNKNOWN\n")); return 1; } if (flash_str) strcpy(flash_str, flashutl_desc->desc); DPRINT(("Flash type \"%s\"\n", flashutl_desc->desc)); return 0; }
/* * Setup the gige core. * Resetting the core will lose all settings. */ void hndgige_init(si_t *sih, uint32 unit, bool *rgmii) { volatile pci_config_regs *pci; sbgige_pcishim_t *ocp; sbconfig_t *sb; osl_t *osh; uint32 statelow; uint32 statehigh; uint32 base; uint32 idx; void *regs; /* Sanity checks */ ASSERT(sih); ASSERT(rgmii); idx = si_coreidx(sih); /* point to the gige core registers */ regs = si_setcore(sih, GIGETH_CORE_ID, unit); ASSERT(regs); osh = si_osh(sih); pci = &((sbgige_t *)regs)->pcicfg; ocp = &((sbgige_t *)regs)->pcishim; sb = &((sbgige_t *)regs)->sbconfig; /* Enable the core clock and memory access */ if (!si_iscoreup(sih)) si_core_reset(sih, 0, 0); /* * Setup the 64K memory-mapped region base address through BAR0. * Leave the other BAR values alone. */ base = si_addrspace(sih, 1); W_REG(osh, &pci->base[0], base); W_REG(osh, &pci->base[1], 0); /* * Enable the PCI memory access anyway. Any PCI config commands * issued before the core is enabled will go to the emulation * only and will not go to the real PCI config registers. */ OR_REG(osh, &pci->command, 2); /* * Enable the posted write flush scheme as follows: * * - Enable flush on any core register read * - Enable timeout on the flush * - Disable the interrupt mask when flushing * * This differs from the default setting only in that interrupts are * not masked. Since posted writes are not flushed on interrupt, the * driver must explicitly request a flush in its interrupt handling * by reading a core register. */ W_REG(osh, &ocp->FlushStatusControl, 0x68); /* * Determine whether the GbE is in GMII or RGMII mode. This is * indicated in bit 16 of the SBTMStateHigh register, which is * part of the core-specific flags field. * * For GMII, bypass the Rx/Tx DLLs, i.e. add no delay to RXC/GTXC * within the core. For RGMII, do not bypass the DLLs, resulting * in added delay for RXC/GTXC. The SBTMStateLow register contains * the controls for doing this in the core-specific flags field: * * bit 24 - Enable DLL controls * bit 20 - Bypass Rx DLL * bit 19 - Bypass Tx DLL */ statelow = R_REG(osh, &sb->sbtmstatelow); /* DLL controls */ statehigh = R_REG(osh, &sb->sbtmstatehigh); /* GMII/RGMII mode */ if ((statehigh & (1 << 16)) != 0) /* RGMII */ { statelow &= ~(1 << 20); /* no Rx bypass (delay) */ statelow &= ~(1 << 19); /* no Tx bypass (delay) */ *rgmii = TRUE; } else /* GMII */ { statelow |= (1 << 20); /* Rx bypass (no delay) */ statelow |= (1 << 19); /* Tx bypass (no delay) */ *rgmii = FALSE; } statelow |= (1 << 24); /* enable DLL controls */ W_REG(osh, &sb->sbtmstatelow, statelow); si_setcoreidx(sih, idx); }
/* * Initializes UART access. The callback function will be called once * per found UART. */ void BCMATTACHFN(si_serial_init)(si_t *sih, si_serial_init_fn add) { osl_t *osh; void *regs; chipcregs_t *cc; uint32 rev, cap, pll, baud_base, div; uint irq; int i, n; osh = si_osh(sih); cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); ASSERT(cc); /* Determine core revision and capabilities */ rev = sih->ccrev; cap = sih->cccaps; pll = cap & CC_CAP_PLL_MASK; /* Determine IRQ */ irq = si_irq(sih); if (CCPLL_ENAB(sih) && pll == PLL_TYPE1) { /* PLL clock */ baud_base = si_clock_rate(pll, R_REG(osh, &cc->clockcontrol_n), R_REG(osh, &cc->clockcontrol_m2)); div = 1; } else { /* Fixed ALP clock */ if (rev >= 11 && rev != 15) { baud_base = si_alp_clock(sih); 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 */ baud_base = si_clock(sih); div = 2; /* Minimum divisor */ W_REG(osh, &cc->clkdiv, ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div)); } else { /* Fixed internal backplane clock */ baud_base = 88000000; div = 48; } /* Clock source depends on strapping if UartClkOverride is unset */ if ((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 & CC_CAP_UARTS_MASK; for (i = 0; i < n; i++) { regs = (void *)((ulong) &cc->uart0data + (i * 256)); if (add) add(regs, irq, baud_base, 0); } }
/* * Initializes UART access. The callback function will be called once * per found UART. */ void BCMINITFN(si_serial_init)(si_t *sih, si_serial_init_fn add, uint32 baudrate) { osl_t *osh; void *regs; chipcregs_t *cc; uint32 rev, cap, pll, baud_base, div; uint irq; int i, n; osh = si_osh(sih); cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); ASSERT(cc); /* Determine core revision and capabilities */ rev = sih->ccrev; cap = sih->cccaps; pll = cap & CC_CAP_PLL_MASK; /* Determine IRQ */ irq = si_irq(sih); if (CCPLL_ENAB(sih) && pll == PLL_TYPE1) { /* PLL clock */ baud_base = si_clock_rate(pll, R_REG(osh, &cc->clockcontrol_n), R_REG(osh, &cc->clockcontrol_m2)); div = 1; } else { /* Fixed ALP clock */ /* XXX rev. 15 in 4785 breaks the rule! */ if (rev >= 11 && rev != 15) { baud_base = si_alp_clock(sih); div = 1; /* * If baudrate parameter is given with a non-zero value, * UART clock will be divided for the given baud rate before * feeding into UART module. * Note: UART driver could also adjust UART module's divider for * clock fine tunning. */ if (baudrate) { /* Turn off UART clock before switching clock source */ if (rev >= 21) AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN); /* Don't set the override bit so we divide it */ AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKO); div = baud_base / (baudrate * 16); div = (div + 1) & ~0x1; AND_REG(osh, &cc->clkdiv, ~CLKD_UART); OR_REG(osh, &cc->clkdiv, div); /* Turn back UART clock on */ if (rev >= 21) OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN); } else { /* Turn off UART clock before switching clock source */ if (rev >= 21) AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN); OR_REG(osh, &cc->corecontrol, CC_UARTCLKO); /* Turn back UART clock on */ if (rev >= 21) OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN); } if (CONSOLE_TTY == 1) { /* Use UART1, enable "UART1 use GPIO" bit */ OR_REG(osh, &cc->corecontrol, 0x80); } } else if (rev >= 3) { /* Internal backplane clock */ baud_base = si_clock(sih); div = 2; /* Minimum divisor */ W_REG(osh, &cc->clkdiv, ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div)); } else { /* Fixed internal backplane clock */ 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 & 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 & 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); } }
static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, uint *origidx, void *regs) { bool pci, pcie; uint i; uint pciidx, pcieidx, pcirev, pcierev; cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ASSERT((uintptr)cc); /* get chipcommon rev */ sii->pub.ccrev = (int)si_corerev(&sii->pub); /* get chipcommon chipstatus */ if (sii->pub.ccrev >= 11) sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); /* get chipcommon capabilites */ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); /* get pmu rev and caps */ if (sii->pub.cccaps & CC_CAP_PMU) { sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; } SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, sii->pub.pmucaps)); /* figure out bus/orignal core idx */ sii->pub.buscoretype = NODEV_CORE_ID; sii->pub.buscorerev = NOREV; sii->pub.buscoreidx = BADIDX; pci = pcie = FALSE; pcirev = pcierev = NOREV; pciidx = pcieidx = BADIDX; for (i = 0; i < sii->numcores; i++) { uint cid, crev; si_setcoreidx(&sii->pub, i); cid = si_coreid(&sii->pub); crev = si_corerev(&sii->pub); /* Display cores found */ SI_MSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", i, cid, crev, sii->common_info->coresba[i], sii->common_info->regs[i])); if (BUSTYPE(bustype) == PCI_BUS) { if (cid == PCI_CORE_ID) { pciidx = i; pcirev = crev; pci = TRUE; } else if (cid == PCIE_CORE_ID) { pcieidx = i; pcierev = crev; pcie = TRUE; } } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && (cid == PCMCIA_CORE_ID)) { sii->pub.buscorerev = crev; sii->pub.buscoretype = cid; sii->pub.buscoreidx = i; } else if (((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) && ((cid == PCMCIA_CORE_ID) || (cid == SDIOD_CORE_ID))) { sii->pub.buscorerev = crev; sii->pub.buscoretype = cid; sii->pub.buscoreidx = i; } /* find the core idx before entering this func. */ if ((savewin && (savewin == sii->common_info->coresba[i])) || (regs == sii->common_info->regs[i])) *origidx = i; } SI_MSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, sii->pub.buscorerev)); if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (sii->pub.chiprev <= 3)) OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was * already running. */ if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) { if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) || si_setcore(&sii->pub, ARMCM3_CORE_ID, 0)) si_core_disable(&sii->pub, 0); } /* return to the original core */ si_setcoreidx(&sii->pub, *origidx); return TRUE; }
/* Disable register access to the chip */ static void adm_disable(adm_info_t *adm) { /* Switch back to original core */ si_setcoreidx(adm->sih, adm->coreidx); }
static uint32 config_cmd(si_t *sih, uint coreunit, uint bus, uint dev, uint func, uint off) { uint coreidx; sbpciregs_t *pci; uint32 addr = 0, *sbtopci1; osl_t *osh; /* CardBusMode supports only one device */ if (cardbus && dev > 1) return 0; osh = si_osh(sih); coreidx = si_coreidx(sih); pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit); if (pci) { sbtopci1 = &pci->sbtopci1; } else { sbpcieregs_t *pcie; pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit); /* Issue config commands only when the data link is up (atleast * one external pcie device is present). */ if (pcie && (dev < 2) && (pcie_readreg(sih, pcie, PCIE_PCIEREGS, PCIE_DLLP_LSREG) & PCIE_DLLP_LSREG_LINKUP)) { sbtopci1 = &pcie->sbtopcie1; } else { si_setcoreidx(sih, coreidx); return 0; } } /* Type 0 transaction */ if (!hndpci_is_hostbridge(bus, dev)) { /* Skip unwired slots */ if (dev < PCI_SLOT_MAX) { /* Slide the PCI window to the appropriate slot */ if (pci) { uint32 win; win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); W_REG(osh, sbtopci1, win); addr = (pci_membase_cfg[coreunit] | ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | (func << PCICFG_FUN_SHIFT) | (off & ~3)); } else { W_REG(osh, sbtopci1, SBTOPCI_CFG0); addr = (pci_membase_cfg[coreunit] | (dev << PCIECFG_SLOT_SHIFT) | (func << PCIECFG_FUN_SHIFT) | (off & ~3)); } } } else { /* Type 1 transaction */ W_REG(osh, sbtopci1, SBTOPCI_CFG1); addr = (pci_membase_cfg[coreunit] | (pci ? PCI_CONFIG_ADDR(bus, dev, func, (off & ~3)) : PCIE_CONFIG_ADDR((bus - 1), dev, func, (off & ~3)))); } si_setcoreidx(sih, coreidx); return addr; }
void board_pinmux_init(si_t *sih) { uint origidx; chipcommonbregs_t *chipcb; origidx = si_coreidx(sih); chipcb = si_setcore(sih, NS_CCB_CORE_ID, 0); if (chipcb != NULL) { /* Default select the mux pins for GPIO */ W_REG(osh, &chipcb->cru_gpio_control0, 0x1fffff); } si_setcoreidx(sih, origidx); si_gpioouten(sih, PWR_LED_GPIO, PWR_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioouten(sih, USB_LED_GPIO, USB_LED_GPIO, GPIO_DRV_PRIORITY); #ifdef RTAC68U si_gpioouten(sih, TURBO_LED_GPIO, TURBO_LED_GPIO, GPIO_DRV_PRIORITY); #endif #ifndef RTN18U si_gpioouten(sih, WL5G_LED_GPIO, WL5G_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioouten(sih, USB3_LED_GPIO, USB3_LED_GPIO, GPIO_DRV_PRIORITY); #endif #ifndef RTAC68U si_gpioouten(sih, WAN_LED_GPIO, WAN_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioouten(sih, LAN_LED_GPIO, LAN_LED_GPIO, GPIO_DRV_PRIORITY); #endif #ifndef RTN18U // for RT-AC56U & RT-AC68U si_gpioouten(sih, USB_PWR1_GPIO, USB_PWR1_GPIO, GPIO_DRV_PRIORITY); #ifndef RTAC68U si_gpioouten(sih, USB_PWR2_GPIO, USB_PWR2_GPIO, GPIO_DRV_PRIORITY); #endif #endif #ifdef RTN18U // RT-N18U si_gpioouten(sih, USB_PWR1_GPIO, USB_PWR1_GPIO, GPIO_DRV_PRIORITY); si_gpioouten(sih, WL2G_LED_GPIO, WL2G_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioouten(sih, USB3_LED_GPIO, USB3_LED_GPIO, GPIO_DRV_PRIORITY); #endif si_gpioout(sih, PWR_LED_GPIO, 0, GPIO_DRV_PRIORITY); si_gpioout(sih, USB_LED_GPIO, USB_LED_GPIO, GPIO_DRV_PRIORITY); #ifdef RTAC68U si_gpioout(sih, TURBO_LED_GPIO, 0, GPIO_DRV_PRIORITY); #endif #ifndef RTN18U // for RT-AC56U & RT-AC68U to enable USB power si_gpioout(sih, WL5G_LED_GPIO, WL5G_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioout(sih, USB3_LED_GPIO, USB3_LED_GPIO, GPIO_DRV_PRIORITY); #endif #ifndef RTAC68U si_gpioout(sih, WAN_LED_GPIO, WAN_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioout(sih, LAN_LED_GPIO, LAN_LED_GPIO, GPIO_DRV_PRIORITY); #endif #ifndef RTN18U // for RT-AC56U & RT-AC68U to enable USB power si_gpioout(sih, USB_PWR1_GPIO, USB_PWR1_GPIO, GPIO_DRV_PRIORITY); #ifndef RTAC68U si_gpioout(sih, USB_PWR2_GPIO, USB_PWR2_GPIO, GPIO_DRV_PRIORITY); #endif #endif #ifdef RTN18U // RT-N18U /* enable USB power */ si_gpioout(sih, USB_PWR1_GPIO, USB_PWR1_GPIO, GPIO_DRV_PRIORITY); /* power on LEDs */ si_gpioout(sih, PWR_LED_GPIO, PWR_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioout(sih, WL2G_LED_GPIO, WL2G_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioout(sih, WAN_LED_GPIO, WAN_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioout(sih, LAN_LED_GPIO, LAN_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioout(sih, USB_LED_GPIO, USB_LED_GPIO, GPIO_DRV_PRIORITY); si_gpioout(sih, USB3_LED_GPIO, USB3_LED_GPIO, GPIO_DRV_PRIORITY); #endif }
static int __init init_bcm947xx_map(void) { ulong flags; uint coreidx; chipcregs_t *cc; uint32 fltype; uint window_addr = 0, window_size = 0; size_t size; int ret = 0; #ifdef CONFIG_MTD_PARTITIONS struct mtd_partition *parts; #endif spin_lock_irqsave(&sih_lock, flags); coreidx = si_coreidx(sih); /* Check strapping option if chipcommon exists */ if ((cc = si_setcore(sih, CC_CORE_ID, 0))) { fltype = readl(&cc->capabilities) & CC_CAP_FLASH_MASK; if (fltype == PFLASH) { bcm947xx_map.map_priv_2 = 1; window_addr = 0x1c000000; bcm947xx_map.size = window_size = 32 * 1024 * 1024; if ((readl(&cc->flash_config) & CC_CFG_DS) == 0) bcm947xx_map.bankwidth = 1; } } else { fltype = PFLASH; bcm947xx_map.map_priv_2 = 0; window_addr = WINDOW_ADDR; bcm947xx_map.size = window_size = WINDOW_SIZE; } si_setcoreidx(sih, coreidx); spin_unlock_irqrestore(&sih_lock, flags); if (fltype != PFLASH) { printk(KERN_ERR "pflash: found no supported devices\n"); ret = -ENODEV; goto fail; } bcm947xx_map.virt = ioremap(window_addr, window_size); if (bcm947xx_map.virt == NULL) { printk(KERN_ERR "pflash: ioremap failed\n"); ret = -EIO; goto fail; } if ((bcm947xx_mtd = do_map_probe("cfi_probe", &bcm947xx_map)) == NULL) { printk(KERN_ERR "pflash: cfi_probe failed\n"); ret = -ENXIO; goto fail; } bcm947xx_mtd->owner = THIS_MODULE; /* Allow size override for testing */ size = flash ? : bcm947xx_mtd->size; printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, window_addr); #ifdef CONFIG_MTD_PARTITIONS parts = init_mtd_partitions(bcm947xx_mtd, size); ret = add_mtd_partitions(bcm947xx_mtd, parts, 4); if (ret) { printk(KERN_ERR "pflash: add_mtd_partitions failed\n"); goto fail; } #endif return 0; fail: if (bcm947xx_mtd) map_destroy(bcm947xx_mtd); if (bcm947xx_map.map_priv_1) iounmap((void *) bcm947xx_map.map_priv_1); bcm947xx_map.map_priv_1 = 0; return ret; }
/* change logical "focus" to the gpio core for optimized access */ void * si_gpiosetcore(si_t *sih) { return (si_setcoreidx(sih, SI_CC_IDX)); }
static uint32 config_cmd(si_t *sih, uint bus, uint dev, uint func, uint off) { uint coreidx; sbpciregs_t *pci; uint32 addr = 0, *sbtopci1; osl_t *osh; uint8 port; /* CardBusMode supports only one device */ if (cardbus && dev > 1) return 0; /* Convert logical bus to physical port/bus for following processing */ port = PCIE_GET_PORT_BY_BUS(bus); if (port == 1) { /* 1-based bus number */ bus = bus - PCIE_PORT1_BUS_START + 1; } osh = si_osh(sih); coreidx = si_coreidx(sih); pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, port); if (pci) { sbtopci1 = &pci->sbtopci1; } else { sbpcieregs_t *pcie; pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, port); /* Issue config commands only when the data link is up (atleast * one external pcie device is present). */ if (pcie && (dev < 2) && (pcie_readreg(osh, pcie, PCIE_PCIEREGS, PCIE_DLLP_LSREG) & PCIE_DLLP_LSREG_LINKUP)) { sbtopci1 = &pcie->sbtopcie1; } else { si_setcoreidx(sih, coreidx); return 0; } } /* Type 0 transaction */ if (bus == 1) { /* Skip unwired slots */ if (dev < PCI_SLOT_MAX) { /* Slide the PCI window to the appropriate slot */ if (pci) { uint32 win; win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); W_REG(osh, sbtopci1, win); addr = (SI_PCI_CFG(port) | ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | (func << PCICFG_FUN_SHIFT) | (off & ~3)); } else { W_REG(osh, sbtopci1, SBTOPCI_CFG0); addr = (SI_PCI_CFG(port) | (dev << PCIECFG_SLOT_SHIFT) | (func << PCIECFG_FUN_SHIFT) | (off & ~3)); } } } else { /* Type 1 transaction */ addr = SI_PCI_CFG(port); if (pci) { addr |= PCI_CONFIG_ADDR(bus, dev, func, (off & ~3)); /* * Higher bus bits (which lets the address exceed the 64MB space) * should be specified in sbtopci1's UpperAddress. */ W_REG(osh, sbtopci1, SBTOPCI_CFG1 | (addr & SBTOPCI1_MASK)); /* To not exceed the 64MB space (by using UA instead) */ addr &= ~SBTOPCI1_MASK; } else { addr |= PCIE_CONFIG_ADDR((bus - 1), dev, func, (off & ~3)); /* * Higher bus bits (which lets the address exceed the 64MB space) * should be specified in sbtopci1's UpperAddress. */ W_REG(osh, sbtopci1, SBTOPCI_CFG1 | (addr & SBTOPCIE1_MASK)); /* To not exceed the 64MB space (by using UA instead) */ addr &= ~SBTOPCIE1_MASK; } } si_setcoreidx(sih, coreidx); return addr; }
static si_info_t * si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, uint bustype, void *sdh, char **vars, uint *varsz) { struct si_pub *sih = &sii->pub; uint32 w, savewin; chipcregs_t *cc; char *pvars = NULL; uint origidx; ASSERT(GOODREGS(regs)); bzero((uchar*)sii, sizeof(si_info_t)); { if (NULL == (common_info_alloced = (void *)MALLOC(osh, sizeof(si_common_info_t)))) { SI_ERROR(("si_doattach: malloc failed! malloced %dbytes\n", MALLOCED(osh))); return (NULL); } bzero((uchar*)(common_info_alloced), sizeof(si_common_info_t)); } sii->common_info = (si_common_info_t *)common_info_alloced; sii->common_info->attach_count++; savewin = 0; sih->buscoreidx = BADIDX; sii->curmap = regs; sii->sdh = sdh; sii->osh = osh; /* find Chipcommon address */ if (bustype == PCI_BUS) { savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) savewin = SI_ENUM_BASE; OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); cc = (chipcregs_t *)regs; } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { cc = (chipcregs_t *)sii->curmap; } else { cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); } sih->bustype = bustype; if (bustype != BUSTYPE(bustype)) { SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype))); return NULL; } /* bus/core/clk setup for register access */ if (!si_buscore_prep(sii, bustype, devid, sdh)) { SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); return NULL; } /* ChipID recognition. * We assume we can read chipid at offset 0 from the regs arg. * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), * some way of recognizing them needs to be added here. */ w = R_REG(osh, &cc->chipid); sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; /* Might as wll fill in chip id rev & pkg */ sih->chip = w & CID_ID_MASK; sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chippkg != BCM4329_289PIN_PKG_ID)) sih->chippkg = BCM4329_182PIN_PKG_ID; sih->issim = IS_SIM(sih->chippkg); /* scan for cores */ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { SI_MSG(("Found chip type SB (0x%08x)\n", w)); sb_scan(&sii->pub, regs, devid); } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { SI_MSG(("Found chip type AI (0x%08x)\n", w)); /* pass chipc address instead of original core base */ ai_scan(&sii->pub, (void *)cc, devid); } else { SI_ERROR(("Found chip of unkown type (0x%08x)\n", w)); return NULL; } /* no cores found, bail out */ if (sii->numcores == 0) { SI_ERROR(("si_doattach: could not find any cores\n")); return NULL; } /* bus/core/clk setup */ origidx = SI_CC_IDX; if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { SI_ERROR(("si_doattach: si_buscore_setup failed\n")); return NULL; } pvars = NULL; if (sii->pub.ccrev >= 20) { cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); W_REG(osh, &cc->gpiopullup, 0); W_REG(osh, &cc->gpiopulldown, 0); si_setcoreidx(sih, origidx); } /* Skip PMU initialization from the Dongle Host. * Firmware will take care of it when it comes up. */ return (sii); }
/* Initialize serial flash access */ hndsflash_t * ccsflash_init(si_t *sih) { chipcregs_t *cc; uint32 id, id2; const char *name = ""; osl_t *osh; ASSERT(sih); /* No sflash for NorthStar */ if (sih->ccrev == 42) return NULL; if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX)) == NULL) return NULL; if (!firsttime && ccsflash.size != 0) return &ccsflash; osh = si_osh(sih); bzero(&ccsflash, sizeof(ccsflash)); ccsflash.sih = sih; ccsflash.core = (void *)cc; ccsflash.read = ccsflash_read; ccsflash.write = ccsflash_write; ccsflash.erase = ccsflash_erase; ccsflash.commit = ccsflash_commit; ccsflash.poll = ccsflash_poll; ccsflash.type = sih->cccaps & CC_CAP_FLASH_MASK; switch (ccsflash.type) { case SFLASH_ST: /* Probe for ST chips */ name = "ST compatible"; ccsflash_cmd(osh, cc, SFLASH_ST_DP); W_REG(osh, &cc->flashaddress, 0); ccsflash_cmd(osh, cc, SFLASH_ST_RES); id = R_REG(osh, &cc->flashdata); ccsflash.blocksize = 64 * 1024; switch (id) { case 0x11: /* ST M25P20 2 Mbit Serial Flash */ ccsflash.numblocks = 4; break; case 0x12: /* ST M25P40 4 Mbit Serial Flash */ ccsflash.numblocks = 8; break; case 0x13: ccsflash_cmd(osh, cc, SFLASH_MXIC_RDID); id = R_REG(osh, &cc->flashdata); if (id == SFLASH_MXIC_MFID) { /* MXIC MX25L8006E 8 Mbit Serial Flash */ ccsflash.blocksize = 4 * 1024; ccsflash.numblocks = 16 * 16; } else { /* ST M25P80 8 Mbit Serial Flash */ ccsflash.numblocks = 16; } break; case 0x14: /* ST M25P16 16 Mbit Serial Flash */ ccsflash.numblocks = 32; break; case 0x15: /* ST M25P32 32 Mbit Serial Flash */ ccsflash.numblocks = 64; break; case 0x16: /* ST M25P64 64 Mbit Serial Flash */ ccsflash.numblocks = 128; break; case 0x17: /* ST M25FL128 128 Mbit Serial Flash */ ccsflash.numblocks = 256; break; case 0xbf: /* All of the following flashes are SST with * 4KB subsectors. Others should be added but * We'll have to revamp the way we identify them * since RES is not eough to disambiguate them. */ name = "SST"; ccsflash.blocksize = 4 * 1024; W_REG(osh, &cc->flashaddress, 1); ccsflash_cmd(osh, cc, SFLASH_ST_RES); id2 = R_REG(osh, &cc->flashdata); switch (id2) { case 1: /* SST25WF512 512 Kbit Serial Flash */ ccsflash.numblocks = 16; break; case 0x48: /* SST25VF512 512 Kbit Serial Flash */ ccsflash.numblocks = 16; break; case 2: /* SST25WF010 1 Mbit Serial Flash */ ccsflash.numblocks = 32; break; case 0x49: /* SST25VF010 1 Mbit Serial Flash */ ccsflash.numblocks = 32; break; case 3: /* SST25WF020 2 Mbit Serial Flash */ ccsflash.numblocks = 64; break; case 0x43: /* SST25VF020 2 Mbit Serial Flash */ ccsflash.numblocks = 64; break; case 4: /* SST25WF040 4 Mbit Serial Flash */ ccsflash.numblocks = 128; break; case 0x44: /* SST25VF040 4 Mbit Serial Flash */ ccsflash.numblocks = 128; break; case 0x8d: /* SST25VF040B 4 Mbit Serial Flash */ ccsflash.numblocks = 128; break; case 5: /* SST25WF080 8 Mbit Serial Flash */ ccsflash.numblocks = 256; break; case 0x8e: /* SST25VF080B 8 Mbit Serial Flash */ ccsflash.numblocks = 256; break; case 0x41: /* SST25VF016 16 Mbit Serial Flash */ ccsflash.numblocks = 512; break; case 0x4a: /* SST25VF032 32 Mbit Serial Flash */ ccsflash.numblocks = 1024; break; case 0x4b: /* SST25VF064 64 Mbit Serial Flash */ ccsflash.numblocks = 2048; break; } break; } break; case SFLASH_AT: /* Probe for Atmel chips */ name = "Atmel"; ccsflash_cmd(osh, cc, SFLASH_AT_STATUS); id = R_REG(osh, &cc->flashdata) & 0x3c; switch (id) { case 0xc: /* Atmel AT45DB011 1Mbit Serial Flash */ ccsflash.blocksize = 256; ccsflash.numblocks = 512; break; case 0x14: /* Atmel AT45DB021 2Mbit Serial Flash */ ccsflash.blocksize = 256; ccsflash.numblocks = 1024; break; case 0x1c: /* Atmel AT45DB041 4Mbit Serial Flash */ ccsflash.blocksize = 256; ccsflash.numblocks = 2048; break; case 0x24: /* Atmel AT45DB081 8Mbit Serial Flash */ ccsflash.blocksize = 256; ccsflash.numblocks = 4096; break; case 0x2c: /* Atmel AT45DB161 16Mbit Serial Flash */ ccsflash.blocksize = 512; ccsflash.numblocks = 4096; break; case 0x34: /* Atmel AT45DB321 32Mbit Serial Flash */ ccsflash.blocksize = 512; ccsflash.numblocks = 8192; break; case 0x3c: /* Atmel AT45DB642 64Mbit Serial Flash */ ccsflash.blocksize = 1024; ccsflash.numblocks = 8192; break; } break; } ccsflash.size = ccsflash.blocksize * ccsflash.numblocks; ccsflash.phybase = SI_FLASH2; if (firsttime) printf("Found an %s serial flash with %d %dKB blocks; total size %dMB\n", name, ccsflash.numblocks, ccsflash.blocksize / 1024, ccsflash.size / (1024 * 1024)); firsttime = FALSE; return ccsflash.size ? &ccsflash : NULL; }
int si_bist_d11(si_t *sih, uint32 *biststatus1, uint32 *biststatus2) { si_info_t *sii; uint origidx; uint intr_val = 0; void *regs; int error = 0; bool wasup; uint32 offset = SBCONFIGOFF + SBTMSTATELOW; uint32 max_res_mask; uint32 pmu_ctrl; *biststatus1 = 0; *biststatus2 = 0; SI_ERROR(("doing the bist on D11\n")); sii = SI_INFO(sih); if (CHIPTYPE(sih->socitype) != SOCI_SB) { return 0; } /* Block ints and save current core */ INTR_OFF(sii, intr_val); origidx = si_coreidx(sih); /* Switch to D11 core */ if (!(regs = si_setcore(sih, D11_CORE_ID, 0))) goto done; /* Get info for determining size */ /* coming out of reset device shoudl have clk enabled, bw set, etc */ if (!(wasup = si_iscoreup(sih))) si_core_reset(sih, 0x4F, 0x4F); max_res_mask = si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), 0, 0); si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), ~0, 0x3fffff); if (si_corerev(&sii->pub) == 20) { uint32 phy_reset_val; uint32 bist_test_val, bist_status; /* XXX: enable the phy PLL */ pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); pmu_ctrl |= 0x000010000; si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, ~0, pmu_ctrl); SPINWAIT(((si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0) & 0x01000000) == 0), 1000000); pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); /* take the phy out of reset */ phy_reset_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); phy_reset_val &= ~(0x0008 << SBTML_SICF_SHIFT); si_corereg(sih, si_coreidx(&sii->pub), offset, ~0, phy_reset_val); phy_reset_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); /* enable bist first */ bist_test_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); bist_test_val |= (SICF_BIST_EN << 16); si_corereg(sih, si_coreidx(&sii->pub), offset, ~0, bist_test_val); SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 1000000); bist_status = si_core_sflags(sih, 0, 0); SI_ERROR(("status are 0x%08x\n", bist_status)); if (bist_status & SISF_BIST_DONE) { if (bist_status & SISF_BIST_ERROR) { error = 1; *biststatus1 = si_corereg(sih, si_coreidx(&sii->pub), 12, 0, 0); *biststatus2 = si_corereg(sih, si_coreidx(&sii->pub), 16, 0, 0); } } /* stop the phy pll */ pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); pmu_ctrl &= ~0x10000; si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, ~0, pmu_ctrl); } /* remove the resource mask */ si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), ~0, max_res_mask); /* Return to previous state and core */ if (!wasup) si_core_disable(sih, 0); /* Return to previous state and core */ si_setcoreidx(sih, origidx); done: INTR_RESTORE(sii, intr_val); return error; }
int flashDrvLibInit(void) { FLASH_TYPES dev; FLASH_VENDORS vendor; int i; uint32 fltype = PFLASH; osl_t *osh; struct sflash *sflash; if (flashDrvInitialized) return (OK); flashBaseAddress = FLASH_BASE_ADDRESS_ALIAS; /* * Check for serial flash. */ sih = si_kattach(SI_OSH); ASSERT(sih); osh = si_osh(sih); cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); ASSERT(cc); /* Select SFLASH */ fltype = R_REG(osh, &cc->capabilities) & CC_CAP_FLASH_MASK; if (fltype == SFLASH_ST || fltype == SFLASH_AT) { sflash = sflash_init(sih, cc); if (sflash == NULL) { printf("flashInit(): Unrecognized Device (SFLASH)\n"); return (ERROR); } flashDrvFuncs = &flashsflash; flashDrvFuncs->flashAutoSelect(&dev, &vendor); flashSectorCount = sflash->numblocks; flashDevSectorSize = sflash->blocksize; if (flashVerbose) { printf("flashInit(): SFLASH Found\n"); } } else { flashDrvFuncs = &flashs29gl256p; flashDrvFuncs->flashAutoSelect(&dev, &vendor); if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash29gl128; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash29l640; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash29l320; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash29l160; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } if ((vendor == 0xFF) && (dev == 0xFF)) { flashDrvFuncs = &flash28f320; flashDrvFuncs->flashAutoSelect(&dev, &vendor); } switch (vendor) { case AMD: case ALLIANCE: case MXIC: switch (dev) { case FLASH_2F040: flashSectorCount = 8; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 2F040 Found\n"); break; case FLASH_2F080: flashSectorCount = 16; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 2F080 Found\n"); break; case FLASH_2L081: flashSectorCount = 16; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 29LV081B Found\n"); break; case FLASH_2L160: case FLASH_2L017: flashSectorCount = 32; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 29LV160D Found\n"); break; case FLASH_2L640: case FLASH_MX2L640: flashSectorCount = 128; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 29LV640M Found\n"); break; case FLASH_29GL128: /* Spansion 29GL128 is physically 128 sector count * To make flash support backward compatible to old device, * only use 64 for 8MB */ flashSectorCount = 64; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): 29GL128 Found\n"); break; case FLASH_2L320: flashSectorCount = 64; flashDevSectorSize = 0x10000; if (flashVerbose) printf("flashInit(): 29LV320D Found\n"); break; case FLASH_S29GL128P: flashSectorCount = 128; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): FLASH_S29GL128P Found\n"); break; case FLASH_S29GL256P: flashSectorCount = 256; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): S29GL256P Found\n"); break; case FLASH_S29GL512P: flashSectorCount = 512; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): FLASH_S29GL512P Found\n"); break; case FLASH_S29GL01GP: flashSectorCount = 1024; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): FLASH_S29GL01GP Found\n"); break; default: printf("flashInit(): Unrecognized Device (0x%02X)\n", dev); return (ERROR); } break; case INTEL: switch (dev) { case FLASH_2F320: flashSectorCount = 32; flashDevSectorSize = 0x20000; if (flashVerbose) printf("flashInit(): 28F320 Found\n"); break; default: printf("flashInit(): Unrecognized Device (0x%02X)\n", dev); return (ERROR); } break; default: printf("flashInit(): Unrecognized Vendor (0x%02X)\n", vendor); return (ERROR); } } flashSize = flashDevSectorSize * flashSectorCount; for (i = 0; i < TOTAL_LOADED_SECS; i++) { flashLoadedSectors[i].buffer = malloc(FLASH_SECTOR_SIZE); if (flashLoadedSectors[i].buffer == NULL) { printf("flashInit(): malloc() failed\n"); for (; i > 0; i--) { free(flashLoadedSectors[i-1].buffer); } return (ERROR); } flashLoadedSectors[i].sector = -1; flashLoadedSectors[i].dirty = 0; flashLoadedSectors[i].fsSemID = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE); } flashDrvInitialized ++; return (OK); }
static void flash_init(void) { newflash_probe_t fprobe; int bootdev; uint32 bootsz, *bisz; cfe_driver_t *drv = NULL; int j = 0; fl_size_t max_image_size = 0; int rom_envram_size; #if defined(DUAL_IMAGE) || defined(FAILSAFE_UPGRADE) int need_commit = 0; #endif #ifdef CFG_NFLASH hndnand_t *nfl_info = NULL; #endif #if CFG_SFLASH hndsflash_t *sfl_info = NULL; #endif memset(&fprobe, 0, sizeof(fprobe)); bootdev = soc_boot_dev((void *)sih); if(!nvram_match("nospare", "0")) nospare = 1; else nospare = 0; #ifdef CFG_NFLASH if (bootdev == SOC_BOOTDEV_NANDFLASH) { nfl_info = hndnand_init(sih); if (!nfl_info) return; fprobe.flash_phys = nfl_info->phybase; drv = &nflashdrv; } else #endif /* CFG_NFLASH */ #if CFG_SFLASH if (bootdev == SOC_BOOTDEV_SFLASH) { sfl_info = hndsflash_init(sih); if (!sfl_info) return; fprobe.flash_phys = sfl_info->phybase; drv = &sflashdrv; } else #endif #if CFG_FLASH { /* This might be wrong, but set pflash * as default if nothing configured */ chipcregs_t *cc; if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX)) == NULL) return; fprobe.flash_phys = SI_FLASH2; fprobe.flash_flags = FLASH_FLG_BUS16 | FLASH_FLG_DEV16; if (!(R_REG(NULL, &cc->flash_config) & CC_CFG_DS)) fprobe.flash_flags = FLASH_FLG_BUS8 | FLASH_FLG_DEV16; drv = &newflashdrv; } #endif /* CFG_FLASH */ ASSERT(drv); /* Default is 256K boot partition */ bootsz = 256 * 1024; /* Do we have a self-describing binary image? */ bisz = (uint32 *)UNCADDR(fprobe.flash_phys + BISZ_OFFSET); if (bisz[BISZ_MAGIC_IDX] == BISZ_MAGIC) { int isz = bisz[BISZ_DATAEND_IDX] - bisz[BISZ_TXTST_IDX]; if (isz > (1024 * 1024)) bootsz = 2048 * 1024; else if (isz > (512 * 1024)) bootsz = 1024 * 1024; else if (isz > (256 * 1024)) bootsz = 512 * 1024; else if (isz <= (128 * 1024)) bootsz = 128 * 1024; } printf("Boot partition size = %d(0x%x)\n", bootsz, bootsz); #if CFG_NFLASH if (nfl_info) { fl_size_t flash_size = 0; if (bootsz > nfl_info->blocksize) { /* Prepare double space in case of bad blocks */ bootsz = (bootsz << 1); } else { /* CFE occupies at least one block */ bootsz = nfl_info->blocksize; } /* Because sometimes we want to program the entire device */ fprobe.flash_nparts = 0; cfe_add_device(drv, 0, 0, &fprobe); #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) max_image_size = calculate_max_image_size("nflash0", nfl_boot_size(nfl_info), 0, &need_commit, nfl_boot_os_size(nfl_info)); #endif /* Because sometimes we want to program the entire device */ /* Because CFE can only boot from the beginning of a partition */ j = 0; fprobe.flash_parts[j].fp_size = bootsz; fprobe.flash_parts[j++].fp_name = "boot"; fprobe.flash_parts[j].fp_size = (nfl_boot_size(nfl_info) - bootsz); fprobe.flash_parts[j++].fp_name = "nvram"; fprobe.flash_parts[j].fp_size = sizeof(struct trx_header); fprobe.flash_parts[j++].fp_name = "trx"; fprobe.flash_parts[j].fp_size = max_image_size ? max_image_size - sizeof(struct trx_header) : 0; fprobe.flash_parts[j++].fp_name = "os"; #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (max_image_size) { fprobe.flash_parts[j].fp_size = sizeof(struct trx_header); fprobe.flash_parts[j++].fp_name = "trx2"; fprobe.flash_parts[j].fp_size = max_image_size; fprobe.flash_parts[j++].fp_name = "os2"; } #endif fprobe.flash_nparts = j; cfe_add_device(drv, 0, 0, &fprobe); /* Because CFE can only flash an entire partition */ j = 0; fprobe.flash_parts[j].fp_size = bootsz; fprobe.flash_parts[j++].fp_name = "boot"; fprobe.flash_parts[j].fp_size = (nfl_boot_size(nfl_info) - bootsz); fprobe.flash_parts[j++].fp_name = "nvram"; fprobe.flash_parts[j].fp_size = max_image_size; fprobe.flash_parts[j++].fp_name = "trx"; #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (max_image_size) { fprobe.flash_parts[j].fp_size = nfl_boot_os_size(nfl_info) - nfl_boot_size(nfl_info) - max_image_size; fprobe.flash_parts[j++].fp_name = "trx2"; } #endif flash_size = get_flash_size("nflash0") - nfl_boot_os_size(nfl_info); #ifdef DUAL_TRX fprobe.flash_parts[j].fp_size = NFL_BOOT_OS_SIZE; fprobe.flash_parts[j++].fp_name = "trx2"; flash_size -= NFL_BOOT_OS_SIZE; #endif if (flash_size > 0) { fprobe.flash_parts[j].fp_size = flash_size; fprobe.flash_parts[j++].fp_name = "brcmnand"; } fprobe.flash_nparts = j; cfe_add_device(drv, 0, 0, &fprobe); /* Change nvram device name for NAND boot */ flashdrv_nvram = "nflash0.nvram"; } else #endif /* CFG_NFLASH */ { /* Because sometimes we want to program the entire device */ fprobe.flash_nparts = 0; cfe_add_device(drv, 0, 0, &fprobe); #ifdef CFG_ROMBOOT if (board_bootdev_rom(sih)) { rom_envram_size = ROM_ENVRAM_SPACE; } else #endif { rom_envram_size = 0; } #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) /* If the kernel is not in nand flash, split up the sflash */ if (soc_knl_dev((void *)sih) != SOC_KNLDEV_NANDFLASH) { max_image_size = calculate_max_image_size("flash0", bootsz, MAX_NVRAM_SPACE+rom_envram_size, &need_commit, 0); } #endif /* Because CFE can only boot from the beginning of a partition */ j = 0; fprobe.flash_parts[j].fp_size = bootsz; fprobe.flash_parts[j++].fp_name = "boot"; fprobe.flash_parts[j].fp_size = sizeof(struct trx_header); fprobe.flash_parts[j++].fp_name = "trx"; fprobe.flash_parts[j].fp_size = max_image_size ? max_image_size - sizeof(struct trx_header) : 0; fprobe.flash_parts[j++].fp_name = "os"; #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (max_image_size) { fprobe.flash_parts[j].fp_size = sizeof(struct trx_header); fprobe.flash_parts[j++].fp_name = "trx2"; fprobe.flash_parts[j].fp_size = 0; fprobe.flash_parts[j++].fp_name = "os2"; } #endif #ifdef CFG_ROMBOOT if (rom_envram_size) { fprobe.flash_parts[j].fp_size = rom_envram_size; fprobe.flash_parts[j++].fp_name = "envram"; } #endif #ifdef BCM_DEVINFO fprobe.flash_parts[j].fp_size = 0x80000; fprobe.flash_parts[j++].fp_name = "fs_rw"; fprobe.flash_parts[j].fp_size = 0x10000; fprobe.flash_parts[j++].fp_name = "devinfo"; #endif /* BCM_DEVINFO */ fprobe.flash_parts[j].fp_size = MAX_NVRAM_SPACE; fprobe.flash_parts[j++].fp_name = "nvram"; fprobe.flash_nparts = j; cfe_add_device(drv, 0, 0, &fprobe); /* Because CFE can only flash an entire partition */ j = 0; fprobe.flash_parts[j].fp_size = bootsz; fprobe.flash_parts[j++].fp_name = "boot"; fprobe.flash_parts[j].fp_size = max_image_size; fprobe.flash_parts[j++].fp_name = "trx"; #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (max_image_size) { fprobe.flash_parts[j].fp_size = 0; fprobe.flash_parts[j++].fp_name = "trx2"; } #endif #ifdef CFG_ROMBOOT if (rom_envram_size) { fprobe.flash_parts[j].fp_size = rom_envram_size; fprobe.flash_parts[j++].fp_name = "envram"; } #endif #ifdef BCM_DEVINFO fprobe.flash_parts[j].fp_size = 0x80000; fprobe.flash_parts[j++].fp_name = "fs_rw"; fprobe.flash_parts[j].fp_size = 0x10000; fprobe.flash_parts[j++].fp_name = "devinfo"; #endif /* BCM_DEVINFO */ fprobe.flash_parts[j].fp_size = MAX_NVRAM_SPACE; fprobe.flash_parts[j++].fp_name = "nvram"; fprobe.flash_nparts = j; cfe_add_device(drv, 0, 0, &fprobe); } #if (CFG_FLASH || CFG_SFLASH) flash_memory_size_config(sih, (void *)&fprobe); #endif /* (CFG_FLASH || CFG_SFLASH) */ #ifdef CFG_NFLASH /* If boot from sflash, try to init partition for JFFS2 anyway */ if (nfl_info == NULL) flash_nflash_init(); #endif /* CFG_NFLASH */ #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (need_commit) nvram_commit(); #endif }
/** * Balance between stable SDIO operation and power consumption is achieved using this function. * Note that each drive strength table is for a specific VDDIO of the SDIO pads, ideally this * function should read the VDDIO itself to select the correct table. For now it has been solved * with the 'BCM_SDIO_VDDIO' preprocessor constant. * * 'drivestrength': desired pad drive strength in mA. Drive strength of 0 requests tri-state (if * hardware supports this), if no hw support drive strength is not programmed. */ void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) { sdiod_drive_str_t *str_tab = NULL; uint32 str_mask = 0; /* only alter desired bits in PMU chipcontrol 1 register */ uint32 str_shift = 0; uint32 str_ovr_pmuctl = PMU_CHIPCTL0; /* PMU chipcontrol register containing override bit */ uint32 str_ovr_pmuval = 0; /* position of bit within this register */ pmuregs_t *pmu; uint origidx; if (!(sih->cccaps & CC_CAP_PMU)) { return; } /* Remember original core before switch to chipc/pmu */ origidx = si_coreidx(sih); if (AOB_ENAB(sih)) { pmu = si_setcore(sih, PMU_CORE_ID, 0); } else { pmu = si_setcoreidx(sih, SI_CC_IDX); } ASSERT(pmu != NULL); switch (SDIOD_DRVSTR_KEY(CHIPID(sih->chip), sih->pmurev)) { case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1): str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1; str_mask = 0x30000000; str_shift = 28; break; case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2): case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3): case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4): str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2; str_mask = 0x00003800; str_shift = 11; break; case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11): if (sih->pmurev == 8) { str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3; } else if (sih->pmurev == 11) { str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; } str_mask = 0x00003800; str_shift = 11; break; case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; str_mask = 0x00003800; str_shift = 11; break; case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8; str_mask = 0x00003800; str_shift = 11; break; case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17): str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab6_1v8; str_mask = 0x00001800; str_shift = 11; break; case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): #if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33 if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_3v3)->strength) { str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_3v3; } #else if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_1v8)->strength) { str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_1v8; } #endif /* BCM_SDIO_VDDIO */ str_mask = 0x00000007; str_ovr_pmuval = PMU43143_CC0_SDIO_DRSTR_OVR; break; default: PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", bcm_chipname( CHIPID(sih->chip), chn, 8), CHIPREV(sih->chiprev), sih->pmurev)); break; } if (str_tab != NULL) { uint32 cc_data_temp; int i; /* Pick the lowest available drive strength equal or greater than the * requested strength. Drive strength of 0 requests tri-state. */ for (i = 0; drivestrength < str_tab[i].strength; i++) ; if (i > 0 && drivestrength > str_tab[i].strength) i--; W_REG(osh, &pmu->chipcontrol_addr, PMU_CHIPCTL1); cc_data_temp = R_REG(osh, &pmu->chipcontrol_data); cc_data_temp &= ~str_mask; cc_data_temp |= str_tab[i].sel << str_shift; W_REG(osh, &pmu->chipcontrol_data, cc_data_temp); if (str_ovr_pmuval) { /* enables the selected drive strength */ W_REG(osh, &pmu->chipcontrol_addr, str_ovr_pmuctl); OR_REG(osh, &pmu->chipcontrol_data, str_ovr_pmuval); } PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n", drivestrength, str_tab[i].strength)); } /* Return to original core */ si_setcoreidx(sih, origidx); } /* si_sdiod_drive_strength_init */