Пример #1
0
static uint32
sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr)
{
	uint8 tmp;
	uint32 val, intr_val = 0;


	/*
	 * compact flash only has 11 bits address, while we needs 12 bits address.
	 * MEM_SEG will be OR'd with other 11 bits address in hardware,
	 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
	 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
	 */
	if (PCMCIA(sii)) {
		INTR_OFF(sii, intr_val);
		tmp = 1;
		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
		sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
	}

	val = R_REG(sii->osh, sbr);

	if (PCMCIA(sii)) {
		tmp = 0;
		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
		INTR_RESTORE(sii, intr_val);
	}

	return (val);
}
Пример #2
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);
}
Пример #3
0
/*
 * Switch to 'coreidx', issue a single arbitrary 32bit
 * register mask&set operation,
 * switch back to the original core, and return the new value.
 *
 * When using the silicon backplane, no fidleing with interrupts
 * or core switches are needed.
 *
 * Also, when using pci/pcie, we can optimize away the core switching
 * for pci registers
 * and (on newer pci cores) chipcommon registers.
 */
uint sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
{
	uint origidx = 0;
	u32 *r = NULL;
	uint w;
	uint intr_val = 0;
	bool fast = false;
	si_info_t *sii;

	sii = SI_INFO(sih);

	ASSERT(GOODIDX(coreidx));
	ASSERT(regoff < SI_CORE_SIZE);
	ASSERT((val & ~mask) == 0);

	if (coreidx >= SI_MAXCORES)
		return 0;

	if (!fast) {
		INTR_OFF(sii, intr_val);

		/* save current core index */
		origidx = si_coreidx(&sii->pub);

		/* switch core */
		r = (u32 *) ((unsigned char *) sb_setcoreidx(&sii->pub, coreidx) +
				regoff);
	}
	ASSERT(r != NULL);

	/* mask and set */
	if (mask || val) {
		if (regoff >= SBCONFIGOFF) {
			w = (R_SBREG(sii, r) & ~mask) | val;
			W_SBREG(sii, r, w);
		} else {
			w = (R_REG(sii->osh, r) & ~mask) | val;
			W_REG(sii->osh, r, w);
		}
	}

	/* readback */
	if (regoff >= SBCONFIGOFF)
		w = R_SBREG(sii, r);
	else
		w = R_REG(sii->osh, r);

	if (!fast) {
		/* restore core index */
		if (origidx != coreidx)
			sb_setcoreidx(&sii->pub, origidx);

		INTR_RESTORE(sii, intr_val);
	}

	return w;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
0
/* get gpio registers base addr */
static uint32* get_gpio_base_addr(void) {
        sb_info_t *si;
	uint origidx;
	uint32 *addr = NULL;
	uint intr_val = 0;
	
        si = SB_INFO(sbh);

	INTR_OFF(si, intr_val);

	/* save current core index */
        origidx = sb_coreidx(sbh);

	addr = (uint32*) sb_setcoreidx(sbh, si->gpioidx);

	/* restore core index */
        if (origidx != si->gpioidx) sb_setcoreidx(sbh, origidx);

        INTR_RESTORE(si, intr_val);

	return addr;
}
Пример #7
0
static uint32
sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr)
{
	uint8 tmp;
	uint32 val, intr_val = 0;


	if (PCMCIA(sii)) {
		INTR_OFF(sii, intr_val);
		tmp = 1;
		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
		sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); 
	}

	val = R_REG(sii->osh, sbr);

	if (PCMCIA(sii)) {
		tmp = 0;
		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
		INTR_RESTORE(sii, intr_val);
	}

	return (val);
}
Пример #8
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;
}