summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatryk Duda <pdk@semihalf.com>2022-10-04 17:51:26 +0200
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-01-11 19:30:53 +0000
commit23b85496baeaa77ae582ff50659ccfb51469ab99 (patch)
tree23f4cd9c6b25dc17cc921a569ffa918e8bd7aeb3
parent883caf605af66cf149e4580071962388ff922ecb (diff)
downloadchrome-ec-23b85496baeaa77ae582ff50659ccfb51469ab99.tar.gz
shim/src/flash: Add functions for providing flash sectors info
Introduce Zephyr counterparts of functions that provide information about flash sectors, total number of sectors, size of array to describe sector types, etc. These functions use Zephyr flash pages API. To use functions, enable PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT config. BUG=b:239712345 BRANCH=none TEST=zmake build -a --clobber Signed-off-by: Patryk Duda <pdk@semihalf.com> Change-Id: I9ee9a8f36401e4643adfa150c745ba502b72c36a Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4030378 Tested-by: Patryk Duda <patrykd@google.com> Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com> Reviewed-by: Keith Short <keithshort@chromium.org> Commit-Queue: Patryk Duda <patrykd@google.com>
-rw-r--r--common/flash.c9
-rw-r--r--include/flash.h2
-rw-r--r--zephyr/Kconfig.flash8
-rw-r--r--zephyr/shim/include/config_chip.h5
-rw-r--r--zephyr/shim/src/flash.c182
5 files changed, 206 insertions, 0 deletions
diff --git a/common/flash.c b/common/flash.c
index 2649787101..f2469cca32 100644
--- a/common/flash.c
+++ b/common/flash.c
@@ -125,6 +125,9 @@ const uint32_t pstate_data __attribute__((section(".rodata.pstate"))) =
#endif /* !CONFIG_FLASH_PSTATE_BANK */
#endif /* CONFIG_FLASH_PSTATE */
+/* Shim layer provides implementation of these functions based on Zephyr API */
+#if !defined(CONFIG_ZEPHYR) || \
+ !defined(CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT)
#ifdef CONFIG_FLASH_MULTIPLE_REGION
const struct ec_flash_bank *flash_bank_info(int bank)
{
@@ -260,6 +263,9 @@ int crec_flash_total_banks(void)
{
return PHYSICAL_BANKS;
}
+#endif /* !defined(CONFIG_ZEPHYR) || \
+ * !defined(CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT) \
+ */
static int flash_range_ok(int offset, int size_req, int align)
{
@@ -1025,6 +1031,8 @@ static void flash_erase_deferred(void)
DECLARE_DEFERRED(flash_erase_deferred);
#endif
+#if !defined(CONFIG_ZEPHYR) || \
+ !defined(CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT)
void crec_flash_print_region_info(void)
{
#ifdef CONFIG_FLASH_MULTIPLE_REGION
@@ -1046,6 +1054,7 @@ void crec_flash_print_region_info(void)
ccprintf("Protect: %4d B\n", CONFIG_FLASH_BANK_SIZE);
#endif
}
+#endif
/*****************************************************************************/
/* Console commands */
diff --git a/include/flash.h b/include/flash.h
index 9a498bce82..240db02d67 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -12,8 +12,10 @@
#include "ec_commands.h" /* For EC_FLASH_PROTECT_* flags */
#ifdef CONFIG_FLASH_MULTIPLE_REGION
+#ifndef CONFIG_ZEPHYR
extern struct ec_flash_bank const
flash_bank_array[CONFIG_FLASH_REGION_TYPE_COUNT];
+#endif
/*
* Return the bank the offset is in.
diff --git a/zephyr/Kconfig.flash b/zephyr/Kconfig.flash
index e3c161f31b..c8fa606bde 100644
--- a/zephyr/Kconfig.flash
+++ b/zephyr/Kconfig.flash
@@ -119,4 +119,12 @@ config PLATFORM_EC_FLASH_PSTATE
defined, write protect state is maintained solely by the physical
flash driver.
+config PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT
+ bool "Use Zephyr flash page layout API to get sector information"
+ default y if SOC_FAMILY_STM32
+ select FLASH_PAGE_LAYOUT
+ help
+ When enabled, EC will use flash page layout API to get information
+ about flash sectors (index, offset, and size).
+
endif # PLATFORM_EC_FLASH_CROS
diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h
index 19fb335a57..ee79496035 100644
--- a/zephyr/shim/include/config_chip.h
+++ b/zephyr/shim/include/config_chip.h
@@ -615,6 +615,11 @@ extern char mock_jump_data[CONFIG_PLATFORM_EC_PRESERVED_END_OF_RAM_SIZE];
#define CONFIG_CMD_FLASH_WP
#endif
+#undef CONFIG_FLASH_MULTIPLE_REGION
+#ifdef CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT
+#define CONFIG_FLASH_MULTIPLE_REGION
+#endif
+
#endif /* CONFIG_PLATFORM_EC_FLASH_CROS */
#undef CONFIG_MAPPED_STORAGE_BASE
diff --git a/zephyr/shim/src/flash.c b/zephyr/shim/src/flash.c
index 5b7079e450..53c79ec7cb 100644
--- a/zephyr/shim/src/flash.c
+++ b/zephyr/shim/src/flash.c
@@ -167,6 +167,188 @@ uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags)
return ret;
}
+#if IS_ENABLED(CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT)
+int crec_flash_bank_size(int bank)
+{
+ int rv;
+ struct flash_pages_info info;
+
+ rv = flash_get_page_info_by_idx(flash_ctrl_dev, bank, &info);
+
+ if (rv)
+ return -1;
+
+ return info.size;
+}
+
+int crec_flash_bank_erase_size(int bank)
+{
+ return crec_flash_bank_size(bank);
+}
+
+int crec_flash_bank_index(int offset)
+{
+ int rv;
+ struct flash_pages_info info;
+
+ rv = flash_get_page_info_by_offs(flash_ctrl_dev, offset, &info);
+
+ if (rv)
+ return -1;
+
+ return info.index;
+}
+
+int crec_flash_bank_count(int offset, int size)
+{
+ int begin, end;
+
+ if (size < 1)
+ return -1;
+
+ begin = crec_flash_bank_index(offset);
+ end = crec_flash_bank_index(offset + size - 1);
+
+ if (begin < 0 || end < 0)
+ return -1;
+
+ return end - begin + 1;
+}
+
+int crec_flash_bank_start_offset(int bank)
+{
+ int rv;
+ struct flash_pages_info info;
+
+ rv = flash_get_page_info_by_idx(flash_ctrl_dev, bank, &info);
+
+ if (rv)
+ return -1;
+
+ return info.start_offset;
+}
+
+/*
+ * Flash_get_region() is used to get information about region which contains
+ * 'start_idx' sector. Information about region is saved in a ec_flash_bank
+ * structure. Function returns EC_RES_IN_PROGRESS if there are more regions.
+ * EC_RES_SUCCESS is returned if the region is the last one. EC_RES_ERROR is
+ * returned if there was an error.
+ *
+ * Please note that 'start_idx' should point to first sector of the region
+ * otherwise number of sectors in region will be wrong.
+ */
+static int flash_get_region(size_t start_idx, struct ec_flash_bank *region)
+{
+ struct flash_pages_info first, next;
+ size_t total_pages;
+ int rv;
+
+ total_pages = flash_get_page_count(flash_ctrl_dev);
+ rv = flash_get_page_info_by_idx(flash_ctrl_dev, start_idx, &first);
+ if (rv)
+ return EC_RES_ERROR;
+
+ /* Region has sectors with the same size, save these information now. */
+ region->count = 1;
+ region->size_exp = __fls(first.size);
+ region->write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE);
+ region->erase_size_exp = __fls(first.size);
+ region->protect_size_exp = __fls(first.size);
+
+ for (size_t i = start_idx + 1; i < total_pages; i++) {
+ rv = flash_get_page_info_by_idx(flash_ctrl_dev, i, &next);
+ if (rv)
+ return EC_RES_ERROR;
+
+ /*
+ * If size of the next page is different than size of the first
+ * page of this region then we know how many pages the region
+ * has and this is not the last region.
+ */
+ if (next.size != first.size)
+ return EC_RES_IN_PROGRESS;
+
+ region->count++;
+ }
+
+ return EC_RES_SUCCESS;
+}
+
+/*
+ * Both crec_flash_print_region_into() and crec_flash_response_fill_banks()
+ * could be easily implemented if we had an access to flash layout structure
+ * that aggregates pages with the same size in one entry ('compressed' form).
+ *
+ * Zephyr internally keeps flash layout in structure of this type, but using the
+ * flash API it's only possible to get information about single pages. Extending
+ * flash API encounters resistance from developers.
+ */
+void crec_flash_print_region_info(void)
+{
+ const struct flash_parameters *params;
+ struct ec_flash_bank region;
+ size_t sector_idx = 0;
+ int res;
+
+ params = flash_get_parameters(flash_ctrl_dev);
+ if (!params)
+ return;
+
+ cprintf(CC_COMMAND, "Regions:\n");
+ do {
+ res = flash_get_region(sector_idx, &region);
+ if (res != EC_RES_SUCCESS && res != EC_RES_IN_PROGRESS)
+ break;
+
+ cprintf(CC_COMMAND, " %d region%s:\n", region.count,
+ (region.count == 1 ? "" : "s"));
+ cprintf(CC_COMMAND, " Erase: %4d B (to %d-bits)\n",
+ 1 << region.erase_size_exp,
+ params->erase_value ? 1 : 0);
+ cprintf(CC_COMMAND, " Size/Protect: %4d B\n",
+ 1 << region.size_exp);
+
+ sector_idx += region.count;
+ } while (res == EC_RES_IN_PROGRESS);
+}
+
+int crec_flash_response_fill_banks(struct ec_response_flash_info_2 *r,
+ int num_banks)
+{
+ struct ec_flash_bank region;
+ size_t sector_idx = 0;
+ int banks_idx = 0;
+ int res;
+
+ if (num_banks < 1)
+ return EC_RES_INVALID_PARAM;
+
+ do {
+ res = flash_get_region(sector_idx, &region);
+ if (res != EC_RES_SUCCESS && res != EC_RES_IN_PROGRESS)
+ break;
+
+ if (banks_idx < num_banks)
+ memcpy(&r->banks[banks_idx], &region,
+ sizeof(struct ec_flash_bank));
+
+ sector_idx += region.count;
+ banks_idx++;
+ } while (res == EC_RES_IN_PROGRESS);
+
+ r->num_banks_desc = MIN(banks_idx, num_banks);
+ r->num_banks_total = banks_idx;
+
+ return res;
+}
+
+int crec_flash_total_banks(void)
+{
+ return flash_get_page_count(flash_ctrl_dev);
+}
+#endif /* CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT */
+
#if IS_ENABLED(CONFIG_SHELL)
static int command_flashchip(const struct shell *shell, size_t argc,
char **argv)