xref: /qemu/tests/qtest/aspeed_smc-test.c (revision 975d4baf686c1bf16daf0277c25cd6f494df0c68)
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
357a2334f7SCédric Le Goater #define   CONF_ENABLE_W0       (1 << 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
397a2334f7SCédric Le Goater #define   CTRL_CE_STOP_ACTIVE  (1 << 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 
67*975d4bafSJamin Lin typedef struct TestData {
68*975d4bafSJamin Lin     QTestState *s;
69*975d4bafSJamin Lin     uint64_t spi_base;
70*975d4bafSJamin Lin     uint64_t flash_base;
71*975d4bafSJamin Lin     uint32_t jedec_id;
72*975d4bafSJamin Lin     char *tmp_path;
73*975d4bafSJamin Lin } TestData;
74*975d4bafSJamin Lin 
757a2334f7SCédric Le Goater /*
767a2334f7SCédric Le Goater  * Use an explicit bswap for the values read/wrote to the flash region
777a2334f7SCédric Le Goater  * as they are BE and the Aspeed CPU is LE.
787a2334f7SCédric Le Goater  */
797a2334f7SCédric Le Goater static inline uint32_t make_be32(uint32_t data)
807a2334f7SCédric Le Goater {
817a2334f7SCédric Le Goater     return bswap32(data);
827a2334f7SCédric Le Goater }
837a2334f7SCédric Le Goater 
84*975d4bafSJamin Lin static inline void spi_writel(const TestData *data, uint64_t offset,
85*975d4bafSJamin Lin                               uint32_t value)
867a2334f7SCédric Le Goater {
87*975d4bafSJamin Lin     qtest_writel(data->s, data->spi_base + offset, value);
887a2334f7SCédric Le Goater }
897a2334f7SCédric Le Goater 
90*975d4bafSJamin Lin static inline uint32_t spi_readl(const TestData *data, uint64_t offset)
91bd9f5052SCédric Le Goater {
92*975d4bafSJamin Lin     return qtest_readl(data->s, data->spi_base + offset);
93*975d4bafSJamin Lin }
94*975d4bafSJamin Lin 
95*975d4bafSJamin Lin static inline void flash_writeb(const TestData *data, uint64_t offset,
96*975d4bafSJamin Lin                                 uint8_t value)
97*975d4bafSJamin Lin {
98*975d4bafSJamin Lin     qtest_writeb(data->s, data->flash_base + offset, value);
99*975d4bafSJamin Lin }
100*975d4bafSJamin Lin 
101*975d4bafSJamin Lin static inline void flash_writel(const TestData *data, uint64_t offset,
102*975d4bafSJamin Lin                                 uint32_t value)
103*975d4bafSJamin Lin {
104*975d4bafSJamin Lin     qtest_writel(data->s, data->flash_base + offset, value);
105*975d4bafSJamin Lin }
106*975d4bafSJamin Lin 
107*975d4bafSJamin Lin static inline uint8_t flash_readb(const TestData *data, uint64_t offset)
108*975d4bafSJamin Lin {
109*975d4bafSJamin Lin     return qtest_readb(data->s, data->flash_base + offset);
110*975d4bafSJamin Lin }
111*975d4bafSJamin Lin 
112*975d4bafSJamin Lin static inline uint32_t flash_readl(const TestData *data, uint64_t offset)
113*975d4bafSJamin Lin {
114*975d4bafSJamin Lin     return qtest_readl(data->s, data->flash_base + offset);
115*975d4bafSJamin Lin }
116*975d4bafSJamin Lin 
117*975d4bafSJamin Lin static void spi_conf(const TestData *data, uint32_t value)
118*975d4bafSJamin Lin {
119*975d4bafSJamin Lin     uint32_t conf = spi_readl(data, R_CONF);
120*975d4bafSJamin Lin 
121*975d4bafSJamin Lin     conf |= value;
122*975d4bafSJamin Lin     spi_writel(data, R_CONF, conf);
123*975d4bafSJamin Lin }
124*975d4bafSJamin Lin 
125*975d4bafSJamin Lin static void spi_conf_remove(const TestData *data, uint32_t value)
126*975d4bafSJamin Lin {
127*975d4bafSJamin Lin     uint32_t conf = spi_readl(data, R_CONF);
128bd9f5052SCédric Le Goater 
129bd9f5052SCédric Le Goater     conf &= ~value;
130*975d4bafSJamin Lin     spi_writel(data, R_CONF, conf);
131bd9f5052SCédric Le Goater }
132bd9f5052SCédric Le Goater 
133*975d4bafSJamin Lin static void spi_ce_ctrl(const TestData *data, uint32_t value)
134371a3dd2SCédric Le Goater {
135*975d4bafSJamin Lin     uint32_t conf = spi_readl(data, R_CE_CTRL);
136371a3dd2SCédric Le Goater 
137371a3dd2SCédric Le Goater     conf |= value;
138*975d4bafSJamin Lin     spi_writel(data, R_CE_CTRL, conf);
139371a3dd2SCédric Le Goater }
140371a3dd2SCédric Le Goater 
141*975d4bafSJamin Lin static void spi_ctrl_setmode(const TestData *data, uint8_t mode, uint8_t cmd)
142371a3dd2SCédric Le Goater {
143*975d4bafSJamin Lin     uint32_t ctrl = spi_readl(data, R_CTRL0);
144371a3dd2SCédric Le Goater     ctrl &= ~(CTRL_USERMODE | 0xff << 16);
145371a3dd2SCédric Le Goater     ctrl |= mode | (cmd << 16);
146*975d4bafSJamin Lin     spi_writel(data, R_CTRL0, ctrl);
147371a3dd2SCédric Le Goater }
148371a3dd2SCédric Le Goater 
149*975d4bafSJamin Lin static void spi_ctrl_start_user(const TestData *data)
1507a2334f7SCédric Le Goater {
151*975d4bafSJamin Lin     uint32_t ctrl = spi_readl(data, R_CTRL0);
1527a2334f7SCédric Le Goater 
1537a2334f7SCédric Le Goater     ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
154*975d4bafSJamin Lin     spi_writel(data, R_CTRL0, ctrl);
1557a2334f7SCédric Le Goater 
1567a2334f7SCédric Le Goater     ctrl &= ~CTRL_CE_STOP_ACTIVE;
157*975d4bafSJamin Lin     spi_writel(data, R_CTRL0, ctrl);
1587a2334f7SCédric Le Goater }
1597a2334f7SCédric Le Goater 
160*975d4bafSJamin Lin static void spi_ctrl_stop_user(const TestData *data)
1617a2334f7SCédric Le Goater {
162*975d4bafSJamin Lin     uint32_t ctrl = spi_readl(data, R_CTRL0);
1637a2334f7SCédric Le Goater 
1647a2334f7SCédric Le Goater     ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
165*975d4bafSJamin Lin     spi_writel(data, R_CTRL0, ctrl);
1667a2334f7SCédric Le Goater }
1677a2334f7SCédric Le Goater 
168*975d4bafSJamin Lin static void flash_reset(const TestData *data)
169bd9f5052SCédric Le Goater {
170*975d4bafSJamin Lin     spi_conf(data, CONF_ENABLE_W0);
171bd9f5052SCédric Le Goater 
172*975d4bafSJamin Lin     spi_ctrl_start_user(data);
173*975d4bafSJamin Lin     flash_writeb(data, 0, RESET_ENABLE);
174*975d4bafSJamin Lin     flash_writeb(data, 0, RESET_MEMORY);
175*975d4bafSJamin Lin     flash_writeb(data, 0, WREN);
176*975d4bafSJamin Lin     flash_writeb(data, 0, BULK_ERASE);
177*975d4bafSJamin Lin     flash_writeb(data, 0, WRDI);
178*975d4bafSJamin Lin     spi_ctrl_stop_user(data);
179bd9f5052SCédric Le Goater 
180*975d4bafSJamin Lin     spi_conf_remove(data, CONF_ENABLE_W0);
181bd9f5052SCédric Le Goater }
182bd9f5052SCédric Le Goater 
183*975d4bafSJamin Lin static void test_read_jedec(const void *data)
1847a2334f7SCédric Le Goater {
185*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
1867a2334f7SCédric Le Goater     uint32_t jedec = 0x0;
1877a2334f7SCédric Le Goater 
188*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
1897a2334f7SCédric Le Goater 
190*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
191*975d4bafSJamin Lin     flash_writeb(test_data, 0, JEDEC_READ);
192*975d4bafSJamin Lin     jedec |= flash_readb(test_data, 0) << 16;
193*975d4bafSJamin Lin     jedec |= flash_readb(test_data, 0) << 8;
194*975d4bafSJamin Lin     jedec |= flash_readb(test_data, 0);
195*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
1967a2334f7SCédric Le Goater 
197*975d4bafSJamin Lin     flash_reset(test_data);
198bd9f5052SCédric Le Goater 
199*975d4bafSJamin Lin     g_assert_cmphex(jedec, ==, test_data->jedec_id);
2007a2334f7SCédric Le Goater }
2017a2334f7SCédric Le Goater 
202*975d4bafSJamin Lin static void read_page(const TestData *data, uint32_t addr, uint32_t *page)
2037a2334f7SCédric Le Goater {
2047a2334f7SCédric Le Goater     int i;
2057a2334f7SCédric Le Goater 
206*975d4bafSJamin Lin     spi_ctrl_start_user(data);
2077a2334f7SCédric Le Goater 
208*975d4bafSJamin Lin     flash_writeb(data, 0, EN_4BYTE_ADDR);
209*975d4bafSJamin Lin     flash_writeb(data, 0, READ);
210*975d4bafSJamin Lin     flash_writel(data, 0, make_be32(addr));
2117a2334f7SCédric Le Goater 
2127a2334f7SCédric Le Goater     /* Continuous read are supported */
213d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
214*975d4bafSJamin Lin         page[i] = make_be32(flash_readl(data, 0));
2157a2334f7SCédric Le Goater     }
216*975d4bafSJamin Lin     spi_ctrl_stop_user(data);
2177a2334f7SCédric Le Goater }
2187a2334f7SCédric Le Goater 
219*975d4bafSJamin Lin static void read_page_mem(const TestData *data, uint32_t addr, uint32_t *page)
220371a3dd2SCédric Le Goater {
221371a3dd2SCédric Le Goater     int i;
222371a3dd2SCédric Le Goater 
223371a3dd2SCédric Le Goater     /* move out USER mode to use direct reads from the AHB bus */
224*975d4bafSJamin Lin     spi_ctrl_setmode(data, CTRL_READMODE, READ);
225371a3dd2SCédric Le Goater 
226d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
227*975d4bafSJamin Lin         page[i] = make_be32(flash_readl(data, addr + i * 4));
228371a3dd2SCédric Le Goater     }
229371a3dd2SCédric Le Goater }
230371a3dd2SCédric Le Goater 
231*975d4bafSJamin Lin static void write_page_mem(const TestData *data, uint32_t addr,
232*975d4bafSJamin Lin                            uint32_t write_value)
2338abf9ba4SIris Chen {
234*975d4bafSJamin Lin     spi_ctrl_setmode(data, CTRL_WRITEMODE, PP);
2358abf9ba4SIris Chen 
2368abf9ba4SIris Chen     for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
237*975d4bafSJamin Lin         flash_writel(data, addr + i * 4, write_value);
2388abf9ba4SIris Chen     }
2398abf9ba4SIris Chen }
2408abf9ba4SIris Chen 
241*975d4bafSJamin Lin static void assert_page_mem(const TestData *data, uint32_t addr,
242*975d4bafSJamin Lin                             uint32_t expected_value)
2438abf9ba4SIris Chen {
2448abf9ba4SIris Chen     uint32_t page[FLASH_PAGE_SIZE / 4];
245*975d4bafSJamin Lin     read_page_mem(data, addr, page);
2468abf9ba4SIris Chen     for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
2478abf9ba4SIris Chen         g_assert_cmphex(page[i], ==, expected_value);
2488abf9ba4SIris Chen     }
2498abf9ba4SIris Chen }
2508abf9ba4SIris Chen 
251*975d4bafSJamin Lin static void test_erase_sector(const void *data)
2527a2334f7SCédric Le Goater {
253*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
254d2c4f384SJiaxun Yang     uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE;
255d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
2567a2334f7SCédric Le Goater     int i;
2577a2334f7SCédric Le Goater 
258*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
2597a2334f7SCédric Le Goater 
26092a45bdeSIris Chen     /*
26192a45bdeSIris Chen      * Previous page should be full of 0xffs after backend is
26292a45bdeSIris Chen      * initialized
26392a45bdeSIris Chen      */
264*975d4bafSJamin Lin     read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page);
26592a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
26692a45bdeSIris Chen         g_assert_cmphex(page[i], ==, 0xffffffff);
26792a45bdeSIris Chen     }
26892a45bdeSIris Chen 
269*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
270*975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
271*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
272*975d4bafSJamin Lin     flash_writeb(test_data, 0, PP);
273*975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(some_page_addr));
27492a45bdeSIris Chen 
27592a45bdeSIris Chen     /* Fill the page with its own addresses */
27692a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
277*975d4bafSJamin Lin         flash_writel(test_data, 0, make_be32(some_page_addr + i * 4));
27892a45bdeSIris Chen     }
279*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
28092a45bdeSIris Chen 
28192a45bdeSIris Chen     /* Check the page is correctly written */
282*975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
28392a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
28492a45bdeSIris Chen         g_assert_cmphex(page[i], ==, some_page_addr + i * 4);
28592a45bdeSIris Chen     }
28692a45bdeSIris Chen 
287*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
288*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
289*975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
290*975d4bafSJamin Lin     flash_writeb(test_data, 0, ERASE_SECTOR);
291*975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(some_page_addr));
292*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
2937a2334f7SCédric Le Goater 
29492a45bdeSIris Chen     /* Check the page is erased */
295*975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
296d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
2977a2334f7SCédric Le Goater         g_assert_cmphex(page[i], ==, 0xffffffff);
2987a2334f7SCédric Le Goater     }
299bd9f5052SCédric Le Goater 
300*975d4bafSJamin Lin     flash_reset(test_data);
3017a2334f7SCédric Le Goater }
3027a2334f7SCédric Le Goater 
303*975d4bafSJamin Lin static void test_erase_all(const void *data)
3047a2334f7SCédric Le Goater {
305*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
306d2c4f384SJiaxun Yang     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
307d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
3087a2334f7SCédric Le Goater     int i;
3097a2334f7SCédric Le Goater 
310*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
3117a2334f7SCédric Le Goater 
31292a45bdeSIris Chen     /*
31392a45bdeSIris Chen      * Previous page should be full of 0xffs after backend is
31492a45bdeSIris Chen      * initialized
31592a45bdeSIris Chen      */
316*975d4bafSJamin Lin     read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page);
31792a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
31892a45bdeSIris Chen         g_assert_cmphex(page[i], ==, 0xffffffff);
31992a45bdeSIris Chen     }
32092a45bdeSIris Chen 
321*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
322*975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
323*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
324*975d4bafSJamin Lin     flash_writeb(test_data, 0, PP);
325*975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(some_page_addr));
32692a45bdeSIris Chen 
32792a45bdeSIris Chen     /* Fill the page with its own addresses */
32892a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
329*975d4bafSJamin Lin         flash_writel(test_data, 0, make_be32(some_page_addr + i * 4));
33092a45bdeSIris Chen     }
331*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
33292a45bdeSIris Chen 
33392a45bdeSIris Chen     /* Check the page is correctly written */
334*975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
335d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
33692a45bdeSIris Chen         g_assert_cmphex(page[i], ==, some_page_addr + i * 4);
3377a2334f7SCédric Le Goater     }
3387a2334f7SCédric Le Goater 
339*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
340*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
341*975d4bafSJamin Lin     flash_writeb(test_data, 0, BULK_ERASE);
342*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
3437a2334f7SCédric Le Goater 
34492a45bdeSIris Chen     /* Check the page is erased */
345*975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
346d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
3477a2334f7SCédric Le Goater         g_assert_cmphex(page[i], ==, 0xffffffff);
3487a2334f7SCédric Le Goater     }
349bd9f5052SCédric Le Goater 
350*975d4bafSJamin Lin     flash_reset(test_data);
3517a2334f7SCédric Le Goater }
3527a2334f7SCédric Le Goater 
353*975d4bafSJamin Lin static void test_write_page(const void *data)
3547a2334f7SCédric Le Goater {
355*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
356d2c4f384SJiaxun Yang     uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */
357d2c4f384SJiaxun Yang     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
358d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
3597a2334f7SCédric Le Goater     int i;
3607a2334f7SCédric Le Goater 
361*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
3627a2334f7SCédric Le Goater 
363*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
364*975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
365*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
366*975d4bafSJamin Lin     flash_writeb(test_data, 0, PP);
367*975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(my_page_addr));
3687a2334f7SCédric Le Goater 
3697a2334f7SCédric Le Goater     /* Fill the page with its own addresses */
370d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
371*975d4bafSJamin Lin         flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
3727a2334f7SCédric Le Goater     }
373*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
3747a2334f7SCédric Le Goater 
3757a2334f7SCédric Le Goater     /* Check what was written */
376*975d4bafSJamin Lin     read_page(test_data, my_page_addr, page);
377d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
3787a2334f7SCédric Le Goater         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
3797a2334f7SCédric Le Goater     }
3807a2334f7SCédric Le Goater 
3817a2334f7SCédric Le Goater     /* Check some other page. It should be full of 0xff */
382*975d4bafSJamin Lin     read_page(test_data, some_page_addr, page);
383d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
3847a2334f7SCédric Le Goater         g_assert_cmphex(page[i], ==, 0xffffffff);
3857a2334f7SCédric Le Goater     }
386bd9f5052SCédric Le Goater 
387*975d4bafSJamin Lin     flash_reset(test_data);
3887a2334f7SCédric Le Goater }
3897a2334f7SCédric Le Goater 
390*975d4bafSJamin Lin static void test_read_page_mem(const void *data)
391371a3dd2SCédric Le Goater {
392*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
393d2c4f384SJiaxun Yang     uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */
394d2c4f384SJiaxun Yang     uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE;
395d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
396371a3dd2SCédric Le Goater     int i;
397371a3dd2SCédric Le Goater 
3981df52a9aSJamin Lin     /*
3991df52a9aSJamin Lin      * Enable 4BYTE mode for controller. This is should be strapped by
400371a3dd2SCédric Le Goater      * HW for CE0 anyhow.
401371a3dd2SCédric Le Goater      */
402*975d4bafSJamin Lin     spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0);
403371a3dd2SCédric Le Goater 
404371a3dd2SCédric Le Goater     /* Enable 4BYTE mode for flash. */
405*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
406*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
407*975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
408*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
409*975d4bafSJamin Lin     flash_writeb(test_data, 0, PP);
410*975d4bafSJamin Lin     flash_writel(test_data, 0, make_be32(my_page_addr));
41192a45bdeSIris Chen 
41292a45bdeSIris Chen     /* Fill the page with its own addresses */
41392a45bdeSIris Chen     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
414*975d4bafSJamin Lin         flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
41592a45bdeSIris Chen     }
416*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
417*975d4bafSJamin Lin     spi_conf_remove(test_data, CONF_ENABLE_W0);
418371a3dd2SCédric Le Goater 
419371a3dd2SCédric Le Goater     /* Check what was written */
420*975d4bafSJamin Lin     read_page_mem(test_data, my_page_addr, page);
421d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
422371a3dd2SCédric Le Goater         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
423371a3dd2SCédric Le Goater     }
424371a3dd2SCédric Le Goater 
425371a3dd2SCédric Le Goater     /* Check some other page. It should be full of 0xff */
426*975d4bafSJamin Lin     read_page_mem(test_data, some_page_addr, page);
427d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
428371a3dd2SCédric Le Goater         g_assert_cmphex(page[i], ==, 0xffffffff);
429371a3dd2SCédric Le Goater     }
430371a3dd2SCédric Le Goater 
431*975d4bafSJamin Lin     flash_reset(test_data);
432371a3dd2SCédric Le Goater }
433371a3dd2SCédric Le Goater 
434*975d4bafSJamin Lin static void test_write_page_mem(const void *data)
435371a3dd2SCédric Le Goater {
436*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
437d2c4f384SJiaxun Yang     uint32_t my_page_addr = 0x15000 * FLASH_PAGE_SIZE;
438d2c4f384SJiaxun Yang     uint32_t page[FLASH_PAGE_SIZE / 4];
439371a3dd2SCédric Le Goater     int i;
440371a3dd2SCédric Le Goater 
4411df52a9aSJamin Lin     /*
4421df52a9aSJamin Lin      * Enable 4BYTE mode for controller. This is should be strapped by
443371a3dd2SCédric Le Goater      * HW for CE0 anyhow.
444371a3dd2SCédric Le Goater      */
445*975d4bafSJamin Lin     spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0);
446371a3dd2SCédric Le Goater 
447371a3dd2SCédric Le Goater     /* Enable 4BYTE mode for flash. */
448*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
449*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
450*975d4bafSJamin Lin     flash_writeb(test_data, 0, EN_4BYTE_ADDR);
451*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
452*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
453371a3dd2SCédric Le Goater 
454371a3dd2SCédric Le Goater     /* move out USER mode to use direct writes to the AHB bus */
455*975d4bafSJamin Lin     spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP);
456371a3dd2SCédric Le Goater 
457d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
458*975d4bafSJamin Lin         flash_writel(test_data, my_page_addr + i * 4,
459371a3dd2SCédric Le Goater                make_be32(my_page_addr + i * 4));
460371a3dd2SCédric Le Goater     }
461371a3dd2SCédric Le Goater 
462371a3dd2SCédric Le Goater     /* Check what was written */
463*975d4bafSJamin Lin     read_page_mem(test_data, my_page_addr, page);
464d2c4f384SJiaxun Yang     for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
465371a3dd2SCédric Le Goater         g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
466371a3dd2SCédric Le Goater     }
467371a3dd2SCédric Le Goater 
468*975d4bafSJamin Lin     flash_reset(test_data);
469371a3dd2SCédric Le Goater }
470371a3dd2SCédric Le Goater 
471*975d4bafSJamin Lin static void test_read_status_reg(const void *data)
472188052a1SIris Chen {
473*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
474188052a1SIris Chen     uint8_t r;
475188052a1SIris Chen 
476*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
477188052a1SIris Chen 
478*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
479*975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
480*975d4bafSJamin Lin     r = flash_readb(test_data, 0);
481*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
482188052a1SIris Chen 
483188052a1SIris Chen     g_assert_cmphex(r & SR_WEL, ==, 0);
484188052a1SIris Chen     g_assert(!qtest_qom_get_bool
485*975d4bafSJamin Lin             (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
486188052a1SIris Chen 
487*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
488*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
489*975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
490*975d4bafSJamin Lin     r = flash_readb(test_data, 0);
491*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
492188052a1SIris Chen 
493188052a1SIris Chen     g_assert_cmphex(r & SR_WEL, ==, SR_WEL);
494188052a1SIris Chen     g_assert(qtest_qom_get_bool
495*975d4bafSJamin Lin             (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
496188052a1SIris Chen 
497*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
498*975d4bafSJamin Lin     flash_writeb(test_data, 0, WRDI);
499*975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
500*975d4bafSJamin Lin     r = flash_readb(test_data, 0);
501*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
502188052a1SIris Chen 
503188052a1SIris Chen     g_assert_cmphex(r & SR_WEL, ==, 0);
504188052a1SIris Chen     g_assert(!qtest_qom_get_bool
505*975d4bafSJamin Lin             (test_data->s, "/machine/soc/fmc/ssi.0/child[0]", "write-enable"));
506188052a1SIris Chen 
507*975d4bafSJamin Lin     flash_reset(test_data);
508188052a1SIris Chen }
509188052a1SIris Chen 
510*975d4bafSJamin Lin static void test_status_reg_write_protection(const void *data)
5111de51272SIris Chen {
512*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
5131de51272SIris Chen     uint8_t r;
5141de51272SIris Chen 
515*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
5161de51272SIris Chen 
5171de51272SIris Chen     /* default case: WP# is high and SRWD is low -> status register writable */
518*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
519*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
5201de51272SIris Chen     /* test ability to write SRWD */
521*975d4bafSJamin Lin     flash_writeb(test_data, 0, WRSR);
522*975d4bafSJamin Lin     flash_writeb(test_data, 0, SRWD);
523*975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
524*975d4bafSJamin Lin     r = flash_readb(test_data, 0);
525*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
5261de51272SIris Chen     g_assert_cmphex(r & SRWD, ==, SRWD);
5271de51272SIris Chen 
5281de51272SIris Chen     /* WP# high and SRWD high -> status register writable */
529*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
530*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
5311de51272SIris Chen     /* test ability to write SRWD */
532*975d4bafSJamin Lin     flash_writeb(test_data, 0, WRSR);
533*975d4bafSJamin Lin     flash_writeb(test_data, 0, 0);
534*975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
535*975d4bafSJamin Lin     r = flash_readb(test_data, 0);
536*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
5371de51272SIris Chen     g_assert_cmphex(r & SRWD, ==, 0);
5381de51272SIris Chen 
5391de51272SIris Chen     /* WP# low and SRWD low -> status register writable */
540*975d4bafSJamin Lin     qtest_set_irq_in(test_data->s,
5411de51272SIris Chen                      "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 0);
542*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
543*975d4bafSJamin Lin     flash_writeb(test_data, 0, WREN);
5441de51272SIris Chen     /* test ability to write SRWD */
545*975d4bafSJamin Lin     flash_writeb(test_data, 0, WRSR);
546*975d4bafSJamin Lin     flash_writeb(test_data, 0, SRWD);
547*975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
548*975d4bafSJamin Lin     r = flash_readb(test_data, 0);
549*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
5501de51272SIris Chen     g_assert_cmphex(r & SRWD, ==, SRWD);
5511de51272SIris Chen 
5521de51272SIris Chen     /* WP# low and SRWD high -> status register NOT writable */
553*975d4bafSJamin Lin     spi_ctrl_start_user(test_data);
554*975d4bafSJamin Lin     flash_writeb(test_data, 0 , WREN);
5551de51272SIris Chen     /* test ability to write SRWD */
556*975d4bafSJamin Lin     flash_writeb(test_data, 0, WRSR);
557*975d4bafSJamin Lin     flash_writeb(test_data, 0, 0);
558*975d4bafSJamin Lin     flash_writeb(test_data, 0, RDSR);
559*975d4bafSJamin Lin     r = flash_readb(test_data, 0);
560*975d4bafSJamin Lin     spi_ctrl_stop_user(test_data);
5611de51272SIris Chen     /* write is not successful */
5621de51272SIris Chen     g_assert_cmphex(r & SRWD, ==, SRWD);
5631de51272SIris Chen 
564*975d4bafSJamin Lin     qtest_set_irq_in(test_data->s,
5651de51272SIris Chen                      "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 1);
566*975d4bafSJamin Lin     flash_reset(test_data);
5671de51272SIris Chen }
5681de51272SIris Chen 
569*975d4bafSJamin Lin static void test_write_block_protect(const void *data)
5708abf9ba4SIris Chen {
571*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
5728abf9ba4SIris Chen     uint32_t sector_size = 65536;
5738abf9ba4SIris Chen     uint32_t n_sectors = 512;
5748abf9ba4SIris Chen 
575*975d4bafSJamin Lin     spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0);
576*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
5778abf9ba4SIris Chen 
5788abf9ba4SIris Chen     uint32_t bp_bits = 0b0;
5798abf9ba4SIris Chen 
5808abf9ba4SIris Chen     for (int i = 0; i < 16; i++) {
5818abf9ba4SIris Chen         bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2);
5828abf9ba4SIris Chen 
583*975d4bafSJamin Lin         spi_ctrl_start_user(test_data);
584*975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
585*975d4bafSJamin Lin         flash_writeb(test_data, 0, BULK_ERASE);
586*975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
587*975d4bafSJamin Lin         flash_writeb(test_data, 0, WRSR);
588*975d4bafSJamin Lin         flash_writeb(test_data, 0, bp_bits);
589*975d4bafSJamin Lin         flash_writeb(test_data, 0, EN_4BYTE_ADDR);
590*975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
591*975d4bafSJamin Lin         spi_ctrl_stop_user(test_data);
5928abf9ba4SIris Chen 
5938abf9ba4SIris Chen         uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
5948abf9ba4SIris Chen         uint32_t protection_start = n_sectors - num_protected_sectors;
5958abf9ba4SIris Chen         uint32_t protection_end = n_sectors;
5968abf9ba4SIris Chen 
5978abf9ba4SIris Chen         for (int sector = 0; sector < n_sectors; sector++) {
5988abf9ba4SIris Chen             uint32_t addr = sector * sector_size;
5998abf9ba4SIris Chen 
600*975d4bafSJamin Lin             assert_page_mem(test_data, addr, 0xffffffff);
601*975d4bafSJamin Lin             write_page_mem(test_data, addr, make_be32(0xabcdef12));
6028abf9ba4SIris Chen 
6038abf9ba4SIris Chen             uint32_t expected_value = protection_start <= sector
6048abf9ba4SIris Chen                                       && sector < protection_end
6058abf9ba4SIris Chen                                       ? 0xffffffff : 0xabcdef12;
6068abf9ba4SIris Chen 
607*975d4bafSJamin Lin             assert_page_mem(test_data, addr, expected_value);
6088abf9ba4SIris Chen         }
6098abf9ba4SIris Chen     }
6108abf9ba4SIris Chen 
611*975d4bafSJamin Lin     flash_reset(test_data);
6128abf9ba4SIris Chen }
6138abf9ba4SIris Chen 
614*975d4bafSJamin Lin static void test_write_block_protect_bottom_bit(const void *data)
6158abf9ba4SIris Chen {
616*975d4bafSJamin Lin     const TestData *test_data = (const TestData *)data;
6178abf9ba4SIris Chen     uint32_t sector_size = 65536;
6188abf9ba4SIris Chen     uint32_t n_sectors = 512;
6198abf9ba4SIris Chen 
620*975d4bafSJamin Lin     spi_ce_ctrl(test_data, 1 << CRTL_EXTENDED0);
621*975d4bafSJamin Lin     spi_conf(test_data, CONF_ENABLE_W0);
6228abf9ba4SIris Chen 
6238abf9ba4SIris Chen     /* top bottom bit is enabled */
6248abf9ba4SIris Chen     uint32_t bp_bits = 0b00100 << 3;
6258abf9ba4SIris Chen 
6268abf9ba4SIris Chen     for (int i = 0; i < 16; i++) {
6278abf9ba4SIris Chen         bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2);
6288abf9ba4SIris Chen 
629*975d4bafSJamin Lin         spi_ctrl_start_user(test_data);
630*975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
631*975d4bafSJamin Lin         flash_writeb(test_data, 0, BULK_ERASE);
632*975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
633*975d4bafSJamin Lin         flash_writeb(test_data, 0, WRSR);
634*975d4bafSJamin Lin         flash_writeb(test_data, 0, bp_bits);
635*975d4bafSJamin Lin         flash_writeb(test_data, 0, EN_4BYTE_ADDR);
636*975d4bafSJamin Lin         flash_writeb(test_data, 0, WREN);
637*975d4bafSJamin Lin         spi_ctrl_stop_user(test_data);
6388abf9ba4SIris Chen 
6398abf9ba4SIris Chen         uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
6408abf9ba4SIris Chen         uint32_t protection_start = 0;
6418abf9ba4SIris Chen         uint32_t protection_end = num_protected_sectors;
6428abf9ba4SIris Chen 
6438abf9ba4SIris Chen         for (int sector = 0; sector < n_sectors; sector++) {
6448abf9ba4SIris Chen             uint32_t addr = sector * sector_size;
6458abf9ba4SIris Chen 
646*975d4bafSJamin Lin             assert_page_mem(test_data, addr, 0xffffffff);
647*975d4bafSJamin Lin             write_page_mem(test_data, addr, make_be32(0xabcdef12));
6488abf9ba4SIris Chen 
6498abf9ba4SIris Chen             uint32_t expected_value = protection_start <= sector
6508abf9ba4SIris Chen                                       && sector < protection_end
6518abf9ba4SIris Chen                                       ? 0xffffffff : 0xabcdef12;
6528abf9ba4SIris Chen 
653*975d4bafSJamin Lin             assert_page_mem(test_data, addr, expected_value);
6548abf9ba4SIris Chen         }
6558abf9ba4SIris Chen     }
6568abf9ba4SIris Chen 
657*975d4bafSJamin Lin     flash_reset(test_data);
6588abf9ba4SIris Chen }
6598abf9ba4SIris Chen 
660*975d4bafSJamin Lin static void test_palmetto_bmc(TestData *data)
6617a2334f7SCédric Le Goater {
6627a2334f7SCédric Le Goater     int ret;
6637a2334f7SCédric Le Goater     int fd;
6647a2334f7SCédric Le Goater 
665*975d4bafSJamin Lin     fd = g_file_open_tmp("qtest.m25p80.n25q256a.XXXXXX", &data->tmp_path, NULL);
6667a2334f7SCédric Le Goater     g_assert(fd >= 0);
667*975d4bafSJamin Lin     ret = ftruncate(fd, 32 * 1024 * 1024);
6687a2334f7SCédric Le Goater     g_assert(ret == 0);
6697a2334f7SCédric Le Goater     close(fd);
6707a2334f7SCédric Le Goater 
671*975d4bafSJamin Lin     data->s = qtest_initf("-m 256 -machine palmetto-bmc "
6727a2334f7SCédric Le Goater                           "-drive file=%s,format=raw,if=mtd",
673*975d4bafSJamin Lin                           data->tmp_path);
6747a2334f7SCédric Le Goater 
675*975d4bafSJamin Lin     /* fmc cs0 with n25q256a flash */
676*975d4bafSJamin Lin     data->flash_base = 0x20000000;
677*975d4bafSJamin Lin     data->spi_base = 0x1E620000;
678*975d4bafSJamin Lin     data->jedec_id = 0x20ba19;
6797a2334f7SCédric Le Goater 
680*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/read_jedec", data, test_read_jedec);
681*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/erase_sector", data, test_erase_sector);
682*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/erase_all",  data, test_erase_all);
683*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/write_page", data, test_write_page);
684*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/read_page_mem",
685*975d4bafSJamin Lin                         data, test_read_page_mem);
686*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/write_page_mem",
687*975d4bafSJamin Lin                         data, test_write_page_mem);
688*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/read_status_reg",
689*975d4bafSJamin Lin                         data, test_read_status_reg);
690*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/status_reg_write_protection",
691*975d4bafSJamin Lin                         data, test_status_reg_write_protection);
692*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/write_block_protect",
693*975d4bafSJamin Lin                         data, test_write_block_protect);
694*975d4bafSJamin Lin     qtest_add_data_func("/ast2400/smc/write_block_protect_bottom_bit",
695*975d4bafSJamin Lin                         data, test_write_block_protect_bottom_bit);
696755e984aSJamin Lin }
697755e984aSJamin Lin 
698755e984aSJamin Lin int main(int argc, char **argv)
699755e984aSJamin Lin {
700*975d4bafSJamin Lin     TestData palmetto_data;
701755e984aSJamin Lin     int ret;
702755e984aSJamin Lin 
703755e984aSJamin Lin     g_test_init(&argc, &argv, NULL);
704755e984aSJamin Lin 
705*975d4bafSJamin Lin     test_palmetto_bmc(&palmetto_data);
706*975d4bafSJamin Lin     ret = g_test_run();
707*975d4bafSJamin Lin 
708*975d4bafSJamin Lin     qtest_quit(palmetto_data.s);
709*975d4bafSJamin Lin     unlink(palmetto_data.tmp_path);
7107a2334f7SCédric Le Goater     return ret;
7117a2334f7SCédric Le Goater }
712