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 /* Enable 4BYTE mode for controller. This is should be strapped by 357 * HW for CE0 anyhow. 358 */ 359 spi_ce_ctrl(1 << CRTL_EXTENDED0); 360 361 /* Enable 4BYTE mode for flash. */ 362 spi_conf(CONF_ENABLE_W0); 363 spi_ctrl_start_user(); 364 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 365 writeb(ASPEED_FLASH_BASE, WREN); 366 writeb(ASPEED_FLASH_BASE, PP); 367 writel(ASPEED_FLASH_BASE, make_be32(my_page_addr)); 368 369 /* Fill the page with its own addresses */ 370 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 371 writel(ASPEED_FLASH_BASE, make_be32(my_page_addr + i * 4)); 372 } 373 spi_ctrl_stop_user(); 374 spi_conf_remove(CONF_ENABLE_W0); 375 376 /* Check what was written */ 377 read_page_mem(my_page_addr, page); 378 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 379 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 380 } 381 382 /* Check some other page. It should be full of 0xff */ 383 read_page_mem(some_page_addr, page); 384 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 385 g_assert_cmphex(page[i], ==, 0xffffffff); 386 } 387 388 flash_reset(); 389 } 390 391 static void test_write_page_mem(void) 392 { 393 uint32_t my_page_addr = 0x15000 * FLASH_PAGE_SIZE; 394 uint32_t page[FLASH_PAGE_SIZE / 4]; 395 int i; 396 397 /* Enable 4BYTE mode for controller. This is should be strapped by 398 * HW for CE0 anyhow. 399 */ 400 spi_ce_ctrl(1 << CRTL_EXTENDED0); 401 402 /* Enable 4BYTE mode for flash. */ 403 spi_conf(CONF_ENABLE_W0); 404 spi_ctrl_start_user(); 405 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 406 writeb(ASPEED_FLASH_BASE, WREN); 407 spi_ctrl_stop_user(); 408 409 /* move out USER mode to use direct writes to the AHB bus */ 410 spi_ctrl_setmode(CTRL_WRITEMODE, PP); 411 412 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 413 writel(ASPEED_FLASH_BASE + my_page_addr + i * 4, 414 make_be32(my_page_addr + i * 4)); 415 } 416 417 /* Check what was written */ 418 read_page_mem(my_page_addr, page); 419 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 420 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 421 } 422 423 flash_reset(); 424 } 425 426 static void test_read_status_reg(void) 427 { 428 uint8_t r; 429 430 spi_conf(CONF_ENABLE_W0); 431 432 spi_ctrl_start_user(); 433 writeb(ASPEED_FLASH_BASE, RDSR); 434 r = readb(ASPEED_FLASH_BASE); 435 spi_ctrl_stop_user(); 436 437 g_assert_cmphex(r & SR_WEL, ==, 0); 438 g_assert(!qtest_qom_get_bool 439 (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); 440 441 spi_ctrl_start_user(); 442 writeb(ASPEED_FLASH_BASE, WREN); 443 writeb(ASPEED_FLASH_BASE, RDSR); 444 r = readb(ASPEED_FLASH_BASE); 445 spi_ctrl_stop_user(); 446 447 g_assert_cmphex(r & SR_WEL, ==, SR_WEL); 448 g_assert(qtest_qom_get_bool 449 (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); 450 451 spi_ctrl_start_user(); 452 writeb(ASPEED_FLASH_BASE, WRDI); 453 writeb(ASPEED_FLASH_BASE, RDSR); 454 r = readb(ASPEED_FLASH_BASE); 455 spi_ctrl_stop_user(); 456 457 g_assert_cmphex(r & SR_WEL, ==, 0); 458 g_assert(!qtest_qom_get_bool 459 (global_qtest, "/machine/soc/fmc/ssi.0/child[0]", "write-enable")); 460 461 flash_reset(); 462 } 463 464 static void test_status_reg_write_protection(void) 465 { 466 uint8_t r; 467 468 spi_conf(CONF_ENABLE_W0); 469 470 /* default case: WP# is high and SRWD is low -> status register writable */ 471 spi_ctrl_start_user(); 472 writeb(ASPEED_FLASH_BASE, WREN); 473 /* test ability to write SRWD */ 474 writeb(ASPEED_FLASH_BASE, WRSR); 475 writeb(ASPEED_FLASH_BASE, SRWD); 476 writeb(ASPEED_FLASH_BASE, RDSR); 477 r = readb(ASPEED_FLASH_BASE); 478 spi_ctrl_stop_user(); 479 g_assert_cmphex(r & SRWD, ==, SRWD); 480 481 /* WP# high and SRWD high -> status register writable */ 482 spi_ctrl_start_user(); 483 writeb(ASPEED_FLASH_BASE, WREN); 484 /* test ability to write SRWD */ 485 writeb(ASPEED_FLASH_BASE, WRSR); 486 writeb(ASPEED_FLASH_BASE, 0); 487 writeb(ASPEED_FLASH_BASE, RDSR); 488 r = readb(ASPEED_FLASH_BASE); 489 spi_ctrl_stop_user(); 490 g_assert_cmphex(r & SRWD, ==, 0); 491 492 /* WP# low and SRWD low -> status register writable */ 493 qtest_set_irq_in(global_qtest, 494 "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 0); 495 spi_ctrl_start_user(); 496 writeb(ASPEED_FLASH_BASE, WREN); 497 /* test ability to write SRWD */ 498 writeb(ASPEED_FLASH_BASE, WRSR); 499 writeb(ASPEED_FLASH_BASE, SRWD); 500 writeb(ASPEED_FLASH_BASE, RDSR); 501 r = readb(ASPEED_FLASH_BASE); 502 spi_ctrl_stop_user(); 503 g_assert_cmphex(r & SRWD, ==, SRWD); 504 505 /* WP# low and SRWD high -> status register NOT writable */ 506 spi_ctrl_start_user(); 507 writeb(ASPEED_FLASH_BASE, WREN); 508 /* test ability to write SRWD */ 509 writeb(ASPEED_FLASH_BASE, WRSR); 510 writeb(ASPEED_FLASH_BASE, 0); 511 writeb(ASPEED_FLASH_BASE, RDSR); 512 r = readb(ASPEED_FLASH_BASE); 513 spi_ctrl_stop_user(); 514 /* write is not successful */ 515 g_assert_cmphex(r & SRWD, ==, SRWD); 516 517 qtest_set_irq_in(global_qtest, 518 "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 1); 519 flash_reset(); 520 } 521 522 static void test_write_block_protect(void) 523 { 524 uint32_t sector_size = 65536; 525 uint32_t n_sectors = 512; 526 527 spi_ce_ctrl(1 << CRTL_EXTENDED0); 528 spi_conf(CONF_ENABLE_W0); 529 530 uint32_t bp_bits = 0b0; 531 532 for (int i = 0; i < 16; i++) { 533 bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2); 534 535 spi_ctrl_start_user(); 536 writeb(ASPEED_FLASH_BASE, WREN); 537 writeb(ASPEED_FLASH_BASE, BULK_ERASE); 538 writeb(ASPEED_FLASH_BASE, WREN); 539 writeb(ASPEED_FLASH_BASE, WRSR); 540 writeb(ASPEED_FLASH_BASE, bp_bits); 541 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 542 writeb(ASPEED_FLASH_BASE, WREN); 543 spi_ctrl_stop_user(); 544 545 uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; 546 uint32_t protection_start = n_sectors - num_protected_sectors; 547 uint32_t protection_end = n_sectors; 548 549 for (int sector = 0; sector < n_sectors; sector++) { 550 uint32_t addr = sector * sector_size; 551 552 assert_page_mem(addr, 0xffffffff); 553 write_page_mem(addr, make_be32(0xabcdef12)); 554 555 uint32_t expected_value = protection_start <= sector 556 && sector < protection_end 557 ? 0xffffffff : 0xabcdef12; 558 559 assert_page_mem(addr, expected_value); 560 } 561 } 562 563 flash_reset(); 564 } 565 566 static void test_write_block_protect_bottom_bit(void) 567 { 568 uint32_t sector_size = 65536; 569 uint32_t n_sectors = 512; 570 571 spi_ce_ctrl(1 << CRTL_EXTENDED0); 572 spi_conf(CONF_ENABLE_W0); 573 574 /* top bottom bit is enabled */ 575 uint32_t bp_bits = 0b00100 << 3; 576 577 for (int i = 0; i < 16; i++) { 578 bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2); 579 580 spi_ctrl_start_user(); 581 writeb(ASPEED_FLASH_BASE, WREN); 582 writeb(ASPEED_FLASH_BASE, BULK_ERASE); 583 writeb(ASPEED_FLASH_BASE, WREN); 584 writeb(ASPEED_FLASH_BASE, WRSR); 585 writeb(ASPEED_FLASH_BASE, bp_bits); 586 writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); 587 writeb(ASPEED_FLASH_BASE, WREN); 588 spi_ctrl_stop_user(); 589 590 uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; 591 uint32_t protection_start = 0; 592 uint32_t protection_end = num_protected_sectors; 593 594 for (int sector = 0; sector < n_sectors; sector++) { 595 uint32_t addr = sector * sector_size; 596 597 assert_page_mem(addr, 0xffffffff); 598 write_page_mem(addr, make_be32(0xabcdef12)); 599 600 uint32_t expected_value = protection_start <= sector 601 && sector < protection_end 602 ? 0xffffffff : 0xabcdef12; 603 604 assert_page_mem(addr, expected_value); 605 } 606 } 607 608 flash_reset(); 609 } 610 611 int main(int argc, char **argv) 612 { 613 g_autofree char *tmp_path = NULL; 614 int ret; 615 int fd; 616 617 g_test_init(&argc, &argv, NULL); 618 619 fd = g_file_open_tmp("qtest.m25p80.XXXXXX", &tmp_path, NULL); 620 g_assert(fd >= 0); 621 ret = ftruncate(fd, FLASH_SIZE); 622 g_assert(ret == 0); 623 close(fd); 624 625 global_qtest = qtest_initf("-m 256 -machine palmetto-bmc " 626 "-drive file=%s,format=raw,if=mtd", 627 tmp_path); 628 629 qtest_add_func("/ast2400/smc/read_jedec", test_read_jedec); 630 qtest_add_func("/ast2400/smc/erase_sector", test_erase_sector); 631 qtest_add_func("/ast2400/smc/erase_all", test_erase_all); 632 qtest_add_func("/ast2400/smc/write_page", test_write_page); 633 qtest_add_func("/ast2400/smc/read_page_mem", test_read_page_mem); 634 qtest_add_func("/ast2400/smc/write_page_mem", test_write_page_mem); 635 qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg); 636 qtest_add_func("/ast2400/smc/status_reg_write_protection", 637 test_status_reg_write_protection); 638 qtest_add_func("/ast2400/smc/write_block_protect", 639 test_write_block_protect); 640 qtest_add_func("/ast2400/smc/write_block_protect_bottom_bit", 641 test_write_block_protect_bottom_bit); 642 643 flash_reset(); 644 ret = g_test_run(); 645 646 qtest_quit(global_qtest); 647 unlink(tmp_path); 648 return ret; 649 } 650