xref: /qemu/tests/qtest/aspeed_smc-test.c (revision dc32f5baf94e901e570e48d6244897c2418fe63c)
17a2334f7SCédric Le Goater /*
27a2334f7SCédric Le Goater  * QTest testcase for the M25P80 Flash (Using the Aspeed SPI
37a2334f7SCédric Le Goater  * Controller)
47a2334f7SCédric Le Goater  *
57a2334f7SCédric Le Goater  * Copyright (C) 2016 IBM Corp.
67a2334f7SCédric Le Goater  *
77a2334f7SCédric Le Goater  * Permission is hereby granted, free of charge, to any person obtaining a copy
87a2334f7SCédric Le Goater  * of this software and associated documentation files (the "Software"), to deal
97a2334f7SCédric Le Goater  * in the Software without restriction, including without limitation the rights
107a2334f7SCédric Le Goater  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
117a2334f7SCédric Le Goater  * copies of the Software, and to permit persons to whom the Software is
127a2334f7SCédric Le Goater  * furnished to do so, subject to the following conditions:
137a2334f7SCédric Le Goater  *
147a2334f7SCédric Le Goater  * The above copyright notice and this permission notice shall be included in
157a2334f7SCédric Le Goater  * all copies or substantial portions of the Software.
167a2334f7SCédric Le Goater  *
177a2334f7SCédric Le Goater  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
187a2334f7SCédric Le Goater  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197a2334f7SCédric Le Goater  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
207a2334f7SCédric Le Goater  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
217a2334f7SCédric Le Goater  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
227a2334f7SCédric Le Goater  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
237a2334f7SCédric Le Goater  * THE SOFTWARE.
247a2334f7SCédric Le Goater  */
257a2334f7SCédric Le Goater 
267a2334f7SCédric Le Goater #include "qemu/osdep.h"
277a2334f7SCédric Le Goater #include "qemu/bswap.h"
28dd210749SThomas Huth #include "libqtest-single.h"
29188052a1SIris Chen #include "qemu/bitops.h"
307a2334f7SCédric Le Goater 
317a2334f7SCédric Le Goater /*
327a2334f7SCédric Le Goater  * ASPEED SPI Controller registers
337a2334f7SCédric Le Goater  */
347a2334f7SCédric Le Goater #define R_CONF              0x00
35*dc32f5baSJamin Lin #define   CONF_ENABLE_W0       16
367a2334f7SCédric Le Goater #define R_CE_CTRL           0x04
377a2334f7SCédric Le Goater #define   CRTL_EXTENDED0       0  /* 32 bit addressing for SPI */
387a2334f7SCédric Le Goater #define R_CTRL0             0x10
39*dc32f5baSJamin Lin #define   CTRL_CE_STOP_ACTIVE  BIT(2)
40371a3dd2SCédric Le Goater #define   CTRL_READMODE        0x0
41371a3dd2SCédric Le Goater #define   CTRL_FREADMODE       0x1
42371a3dd2SCédric Le Goater #define   CTRL_WRITEMODE       0x2
437a2334f7SCédric Le Goater #define   CTRL_USERMODE        0x3
44188052a1SIris Chen #define SR_WEL BIT(1)
457a2334f7SCédric Le Goater 
467a2334f7SCédric Le Goater /*
477a2334f7SCédric Le Goater  * Flash commands
487a2334f7SCédric Le Goater  */
497a2334f7SCédric Le Goater enum {
507a2334f7SCédric Le Goater     JEDEC_READ = 0x9f,
51188052a1SIris Chen     RDSR = 0x5,
52188052a1SIris Chen     WRDI = 0x4,
537a2334f7SCédric Le Goater     BULK_ERASE = 0xc7,
547a2334f7SCédric Le Goater     READ = 0x03,
557a2334f7SCédric Le Goater     PP = 0x02,
561de51272SIris Chen     WRSR = 0x1,
577a2334f7SCédric Le Goater     WREN = 0x6,
581de51272SIris Chen     SRWD = 0x80,
59bd9f5052SCédric Le Goater     RESET_ENABLE = 0x66,
60bd9f5052SCédric Le Goater     RESET_MEMORY = 0x99,
617a2334f7SCédric Le Goater     EN_4BYTE_ADDR = 0xB7,
627a2334f7SCédric Le Goater     ERASE_SECTOR = 0xd8,
637a2334f7SCédric Le Goater };
647a2334f7SCédric Le Goater 
65d2c4f384SJiaxun Yang #define FLASH_PAGE_SIZE           256
667a2334f7SCédric Le Goater 
67975d4bafSJamin Lin typedef struct TestData {
68975d4bafSJamin Lin     QTestState *s;
69975d4bafSJamin Lin     uint64_t spi_base;
70975d4bafSJamin Lin     uint64_t flash_base;
71975d4bafSJamin Lin     uint32_t jedec_id;
72975d4bafSJamin Lin     char *tmp_path;
73*dc32f5baSJamin Lin     uint8_t cs;
74*dc32f5baSJamin Lin     const char *node;
75975d4bafSJamin Lin } TestData;
76975d4bafSJamin Lin 
777a2334f7SCédric Le Goater /*
787a2334f7SCédric Le Goater  * Use an explicit bswap for the values read/wrote to the flash region
797a2334f7SCédric Le Goater  * as they are BE and the Aspeed CPU is LE.
807a2334f7SCédric Le Goater  */
817a2334f7SCédric Le Goater static inline uint32_t make_be32(uint32_t data)
827a2334f7SCédric Le Goater {
837a2334f7SCédric Le Goater     return bswap32(data);
847a2334f7SCédric Le Goater }
857a2334f7SCédric Le Goater 
86975d4bafSJamin Lin static inline void spi_writel(const TestData *data, uint64_t offset,
87975d4bafSJamin Lin                               uint32_t value)
887a2334f7SCédric Le Goater {
89975d4bafSJamin Lin     qtest_writel(data->s, data->spi_base + offset, value);
907a2334f7SCédric Le Goater }
917a2334f7SCédric Le Goater 
92975d4bafSJamin Lin static inline uint32_t spi_readl(const TestData *data, uint64_t offset)
93bd9f5052SCédric Le Goater {
94975d4bafSJamin Lin     return qtest_readl(data->s, data->spi_base + offset);
95975d4bafSJamin Lin }
96975d4bafSJamin Lin 
97975d4bafSJamin Lin static inline void flash_writeb(const TestData *data, uint64_t offset,
98975d4bafSJamin Lin                                 uint8_t value)
99975d4bafSJamin Lin {
100975d4bafSJamin Lin     qtest_writeb(data->s, data->flash_base + offset, value);
101975d4bafSJamin Lin }
102975d4bafSJamin Lin 
103975d4bafSJamin Lin static inline void flash_writel(const TestData *data, uint64_t offset,
104975d4bafSJamin Lin                                 uint32_t value)
105975d4bafSJamin Lin {
106975d4bafSJamin Lin     qtest_writel(data->s, data->flash_base + offset, value);
107975d4bafSJamin Lin }
108975d4bafSJamin Lin 
109975d4bafSJamin Lin static inline uint8_t flash_readb(const TestData *data, uint64_t offset)
110975d4bafSJamin Lin {
111975d4bafSJamin Lin     return qtest_readb(data->s, data->flash_base + offset);
112975d4bafSJamin Lin }
113975d4bafSJamin Lin 
114975d4bafSJamin Lin static inline uint32_t flash_readl(const TestData *data, uint64_t offset)
115975d4bafSJamin Lin {
116975d4bafSJamin Lin     return qtest_readl(data->s, data->flash_base + offset);
117975d4bafSJamin Lin }
118975d4bafSJamin Lin 
119975d4bafSJamin Lin static void spi_conf(const TestData *data, uint32_t value)
120975d4bafSJamin Lin {
121975d4bafSJamin Lin     uint32_t conf = spi_readl(data, R_CONF);
122975d4bafSJamin Lin 
123975d4bafSJamin Lin     conf |= value;
124975d4bafSJamin Lin     spi_writel(data, R_CONF, conf);
125975d4bafSJamin Lin }
126975d4bafSJamin Lin 
127975d4bafSJamin Lin static void spi_conf_remove(const TestData *data, uint32_t value)
128975d4bafSJamin Lin {
129975d4bafSJamin Lin     uint32_t conf = spi_readl(data, R_CONF);
130bd9f5052SCédric Le Goater 
131bd9f5052SCédric Le Goater     conf &= ~value;
132975d4bafSJamin Lin     spi_writel(data, R_CONF, conf);
133bd9f5052SCédric Le Goater }
134bd9f5052SCédric Le Goater 
135975d4bafSJamin Lin static void spi_ce_ctrl(const TestData *data, uint32_t value)
136371a3dd2SCédric Le Goater {
137975d4bafSJamin Lin     uint32_t conf = spi_readl(data, R_CE_CTRL);
138371a3dd2SCédric Le Goater 
139371a3dd2SCédric Le Goater     conf |= value;
140975d4bafSJamin Lin     spi_writel(data, R_CE_CTRL, conf);
141371a3dd2SCédric Le Goater }
142371a3dd2SCédric Le Goater 
143975d4bafSJamin Lin static void spi_ctrl_setmode(const TestData *data, uint8_t mode, uint8_t cmd)
144371a3dd2SCédric Le Goater {
145*dc32f5baSJamin Lin     uint32_t ctrl_reg = R_CTRL0 + data->cs * 4;
146*dc32f5baSJamin Lin     uint32_t ctrl = spi_readl(data, ctrl_reg);
147371a3dd2SCédric Le Goater     ctrl &= ~(CTRL_USERMODE | 0xff << 16);
148371a3dd2SCédric Le Goater     ctrl |= mode | (cmd << 16);
149*dc32f5baSJamin Lin     spi_writel(data, ctrl_reg, ctrl);
150371a3dd2SCédric Le Goater }
151371a3dd2SCédric Le Goater 
152975d4bafSJamin Lin static void spi_ctrl_start_user(const TestData *data)
1537a2334f7SCédric Le Goater {
154*dc32f5baSJamin Lin     uint32_t ctrl_reg = R_CTRL0 + data->cs * 4;
155*dc32f5baSJamin Lin     uint32_t ctrl = spi_readl(data, ctrl_reg);
1567a2334f7SCédric Le Goater 
1577a2334f7SCédric Le Goater     ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
158*dc32f5baSJamin Lin     spi_writel(data, ctrl_reg, ctrl);
1597a2334f7SCédric Le Goater 
1607a2334f7SCédric Le Goater     ctrl &= ~CTRL_CE_STOP_ACTIVE;
161*dc32f5baSJamin Lin     spi_writel(data, ctrl_reg, ctrl);
1627a2334f7SCédric Le Goater }
1637a2334f7SCédric Le Goater 
164975d4bafSJamin Lin static void spi_ctrl_stop_user(const TestData *data)
1657a2334f7SCédric Le Goater {
166*dc32f5baSJamin Lin     uint32_t ctrl_reg = R_CTRL0 + data->cs * 4;
167*dc32f5baSJamin Lin     uint32_t ctrl = spi_readl(data, ctrl_reg);
1687a2334f7SCédric Le Goater 
1697a2334f7SCédric Le Goater     ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
170*dc32f5baSJamin Lin     spi_writel(data, ctrl_reg, ctrl);
1717a2334f7SCédric Le Goater }
1727a2334f7SCédric Le Goater 
173975d4bafSJamin Lin static void flash_reset(const TestData *data)
174bd9f5052SCédric Le Goater {
175*dc32f5baSJamin Lin     spi_conf(data, 1 << (CONF_ENABLE_W0 + data->cs));
176bd9f5052SCédric Le Goater 
177975d4bafSJamin Lin     spi_ctrl_start_user(data);
178975d4bafSJamin Lin     flash_writeb(data, 0, RESET_ENABLE);
179975d4bafSJamin Lin     flash_writeb(data, 0, RESET_MEMORY);
180975d4bafSJamin Lin     flash_writeb(data, 0, WREN);
181975d4bafSJamin Lin     flash_writeb(data, 0, BULK_ERASE);
182975d4bafSJamin Lin     flash_writeb(data, 0, WRDI);
183975d4bafSJamin Lin     spi_ctrl_stop_user(data);
184bd9f5052SCédric Le Goater 
185*dc32f5baSJamin Lin     spi_conf_remove(data, 1 << (CONF_ENABLE_W0 + data->cs));
186bd9f5052SCédric Le Goater }
187bd9f5052SCédric Le Goater 
188975d4bafSJamin Lin static void test_read_jedec(const void *data)
1897a2334f7SCédric Le Goater {
190975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
1917a2334f7SCédric Le Goater     uint32_t jedec = 0x0;
1927a2334f7SCédric Le Goater 
193*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
1947a2334f7SCédric Le Goater 
195975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
196975d4bafSJamin Lin     flash_writeb(test_data, 0, JEDEC_READ);
197975d4bafSJamin Lin     jedec |= flash_readb(test_data, 0) << 16;
198975d4bafSJamin Lin     jedec |= flash_readb(test_data, 0) << 8;
199975d4bafSJamin Lin     jedec |= flash_readb(test_data, 0);
200975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
2017a2334f7SCédric Le Goater 
202975d4bafSJamin Lin     flash_reset(test_data);
203bd9f5052SCédric Le Goater 
204975d4bafSJamin Lin     g_assert_cmphex(jedec, ==, test_data->jedec_id);
2057a2334f7SCédric Le Goater }
2067a2334f7SCédric Le Goater 
207975d4bafSJamin Lin static void read_page(const TestData *data, uint32_t addr, uint32_t *page)
2087a2334f7SCédric Le Goater {
2097a2334f7SCédric Le Goater     int i;
2107a2334f7SCédric Le Goater 
211975d4bafSJamin Lin     spi_ctrl_start_user(data);
2127a2334f7SCédric Le Goater 
213975d4bafSJamin Lin     flash_writeb(data, 0, EN_4BYTE_ADDR);
214975d4bafSJamin Lin     flash_writeb(data, 0, READ);
215975d4bafSJamin Lin     flash_writel(data, 0, make_be32(addr));
2167a2334f7SCédric Le Goater 
2177a2334f7SCédric Le Goater     /* Continuous read are supported */
218d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
219975d4bafSJamin Lin         page[i] = make_be32(flash_readl(data, 0));
2207a2334f7SCédric Le Goater     }
221975d4bafSJamin Lin     spi_ctrl_stop_user(data);
2227a2334f7SCédric Le Goater }
2237a2334f7SCédric Le Goater 
224975d4bafSJamin Lin static void read_page_mem(const TestData *data, uint32_t addr, uint32_t *page)
225371a3dd2SCédric Le Goater {
226371a3dd2SCédric Le Goater     int i;
227371a3dd2SCédric Le Goater 
228371a3dd2SCédric Le Goater     /* move out USER mode to use direct reads from the AHB bus */
229975d4bafSJamin Lin     spi_ctrl_setmode(data, CTRL_READMODE, READ);
230371a3dd2SCédric Le Goater 
231d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
232975d4bafSJamin Lin         page[i] = make_be32(flash_readl(data, addr + i * 4));
233371a3dd2SCédric Le Goater     }
234371a3dd2SCédric Le Goater }
235371a3dd2SCédric Le Goater 
236975d4bafSJamin Lin static void write_page_mem(const TestData *data, uint32_t addr,
237975d4bafSJamin Lin                            uint32_t write_value)
2388abf9ba4SIris Chen {
239975d4bafSJamin Lin     spi_ctrl_setmode(data, CTRL_WRITEMODE, PP);
2408abf9ba4SIris Chen 
2418abf9ba4SIris Chen     for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
242975d4bafSJamin Lin         flash_writel(data, addr + i * 4, write_value);
2438abf9ba4SIris Chen     }
2448abf9ba4SIris Chen }
2458abf9ba4SIris Chen 
246975d4bafSJamin Lin static void assert_page_mem(const TestData *data, uint32_t addr,
247975d4bafSJamin Lin                             uint32_t expected_value)
2488abf9ba4SIris Chen {
2498abf9ba4SIris Chen     uint32_t page[FLASH_PAGE_SIZE / 4];
250975d4bafSJamin Lin     read_page_mem(data, addr, page);
2518abf9ba4SIris Chen     for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
2528abf9ba4SIris Chen         g_assert_cmphex(page[i], ==, expected_value);
2538abf9ba4SIris Chen     }
2548abf9ba4SIris Chen }
2558abf9ba4SIris Chen 
256975d4bafSJamin Lin static void test_erase_sector(const void *data)
2577a2334f7SCédric Le Goater {
258975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
259d2c4f384SJiaxun Yang     uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE;
260d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
2617a2334f7SCédric Le Goater     int i;
2627a2334f7SCédric Le Goater 
263*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
2647a2334f7SCédric Le Goater 
26592a45bdeSIris Chen     /*
26692a45bdeSIris Chen      * Previous page should be full of 0xffs after backend is
26792a45bdeSIris Chen      * initialized
26892a45bdeSIris Chen      */
269975d4bafSJamin Lin     read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page);
27092a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
27192a45bdeSIris Chen         g_assert_cmphex(page[i], ==, 0xffffffff);
27292a45bdeSIris Chen     }
27392a45bdeSIris Chen 
274975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
275975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
276975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
277975d4bafSJamin Lin     flash_writeb(test_data, 0, PP);
278975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(some_page_addr));
27992a45bdeSIris Chen 
28092a45bdeSIris Chen     /* Fill the page with its own addresses */
28192a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
282975d4bafSJamin Lin         flash_writel(test_data, 0, make_be32(some_page_addr + i * 4));
28392a45bdeSIris Chen     }
284975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
28592a45bdeSIris Chen 
28692a45bdeSIris Chen     /* Check the page is correctly written */
287975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
28892a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
28992a45bdeSIris Chen         g_assert_cmphex(page[i], ==, some_page_addr + i * 4);
29092a45bdeSIris Chen     }
29192a45bdeSIris Chen 
292975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
293975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
294975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
295975d4bafSJamin Lin     flash_writeb(test_data, 0, ERASE_SECTOR);
296975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(some_page_addr));
297975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
2987a2334f7SCédric Le Goater 
29992a45bdeSIris Chen     /* Check the page is erased */
300975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
301d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
3027a2334f7SCédric Le Goater         g_assert_cmphex(page[i], ==, 0xffffffff);
3037a2334f7SCédric Le Goater     }
304bd9f5052SCédric Le Goater 
305975d4bafSJamin Lin     flash_reset(test_data);
3067a2334f7SCédric Le Goater }
3077a2334f7SCédric Le Goater 
308975d4bafSJamin Lin static void test_erase_all(const void *data)
3097a2334f7SCédric Le Goater {
310975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
311d2c4f384SJiaxun Yang     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
312d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
3137a2334f7SCédric Le Goater     int i;
3147a2334f7SCédric Le Goater 
315*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
3167a2334f7SCédric Le Goater 
31792a45bdeSIris Chen     /*
31892a45bdeSIris Chen      * Previous page should be full of 0xffs after backend is
31992a45bdeSIris Chen      * initialized
32092a45bdeSIris Chen      */
321975d4bafSJamin Lin     read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page);
32292a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
32392a45bdeSIris Chen         g_assert_cmphex(page[i], ==, 0xffffffff);
32492a45bdeSIris Chen     }
32592a45bdeSIris Chen 
326975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
327975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
328975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
329975d4bafSJamin Lin     flash_writeb(test_data, 0, PP);
330975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(some_page_addr));
33192a45bdeSIris Chen 
33292a45bdeSIris Chen     /* Fill the page with its own addresses */
33392a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
334975d4bafSJamin Lin         flash_writel(test_data, 0, make_be32(some_page_addr + i * 4));
33592a45bdeSIris Chen     }
336975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
33792a45bdeSIris Chen 
33892a45bdeSIris Chen     /* Check the page is correctly written */
339975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
340d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
34192a45bdeSIris Chen         g_assert_cmphex(page[i], ==, some_page_addr + i * 4);
3427a2334f7SCédric Le Goater     }
3437a2334f7SCédric Le Goater 
344975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
345975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
346975d4bafSJamin Lin     flash_writeb(test_data, 0, BULK_ERASE);
347975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
3487a2334f7SCédric Le Goater 
34992a45bdeSIris Chen     /* Check the page is erased */
350975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
351d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
3527a2334f7SCédric Le Goater         g_assert_cmphex(page[i], ==, 0xffffffff);
3537a2334f7SCédric Le Goater     }
354bd9f5052SCédric Le Goater 
355975d4bafSJamin Lin     flash_reset(test_data);
3567a2334f7SCédric Le Goater }
3577a2334f7SCédric Le Goater 
358975d4bafSJamin Lin static void test_write_page(const void *data)
3597a2334f7SCédric Le Goater {
360975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
361d2c4f384SJiaxun Yang     uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */
362d2c4f384SJiaxun Yang     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
363d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
3647a2334f7SCédric Le Goater     int i;
3657a2334f7SCédric Le Goater 
366*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
3677a2334f7SCédric Le Goater 
368975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
369975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
370975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
371975d4bafSJamin Lin     flash_writeb(test_data, 0, PP);
372975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(my_page_addr));
3737a2334f7SCédric Le Goater 
3747a2334f7SCédric Le Goater     /* Fill the page with its own addresses */
375d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
376975d4bafSJamin Lin         flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
3777a2334f7SCédric Le Goater     }
378975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
3797a2334f7SCédric Le Goater 
3807a2334f7SCédric Le Goater     /* Check what was written */
381975d4bafSJamin Lin     read_page(test_data, my_page_addr, page);
382d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
3837a2334f7SCédric Le Goater         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
3847a2334f7SCédric Le Goater     }
3857a2334f7SCédric Le Goater 
3867a2334f7SCédric Le Goater     /* Check some other page. It should be full of 0xff */
387975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
388d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
3897a2334f7SCédric Le Goater         g_assert_cmphex(page[i], ==, 0xffffffff);
3907a2334f7SCédric Le Goater     }
391bd9f5052SCédric Le Goater 
392975d4bafSJamin Lin     flash_reset(test_data);
3937a2334f7SCédric Le Goater }
3947a2334f7SCédric Le Goater 
395975d4bafSJamin Lin static void test_read_page_mem(const void *data)
396371a3dd2SCédric Le Goater {
397975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
398d2c4f384SJiaxun Yang     uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */
399d2c4f384SJiaxun Yang     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
400d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
401371a3dd2SCédric Le Goater     int i;
402371a3dd2SCédric Le Goater 
4031df52a9aSJamin Lin     /*
404*dc32f5baSJamin Lin      * Enable 4BYTE mode for controller.
405371a3dd2SCédric Le Goater      */
406*dc32f5baSJamin Lin     spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs));
407371a3dd2SCédric Le Goater 
408371a3dd2SCédric Le Goater     /* Enable 4BYTE mode for flash. */
409*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
410975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
411975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
412975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
413975d4bafSJamin Lin     flash_writeb(test_data, 0, PP);
414975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(my_page_addr));
41592a45bdeSIris Chen 
41692a45bdeSIris Chen     /* Fill the page with its own addresses */
41792a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
418975d4bafSJamin Lin         flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
41992a45bdeSIris Chen     }
420975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
421*dc32f5baSJamin Lin     spi_conf_remove(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
422371a3dd2SCédric Le Goater 
423371a3dd2SCédric Le Goater     /* Check what was written */
424975d4bafSJamin Lin     read_page_mem(test_data, my_page_addr, page);
425d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
426371a3dd2SCédric Le Goater         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
427371a3dd2SCédric Le Goater     }
428371a3dd2SCédric Le Goater 
429371a3dd2SCédric Le Goater     /* Check some other page. It should be full of 0xff */
430975d4bafSJamin Lin     read_page_mem(test_data, some_page_addr, page);
431d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
432371a3dd2SCédric Le Goater         g_assert_cmphex(page[i], ==, 0xffffffff);
433371a3dd2SCédric Le Goater     }
434371a3dd2SCédric Le Goater 
435975d4bafSJamin Lin     flash_reset(test_data);
436371a3dd2SCédric Le Goater }
437371a3dd2SCédric Le Goater 
438975d4bafSJamin Lin static void test_write_page_mem(const void *data)
439371a3dd2SCédric Le Goater {
440975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
441d2c4f384SJiaxun Yang     uint32_t my_page_addr = 0x15000 * FLASH_PAGE_SIZE;
442d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
443371a3dd2SCédric Le Goater     int i;
444371a3dd2SCédric Le Goater 
4451df52a9aSJamin Lin     /*
446*dc32f5baSJamin Lin      * Enable 4BYTE mode for controller.
447371a3dd2SCédric Le Goater      */
448*dc32f5baSJamin Lin     spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs));
449371a3dd2SCédric Le Goater 
450371a3dd2SCédric Le Goater     /* Enable 4BYTE mode for flash. */
451*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
452975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
453975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
454975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
455975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
456371a3dd2SCédric Le Goater 
457371a3dd2SCédric Le Goater     /* move out USER mode to use direct writes to the AHB bus */
458975d4bafSJamin Lin     spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP);
459371a3dd2SCédric Le Goater 
460d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
461975d4bafSJamin Lin         flash_writel(test_data, my_page_addr + i * 4,
462371a3dd2SCédric Le Goater                make_be32(my_page_addr + i * 4));
463371a3dd2SCédric Le Goater     }
464371a3dd2SCédric Le Goater 
465371a3dd2SCédric Le Goater     /* Check what was written */
466975d4bafSJamin Lin     read_page_mem(test_data, my_page_addr, page);
467d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
468371a3dd2SCédric Le Goater         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
469371a3dd2SCédric Le Goater     }
470371a3dd2SCédric Le Goater 
471975d4bafSJamin Lin     flash_reset(test_data);
472371a3dd2SCédric Le Goater }
473371a3dd2SCédric Le Goater 
474975d4bafSJamin Lin static void test_read_status_reg(const void *data)
475188052a1SIris Chen {
476975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
477188052a1SIris Chen     uint8_t r;
478188052a1SIris Chen 
479*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
480188052a1SIris Chen 
481975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
482975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
483975d4bafSJamin Lin     r = flash_readb(test_data, 0);
484975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
485188052a1SIris Chen 
486188052a1SIris Chen     g_assert_cmphex(r & SR_WEL, ==, 0);
487188052a1SIris Chen     g_assert(!qtest_qom_get_bool
488*dc32f5baSJamin Lin             (test_data->s, test_data->node, "write-enable"));
489188052a1SIris Chen 
490975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
491975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
492975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
493975d4bafSJamin Lin     r = flash_readb(test_data, 0);
494975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
495188052a1SIris Chen 
496188052a1SIris Chen     g_assert_cmphex(r & SR_WEL, ==, SR_WEL);
497188052a1SIris Chen     g_assert(qtest_qom_get_bool
498*dc32f5baSJamin Lin             (test_data->s, test_data->node, "write-enable"));
499188052a1SIris Chen 
500975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
501975d4bafSJamin Lin     flash_writeb(test_data, 0, WRDI);
502975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
503975d4bafSJamin Lin     r = flash_readb(test_data, 0);
504975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
505188052a1SIris Chen 
506188052a1SIris Chen     g_assert_cmphex(r & SR_WEL, ==, 0);
507188052a1SIris Chen     g_assert(!qtest_qom_get_bool
508*dc32f5baSJamin Lin             (test_data->s, test_data->node, "write-enable"));
509188052a1SIris Chen 
510975d4bafSJamin Lin     flash_reset(test_data);
511188052a1SIris Chen }
512188052a1SIris Chen 
513975d4bafSJamin Lin static void test_status_reg_write_protection(const void *data)
5141de51272SIris Chen {
515975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
5161de51272SIris Chen     uint8_t r;
5171de51272SIris Chen 
518*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
5191de51272SIris Chen 
5201de51272SIris Chen     /* default case: WP# is high and SRWD is low -> status register writable */
521975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
522975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
5231de51272SIris Chen     /* test ability to write SRWD */
524975d4bafSJamin Lin     flash_writeb(test_data, 0, WRSR);
525975d4bafSJamin Lin     flash_writeb(test_data, 0, SRWD);
526975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
527975d4bafSJamin Lin     r = flash_readb(test_data, 0);
528975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
5291de51272SIris Chen     g_assert_cmphex(r & SRWD, ==, SRWD);
5301de51272SIris Chen 
5311de51272SIris Chen     /* WP# high and SRWD high -> status register writable */
532975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
533975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
5341de51272SIris Chen     /* test ability to write SRWD */
535975d4bafSJamin Lin     flash_writeb(test_data, 0, WRSR);
536975d4bafSJamin Lin     flash_writeb(test_data, 0, 0);
537975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
538975d4bafSJamin Lin     r = flash_readb(test_data, 0);
539975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
5401de51272SIris Chen     g_assert_cmphex(r & SRWD, ==, 0);
5411de51272SIris Chen 
5421de51272SIris Chen     /* WP# low and SRWD low -> status register writable */
543*dc32f5baSJamin Lin     qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 0);
544975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
545975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
5461de51272SIris Chen     /* test ability to write SRWD */
547975d4bafSJamin Lin     flash_writeb(test_data, 0, WRSR);
548975d4bafSJamin Lin     flash_writeb(test_data, 0, SRWD);
549975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
550975d4bafSJamin Lin     r = flash_readb(test_data, 0);
551975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
5521de51272SIris Chen     g_assert_cmphex(r & SRWD, ==, SRWD);
5531de51272SIris Chen 
5541de51272SIris Chen     /* WP# low and SRWD high -> status register NOT writable */
555975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
556975d4bafSJamin Lin     flash_writeb(test_data, 0 , WREN);
5571de51272SIris Chen     /* test ability to write SRWD */
558975d4bafSJamin Lin     flash_writeb(test_data, 0, WRSR);
559975d4bafSJamin Lin     flash_writeb(test_data, 0, 0);
560975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
561975d4bafSJamin Lin     r = flash_readb(test_data, 0);
562975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
5631de51272SIris Chen     /* write is not successful */
5641de51272SIris Chen     g_assert_cmphex(r & SRWD, ==, SRWD);
5651de51272SIris Chen 
566*dc32f5baSJamin Lin     qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 1);
567975d4bafSJamin Lin     flash_reset(test_data);
5681de51272SIris Chen }
5691de51272SIris Chen 
570975d4bafSJamin Lin static void test_write_block_protect(const void *data)
5718abf9ba4SIris Chen {
572975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
5738abf9ba4SIris Chen     uint32_t sector_size = 65536;
5748abf9ba4SIris Chen     uint32_t n_sectors = 512;
5758abf9ba4SIris Chen 
576*dc32f5baSJamin Lin     spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs));
577*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
5788abf9ba4SIris Chen 
5798abf9ba4SIris Chen     uint32_t bp_bits = 0b0;
5808abf9ba4SIris Chen 
5818abf9ba4SIris Chen     for (int i = 0; i < 16; i++) {
5828abf9ba4SIris Chen         bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2);
5838abf9ba4SIris Chen 
584975d4bafSJamin Lin         spi_ctrl_start_user(test_data);
585975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
586975d4bafSJamin Lin         flash_writeb(test_data, 0, BULK_ERASE);
587975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
588975d4bafSJamin Lin         flash_writeb(test_data, 0, WRSR);
589975d4bafSJamin Lin         flash_writeb(test_data, 0, bp_bits);
590975d4bafSJamin Lin         flash_writeb(test_data, 0, EN_4BYTE_ADDR);
591975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
592975d4bafSJamin Lin         spi_ctrl_stop_user(test_data);
5938abf9ba4SIris Chen 
5948abf9ba4SIris Chen         uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
5958abf9ba4SIris Chen         uint32_t protection_start = n_sectors - num_protected_sectors;
5968abf9ba4SIris Chen         uint32_t protection_end = n_sectors;
5978abf9ba4SIris Chen 
5988abf9ba4SIris Chen         for (int sector = 0; sector < n_sectors; sector++) {
5998abf9ba4SIris Chen             uint32_t addr = sector * sector_size;
6008abf9ba4SIris Chen 
601975d4bafSJamin Lin             assert_page_mem(test_data, addr, 0xffffffff);
602975d4bafSJamin Lin             write_page_mem(test_data, addr, make_be32(0xabcdef12));
6038abf9ba4SIris Chen 
6048abf9ba4SIris Chen             uint32_t expected_value = protection_start <= sector
6058abf9ba4SIris Chen                                       && sector < protection_end
6068abf9ba4SIris Chen                                       ? 0xffffffff : 0xabcdef12;
6078abf9ba4SIris Chen 
608975d4bafSJamin Lin             assert_page_mem(test_data, addr, expected_value);
6098abf9ba4SIris Chen         }
6108abf9ba4SIris Chen     }
6118abf9ba4SIris Chen 
612975d4bafSJamin Lin     flash_reset(test_data);
6138abf9ba4SIris Chen }
6148abf9ba4SIris Chen 
615975d4bafSJamin Lin static void test_write_block_protect_bottom_bit(const void *data)
6168abf9ba4SIris Chen {
617975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
6188abf9ba4SIris Chen     uint32_t sector_size = 65536;
6198abf9ba4SIris Chen     uint32_t n_sectors = 512;
6208abf9ba4SIris Chen 
621*dc32f5baSJamin Lin     spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs));
622*dc32f5baSJamin Lin     spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
6238abf9ba4SIris Chen 
6248abf9ba4SIris Chen     /* top bottom bit is enabled */
6258abf9ba4SIris Chen     uint32_t bp_bits = 0b00100 << 3;
6268abf9ba4SIris Chen 
6278abf9ba4SIris Chen     for (int i = 0; i < 16; i++) {
6288abf9ba4SIris Chen         bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2);
6298abf9ba4SIris Chen 
630975d4bafSJamin Lin         spi_ctrl_start_user(test_data);
631975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
632975d4bafSJamin Lin         flash_writeb(test_data, 0, BULK_ERASE);
633975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
634975d4bafSJamin Lin         flash_writeb(test_data, 0, WRSR);
635975d4bafSJamin Lin         flash_writeb(test_data, 0, bp_bits);
636975d4bafSJamin Lin         flash_writeb(test_data, 0, EN_4BYTE_ADDR);
637975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
638975d4bafSJamin Lin         spi_ctrl_stop_user(test_data);
6398abf9ba4SIris Chen 
6408abf9ba4SIris Chen         uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
6418abf9ba4SIris Chen         uint32_t protection_start = 0;
6428abf9ba4SIris Chen         uint32_t protection_end = num_protected_sectors;
6438abf9ba4SIris Chen 
6448abf9ba4SIris Chen         for (int sector = 0; sector < n_sectors; sector++) {
6458abf9ba4SIris Chen             uint32_t addr = sector * sector_size;
6468abf9ba4SIris Chen 
647975d4bafSJamin Lin             assert_page_mem(test_data, addr, 0xffffffff);
648975d4bafSJamin Lin             write_page_mem(test_data, addr, make_be32(0xabcdef12));
6498abf9ba4SIris Chen 
6508abf9ba4SIris Chen             uint32_t expected_value = protection_start <= sector
6518abf9ba4SIris Chen                                       && sector < protection_end
6528abf9ba4SIris Chen                                       ? 0xffffffff : 0xabcdef12;
6538abf9ba4SIris Chen 
654975d4bafSJamin Lin             assert_page_mem(test_data, addr, expected_value);
6558abf9ba4SIris Chen         }
6568abf9ba4SIris Chen     }
6578abf9ba4SIris Chen 
658975d4bafSJamin Lin     flash_reset(test_data);
6598abf9ba4SIris Chen }
6608abf9ba4SIris Chen 
661975d4bafSJamin Lin static void test_palmetto_bmc(TestData *data)
6627a2334f7SCédric Le Goater {
6637a2334f7SCédric Le Goater     int ret;
6647a2334f7SCédric Le Goater     int fd;
6657a2334f7SCédric Le Goater 
666975d4bafSJamin Lin     fd = g_file_open_tmp("qtest.m25p80.n25q256a.XXXXXX", &data->tmp_path, NULL);
6677a2334f7SCédric Le Goater     g_assert(fd >= 0);
668975d4bafSJamin Lin     ret = ftruncate(fd, 32 * 1024 * 1024);
6697a2334f7SCédric Le Goater     g_assert(ret == 0);
6707a2334f7SCédric Le Goater     close(fd);
6717a2334f7SCédric Le Goater 
672975d4bafSJamin Lin     data->s = qtest_initf("-m 256 -machine palmetto-bmc "
6737a2334f7SCédric Le Goater                           "-drive file=%s,format=raw,if=mtd",
674975d4bafSJamin Lin                           data->tmp_path);
6757a2334f7SCédric Le Goater 
676975d4bafSJamin Lin     /* fmc cs0 with n25q256a flash */
677975d4bafSJamin Lin     data->flash_base = 0x20000000;
678975d4bafSJamin Lin     data->spi_base = 0x1E620000;
679975d4bafSJamin Lin     data->jedec_id = 0x20ba19;
680*dc32f5baSJamin Lin     data->cs = 0;
681*dc32f5baSJamin Lin     data->node = "/machine/soc/fmc/ssi.0/child[0]";
6827a2334f7SCédric Le Goater 
683975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/read_jedec", data, test_read_jedec);
684975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/erase_sector", data, test_erase_sector);
685975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/erase_all",  data, test_erase_all);
686975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/write_page", data, test_write_page);
687975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/read_page_mem",
688975d4bafSJamin Lin                         data, test_read_page_mem);
689975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/write_page_mem",
690975d4bafSJamin Lin                         data, test_write_page_mem);
691975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/read_status_reg",
692975d4bafSJamin Lin                         data, test_read_status_reg);
693975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/status_reg_write_protection",
694975d4bafSJamin Lin                         data, test_status_reg_write_protection);
695975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/write_block_protect",
696975d4bafSJamin Lin                         data, test_write_block_protect);
697975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/write_block_protect_bottom_bit",
698975d4bafSJamin Lin                         data, test_write_block_protect_bottom_bit);
699755e984aSJamin Lin }
700755e984aSJamin Lin 
701755e984aSJamin Lin int main(int argc, char **argv)
702755e984aSJamin Lin {
703975d4bafSJamin Lin     TestData palmetto_data;
704755e984aSJamin Lin     int ret;
705755e984aSJamin Lin 
706755e984aSJamin Lin     g_test_init(&argc, &argv, NULL);
707755e984aSJamin Lin 
708975d4bafSJamin Lin     test_palmetto_bmc(&palmetto_data);
709975d4bafSJamin Lin     ret = g_test_run();
710975d4bafSJamin Lin 
711975d4bafSJamin Lin     qtest_quit(palmetto_data.s);
712975d4bafSJamin Lin     unlink(palmetto_data.tmp_path);
7137a2334f7SCédric Le Goater     return ret;
7147a2334f7SCédric Le Goater }
715