From fabfef6c24530c39c2190a0482f37deebf0b3421 Mon Sep 17 00:00:00 2001 From: Aaron Nyholm Date: Mon, 3 Nov 2025 15:18:01 +1100 Subject: [PATCH] bsps/shared/dev/nor: Added support for multiple CFI regions CFI parser now returns largest block size when multiple regions are present allowing for block erase to be used with returned size. --- bsps/shared/dev/nor/config-parser.c | 42 ++++++++++++++++++----------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/bsps/shared/dev/nor/config-parser.c b/bsps/shared/dev/nor/config-parser.c index 09860275ff..a77c95a714 100644 --- a/bsps/shared/dev/nor/config-parser.c +++ b/bsps/shared/dev/nor/config-parser.c @@ -120,7 +120,6 @@ rtems_status_code CFI_parse_from_buffer( /* get device geometry */ uint8_t bufbyte; - /* Device size for at least s25fl512s is off by 1, calculate with sectors */ if (read_config_byte(cfi_raw, cfi_raw_len, datalen, 0x27, &bufbyte)) { return RTEMS_INVALID_ADDRESS; } @@ -135,24 +134,35 @@ rtems_status_code CFI_parse_from_buffer( if (read_config_byte(cfi_raw, cfi_raw_len, datalen, 0x2c, &bufbyte)) { return RTEMS_INVALID_ADDRESS; } - /* this parser only supports one erase block region */ - if (bufbyte != 1) { - return RTEMS_TOO_MANY; + + /* Get largest block */ + uint8_t num_regions = bufbyte; + data->SectorSize = 0; + for (int region = 0; region < num_regions; ++region) { + uint16_t num_sectors_sub; + if (read_config_short(cfi_raw, cfi_raw_len, datalen, 0x2d + (region * 4), + &num_sectors_sub)) { + return RTEMS_INVALID_ADDRESS; + } + + uint16_t sector_base; + if (read_config_short(cfi_raw, cfi_raw_len, datalen, 0x2f + (region * 4), + §or_base)) { + return RTEMS_INVALID_ADDRESS; + } + + if (data->SectorSize < (sector_base * 256UL)) { + data->NumSectors = num_sectors_sub + 1; + data->SectorSize = sector_base * 256UL; + } } - uint16_t num_sectors_sub; - if (read_config_short(cfi_raw, cfi_raw_len, datalen, 0x2d, &num_sectors_sub)) { - return RTEMS_INVALID_ADDRESS; + if (num_regions == 1) { + /* Device size for at least s25fl512s is off by 1, calculate with sectors */ + data->DeviceSize = data->NumSectors * data->SectorSize; + } else { + data->NumSectors = data->DeviceSize / data->SectorSize; } - data->NumSectors = num_sectors_sub + 1; - - uint16_t sector_base; - if (read_config_short(cfi_raw, cfi_raw_len, datalen, 0x2f, §or_base)) { - return RTEMS_INVALID_ADDRESS; - } - data->SectorSize = sector_base * 256UL; - - data->DeviceSize = data->NumSectors * data->SectorSize; return RTEMS_SUCCESSFUL; }