示例#1
0
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), &regs->intmask);
		cc_intmask |= ccintmask;
		W_REG(si_osh(sih), &regs->intmask, cc_intmask);
	}

	/* restore original coreidx */
	si_setcoreidx(sih, origidx);
	return done;
}
示例#2
0
/* 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;
}
示例#3
0
/* 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);

}
示例#4
0
/* 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;
}
示例#5
0
/* 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);
}
示例#6
0
/*
 * 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));
	}
}
示例#7
0
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;
}
示例#8
0
/* 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, &regs->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;
}
示例#9
0
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;
}
示例#10
0
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);
}
示例#11
0
文件: hndchipc.c 项目: ariavie/bcm
/*
 * 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);
}
示例#12
0
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);
}
示例#13
0
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
示例#14
0
/* 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;
}
示例#15
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);
}
示例#16
0
/*
 * 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);
	}
}
示例#17
0
文件: hndchipc.c 项目: ariavie/bcm
/*
 * 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);
    }
}
示例#18
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;
}
示例#19
0
/* 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);
}
示例#20
0
文件: hndpci.c 项目: hajuuk/R7000
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;
}
示例#21
0
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
}
示例#22
0
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;
}
示例#23
0
/* change logical "focus" to the gpio core for optimized access */
void *
si_gpiosetcore(si_t *sih)
{
	return (si_setcoreidx(sih, SI_CC_IDX));
}
示例#24
0
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;
}
示例#25
0
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);
}
示例#26
0
文件: ccsflash.c 项目: hajuuk/R7000
/* 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;
}
示例#27
0
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;
}
示例#28
0
文件: flashDrvLib.c 项目: ariavie/bcm
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);
}
示例#29
0
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
}
示例#30
0
/**
 * 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 */