コード例 #1
0
ファイル: hnddma.c プロジェクト: ariavie/bcm
void
dma_txreset(dma_info_t *di)
{
	uint32 status;

	DMA_TRACE(("%s: dma_txreset\n", di->name));

	/* address PR8249/PR7577 issue */
	/* suspend tx DMA first */
	W_REG(&di->regs->xmtcontrol, XC_SE);
	SPINWAIT((status = (R_REG(&di->regs->xmtstatus) & XS_XS_MASK)) != XS_XS_DISABLED &&
		 status != XS_XS_IDLE &&
		 status != XS_XS_STOPPED,
		 10000);

	/* PR2414 WAR: DMA engines are not disabled until transfer finishes */
	W_REG(&di->regs->xmtcontrol, 0);
	SPINWAIT((status = (R_REG(&di->regs->xmtstatus) & XS_XS_MASK)) != XS_XS_DISABLED,
		 10000);

	if (status != XS_XS_DISABLED) {
		DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name));
	}

	/* wait for the last transaction to complete */
	OSL_DELAY(300);
}
コード例 #2
0
ファイル: bcm-sf2-eth-gmac.c プロジェクト: Noltari/u-boot
static int gmac_disable_dma(struct eth_dma *dma, int dir)
{
	int status;

	debug("%s enter\n", __func__);

	if (dir == MAC_DMA_TX) {
		/* address PR8249/PR7577 issue */
		/* suspend tx DMA first */
		writel(D64_XC_SE, GMAC0_DMA_TX_CTRL_ADDR);
		SPINWAIT(((status = (readl(GMAC0_DMA_TX_STATUS0_ADDR) &
				     D64_XS0_XS_MASK)) !=
			  D64_XS0_XS_DISABLED) &&
			 (status != D64_XS0_XS_IDLE) &&
			 (status != D64_XS0_XS_STOPPED), 10000);

		/*
		 * PR2414 WAR: DMA engines are not disabled until
		 * transfer finishes
		 */
		writel(0, GMAC0_DMA_TX_CTRL_ADDR);
		SPINWAIT(((status = (readl(GMAC0_DMA_TX_STATUS0_ADDR) &
				     D64_XS0_XS_MASK)) !=
			  D64_XS0_XS_DISABLED), 10000);

		/* wait for the last transaction to complete */
		udelay(2);

		status = (status == D64_XS0_XS_DISABLED);
	} else {
		/*
		 * PR2414 WAR: DMA engines are not disabled until
		 * transfer finishes
		 */
		writel(0, GMAC0_DMA_RX_CTRL_ADDR);
		SPINWAIT(((status = (readl(GMAC0_DMA_RX_STATUS0_ADDR) &
				     D64_RS0_RS_MASK)) !=
			  D64_RS0_RS_DISABLED), 10000);

		status = (status == D64_RS0_RS_DISABLED);
	}

	return status;
}
コード例 #3
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;
}
コード例 #4
0
ファイル: hnddma.c プロジェクト: ariavie/bcm
void
dma_rxreset(dma_info_t *di)
{
	uint32 status;

	DMA_TRACE(("%s: dma_rxreset\n", di->name));

	/* PR2414 WAR: DMA engines are not disabled until transfer finishes */
	W_REG(&di->regs->rcvcontrol, 0);
	SPINWAIT((status = (R_REG(&di->regs->rcvstatus) & RS_RS_MASK)) != RS_RS_DISABLED,
		 10000);

	if (status != RS_RS_DISABLED) {
		DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name));
	}
}
コード例 #5
0
static int
brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
{
	int err = 0;
	u8 clkval, clkset;

	/* Try forcing SDIO core to do ALPAvail request only */
	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
	brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
			       SBSDIO_FUNC1_CHIPCLKCSR,	clkset, &err);
	if (err) {
		brcmf_dbg(ERROR, "error writing for HT off\n");
		return err;
	}

	/* If register supported, wait for ALPAvail and then force ALP */
	/* This may take up to 15 milliseconds */
	clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
				       SBSDIO_FUNC1_CHIPCLKCSR, NULL);

	if ((clkval & ~SBSDIO_AVBITS) != clkset) {
		brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
			  clkset, clkval);
		return -EACCES;
	}

	SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
				SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
			!SBSDIO_ALPAV(clkval)),
			PMU_MAX_TRANSITION_DLY);
	if (!SBSDIO_ALPAV(clkval)) {
		brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
			  clkval);
		return -EBUSY;
	}

	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
	brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
			       SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
	udelay(65);

	/* Also, disable the extra SDIO pull-ups */
	brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
			       SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);

	return 0;
}
コード例 #6
0
ファイル: mac80211_if.c プロジェクト: 19Dan01/linux
/*
 * precondition: perimeter lock has been acquired
 */
void brcms_down(struct brcms_info *wl)
{
	uint callbacks, ret_val = 0;

	/* call common down function */
	ret_val = brcms_c_down(wl->wlc);
	callbacks = atomic_read(&wl->callbacks) - ret_val;

	/* wait for down callbacks to complete */
	spin_unlock_bh(&wl->lock);

	/* For HIGH_only driver, it's important to actually schedule other work,
	 * not just spin wait since everything runs at schedule level
	 */
	SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);

	spin_lock_bh(&wl->lock);
}
コード例 #7
0
static bool
si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
{
	/* need to set memseg flag for CF card first before any sb registers access */
	if (BUSTYPE(bustype) == PCMCIA_BUS)
		sii->memseg = TRUE;


	if (BUSTYPE(bustype) == SDIO_BUS) {
		int err;
		uint8 clkset;

		/* Try forcing SDIO core to do ALPAvail request only */
		clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
		if (!err) {
			uint8 clkval;

			/* If register supported, wait for ALPAvail and then force ALP */
			clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
			if ((clkval & ~SBSDIO_AVBITS) == clkset) {
				SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
					SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
					PMU_MAX_TRANSITION_DLY);
				if (!SBSDIO_ALPAV(clkval)) {
					SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
						clkval));
					return FALSE;
				}
				clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
					clkset, &err);
				OSL_DELAY(65);
			}
		}
#ifndef MMC_SDIO_FORCE_PULLUP
		/* Also, disable the extra SDIO pull-ups */
		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
#endif
	}


	return TRUE;
}
コード例 #8
0
static uint16
chipphyrd(struct bcm4xxx *ch, uint phyaddr, uint reg)
{
	bcmenetregs_t *regs;

	ASSERT(phyaddr < MAXEPHY);

	/*
	 * BCM5222 dualphy shared mdio contortion.
	 * remote phy: another emac controls our phy.
	 */
	if (ch->etc->mdcport != ch->etc->coreunit) {
		if (ch->etphy == NULL) {
			ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);

			/* first time reset */
			if (ch->etphy)
				chipphyreset(ch, ch->etc->phyaddr);
		}
		if (ch->etphy)
			return (et_phyrd(ch->etphy, phyaddr, reg));
		else
			return (0xffff);
	}

	/* local phy: our emac controls our phy */

	regs = ch->regs;

	/* clear mii_int */
	W_REG(ch->osh, &regs->emacintstatus, EI_MII);

	/* issue the read */
	W_REG(ch->osh, &regs->mdiodata,  (MD_SB_START | MD_OP_READ | (phyaddr << MD_PMD_SHIFT)
		| (reg << MD_RA_SHIFT) | MD_TA_VALID));

	/* wait for it to complete */
	SPINWAIT(((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0), 100);
	if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
		ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit));
	}

	return (R_REG(ch->osh, &regs->mdiodata) & MD_DATA_MASK);
}
コード例 #9
0
static bool
sdspi_switch_clock(sdioh_info_t *sd, bool ext_clk)
{
	spih_info_t *si = (spih_info_t *)sd->controller;
	osl_t *osh = si->osh;
	spih_regs_t *regs = si->regs;

	
	SPIPCI_WREG(osh, &regs->spih_pll_ctrl, ext_clk ? SPIH_EXT_CLK : 0);

	SPINWAIT(((SPIPCI_RREG(osh, &regs->spih_pll_status) & SPIH_PLL_LOCKED)
	          != SPIH_PLL_LOCKED), 1000);
	if ((SPIPCI_RREG(osh, &regs->spih_pll_status) & SPIH_PLL_LOCKED) != SPIH_PLL_LOCKED) {
		sd_err(("%s: timeout waiting for PLL to lock\n", __FUNCTION__));
		return (FALSE);
	}
	return (TRUE);

}
コード例 #10
0
ファイル: sdio_chip.c プロジェクト: CenturyGlorion/linux
static void
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
			  struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
			  u32 in_resetbits)
{
	u8 idx;
	u32 regdata;
	u32 wrapbase;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
	if (idx == BRCMF_MAX_CORENUM)
		return;

	wrapbase = ci->c_inf[idx].wrapbase;

	/* if core is already in reset, just return */
	regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL);
	if ((regdata & BCMA_RESET_CTL_RESET) != 0)
		return;

	/* configure reset */
	brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
			  BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
	regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);

	/* put in reset */
	brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL,
			  BCMA_RESET_CTL_RESET, NULL);
	usleep_range(10, 20);

	/* wait till reset is 1 */
	SPINWAIT(brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) !=
		 BCMA_RESET_CTL_RESET, 300);

	/* post reset configure */
	brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
			  BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
	regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
}
コード例 #11
0
static void
chipwrcam(struct bcm4xxx *ch, struct ether_addr *ea, uint camindex)
{
	uint32 w;

	ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & (CC_CB | CC_CE)) == 0);

	w = (ea->octet[2] << 24) | (ea->octet[3] << 16) | (ea->octet[4] << 8)
		| ea->octet[5];
	W_REG(ch->osh, &ch->regs->camdatalo, w);
	w = CD_V | (ea->octet[0] << 8) | ea->octet[1];
	W_REG(ch->osh, &ch->regs->camdatahi, w);
	W_REG(ch->osh, &ch->regs->camcontrol, ((camindex << CC_INDEX_SHIFT) | CC_WR));

	/* spin until done */
	SPINWAIT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB), 1000);

	/*
	 * This assertion is usually caused by the phy not providing a clock
	 * to the bottom portion of the mac..
	 */
	ASSERT((R_REG(ch->osh, &ch->regs->camcontrol) & CC_CB) == 0);
}
コード例 #12
0
/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
int
si_corebist(si_t *sih)
{
	uint32 cflags;
	int result = 0;

	/* Read core control flags */
	cflags = si_core_cflags(sih, 0, 0);

	/* Set bist & fgc */
	si_core_cflags(sih, 0, (SICF_BIST_EN | SICF_FGC));

	/* Wait for bist done */
	SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);

	if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
		result = BCME_ERROR;

	/* Reset core control flags */
	si_core_cflags(sih, 0xffff, cflags);

	return result;
}
コード例 #13
0
static void
chipphywr(struct bcm4xxx *ch, uint phyaddr, uint reg, uint16 v)
{
	bcmenetregs_t *regs;

	ASSERT(phyaddr < MAXEPHY);

	/*
	 * BCM5222 dualphy shared mdio contortion.
	 * remote phy: another emac controls our phy.
	 */
	if (ch->etc->mdcport != ch->etc->coreunit) {
		if (ch->etphy == NULL)
			ch->etphy = et_phyfind(ch->et, ch->etc->mdcport);
		if (ch->etphy)
			et_phywr(ch->etphy, phyaddr, reg, v);
		return;
	}

	/* local phy: our emac controls our phy */

	regs = ch->regs;

	/* clear mii_int */
	W_REG(ch->osh, &regs->emacintstatus, EI_MII);
	ASSERT((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0);

	/* issue the write */
	W_REG(ch->osh, &regs->mdiodata,  (MD_SB_START | MD_OP_WRITE | (phyaddr << MD_PMD_SHIFT)
		| (reg << MD_RA_SHIFT) | MD_TA_VALID | v));

	/* wait for it to complete */
	SPINWAIT(((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0), 100);
	if ((R_REG(ch->osh, &regs->emacintstatus) & EI_MII) == 0) {
		ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit));
	}
}
コード例 #14
0
int
sflash_write(si_t *sih, chipcregs_t *cc, uint offset, uint length, const uchar *buffer)
{
	struct sflash *sfl;
	uint off = offset, len = length;
	const uint8 *buf = buffer;
	uint8 data;
	int ret = 0, ntry = 0;
	bool is4712b0;
	uint32 page, byte, mask;
	osl_t *osh;

	ASSERT(sih);

	osh = si_osh(sih);

	if (!len)
		return 0;

	sfl = &sflash;
	if ((off + len) > sfl->size)
		return -22;

	switch (sfl->type) {
	case SFLASH_ST:
		is4712b0 = (CHIPID(sih->chip) == BCM4712_CHIP_ID) && (CHIPREV(sih->chiprev) == 3);
		/* Enable writes */
retry:		sflash_cmd(osh, cc, SFLASH_ST_WREN);
		off = offset;
		len = length;
		buf = buffer;
		ntry++;
		if (is4712b0) {
			mask = 1 << 14;
			W_REG(osh, &cc->flashaddress, off);
			data = GET_BYTE(buf);
			buf++;
			W_REG(osh, &cc->flashdata, data);
			/* Set chip select */
			OR_REG(osh, &cc->gpioout, mask);
			/* Issue a page program with the first byte */
			sflash_cmd(osh, cc, SFLASH_ST_PP);
			ret = 1;
			off++;
			len--;
			while (len > 0) {
				if ((off & 255) == 0) {
					/* Page boundary, drop cs and return */
					AND_REG(osh, &cc->gpioout, ~mask);
					OSL_DELAY(1);
					if (!sflash_poll(sih, cc, off)) {
						/* Flash rejected command */
						if (ntry <= ST_RETRIES)
							goto retry;
						else
							return -11;
					}
					return ret;
				} else {
					/* Write single byte */
					data = GET_BYTE(buf);
					buf++;
					sflash_cmd(osh, cc, data);
				}
				ret++;
				off++;
				len--;
			}
			/* All done, drop cs */
			AND_REG(osh, &cc->gpioout, ~mask);
			OSL_DELAY(1);
			if (!sflash_poll(sih, cc, off)) {
				/* Flash rejected command */
				if (ntry <= ST_RETRIES)
					goto retry;
				else
					return -12;
			}
		} else if (sih->ccrev >= 20) {
			W_REG(osh, &cc->flashaddress, off);
			data = GET_BYTE(buf);
			buf++;
			W_REG(osh, &cc->flashdata, data);
			/* Issue a page program with CSA bit set */
			sflash_cmd(osh, cc, SFLASH_ST_CSA | SFLASH_ST_PP);
			ret = 1;
			off++;
			len--;
			while (len > 0) {
				if ((off & 255) == 0) {
					/* Page boundary, poll droping cs and return */
					W_REG(NULL, &cc->flashcontrol, 0);
					OSL_DELAY(1);
					if (sflash_poll(sih, cc, off) == 0) {
						/* Flash rejected command */
						SFL_MSG(("sflash: pp rejected, ntry: %d,"
						         " off: %d/%d, len: %d/%d, ret:"
						         "%d\n", ntry, off, offset, len,
						         length, ret));
						if (ntry <= ST_RETRIES)
							goto retry;
						else
							return -11;
					}
					return ret;
				} else {
					/* Write single byte */
					data = GET_BYTE(buf);
					buf++;
					sflash_cmd(osh, cc, SFLASH_ST_CSA | data);
				}
				ret++;
				off++;
				len--;
			}
			/* All done, drop cs & poll */
			W_REG(NULL, &cc->flashcontrol, 0);
			OSL_DELAY(1);
			if (sflash_poll(sih, cc, off) == 0) {
				/* Flash rejected command */
				SFL_MSG(("sflash: pp rejected, ntry: %d, off: %d/%d,"
				         " len: %d/%d, ret: %d\n",
				         ntry, off, offset, len, length, ret));
				if (ntry <= ST_RETRIES)
					goto retry;
				else
					return -12;
			}
		} else {
			ret = 1;
			W_REG(osh, &cc->flashaddress, off);
			data = GET_BYTE(buf);
			buf++;
			W_REG(osh, &cc->flashdata, data);
			/* Page program */
			sflash_cmd(osh, cc, SFLASH_ST_PP);
		}
		break;
	case SFLASH_AT:
		mask = sfl->blocksize - 1;
		page = (off & ~mask) << 1;
		byte = off & mask;
		/* Read main memory page into buffer 1 */
		if (byte || (len < sfl->blocksize)) {
			W_REG(osh, &cc->flashaddress, page);
			sflash_cmd(osh, cc, SFLASH_AT_BUF1_LOAD);
			/* 250 us for AT45DB321B */
			SPINWAIT(sflash_poll(sih, cc, off), 1000);
			ASSERT(!sflash_poll(sih, cc, off));
		}
		/* Write into buffer 1 */
		for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
			W_REG(osh, &cc->flashaddress, byte++);
			W_REG(osh, &cc->flashdata, *buf++);
			sflash_cmd(osh, cc, SFLASH_AT_BUF1_WRITE);
		}
		/* Write buffer 1 into main memory page */
		W_REG(osh, &cc->flashaddress, page);
		sflash_cmd(osh, cc, SFLASH_AT_BUF1_PROGRAM);
		break;
	}

	return ret;
}
コード例 #15
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;
}
コード例 #16
0
ファイル: sflash.c プロジェクト: ariavie/bcm
int
sflash_write(si_t *sih, chipcregs_t *cc, uint offset, uint length, const uchar *buffer)
{
    struct sflash *sfl;
    uint off = offset, len = length;
#if SFLASH_ST_PAGE_MODE_WRITE
    int tryn = 0;
#else /* !SFLASH_ST_PAGE_MODE_WRITE */
    uint quot = 0, remain = 0, wlen = 0;
    uint32 reg_val = 0;
#endif /* SFLASH_ST_PAGE_MODE_WRITE */
    const uchar *buf = buffer;
    int ret = 0;
    uint32 page, byte, mask;
    osl_t *osh;
    
    ASSERT(sih);
    
    osh = si_osh(sih);
    
    if (!len)
        return 0;
    
    sfl = &sflash;
    if ((off + len) > sfl->size)
        return -22;
    
    switch (sfl->type) {
    case SFLASH_ST:
#if SFLASH_ST_PAGE_MODE_WRITE
          /* Enable writes */
retry:      sflash_cmd(osh, cc, SFLASH_ST_WREN);
          off = offset;
          len = length;
          buf = buffer;
          tryn++;
          if (sih->ccrev >= 20) {
              W_REG(osh, &cc->sflashaddress, off);
              W_REG(osh, &cc->sflashdata, *buf++);
              /* Issue a page program with CSA bit set */
              sflash_cmd(osh, cc, SFLASH_ST_CSA | SFLASH_ST_PP);
              ret = 1;
              off++;
              len--;
              while (len > 0) {
                  if ((off & 255) == 0) {
                      /* Page boundary, poll droping cs and return */
                      W_REG(osh, &cc->sflashcontrol, 0);
                      OSL_DELAY(1);
                      if (sflash_poll(sih, cc, offset) != 0) {
                          /* Flash rejected command */
                          SFL_MSG(("sflash: pp rejected, tryn: %d,"
                                   " off: %d/%d, len: %d/%d, ret:"
                                   "%d\n", tryn, off, offset, len,
                                   length, ret));
                          if (tryn <= ST_RETRIES)
                              goto retry;
                          else
                              return -11;
                      }
                      return ret;
                  } else {
                      /* Write single byte */
                      sflash_cmd(osh, cc, SFLASH_ST_CSA | *buf++);
                  }
                  ret++;
                  off++;
                  len--;
              }
              /* All done, drop cs & poll */
              W_REG(osh, &cc->sflashcontrol, 0);
              OSL_DELAY(1);
              if (sflash_poll(sih, cc, offset) != 0) {
                  /* Flash rejected command */
                  SFL_MSG(("sflash: pp rejected, tryn: %d, off: %d/%d,"
                           " len: %d/%d, ret: %d\n",
                           tryn, off, offset, len, length, ret));
                  if (tryn <= ST_RETRIES)
                      goto retry;
                  else
                      return -12;
              }
          } else {
              ret = 1;
              W_REG(osh, &cc->sflashaddress, off);
              W_REG(osh, &cc->sflashdata, *buf);
              /* Page program */
              sflash_cmd(osh, cc, SFLASH_ST_PP);
          }
#else /* !SFLASH_ST_PAGE_MODE_WRITE */
          off = offset;
          len = length;
          buf = buffer;
          if (sih->ccrev >= 20) {
              ret = 0;
              while (len > 0) {
                  /* Enable writes */
                  sflash_cmd(osh, cc, SFLASH_ST_WREN);
                  /* Drop cs before starting a page program */
                  W_REG(osh, &cc->sflashcontrol, 0);

                  W_REG(osh, &cc->sflashaddress, off);
                  quot = (len / 4);
                  remain = (len % 4);
                  if (quot != 0) { /* len >= 4 bytes */
                      wlen = 4;
                      reg_val = (*buf << 24);
                      buf++;
                      reg_val |= (*buf << 16);
                      buf++;
                      reg_val |= (*buf << 8);
                      buf++;
                      reg_val |= (*buf);
                      buf++;
                      W_REG(osh, &cc->sflashdata, reg_val);
                      /* Issue a page program with CSA bit set : opcode+3 addres & 4 data bytes */
                      sflash_cmd(osh, cc, (SFLASH_ST_CSA | SFLASH_ST_PP3A4D));
                  } else { /* len < 4 bytes */
                      wlen = 1;
                      W_REG(osh, &cc->sflashdata, *buf++);
                      /* Issue a page program with CSA bit set : opcode+3 addres & 1 data bytes */
                      sflash_cmd(osh, cc, (SFLASH_ST_CSA | SFLASH_ST_PP));
                  }
                  ret += wlen;
                  off += wlen;
                  len -= wlen;

                  /* A page program done(1 or 4 data bytes), drop cs & poll */
                  W_REG(osh, &cc->sflashcontrol, 0);
                  while (sflash_poll(sih, cc, offset) != 0) {
                      /* Poll until command completion */
                  }

                  /* Page boundary and return for 256 bytes write */
                  if ((off & 255) == 0) {
                      return ret;
                  }
              }
          } else {
              /* Enable writes */
              sflash_cmd(osh, cc, SFLASH_ST_WREN);
              ret = 1;
              W_REG(osh, &cc->sflashaddress, off);
              W_REG(osh, &cc->sflashdata, *buf);
              /* Page program */
              sflash_cmd(osh, cc, SFLASH_ST_PP);
          }
#endif  /* SFLASH_ST_PAGE_MODE_WRITE */
          break;
    case SFLASH_AT:
          mask = sfl->blocksize - 1;
          page = (off & ~mask) << 1;
          byte = off & mask;
          /* Read main memory page into buffer 1 */
          if (byte || (len < sfl->blocksize)) {
              W_REG(osh, &cc->sflashaddress, page);
              sflash_cmd(osh, cc, SFLASH_AT_BUF1_LOAD);
              /* 250 us for AT45DB321B */
              SPINWAIT(sflash_poll(sih, cc, offset), 1000);
              ASSERT(!sflash_poll(sih, cc, offset));
          }
          /* Write into buffer 1 */
          for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
              W_REG(osh, &cc->sflashaddress, byte++);
              W_REG(osh, &cc->sflashdata, *buf++);
              sflash_cmd(osh, cc, SFLASH_AT_BUF1_WRITE);
          }
          /* Write buffer 1 into main memory page */
          W_REG(osh, &cc->sflashaddress, page);
          sflash_cmd(osh, cc, SFLASH_AT_BUF1_PROGRAM);
          break;
    }
    
    return ret;
}
コード例 #17
0
ファイル: sflash.c プロジェクト: NieHao/Tomato-RAF
/* Write len bytes starting at offset into buf. Returns number of bytes
 * written. Caller should poll for completion.
 */
int
sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf)
{
	struct sflash *sfl;
	int ret = 0;
	bool is4712b0;
	uint32 page, byte, mask;

	if (!len)
		return 0;

	if ((offset + len) > sflash.size)
		return -22;

	sfl = &sflash;
	switch (sfl->type) {
	case SFLASH_ST:
		mask = R_REG(NULL, &cc->chipid);
		is4712b0 = (((mask & CID_ID_MASK) == BCM4712_CHIP_ID) &&
		            ((mask & CID_REV_MASK) == (3 << CID_REV_SHIFT)));
		/* Enable writes */
		sflash_cmd(cc, SFLASH_ST_WREN);
		if (is4712b0) {
			mask = 1 << 14;
			W_REG(NULL, &cc->flashaddress, offset);
			W_REG(NULL, &cc->flashdata, *buf++);
			/* Set chip select */
			OR_REG(NULL, &cc->gpioout, mask);
			/* Issue a page program with the first byte */
			sflash_cmd(cc, SFLASH_ST_PP);
			ret = 1;
			offset++;
			len--;
			while (len > 0) {
				if ((offset & 255) == 0) {
					/* Page boundary, drop cs and return */
					AND_REG(NULL, &cc->gpioout, ~mask);
					if (!sflash_poll(cc, offset)) {
						/* Flash rejected command */
						return -11;
					}
					return ret;
				} else {
					/* Write single byte */
					sflash_cmd(cc, *buf++);
				}
				ret++;
				offset++;
				len--;
			}
			/* All done, drop cs if needed */
			if ((offset & 255) != 1) {
				/* Drop cs */
				AND_REG(NULL, &cc->gpioout, ~mask);
				if (!sflash_poll(cc, offset)) {
					/* Flash rejected command */
					return -12;
				}
			}
		} else {
			ret = 1;
			W_REG(NULL, &cc->flashaddress, offset);
			W_REG(NULL, &cc->flashdata, *buf);
		/* Page program */
		sflash_cmd(cc, SFLASH_ST_PP);
		}
		break;
	case SFLASH_AT:
		mask = sfl->blocksize - 1;
		page = (offset & ~mask) << 1;
		byte = offset & mask;
		/* Read main memory page into buffer 1 */
		if (byte || (len < sfl->blocksize)) {
			W_REG(NULL, &cc->flashaddress, page);
			sflash_cmd(cc, SFLASH_AT_BUF1_LOAD);
			/* 250 us for AT45DB321B */
			SPINWAIT(sflash_poll(cc, offset), 1000);
			ASSERT(!sflash_poll(cc, offset));
		}
		/* Write into buffer 1 */
		for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
			W_REG(NULL, &cc->flashaddress, byte++);
			W_REG(NULL, &cc->flashdata, *buf++);
			sflash_cmd(cc, SFLASH_AT_BUF1_WRITE);
		}
		/* Write buffer 1 into main memory page */
		W_REG(NULL, &cc->flashaddress, page);
		sflash_cmd(cc, SFLASH_AT_BUF1_PROGRAM);
		break;
	}

	return ret;
}
コード例 #18
0
static void
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
			  struct chip_info *ci, u16 coreid)
{
	u32 regdata, base;
	u8 idx;

	idx = brcmf_sdio_chip_getinfidx(ci, coreid);
	base = ci->c_inf[idx].base;

	regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
	if (regdata & SSB_TMSLOW_RESET)
		return;

	regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
	if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
		/*
		 * set target reject and spin until busy is clear
		 * (preserve core-specific bits)
		 */
		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
					   NULL);
		brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
				 regdata | SSB_TMSLOW_REJECT, NULL);

		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
					   NULL);
		udelay(1);
		SPINWAIT((brcmf_sdio_regrl(sdiodev,
					   CORE_SB(base, sbtmstatehigh),
					   NULL) &
			SSB_TMSHIGH_BUSY), 100000);

		regdata = brcmf_sdio_regrl(sdiodev,
					   CORE_SB(base, sbtmstatehigh),
					   NULL);
		if (regdata & SSB_TMSHIGH_BUSY)
			brcmf_dbg(ERROR, "core state still busy\n");

		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
					   NULL);
		if (regdata & SSB_IDLOW_INITIATOR) {
			regdata = brcmf_sdio_regrl(sdiodev,
						   CORE_SB(base, sbimstate),
						   NULL);
			regdata |= SSB_IMSTATE_REJECT;
			brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
					 regdata, NULL);
			regdata = brcmf_sdio_regrl(sdiodev,
						   CORE_SB(base, sbimstate),
						   NULL);
			udelay(1);
			SPINWAIT((brcmf_sdio_regrl(sdiodev,
						   CORE_SB(base, sbimstate),
						   NULL) &
				SSB_IMSTATE_BUSY), 100000);
		}

		/* set reset and reject while enabling the clocks */
		regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
			  SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
		brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
				 regdata, NULL);
		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow),
					   NULL);
		udelay(10);

		/* clear the initiator reject bit */
		regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow),
					   NULL);
		if (regdata & SSB_IDLOW_INITIATOR) {
			regdata = brcmf_sdio_regrl(sdiodev,
						   CORE_SB(base, sbimstate),
						   NULL);
			regdata &= ~SSB_IMSTATE_REJECT;
			brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate),
					 regdata, NULL);
		}
	}

	/* leave reset and reject asserted */
	brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
			 (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
	udelay(1);
}