Example #1
0
static bool
_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs)
{
	uint32 w;

	OR_REG(osh, &dma32regs->control, XC_AE);
	w = R_REG(osh, &dma32regs->control);
	AND_REG(osh, &dma32regs->control, ~XC_AE);
	return ((w & XC_AE) == XC_AE);
}
Example #2
0
static void
chipduplexupd(struct bcm4xxx *ch)
{
	uint32 txcontrol;

	txcontrol = R_REG(ch->osh, &ch->regs->txcontrol);
	if (ch->etc->duplex && !(txcontrol & EXC_FD))
		OR_REG(ch->osh, &ch->regs->txcontrol, EXC_FD);
	else if (!ch->etc->duplex && (txcontrol & EXC_FD))
		AND_REG(ch->osh, &ch->regs->txcontrol, ~EXC_FD);
}
Example #3
0
static void
chipenablepme(struct bcm4xxx *ch)
{
	bcmenetregs_t *regs;

	regs = ch->regs;

	/* enable chip wakeup pattern matching */
	OR_REG(ch->osh, &regs->devcontrol, DC_PM);

	/* enable sonics bus PME */
	si_core_cflags(ch->sih, SICF_PME_EN, SICF_PME_EN);
}
Example #4
0
/* initialize PMU */
void si_pmu_init(struct si_pub *sih)
{
	chipcregs_t *cc;
	uint origidx;

	/* Remember original core before switch to chipc */
	origidx = ai_coreidx(sih);
	cc = ai_setcoreidx(sih, SI_CC_IDX);

	if (sih->pmurev == 1)
		AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
	else if (sih->pmurev >= 2)
		OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT);

	/* Return to original core */
	ai_setcoreidx(sih, origidx);
}
Example #5
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;
}
Example #6
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;
}
Example #7
0
/* 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;
}
Example #8
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);
}
Example #9
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);
	}
}
Example #10
0
/*
 * Initializes UART access. The callback function will be called once
 * per found UART.
 */
void BCMINITFN(sb_serial_init) (sb_t * sbh, sb_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 = sb_osh(sbh);

	regs = sb_setcore(sbh, SB_EXTIF, 0);
	if (regs) {
		sb_extif_serial_init(sbh, regs, add);
		return;
	}

	cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);
	ASSERT(cc);

	/* Determine core revision and capabilities */
	rev = sbh->ccrev;
	cap = sbh->cccaps;
	pll = cap & CC_CAP_PLL_MASK;

	/* Determine IRQ */
	irq = sb_irq(sbh);

	if (pll == PLL_TYPE1) {
		/* PLL clock */
		baud_base = sb_clock_rate(pll,
					  R_REG(osh, &cc->clockcontrol_n),
					  R_REG(osh, &cc->clockcontrol_m2));
		div = 1;
	} else {
		/* 5354 chip common uart uses a constant clock
		 * frequency of 25MHz */
		if (sb_corerev(sbh) == 20) {
			/* Set the override bit so we don't divide it */
			W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
			baud_base = 25000000;
		} else if (rev >= 11 && rev != 15) {
			/* Fixed ALP clock */
			baud_base = sb_alp_clock(sbh);
			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 = sb_clock(sbh);
			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);
	}
}
/**
 * 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)
{
	chipcregs_t *cc;
	uint origidx, intr_val = 0;
	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 */

	if (!(sih->cccaps & CC_CAP_PMU)) {
		return;
	}

	/* Remember original core before switch to chipc */
	cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);

	switch (SDIOD_DRVSTR_KEY(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(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
		break;
	}

	if (str_tab != NULL && cc != 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, &cc->chipcontrol_addr, PMU_CHIPCTL1);
		cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
		cc_data_temp &= ~str_mask;
		cc_data_temp |= str_tab[i].sel << str_shift;
		W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
		if (str_ovr_pmuval) { /* enables the selected drive strength */
			W_REG(osh,  &cc->chipcontrol_addr, str_ovr_pmuctl);
			OR_REG(osh, &cc->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_restore_core(sih, origidx, intr_val);
} /* si_sdiod_drive_strength_init */
Example #12
0
void
si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
{
	chipcregs_t *cc;
	uint origidx, intr_val = 0;
	sdiod_drive_str_t *str_tab = NULL;
	uint32 str_mask = 0;	
	uint32 str_shift = 0;
	uint32 str_ovr_pmuctl = PMU_CHIPCTL0; 
	uint32 str_ovr_pmuval = 0;            

	if (!(sih->cccaps & CC_CAP_PMU)) {
		return;
	}

	
	cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);

	switch (SDIOD_DRVSTR_KEY(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 
		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(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
		break;
	}

	if (str_tab != NULL && cc != NULL) {
		uint32 cc_data_temp;
		int i;

		for (i = 0; drivestrength < str_tab[i].strength; i++)
			;

		if (i > 0 && drivestrength > str_tab[i].strength)
			i--;

		if( cc!= NULL ) 
		{
			W_REG(osh, &cc->chipcontrol_addr, PMU_CHIPCTL1);
			cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
			cc_data_temp &= ~str_mask;
			cc_data_temp |= str_tab[i].sel << str_shift;
			W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
			if (str_ovr_pmuval) { 
				W_REG(osh,  &cc->chipcontrol_addr, str_ovr_pmuctl);
				OR_REG(osh, &cc->chipcontrol_data, str_ovr_pmuval);
			}
			PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n",
			         drivestrength, str_tab[i].strength));
		}
	}

	
	si_restore_core(sih, origidx, intr_val);
} 
Example #13
0
/*
 * Initializes UART access. The callback function will be called once
 * per found UART.
 */
void
BCMINITFN(si_serial_init)(si_t *sih, si_serial_init_fn add, uint32 baudrate)
{
    osl_t *osh;
    void *regs;
    chipcregs_t *cc;
    uint32 rev, cap, pll, baud_base, div;
    uint irq;
    int i, n;

    osh = si_osh(sih);

    cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
    ASSERT(cc);

    /* Determine core revision and capabilities */
    rev = sih->ccrev;
    cap = sih->cccaps;
    pll = cap & CC_CAP_PLL_MASK;

    /* Determine IRQ */
    irq = si_irq(sih);

    if (CCPLL_ENAB(sih) && pll == PLL_TYPE1) {
        /* PLL clock */
        baud_base = si_clock_rate(pll,
                                  R_REG(osh, &cc->clockcontrol_n),
                                  R_REG(osh, &cc->clockcontrol_m2));
        div = 1;
    } else {
        /* Fixed ALP clock */
        /* XXX rev. 15 in 4785 breaks the rule! */
        if (rev >= 11 && rev != 15) {
            baud_base = si_alp_clock(sih);
            div = 1;
            
            /*
             * If baudrate parameter is given with a non-zero value,
             * UART clock will be divided for the given baud rate before 
             * feeding into UART module.
             * Note: UART driver could also adjust UART module's divider for 
             *       clock fine tunning.
             */
            if (baudrate) {
                /* Turn off UART clock before switching clock source */
                if (rev >= 21)
                    AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN);

                /* Don't set the override bit so we divide it */
                AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKO);

                div = baud_base / (baudrate * 16); 
                div = (div + 1) & ~0x1;
                AND_REG(osh, &cc->clkdiv, ~CLKD_UART);
                OR_REG(osh, &cc->clkdiv, div);

                /* Turn back UART clock on */
                if (rev >= 21)
                    OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN);
            } else {

                /* Turn off UART clock before switching clock source */
                if (rev >= 21)
                    AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN);

                OR_REG(osh, &cc->corecontrol, CC_UARTCLKO);

                /* Turn back UART clock on */
                if (rev >= 21)
                    OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN);
            }

            if (CONSOLE_TTY == 1) {
                /* Use UART1, enable "UART1 use GPIO" bit */
                OR_REG(osh, &cc->corecontrol, 0x80);
            }

        } else if (rev >= 3) {
            /* Internal backplane clock */
            baud_base = si_clock(sih);
            div = 2;    /* Minimum divisor */
            W_REG(osh, &cc->clkdiv,
                  ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div));
        } else {
            /* Fixed internal backplane clock */
            baud_base = 88000000;
            div = 48;
        }

        /* Clock source depends on strapping if UartClkOverride is unset */
        if ((rev > 0) &&
            ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) {
            if ((cap & CC_CAP_UCLKSEL) == CC_CAP_UINTCLK) {
                /* Internal divided backplane clock */
                baud_base /= div;
            } else {
                /* Assume external clock of 1.8432 MHz */
                baud_base = 1843200;
            }
        }
    }

    /* Add internal UARTs */
    n = cap & CC_CAP_UARTS_MASK;
    for (i = 0; i < n; i++) {
        /* Register offset changed after revision 0 */
        if (rev)
            regs = (void *)((ulong) &cc->uart0data + (i * 256));
        else
            regs = (void *)((ulong) &cc->uart0data + (i * 8));

        if (add)
            add(regs, irq, baud_base, 0);
    }
}
Example #14
0
File: hnddma.c Project: ariavie/bcm
void
dma_fifoloopbackenable(dma_info_t *di)
{
	DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
	OR_REG(&di->regs->xmtcontrol, XC_LE);
}
Example #15
0
File: hnddma.c Project: ariavie/bcm
void
dma_txsuspend(dma_info_t *di)
{
	DMA_TRACE(("%s: dma_txsuspend\n", di->name));
	OR_REG(&di->regs->xmtcontrol, XC_SE);
}
Example #16
0
/*
 * Initialize all the chip registers.  If dma mode, init tx and rx dma engines
 * but leave the devcontrol tx and rx (fifos) disabled.
 */
static void
chipinit(struct bcm4xxx *ch, uint options)
{
	etc_info_t *etc;
	bcmenetregs_t *regs;
	uint idx;
	uint i;

	regs = ch->regs;
	etc = ch->etc;
	idx = 0;

	ET_TRACE(("et%d: chipinit\n", etc->unit));

	/* enable crc32 generation */
	OR_REG(ch->osh, &regs->emaccontrol, EMC_CG);

	/* enable one rx interrupt per received frame */
	W_REG(ch->osh, &regs->intrecvlazy, (1 << IRL_FC_SHIFT));

	/* enable 802.3x tx flow control (honor received PAUSE frames) */
	W_REG(ch->osh, &regs->rxconfig, ERC_FE | ERC_UF);

	/* initialize CAM */
	if (etc->promisc || (R_REG(ch->osh, &regs->rxconfig) & ERC_CA))
		OR_REG(ch->osh, &regs->rxconfig, ERC_PE);
	else {
		/* our local address */
		chipwrcam(ch, &etc->cur_etheraddr, idx++);

		/* allmulti or a list of discrete multicast addresses */
		if (etc->allmulti)
			OR_REG(ch->osh, &regs->rxconfig, ERC_AM);
		else if (etc->nmulticast) {
			for (i = 0; i < etc->nmulticast; i++)
				chipwrcam(ch, &etc->multicast[i], idx++);
		}

		/* enable cam */
		OR_REG(ch->osh, &regs->camcontrol, CC_CE);
	}

	/* optionally enable mac-level loopback */
	if (etc->loopbk)
		OR_REG(ch->osh, &regs->rxconfig, ERC_LE);

	/* set max frame lengths - account for possible vlan tag */
	W_REG(ch->osh, &regs->rxmaxlength, ETHER_MAX_LEN + 32);
	W_REG(ch->osh, &regs->txmaxlength, ETHER_MAX_LEN + 32);

	/* set tx watermark */
	W_REG(ch->osh, &regs->txwatermark, 56);

	/*
	 * Optionally, disable phy autonegotiation and force our speed/duplex
	 * or constrain our advertised capabilities.
	 */
	if (etc->forcespeed != ET_AUTO)
		chipphyforce(ch, etc->phyaddr);
	else if (etc->advertise && etc->needautoneg)
		chipphyadvertise(ch, etc->phyaddr);

	if (options & ET_INIT_FULL) {
		/* initialize the tx and rx dma channels */
		dma_txinit(ch->di);
		dma_rxinit(ch->di);

		/* post dma receive buffers */
		dma_rxfill(ch->di);

		/* lastly, enable interrupts */
		if (options & ET_INIT_INTRON)
			et_intrson(etc->et);
	}
	else
		dma_rxenable(ch->di);

	/* turn on the emac */
	OR_REG(ch->osh, &regs->enetcontrol, EC_EE);
}