1 /* 2 * QTest testcase for the M25P80 Flash (Using the Aspeed SPI 3 * Controller) 4 * 5 * Copyright (C) 2016 IBM Corp. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include "qemu/osdep.h" 27 #include "qemu/bswap.h" 28 #include "libqtest-single.h" 29 #include "qemu/bitops.h" 30 31 /* 32 * ASPEED SPI Controller registers 33 */ 34 #define R_CONF 0x00 35 #define CONF_ENABLE_W0 (1 << 16) 36 #define R_CE_CTRL 0x04 37 #define CRTL_EXTENDED0 0 /* 32 bit addressing for SPI */ 38 #define R_CTRL0 0x10 39 #define CTRL_CE_STOP_ACTIVE (1 << 2) 40 #define CTRL_READMODE 0x0 41 #define CTRL_FREADMODE 0x1 42 #define CTRL_WRITEMODE 0x2 43 #define CTRL_USERMODE 0x3 44 #define SR_WEL BIT(1) 45 46 #define ASPEED_FMC_BASE 0x1E620000 47 #define ASPEED_FLASH_BASE 0x20000000 48 49 /* 50 * Flash commands 51 */ 52 enum { 53 JEDEC_READ = 0x9f, 54 RDSR = 0x5, 55 WRDI = 0x4, 56 BULK_ERASE = 0xc7, 57 READ = 0x03, 58 PP = 0x02, 59 WRSR = 0x1, 60 WREN = 0x6, 61 SRWD = 0x80, 62 RESET_ENABLE = 0x66, 63 RESET_MEMORY = 0x99, 64 EN_4BYTE_ADDR = 0xB7, 65 ERASE_SECTOR = 0xd8, 66 }; 67 68 #define FLASH_JEDEC 0x20ba19 /* n25q256a */ 69 #define FLASH_SIZE (32 * 1024 * 1024) 70 71 #define FLASH_PAGE_SIZE 256 72 73 /* 74 * Use an explicit bswap for the values read/wrote to the flash region 75 * as they are BE and the Aspeed CPU is LE. 76 */ 77 static inline uint32_t make_be32(uint32_t data) 78 { 79 return bswap32(data); 80 } 81 82 static void spi_conf(uint32_t value) 83 { 84 uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF); 85 86 conf |= value; 87 writel(ASPEED_FMC_BASE + R_CONF, conf); 88 } 89 90 static void spi_conf_remove(uint32_t value) 91 { 92 uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF); 93 94 conf &= ~value; 95 writel(ASPEED_FMC_BASE + R_CONF, conf); 96 } 97 98 static void spi_ce_ctrl(uint32_t value) 99 { 100 uint32_t conf = readl(ASPEED_FMC_BASE + R_CE_CTRL); 101 102 conf |= value; 103 writel(ASPEED_FMC_BASE + R_CE_CTRL, conf); 104 } 105 106 static void spi_ctrl_setmode(uint8_t mode, uint8_t cmd) 107 { 108 uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0); 109 ctrl &= ~(CTRL_USERMODE | 0xff << 16); 110 ctrl |= mode | (cmd << 16); 111 writel(ASPEED_FMC_BASE + R_CTRL0, ctrl); 112 } 113 114 static void spi_ctrl_start_user(void) 115 { 116 uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0); 117 118 ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; 119 writel(ASPEED_FMC_BASE + R_CTRL0, ctrl); 120 121 ctrl &= ~CTRL_CE_STOP_ACTIVE; 122 writel(ASPEED_FMC_BASE + R_CTRL0, ctrl); 123 } 124 125 static void spi_ctrl_stop_user(void) 126 { 127 uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0); 128 129 ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; 130 writel(ASPEED_FMC_BASE + R_CTRL0, ctrl); 131 } 132 133 static void flash_reset(void) 134 { 135 spi_conf(CONF_ENABLE_W0); 136 137 spi_ctrl_start_user(); 138 writeb(ASPEED_FLASH_BASE, RESET_ENABLE); 139 writeb(ASPEED_FLASH_BASE, RESET_MEMORY); 140 writeb(ASPEED_FLASH_BASE, WREN); 141 writeb(ASPEED_FLASH_BASE, BULK_ERASE); 142 writeb(ASPEED_FLASH_BASE, WRDI); 143 spi_ctrl_stop_user(); 144 145 spi_conf_remove(CONF_ENABLE_W0); 146 } 147 148 static void test_read_jedec(void) 149 { 150 uint32_t jedec = 0x0; 151 152 spi_conf(CONF_ENABLE_W0); 153 154 spi_ctrl_start_user(); 155 writeb(ASPEED_FLASH_BASE, JEDEC_READ); 156 jedec |= readb(ASPEED_FLASH_BASE) << 16; 157 jedec |= readb(ASPEED_FLASH_BASE) << 8; 158 jedec |= readb(ASPEED_FLASH_BASE); 159 spi_ctrl_stop_user(); 160 161 flash_reset(); 162 163 g_assert_cmphex(jedec, ==, FLASH_JEDEC); 164 } 165 166 static void read_page(uint32_t addr, uint32_t *page) 167 { 168 int i; 169 170 spi_ctrl_start_user(); 171 172 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 173 writeb(ASPEED_FLASH_BASE, READ); 174 writel(ASPEED_FLASH_BASE, make_be32(addr)); 175 176 /* Continuous read are supported */ 177 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 178 page[i] = make_be32(readl(ASPEED_FLASH_BASE)); 179 } 180 spi_ctrl_stop_user(); 181 } 182 183 static void read_page_mem(uint32_t addr, uint32_t *page) 184 { 185 int i; 186 187 /* move out USER mode to use direct reads from the AHB bus */ 188 spi_ctrl_setmode(CTRL_READMODE, READ); 189 190 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 191 page[i] = make_be32(readl(ASPEED_FLASH_BASE + addr + i * 4)); 192 } 193 } 194 195 static void write_page_mem(uint32_t addr, uint32_t write_value) 196 { 197 spi_ctrl_setmode(CTRL_WRITEMODE, PP); 198 199 for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 200 writel(ASPEED_FLASH_BASE + addr + i * 4, write_value); 201 } 202 } 203 204 static void assert_page_mem(uint32_t addr, uint32_t expected_value) 205 { 206 uint32_t page[FLASH_PAGE_SIZE / 4]; 207 read_page_mem(addr, page); 208 for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 209 g_assert_cmphex(page[i], ==, expected_value); 210 } 211 } 212 213 static void test_erase_sector(void) 214 { 215 uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE; 216 uint32_t page[FLASH_PAGE_SIZE / 4]; 217 int i; 218 219 spi_conf(CONF_ENABLE_W0); 220 221 /* 222 * Previous page should be full of 0xffs after backend is 223 * initialized 224 */ 225 read_page(some_page_addr - FLASH_PAGE_SIZE, page); 226 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 227 g_assert_cmphex(page[i], ==, 0xffffffff); 228 } 229 230 spi_ctrl_start_user(); 231 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 232 writeb(ASPEED_FLASH_BASE, WREN); 233 writeb(ASPEED_FLASH_BASE, PP); 234 writel(ASPEED_FLASH_BASE, make_be32(some_page_addr)); 235 236 /* Fill the page with its own addresses */ 237 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 238 writel(ASPEED_FLASH_BASE, make_be32(some_page_addr + i * 4)); 239 } 240 spi_ctrl_stop_user(); 241 242 /* Check the page is correctly written */ 243 read_page(some_page_addr, page); 244 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 245 g_assert_cmphex(page[i], ==, some_page_addr + i * 4); 246 } 247 248 spi_ctrl_start_user(); 249 writeb(ASPEED_FLASH_BASE, WREN); 250 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 251 writeb(ASPEED_FLASH_BASE, ERASE_SECTOR); 252 writel(ASPEED_FLASH_BASE, make_be32(some_page_addr)); 253 spi_ctrl_stop_user(); 254 255 /* Check the page is erased */ 256 read_page(some_page_addr, page); 257 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 258 g_assert_cmphex(page[i], ==, 0xffffffff); 259 } 260 261 flash_reset(); 262 } 263 264 static void test_erase_all(void) 265 { 266 uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; 267 uint32_t page[FLASH_PAGE_SIZE / 4]; 268 int i; 269 270 spi_conf(CONF_ENABLE_W0); 271 272 /* 273 * Previous page should be full of 0xffs after backend is 274 * initialized 275 */ 276 read_page(some_page_addr - FLASH_PAGE_SIZE, page); 277 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 278 g_assert_cmphex(page[i], ==, 0xffffffff); 279 } 280 281 spi_ctrl_start_user(); 282 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 283 writeb(ASPEED_FLASH_BASE, WREN); 284 writeb(ASPEED_FLASH_BASE, PP); 285 writel(ASPEED_FLASH_BASE, make_be32(some_page_addr)); 286 287 /* Fill the page with its own addresses */ 288 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 289 writel(ASPEED_FLASH_BASE, make_be32(some_page_addr + i * 4)); 290 } 291 spi_ctrl_stop_user(); 292 293 /* Check the page is correctly written */ 294 read_page(some_page_addr, page); 295 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 296 g_assert_cmphex(page[i], ==, some_page_addr + i * 4); 297 } 298 299 spi_ctrl_start_user(); 300 writeb(ASPEED_FLASH_BASE, WREN); 301 writeb(ASPEED_FLASH_BASE, BULK_ERASE); 302 spi_ctrl_stop_user(); 303 304 /* Check the page is erased */ 305 read_page(some_page_addr, page); 306 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 307 g_assert_cmphex(page[i], ==, 0xffffffff); 308 } 309 310 flash_reset(); 311 } 312 313 static void test_write_page(void) 314 { 315 uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */ 316 uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; 317 uint32_t page[FLASH_PAGE_SIZE / 4]; 318 int i; 319 320 spi_conf(CONF_ENABLE_W0); 321 322 spi_ctrl_start_user(); 323 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 324 writeb(ASPEED_FLASH_BASE, WREN); 325 writeb(ASPEED_FLASH_BASE, PP); 326 writel(ASPEED_FLASH_BASE, make_be32(my_page_addr)); 327 328 /* Fill the page with its own addresses */ 329 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 330 writel(ASPEED_FLASH_BASE, make_be32(my_page_addr + i * 4)); 331 } 332 spi_ctrl_stop_user(); 333 334 /* Check what was written */ 335 read_page(my_page_addr, page); 336 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 337 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 338 } 339 340 /* Check some other page. It should be full of 0xff */ 341 read_page(some_page_addr, page); 342 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 343 g_assert_cmphex(page[i], ==, 0xffffffff); 344 } 345 346 flash_reset(); 347 } 348 349 static void test_read_page_mem(void) 350 { 351 uint32_t my_page_addr = 0x14000 * FLASH_PAGE_SIZE; /* beyond 16MB */ 352 uint32_t some_page_addr = 0x15000 * FLASH_PAGE_SIZE; 353 uint32_t page[FLASH_PAGE_SIZE / 4]; 354 int i; 355 356 /* 357 * Enable 4BYTE mode for controller. This is should be strapped by 358 * HW for CE0 anyhow. 359 */ 360 spi_ce_ctrl(1 << CRTL_EXTENDED0); 361 362 /* Enable 4BYTE mode for flash. */ 363 spi_conf(CONF_ENABLE_W0); 364 spi_ctrl_start_user(); 365 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 366 writeb(ASPEED_FLASH_BASE, WREN); 367 writeb(ASPEED_FLASH_BASE, PP); 368 writel(ASPEED_FLASH_BASE, make_be32(my_page_addr)); 369 370 /* Fill the page with its own addresses */ 371 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 372 writel(ASPEED_FLASH_BASE, make_be32(my_page_addr + i * 4)); 373 } 374 spi_ctrl_stop_user(); 375 spi_conf_remove(CONF_ENABLE_W0); 376 377 /* Check what was written */ 378 read_page_mem(my_page_addr, page); 379 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 380 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 381 } 382 383 /* Check some other page. It should be full of 0xff */ 384 read_page_mem(some_page_addr, page); 385 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 386 g_assert_cmphex(page[i], ==, 0xffffffff); 387 } 388 389 flash_reset(); 390 } 391 392 static void test_write_page_mem(void) 393 { 394 uint32_t my_page_addr = 0x15000 * FLASH_PAGE_SIZE; 395 uint32_t page[FLASH_PAGE_SIZE / 4]; 396 int i; 397 398 /* 399 * Enable 4BYTE mode for controller. This is should be strapped by 400 * HW for CE0 anyhow. 401 */ 402 spi_ce_ctrl(1 << CRTL_EXTENDED0); 403 404 /* Enable 4BYTE mode for flash. */ 405 spi_conf(CONF_ENABLE_W0); 406 spi_ctrl_start_user(); 407 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 408 writeb(ASPEED_FLASH_BASE, WREN); 409 spi_ctrl_stop_user(); 410 411 /* move out USER mode to use direct writes to the AHB bus */ 412 spi_ctrl_setmode(CTRL_WRITEMODE, PP); 413 414 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 415 writel(ASPEED_FLASH_BASE + my_page_addr + i * 4, 416 make_be32(my_page_addr + i * 4)); 417 } 418 419 /* Check what was written */ 420 read_page_mem(my_page_addr, page); 421 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 422 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 423 } 424 425 flash_reset(); 426 } 427 428 static void test_read_status_reg(void) 429 { 430 uint8_t r; 431 432 spi_conf(CONF_ENABLE_W0); 433 434 spi_ctrl_start_user(); 435 writeb(ASPEED_FLASH_BASE, RDSR); 436 r = readb(ASPEED_FLASH_BASE); 437 spi_ctrl_stop_user(); 438 439 g_assert_cmphex(r & SR_WEL, ==, 0); 440 g_assert(!qtest_qom_get_bool 441 (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); 442 443 spi_ctrl_start_user(); 444 writeb(ASPEED_FLASH_BASE, WREN); 445 writeb(ASPEED_FLASH_BASE, RDSR); 446 r = readb(ASPEED_FLASH_BASE); 447 spi_ctrl_stop_user(); 448 449 g_assert_cmphex(r & SR_WEL, ==, SR_WEL); 450 g_assert(qtest_qom_get_bool 451 (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); 452 453 spi_ctrl_start_user(); 454 writeb(ASPEED_FLASH_BASE, WRDI); 455 writeb(ASPEED_FLASH_BASE, RDSR); 456 r = readb(ASPEED_FLASH_BASE); 457 spi_ctrl_stop_user(); 458 459 g_assert_cmphex(r & SR_WEL, ==, 0); 460 g_assert(!qtest_qom_get_bool 461 (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); 462 463 flash_reset(); 464 } 465 466 static void test_status_reg_write_protection(void) 467 { 468 uint8_t r; 469 470 spi_conf(CONF_ENABLE_W0); 471 472 /* default case: WP# is high and SRWD is low -> status register writable */ 473 spi_ctrl_start_user(); 474 writeb(ASPEED_FLASH_BASE, WREN); 475 /* test ability to write SRWD */ 476 writeb(ASPEED_FLASH_BASE, WRSR); 477 writeb(ASPEED_FLASH_BASE, SRWD); 478 writeb(ASPEED_FLASH_BASE, RDSR); 479 r = readb(ASPEED_FLASH_BASE); 480 spi_ctrl_stop_user(); 481 g_assert_cmphex(r & SRWD, ==, SRWD); 482 483 /* WP# high and SRWD high -> status register writable */ 484 spi_ctrl_start_user(); 485 writeb(ASPEED_FLASH_BASE, WREN); 486 /* test ability to write SRWD */ 487 writeb(ASPEED_FLASH_BASE, WRSR); 488 writeb(ASPEED_FLASH_BASE, 0); 489 writeb(ASPEED_FLASH_BASE, RDSR); 490 r = readb(ASPEED_FLASH_BASE); 491 spi_ctrl_stop_user(); 492 g_assert_cmphex(r & SRWD, ==, 0); 493 494 /* WP# low and SRWD low -> status register writable */ 495 qtest_set_irq_in(global_qtest, 496 "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 0); 497 spi_ctrl_start_user(); 498 writeb(ASPEED_FLASH_BASE, WREN); 499 /* test ability to write SRWD */ 500 writeb(ASPEED_FLASH_BASE, WRSR); 501 writeb(ASPEED_FLASH_BASE, SRWD); 502 writeb(ASPEED_FLASH_BASE, RDSR); 503 r = readb(ASPEED_FLASH_BASE); 504 spi_ctrl_stop_user(); 505 g_assert_cmphex(r & SRWD, ==, SRWD); 506 507 /* WP# low and SRWD high -> status register NOT writable */ 508 spi_ctrl_start_user(); 509 writeb(ASPEED_FLASH_BASE, WREN); 510 /* test ability to write SRWD */ 511 writeb(ASPEED_FLASH_BASE, WRSR); 512 writeb(ASPEED_FLASH_BASE, 0); 513 writeb(ASPEED_FLASH_BASE, RDSR); 514 r = readb(ASPEED_FLASH_BASE); 515 spi_ctrl_stop_user(); 516 /* write is not successful */ 517 g_assert_cmphex(r & SRWD, ==, SRWD); 518 519 qtest_set_irq_in(global_qtest, 520 "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 1); 521 flash_reset(); 522 } 523 524 static void test_write_block_protect(void) 525 { 526 uint32_t sector_size = 65536; 527 uint32_t n_sectors = 512; 528 529 spi_ce_ctrl(1 << CRTL_EXTENDED0); 530 spi_conf(CONF_ENABLE_W0); 531 532 uint32_t bp_bits = 0b0; 533 534 for (int i = 0; i < 16; i++) { 535 bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2); 536 537 spi_ctrl_start_user(); 538 writeb(ASPEED_FLASH_BASE, WREN); 539 writeb(ASPEED_FLASH_BASE, BULK_ERASE); 540 writeb(ASPEED_FLASH_BASE, WREN); 541 writeb(ASPEED_FLASH_BASE, WRSR); 542 writeb(ASPEED_FLASH_BASE, bp_bits); 543 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 544 writeb(ASPEED_FLASH_BASE, WREN); 545 spi_ctrl_stop_user(); 546 547 uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; 548 uint32_t protection_start = n_sectors - num_protected_sectors; 549 uint32_t protection_end = n_sectors; 550 551 for (int sector = 0; sector < n_sectors; sector++) { 552 uint32_t addr = sector * sector_size; 553 554 assert_page_mem(addr, 0xffffffff); 555 write_page_mem(addr, make_be32(0xabcdef12)); 556 557 uint32_t expected_value = protection_start <= sector 558 && sector < protection_end 559 ? 0xffffffff : 0xabcdef12; 560 561 assert_page_mem(addr, expected_value); 562 } 563 } 564 565 flash_reset(); 566 } 567 568 static void test_write_block_protect_bottom_bit(void) 569 { 570 uint32_t sector_size = 65536; 571 uint32_t n_sectors = 512; 572 573 spi_ce_ctrl(1 << CRTL_EXTENDED0); 574 spi_conf(CONF_ENABLE_W0); 575 576 /* top bottom bit is enabled */ 577 uint32_t bp_bits = 0b00100 << 3; 578 579 for (int i = 0; i < 16; i++) { 580 bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2); 581 582 spi_ctrl_start_user(); 583 writeb(ASPEED_FLASH_BASE, WREN); 584 writeb(ASPEED_FLASH_BASE, BULK_ERASE); 585 writeb(ASPEED_FLASH_BASE, WREN); 586 writeb(ASPEED_FLASH_BASE, WRSR); 587 writeb(ASPEED_FLASH_BASE, bp_bits); 588 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 589 writeb(ASPEED_FLASH_BASE, WREN); 590 spi_ctrl_stop_user(); 591 592 uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; 593 uint32_t protection_start = 0; 594 uint32_t protection_end = num_protected_sectors; 595 596 for (int sector = 0; sector < n_sectors; sector++) { 597 uint32_t addr = sector * sector_size; 598 599 assert_page_mem(addr, 0xffffffff); 600 write_page_mem(addr, make_be32(0xabcdef12)); 601 602 uint32_t expected_value = protection_start <= sector 603 && sector < protection_end 604 ? 0xffffffff : 0xabcdef12; 605 606 assert_page_mem(addr, expected_value); 607 } 608 } 609 610 flash_reset(); 611 } 612 613 int main(int argc, char **argv) 614 { 615 g_autofree char *tmp_path = NULL; 616 int ret; 617 int fd; 618 619 g_test_init(&argc, &argv, NULL); 620 621 fd = g_file_open_tmp("qtest.m25p80.XXXXXX", &tmp_path, NULL); 622 g_assert(fd >= 0); 623 ret = ftruncate(fd, FLASH_SIZE); 624 g_assert(ret == 0); 625 close(fd); 626 627 global_qtest = qtest_initf("-m 256 -machine palmetto-bmc " 628 "-drive file=%s,format=raw,if=mtd", 629 tmp_path); 630 631 qtest_add_func("/ast2400/smc/read_jedec", test_read_jedec); 632 qtest_add_func("/ast2400/smc/erase_sector", test_erase_sector); 633 qtest_add_func("/ast2400/smc/erase_all", test_erase_all); 634 qtest_add_func("/ast2400/smc/write_page", test_write_page); 635 qtest_add_func("/ast2400/smc/read_page_mem", test_read_page_mem); 636 qtest_add_func("/ast2400/smc/write_page_mem", test_write_page_mem); 637 qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg); 638 qtest_add_func("/ast2400/smc/status_reg_write_protection", 639 test_status_reg_write_protection); 640 qtest_add_func("/ast2400/smc/write_block_protect", 641 test_write_block_protect); 642 qtest_add_func("/ast2400/smc/write_block_protect_bottom_bit", 643 test_write_block_protect_bottom_bit); 644 645 flash_reset(); 646 ret = g_test_run(); 647 648 qtest_quit(global_qtest); 649 unlink(tmp_path); 650 return ret; 651 } 652