Exemplo n.º 1
0
static int
flash_poll(unsigned long off, uint16 data)
{
	unsigned long addr;
	int cnt = FLASH_TRIES;
	uint16 st;

	ASSERT(flashutl_desc != NULL);

	if (flashutl_desc->type == AMD || flashutl_desc->type == SST) {
		/* AMD style poll checkes the address being written */
		addr = FLASH_ADDR(off);
		while ((st = flash_readword(addr)) != data && cnt != 0)
			cnt--;
		if (cnt == 0) {
			DPRINT(("flash_poll: timeout, off %lx, read 0x%x, expected 0x%x\n",
			        off, st, data));
			return -1;
		}
	} else {
		/* INTEL style poll is at second word of the block being written */
		addr = FLASH_ADDR(block(off, BLOCK_BASE)+sizeof(uint16));
		while (((st = flash_readword(addr)) & DONE) == 0 && cnt != 0)
			cnt--;
		if (cnt == 0) {
			DPRINT(("flash_poll: timeout, error status = 0x%x\n", st));
			return -1;
		}
	}
	
	return 0;
}
Exemplo n.º 2
0
Arquivo: nvm.c Projeto: miaofng/ulp
int nvm_save(void)
{
	char *src, *dest, *bak;
	int magic = NVM_MAGIC;
	int sz_ram, pages;

	src = __section_begin(".nvm.ram");
	sz_ram = (int)__section_end(".nvm.ram") - (int)__section_begin(".nvm.ram");
	if(sz_ram == 0)
		return 0;
	sz_ram = align(sz_ram, 4);
	pages = align(sz_ram + 8, FLASH_PAGE_SZ) / FLASH_PAGE_SZ;
	dest = (char *)FLASH_ADDR(FLASH_PAGE_NR - pages); //rom 1
	bak = (char *)FLASH_ADDR(FLASH_PAGE_NR - pages - pages); // rom 2

	//ram -> rom 1
	flash_Write(dest + 4, &sz_ram, 4);
	flash_Write(dest + 8, src, sz_ram);
	flash_Write(dest + 0, &magic, 4);

	//ram -> rom 2
	flash_Erase(bak, pages);
	flash_Write(bak + 4, &sz_ram, 4);
	flash_Write(bak + 8, src, sz_ram);
	flash_Write(bak + 0, &magic, 4);

	//erase rom 1
	flash_Erase(dest, pages);
	return 0;
}
Exemplo n.º 3
0
Arquivo: nvm.c Projeto: miaofng/ulp
int nvm_init(void)
{
	char *src, *dst, *bak;
	int sz_ram, magic, sz_nvm, pages;

	dst = __section_begin(".nvm.ram");
	sz_ram = (int)__section_end(".nvm.ram") - (int)__section_begin(".nvm.ram");
	if(sz_ram == 0) { //no nvm var is used
		nvm_flag_null = 0;
		return 0;
	}

	sz_ram = align(sz_ram, 4);
	pages = align(sz_ram + 8, FLASH_PAGE_SZ) / FLASH_PAGE_SZ;
	src = (char *)FLASH_ADDR(FLASH_PAGE_NR - pages); //rom 1
	bak = (char *)FLASH_ADDR(FLASH_PAGE_NR - pages - pages); // rom 2

	//rom 1 -> ram, always read & erase rom 1 in case of "rom1 not null!!!"
	flash_Read(&magic, src, 4);
	flash_Read(&sz_nvm, src + 4, 4);

	if(magic == NVM_MAGIC && sz_nvm == sz_ram) {
		flash_Read(dst, src + 8, sz_ram);

		//rom1 data is ok, rom1 -> rom 2
		flash_Erase(bak, pages);
		flash_Write(bak + 4, &sz_nvm, 4);
		flash_Write(bak + 8, dst, sz_ram);
		flash_Write(bak + 0, &magic, 4);
		flash_Erase(src, pages); //erase rom 1
		nvm_flag_null = 0;
		return 0;
	}

	//to avoid one more time erase op on an empty flash page
	if(sz_nvm != -1) {
		flash_Erase(src, pages); //erase rom 1
	}

	//rom 2 -> ram
	src = bak;
	flash_Read(&magic, src, 4);
	flash_Read(&sz_nvm, src + 4, 4);
	if(magic == NVM_MAGIC && sz_nvm == sz_ram) {
		flash_Read(dst, src + 8, sz_ram);
		nvm_flag_null = 0;
		return 0;
	}

	//fail ...
	nvm_flag_null = 1;
	return -1;
}
Exemplo n.º 4
0
/* Writes a command to flash, performing an unlock if needed. */
static void
cmd(uint16 cmd, unsigned long off)
{
	int i;
	unlock_cmd_t *ul = NULL;

	ASSERT(flashutl_cmd != NULL);

	switch (flashutl_cmd->type) {
	case AMD:
		ul = &unlock_cmd_amd;
		break;
	case SST:
		ul = &unlock_cmd_sst;
		break;
	default:
		break;
	}

	if (flashutl_cmd->need_unlock) {
		ASSERT(ul);
		for (i = 0; i < UNLOCK_CMD_WORDS; i++)
			flash_writeword(FLASH_ADDR(ul->addr[i]), ul->cmd[i]);
	}

	/* cmd |= cmd << 8; */

	if (off == CMD_ADDR) {
		switch (flashutl_cmd->type) {
		case AMD:
			off = AMD_CMD;
			break;
		case SST:
			off = SST_CMD;
			break;
		default:
			off = 0;
			break;
		}
	}

#ifdef MIPSEB
#ifdef	BCMHND74K
	off ^= 6;
#else	/* !74K, bcm33xx */
	off ^= 2;
#endif	/* BCMHND74K */
#endif /* MIPSEB */

	flash_writeword(FLASH_ADDR(off), cmd);
}
Exemplo n.º 5
0
int
sysFlashRead(uint off, uchar *buf, uint numbytes)
{
	uint read, total_read = 0;

	if (flashutl_cmd->type == SFLASH) {
		while (numbytes) {
			read = sflash_read(sih, cc, off, numbytes, buf);
			numbytes -= read;
			buf += read;
			off += read;
			total_read += read;
		}
	} else {
		ASSERT(!(off & (flashutl_wsz - 1)));
		ASSERT(!(numbytes & (flashutl_wsz - 1)));

		while (numbytes) {
			flash_writeword((unsigned long)buf, flash_readword(FLASH_ADDR(off)));
			numbytes -= flashutl_wsz;
			buf += flashutl_wsz;
			off += flashutl_wsz;
			total_read += flashutl_wsz;
		}
	}

	return (total_read);
}
Exemplo n.º 6
0
/* Writes a single command to the flash. */
static void
scmd(uint16 cmd, unsigned long off)
{
	/*  cmd |= cmd << 8; */

	flash_writeword(FLASH_ADDR(off), cmd);
}
Exemplo n.º 7
0
Arquivo: nvm.c Projeto: miaofng/ulp
/*clear nvm strorage to default state*/
int nvm_clear(void)
{
	char *src, *dest, *bak;
	int sz_ram, pages;

	src = __section_begin(".nvm.ram");
	sz_ram = (int)__section_end(".nvm.ram") - (int)__section_begin(".nvm.ram");
	if(sz_ram == 0)
		return 0;
	sz_ram = align(sz_ram, 4);
	pages = align(sz_ram + 8, FLASH_PAGE_SZ) / FLASH_PAGE_SZ;
	dest = (char *)FLASH_ADDR(FLASH_PAGE_NR - pages); //rom 1
	bak = (char *)FLASH_ADDR(FLASH_PAGE_NR - pages - pages); // rom 2

	//erase rom 2
	flash_Erase(bak, pages);

	//erase rom 1
	flash_Erase(dest, pages);
	return 0;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
static int
flash_write(unsigned long off, uint8 *src, uint nbytes)
{
	uint8 *dest;
	uint16 st, data;
	uint i, len;

	ASSERT(flashutl_desc != NULL);

	if (off >= flashutl_desc->size)
		return 1;

	ASSERT(!(off & (flashutl_wsz - 1)));

	dest = (uint8*)FLASH_ADDR(off);
	st = 0;

	while (nbytes) {
		if ((flashutl_desc->type == SCS) &&
		    flashutl_cmd->write_buf &&
		    ((off & (WBUFSIZE - 1)) == 0)) {
			/* issue write command */
			if (flashutl_cmd->write_buf)
				cmd(flashutl_cmd->write_buf, off);
			if ((st = flash_poll(off, DONE)))
				continue;

			len = MIN(nbytes, WBUFSIZE);

#ifndef MIPSEB
			/* write (length - 1) */
			cmd(len / sizeof(uint16) - 1, off);

			/* write data */
			for (i = 0; i < len; i += sizeof(uint16),
			             dest += sizeof(uint16), src += sizeof(uint16))
				*(uint16 *)dest = *(uint16 *)src;
#else
			/*
			 * BCM4710 endianness is word consistent but
			 * byte/short scrambled. This write buffer
			 * mechanism appears to be sensitive to the
			 * order of the addresses hence we need to
			 * unscramble them. We may also need to pad
			 * the source with two bytes of 0xffff in case
			 * an odd number of shorts are presented.
			 */

			/* write (padded length - 1) */
			cmd((ROUNDUP(len, sizeof(uint32)) / sizeof(uint16)) - 1, off);

			/* write data (plus pad if necessary) */
			for (i = 0; i < ROUNDUP(len, sizeof(uint32)); i += sizeof(uint32),
			             dest += sizeof(uint32), src += sizeof(uint32)) {
				*((uint16 *)dest + 1) = ((i + sizeof(uint16)) < len) ?
				        *((uint16 *)src + 1) : 0xffff;
				*(uint16 *)dest = *(uint16 *)src;
			}
#endif /* MIPSEB */

			/* write confirm */
			if (flashutl_cmd->confirm)
				cmd(flashutl_cmd->confirm, off);

			if ((st = flash_poll(off, DONE)))
				break;
		} else {
			/* issue write command */
			if (flashutl_cmd->write_word)
				cmd(flashutl_cmd->write_word, CMD_ADDR);

			/* write data */
			data = flash_readword((unsigned long)src);
			flash_writeword((unsigned long)dest, data);

			/* poll for done */
			if ((st = flash_poll(off, data)))
				break;

			len = MIN(nbytes, flashutl_wsz);
			dest += len;
			src += len;
		}

		nbytes -= len;
		off += len;
	}

	flash_reset();

	return st;
}