[sw] - Update flash sanity test for info partitions as well

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/sw/device/boot_rom/bootstrap.c b/sw/device/boot_rom/bootstrap.c
index 2566669..9d8ea78 100644
--- a/sw/device/boot_rom/bootstrap.c
+++ b/sw/device/boot_rom/bootstrap.c
@@ -112,7 +112,7 @@
           LOG_INFO("Flash erase successful");
         }
 
-        if (flash_write(frame.header.flash_offset, frame.data,
+        if (flash_write(frame.header.flash_offset, kDataPartition, frame.data,
                         SPIFLASH_FRAME_DATA_WORDS) != 0) {
           return E_BS_WRITE;
         }
diff --git a/sw/device/lib/flash_ctrl.c b/sw/device/lib/flash_ctrl.c
index 39fbb08..a1419e1 100644
--- a/sw/device/lib/flash_ctrl.c
+++ b/sw/device/lib/flash_ctrl.c
@@ -5,7 +5,6 @@
 
 #include "flash_ctrl_regs.h"  // Generated.
 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
-
 #include "sw/device/lib/common.h"
 
 #define FLASH_CTRL0_BASE_ADDR TOP_EARLGREY_FLASH_CTRL_BASE_ADDR
@@ -82,22 +81,24 @@
   return get_clr_err();
 }
 
-int flash_page_erase(uint32_t addr) {
+int flash_page_erase(uint32_t addr, part_type_t part) {
   REG32(FLASH_CTRL_ADDR(0)) = addr;
   REG32(FLASH_CTRL_CONTROL(0)) = FLASH_ERASE << FLASH_CTRL_CONTROL_OP_OFFSET |
                                  FLASH_PAGE_ERASE
                                      << FLASH_CTRL_CONTROL_ERASE_SEL |
+                                 part << FLASH_CTRL_CONTROL_PARTITION_SEL |
                                  0x1 << FLASH_CTRL_CONTROL_START;
   wait_done_and_ack();
   return get_clr_err();
 }
 
-static int flash_write_internal(uint32_t addr, const uint32_t *data,
-                                uint32_t size) {
+static int flash_write_internal(uint32_t addr, part_type_t part,
+                                const uint32_t *data, uint32_t size) {
   // TODO: Do we need to select bank as part of the write?
   // TODO: Update with address alignment requirements.
   REG32(FLASH_CTRL_ADDR(0)) = addr;
   REG32(FLASH_CTRL_CONTROL(0)) = (FLASH_PROG << FLASH_CTRL_CONTROL_OP_OFFSET |
+                                  part << FLASH_CTRL_CONTROL_PARTITION_SEL |
                                   (size - 1) << FLASH_CTRL_CONTROL_NUM_OFFSET |
                                   0x1 << FLASH_CTRL_CONTROL_START);
   for (int i = 0; i < size; ++i) {
@@ -107,14 +108,16 @@
   return get_clr_err();
 }
 
-int flash_write(uint32_t addr, const uint32_t *data, uint32_t size) {
+int flash_write(uint32_t addr, part_type_t part, const uint32_t *data,
+                uint32_t size) {
   // TODO: Breakdown into FIFO chunks if needed.
-  return flash_write_internal(addr, data, size);
+  return flash_write_internal(addr, part, data, size);
 }
 
-int flash_read(uint32_t addr, uint32_t size, uint32_t *data) {
+int flash_read(uint32_t addr, part_type_t part, uint32_t size, uint32_t *data) {
   REG32(FLASH_CTRL_ADDR(0)) = addr;
   REG32(FLASH_CTRL_CONTROL(0)) = FLASH_READ << FLASH_CTRL_CONTROL_OP_OFFSET |
+                                 part << FLASH_CTRL_CONTROL_PARTITION_SEL |
                                  (size - 1) << FLASH_CTRL_CONTROL_NUM_OFFSET |
                                  0x1 << FLASH_CTRL_CONTROL_START;
   for (uint32_t i = 0; i < size;) {
@@ -145,6 +148,7 @@
   REG32(FLASH_CTRL_MP_REGION_CFG0(0) + region_cfg->num * 4) =
       region_cfg->base << FLASH_CTRL_MP_REGION_CFG0_BASE0_OFFSET |
       region_cfg->size << FLASH_CTRL_MP_REGION_CFG0_SIZE0_OFFSET |
+      region_cfg->part << FLASH_CTRL_MP_REGION_CFG0_PARTITION0 |
       region_cfg->rd_en << FLASH_CTRL_MP_REGION_CFG0_RD_EN0 |
       region_cfg->prog_en << FLASH_CTRL_MP_REGION_CFG0_PROG_EN0 |
       region_cfg->erase_en << FLASH_CTRL_MP_REGION_CFG0_ERASE_EN0 |
diff --git a/sw/device/lib/flash_ctrl.h b/sw/device/lib/flash_ctrl.h
index f15d197..cad7cb9 100644
--- a/sw/device/lib/flash_ctrl.h
+++ b/sw/device/lib/flash_ctrl.h
@@ -22,6 +22,14 @@
 typedef enum bank_index { FLASH_BANK_0 = 0, FLASH_BANK_1 = 1 } bank_index_t;
 
 /**
+ * Flash partitions
+ */
+typedef enum partition_type {
+  kDataPartition = 0,
+  kInfoPartition = 1
+} part_type_t;
+
+/**
  * Memory protection configuration options.
  */
 typedef struct mp_region {
@@ -31,6 +39,8 @@
   uint32_t base;
   /** Region config size. */
   uint32_t size;
+  /** Region partition size. */
+  part_type_t part;
   /** Read enable flag. */
   uint32_t rd_en;
   /** Program enable flag. */
@@ -56,27 +66,30 @@
  * @return Non zero on failure.
  */
 int flash_bank_erase(bank_index_t idx);
-int flash_page_erase(uint32_t addr);
+int flash_page_erase(uint32_t addr, part_type_t part);
 
 /**
  * Write `data` at `addr` offset with `size` in 4B words
  *
  * @param addr Flash address 32bit aligned.
+ * @param part Flash parittion to access.
  * @param data Data to write.
  * @param size Number of 4B words to write from `data` buffer.
  * @return Non zero on failure.
  */
-int flash_write(uint32_t addr, const uint32_t *data, uint32_t size);
+int flash_write(uint32_t addr, part_type_t part, const uint32_t *data,
+                uint32_t size);
 
 /**
  * Read `size` 4B words and write result to `data`.
  *
  * @param addr Read start address.
+ * @param part Flash parittion to access.
  * @param size Number of 4B words to read.
  * @param data Output buffer.
  * @return Non zero on failure.
  */
-int flash_read(uint32_t addr, uint32_t size, uint32_t *data);
+int flash_read(uint32_t addr, part_type_t part, uint32_t size, uint32_t *data);
 
 /**
  * Configure bank erase enable
diff --git a/sw/device/tests/flash_ctrl_test.c b/sw/device/tests/flash_ctrl_test.c
index 6a40cc1..5f54baf 100644
--- a/sw/device/tests/flash_ctrl_test.c
+++ b/sw/device/tests/flash_ctrl_test.c
@@ -24,19 +24,40 @@
 #define CHECK_EQZ(x) CHECK((x) == 0)
 #define CHECK_NEZ(x) CHECK((x) != 0)
 
+/*
+ * Basic test of page erase / program / read functions
+ * Tests pages from both the data and info partitions
+ */
 static void test_basic_io(void) {
+  // setup default access for data partition
   flash_default_region_access(/*rd_en=*/true, /*prog_en=*/true,
                               /*erase_en=*/true);
 
+  // info partition has no default access, specifically setup a region
+  mp_region_t info_region = {
+      .num = 0x0,
+      .base = FLASH_PAGES_PER_BANK,
+      .size = 0x1,
+      .part = kInfoPartition,
+      .rd_en = true,
+      .prog_en = true,
+      .erase_en = true,
+  };
+  flash_cfg_region(&info_region);
+
   uintptr_t flash_bank_1_addr = FLASH_MEM_BASE_ADDR + FLASH_BANK_SZ;
   mmio_region_t flash_bank_1 = mmio_region_from_addr(flash_bank_1_addr);
 
-  // Test erasing flash; this should turn the whole bank to all ones.
-  CHECK_EQZ(flash_page_erase(flash_bank_1_addr));
+  // Test erasing flash data partition; this should turn the whole bank to all
+  // ones.
+  CHECK_EQZ(flash_page_erase(flash_bank_1_addr, kDataPartition));
   for (int i = 0; i < FLASH_WORDS_PER_PAGE; ++i) {
     CHECK_EQZ(~mmio_region_read32(flash_bank_1, i * sizeof(uint32_t)));
   }
 
+  // Erasing flash info partition; this should turn the whole bank to all ones.
+  CHECK_EQZ(flash_page_erase(flash_bank_1_addr, kInfoPartition));
+
   // Prepare an entire page of non-trivial data to program
   // into flash.
   uint32_t input_page[FLASH_WORDS_PER_PAGE];
@@ -48,20 +69,34 @@
 
   // Attempt to live-program an entire page, where the overall
   // payload is much larger than the internal flash FIFO.
-  CHECK_EQZ(flash_page_erase(flash_bank_1_addr));
+  CHECK_EQZ(flash_page_erase(flash_bank_1_addr, kDataPartition));
+  CHECK_EQZ(flash_write(flash_bank_1_addr, kDataPartition, input_page,
+                        FLASH_WORDS_PER_PAGE));
+  CHECK_EQZ(flash_read(flash_bank_1_addr, kDataPartition, FLASH_WORDS_PER_PAGE,
+                       output_page));
+  CHECK_ARRAYS_EQ(output_page, input_page, FLASH_WORDS_PER_PAGE);
 
-  CHECK_EQZ(flash_write(flash_bank_1_addr, input_page, FLASH_WORDS_PER_PAGE));
-  CHECK_EQZ(flash_read(flash_bank_1_addr, FLASH_WORDS_PER_PAGE, output_page));
-
+  // Similar check for info page
+  CHECK_EQZ(flash_page_erase(flash_bank_1_addr, kInfoPartition));
+  CHECK_EQZ(flash_write(flash_bank_1_addr, kInfoPartition, input_page,
+                        FLASH_WORDS_PER_PAGE));
+  CHECK_EQZ(flash_read(flash_bank_1_addr, kInfoPartition, FLASH_WORDS_PER_PAGE,
+                       output_page));
   CHECK_ARRAYS_EQ(output_page, input_page, FLASH_WORDS_PER_PAGE);
 
   uintptr_t flash_bank_0_last_page_addr = flash_bank_1_addr - FLASH_PAGE_SZ;
-  CHECK_EQZ(flash_page_erase(flash_bank_0_last_page_addr));
+  mmio_region_t flash_bank_0_last_page =
+      mmio_region_from_addr(flash_bank_0_last_page_addr);
+  CHECK_EQZ(flash_page_erase(flash_bank_0_last_page_addr, kDataPartition));
+  for (int i = 0; i < FLASH_WORDS_PER_PAGE; ++i) {
+    CHECK_EQZ(
+        ~mmio_region_read32(flash_bank_0_last_page, i * sizeof(uint32_t)));
+  }
 
-  CHECK_EQZ(flash_write(flash_bank_0_last_page_addr, input_page,
+  CHECK_EQZ(flash_write(flash_bank_0_last_page_addr, kDataPartition, input_page,
                         FLASH_WORDS_PER_PAGE));
-  CHECK_EQZ(flash_read(flash_bank_0_last_page_addr, FLASH_WORDS_PER_PAGE,
-                       output_page));
+  CHECK_EQZ(flash_read(flash_bank_0_last_page_addr, kDataPartition,
+                       FLASH_WORDS_PER_PAGE, output_page));
 
   CHECK_ARRAYS_EQ(output_page, input_page, FLASH_WORDS_PER_PAGE);
 }
@@ -75,6 +110,7 @@
       .num = 0x0,
       .base = FLASH_PAGES_PER_BANK,
       .size = 0x1,
+      .part = kDataPartition,
       .rd_en = true,
       .prog_en = true,
       .erase_en = true,
@@ -89,8 +125,8 @@
   uintptr_t bad_region_start = ok_region_end;
 
   // Erase good and bad regions.
-  CHECK_EQZ(flash_page_erase(ok_region_start));
-  CHECK_EQZ(flash_page_erase(bad_region_start));
+  CHECK_EQZ(flash_page_erase(ok_region_start, kDataPartition));
+  CHECK_EQZ(flash_page_erase(bad_region_start, kDataPartition));
 
   // Turn off flash access by default.
   flash_default_region_access(/*rd_en=*/false, /*prog_en=*/false,
@@ -108,7 +144,8 @@
   }
 
   // Perform a partial write.
-  CHECK_NEZ(flash_write(region_boundary_start, words, ARRAYSIZE(words)));
+  CHECK_NEZ(flash_write(region_boundary_start, kDataPartition, words,
+                        ARRAYSIZE(words)));
   // Words in the good region should still match, while words in the bad
   // region should be all-ones, since we erased
   for (int i = 0; i < ARRAYSIZE(words); ++i) {
@@ -121,10 +158,10 @@
   }
 
   // Attempt to erase bad page, which should fail.
-  CHECK_NEZ(flash_page_erase(bad_region_start));
+  CHECK_NEZ(flash_page_erase(bad_region_start, kDataPartition));
 
   // Attempt to erase the good page, which should succeed.
-  CHECK_EQZ(flash_page_erase(ok_region_start));
+  CHECK_EQZ(flash_page_erase(ok_region_start, kDataPartition));
   for (int i = 0; i < FLASH_WORDS_PER_PAGE; i++) {
     CHECK_EQZ(~mmio_region_read32(ok_region, i * sizeof(uint32_t)));
   }