/* 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);
}
/* trigger watchdog reset after ms milliseconds */
void
si_watchdog_ms(si_t *sih, uint32 ms)
{
	si_info_t *sii;

	sii = SI_INFO(sih);

	si_watchdog(sih, wd_msticks * ms);
}
/* return list of found cores */
uint
si_corelist(si_t *sih, uint coreid[])
{
	si_info_t *sii;

	sii = SI_INFO(sih);

	bcopy((uchar*)sii->common_info->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
	return (sii->numcores);
}
/* return current register mapping */
void *
si_coreregs(si_t *sih)
{
	si_info_t *sii;

	sii = SI_INFO(sih);
	ASSERT(GOODREGS(sii->curmap));

	return (sii->curmap);
}
uint sb_coreid(si_t *sih)
{
	si_info_t *sii;
	sbconfig_t *sb;

	sii = SI_INFO(sih);
	sb = REGS2SB(sii->curmap);

	return (R_SBREG(sii, &sb->sbidhigh) & SBIDH_CC_MASK) >>
		SBIDH_CC_SHIFT;
}
/* assign the gpio to an led */
uint32
si_gpioled(si_t *sih, uint32 mask, uint32 val)
{
	si_info_t *sii;

	sii = SI_INFO(sih);
	if (sih->ccrev < 16)
		return -1;

	/* gpio led powersave reg */
	return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
}
void
si_setosh(si_t *sih, osl_t *osh)
{
	si_info_t *sii;

	sii = SI_INFO(sih);
	if (sii->osh != NULL) {
		SI_ERROR(("osh is already set....\n"));
		ASSERT(!sii->osh);
	}
	sii->osh = osh;
}
uint sb_corerev(si_t *sih)
{
	si_info_t *sii;
	sbconfig_t *sb;
	uint sbidh;

	sii = SI_INFO(sih);
	sb = REGS2SB(sii->curmap);
	sbidh = R_SBREG(sii, &sb->sbidhigh);

	return SBCOREREV(sbidh);
}
/* return the current gpioin register value */
uint32
si_gpioin(si_t *sih)
{
	si_info_t *sii;
	uint regoff;

	sii = SI_INFO(sih);
	regoff = 0;

	regoff = OFFSETOF(chipcregs_t, gpioin);
	return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
}
bool sb_iscoreup(si_t *sih)
{
	si_info_t *sii;
	sbconfig_t *sb;

	sii = SI_INFO(sih);
	sb = REGS2SB(sii->curmap);

	return (R_SBREG(sii, &sb->sbtmstatelow) &
		 (SBTML_RESET | SBTML_REJ_MASK |
		  (SICF_CLOCK_EN << SBTML_SICF_SHIFT))) ==
		(SICF_CLOCK_EN << SBTML_SICF_SHIFT);
}
/* mask&set gpio timer val */
uint32
si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
{
	si_info_t *sii;

	sii = SI_INFO(sih);

	if (sih->ccrev < 16)
		return -1;

	return (si_corereg(sih, SI_CC_IDX,
		OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
}
uint32
si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
{
	si_info_t *sii;
	uint offs;

	sii = SI_INFO(sih);
	if (sih->ccrev < 20)
		return -1;

	offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
}
uint32
si_gpio_int_enable(si_t *sih, bool enable)
{
	si_info_t *sii;
	uint offs;

	sii = SI_INFO(sih);
	if (sih->ccrev < 11)
		return -1;

	offs = OFFSETOF(chipcregs_t, intmask);
	return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
}
/* Turn off interrupt as required by sb_setcore, before switch core */
void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
{
	void *cc;
	si_info_t *sii;

	sii = SI_INFO(sih);

	INTR_OFF(sii, *intr_val);
	*origidx = sii->curidx;
	cc = si_setcore(sih, coreid, 0);
	ASSERT(cc != NULL);

	return cc;
}
Exemple #15
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;
#ifdef HTC_KlocWork
		sdpcmd_regs_t *sdpregs=NULL;
#else
		sdpcmd_regs_t *sdpregs;
#endif

		/* 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));

#ifdef HTC_KlocWork
		if (sdpregs != NULL) {
			/* 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)));
		} else
			SI_ERROR(("[HTCKW] si_sdio_init: sdpregs is NULL\n"));
#else
		/* 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)));
#endif

		/* switch back to previous core */
		si_setcoreidx(sih, idx);
	}

	/* enable interrupts */
	bcmsdh_intr_enable(sii->sdh);

}
/* 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;
}
/* register driver interrupt disabling and restoring callback functions */
void
si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
                          void *intrsenabled_fn, void *intr_arg)
{
	si_info_t *sii;

	sii = SI_INFO(sih);
	sii->intr_arg = intr_arg;
	sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
	sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
	sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
	/* save current core id.  when this function called, the current core
	 * must be the core which provides driver functions(il, et, wl, etc.)
	 */
	sii->dev_coreid = sii->common_info->coreid[sii->curidx];
}
uint
si_intflag(si_t *sih)
{
	si_info_t *sii = SI_INFO(sih);
	if (CHIPTYPE(sih->socitype) == SOCI_SB) {
		sbconfig_t *ccsbr = (sbconfig_t *)((uintptr)((ulong)
			    (sii->common_info->coresba[SI_CC_IDX]) + SBCONFIGOFF));
		return R_REG(sii->osh, &ccsbr->sbflagst);
	} else if (CHIPTYPE(sih->socitype) == SOCI_AI)
		return R_REG(sii->osh, ((uint32 *)(uintptr)
			    (sii->common_info->oob_router + OOB_STATUSA)));
	else {
		ASSERT(0);
		return 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;
}
Exemple #20
0
/* Release access to the RoboSwitch */
void
robo_detach(void *rinfo)
{
    robo_info_t *robo = (robo_info_t *)rinfo;
    si_info_t *sii;

    sii = SI_INFO((si_t*)robo->sbh);

	if (robo->regs) {
		REG_UNMAP(robo->regs);
		robo->regs = NULL;
	}

    COMPILER_REFERENCE(sii);

    /* Free private state */
    MFREE(sii->osh, robo, sizeof(robo_info_t));
}
/* mask&set gpio interrupt mask bits */
uint32
si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
{
	si_info_t *sii;
	uint regoff;

	sii = SI_INFO(sih);
	regoff = 0;

	/* gpios could be shared on router platforms */
	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
		mask = priority ? (si_gpioreservation & mask) :
			((si_gpioreservation | mask) & ~(si_gpioreservation));
		val &= mask;
	}

	regoff = OFFSETOF(chipcregs_t, gpiointmask);
	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
}
Exemple #22
0
static
void _switch_release_grant(void *rinfo)
{
    uint32 regval;
    robo_info_t *robo = (robo_info_t *)rinfo;
    si_info_t *sii;
    osl_t       *osh;
    nssrabregs_t *regs;      /* pointer to chip registers */

    sii = SI_INFO((si_t*)robo->sbh);
    osh = sii->osh;
    regs = robo->regs;

    COMPILER_REFERENCE(osh);

	regval = R_REG(osh, &regs->chipcommonb_srab_sw_if);
    regval &= ~CHIPCOMMONB_SRAB_SW_IF_RCAREQ_MASK;
    W_REG(osh, &regs->chipcommonb_srab_sw_if, regval);
}
Exemple #23
0
static
uint64 _switch_reg_read(void *rinfo, uint8 page, uint8 offset)
{
    uint64 value = ~(uint64)0;
    uint32 regval;
    uint32 timeout = ROBO_POLL_TIMEOUT;

    robo_info_t *robo = (robo_info_t *)rinfo;
    si_info_t *sii;
    osl_t       *osh;
    nssrabregs_t *regs;      /* pointer to chip registers */

    sii = SI_INFO((si_t*)robo->sbh);
    osh = sii->osh;
    regs = robo->regs;

    COMPILER_REFERENCE(osh);

    /* Assemble read command */
    _switch_request_grant(rinfo);
    regval = ((page << CHIPCOMMONB_SRAB_CMDSTAT_SRA_PAGE_SHIFT)
              | (offset << CHIPCOMMONB_SRAB_CMDSTAT_SRA_OFFSET_SHIFT)
              | CHIPCOMMONB_SRAB_CMDSTAT_SRA_GORDYN_MASK);
    W_REG(osh, &regs->chipcommonb_srab_cmdstat, regval);

    /* Wait for command complete */
    while (R_REG(osh, &regs->chipcommonb_srab_cmdstat) & CHIPCOMMONB_SRAB_CMDSTAT_SRA_GORDYN_MASK) {
        if (!--timeout) {
			SRAB_ERR(("robo_read: timeout"));
            _switch_interface_reset(rinfo);
            break;
        }
    }
    if (timeout) {
        /* Didn't time out, read and return the value */
        value = (((uint64)R_REG(osh, &regs->chipcommonb_srab_rdh)) << 32)
                        | R_REG(osh, &regs->chipcommonb_srab_rdl);
    }

    _switch_release_grant(rinfo);
    return value;
}
/* return index of coreid or BADIDX if not found */
uint
si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
{
	si_info_t *sii;
	uint found;
	uint i;

	sii = SI_INFO(sih);

	found = 0;

	for (i = 0; i < sii->numcores; i++)
		if (sii->common_info->coreid[i] == coreid) {
			if (found == coreunit)
				return (i);
			found++;
		}

	return (BADIDX);
}
Exemple #25
0
/* Get access to the RoboSwitch */
void *
robo_attach(void *sih)
{
    robo_info_t *robo;
    si_info_t *sii;
    nssrabregs_t *regs;      /* pointer to chip registers */
	struct si_pub *sii_pub = NULL;
	uint32	base_addr;

    sii = SI_INFO((si_t*)sih);

    /* Allocate private state */
    if (!(robo = MALLOC(sii->osh, sizeof(robo_info_t)))) {
        SRAB_ERR(("robo_attach: out of memory"));
        return NULL;
    } else {
        robo_sbh = (void *)robo;
    }
    bzero((char *) robo, sizeof(robo_info_t));

    robo->sbh = sih;
	sii_pub = &sii->pub;

	if (sii_pub->chip == BCM53020_CHIP_ID) {
		base_addr = NSP_CCB_SRAB_BASE;
	} else {
		base_addr = CCB_SRAB_BASE;
	}
    if ((regs = (void*)REG_MAP(base_addr, CORE_SIZE)) == NULL) {
        SRAB_ERR(("robo_attach: can't get base address"));
        return NULL;
    }
/*    printk("%d: robo_attach: regs=0x%x\n",__LINE__,(uint32)regs);*/
    robo->regs = regs;

#ifdef _KERNEL_
    /* Initialize lock */
    spin_lock_init(&robo->lock);
#endif
    return robo;
}
uint32
si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
{
	si_info_t *sii;
	uint offs;

	sii = SI_INFO(sih);
	if (sih->ccrev < 11)
		return -1;

	if (regtype == GPIO_REGEVT)
		offs = OFFSETOF(chipcregs_t, gpioevent);
	else if (regtype == GPIO_REGEVT_INTMSK)
		offs = OFFSETOF(chipcregs_t, gpioeventintmask);
	else if (regtype == GPIO_REGEVT_INTPOL)
		offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
	else
		return -1;

	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
}
void
si_gpio_handler_process(si_t *sih)
{
	si_info_t *sii;
	gpioh_item_t *h;
	uint32 status;
	uint32 level = si_gpioin(sih);
	uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);

	sii = SI_INFO(sih);
	for (h = sii->gpioh_head; h != NULL; h = h->next) {
		if (h->handler) {
			status = (h->level ? level : edge);

			if (status & h->event)
				h->handler(status, h->arg);
		}
	}

	si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
}
Exemple #28
0
static
void _switch_reg_write(void *rinfo, uint8 page, uint8 offset, uint64 value)
{
    uint32 regval;
    uint32 timeout = ROBO_POLL_TIMEOUT;
    robo_info_t *robo = (robo_info_t *)rinfo;
    si_info_t *sii;
    osl_t       *osh;
    nssrabregs_t *regs;      /* pointer to chip registers */

    sii = SI_INFO((si_t*)robo->sbh);
    osh = sii->osh;
    regs = robo->regs;

    COMPILER_REFERENCE(osh);

    _switch_request_grant(rinfo);
    /* Load the value to write */
    W_REG(osh, &regs->chipcommonb_srab_wdh, (uint32)(value >> 32));
    W_REG(osh, &regs->chipcommonb_srab_wdl, (uint32)(value));

    /* Issue the write command */
    regval = ((page << CHIPCOMMONB_SRAB_CMDSTAT_SRA_PAGE_SHIFT)
              | (offset << CHIPCOMMONB_SRAB_CMDSTAT_SRA_OFFSET_SHIFT)
              | CHIPCOMMONB_SRAB_CMDSTAT_SRA_GORDYN_MASK
              | CHIPCOMMONB_SRAB_CMDSTAT_SRA_WRITE_MASK);
    W_REG(osh, &regs->chipcommonb_srab_cmdstat, regval);
    /* Wait for command complete */
    while (R_REG(osh, &regs->chipcommonb_srab_cmdstat) & CHIPCOMMONB_SRAB_CMDSTAT_SRA_GORDYN_MASK) {
        if (!--timeout) {
			SRAB_ERR(("robo_write: timeout"));
            _switch_interface_reset(rinfo);
            break;
        }
    }
    _switch_release_grant(rinfo);

}
/* Return the RAM size of the SOCRAM core */
uint32
si_socram_size(si_t *sih)
{
	si_info_t *sii;
	uint origidx;
	uint intr_val = 0;

	sbsocramregs_t *regs;
	bool wasup;
	uint corerev;
	uint32 coreinfo;
	uint memsize = 0;

	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;

	/* Get info for determining size */
	if (!(wasup = si_iscoreup(sih)))
		si_core_reset(sih, 0, 0);
	corerev = si_corerev(sih);
	coreinfo = R_REG(sii->osh, &regs->coreinfo);

	/* Calculate size from coreinfo based on rev */
	if (corerev == 0)
		memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
	else if (corerev < 3) {
		memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
		memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
	} else {
/* return the core-type instantiation # of the current core */
uint
si_coreunit(si_t *sih)
{
	si_info_t *sii;
	uint idx;
	uint coreid;
	uint coreunit;
	uint i;

	sii = SI_INFO(sih);
	coreunit = 0;

	idx = sii->curidx;

	ASSERT(GOODREGS(sii->curmap));
	coreid = si_coreid(sih);

	/* count the cores of our type */
	for (i = 0; i < idx; i++)
		if (sii->common_info->coreid[i] == coreid)
			coreunit++;

	return (coreunit);
}