예제 #1
0
파일: nvram.c 프로젝트: millken/zhuxianB30
/* Initialize hash table. Should be locked. */
int
BCMINITFN(_nvram_init)(void *sih)
{
	struct nvram_header *header;
	int ret;


	if (!(header = (struct nvram_header *) MALLOC(si_osh(sih), NVRAM_SPACE))) {
		printf("nvram_init: out of memory\n");
		return -12; /* -ENOMEM */
	}

#if 0
    if ((ret = _nvram_read(header)) == 0 &&
	    header->magic == NVRAM_MAGIC)
		nvram_rehash(header);
#else
// nvram_rehash - may corrupt correct header
	_nvram_read(header);
	if (header->magic != NVRAM_MAGIC)
		nvram_rehash(header);
#endif

	MFREE(si_osh(sih), header, NVRAM_SPACE);
	return ret;
}
예제 #2
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;
}
예제 #3
0
파일: sflash.c 프로젝트: ariavie/bcm
/* Erase a region. Returns number of bytes scheduled for erasure.
 * Caller should poll for completion.
 */
int
sflash_erase(si_t *sih, chipcregs_t *cc, uint offset)
{
    struct sflash *sfl;
    osl_t *osh;
    
    ASSERT(sih);
    
    osh = si_osh(sih);
    
    sfl = &sflash;
    if (offset >= sfl->size)
        return -22;
    
    switch (sfl->type) {
    case SFLASH_ST:
          sflash_cmd(osh, cc, SFLASH_ST_WREN);
          W_REG(osh, &cc->sflashaddress, offset);
          sflash_cmd(osh, cc, SFLASH_ST_SE);
          return sfl->blocksize;
    case SFLASH_AT:
          W_REG(osh, &cc->sflashaddress, offset << 1);
          sflash_cmd(osh, cc, SFLASH_AT_PAGE_ERASE);
          return sfl->blocksize;
    }
    
    return 0;
}
예제 #4
0
파일: ccsflash.c 프로젝트: hajuuk/R7000
/* Poll for command completion. Returns zero when complete. */
static int
ccsflash_poll(hndsflash_t *sfl, uint offset)
{
	si_t *sih = sfl->sih;
	chipcregs_t *cc = (chipcregs_t *)sfl->core;
	osl_t *osh;

	ASSERT(sih);

	osh = si_osh(sih);

	if (offset >= sfl->size)
		return -22;

	switch (sfl->type) {
	case SFLASH_ST:
		/* Check for ST Write In Progress bit */
		ccsflash_cmd(osh, cc, SFLASH_ST_RDSR);
		return R_REG(osh, &cc->flashdata) & SFLASH_ST_WIP;
	case SFLASH_AT:
		/* Check for Atmel Ready bit */
		ccsflash_cmd(osh, cc, SFLASH_AT_STATUS);
		return !(R_REG(osh, &cc->flashdata) & SFLASH_AT_READY);
	}

	return 0;
}
예제 #5
0
uint
pcie_writereg(si_t *sih, sbpcieregs_t *pcieregs, uint addrtype, uint offset, uint val)
{
	osl_t   *osh = si_osh(sih);

	ASSERT(pcieregs != NULL);
	BCM_REFERENCE(osh);

	if ((BUSTYPE(sih->bustype) == SI_BUS) || PCIE_GEN1(sih)) {
		switch (addrtype) {
			case PCIE_CONFIGREGS:
				W_REG(osh, (&pcieregs->configaddr), offset);
				W_REG(osh, (&pcieregs->configdata), val);
				break;
			case PCIE_PCIEREGS:
				W_REG(osh, (&pcieregs->u.pcie1.pcieindaddr), offset);
				W_REG(osh, (&pcieregs->u.pcie1.pcieinddata), val);
				break;
			default:
				ASSERT(0);
				break;
		}
	}
	else if (PCIE_GEN2(sih)) {
		W_REG(osh, (&pcieregs->configaddr), offset);
		W_REG(osh, (&pcieregs->configdata), val);
	}
	return 0;
}
예제 #6
0
/* Poll for command completion. Returns zero when complete. */
int
sflash_poll(si_t *sih, chipcregs_t *cc, uint offset)
{
	osl_t *osh;

	ASSERT(sih);

	osh = si_osh(sih);

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

	switch (sflash.type) {
	case SFLASH_ST:
		/* Check for ST Write In Progress bit */
		sflash_cmd(osh, cc, SFLASH_ST_RDSR);
		return R_REG(osh, &cc->flashdata) & SFLASH_ST_WIP;
	case SFLASH_AT:
		/* Check for Atmel Ready bit */
		sflash_cmd(osh, cc, SFLASH_AT_STATUS);
		return !(R_REG(osh, &cc->flashdata) & SFLASH_AT_READY);
	}

	return 0;
}
예제 #7
0
파일: hndpci.c 프로젝트: millken/zhuxianB30
/*
 * Read host bridge PCI config registers from Silicon Backplane ( >= rev8 ).
 *
 * It returns TRUE to indicate that access to the host bridge's pci config
 * from SI is ok, and values in 'addr' and 'val' are valid.
 *
 * It can only read registers at multiple of 4-bytes. Callers must pick up
 * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects
 * the register address where value in 'val' is read.
 */
static bool
si_pcihb_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, uint32 **addr,
    uint32 *val)
{
    sbpciregs_t *pci;
    osl_t *osh;
    uint coreidx;
    bool ret = FALSE;
    uint8 port;

    /* sanity check */
    ASSERT(PCIE_IS_BUS_HOST_BRIDGE(bus));
    ASSERT(dev == pci_hbslot);

    /* we support only two functions on device 0 */
    if (func > 1)
        return FALSE;

    /* Convert logical bus to physical port/bus for following processing */
    port = PCIE_GET_PORT_BY_BUS(bus);

    osh = si_osh(sih);

    /* read pci config when core rev >= 8 */
    coreidx = si_coreidx(sih);
    pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, port);
    if (pci) {
        if (si_corerev(sih) >= PCI_HBSBCFG_REV) {
            *addr = (uint32 *)&pci->pcicfg[func][off >> 2];
            *val = R_REG(osh, *addr);
            ret = TRUE;
        }
    } else {
예제 #8
0
파일: hndpci.c 프로젝트: hajuuk/R7000
/*
 * Read host bridge PCI config registers from Silicon Backplane ( >= rev8 ).
 *
 * It returns TRUE to indicate that access to the host bridge's pci config
 * from SI is ok, and values in 'addr' and 'val' are valid.
 *
 * It can only read registers at multiple of 4-bytes. Callers must pick up
 * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects
 * the register address where value in 'val' is read.
 */
static bool
si_pcihb_read_config(si_t *sih, uint coreunit, uint bus, uint dev, uint func,
	uint off, uint32 **addr, uint32 *val)
{
	sbpciregs_t *pci;
	osl_t *osh;
	uint coreidx;
	bool ret = FALSE;

	/* sanity check */
	ASSERT(hndpci_is_hostbridge(bus, dev));

	/* we support only two functions on device 0 */
	if (func > 1)
		return FALSE;

	osh = si_osh(sih);

	/* read pci config when core rev >= 8 */
	coreidx = si_coreidx(sih);
	pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit);
	if (pci) {
		if (si_corerev(sih) >= PCI_HBSBCFG_REV) {
			*addr = (uint32 *)&pci->pcicfg[func][off >> 2];
			*val = R_REG(osh, *addr);
			ret = TRUE;
		}
	} else {
예제 #9
0
/* Erase a region. Returns number of bytes scheduled for erasure.
 * Caller should poll for completion.
 */
int
sflash_erase(si_t *sih, chipcregs_t *cc, uint offset)
{
	struct sflash *sfl;
	osl_t *osh;

	ASSERT(sih);

	osh = si_osh(sih);

	sfl = &sflash;
	if (offset >= sfl->size)
		return -22;

	switch (sfl->type) {
	case SFLASH_ST:
		sflash_cmd(osh, cc, SFLASH_ST_WREN);
		W_REG(osh, &cc->flashaddress, offset);
		/* Newer flashes have "sub-sectors" which can be erased independently
		 * with a new command: ST_SSE. The ST_SE command erases 64KB just as
		 * before.
		 */
		sflash_cmd(osh, cc, (sfl->blocksize < (64 * 1024)) ? SFLASH_ST_SSE : SFLASH_ST_SE);
		return sfl->blocksize;
	case SFLASH_AT:
		W_REG(osh, &cc->flashaddress, offset << 1);
		sflash_cmd(osh, cc, SFLASH_AT_PAGE_ERASE);
		return sfl->blocksize;
	}

	return 0;
}
예제 #10
0
/* Allocate private resource */
adm_info_t *
adm_attach(si_t *sih, char *vars)
{
	adm_info_t *adm;
	int gpio;

	/* Allocate private data */
	if (!(adm = MALLOC(si_osh(sih), sizeof(adm_info_t)))) {
		ET_ERROR(("adm_attach: out of memory, malloc %d bytes", MALLOCED(si_osh(sih))));
		return NULL;
	}
	bzero((char *) adm, sizeof(adm_info_t));
	adm->sih = sih;
	adm->vars = vars;

	/* Init GPIO mapping. Default GPIO: 2, 3, 4 */
	gpio = getgpiopin(vars, "adm_eecs", 2);
	ET_ERROR(("adm_attach: got %d as adm_eecs", gpio));
	if (gpio == GPIO_PIN_NOTDEFINED) {
		ET_ERROR(("adm_attach: adm_eecs gpio fail: GPIO 2 in use"));
		goto error;
	}
	adm->eecs = 1 << gpio;

	gpio = getgpiopin(vars, "adm_eesk", 3);
	ET_ERROR(("adm_attach: got %d as adm_eesk", gpio));
	if (gpio == GPIO_PIN_NOTDEFINED) {
		ET_ERROR(("adm_attach: adm_eesk gpio fail: GPIO 3 in use"));
		goto error;
	}
	adm->eesk = 1 << gpio;

	gpio = getgpiopin(vars, "adm_eedi", 4);
	ET_ERROR(("adm_attach: got %d as adm_eedi", gpio));
	if (gpio == GPIO_PIN_NOTDEFINED) {
		ET_ERROR(("adm_attach: adm_eedi gpio fail: GPIO 4 in use"));
		goto error;
	}
	adm->eedi = 1 << gpio;

	return adm;

error:
	adm_detach(adm);
	return NULL;
}
예제 #11
0
/* Read len bytes starting at offset into buf. Returns number of bytes read. */
int
sflash_read(si_t *sih, chipcregs_t *cc, uint offset, uint len, uchar *buf)
{
	uint8 *from, *to;
	int cnt, i;
	osl_t *osh;

	ASSERT(sih);

	if (!len)
		return 0;

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

	if ((len >= 4) && (offset & 3))
		cnt = 4 - (offset & 3);
	else if ((len >= 4) && ((uintptr)buf & 3))
		cnt = 4 - ((uintptr)buf & 3);
	else
		cnt = len;

	osh = si_osh(sih);

	if (sih->ccrev == 12)
		from = (uint8 *)OSL_UNCACHED((void *)SI_FLASH2 + offset);
	else
		from = (uint8 *)OSL_CACHED((void *)SI_FLASH2 + offset);
	to = (uint8 *)buf;

	if (cnt < 4) {
		for (i = 0; i < cnt; i ++) {
			/* Cannot use R_REG because in bigendian that will
			 * xor the address and we don't want that here.
			 */
			*to = *from;
			from ++;
			to ++;
		}
		return cnt;
	}

	while (cnt >= 4) {
		*(uint32 *)to = *(uint32 *)from;
		from += 4;
		to += 4;
		cnt -= 4;
	}

	return (len - cnt);
}
예제 #12
0
파일: sflash.c 프로젝트: ariavie/bcm
/* Read len bytes starting at offset into buf. Returns number of bytes read. */
int
sflash_read(si_t *sih, chipcregs_t *cc, uint offset, uint len, uchar *buf)
{
    uint8 *from, *to;
    int cnt, i;
    osl_t *osh;
    
    ASSERT(sih);
    
    if (!len)
        return 0;
    
    if ((offset + len) > sflash.size)
        return -22;
    
    if ((len >= 4) && (offset & 3))
        cnt = 4 - (offset & 3);
    else if ((len >= 4) && ((uintptr)buf & 3))
        cnt = 4 - ((uintptr)buf & 3);
    else
        cnt = len;
    
    osh = si_osh(sih);
    
    from = (uint8 *)OSL_UNCACHED(SI_FLASH2 + offset);
    to = (uint8 *)buf;
    
    if (cnt < 4) {
        for (i = 0; i < cnt; i ++) {
            *to = R_REG(osh, from);
            from ++;
            to ++;
        }
        return cnt;
    }
    
    while (cnt >= 4) {
        *(uint32 *)to = R_REG(osh, (uint32 *)from);
        from += 4;
        to += 4;
        cnt -= 4;
    }
    
    return (len - cnt);
}
예제 #13
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);
}
예제 #14
0
파일: hndchipc.c 프로젝트: ariavie/bcm
void
si_cc_isr(si_t *sih, chipcregs_t *regs)
{
    uint32 ccintstatus;
    uint32 intstatus;
    uint32 i;

    /* prior to rev 21 chipc interrupt means uart and gpio */
    if (sih->ccrev >= 21)
        ccintstatus = R_REG(si_osh(sih), &regs->intstatus) & cc_intmask;
    else
        ccintstatus = (CI_UART | CI_GPIO);

    for (i = 0; i < MAX_CC_INT_SOURCE; i ++) {
        if ((cc_isr_desc[i].isr != NULL) &&
            (intstatus = (cc_isr_desc[i].intmask & ccintstatus))) {
            (cc_isr_desc[i].isr)(cc_isr_desc[i].cbdata, intstatus);
        }
    }
}
예제 #15
0
void
si_cc_isr(si_t *sih, chipcregs_t *regs)
{
	uint32 ccintstatus;
	uint32 intstatus;
	uint32 i;
	cc_isr_info_t *desc;

	/* prior to rev 21 chipc interrupt means uart and gpio */
	if (sih->ccrev >= 21)
		ccintstatus = R_REG(si_osh(sih), &regs->intstatus) & cc_intmask;
	else
		ccintstatus = (CI_UART | CI_GPIO);

	desc = get_cc_isr_desc();
	ASSERT(desc);
	for (i = 0; i < MAX_CC_INT_SOURCE; i++, desc++) {
		if ((desc->isr != NULL) &&
		    (intstatus = (desc->intmask & ccintstatus))) {
			(desc->isr)(desc->cbdata, intstatus);
		}
	}
}
예제 #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
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;
}
예제 #18
0
파일: hndpci.c 프로젝트: millken/zhuxianB30
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;
}
예제 #19
0
static int
dev_nvram_init(void)
{
	int order = 0, ret = 0;
	struct page *page, *end;
	osl_t *osh;
#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
	unsigned int i;
#endif

	/* Allocate and reserve memory to mmap() */
	while ((PAGE_SIZE << order) < nvram_space)
		order++;
	end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
	for (page = virt_to_page(nvram_buf); page <= end; page++) {
		SetPageReserved(page);
	}

#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
	/* Find associated MTD device */
	for (i = 0; i < MAX_MTD_DEVICES; i++) {
		nvram_mtd = get_mtd_device(NULL, i);
		if (!IS_ERR(nvram_mtd)) {
			if (!strcmp(nvram_mtd->name, "nvram") &&
			    nvram_mtd->size >= nvram_space) {
				break;
			}
			put_mtd_device(nvram_mtd);
		}
	}
	if (i >= MAX_MTD_DEVICES)
		nvram_mtd = NULL;
#endif

	/* Initialize hash table lock */
	spin_lock_init(&nvram_lock);

	/* Initialize commit semaphore */
	init_MUTEX(&nvram_sem);

	/* Register char device */
	if ((nvram_major = register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) {
		ret = nvram_major;
		goto err;
	}

	if (si_osh(sih) == NULL) {
		osh = osl_attach(NULL, SI_BUS, FALSE);
		if (osh == NULL) {
			printk("Error allocating osh\n");
			unregister_chrdev(nvram_major, "nvram");
			goto err;
		}
		si_setosh(sih, osh);
	}

	/* Initialize hash table */
	_nvram_init(sih);

	/* Create /dev/nvram handle */
	nvram_class = class_create(THIS_MODULE, "nvram");
	if (IS_ERR(nvram_class)) {
		printk("Error creating nvram class\n");
		goto err;
	}

	/* Add the device nvram0 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
	class_device_create(nvram_class, NULL, MKDEV(nvram_major, 0), NULL, "nvram");
#else /* Linux 2.6.36 and above */
	device_create(nvram_class, NULL, MKDEV(nvram_major, 0), NULL, "nvram");
#endif	/* Linux 2.6.36 */

	return 0;

err:
	dev_nvram_exit();
	return ret;
}
예제 #20
0
#endif

static char *findvar(char *vars_arg, char *lim, const char *name);

extern void nvram_get_global_vars(char **varlst, uint *varsz);
static char *nvram_get_internal(const char *name);
static int nvram_getall_internal(char *buf, int count);

static void
#if defined(WLTEST) || !defined(WLC_HIGH)
sortvars(si_t *sih, vars_t *new)
#else
	BCMATTACHFN(sortvars)(si_t *sih, vars_t *new)
#endif
{
	osl_t *osh = si_osh(sih);
	char *s = new->vars;
	int i;
	char *temp;
	char *c, *cend;
	uint8 *lp;

	/*
	 * Sort the variables by length.  Everything len NUM_VISZES or
	 * greater is dumped into the end of the area
	 * in no particular order.  The search algorithm can then
	 * restrict the search to just those variables that are the
	 * proper length.
	 */

	/* get a temp array to hold the sorted vars */
예제 #21
0
파일: sflash.c 프로젝트: ariavie/bcm
/* Initialize serial flash access */
struct sflash *
sflash_init(si_t *sih, chipcregs_t *cc)
{
    uint32 id;
    osl_t *osh;
    uint32  mem_type, mem_cap;
    
    ASSERT(sih);
    
    osh = si_osh(sih);
    
    bzero(&sflash, sizeof(sflash));
    
    sflash.type = sih->cccaps & CC_CAP_FLASH_MASK;
    
    switch (sflash.type) {
    case SFLASH_ST:
          /* Probe for ST chips */
          sflash_cmd(osh, cc, (SFLASH_ST_RDID | SFLASH_ST_CSA));
          sflash_cmd(osh, cc, (SFLASH_ST_RDID_READ | SFLASH_ST_CSA));
          id = R_REG(osh, &cc->sflashdata);
          sflash_cmd(osh, cc, (SFLASH_ST_RDID_READ | SFLASH_ST_CSA));
          mem_type = R_REG(osh, &cc->sflashdata);
          sflash_cmd(osh, cc, (SFLASH_ST_RDID_READ | SFLASH_ST_CSA));
          mem_cap = R_REG(osh, &cc->sflashdata);
          switch (id) {
          case 0x20: /* Micron */
              switch(mem_type) {
              case 0x20: /* M25P series */
              case 0xba: /* N25Q series */
                switch (mem_cap) {
                case 0x12:
                    /* ST M25P20 2 Mbit Serial Flash */
                    sflash.blocksize = 64 * 1024;
                    sflash.numblocks = 4;
                    break;
                case 0x13:
                    /* ST M25P40 4 Mbit Serial Flash */
                    sflash.blocksize = 64 * 1024;
                    sflash.numblocks = 8;
                    break;
                case 0x14:
                    /* ST M25P80 8 Mbit Serial Flash */
                    sflash.blocksize = 64 * 1024;
                    sflash.numblocks = 16;
                    break;
                case 0x15:
                    /* ST M25P16 16 Mbit Serial Flash */
                    sflash.blocksize = 64 * 1024;
                    sflash.numblocks = 32;
                    break;
                case 0x16:
                    /* ST M25P32 32 Mbit Serial Flash */
                    sflash.blocksize = 64 * 1024;
                    sflash.numblocks = 64;
                    break;
                case 0x17:
                    /* ST M25P64 64 Mbit Serial Flash */
                    sflash.blocksize = 64 * 1024;
                    sflash.numblocks = 128;
                    break;
                case 0x18:
                    /* ST M25P 128 Mbit Serial Flash */
                    sflash.blocksize = 64 * 1024;
                    sflash.numblocks = 256;
                    break;
                }
                break;
              }
              break;
          case 0x01: /* Spansion */
              if ((mem_type == 0x20) && (mem_cap == 0x18)) {
                /* ST S25FL128P00M 128 Mbit */
                sflash.blocksize = 64 * 1024;
                sflash.numblocks = 256;
              } else if ((mem_type == 0x02) && (mem_cap == 0x15)) {
                /* ST S25FL032P */
                sflash.blocksize = 64 * 1024;
                sflash.numblocks = 64;
              }
              break;
          case 0xbf: /* SST */
              if ((mem_type == 0x25) && (mem_cap == 0x8e)) {
                /* SST 25VF80 */
                sflash.blocksize = 64 * 1024;
                sflash.numblocks = 8;
              }
              break;
          }
          /* All done, drop cs & read */
          W_REG(osh, &cc->sflashcontrol, 0);
          break;
    
    case SFLASH_AT:
          /* Probe for Atmel chips */
          sflash_cmd(osh, cc, SFLASH_AT_STATUS);
          id = R_REG(osh, &cc->sflashdata) & 0x3c;
          switch (id) {
          case 0xc:
              /* Atmel AT45DB011 1Mbit Serial Flash */
              sflash.blocksize = 256;
              sflash.numblocks = 512;
              break;
          case 0x14:
              /* Atmel AT45DB021 2Mbit Serial Flash */
              sflash.blocksize = 256;
              sflash.numblocks = 1024;
              break;
          case 0x1c:
              /* Atmel AT45DB041 4Mbit Serial Flash */
              sflash.blocksize = 256;
              sflash.numblocks = 2048;
              break;
          case 0x24:
              /* Atmel AT45DB081 8Mbit Serial Flash */
              sflash.blocksize = 256;
              sflash.numblocks = 4096;
              break;
          case 0x2c:
              /* Atmel AT45DB161 16Mbit Serial Flash */
              sflash.blocksize = 512;
              sflash.numblocks = 4096;
              break;
          case 0x34:
              /* Atmel AT45DB321 32Mbit Serial Flash */
              sflash.blocksize = 512;
              sflash.numblocks = 8192;
              break;
          case 0x3c:
              /* Atmel AT45DB642 64Mbit Serial Flash */
              sflash.blocksize = 1024;
              sflash.numblocks = 8192;
              break;
          }
          break;
    }
    
    sflash.size = sflash.blocksize * sflash.numblocks;
    return sflash.size ? &sflash : NULL;
}
예제 #22
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;
}
예제 #23
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;
}
예제 #24
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);
}
예제 #25
0
static int
dev_nvram_init(void)
{
	int order = 0, ret = 0;
	struct page *page, *end;
	unsigned int i;
	osl_t *osh;

	/* Allocate and reserve memory to mmap() */
	while ((PAGE_SIZE << order) < nvram_space)
		order++;
	end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
	for (page = virt_to_page(nvram_buf); page <= end; page++) {
		SetPageReserved(page);
	}

#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
	/* Find associated MTD device */
	for (i = 0; i < MAX_MTD_DEVICES; i++) {
		nvram_mtd = get_mtd_device(NULL, i);
		if (!IS_ERR(nvram_mtd)) {
			if (!strcmp(nvram_mtd->name, "nvram") &&
			    nvram_mtd->size >= nvram_space) {
				break;
			}
			put_mtd_device(nvram_mtd);
		}
	}
	if (i >= MAX_MTD_DEVICES)
		nvram_mtd = NULL;
#endif

	/* Initialize hash table lock */
	spin_lock_init(&nvram_lock);

	/* Initialize commit semaphore */
	init_MUTEX(&nvram_sem);

	/* Register char device */
	if ((nvram_major = register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) {
		ret = nvram_major;
		goto err;
	}

	if (si_osh(sih) == NULL) {
		osh = osl_attach(NULL, SI_BUS, FALSE);
		if (osh == NULL) {
			printk("Error allocating osh\n");
			unregister_chrdev(nvram_major, "nvram");
			goto err;
		}
		si_setosh(sih, osh);
	}

printk("dev_nvram_init: _nvram_init\n");
	/* Initialize hash table */
	_nvram_init((void *)sih);

	/* Create /dev/nvram handle */
	nvram_class = class_create(THIS_MODULE, "nvram");
	if (IS_ERR(nvram_class)) {
		printk("Error creating nvram class\n");
		goto err;
	}

	/* Add the device nvram0 */
	class_device_create(nvram_class, NULL, MKDEV(nvram_major, 0), NULL, "nvram");

	/* reserve commit read buffer */
	/* Backup sector blocks to be erased */
	if (!(nvram_commit_buf = kmalloc(ROUNDUP(nvram_space, nvram_mtd->erasesize), GFP_KERNEL))) {
		printk("dev_nvram_init: nvram_commit_buf out of memory\n");
		goto err;
	}

	/* Set the SDRAM NCDL value into NVRAM if not already done */
	if (getintvar(NULL, "sdram_ncdl") == 0) {
		unsigned int ncdl;
		char buf[] = "0x00000000";

		if ((ncdl = si_memc_get_ncdl(sih))) {
			sprintf(buf, "0x%08x", ncdl);
			nvram_set("sdram_ncdl", buf);
			nvram_commit();
		}
	}

	return 0;

err:
	dev_nvram_exit();
	return ret;
}
예제 #26
0
static int
dev_nvram_init(void)
{
	int order = 0, ret = 0;
	struct page *page, *end;
	unsigned int i;
	osl_t *osh;

	/* Allocate and reserve memory to mmap() */
	while ((PAGE_SIZE << order) < NVRAM_SPACE)
		order++;
	end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
	for (page = virt_to_page(nvram_buf); page <= end; page++) {
		SetPageReserved(page);
	}

#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
	/* Find associated MTD device */
	for (i = 0; i < MAX_MTD_DEVICES; i++) {
		nvram_mtd = get_mtd_device(NULL, i);
		if (!IS_ERR(nvram_mtd)) {
			if (!strcmp(nvram_mtd->name, "nvram") &&
			    nvram_mtd->size >= NVRAM_SPACE) {
				break;
			}
			put_mtd_device(nvram_mtd);
		}
	}
	if (i >= MAX_MTD_DEVICES)
		nvram_mtd = NULL;
#endif

#ifdef RTN66U_NVRAM_64K_SUPPORT
        int ret32;
        char *log_buf;
        u_int32_t offset_t;
        size_t log_len;
        DECLARE_WAITQUEUE(wait, current);
        wait_queue_head_t wait_q;
        struct erase_info erase;

        offset_t = 0x18000;
        ret32 = nvram_mtd->read(nvram_mtd, offset_t, 4, &log_len, &log_buf);
        if(log_buf==0xffffffff) {
	        /* Erase sector blocks */
                init_waitqueue_head(&wait_q);

                erase.mtd = nvram_mtd;
                erase.addr = 0;
                erase.len = nvram_mtd->erasesize;
                erase.callback = erase_callback;
                erase.priv = (u_long) &wait_q;
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wait_q, &wait);

                /* Unlock sector blocks */
                if (nvram_mtd->unlock)
                        nvram_mtd->unlock(nvram_mtd, 0, nvram_mtd->erasesize);

                if ((ret = nvram_mtd->erase(nvram_mtd, &erase))) {
                        set_current_state(TASK_RUNNING);
                        remove_wait_queue(&wait_q, &wait);
                        printk("nvram mtd erase error\n");
                }

                /* Wait for erase to finish */
                schedule();
                remove_wait_queue(&wait_q, &wait);
        }
#endif

	/* Initialize hash table lock */
	spin_lock_init(&nvram_lock);

	/* Initialize commit semaphore */
	init_MUTEX(&nvram_sem);

	/* Register char device */
	if ((nvram_major = register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) {
		ret = nvram_major;
		goto err;
	}

	if (si_osh(sih) == NULL) {
		osh = osl_attach(NULL, SI_BUS, FALSE);
		if (osh == NULL) {
			printk("Error allocating osh\n");
			unregister_chrdev(nvram_major, "nvram");
			goto err;
		}
		si_setosh(sih, osh);
	}

        /* Initialize hash table */
        _nvram_init(sih);

	/* Create /dev/nvram handle */
	nvram_class = class_create(THIS_MODULE, "nvram");
	if (IS_ERR(nvram_class)) {
		printk("Error creating nvram class\n");
		goto err;
	}

	/* Add the device nvram0 */
	class_device_create(nvram_class, NULL, MKDEV(nvram_major, 0), NULL, "nvram");

	/* reserve commit read buffer */
	/* Backup sector blocks to be erased */
	if (!(nvram_commit_buf = kmalloc(ROUNDUP(NVRAM_SPACE, nvram_mtd->erasesize), GFP_KERNEL))) {
		printk("dev_nvram_init: nvram_commit_buf out of memory\n");
		goto err;
	}

	/* Set the SDRAM NCDL value into NVRAM if not already done */
	if (getintvar(NULL, "sdram_ncdl") == 0) {
		unsigned int ncdl;
		char buf[] = "0x00000000";

		if ((ncdl = si_memc_get_ncdl(sih))) {
			sprintf(buf, "0x%08x", ncdl);
			nvram_set("sdram_ncdl", buf);
			nvram_commit();
		}
	}

	return 0;

err:
	dev_nvram_exit();
	return ret;
}
예제 #27
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;
}
예제 #28
0
/* Initialize serial flash access */
struct sflash *
sflash_init(si_t *sih, chipcregs_t *cc)
{
	uint32 id, id2;
	char *name = "";
	osl_t *osh;

	ASSERT(sih);

	osh = si_osh(sih);

	bzero(&sflash, sizeof(sflash));

	sflash.type = sih->cccaps & CC_CAP_FLASH_MASK;

	switch (sflash.type) {
	case SFLASH_ST:
		/* Probe for ST chips */
		name = "ST compatible";
		sflash_cmd(osh, cc, SFLASH_ST_DP);
		W_REG(osh, &cc->flashaddress, 0);
		sflash_cmd(osh, cc, SFLASH_ST_RES);
		id = R_REG(osh, &cc->flashdata);
		sflash.blocksize = 64 * 1024;
		switch (id) {
		case 0x11:
			/* ST M25P20 2 Mbit Serial Flash */
			sflash.numblocks = 4;
			break;
		case 0x12:
			/* ST M25P40 4 Mbit Serial Flash */
			sflash.numblocks = 8;
			break;
		case 0x13:
			/* ST M25P80 8 Mbit Serial Flash */
			sflash.numblocks = 16;
			break;
		case 0x14:
			/* ST M25P16 16 Mbit Serial Flash */
			sflash.numblocks = 32;
			break;
		case 0x15:
			/* ST M25P32 32 Mbit Serial Flash */
			sflash.numblocks = 64;
			break;
		case 0x16:
			/* ST M25P64 64 Mbit Serial Flash */
			sflash.numblocks = 128;
			break;
		case 0x17:
			/* ST M25FL128 128 Mbit Serial Flash */
			sflash.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";
			sflash.blocksize = 4 * 1024;
			W_REG(osh, &cc->flashaddress, 1);
			sflash_cmd(osh, cc, SFLASH_ST_RES);
			id2 = R_REG(osh, &cc->flashdata);
			switch (id2) {
			case 1:
				/* SST25WF512 512 Kbit Serial Flash */
				sflash.numblocks = 16;
				break;
			case 0x48:
				/* SST25VF512 512 Kbit Serial Flash */
				sflash.numblocks = 16;
				break;
			case 2:
				/* SST25WF010 1 Mbit Serial Flash */
				sflash.numblocks = 32;
				break;
			case 0x49:
				/* SST25VF010 1 Mbit Serial Flash */
				sflash.numblocks = 32;
				break;
			case 3:
				/* SST25WF020 2 Mbit Serial Flash */
				sflash.numblocks = 64;
				break;
			case 0x43:
				/* SST25VF020 2 Mbit Serial Flash */
				sflash.numblocks = 64;
				break;
			case 4:
				/* SST25WF040 4 Mbit Serial Flash */
				sflash.numblocks = 128;
				break;
			case 0x44:
				/* SST25VF040 4 Mbit Serial Flash */
				sflash.numblocks = 128;
				break;
			case 0x8d:
				/* SST25VF040B 4 Mbit Serial Flash */
				sflash.numblocks = 128;
				break;
			case 5:
				/* SST25WF080 8 Mbit Serial Flash */
				sflash.numblocks = 256;
				break;
			case 0x8e:
				/* SST25VF080B 8 Mbit Serial Flash */
				sflash.numblocks = 256;
				break;
			case 0x41:
				/* SST25VF016 16 Mbit Serial Flash */
				sflash.numblocks = 512;
				break;
			case 0x4a:
				/* SST25VF032 32 Mbit Serial Flash */
				sflash.numblocks = 1024;
				break;
			case 0x4b:
				/* SST25VF064 64 Mbit Serial Flash */
				sflash.numblocks = 2048;
				break;
			}
			break;
		}
		break;

	case SFLASH_AT:
		/* Probe for Atmel chips */
		name = "Atmel";
		sflash_cmd(osh, cc, SFLASH_AT_STATUS);
		id = R_REG(osh, &cc->flashdata) & 0x3c;
		switch (id) {
		case 0xc:
			/* Atmel AT45DB011 1Mbit Serial Flash */
			sflash.blocksize = 256;
			sflash.numblocks = 512;
			break;
		case 0x14:
			/* Atmel AT45DB021 2Mbit Serial Flash */
			sflash.blocksize = 256;
			sflash.numblocks = 1024;
			break;
		case 0x1c:
			/* Atmel AT45DB041 4Mbit Serial Flash */
			sflash.blocksize = 256;
			sflash.numblocks = 2048;
			break;
		case 0x24:
			/* Atmel AT45DB081 8Mbit Serial Flash */
			sflash.blocksize = 256;
			sflash.numblocks = 4096;
			break;
		case 0x2c:
			/* Atmel AT45DB161 16Mbit Serial Flash */
			sflash.blocksize = 512;
			sflash.numblocks = 4096;
			break;
		case 0x34:
			/* Atmel AT45DB321 32Mbit Serial Flash */
			sflash.blocksize = 512;
			sflash.numblocks = 8192;
			break;
		case 0x3c:
			/* Atmel AT45DB642 64Mbit Serial Flash */
			sflash.blocksize = 1024;
			sflash.numblocks = 8192;
			break;
		}
		break;
	}

	sflash.size = sflash.blocksize * sflash.numblocks;

	if (firsttime)
		printf("Found an %s serial flash with %d %dKB blocks; total size %dMB\n",
		       name, sflash.numblocks, sflash.blocksize / 1024,
		       sflash.size / (1024 * 1024));

	firsttime = FALSE;
	return sflash.size ? &sflash : NULL;
}
예제 #29
0
/*
 * writes the appropriate range of flash, a NULL buf simply erases
 * the region of flash
 */
int
sflash_commit(si_t *sih, chipcregs_t *cc, uint offset, uint len, const uchar *buf)
{
	struct sflash *sfl;
	uchar *block = NULL, *cur_ptr, *blk_ptr;
	uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder;
	uint blk_offset, blk_len, copied;
	int bytes, ret = 0;
	osl_t *osh;

	ASSERT(sih);

	osh = si_osh(sih);

	/* Check address range */
	if (len <= 0)
		return 0;

	sfl = &sflash;
	if ((offset + len) > sfl->size)
		return -1;

	blocksize = sfl->blocksize;
	mask = blocksize - 1;

	/* Allocate a block of mem */
	if (!(block = MALLOC(osh, blocksize)))
		return -1;

	while (len) {
		/* Align offset */
		cur_offset = offset & ~mask;
		cur_length = blocksize;
		cur_ptr = block;

		remainder = blocksize - (offset & mask);
		if (len < remainder)
			cur_retlen = len;
		else
			cur_retlen = remainder;

		/* buf == NULL means erase only */
		if (buf) {
			/* Copy existing data into holding block if necessary */
			if ((offset & mask) || (len < blocksize)) {
				blk_offset = cur_offset;
				blk_len = cur_length;
				blk_ptr = cur_ptr;

				/* Copy entire block */
				while (blk_len) {
					copied = sflash_read(sih, cc, blk_offset, blk_len, blk_ptr);
					blk_offset += copied;
					blk_len -= copied;
					blk_ptr += copied;
				}
			}

			/* Copy input data into holding block */
			memcpy(cur_ptr + (offset & mask), buf, cur_retlen);
		}

		/* Erase block */
		if ((ret = sflash_erase(sih, cc, (uint) cur_offset)) < 0)
			goto done;
		while (sflash_poll(sih, cc, (uint) cur_offset));

		/* buf == NULL means erase only */
		if (!buf) {
			offset += cur_retlen;
			len -= cur_retlen;
			continue;
		}

		/* Write holding block */
		while (cur_length > 0) {
			if ((bytes = sflash_write(sih, cc,
			                          (uint) cur_offset,
			                          (uint) cur_length,
			                          (uchar *) cur_ptr)) < 0) {
				ret = bytes;
				goto done;
			}
			while (sflash_poll(sih, cc, (uint) cur_offset));
			cur_offset += bytes;
			cur_length -= bytes;
			cur_ptr += bytes;
		}

		offset += cur_retlen;
		len -= cur_retlen;
		buf += cur_retlen;
	}

	ret = len;
done:
	if (block)
		MFREE(osh, block, blocksize);
	return ret;
}
예제 #30
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);
}