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