コード例 #1
0
ファイル: flashutl.c プロジェクト: NieHao/Tomato-RAF
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;
}
コード例 #2
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);
}
コード例 #3
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;
}
コード例 #4
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;
}