欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

flash.c

适合KS8695X
C
第 1 页 / 共 2 页
字号:
#define SIZE_4MiB 22

static const struct jedec_flash_info jedec_table[] = {
	{
		mfr_id: (uint16_t)AMD_MANUFACT,
		dev_id: (uint16_t)AMD_ID_LV800T,
		name: "AMD AM29LV800T",
		DevSize: SIZE_1MiB,
		NumEraseRegions: 4,
		regions: {ERASEINFO(0x10000,15),
			  ERASEINFO(0x08000,1),
			  ERASEINFO(0x02000,2),
			  ERASEINFO(0x04000,1)
		}
	}, {
		mfr_id: (uint16_t)AMD_MANUFACT,
		dev_id: (uint16_t)AMD_ID_LV800B,
		name: "AMD AM29LV800B",
		DevSize: SIZE_1MiB,
		NumEraseRegions: 4,
		regions: {ERASEINFO(0x10000,15),
		          ERASEINFO(0x08000,1),
			  ERASEINFO(0x02000,2),
			  ERASEINFO(0x04000,1)
		}
	}, {
		mfr_id: (uint16_t)AMD_MANUFACT,
		dev_id: (uint16_t)AMD_ID_LV160T,
		name: "AMD AM29LV160T",
		DevSize: SIZE_2MiB,
		NumEraseRegions: 4,
		regions: {ERASEINFO(0x10000,31),
		          ERASEINFO(0x08000,1),
			  ERASEINFO(0x02000,2),
			  ERASEINFO(0x04000,1)
		}
	}, {
		mfr_id: (uint16_t)AMD_MANUFACT,
		dev_id: (uint16_t)AMD_ID_LV160B,
		name: "AMD AM29LV160B",
		DevSize: SIZE_2MiB,
		NumEraseRegions: 4,
		regions: {ERASEINFO(0x04000,1),
		          ERASEINFO(0x02000,2),
			  ERASEINFO(0x08000,1),
			  ERASEINFO(0x10000,31)
		}
	}, {
		mfr_id: (uint16_t)AMD_MANUFACT,
		dev_id: (uint16_t)AMD_ID_LV320T,
		name: "AMD AM29LV320T",
		DevSize: SIZE_4MiB,
		NumEraseRegions: 2,
		regions: {ERASEINFO(0x10000,63),
		          ERASEINFO(0x02000,8)
		}

	}, {
		mfr_id: (uint16_t)AMD_MANUFACT,
		dev_id: (uint16_t)AMD_ID_LV320B,
		name: "AMD AM29LV320B",
		DevSize: SIZE_4MiB,
		NumEraseRegions: 2,
		regions: {ERASEINFO(0x02000,8),
		          ERASEINFO(0x10000,63)
		}
	}
};

static ulong cfi_init(uint32_t base,  flash_info_t *flash)
{
	int sector;
	int block;
	int block_count;
	int offset = 0;
	int reverse = 0;
	int primary;
	int mfr_id;
	int dev_id;

	flash->start[0] = base;
	cfi_cmd(flash, 0xF0, 0);
	cfi_cmd(flash, 0x98, 0);
	if ( !( cfi_read_query(flash, 0x10) == 'Q' &&
		cfi_read_query(flash, 0x11) == 'R' &&
		cfi_read_query(flash, 0x12) == 'Y' )) {
		cfi_cmd(flash, 0xff, 0);
		return 0;
	}

	flash->size = 1 << cfi_read_query(flash, 0x27);
	flash->size *= 4;
	block_count = cfi_read_query(flash, 0x2c);
	primary = cfi_read_query(flash, 0x15);
	if ( cfi_read_query(flash, primary + 4) == 0x30)
		reverse = (cfi_read_query(flash, 0x1) & 0x01);
	else
		reverse = (cfi_read_query(flash, primary+15) == 3);

	flash->sector_count = 0;

	for ( block = reverse ? block_count - 1	: 0;
		      reverse ? block >= 0	: block < block_count;
		      reverse ? block--		: block ++) {
		int sector_size =
			(cfi_read_query(flash, 0x2d + block*4+2) |
			(cfi_read_query(flash, 0x2d + block*4+3) << 8)) << 8;
		int sector_count =
			(cfi_read_query(flash, 0x2d + block*4+0) |
			(cfi_read_query(flash, 0x2d + block*4+1) << 8)) + 1;
		for(sector = 0; sector < sector_count; sector++) {
			flash->start[flash->sector_count++] = base + offset;
			offset += sector_size * 4;
		}
	}
	mfr_id = cfi_read_query(flash, 0x00);
	dev_id = cfi_read_query(flash, 0x01);

	cfi_cmd(flash, 0xff, 0);

	flash->flash_id = (mfr_id << 16) | dev_id;

	for (sector = 0; sector < flash->sector_count; sector++) {
		write32(flash->start[sector], 0x00600060);
		write32(flash->start[sector], 0x00d000d0);
	}
	cfi_cmd(flash, 0xff, 0);

	for (sector = 0; sector < flash->sector_count; sector++)
		flash->protect[sector] = 0;

	do_flash_erase = cfi_erase;
	write_dword = cfi_write_dword;

	return flash->size;
}

static ulong jedec_init(unsigned long base, flash_info_t *flash)
{
	int i;
	int block, block_count;
	int sector, offset;
	int mfr_id, dev_id;
	flash->start[0] = base;
	cfi_cmd(flash, 0xF0, 0x000);
	cfi_cmd(flash, 0xAA, 0x555);
	cfi_cmd(flash, 0x55, 0x2AA);
	cfi_cmd(flash, 0x90, 0x555);
	mfr_id = cfi_read_query(flash, 0x000);
	dev_id = cfi_read_query(flash, 0x0001);
	cfi_cmd(flash, 0xf0, 0x000);

	for(i=0; i<sizeof(jedec_table)/sizeof(struct jedec_flash_info); i++) {
		if((jedec_table[i].mfr_id == mfr_id) &&
			(jedec_table[i].dev_id == dev_id)) {

			flash->flash_id = (mfr_id << 16) | dev_id;
			flash->size = 1 << jedec_table[0].DevSize;
			flash->size *= 4;
			block_count = jedec_table[i].NumEraseRegions;
			offset = 0;
			flash->sector_count = 0;
			for (block = 0; block < block_count; block++) {
				int sector_size = jedec_table[i].regions[block];
				int sector_count = (sector_size & 0xff) + 1;
				sector_size >>= 8;
				for (sector=0; sector<sector_count; sector++) {
					flash->start[flash->sector_count++] =
						base + offset;
					offset += sector_size * 4;
				}
			}
			break;
		}
	}

	for (sector = 0; sector < flash->sector_count; sector++)
		flash->protect[sector] = 0;

	do_flash_erase = jedec_erase;
	write_dword = jedec_write_dword;

	return flash->size;
}

inline void mtibat1u(unsigned int x)
{
	__asm__ __volatile__ ("mtspr   530, %0" :: "r" (x));
}

inline void mtibat1l(unsigned int x)
{
	__asm__ __volatile__ ("mtspr   531, %0" :: "r" (x));
}

inline void mtdbat1u(unsigned int x)
{
	__asm__ __volatile__ ("mtspr   538, %0" :: "r" (x));
}

inline void mtdbat1l(unsigned int x)
{
	__asm__ __volatile__ ("mtspr   539, %0" :: "r" (x));
}

unsigned long flash_init (void)
{
	unsigned long size = 0;
	int i;
	unsigned int msr;

	/* BAT1 */
	CONFIG_WRITE_WORD(ERCR3, 0x0C00000C);
	CONFIG_WRITE_WORD(ERCR4, 0x0800000C);
	msr = get_msr();
	set_msr(msr & ~(MSR_IR | MSR_DR));
	mtibat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT);
	mtibat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP);
	mtdbat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT);
	mtdbat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP);
	set_msr(msr);

	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
		flash_info[i].flash_id = FLASH_UNKNOWN;
	size = cfi_init(FLASH_BASE0_PRELIM, &flash_info[0]);
	if (!size)
		size = jedec_init(FLASH_BASE0_PRELIM, &flash_info[0]);

	if (flash_info[0].flash_id == FLASH_UNKNOWN)
		printf ("# Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
			size, size<<20);

	return size;
}

void flash_print_info  (flash_info_t *flash)
{
	int i;
	int k;
	int size;
	int erased;
	volatile unsigned long *p;

	if (flash->flash_id == FLASH_UNKNOWN) {
		printf ("missing or unknown FLASH type\n");
		flash_init();
	}

	if (flash->flash_id == FLASH_UNKNOWN) {
		printf ("missing or unknown FLASH type\n");
		return;
	}

	switch (((flash->flash_id) >> 16) & 0xff) {
	case 0x01:
		printf ("AMD ");
		break;
	case 0x04:
		printf("FUJITSU ");
		break;
	case 0x20:
		printf("STM ");
		break;
	case 0xBF:
		printf("SST ");
		break;
	case 0x89:
	case 0xB0:
		printf("INTEL ");
		break;
	default:
		printf ("Unknown Vendor ");
		break;
	}

	switch ((flash->flash_id) & 0xffff) {
	case (uint16_t)AMD_ID_LV800T:
		printf ("AM29LV800T\n");
		break;
	case (uint16_t)AMD_ID_LV800B:
		printf ("AM29LV800B\n");
		break;
	case (uint16_t)AMD_ID_LV160T:
		printf ("AM29LV160T\n");
		break;
	case (uint16_t)AMD_ID_LV160B:
		printf ("AM29LV160B\n");
		break;
	case (uint16_t)AMD_ID_LV320T:
		printf ("AM29LV320T\n");
		break;
	case (uint16_t)AMD_ID_LV320B:
		printf ("AM29LV320B\n");
		break;
	case (uint16_t)INTEL_ID_28F800C3T:
		printf ("28F800C3T\n");
		break;
	case (uint16_t)INTEL_ID_28F800C3B:
		printf ("28F800C3B\n");
		break;
	case (uint16_t)INTEL_ID_28F160C3T:
		printf ("28F160C3T\n");
		break;
	case (uint16_t)INTEL_ID_28F160C3B:
		printf ("28F160C3B\n");
		break;
	case (uint16_t)INTEL_ID_28F320C3T:
		printf ("28F320C3T\n");
		break;
	case (uint16_t)INTEL_ID_28F320C3B:
		printf ("28F320C3B\n");
		break;
	case (uint16_t)INTEL_ID_28F640C3T:
		printf ("28F640C3T\n");
		break;
	case (uint16_t)INTEL_ID_28F640C3B:
		printf ("28F640C3B\n");
		break;
	default:
		printf ("Unknown Chip Type\n");
		break;
	}

	if (flash->size >= (1 << 20)) {
		printf ("  Size: %ld MB in %d Sectors\n",
				flash->size >> 20, flash->sector_count);
	} else {
		printf ("  Size: %ld kB in %d Sectors\n",
				flash->size >> 10, flash->sector_count);
	}

	printf ("  Sector Start Addresses:");
	for (i = 0; i < flash->sector_count; ++i) {
		/* Check if whole sector is erased*/
		if (i != (flash->sector_count-1))
			size = flash->start[i+1] - flash->start[i];
		else
			size = flash->start[0] + flash->size - flash->start[i];

		erased = 1;
		p = (volatile unsigned long *)flash->start[i];
		size = size >> 2;        /* divide by 4 for longword access */
		for (k=0; k<size; k++) {
			if (*p++ != 0xffffffff) {
				erased = 0;
				break;
			}
		}

		if ((i % 5) == 0)
			printf ("\n   ");

		printf (" %08lX%s%s",
			flash->start[i],
			erased ? " E" : "  ",
			flash->protect[i] ? "RO " : "   ");
	}
	printf ("\n");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -