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 35dc32f5baSJamin 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 39dc32f5baSJamin 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; 73dc32f5baSJamin Lin uint8_t cs; 74dc32f5baSJamin Lin const char *node; 75369a47aeSJamin Lin uint32_t page_addr; 76975d4bafSJamin Lin } TestData; 77975d4bafSJamin Lin 787a2334f7SCédric Le Goater /* 797a2334f7SCédric Le Goater * Use an explicit bswap for the values read/wrote to the flash region 807a2334f7SCédric Le Goater * as they are BE and the Aspeed CPU is LE. 817a2334f7SCédric Le Goater */ 827a2334f7SCédric Le Goater static inline uint32_t make_be32(uint32_t data) 837a2334f7SCédric Le Goater { 847a2334f7SCédric Le Goater return bswap32(data); 857a2334f7SCédric Le Goater } 867a2334f7SCédric Le Goater 87975d4bafSJamin Lin static inline void spi_writel(const TestData *data, uint64_t offset, 88975d4bafSJamin Lin uint32_t value) 897a2334f7SCédric Le Goater { 90975d4bafSJamin Lin qtest_writel(data->s, data->spi_base + offset, value); 917a2334f7SCédric Le Goater } 927a2334f7SCédric Le Goater 93975d4bafSJamin Lin static inline uint32_t spi_readl(const TestData *data, uint64_t offset) 94bd9f5052SCédric Le Goater { 95975d4bafSJamin Lin return qtest_readl(data->s, data->spi_base + offset); 96975d4bafSJamin Lin } 97975d4bafSJamin Lin 98975d4bafSJamin Lin static inline void flash_writeb(const TestData *data, uint64_t offset, 99975d4bafSJamin Lin uint8_t value) 100975d4bafSJamin Lin { 101975d4bafSJamin Lin qtest_writeb(data->s, data->flash_base + offset, value); 102975d4bafSJamin Lin } 103975d4bafSJamin Lin 104975d4bafSJamin Lin static inline void flash_writel(const TestData *data, uint64_t offset, 105975d4bafSJamin Lin uint32_t value) 106975d4bafSJamin Lin { 107975d4bafSJamin Lin qtest_writel(data->s, data->flash_base + offset, value); 108975d4bafSJamin Lin } 109975d4bafSJamin Lin 110975d4bafSJamin Lin static inline uint8_t flash_readb(const TestData *data, uint64_t offset) 111975d4bafSJamin Lin { 112975d4bafSJamin Lin return qtest_readb(data->s, data->flash_base + offset); 113975d4bafSJamin Lin } 114975d4bafSJamin Lin 115975d4bafSJamin Lin static inline uint32_t flash_readl(const TestData *data, uint64_t offset) 116975d4bafSJamin Lin { 117975d4bafSJamin Lin return qtest_readl(data->s, data->flash_base + offset); 118975d4bafSJamin Lin } 119975d4bafSJamin Lin 120975d4bafSJamin Lin static void spi_conf(const TestData *data, uint32_t value) 121975d4bafSJamin Lin { 122975d4bafSJamin Lin uint32_t conf = spi_readl(data, R_CONF); 123975d4bafSJamin Lin 124975d4bafSJamin Lin conf |= value; 125975d4bafSJamin Lin spi_writel(data, R_CONF, conf); 126975d4bafSJamin Lin } 127975d4bafSJamin Lin 128975d4bafSJamin Lin static void spi_conf_remove(const TestData *data, uint32_t value) 129975d4bafSJamin Lin { 130975d4bafSJamin Lin uint32_t conf = spi_readl(data, R_CONF); 131bd9f5052SCédric Le Goater 132bd9f5052SCédric Le Goater conf &= ~value; 133975d4bafSJamin Lin spi_writel(data, R_CONF, conf); 134bd9f5052SCédric Le Goater } 135bd9f5052SCédric Le Goater 136975d4bafSJamin Lin static void spi_ce_ctrl(const TestData *data, uint32_t value) 137371a3dd2SCédric Le Goater { 138975d4bafSJamin Lin uint32_t conf = spi_readl(data, R_CE_CTRL); 139371a3dd2SCédric Le Goater 140371a3dd2SCédric Le Goater conf |= value; 141975d4bafSJamin Lin spi_writel(data, R_CE_CTRL, conf); 142371a3dd2SCédric Le Goater } 143371a3dd2SCédric Le Goater 144975d4bafSJamin Lin static void spi_ctrl_setmode(const TestData *data, uint8_t mode, uint8_t cmd) 145371a3dd2SCédric Le Goater { 146dc32f5baSJamin Lin uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; 147dc32f5baSJamin Lin uint32_t ctrl = spi_readl(data, ctrl_reg); 148371a3dd2SCédric Le Goater ctrl &= ~(CTRL_USERMODE | 0xff << 16); 149371a3dd2SCédric Le Goater ctrl |= mode | (cmd << 16); 150dc32f5baSJamin Lin spi_writel(data, ctrl_reg, ctrl); 151371a3dd2SCédric Le Goater } 152371a3dd2SCédric Le Goater 153975d4bafSJamin Lin static void spi_ctrl_start_user(const TestData *data) 1547a2334f7SCédric Le Goater { 155dc32f5baSJamin Lin uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; 156dc32f5baSJamin Lin uint32_t ctrl = spi_readl(data, ctrl_reg); 1577a2334f7SCédric Le Goater 1587a2334f7SCédric Le Goater ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; 159dc32f5baSJamin Lin spi_writel(data, ctrl_reg, ctrl); 1607a2334f7SCédric Le Goater 1617a2334f7SCédric Le Goater ctrl &= ~CTRL_CE_STOP_ACTIVE; 162dc32f5baSJamin Lin spi_writel(data, ctrl_reg, ctrl); 1637a2334f7SCédric Le Goater } 1647a2334f7SCédric Le Goater 165975d4bafSJamin Lin static void spi_ctrl_stop_user(const TestData *data) 1667a2334f7SCédric Le Goater { 167dc32f5baSJamin Lin uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; 168dc32f5baSJamin Lin uint32_t ctrl = spi_readl(data, ctrl_reg); 1697a2334f7SCédric Le Goater 1707a2334f7SCédric Le Goater ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; 171dc32f5baSJamin Lin spi_writel(data, ctrl_reg, ctrl); 1727a2334f7SCédric Le Goater } 1737a2334f7SCédric Le Goater 174975d4bafSJamin Lin static void flash_reset(const TestData *data) 175bd9f5052SCédric Le Goater { 176dc32f5baSJamin Lin spi_conf(data, 1 << (CONF_ENABLE_W0 + data->cs)); 177bd9f5052SCédric Le Goater 178975d4bafSJamin Lin spi_ctrl_start_user(data); 179975d4bafSJamin Lin flash_writeb(data, 0, RESET_ENABLE); 180975d4bafSJamin Lin flash_writeb(data, 0, RESET_MEMORY); 181975d4bafSJamin Lin flash_writeb(data, 0, WREN); 182975d4bafSJamin Lin flash_writeb(data, 0, BULK_ERASE); 183975d4bafSJamin Lin flash_writeb(data, 0, WRDI); 184975d4bafSJamin Lin spi_ctrl_stop_user(data); 185bd9f5052SCédric Le Goater 186dc32f5baSJamin Lin spi_conf_remove(data, 1 << (CONF_ENABLE_W0 + data->cs)); 187bd9f5052SCédric Le Goater } 188bd9f5052SCédric Le Goater 189975d4bafSJamin Lin static void test_read_jedec(const void *data) 1907a2334f7SCédric Le Goater { 191975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 1927a2334f7SCédric Le Goater uint32_t jedec = 0x0; 1937a2334f7SCédric Le Goater 194dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 1957a2334f7SCédric Le Goater 196975d4bafSJamin Lin spi_ctrl_start_user(test_data); 197975d4bafSJamin Lin flash_writeb(test_data, 0, JEDEC_READ); 198975d4bafSJamin Lin jedec |= flash_readb(test_data, 0) << 16; 199975d4bafSJamin Lin jedec |= flash_readb(test_data, 0) << 8; 200975d4bafSJamin Lin jedec |= flash_readb(test_data, 0); 201975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 2027a2334f7SCédric Le Goater 203975d4bafSJamin Lin flash_reset(test_data); 204bd9f5052SCédric Le Goater 205975d4bafSJamin Lin g_assert_cmphex(jedec, ==, test_data->jedec_id); 2067a2334f7SCédric Le Goater } 2077a2334f7SCédric Le Goater 208975d4bafSJamin Lin static void read_page(const TestData *data, uint32_t addr, uint32_t *page) 2097a2334f7SCédric Le Goater { 2107a2334f7SCédric Le Goater int i; 2117a2334f7SCédric Le Goater 212975d4bafSJamin Lin spi_ctrl_start_user(data); 2137a2334f7SCédric Le Goater 214975d4bafSJamin Lin flash_writeb(data, 0, EN_4BYTE_ADDR); 215975d4bafSJamin Lin flash_writeb(data, 0, READ); 216975d4bafSJamin Lin flash_writel(data, 0, make_be32(addr)); 2177a2334f7SCédric Le Goater 2187a2334f7SCédric Le Goater /* Continuous read are supported */ 219d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 220975d4bafSJamin Lin page[i] = make_be32(flash_readl(data, 0)); 2217a2334f7SCédric Le Goater } 222975d4bafSJamin Lin spi_ctrl_stop_user(data); 2237a2334f7SCédric Le Goater } 2247a2334f7SCédric Le Goater 225975d4bafSJamin Lin static void read_page_mem(const TestData *data, uint32_t addr, uint32_t *page) 226371a3dd2SCédric Le Goater { 227371a3dd2SCédric Le Goater int i; 228371a3dd2SCédric Le Goater 229371a3dd2SCédric Le Goater /* move out USER mode to use direct reads from the AHB bus */ 230975d4bafSJamin Lin spi_ctrl_setmode(data, CTRL_READMODE, READ); 231371a3dd2SCédric Le Goater 232d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 233975d4bafSJamin Lin page[i] = make_be32(flash_readl(data, addr + i * 4)); 234371a3dd2SCédric Le Goater } 235371a3dd2SCédric Le Goater } 236371a3dd2SCédric Le Goater 237975d4bafSJamin Lin static void write_page_mem(const TestData *data, uint32_t addr, 238975d4bafSJamin Lin uint32_t write_value) 2398abf9ba4SIris Chen { 240975d4bafSJamin Lin spi_ctrl_setmode(data, CTRL_WRITEMODE, PP); 2418abf9ba4SIris Chen 2428abf9ba4SIris Chen for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 243975d4bafSJamin Lin flash_writel(data, addr + i * 4, write_value); 2448abf9ba4SIris Chen } 2458abf9ba4SIris Chen } 2468abf9ba4SIris Chen 247975d4bafSJamin Lin static void assert_page_mem(const TestData *data, uint32_t addr, 248975d4bafSJamin Lin uint32_t expected_value) 2498abf9ba4SIris Chen { 2508abf9ba4SIris Chen uint32_t page[FLASH_PAGE_SIZE / 4]; 251975d4bafSJamin Lin read_page_mem(data, addr, page); 2528abf9ba4SIris Chen for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 2538abf9ba4SIris Chen g_assert_cmphex(page[i], ==, expected_value); 2548abf9ba4SIris Chen } 2558abf9ba4SIris Chen } 2568abf9ba4SIris Chen 257975d4bafSJamin Lin static void test_erase_sector(const void *data) 2587a2334f7SCédric Le Goater { 259975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 260369a47aeSJamin Lin uint32_t some_page_addr = test_data->page_addr; 261d2c4f384SJiaxun Yang uint32_t page[FLASH_PAGE_SIZE / 4]; 2627a2334f7SCédric Le Goater int i; 2637a2334f7SCédric Le Goater 264dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 2657a2334f7SCédric Le Goater 26692a45bdeSIris Chen /* 26792a45bdeSIris Chen * Previous page should be full of 0xffs after backend is 26892a45bdeSIris Chen * initialized 26992a45bdeSIris Chen */ 270975d4bafSJamin Lin read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); 27192a45bdeSIris Chen for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 27292a45bdeSIris Chen g_assert_cmphex(page[i], ==, 0xffffffff); 27392a45bdeSIris Chen } 27492a45bdeSIris Chen 275975d4bafSJamin Lin spi_ctrl_start_user(test_data); 276975d4bafSJamin Lin flash_writeb(test_data, 0, EN_4BYTE_ADDR); 277975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 278975d4bafSJamin Lin flash_writeb(test_data, 0, PP); 279975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(some_page_addr)); 28092a45bdeSIris Chen 28192a45bdeSIris Chen /* Fill the page with its own addresses */ 28292a45bdeSIris Chen for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 283975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); 28492a45bdeSIris Chen } 285975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 28692a45bdeSIris Chen 28792a45bdeSIris Chen /* Check the page is correctly written */ 288975d4bafSJamin Lin read_page(test_data, some_page_addr, page); 28992a45bdeSIris Chen for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 29092a45bdeSIris Chen g_assert_cmphex(page[i], ==, some_page_addr + i * 4); 29192a45bdeSIris Chen } 29292a45bdeSIris Chen 293975d4bafSJamin Lin spi_ctrl_start_user(test_data); 294975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 295975d4bafSJamin Lin flash_writeb(test_data, 0, EN_4BYTE_ADDR); 296975d4bafSJamin Lin flash_writeb(test_data, 0, ERASE_SECTOR); 297975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(some_page_addr)); 298975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 2997a2334f7SCédric Le Goater 30092a45bdeSIris Chen /* Check the page is erased */ 301975d4bafSJamin Lin read_page(test_data, some_page_addr, page); 302d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 3037a2334f7SCédric Le Goater g_assert_cmphex(page[i], ==, 0xffffffff); 3047a2334f7SCédric Le Goater } 305bd9f5052SCédric Le Goater 306975d4bafSJamin Lin flash_reset(test_data); 3077a2334f7SCédric Le Goater } 3087a2334f7SCédric Le Goater 309975d4bafSJamin Lin static void test_erase_all(const void *data) 3107a2334f7SCédric Le Goater { 311975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 312369a47aeSJamin Lin uint32_t some_page_addr = test_data->page_addr; 313d2c4f384SJiaxun Yang uint32_t page[FLASH_PAGE_SIZE / 4]; 3147a2334f7SCédric Le Goater int i; 3157a2334f7SCédric Le Goater 316dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 3177a2334f7SCédric Le Goater 31892a45bdeSIris Chen /* 31992a45bdeSIris Chen * Previous page should be full of 0xffs after backend is 32092a45bdeSIris Chen * initialized 32192a45bdeSIris Chen */ 322975d4bafSJamin Lin read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); 32392a45bdeSIris Chen for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 32492a45bdeSIris Chen g_assert_cmphex(page[i], ==, 0xffffffff); 32592a45bdeSIris Chen } 32692a45bdeSIris Chen 327975d4bafSJamin Lin spi_ctrl_start_user(test_data); 328975d4bafSJamin Lin flash_writeb(test_data, 0, EN_4BYTE_ADDR); 329975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 330975d4bafSJamin Lin flash_writeb(test_data, 0, PP); 331975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(some_page_addr)); 33292a45bdeSIris Chen 33392a45bdeSIris Chen /* Fill the page with its own addresses */ 33492a45bdeSIris Chen for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 335975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); 33692a45bdeSIris Chen } 337975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 33892a45bdeSIris Chen 33992a45bdeSIris Chen /* Check the page is correctly written */ 340975d4bafSJamin Lin read_page(test_data, some_page_addr, page); 341d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 34292a45bdeSIris Chen g_assert_cmphex(page[i], ==, some_page_addr + i * 4); 3437a2334f7SCédric Le Goater } 3447a2334f7SCédric Le Goater 345975d4bafSJamin Lin spi_ctrl_start_user(test_data); 346975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 347975d4bafSJamin Lin flash_writeb(test_data, 0, BULK_ERASE); 348975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 3497a2334f7SCédric Le Goater 35092a45bdeSIris Chen /* Check the page is erased */ 351975d4bafSJamin Lin read_page(test_data, some_page_addr, page); 352d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 3537a2334f7SCédric Le Goater g_assert_cmphex(page[i], ==, 0xffffffff); 3547a2334f7SCédric Le Goater } 355bd9f5052SCédric Le Goater 356975d4bafSJamin Lin flash_reset(test_data); 3577a2334f7SCédric Le Goater } 3587a2334f7SCédric Le Goater 359975d4bafSJamin Lin static void test_write_page(const void *data) 3607a2334f7SCédric Le Goater { 361975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 362369a47aeSJamin Lin uint32_t my_page_addr = test_data->page_addr; 363369a47aeSJamin Lin uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; 364d2c4f384SJiaxun Yang uint32_t page[FLASH_PAGE_SIZE / 4]; 3657a2334f7SCédric Le Goater int i; 3667a2334f7SCédric Le Goater 367dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 3687a2334f7SCédric Le Goater 369975d4bafSJamin Lin spi_ctrl_start_user(test_data); 370975d4bafSJamin Lin flash_writeb(test_data, 0, EN_4BYTE_ADDR); 371975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 372975d4bafSJamin Lin flash_writeb(test_data, 0, PP); 373975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(my_page_addr)); 3747a2334f7SCédric Le Goater 3757a2334f7SCédric Le Goater /* Fill the page with its own addresses */ 376d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 377975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); 3787a2334f7SCédric Le Goater } 379975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 3807a2334f7SCédric Le Goater 3817a2334f7SCédric Le Goater /* Check what was written */ 382975d4bafSJamin Lin read_page(test_data, my_page_addr, page); 383d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 3847a2334f7SCédric Le Goater g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 3857a2334f7SCédric Le Goater } 3867a2334f7SCédric Le Goater 3877a2334f7SCédric Le Goater /* Check some other page. It should be full of 0xff */ 388975d4bafSJamin Lin read_page(test_data, some_page_addr, page); 389d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 3907a2334f7SCédric Le Goater g_assert_cmphex(page[i], ==, 0xffffffff); 3917a2334f7SCédric Le Goater } 392bd9f5052SCédric Le Goater 393975d4bafSJamin Lin flash_reset(test_data); 3947a2334f7SCédric Le Goater } 3957a2334f7SCédric Le Goater 396975d4bafSJamin Lin static void test_read_page_mem(const void *data) 397371a3dd2SCédric Le Goater { 398975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 399369a47aeSJamin Lin uint32_t my_page_addr = test_data->page_addr; 400369a47aeSJamin Lin uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; 401d2c4f384SJiaxun Yang uint32_t page[FLASH_PAGE_SIZE / 4]; 402371a3dd2SCédric Le Goater int i; 403371a3dd2SCédric Le Goater 4041df52a9aSJamin Lin /* 405dc32f5baSJamin Lin * Enable 4BYTE mode for controller. 406371a3dd2SCédric Le Goater */ 407dc32f5baSJamin Lin spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); 408371a3dd2SCédric Le Goater 409371a3dd2SCédric Le Goater /* Enable 4BYTE mode for flash. */ 410dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 411975d4bafSJamin Lin spi_ctrl_start_user(test_data); 412975d4bafSJamin Lin flash_writeb(test_data, 0, EN_4BYTE_ADDR); 413975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 414975d4bafSJamin Lin flash_writeb(test_data, 0, PP); 415975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(my_page_addr)); 41692a45bdeSIris Chen 41792a45bdeSIris Chen /* Fill the page with its own addresses */ 41892a45bdeSIris Chen for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 419975d4bafSJamin Lin flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); 42092a45bdeSIris Chen } 421975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 422dc32f5baSJamin Lin spi_conf_remove(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 423371a3dd2SCédric Le Goater 424371a3dd2SCédric Le Goater /* Check what was written */ 425975d4bafSJamin Lin read_page_mem(test_data, my_page_addr, page); 426d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 427371a3dd2SCédric Le Goater g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 428371a3dd2SCédric Le Goater } 429371a3dd2SCédric Le Goater 430371a3dd2SCédric Le Goater /* Check some other page. It should be full of 0xff */ 431975d4bafSJamin Lin read_page_mem(test_data, some_page_addr, page); 432d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 433371a3dd2SCédric Le Goater g_assert_cmphex(page[i], ==, 0xffffffff); 434371a3dd2SCédric Le Goater } 435371a3dd2SCédric Le Goater 436975d4bafSJamin Lin flash_reset(test_data); 437371a3dd2SCédric Le Goater } 438371a3dd2SCédric Le Goater 439975d4bafSJamin Lin static void test_write_page_mem(const void *data) 440371a3dd2SCédric Le Goater { 441975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 442369a47aeSJamin Lin uint32_t my_page_addr = test_data->page_addr; 443d2c4f384SJiaxun Yang uint32_t page[FLASH_PAGE_SIZE / 4]; 444371a3dd2SCédric Le Goater int i; 445371a3dd2SCédric Le Goater 4461df52a9aSJamin Lin /* 447dc32f5baSJamin Lin * Enable 4BYTE mode for controller. 448371a3dd2SCédric Le Goater */ 449dc32f5baSJamin Lin spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); 450371a3dd2SCédric Le Goater 451371a3dd2SCédric Le Goater /* Enable 4BYTE mode for flash. */ 452dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 453975d4bafSJamin Lin spi_ctrl_start_user(test_data); 454975d4bafSJamin Lin flash_writeb(test_data, 0, EN_4BYTE_ADDR); 455975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 456975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 457371a3dd2SCédric Le Goater 458371a3dd2SCédric Le Goater /* move out USER mode to use direct writes to the AHB bus */ 459975d4bafSJamin Lin spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP); 460371a3dd2SCédric Le Goater 461d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 462975d4bafSJamin Lin flash_writel(test_data, my_page_addr + i * 4, 463371a3dd2SCédric Le Goater make_be32(my_page_addr + i * 4)); 464371a3dd2SCédric Le Goater } 465371a3dd2SCédric Le Goater 466371a3dd2SCédric Le Goater /* Check what was written */ 467975d4bafSJamin Lin read_page_mem(test_data, my_page_addr, page); 468d2c4f384SJiaxun Yang for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 469371a3dd2SCédric Le Goater g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 470371a3dd2SCédric Le Goater } 471371a3dd2SCédric Le Goater 472975d4bafSJamin Lin flash_reset(test_data); 473371a3dd2SCédric Le Goater } 474371a3dd2SCédric Le Goater 475975d4bafSJamin Lin static void test_read_status_reg(const void *data) 476188052a1SIris Chen { 477975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 478188052a1SIris Chen uint8_t r; 479188052a1SIris Chen 480dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 481188052a1SIris Chen 482975d4bafSJamin Lin spi_ctrl_start_user(test_data); 483975d4bafSJamin Lin flash_writeb(test_data, 0, RDSR); 484975d4bafSJamin Lin r = flash_readb(test_data, 0); 485975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 486188052a1SIris Chen 487188052a1SIris Chen g_assert_cmphex(r & SR_WEL, ==, 0); 488188052a1SIris Chen g_assert(!qtest_qom_get_bool 489dc32f5baSJamin Lin (test_data->s, test_data->node, "write-enable")); 490188052a1SIris Chen 491975d4bafSJamin Lin spi_ctrl_start_user(test_data); 492975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 493975d4bafSJamin Lin flash_writeb(test_data, 0, RDSR); 494975d4bafSJamin Lin r = flash_readb(test_data, 0); 495975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 496188052a1SIris Chen 497188052a1SIris Chen g_assert_cmphex(r & SR_WEL, ==, SR_WEL); 498188052a1SIris Chen g_assert(qtest_qom_get_bool 499dc32f5baSJamin Lin (test_data->s, test_data->node, "write-enable")); 500188052a1SIris Chen 501975d4bafSJamin Lin spi_ctrl_start_user(test_data); 502975d4bafSJamin Lin flash_writeb(test_data, 0, WRDI); 503975d4bafSJamin Lin flash_writeb(test_data, 0, RDSR); 504975d4bafSJamin Lin r = flash_readb(test_data, 0); 505975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 506188052a1SIris Chen 507188052a1SIris Chen g_assert_cmphex(r & SR_WEL, ==, 0); 508188052a1SIris Chen g_assert(!qtest_qom_get_bool 509dc32f5baSJamin Lin (test_data->s, test_data->node, "write-enable")); 510188052a1SIris Chen 511975d4bafSJamin Lin flash_reset(test_data); 512188052a1SIris Chen } 513188052a1SIris Chen 514975d4bafSJamin Lin static void test_status_reg_write_protection(const void *data) 5151de51272SIris Chen { 516975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 5171de51272SIris Chen uint8_t r; 5181de51272SIris Chen 519dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 5201de51272SIris Chen 5211de51272SIris Chen /* default case: WP# is high and SRWD is low -> status register writable */ 522975d4bafSJamin Lin spi_ctrl_start_user(test_data); 523975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 5241de51272SIris Chen /* test ability to write SRWD */ 525975d4bafSJamin Lin flash_writeb(test_data, 0, WRSR); 526975d4bafSJamin Lin flash_writeb(test_data, 0, SRWD); 527975d4bafSJamin Lin flash_writeb(test_data, 0, RDSR); 528975d4bafSJamin Lin r = flash_readb(test_data, 0); 529975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 5301de51272SIris Chen g_assert_cmphex(r & SRWD, ==, SRWD); 5311de51272SIris Chen 5321de51272SIris Chen /* WP# high and SRWD high -> status register writable */ 533975d4bafSJamin Lin spi_ctrl_start_user(test_data); 534975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 5351de51272SIris Chen /* test ability to write SRWD */ 536975d4bafSJamin Lin flash_writeb(test_data, 0, WRSR); 537975d4bafSJamin Lin flash_writeb(test_data, 0, 0); 538975d4bafSJamin Lin flash_writeb(test_data, 0, RDSR); 539975d4bafSJamin Lin r = flash_readb(test_data, 0); 540975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 5411de51272SIris Chen g_assert_cmphex(r & SRWD, ==, 0); 5421de51272SIris Chen 5431de51272SIris Chen /* WP# low and SRWD low -> status register writable */ 544dc32f5baSJamin Lin qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 0); 545975d4bafSJamin Lin spi_ctrl_start_user(test_data); 546975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 5471de51272SIris Chen /* test ability to write SRWD */ 548975d4bafSJamin Lin flash_writeb(test_data, 0, WRSR); 549975d4bafSJamin Lin flash_writeb(test_data, 0, SRWD); 550975d4bafSJamin Lin flash_writeb(test_data, 0, RDSR); 551975d4bafSJamin Lin r = flash_readb(test_data, 0); 552975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 5531de51272SIris Chen g_assert_cmphex(r & SRWD, ==, SRWD); 5541de51272SIris Chen 5551de51272SIris Chen /* WP# low and SRWD high -> status register NOT writable */ 556975d4bafSJamin Lin spi_ctrl_start_user(test_data); 557975d4bafSJamin Lin flash_writeb(test_data, 0 , WREN); 5581de51272SIris Chen /* test ability to write SRWD */ 559975d4bafSJamin Lin flash_writeb(test_data, 0, WRSR); 560975d4bafSJamin Lin flash_writeb(test_data, 0, 0); 561975d4bafSJamin Lin flash_writeb(test_data, 0, RDSR); 562975d4bafSJamin Lin r = flash_readb(test_data, 0); 563975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 5641de51272SIris Chen /* write is not successful */ 5651de51272SIris Chen g_assert_cmphex(r & SRWD, ==, SRWD); 5661de51272SIris Chen 567dc32f5baSJamin Lin qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 1); 568975d4bafSJamin Lin flash_reset(test_data); 5691de51272SIris Chen } 5701de51272SIris Chen 571975d4bafSJamin Lin static void test_write_block_protect(const void *data) 5728abf9ba4SIris Chen { 573975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 5748abf9ba4SIris Chen uint32_t sector_size = 65536; 5758abf9ba4SIris Chen uint32_t n_sectors = 512; 5768abf9ba4SIris Chen 577dc32f5baSJamin Lin spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); 578dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 5798abf9ba4SIris Chen 5808abf9ba4SIris Chen uint32_t bp_bits = 0b0; 5818abf9ba4SIris Chen 5828abf9ba4SIris Chen for (int i = 0; i < 16; i++) { 5838abf9ba4SIris Chen bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2); 5848abf9ba4SIris Chen 585975d4bafSJamin Lin spi_ctrl_start_user(test_data); 586975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 587975d4bafSJamin Lin flash_writeb(test_data, 0, BULK_ERASE); 588975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 589975d4bafSJamin Lin flash_writeb(test_data, 0, WRSR); 590975d4bafSJamin Lin flash_writeb(test_data, 0, bp_bits); 591975d4bafSJamin Lin flash_writeb(test_data, 0, EN_4BYTE_ADDR); 592975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 593975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 5948abf9ba4SIris Chen 5958abf9ba4SIris Chen uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; 5968abf9ba4SIris Chen uint32_t protection_start = n_sectors - num_protected_sectors; 5978abf9ba4SIris Chen uint32_t protection_end = n_sectors; 5988abf9ba4SIris Chen 5998abf9ba4SIris Chen for (int sector = 0; sector < n_sectors; sector++) { 6008abf9ba4SIris Chen uint32_t addr = sector * sector_size; 6018abf9ba4SIris Chen 602975d4bafSJamin Lin assert_page_mem(test_data, addr, 0xffffffff); 603975d4bafSJamin Lin write_page_mem(test_data, addr, make_be32(0xabcdef12)); 6048abf9ba4SIris Chen 6058abf9ba4SIris Chen uint32_t expected_value = protection_start <= sector 6068abf9ba4SIris Chen && sector < protection_end 6078abf9ba4SIris Chen ? 0xffffffff : 0xabcdef12; 6088abf9ba4SIris Chen 609975d4bafSJamin Lin assert_page_mem(test_data, addr, expected_value); 6108abf9ba4SIris Chen } 6118abf9ba4SIris Chen } 6128abf9ba4SIris Chen 613975d4bafSJamin Lin flash_reset(test_data); 6148abf9ba4SIris Chen } 6158abf9ba4SIris Chen 616975d4bafSJamin Lin static void test_write_block_protect_bottom_bit(const void *data) 6178abf9ba4SIris Chen { 618975d4bafSJamin Lin const TestData *test_data = (const TestData *)data; 6198abf9ba4SIris Chen uint32_t sector_size = 65536; 6208abf9ba4SIris Chen uint32_t n_sectors = 512; 6218abf9ba4SIris Chen 622dc32f5baSJamin Lin spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); 623dc32f5baSJamin Lin spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 6248abf9ba4SIris Chen 6258abf9ba4SIris Chen /* top bottom bit is enabled */ 6268abf9ba4SIris Chen uint32_t bp_bits = 0b00100 << 3; 6278abf9ba4SIris Chen 6288abf9ba4SIris Chen for (int i = 0; i < 16; i++) { 6298abf9ba4SIris Chen bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2); 6308abf9ba4SIris Chen 631975d4bafSJamin Lin spi_ctrl_start_user(test_data); 632975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 633975d4bafSJamin Lin flash_writeb(test_data, 0, BULK_ERASE); 634975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 635975d4bafSJamin Lin flash_writeb(test_data, 0, WRSR); 636975d4bafSJamin Lin flash_writeb(test_data, 0, bp_bits); 637975d4bafSJamin Lin flash_writeb(test_data, 0, EN_4BYTE_ADDR); 638975d4bafSJamin Lin flash_writeb(test_data, 0, WREN); 639975d4bafSJamin Lin spi_ctrl_stop_user(test_data); 6408abf9ba4SIris Chen 6418abf9ba4SIris Chen uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; 6428abf9ba4SIris Chen uint32_t protection_start = 0; 6438abf9ba4SIris Chen uint32_t protection_end = num_protected_sectors; 6448abf9ba4SIris Chen 6458abf9ba4SIris Chen for (int sector = 0; sector < n_sectors; sector++) { 6468abf9ba4SIris Chen uint32_t addr = sector * sector_size; 6478abf9ba4SIris Chen 648975d4bafSJamin Lin assert_page_mem(test_data, addr, 0xffffffff); 649975d4bafSJamin Lin write_page_mem(test_data, addr, make_be32(0xabcdef12)); 6508abf9ba4SIris Chen 6518abf9ba4SIris Chen uint32_t expected_value = protection_start <= sector 6528abf9ba4SIris Chen && sector < protection_end 6538abf9ba4SIris Chen ? 0xffffffff : 0xabcdef12; 6548abf9ba4SIris Chen 655975d4bafSJamin Lin assert_page_mem(test_data, addr, expected_value); 6568abf9ba4SIris Chen } 6578abf9ba4SIris Chen } 6588abf9ba4SIris Chen 659975d4bafSJamin Lin flash_reset(test_data); 6608abf9ba4SIris Chen } 6618abf9ba4SIris Chen 662975d4bafSJamin Lin static void test_palmetto_bmc(TestData *data) 6637a2334f7SCédric Le Goater { 6647a2334f7SCédric Le Goater int ret; 6657a2334f7SCédric Le Goater int fd; 6667a2334f7SCédric Le Goater 667975d4bafSJamin Lin fd = g_file_open_tmp("qtest.m25p80.n25q256a.XXXXXX", &data->tmp_path, NULL); 6687a2334f7SCédric Le Goater g_assert(fd >= 0); 669975d4bafSJamin Lin ret = ftruncate(fd, 32 * 1024 * 1024); 6707a2334f7SCédric Le Goater g_assert(ret == 0); 6717a2334f7SCédric Le Goater close(fd); 6727a2334f7SCédric Le Goater 673975d4bafSJamin Lin data->s = qtest_initf("-m 256 -machine palmetto-bmc " 6747a2334f7SCédric Le Goater "-drive file=%s,format=raw,if=mtd", 675975d4bafSJamin Lin data->tmp_path); 6767a2334f7SCédric Le Goater 677975d4bafSJamin Lin /* fmc cs0 with n25q256a flash */ 678975d4bafSJamin Lin data->flash_base = 0x20000000; 679975d4bafSJamin Lin data->spi_base = 0x1E620000; 680975d4bafSJamin Lin data->jedec_id = 0x20ba19; 681dc32f5baSJamin Lin data->cs = 0; 682dc32f5baSJamin Lin data->node = "/machine/soc/fmc/ssi.0/child[0]"; 683369a47aeSJamin Lin /* beyond 16MB */ 684369a47aeSJamin Lin data->page_addr = 0x14000 * FLASH_PAGE_SIZE; 6857a2334f7SCédric Le Goater 686975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/read_jedec", data, test_read_jedec); 687975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/erase_sector", data, test_erase_sector); 688975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/erase_all", data, test_erase_all); 689975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/write_page", data, test_write_page); 690975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/read_page_mem", 691975d4bafSJamin Lin data, test_read_page_mem); 692975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/write_page_mem", 693975d4bafSJamin Lin data, test_write_page_mem); 694975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/read_status_reg", 695975d4bafSJamin Lin data, test_read_status_reg); 696975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/status_reg_write_protection", 697975d4bafSJamin Lin data, test_status_reg_write_protection); 698975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/write_block_protect", 699975d4bafSJamin Lin data, test_write_block_protect); 700975d4bafSJamin Lin qtest_add_data_func("/ast2400/smc/write_block_protect_bottom_bit", 701975d4bafSJamin Lin data, test_write_block_protect_bottom_bit); 702755e984aSJamin Lin } 703755e984aSJamin Lin 704658ebe13SJamin Lin static void test_ast2500_evb(TestData *data) 705658ebe13SJamin Lin { 706658ebe13SJamin Lin int ret; 707658ebe13SJamin Lin int fd; 708658ebe13SJamin Lin 709658ebe13SJamin Lin fd = g_file_open_tmp("qtest.m25p80.mx25l25635e.XXXXXX", 710658ebe13SJamin Lin &data->tmp_path, NULL); 711658ebe13SJamin Lin g_assert(fd >= 0); 712658ebe13SJamin Lin ret = ftruncate(fd, 32 * 1024 * 1024); 713658ebe13SJamin Lin g_assert(ret == 0); 714658ebe13SJamin Lin close(fd); 715658ebe13SJamin Lin 716658ebe13SJamin Lin data->s = qtest_initf("-machine ast2500-evb " 717658ebe13SJamin Lin "-drive file=%s,format=raw,if=mtd", 718658ebe13SJamin Lin data->tmp_path); 719658ebe13SJamin Lin 720658ebe13SJamin Lin /* fmc cs0 with mx25l25635e flash */ 721658ebe13SJamin Lin data->flash_base = 0x20000000; 722658ebe13SJamin Lin data->spi_base = 0x1E620000; 723658ebe13SJamin Lin data->jedec_id = 0xc22019; 724658ebe13SJamin Lin data->cs = 0; 725658ebe13SJamin Lin data->node = "/machine/soc/fmc/ssi.0/child[0]"; 726658ebe13SJamin Lin /* beyond 16MB */ 727658ebe13SJamin Lin data->page_addr = 0x14000 * FLASH_PAGE_SIZE; 728658ebe13SJamin Lin 729658ebe13SJamin Lin qtest_add_data_func("/ast2500/smc/read_jedec", data, test_read_jedec); 730658ebe13SJamin Lin qtest_add_data_func("/ast2500/smc/erase_sector", data, test_erase_sector); 731658ebe13SJamin Lin qtest_add_data_func("/ast2500/smc/erase_all", data, test_erase_all); 732658ebe13SJamin Lin qtest_add_data_func("/ast2500/smc/write_page", data, test_write_page); 733658ebe13SJamin Lin qtest_add_data_func("/ast2500/smc/read_page_mem", 734658ebe13SJamin Lin data, test_read_page_mem); 735658ebe13SJamin Lin qtest_add_data_func("/ast2500/smc/write_page_mem", 736658ebe13SJamin Lin data, test_write_page_mem); 737658ebe13SJamin Lin qtest_add_data_func("/ast2500/smc/read_status_reg", 738658ebe13SJamin Lin data, test_read_status_reg); 739658ebe13SJamin Lin } 740*84f7ea6dSJamin Lin 741*84f7ea6dSJamin Lin static void test_ast2600_evb(TestData *data) 742*84f7ea6dSJamin Lin { 743*84f7ea6dSJamin Lin int ret; 744*84f7ea6dSJamin Lin int fd; 745*84f7ea6dSJamin Lin 746*84f7ea6dSJamin Lin fd = g_file_open_tmp("qtest.m25p80.mx66u51235f.XXXXXX", 747*84f7ea6dSJamin Lin &data->tmp_path, NULL); 748*84f7ea6dSJamin Lin g_assert(fd >= 0); 749*84f7ea6dSJamin Lin ret = ftruncate(fd, 64 * 1024 * 1024); 750*84f7ea6dSJamin Lin g_assert(ret == 0); 751*84f7ea6dSJamin Lin close(fd); 752*84f7ea6dSJamin Lin 753*84f7ea6dSJamin Lin data->s = qtest_initf("-machine ast2600-evb " 754*84f7ea6dSJamin Lin "-drive file=%s,format=raw,if=mtd", 755*84f7ea6dSJamin Lin data->tmp_path); 756*84f7ea6dSJamin Lin 757*84f7ea6dSJamin Lin /* fmc cs0 with mx66u51235f flash */ 758*84f7ea6dSJamin Lin data->flash_base = 0x20000000; 759*84f7ea6dSJamin Lin data->spi_base = 0x1E620000; 760*84f7ea6dSJamin Lin data->jedec_id = 0xc2253a; 761*84f7ea6dSJamin Lin data->cs = 0; 762*84f7ea6dSJamin Lin data->node = "/machine/soc/fmc/ssi.0/child[0]"; 763*84f7ea6dSJamin Lin /* beyond 16MB */ 764*84f7ea6dSJamin Lin data->page_addr = 0x14000 * FLASH_PAGE_SIZE; 765*84f7ea6dSJamin Lin 766*84f7ea6dSJamin Lin qtest_add_data_func("/ast2600/smc/read_jedec", data, test_read_jedec); 767*84f7ea6dSJamin Lin qtest_add_data_func("/ast2600/smc/erase_sector", data, test_erase_sector); 768*84f7ea6dSJamin Lin qtest_add_data_func("/ast2600/smc/erase_all", data, test_erase_all); 769*84f7ea6dSJamin Lin qtest_add_data_func("/ast2600/smc/write_page", data, test_write_page); 770*84f7ea6dSJamin Lin qtest_add_data_func("/ast2600/smc/read_page_mem", 771*84f7ea6dSJamin Lin data, test_read_page_mem); 772*84f7ea6dSJamin Lin qtest_add_data_func("/ast2600/smc/write_page_mem", 773*84f7ea6dSJamin Lin data, test_write_page_mem); 774*84f7ea6dSJamin Lin qtest_add_data_func("/ast2600/smc/read_status_reg", 775*84f7ea6dSJamin Lin data, test_read_status_reg); 776*84f7ea6dSJamin Lin } 777755e984aSJamin Lin int main(int argc, char **argv) 778755e984aSJamin Lin { 779975d4bafSJamin Lin TestData palmetto_data; 780658ebe13SJamin Lin TestData ast2500_evb_data; 781*84f7ea6dSJamin Lin TestData ast2600_evb_data; 782755e984aSJamin Lin int ret; 783755e984aSJamin Lin 784755e984aSJamin Lin g_test_init(&argc, &argv, NULL); 785755e984aSJamin Lin 786975d4bafSJamin Lin test_palmetto_bmc(&palmetto_data); 787658ebe13SJamin Lin test_ast2500_evb(&ast2500_evb_data); 788*84f7ea6dSJamin Lin test_ast2600_evb(&ast2600_evb_data); 789975d4bafSJamin Lin ret = g_test_run(); 790975d4bafSJamin Lin 791975d4bafSJamin Lin qtest_quit(palmetto_data.s); 792658ebe13SJamin Lin qtest_quit(ast2500_evb_data.s); 793*84f7ea6dSJamin Lin qtest_quit(ast2600_evb_data.s); 794975d4bafSJamin Lin unlink(palmetto_data.tmp_path); 795658ebe13SJamin Lin unlink(ast2500_evb_data.tmp_path); 796*84f7ea6dSJamin Lin unlink(ast2600_evb_data.tmp_path); 7977a2334f7SCédric Le Goater return ret; 7987a2334f7SCédric Le Goater } 799