diff mbox series

[v1,09/16] test/qtest/aspeed_smc-test: Introduce a new TestData to test different BMC SOCs

Message ID 20241018053112.1886173-10-jamin_lin@aspeedtech.com (mailing list archive)
State New
Headers show
Series Fix write incorrect data into flash in user mode | expand

Commit Message

Jamin Lin Oct. 18, 2024, 5:31 a.m. UTC
Currently, these test cases are only used for testing fmc_cs0 for AST2400.
To test others BMC SOCs, introduces a new TestData structure.
Users can set the spi base address, flash base address, jedesc id and so on
for different BMC SOCs and flash model testing.

Introduce new helper functions to make the test case more readable.

Set spi base address 0x1E620000, flash_base address 0x20000000
and jedec id 0x20ba19 for fmc_cs0 with n25q256a flash for AST2400
SMC model testing.

To pass the TestData into the test case, replace qtest_add_func with
qtest_add_data_func.

Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
 tests/qtest/aspeed_smc-test.c | 546 +++++++++++++++++++---------------
 1 file changed, 299 insertions(+), 247 deletions(-)
diff mbox series

Patch

diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c
index ec1fa6ec15..4c62009605 100644
--- a/tests/qtest/aspeed_smc-test.c
+++ b/tests/qtest/aspeed_smc-test.c
@@ -43,9 +43,6 @@ 
 #define   CTRL_USERMODE        0x3
 #define SR_WEL BIT(1)
 
-#define ASPEED_FMC_BASE    0x1E620000
-#define ASPEED_FLASH_BASE  0x20000000
-
 /*
  * Flash commands
  */
@@ -65,11 +62,16 @@  enum {
     ERASE_SECTOR = 0xd8,
 };
 
-#define FLASH_JEDEC         0x20ba19  /* n25q256a */
-#define FLASH_SIZE          (32 * 1024 * 1024)
-
 #define FLASH_PAGE_SIZE           256
 
+typedef struct TestData {
+    QTestState *s;
+    uint64_t spi_base;
+    uint64_t flash_base;
+    uint32_t jedec_id;
+    char *tmp_path;
+} TestData;
+
 /*
  * Use an explicit bswap for the values read/wrote to the flash region
  * as they are BE and the Aspeed CPU is LE.
@@ -79,275 +81,315 @@  static inline uint32_t make_be32(uint32_t data)
     return bswap32(data);
 }
 
-static void spi_conf(uint32_t value)
+static inline void spi_writel(const TestData *data, uint64_t offset,
+                              uint32_t value)
+{
+    qtest_writel(data->s, data->spi_base + offset, value);
+}
+
+static inline uint32_t spi_readl(const TestData *data, uint64_t offset)
+{
+    return qtest_readl(data->s, data->spi_base + offset);
+}
+
+static inline void flash_writeb(const TestData *data, uint64_t offset,
+                                uint8_t value)
+{
+    qtest_writeb(data->s, data->flash_base + offset, value);
+}
+
+static inline void flash_writel(const TestData *data, uint64_t offset,
+                                uint32_t value)
+{
+    qtest_writel(data->s, data->flash_base + offset, value);
+}
+
+static inline uint8_t flash_readb(const TestData *data, uint64_t offset)
 {
-    uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF);
+    return qtest_readb(data->s, data->flash_base + offset);
+}
+
+static inline uint32_t flash_readl(const TestData *data, uint64_t offset)
+{
+    return qtest_readl(data->s, data->flash_base + offset);
+}
+
+static void spi_conf(const TestData *data, uint32_t value)
+{
+    uint32_t conf = spi_readl(data, R_CONF);
 
     conf |= value;
-    writel(ASPEED_FMC_BASE + R_CONF, conf);
+    spi_writel(data, R_CONF, conf);
 }
 
-static void spi_conf_remove(uint32_t value)
+static void spi_conf_remove(const TestData *data, uint32_t value)
 {
-    uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF);
+    uint32_t conf = spi_readl(data, R_CONF);
 
     conf &= ~value;
-    writel(ASPEED_FMC_BASE + R_CONF, conf);
+    spi_writel(data, R_CONF, conf);
 }
 
-static void spi_ce_ctrl(uint32_t value)
+static void spi_ce_ctrl(const TestData *data, uint32_t value)
 {
-    uint32_t conf = readl(ASPEED_FMC_BASE + R_CE_CTRL);
+    uint32_t conf = spi_readl(data, R_CE_CTRL);
 
     conf |= value;
-    writel(ASPEED_FMC_BASE + R_CE_CTRL, conf);
+    spi_writel(data, R_CE_CTRL, conf);
 }
 
-static void spi_ctrl_setmode(uint8_t mode, uint8_t cmd)
+static void spi_ctrl_setmode(const TestData *data, uint8_t mode, uint8_t cmd)
 {
-    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
+    uint32_t ctrl = spi_readl(data, R_CTRL0);
     ctrl &= ~(CTRL_USERMODE | 0xff << 16);
     ctrl |= mode | (cmd << 16);
-    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
+    spi_writel(data, R_CTRL0, ctrl);
 }
 
-static void spi_ctrl_start_user(void)
+static void spi_ctrl_start_user(const TestData *data)
 {
-    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
+    uint32_t ctrl = spi_readl(data, R_CTRL0);
 
     ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
-    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
+    spi_writel(data, R_CTRL0, ctrl);
 
     ctrl &= ~CTRL_CE_STOP_ACTIVE;
-    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
+    spi_writel(data, R_CTRL0, ctrl);
 }
 
-static void spi_ctrl_stop_user(void)
+static void spi_ctrl_stop_user(const TestData *data)
 {
-    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
+    uint32_t ctrl = spi_readl(data, R_CTRL0);
 
     ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
-    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
+    spi_writel(data, R_CTRL0, ctrl);
 }
 
-static void flash_reset(void)
+static void flash_reset(const TestData *data)
 {
-    spi_conf(CONF_ENABLE_W0);
+    spi_conf(data, CONF_ENABLE_W0);
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, RESET_ENABLE);
-    writeb(ASPEED_FLASH_BASE, RESET_MEMORY);
-    writeb(ASPEED_FLASH_BASE, WREN);
-    writeb(ASPEED_FLASH_BASE, BULK_ERASE);
-    writeb(ASPEED_FLASH_BASE, WRDI);
-    spi_ctrl_stop_user();
+    spi_ctrl_start_user(data);
+    flash_writeb(data, 0, RESET_ENABLE);
+    flash_writeb(data, 0, RESET_MEMORY);
+    flash_writeb(data, 0, WREN);
+    flash_writeb(data, 0, BULK_ERASE);
+    flash_writeb(data, 0, WRDI);
+    spi_ctrl_stop_user(data);
 
-    spi_conf_remove(CONF_ENABLE_W0);
+    spi_conf_remove(data, CONF_ENABLE_W0);
 }
 
-static void test_read_jedec(void)
+static void test_read_jedec(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint32_t jedec = 0x0;
 
-    spi_conf(CONF_ENABLE_W0);
+    spi_conf(test_data, CONF_ENABLE_W0);
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, JEDEC_READ);
-    jedec |= readb(ASPEED_FLASH_BASE) << 16;
-    jedec |= readb(ASPEED_FLASH_BASE) << 8;
-    jedec |= readb(ASPEED_FLASH_BASE);
-    spi_ctrl_stop_user();
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, JEDEC_READ);
+    jedec |= flash_readb(test_data, 0) << 16;
+    jedec |= flash_readb(test_data, 0) << 8;
+    jedec |= flash_readb(test_data, 0);
+    spi_ctrl_stop_user(test_data);
 
-    flash_reset();
+    flash_reset(test_data);
 
-    g_assert_cmphex(jedec, ==, FLASH_JEDEC);
+    g_assert_cmphex(jedec, ==, test_data->jedec_id);
 }
 
-static void read_page(uint32_t addr, uint32_t *page)
+static void read_page(const TestData *data, uint32_t addr, uint32_t *page)
 {
     int i;
 
-    spi_ctrl_start_user();
+    spi_ctrl_start_user(data);
 
-    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-    writeb(ASPEED_FLASH_BASE, READ);
-    writel(ASPEED_FLASH_BASE, make_be32(addr));
+    flash_writeb(data, 0, EN_4BYTE_ADDR);
+    flash_writeb(data, 0, READ);
+    flash_writel(data, 0, make_be32(addr));
 
     /* Continuous read are supported */
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
-        page[i] = make_be32(readl(ASPEED_FLASH_BASE));
+        page[i] = make_be32(flash_readl(data, 0));
     }
-    spi_ctrl_stop_user();
+    spi_ctrl_stop_user(data);
 }
 
-static void read_page_mem(uint32_t addr, uint32_t *page)
+static void read_page_mem(const TestData *data, uint32_t addr, uint32_t *page)
 {
     int i;
 
     /* move out USER mode to use direct reads from the AHB bus */
-    spi_ctrl_setmode(CTRL_READMODE, READ);
+    spi_ctrl_setmode(data, CTRL_READMODE, READ);
 
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
-        page[i] = make_be32(readl(ASPEED_FLASH_BASE + addr + i * 4));
+        page[i] = make_be32(flash_readl(data, addr + i * 4));
     }
 }
 
-static void write_page_mem(uint32_t addr, uint32_t write_value)
+static void write_page_mem(const TestData *data, uint32_t addr,
+                           uint32_t write_value)
 {
-    spi_ctrl_setmode(CTRL_WRITEMODE, PP);
+    spi_ctrl_setmode(data, CTRL_WRITEMODE, PP);
 
     for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
-        writel(ASPEED_FLASH_BASE + addr + i * 4, write_value);
+        flash_writel(data, addr + i * 4, write_value);
     }
 }
 
-static void assert_page_mem(uint32_t addr, uint32_t expected_value)
+static void assert_page_mem(const TestData *data, uint32_t addr,
+                            uint32_t expected_value)
 {
     uint32_t page[FLASH_PAGE_SIZE / 4];
-    read_page_mem(addr, page);
+    read_page_mem(data, addr, page);
     for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, expected_value);
     }
 }
 
-static void test_erase_sector(void)
+static void test_erase_sector(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE;
     uint32_t page[FLASH_PAGE_SIZE / 4];
     int i;
 
-    spi_conf(CONF_ENABLE_W0);
+    spi_conf(test_data, CONF_ENABLE_W0);
 
     /*
      * Previous page should be full of 0xffs after backend is
      * initialized
      */
-    read_page(some_page_addr - FLASH_PAGE_SIZE, page);
+    read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, 0xffffffff);
     }
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-    writeb(ASPEED_FLASH_BASE, WREN);
-    writeb(ASPEED_FLASH_BASE, PP);
-    writel(ASPEED_FLASH_BASE, make_be32(some_page_addr));
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+    flash_writeb(test_data, 0, WREN);
+    flash_writeb(test_data, 0, PP);
+    flash_writel(test_data, 0, make_be32(some_page_addr));
 
     /* Fill the page with its own addresses */
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
-        writel(ASPEED_FLASH_BASE, make_be32(some_page_addr + i * 4));
+        flash_writel(test_data, 0, make_be32(some_page_addr + i * 4));
     }
-    spi_ctrl_stop_user();
+    spi_ctrl_stop_user(test_data);
 
     /* Check the page is correctly written */
-    read_page(some_page_addr, page);
+    read_page(test_data, some_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, some_page_addr + i * 4);
     }
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, WREN);
-    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-    writeb(ASPEED_FLASH_BASE, ERASE_SECTOR);
-    writel(ASPEED_FLASH_BASE, make_be32(some_page_addr));
-    spi_ctrl_stop_user();
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, WREN);
+    flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+    flash_writeb(test_data, 0, ERASE_SECTOR);
+    flash_writel(test_data, 0, make_be32(some_page_addr));
+    spi_ctrl_stop_user(test_data);
 
     /* Check the page is erased */
-    read_page(some_page_addr, page);
+    read_page(test_data, some_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, 0xffffffff);
     }
 
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static void test_erase_all(void)
+static void test_erase_all(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
     uint32_t page[FLASH_PAGE_SIZE / 4];
     int i;
 
-    spi_conf(CONF_ENABLE_W0);
+    spi_conf(test_data, CONF_ENABLE_W0);
 
     /*
      * Previous page should be full of 0xffs after backend is
      * initialized
      */
-    read_page(some_page_addr - FLASH_PAGE_SIZE, page);
+    read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, 0xffffffff);
     }
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-    writeb(ASPEED_FLASH_BASE, WREN);
-    writeb(ASPEED_FLASH_BASE, PP);
-    writel(ASPEED_FLASH_BASE, make_be32(some_page_addr));
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+    flash_writeb(test_data, 0, WREN);
+    flash_writeb(test_data, 0, PP);
+    flash_writel(test_data, 0, make_be32(some_page_addr));
 
     /* Fill the page with its own addresses */
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
-        writel(ASPEED_FLASH_BASE, make_be32(some_page_addr + i * 4));
+        flash_writel(test_data, 0, make_be32(some_page_addr + i * 4));
     }
-    spi_ctrl_stop_user();
+    spi_ctrl_stop_user(test_data);
 
     /* Check the page is correctly written */
-    read_page(some_page_addr, page);
+    read_page(test_data, some_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, some_page_addr + i * 4);
     }
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, WREN);
-    writeb(ASPEED_FLASH_BASE, BULK_ERASE);
-    spi_ctrl_stop_user();
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, WREN);
+    flash_writeb(test_data, 0, BULK_ERASE);
+    spi_ctrl_stop_user(test_data);
 
     /* Check the page is erased */
-    read_page(some_page_addr, page);
+    read_page(test_data, some_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, 0xffffffff);
     }
 
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static void test_write_page(void)
+static void test_write_page(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */
     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
     uint32_t page[FLASH_PAGE_SIZE / 4];
     int i;
 
-    spi_conf(CONF_ENABLE_W0);
+    spi_conf(test_data, CONF_ENABLE_W0);
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-    writeb(ASPEED_FLASH_BASE, WREN);
-    writeb(ASPEED_FLASH_BASE, PP);
-    writel(ASPEED_FLASH_BASE, make_be32(my_page_addr));
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+    flash_writeb(test_data, 0, WREN);
+    flash_writeb(test_data, 0, PP);
+    flash_writel(test_data, 0, make_be32(my_page_addr));
 
     /* Fill the page with its own addresses */
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
-        writel(ASPEED_FLASH_BASE, make_be32(my_page_addr + i * 4));
+        flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
     }
-    spi_ctrl_stop_user();
+    spi_ctrl_stop_user(test_data);
 
     /* Check what was written */
-    read_page(my_page_addr, page);
+    read_page(test_data, my_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
     }
 
     /* Check some other page. It should be full of 0xff */
-    read_page(some_page_addr, page);
+    read_page(test_data, some_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, 0xffffffff);
     }
 
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static void test_read_page_mem(void)
+static void test_read_page_mem(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */
     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
     uint32_t page[FLASH_PAGE_SIZE / 4];
@@ -357,40 +399,41 @@  static void test_read_page_mem(void)
      * Enable 4BYTE mode for controller. This is should be strapped by
      * HW for CE0 anyhow.
      */
-    spi_ce_ctrl(1 << CRTL_EXTENDED0);
+    spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0);
 
     /* Enable 4BYTE mode for flash. */
-    spi_conf(CONF_ENABLE_W0);
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-    writeb(ASPEED_FLASH_BASE, WREN);
-    writeb(ASPEED_FLASH_BASE, PP);
-    writel(ASPEED_FLASH_BASE, make_be32(my_page_addr));
+    spi_conf(test_data, CONF_ENABLE_W0);
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+    flash_writeb(test_data, 0, WREN);
+    flash_writeb(test_data, 0, PP);
+    flash_writel(test_data, 0, make_be32(my_page_addr));
 
     /* Fill the page with its own addresses */
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
-        writel(ASPEED_FLASH_BASE, make_be32(my_page_addr + i * 4));
+        flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
     }
-    spi_ctrl_stop_user();
-    spi_conf_remove(CONF_ENABLE_W0);
+    spi_ctrl_stop_user(test_data);
+    spi_conf_remove(test_data, CONF_ENABLE_W0);
 
     /* Check what was written */
-    read_page_mem(my_page_addr, page);
+    read_page_mem(test_data, my_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
     }
 
     /* Check some other page. It should be full of 0xff */
-    read_page_mem(some_page_addr, page);
+    read_page_mem(test_data, some_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, 0xffffffff);
     }
 
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static void test_write_page_mem(void)
+static void test_write_page_mem(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint32_t my_page_addr = 0x15000 * FLASH_PAGE_SIZE;
     uint32_t page[FLASH_PAGE_SIZE / 4];
     int i;
@@ -399,150 +442,153 @@  static void test_write_page_mem(void)
      * Enable 4BYTE mode for controller. This is should be strapped by
      * HW for CE0 anyhow.
      */
-    spi_ce_ctrl(1 << CRTL_EXTENDED0);
+    spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0);
 
     /* Enable 4BYTE mode for flash. */
-    spi_conf(CONF_ENABLE_W0);
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-    writeb(ASPEED_FLASH_BASE, WREN);
-    spi_ctrl_stop_user();
+    spi_conf(test_data, CONF_ENABLE_W0);
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+    flash_writeb(test_data, 0, WREN);
+    spi_ctrl_stop_user(test_data);
 
     /* move out USER mode to use direct writes to the AHB bus */
-    spi_ctrl_setmode(CTRL_WRITEMODE, PP);
+    spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP);
 
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
-        writel(ASPEED_FLASH_BASE + my_page_addr + i * 4,
+        flash_writel(test_data, my_page_addr + i * 4,
                make_be32(my_page_addr + i * 4));
     }
 
     /* Check what was written */
-    read_page_mem(my_page_addr, page);
+    read_page_mem(test_data, my_page_addr, page);
     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
     }
 
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static void test_read_status_reg(void)
+static void test_read_status_reg(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint8_t r;
 
-    spi_conf(CONF_ENABLE_W0);
+    spi_conf(test_data, CONF_ENABLE_W0);
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, RDSR);
-    r = readb(ASPEED_FLASH_BASE);
-    spi_ctrl_stop_user();
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, RDSR);
+    r = flash_readb(test_data, 0);
+    spi_ctrl_stop_user(test_data);
 
     g_assert_cmphex(r & SR_WEL, ==, 0);
     g_assert(!qtest_qom_get_bool
-            (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
+            (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, WREN);
-    writeb(ASPEED_FLASH_BASE, RDSR);
-    r = readb(ASPEED_FLASH_BASE);
-    spi_ctrl_stop_user();
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, WREN);
+    flash_writeb(test_data, 0, RDSR);
+    r = flash_readb(test_data, 0);
+    spi_ctrl_stop_user(test_data);
 
     g_assert_cmphex(r & SR_WEL, ==, SR_WEL);
     g_assert(qtest_qom_get_bool
-            (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
+            (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
 
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, WRDI);
-    writeb(ASPEED_FLASH_BASE, RDSR);
-    r = readb(ASPEED_FLASH_BASE);
-    spi_ctrl_stop_user();
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, WRDI);
+    flash_writeb(test_data, 0, RDSR);
+    r = flash_readb(test_data, 0);
+    spi_ctrl_stop_user(test_data);
 
     g_assert_cmphex(r & SR_WEL, ==, 0);
     g_assert(!qtest_qom_get_bool
-            (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
+            (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
 
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static void test_status_reg_write_protection(void)
+static void test_status_reg_write_protection(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint8_t r;
 
-    spi_conf(CONF_ENABLE_W0);
+    spi_conf(test_data, CONF_ENABLE_W0);
 
     /* default case: WP# is high and SRWD is low -> status register writable */
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, WREN);
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, WREN);
     /* test ability to write SRWD */
-    writeb(ASPEED_FLASH_BASE, WRSR);
-    writeb(ASPEED_FLASH_BASE, SRWD);
-    writeb(ASPEED_FLASH_BASE, RDSR);
-    r = readb(ASPEED_FLASH_BASE);
-    spi_ctrl_stop_user();
+    flash_writeb(test_data, 0, WRSR);
+    flash_writeb(test_data, 0, SRWD);
+    flash_writeb(test_data, 0, RDSR);
+    r = flash_readb(test_data, 0);
+    spi_ctrl_stop_user(test_data);
     g_assert_cmphex(r & SRWD, ==, SRWD);
 
     /* WP# high and SRWD high -> status register writable */
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, WREN);
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, WREN);
     /* test ability to write SRWD */
-    writeb(ASPEED_FLASH_BASE, WRSR);
-    writeb(ASPEED_FLASH_BASE, 0);
-    writeb(ASPEED_FLASH_BASE, RDSR);
-    r = readb(ASPEED_FLASH_BASE);
-    spi_ctrl_stop_user();
+    flash_writeb(test_data, 0, WRSR);
+    flash_writeb(test_data, 0, 0);
+    flash_writeb(test_data, 0, RDSR);
+    r = flash_readb(test_data, 0);
+    spi_ctrl_stop_user(test_data);
     g_assert_cmphex(r & SRWD, ==, 0);
 
     /* WP# low and SRWD low -> status register writable */
-    qtest_set_irq_in(global_qtest,
+    qtest_set_irq_in(test_data->s,
                      "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 0);
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, WREN);
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0, WREN);
     /* test ability to write SRWD */
-    writeb(ASPEED_FLASH_BASE, WRSR);
-    writeb(ASPEED_FLASH_BASE, SRWD);
-    writeb(ASPEED_FLASH_BASE, RDSR);
-    r = readb(ASPEED_FLASH_BASE);
-    spi_ctrl_stop_user();
+    flash_writeb(test_data, 0, WRSR);
+    flash_writeb(test_data, 0, SRWD);
+    flash_writeb(test_data, 0, RDSR);
+    r = flash_readb(test_data, 0);
+    spi_ctrl_stop_user(test_data);
     g_assert_cmphex(r & SRWD, ==, SRWD);
 
     /* WP# low and SRWD high -> status register NOT writable */
-    spi_ctrl_start_user();
-    writeb(ASPEED_FLASH_BASE, WREN);
+    spi_ctrl_start_user(test_data);
+    flash_writeb(test_data, 0 , WREN);
     /* test ability to write SRWD */
-    writeb(ASPEED_FLASH_BASE, WRSR);
-    writeb(ASPEED_FLASH_BASE, 0);
-    writeb(ASPEED_FLASH_BASE, RDSR);
-    r = readb(ASPEED_FLASH_BASE);
-    spi_ctrl_stop_user();
+    flash_writeb(test_data, 0, WRSR);
+    flash_writeb(test_data, 0, 0);
+    flash_writeb(test_data, 0, RDSR);
+    r = flash_readb(test_data, 0);
+    spi_ctrl_stop_user(test_data);
     /* write is not successful */
     g_assert_cmphex(r & SRWD, ==, SRWD);
 
-    qtest_set_irq_in(global_qtest,
+    qtest_set_irq_in(test_data->s,
                      "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 1);
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static void test_write_block_protect(void)
+static void test_write_block_protect(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint32_t sector_size = 65536;
     uint32_t n_sectors = 512;
 
-    spi_ce_ctrl(1 << CRTL_EXTENDED0);
-    spi_conf(CONF_ENABLE_W0);
+    spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0);
+    spi_conf(test_data, CONF_ENABLE_W0);
 
     uint32_t bp_bits = 0b0;
 
     for (int i = 0; i < 16; i++) {
         bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2);
 
-        spi_ctrl_start_user();
-        writeb(ASPEED_FLASH_BASE, WREN);
-        writeb(ASPEED_FLASH_BASE, BULK_ERASE);
-        writeb(ASPEED_FLASH_BASE, WREN);
-        writeb(ASPEED_FLASH_BASE, WRSR);
-        writeb(ASPEED_FLASH_BASE, bp_bits);
-        writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-        writeb(ASPEED_FLASH_BASE, WREN);
-        spi_ctrl_stop_user();
+        spi_ctrl_start_user(test_data);
+        flash_writeb(test_data, 0, WREN);
+        flash_writeb(test_data, 0, BULK_ERASE);
+        flash_writeb(test_data, 0, WREN);
+        flash_writeb(test_data, 0, WRSR);
+        flash_writeb(test_data, 0, bp_bits);
+        flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+        flash_writeb(test_data, 0, WREN);
+        spi_ctrl_stop_user(test_data);
 
         uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
         uint32_t protection_start = n_sectors - num_protected_sectors;
@@ -551,27 +597,28 @@  static void test_write_block_protect(void)
         for (int sector = 0; sector < n_sectors; sector++) {
             uint32_t addr = sector * sector_size;
 
-            assert_page_mem(addr, 0xffffffff);
-            write_page_mem(addr, make_be32(0xabcdef12));
+            assert_page_mem(test_data, addr, 0xffffffff);
+            write_page_mem(test_data, addr, make_be32(0xabcdef12));
 
             uint32_t expected_value = protection_start <= sector
                                       && sector < protection_end
                                       ? 0xffffffff : 0xabcdef12;
 
-            assert_page_mem(addr, expected_value);
+            assert_page_mem(test_data, addr, expected_value);
         }
     }
 
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static void test_write_block_protect_bottom_bit(void)
+static void test_write_block_protect_bottom_bit(const void *data)
 {
+    const TestData *test_data = (const TestData *)data;
     uint32_t sector_size = 65536;
     uint32_t n_sectors = 512;
 
-    spi_ce_ctrl(1 << CRTL_EXTENDED0);
-    spi_conf(CONF_ENABLE_W0);
+    spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0);
+    spi_conf(test_data, CONF_ENABLE_W0);
 
     /* top bottom bit is enabled */
     uint32_t bp_bits = 0b00100 << 3;
@@ -579,15 +626,15 @@  static void test_write_block_protect_bottom_bit(void)
     for (int i = 0; i < 16; i++) {
         bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2);
 
-        spi_ctrl_start_user();
-        writeb(ASPEED_FLASH_BASE, WREN);
-        writeb(ASPEED_FLASH_BASE, BULK_ERASE);
-        writeb(ASPEED_FLASH_BASE, WREN);
-        writeb(ASPEED_FLASH_BASE, WRSR);
-        writeb(ASPEED_FLASH_BASE, bp_bits);
-        writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
-        writeb(ASPEED_FLASH_BASE, WREN);
-        spi_ctrl_stop_user();
+        spi_ctrl_start_user(test_data);
+        flash_writeb(test_data, 0, WREN);
+        flash_writeb(test_data, 0, BULK_ERASE);
+        flash_writeb(test_data, 0, WREN);
+        flash_writeb(test_data, 0, WRSR);
+        flash_writeb(test_data, 0, bp_bits);
+        flash_writeb(test_data, 0, EN_4BYTE_ADDR);
+        flash_writeb(test_data, 0, WREN);
+        spi_ctrl_stop_user(test_data);
 
         uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
         uint32_t protection_start = 0;
@@ -596,64 +643,69 @@  static void test_write_block_protect_bottom_bit(void)
         for (int sector = 0; sector < n_sectors; sector++) {
             uint32_t addr = sector * sector_size;
 
-            assert_page_mem(addr, 0xffffffff);
-            write_page_mem(addr, make_be32(0xabcdef12));
+            assert_page_mem(test_data, addr, 0xffffffff);
+            write_page_mem(test_data, addr, make_be32(0xabcdef12));
 
             uint32_t expected_value = protection_start <= sector
                                       && sector < protection_end
                                       ? 0xffffffff : 0xabcdef12;
 
-            assert_page_mem(addr, expected_value);
+            assert_page_mem(test_data, addr, expected_value);
         }
     }
 
-    flash_reset();
+    flash_reset(test_data);
 }
 
-static int test_palmetto_bmc(void)
+static void test_palmetto_bmc(TestData *data)
 {
-    g_autofree char *tmp_path = NULL;
     int ret;
     int fd;
 
-    fd = g_file_open_tmp("qtest.m25p80.XXXXXX", &tmp_path, NULL);
+    fd = g_file_open_tmp("qtest.m25p80.n25q256a.XXXXXX", &data->tmp_path, NULL);
     g_assert(fd >= 0);
-    ret = ftruncate(fd, FLASH_SIZE);
+    ret = ftruncate(fd, 32 * 1024 * 1024);
     g_assert(ret == 0);
     close(fd);
 
-    global_qtest = qtest_initf("-m 256 -machine palmetto-bmc "
-                               "-drive file=%s,format=raw,if=mtd",
-                               tmp_path);
-
-    qtest_add_func("/ast2400/smc/read_jedec", test_read_jedec);
-    qtest_add_func("/ast2400/smc/erase_sector", test_erase_sector);
-    qtest_add_func("/ast2400/smc/erase_all",  test_erase_all);
-    qtest_add_func("/ast2400/smc/write_page", test_write_page);
-    qtest_add_func("/ast2400/smc/read_page_mem", test_read_page_mem);
-    qtest_add_func("/ast2400/smc/write_page_mem", test_write_page_mem);
-    qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg);
-    qtest_add_func("/ast2400/smc/status_reg_write_protection",
-                   test_status_reg_write_protection);
-    qtest_add_func("/ast2400/smc/write_block_protect",
-                   test_write_block_protect);
-    qtest_add_func("/ast2400/smc/write_block_protect_bottom_bit",
-                   test_write_block_protect_bottom_bit);
-
-    flash_reset();
-    ret = g_test_run();
-    qtest_quit(global_qtest);
-    unlink(tmp_path);
-
-    return ret;
+    data->s = qtest_initf("-m 256 -machine palmetto-bmc "
+                          "-drive file=%s,format=raw,if=mtd",
+                          data->tmp_path);
+
+    /* fmc cs0 with n25q256a flash */
+    data->flash_base = 0x20000000;
+    data->spi_base = 0x1E620000;
+    data->jedec_id = 0x20ba19;
+
+    qtest_add_data_func("/ast2400/smc/read_jedec", data, test_read_jedec);
+    qtest_add_data_func("/ast2400/smc/erase_sector", data, test_erase_sector);
+    qtest_add_data_func("/ast2400/smc/erase_all",  data, test_erase_all);
+    qtest_add_data_func("/ast2400/smc/write_page", data, test_write_page);
+    qtest_add_data_func("/ast2400/smc/read_page_mem",
+                        data, test_read_page_mem);
+    qtest_add_data_func("/ast2400/smc/write_page_mem",
+                        data, test_write_page_mem);
+    qtest_add_data_func("/ast2400/smc/read_status_reg",
+                        data, test_read_status_reg);
+    qtest_add_data_func("/ast2400/smc/status_reg_write_protection",
+                        data, test_status_reg_write_protection);
+    qtest_add_data_func("/ast2400/smc/write_block_protect",
+                        data, test_write_block_protect);
+    qtest_add_data_func("/ast2400/smc/write_block_protect_bottom_bit",
+                        data, test_write_block_protect_bottom_bit);
 }
 
 int main(int argc, char **argv)
 {
+    TestData palmetto_data;
     int ret;
 
     g_test_init(&argc, &argv, NULL);
-    ret = test_palmetto_bmc();
 
+    test_palmetto_bmc(&palmetto_data);
+    ret = g_test_run();
+
+    qtest_quit(palmetto_data.s);
+    unlink(palmetto_data.tmp_path);
     return ret;
 }