Cavium Octeon appliance has mtd0 to 5 flash present. I want to log/dump firmware/Simple Executive crash backtrace to one of the solid state storage/ flash in the appliance. For that I try to initialize the flash with simple executive helping function in cvmx-flash.c;
cvmx_flash_initialize();
but on boot up the initialize function in Simple Executive prints
cvmx-flash: No CFI chips found
The cvmx_flash_initialize() in cvmx-flash.c code is shared below;
void cvmx_flash_initialize(void){
int boot_region;
int chip_id = 0;
memset(flash_info, 0, sizeof(flash_info));
/* Loop through each boot bus chip select region */
for (boot_region=0; boot_region<MAX_NUM_FLASH_CHIPS; boot_region++)
{
cvmx_mio_boot_reg_cfgx_t region_cfg;
region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFG0 + boot_region*8);
/* Only try chip select regions that are enabled. This assumes the
bootloader already setup the flash */
if (region_cfg.s.en)
{
/* Convert the hardware address to a pointer. Note that the bootbus,
unlike memory, isn't 1:1 mapped in the simple exec */
void *base_ptr = cvmx_phys_to_ptr((region_cfg.s.base<<16) | 0xffffffff80000000ull);
if (__cvmx_flash_query_cfi(chip_id, base_ptr) == 0)
{
/* Valid CFI flash chip found */
chip_id++;
}
}
}
if (chip_id == 0){
cvmx_dprintf("cvmx-flash: No CFI chips found\n");
}}
The __cvmx_flash_query_cfi(chip_id, base_ptr)
function fails in following QRY verification;
/* Make sure we get the QRY response we should */
if ((__cvmx_flash_read_cmd(chip_id, 0x10) != 'Q') ||
(__cvmx_flash_read_cmd(chip_id, 0x11) != 'R') ||
(__cvmx_flash_read_cmd(chip_id, 0x12) != 'Y'))
{
flash->base_ptr = NULL;
return -1;
}
The __cvmx_flash_query_cfi(chip_id, base_ptr) complete function is shared below;
static int __cvmx_flash_query_cfi(int chip_id, void *base_ptr){
int region;
cvmx_flash_t *flash = flash_info + chip_id;
/* Set the minimum needed for the read and write primitives to work */
flash->base_ptr = base_ptr;
flash->is_16bit = 1; /* FIXME: Currently assumes the chip is 16bits */
/* Put flash in CFI query mode */
__cvmx_flash_write_cmd(chip_id, 0x00, 0xf0); /* Reset the flash chip */
__cvmx_flash_write_cmd(chip_id, 0x55, 0x98);
/* Make sure we get the QRY response we should */
if ((__cvmx_flash_read_cmd(chip_id, 0x10) != 'Q') ||
(__cvmx_flash_read_cmd(chip_id, 0x11) != 'R') ||
(__cvmx_flash_read_cmd(chip_id, 0x12) != 'Y'))
{
flash->base_ptr = NULL;
return -1;
}
/* Read the 16bit vendor ID */
flash->vendor = __cvmx_flash_read_cmd16(chip_id, 0x13);
/* Read the write timeout. The timeout is microseconds(us) is 2^0x1f
typically. The worst case is this value time 2^0x23 */
flash->write_timeout = 1ull << (__cvmx_flash_read_cmd(chip_id, 0x1f) +
__cvmx_flash_read_cmd(chip_id, 0x23));
/* Read the erase timeout. The timeout is milliseconds(ms) is 2^0x21
typically. The worst case is this value time 2^0x25 */
flash->erase_timeout = 1ull << (__cvmx_flash_read_cmd(chip_id, 0x21) +
__cvmx_flash_read_cmd(chip_id, 0x25));
/* Get the flash size. This is 2^0x27 */
flash->size = 1<<__cvmx_flash_read_cmd(chip_id, 0x27);
/* Get the number of different sized block regions from 0x2c */
flash->num_regions = __cvmx_flash_read_cmd(chip_id, 0x2c);
int start_offset = 0;
/* Loop through all regions get information about each */
for (region=0; region<flash->num_regions; region++)
{
cvmx_flash_region_t *rgn_ptr = flash->region + region;
rgn_ptr->start_offset = start_offset;
/* The number of blocks in each region is a 16 bit little endian
endian field. It is encoded at 0x2d + region*4 as (blocks-1) */
uint16_t blocks = __cvmx_flash_read_cmd16(chip_id, 0x2d + region*4);
rgn_ptr->num_blocks = 1u + blocks;
/* The size of each block is a 16 bit little endian endian field. It
is encoded at 0x2d + region*4 + 2 as (size/256). Zero is a special
case representing 128 */
uint16_t size = __cvmx_flash_read_cmd16(chip_id, 0x2d + region*4 + 2);
if (size == 0)
rgn_ptr->block_size = 128;
else
rgn_ptr->block_size = 256u * size;
start_offset += rgn_ptr->block_size * rgn_ptr->num_blocks;
}
/* Take the chip out of CFI query mode */
switch (flash_info[chip_id].vendor)
{
case CFI_CMDSET_AMD_STANDARD:
__cvmx_flash_write_cmd(chip_id, 0x00, 0xf0);
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
__cvmx_flash_write_cmd(chip_id, 0x00, 0xff);
break;
}
/* Convert the timeouts to cycles */
flash->write_timeout *= cvmx_clock_get_rate(CVMX_CLOCK_CORE) / 1000000;
flash->erase_timeout *= cvmx_clock_get_rate(CVMX_CLOCK_CORE) / 1000;
#if DEBUG
/* Print the information about the chip */
cvmx_dprintf("cvmx-flash: Base pointer: %p\n"
" Vendor: 0x%04x\n"
" Size: %d bytes\n"
" Num regions: %d\n"
" Erase timeout: %llu cycles\n"
" Write timeout: %llu cycles\n",
flash->base_ptr,
(unsigned int)flash->vendor,
flash->size,
flash->num_regions,
(unsigned long long)flash->erase_timeout,
(unsigned long long)flash->write_timeout);
for (region=0; region<flash->num_regions; region++)
{
cvmx_dprintf(" Region %d: offset 0x%x, %d blocks, %d bytes/block\n",
region,
flash->region[region].start_offset,
flash->region[region].num_blocks,
flash->region[region].block_size);
}
#endif
return 0;}
However on boot up the linux shows that it has mtd flash present with CFI conformant;
Bootbus flash: Setting flash for 256MB flash at 0x10000000 with 2 bank(s)
phys_mapped_flash: Found 1 x16 devices at 0x0 in 16-bit bank
phys_mapped_flash: Found 1 x16 devices at 0x8000000 in 16-bit bank
Amd/Fujitsu Extended Query Table at 0x0040 phys_mapped_flash: CFI does
not contain boot bank location. Assuming top. number of CFI chips: 2
cfi_cmdset_0002: Disabling erase-suspend-program due to code
brokenness. Creating 6 MTD partitions on "phys_mapped_flash":
0x000000000000-0x000000200000 : "FAILSAFE-BOOTLOADER"
0x000000200000-0x0000003e0000 : "NORMAL-BOOTLOADER"
0x0000003e0000-0x000000400000 : "BOOTLOADER-ENVIRONMENT"
0x000000400000-0x000002200000 : "LINUX-KERNEL"
0x000002200000-0x000007200000 : "LINUX-FS"
0x000007200000-0x000008000000 : "RESERVED-14M"
and the flinfo in u-boot displays that mtd flash is present with CFI conformant;
Bank # 1: CFI conformant flash (16 x 16) Size: 128 MB in 1024 Sectors AMD Standard command set, Manufacturer ID: 0x01, Device ID:
0x227E2228 Erase timeout: 4096 ms, write timeout: 1 ms Buffer
write timeout: 3 ms, buffer size: 64 bytes Sector Start Addresses:
B0000000 RO etc etc (lots of hex numbers displayed)
Bank # 2: CFI conformant flash (16 x 16) Size: 128 MB in 1024 Sectors
AMD Standard command set, Manufacturer ID: 0x01, Device ID: 0x227E2228
Erase timeout: 4096 ms, write timeout: 1 ms Buffer write timeout: 3 ms, buffer size: 64 bytes
Sector Start Addresses: B8000000 etc etc (lots of hex numbers displayed)
The mtd flash of the device is already being used by the u-boot and linux but how can I use the same solid state storage/flash with utility functions of cvmx-flash.c in bare metal simple executive firmware of Cavium Octeon for the said purpose (i.e dumping crash)? How octeon simple executive firmware can read/write the solid state storage/flash that is already successfully accessible by linux & uboot?
User contributions licensed under CC BY-SA 3.0