📄 altera_avalon_cfi_flash_table.c
字号:
else
{
flash->write_timeout = (1 << typical_timeout) * (1 << max_timeout);
}
/* Let's read the block erase timeout values from the flash */
typical_timeout = (*flash->read_query)( flash, 0x21);
max_timeout = (*flash->read_query)( flash, 0x25);
if ((typical_timeout == 0 ) || (max_timeout == 0))
{
flash->erase_timeout = 20000000; /* 20s should be more than enough */
}
else
{
flash->erase_timeout = (1 << typical_timeout) * (1 << max_timeout) * 1000;
}
device_size = 0x1 << (*flash->read_query)( flash, 0x27);
flash->dev.number_of_regions = (*flash->read_query)(flash, 0x2c);
if (flash->dev.number_of_regions > ALT_MAX_NUMBER_OF_FLASH_REGIONS)
{
ret_code = -ENOMEM;
}
else
{
for(i=0;i<flash->dev.number_of_regions;i++)
{
flash->dev.region_info[i].number_of_blocks = alt_read_16bit_query_entry(
flash,
(0x2D+i*4));
flash->dev.region_info[i].number_of_blocks += 1;
flash->dev.region_info[i].block_size = alt_read_16bit_query_entry( flash,
(0x2F+i*4));
flash->dev.region_info[i].block_size *= 256;
flash->dev.region_info[i].region_size =
flash->dev.region_info[i].number_of_blocks
* flash->dev.region_info[i].block_size;
size += flash->dev.region_info[i].region_size;
}
if (size != device_size)
{
ret_code = -ENODEV;
}
}
boot_mode = (*flash->read_query)( flash, flash->primary_address + 0xf);
/*
* Intel Flash parts describe the sections in the order they appear
* for AMD they just put all the small ones first then the bigger ones
* So if it's a top boot part we have to reverse the order of the sectors
* so they're in the correct order
*/
if ((flash->algorithm == CFI_ALG_AMD) && (boot_mode == TOP_BOOT_DEVICE))
{
for(i=flash->dev.number_of_regions-1, j=0;
j<=i;i--,j++)
{
swap = flash->dev.region_info[i].region_size;
flash->dev.region_info[i].region_size =
flash->dev.region_info[j].region_size;
flash->dev.region_info[j].region_size = swap;
swap = flash->dev.region_info[i].block_size;
flash->dev.region_info[i].block_size =
flash->dev.region_info[j].block_size;
flash->dev.region_info[j].block_size = swap;
swap = flash->dev.region_info[i].number_of_blocks;
flash->dev.region_info[i].number_of_blocks =
flash->dev.region_info[j].number_of_blocks;
flash->dev.region_info[j].number_of_blocks = swap;
}
}
for(i=0;i<flash->dev.number_of_regions;i++)
{
flash->dev.region_info[i].offset = offset;
offset += flash->dev.region_info[i].region_size;
}
(*flash->write_command)(flash->dev.base_addr,
0x55,
READ_ARRAY_MODE);
}
return ret_code;
}
/*
* alt_read_cfi_width
*
* Work out the width of the device we're talking to and sanity check that we
* can read the CFI and the Primary Vendor specific Table
*/
int alt_read_cfi_width(alt_flash_cfi_dev* flash)
{
int i;
alt_u8 byte_id[12];
alt_u16 iface;
int ret_code = 0;
/*
* Check for 8 bit wide flash
*/
alt_write_flash_command_8bit_device_8bit_mode(flash->dev.base_addr, 0x55, QUERY_MODE);
for(i=0;i<3;i++)
{
byte_id[i] = IORD_8DIRECT(flash->dev.base_addr, QUERY_ADDR+i);
}
if ((byte_id[0] == 'Q') &&
(byte_id[1] == 'R') &&
(byte_id[2] == 'Y'))
{
flash->mode_width = 1;
flash->device_width = 1;
iface = IORD_16DIRECT(flash->dev.base_addr, INTERFACE_ADDR);
iface += 1;
if (!(iface & 0x1))
{
ret_code = -ENODEV;
}
}
else
{
/*
* Check for 8/16 bit in byte wide mode
*/
alt_write_flash_command_16bit_device_8bit_mode(flash->dev.base_addr, 0x55, QUERY_MODE);
for(i=0;i<6;i++)
{
byte_id[i] = IORD_8DIRECT(flash->dev.base_addr, (QUERY_ADDR*2)+i);
}
if ((byte_id[0] == 'Q') &&
(byte_id[1] == 'Q') &&
(byte_id[2] == 'R') &&
(byte_id[3] == 'R') &&
(byte_id[4] == 'Y') &&
(byte_id[5] == 'Y'))
{
flash->mode_width = 1;
flash->device_width = 2;
iface = IORD_16DIRECT(flash->dev.base_addr, INTERFACE_ADDR*2);
iface += 1;
if (!(iface & 0x1))
{
ret_code = -ENODEV;
}
}
else
{
/*
* Check for 16 bit flash in word mode
*/
alt_write_flash_command_16bit_device_16bit_mode(flash->dev.base_addr, 0x55, QUERY_MODE);
for(i=0;i<6;i++)
{
byte_id[i] = IORD_8DIRECT(flash->dev.base_addr, (QUERY_ADDR*2)+i);
}
if ((byte_id[0] == 'Q') &&
(byte_id[1] == '\0') &&
(byte_id[2] == 'R') &&
(byte_id[3] == '\0') &&
(byte_id[4] == 'Y') &&
(byte_id[5] == '\0'))
{
flash->mode_width = 2;
flash->device_width = 2;
iface = IORD_16DIRECT(flash->dev.base_addr, INTERFACE_ADDR*2);
iface += 1;
if (!(iface & 0x2))
{
ret_code = -ENODEV;
}
}
else
{
/*
* Check for 32bit wide flash in 32 bit mode
*/
alt_write_flash_command_32bit_device_32bit_mode(flash->dev.base_addr, 0x55, QUERY_MODE);
for(i=0;i<12;i++)
{
byte_id[i] = IORD_8DIRECT(flash->dev.base_addr, (QUERY_ADDR*4)+i);
}
if ((byte_id[0] == 'Q') &&
(byte_id[1] == '\0') &&
(byte_id[2] == '\0') &&
(byte_id[3] == '\0') &&
(byte_id[4] == 'R') &&
(byte_id[5] == '\0') &&
(byte_id[6] == '\0') &&
(byte_id[7] == '\0') &&
(byte_id[8] == 'Y') &&
(byte_id[9] == '\0') &&
(byte_id[10] == '\0') &&
(byte_id[11] == '\0'))
{
flash->mode_width = 4;
flash->device_width = 4;
iface = IORD_32DIRECT(flash->dev.base_addr, INTERFACE_ADDR*4);
iface += 1;
if (!(iface & 0x4))
{
ret_code = -ENODEV;
}
}
else
{
/*
* Check for 32 bit wide in 16 bit mode
*/
alt_write_flash_command_32bit_device_16bit_mode(flash->dev.base_addr, 0x55, QUERY_MODE);
for(i=0;i<12;i++)
{
byte_id[i] = IORD_8DIRECT(flash->dev.base_addr, (QUERY_ADDR*4)+i);
}
if ((byte_id[0] == 'Q') &&
(byte_id[1] == '\0') &&
(byte_id[2] == 'Q') &&
(byte_id[3] == '\0') &&
(byte_id[4] == 'R') &&
(byte_id[5] == '\0') &&
(byte_id[6] == 'R') &&
(byte_id[7] == '\0') &&
(byte_id[8] == 'Y') &&
(byte_id[9] == '\0') &&
(byte_id[10] == 'Y') &&
(byte_id[11] == '\0'))
{
flash->mode_width = 2;
flash->device_width = 4;
iface = IORD_32DIRECT(flash->dev.base_addr, INTERFACE_ADDR*4);
iface += 1;
if (!(iface & 0x4))
{
ret_code = -ENODEV;
}
}
else
{
/*
* 32 Bit wide flash in byte mode
*/
alt_write_flash_command_32bit_device_8bit_mode(flash->dev.base_addr, 0x55, QUERY_MODE);
if ((byte_id[0] == 'Q') &&
(byte_id[1] == 'Q') &&
(byte_id[2] == 'Q') &&
(byte_id[3] == 'Q') &&
(byte_id[4] == 'R') &&
(byte_id[5] == 'R') &&
(byte_id[6] == 'R') &&
(byte_id[7] == 'R') &&
(byte_id[8] == 'Y') &&
(byte_id[9] == 'Y') &&
(byte_id[10] == 'Y') &&
(byte_id[11] == 'Y'))
{
flash->mode_width = 1;
flash->device_width = 4;
iface = IORD_32DIRECT(flash->dev.base_addr, INTERFACE_ADDR*4);
iface += 1;
if (!(iface & 0x4))
{
ret_code = -ENODEV;
}
}
}
}
}
}
}
return ret_code;
}
/*
* alt_check_primary_table
*
* Check that the primary Vendor table starts with the
* correct pattern
*/
int alt_check_primary_table(alt_flash_cfi_dev* flash)
{
int i;
int ret_code = 0;
alt_u8 primary_query_string[3];
flash->primary_address = alt_read_16bit_query_entry( flash,
PRIMARY_ADDR);
for(i=0;i<3;i++)
{
primary_query_string[i] =
(*flash->read_query)( flash,(flash->primary_address + i));
}
if ((primary_query_string[0] != 'P') ||
(primary_query_string[1] != 'R') ||
(primary_query_string[2] != 'I'))
{
ret_code = -ENODEV;
}
return ret_code;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -