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 #include "aspeed-smc-utils.h" 31 32 /* 33 * Use an explicit bswap for the values read/wrote to the flash region 34 * as they are BE and the Aspeed CPU is LE. 35 */ 36 static inline uint32_t make_be32(uint32_t data) 37 { 38 return bswap32(data); 39 } 40 41 static inline void spi_writel(const AspeedSMCTestData *data, uint64_t offset, 42 uint32_t value) 43 { 44 qtest_writel(data->s, data->spi_base + offset, value); 45 } 46 47 static inline uint32_t spi_readl(const AspeedSMCTestData *data, uint64_t offset) 48 { 49 return qtest_readl(data->s, data->spi_base + offset); 50 } 51 52 static inline void flash_writeb(const AspeedSMCTestData *data, uint64_t offset, 53 uint8_t value) 54 { 55 qtest_writeb(data->s, data->flash_base + offset, value); 56 } 57 58 static inline void flash_writel(const AspeedSMCTestData *data, uint64_t offset, 59 uint32_t value) 60 { 61 qtest_writel(data->s, data->flash_base + offset, value); 62 } 63 64 static inline uint8_t flash_readb(const AspeedSMCTestData *data, 65 uint64_t offset) 66 { 67 return qtest_readb(data->s, data->flash_base + offset); 68 } 69 70 static inline uint32_t flash_readl(const AspeedSMCTestData *data, 71 uint64_t offset) 72 { 73 return qtest_readl(data->s, data->flash_base + offset); 74 } 75 76 static void spi_conf(const AspeedSMCTestData *data, uint32_t value) 77 { 78 uint32_t conf = spi_readl(data, R_CONF); 79 80 conf |= value; 81 spi_writel(data, R_CONF, conf); 82 } 83 84 static void spi_conf_remove(const AspeedSMCTestData *data, uint32_t value) 85 { 86 uint32_t conf = spi_readl(data, R_CONF); 87 88 conf &= ~value; 89 spi_writel(data, R_CONF, conf); 90 } 91 92 static void spi_ce_ctrl(const AspeedSMCTestData *data, uint32_t value) 93 { 94 uint32_t conf = spi_readl(data, R_CE_CTRL); 95 96 conf |= value; 97 spi_writel(data, R_CE_CTRL, conf); 98 } 99 100 static void spi_ctrl_setmode(const AspeedSMCTestData *data, uint8_t mode, 101 uint8_t cmd) 102 { 103 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; 104 uint32_t ctrl = spi_readl(data, ctrl_reg); 105 ctrl &= ~(CTRL_USERMODE | 0xff << 16); 106 ctrl |= mode | (cmd << 16); 107 spi_writel(data, ctrl_reg, ctrl); 108 } 109 110 static void spi_ctrl_start_user(const AspeedSMCTestData *data) 111 { 112 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; 113 uint32_t ctrl = spi_readl(data, ctrl_reg); 114 115 ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; 116 spi_writel(data, ctrl_reg, ctrl); 117 118 ctrl &= ~CTRL_CE_STOP_ACTIVE; 119 spi_writel(data, ctrl_reg, ctrl); 120 } 121 122 static void spi_ctrl_stop_user(const AspeedSMCTestData *data) 123 { 124 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; 125 uint32_t ctrl = spi_readl(data, ctrl_reg); 126 127 ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE; 128 spi_writel(data, ctrl_reg, ctrl); 129 } 130 131 static void spi_ctrl_set_io_mode(const AspeedSMCTestData *data, uint32_t value) 132 { 133 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4; 134 uint32_t ctrl = spi_readl(data, ctrl_reg); 135 uint32_t mode; 136 137 mode = value & CTRL_IO_MODE_MASK; 138 ctrl &= ~CTRL_IO_MODE_MASK; 139 ctrl |= mode; 140 spi_writel(data, ctrl_reg, ctrl); 141 } 142 143 static void flash_reset(const AspeedSMCTestData *data) 144 { 145 spi_conf(data, 1 << (CONF_ENABLE_W0 + data->cs)); 146 147 spi_ctrl_start_user(data); 148 flash_writeb(data, 0, RESET_ENABLE); 149 flash_writeb(data, 0, RESET_MEMORY); 150 flash_writeb(data, 0, WREN); 151 flash_writeb(data, 0, BULK_ERASE); 152 flash_writeb(data, 0, WRDI); 153 spi_ctrl_stop_user(data); 154 155 spi_conf_remove(data, 1 << (CONF_ENABLE_W0 + data->cs)); 156 } 157 158 static void read_page(const AspeedSMCTestData *data, uint32_t addr, 159 uint32_t *page) 160 { 161 int i; 162 163 spi_ctrl_start_user(data); 164 165 flash_writeb(data, 0, EN_4BYTE_ADDR); 166 flash_writeb(data, 0, READ); 167 flash_writel(data, 0, make_be32(addr)); 168 169 /* Continuous read are supported */ 170 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 171 page[i] = make_be32(flash_readl(data, 0)); 172 } 173 spi_ctrl_stop_user(data); 174 } 175 176 static void read_page_mem(const AspeedSMCTestData *data, uint32_t addr, 177 uint32_t *page) 178 { 179 int i; 180 181 /* move out USER mode to use direct reads from the AHB bus */ 182 spi_ctrl_setmode(data, CTRL_READMODE, READ); 183 184 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 185 page[i] = make_be32(flash_readl(data, addr + i * 4)); 186 } 187 } 188 189 static void write_page_mem(const AspeedSMCTestData *data, uint32_t addr, 190 uint32_t write_value) 191 { 192 spi_ctrl_setmode(data, CTRL_WRITEMODE, PP); 193 194 for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 195 flash_writel(data, addr + i * 4, write_value); 196 } 197 } 198 199 static void assert_page_mem(const AspeedSMCTestData *data, uint32_t addr, 200 uint32_t expected_value) 201 { 202 uint32_t page[FLASH_PAGE_SIZE / 4]; 203 read_page_mem(data, addr, page); 204 for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 205 g_assert_cmphex(page[i], ==, expected_value); 206 } 207 } 208 209 void aspeed_smc_test_read_jedec(const void *data) 210 { 211 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 212 uint32_t jedec = 0x0; 213 214 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 215 216 spi_ctrl_start_user(test_data); 217 flash_writeb(test_data, 0, JEDEC_READ); 218 jedec |= flash_readb(test_data, 0) << 16; 219 jedec |= flash_readb(test_data, 0) << 8; 220 jedec |= flash_readb(test_data, 0); 221 spi_ctrl_stop_user(test_data); 222 223 flash_reset(test_data); 224 225 g_assert_cmphex(jedec, ==, test_data->jedec_id); 226 } 227 228 void aspeed_smc_test_erase_sector(const void *data) 229 { 230 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 231 uint32_t some_page_addr = test_data->page_addr; 232 uint32_t page[FLASH_PAGE_SIZE / 4]; 233 int i; 234 235 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 236 237 /* 238 * Previous page should be full of 0xffs after backend is 239 * initialized 240 */ 241 read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); 242 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 243 g_assert_cmphex(page[i], ==, 0xffffffff); 244 } 245 246 spi_ctrl_start_user(test_data); 247 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 248 flash_writeb(test_data, 0, WREN); 249 flash_writeb(test_data, 0, PP); 250 flash_writel(test_data, 0, make_be32(some_page_addr)); 251 252 /* Fill the page with its own addresses */ 253 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 254 flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); 255 } 256 spi_ctrl_stop_user(test_data); 257 258 /* Check the page is correctly written */ 259 read_page(test_data, some_page_addr, page); 260 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 261 g_assert_cmphex(page[i], ==, some_page_addr + i * 4); 262 } 263 264 spi_ctrl_start_user(test_data); 265 flash_writeb(test_data, 0, WREN); 266 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 267 flash_writeb(test_data, 0, ERASE_SECTOR); 268 flash_writel(test_data, 0, make_be32(some_page_addr)); 269 spi_ctrl_stop_user(test_data); 270 271 /* Check the page is erased */ 272 read_page(test_data, some_page_addr, page); 273 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 274 g_assert_cmphex(page[i], ==, 0xffffffff); 275 } 276 277 flash_reset(test_data); 278 } 279 280 void aspeed_smc_test_erase_all(const void *data) 281 { 282 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 283 uint32_t some_page_addr = test_data->page_addr; 284 uint32_t page[FLASH_PAGE_SIZE / 4]; 285 int i; 286 287 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 288 289 /* 290 * Previous page should be full of 0xffs after backend is 291 * initialized 292 */ 293 read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page); 294 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 295 g_assert_cmphex(page[i], ==, 0xffffffff); 296 } 297 298 spi_ctrl_start_user(test_data); 299 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 300 flash_writeb(test_data, 0, WREN); 301 flash_writeb(test_data, 0, PP); 302 flash_writel(test_data, 0, make_be32(some_page_addr)); 303 304 /* Fill the page with its own addresses */ 305 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 306 flash_writel(test_data, 0, make_be32(some_page_addr + i * 4)); 307 } 308 spi_ctrl_stop_user(test_data); 309 310 /* Check the page is correctly written */ 311 read_page(test_data, some_page_addr, page); 312 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 313 g_assert_cmphex(page[i], ==, some_page_addr + i * 4); 314 } 315 316 spi_ctrl_start_user(test_data); 317 flash_writeb(test_data, 0, WREN); 318 flash_writeb(test_data, 0, BULK_ERASE); 319 spi_ctrl_stop_user(test_data); 320 321 /* Check the page is erased */ 322 read_page(test_data, some_page_addr, page); 323 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 324 g_assert_cmphex(page[i], ==, 0xffffffff); 325 } 326 327 flash_reset(test_data); 328 } 329 330 void aspeed_smc_test_write_page(const void *data) 331 { 332 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 333 uint32_t my_page_addr = test_data->page_addr; 334 uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; 335 uint32_t page[FLASH_PAGE_SIZE / 4]; 336 int i; 337 338 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 339 340 spi_ctrl_start_user(test_data); 341 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 342 flash_writeb(test_data, 0, WREN); 343 flash_writeb(test_data, 0, PP); 344 flash_writel(test_data, 0, make_be32(my_page_addr)); 345 346 /* Fill the page with its own addresses */ 347 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 348 flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); 349 } 350 spi_ctrl_stop_user(test_data); 351 352 /* Check what was written */ 353 read_page(test_data, my_page_addr, page); 354 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 355 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 356 } 357 358 /* Check some other page. It should be full of 0xff */ 359 read_page(test_data, some_page_addr, page); 360 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 361 g_assert_cmphex(page[i], ==, 0xffffffff); 362 } 363 364 flash_reset(test_data); 365 } 366 367 void aspeed_smc_test_read_page_mem(const void *data) 368 { 369 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 370 uint32_t my_page_addr = test_data->page_addr; 371 uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; 372 uint32_t page[FLASH_PAGE_SIZE / 4]; 373 int i; 374 375 /* 376 * Enable 4BYTE mode for controller. 377 */ 378 spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); 379 380 /* Enable 4BYTE mode for flash. */ 381 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 382 spi_ctrl_start_user(test_data); 383 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 384 flash_writeb(test_data, 0, WREN); 385 flash_writeb(test_data, 0, PP); 386 flash_writel(test_data, 0, make_be32(my_page_addr)); 387 388 /* Fill the page with its own addresses */ 389 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 390 flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); 391 } 392 spi_ctrl_stop_user(test_data); 393 spi_conf_remove(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 394 395 /* Check what was written */ 396 read_page_mem(test_data, my_page_addr, page); 397 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 398 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 399 } 400 401 /* Check some other page. It should be full of 0xff */ 402 read_page_mem(test_data, some_page_addr, page); 403 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 404 g_assert_cmphex(page[i], ==, 0xffffffff); 405 } 406 407 flash_reset(test_data); 408 } 409 410 void aspeed_smc_test_write_page_mem(const void *data) 411 { 412 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 413 uint32_t my_page_addr = test_data->page_addr; 414 uint32_t page[FLASH_PAGE_SIZE / 4]; 415 int i; 416 417 /* 418 * Enable 4BYTE mode for controller. 419 */ 420 spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); 421 422 /* Enable 4BYTE mode for flash. */ 423 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 424 spi_ctrl_start_user(test_data); 425 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 426 flash_writeb(test_data, 0, WREN); 427 spi_ctrl_stop_user(test_data); 428 429 /* move out USER mode to use direct writes to the AHB bus */ 430 spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP); 431 432 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 433 flash_writel(test_data, my_page_addr + i * 4, 434 make_be32(my_page_addr + i * 4)); 435 } 436 437 /* Check what was written */ 438 read_page_mem(test_data, my_page_addr, page); 439 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 440 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 441 } 442 443 flash_reset(test_data); 444 } 445 446 void aspeed_smc_test_read_status_reg(const void *data) 447 { 448 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 449 uint8_t r; 450 451 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 452 453 spi_ctrl_start_user(test_data); 454 flash_writeb(test_data, 0, RDSR); 455 r = flash_readb(test_data, 0); 456 spi_ctrl_stop_user(test_data); 457 458 g_assert_cmphex(r & SR_WEL, ==, 0); 459 g_assert(!qtest_qom_get_bool 460 (test_data->s, test_data->node, "write-enable")); 461 462 spi_ctrl_start_user(test_data); 463 flash_writeb(test_data, 0, WREN); 464 flash_writeb(test_data, 0, RDSR); 465 r = flash_readb(test_data, 0); 466 spi_ctrl_stop_user(test_data); 467 468 g_assert_cmphex(r & SR_WEL, ==, SR_WEL); 469 g_assert(qtest_qom_get_bool 470 (test_data->s, test_data->node, "write-enable")); 471 472 spi_ctrl_start_user(test_data); 473 flash_writeb(test_data, 0, WRDI); 474 flash_writeb(test_data, 0, RDSR); 475 r = flash_readb(test_data, 0); 476 spi_ctrl_stop_user(test_data); 477 478 g_assert_cmphex(r & SR_WEL, ==, 0); 479 g_assert(!qtest_qom_get_bool 480 (test_data->s, test_data->node, "write-enable")); 481 482 flash_reset(test_data); 483 } 484 485 void aspeed_smc_test_status_reg_write_protection(const void *data) 486 { 487 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 488 uint8_t r; 489 490 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 491 492 /* default case: WP# is high and SRWD is low -> status register writable */ 493 spi_ctrl_start_user(test_data); 494 flash_writeb(test_data, 0, WREN); 495 /* test ability to write SRWD */ 496 flash_writeb(test_data, 0, WRSR); 497 flash_writeb(test_data, 0, SRWD); 498 flash_writeb(test_data, 0, RDSR); 499 r = flash_readb(test_data, 0); 500 spi_ctrl_stop_user(test_data); 501 g_assert_cmphex(r & SRWD, ==, SRWD); 502 503 /* WP# high and SRWD high -> status register writable */ 504 spi_ctrl_start_user(test_data); 505 flash_writeb(test_data, 0, WREN); 506 /* test ability to write SRWD */ 507 flash_writeb(test_data, 0, WRSR); 508 flash_writeb(test_data, 0, 0); 509 flash_writeb(test_data, 0, RDSR); 510 r = flash_readb(test_data, 0); 511 spi_ctrl_stop_user(test_data); 512 g_assert_cmphex(r & SRWD, ==, 0); 513 514 /* WP# low and SRWD low -> status register writable */ 515 qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 0); 516 spi_ctrl_start_user(test_data); 517 flash_writeb(test_data, 0, WREN); 518 /* test ability to write SRWD */ 519 flash_writeb(test_data, 0, WRSR); 520 flash_writeb(test_data, 0, SRWD); 521 flash_writeb(test_data, 0, RDSR); 522 r = flash_readb(test_data, 0); 523 spi_ctrl_stop_user(test_data); 524 g_assert_cmphex(r & SRWD, ==, SRWD); 525 526 /* WP# low and SRWD high -> status register NOT writable */ 527 spi_ctrl_start_user(test_data); 528 flash_writeb(test_data, 0 , WREN); 529 /* test ability to write SRWD */ 530 flash_writeb(test_data, 0, WRSR); 531 flash_writeb(test_data, 0, 0); 532 flash_writeb(test_data, 0, RDSR); 533 r = flash_readb(test_data, 0); 534 spi_ctrl_stop_user(test_data); 535 /* write is not successful */ 536 g_assert_cmphex(r & SRWD, ==, SRWD); 537 538 qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 1); 539 flash_reset(test_data); 540 } 541 542 void aspeed_smc_test_write_block_protect(const void *data) 543 { 544 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 545 uint32_t sector_size = 65536; 546 uint32_t n_sectors = 512; 547 548 spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); 549 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 550 551 uint32_t bp_bits = 0b0; 552 553 for (int i = 0; i < 16; i++) { 554 bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2); 555 556 spi_ctrl_start_user(test_data); 557 flash_writeb(test_data, 0, WREN); 558 flash_writeb(test_data, 0, BULK_ERASE); 559 flash_writeb(test_data, 0, WREN); 560 flash_writeb(test_data, 0, WRSR); 561 flash_writeb(test_data, 0, bp_bits); 562 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 563 flash_writeb(test_data, 0, WREN); 564 spi_ctrl_stop_user(test_data); 565 566 uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; 567 uint32_t protection_start = n_sectors - num_protected_sectors; 568 uint32_t protection_end = n_sectors; 569 570 for (int sector = 0; sector < n_sectors; sector++) { 571 uint32_t addr = sector * sector_size; 572 573 assert_page_mem(test_data, addr, 0xffffffff); 574 write_page_mem(test_data, addr, make_be32(0xabcdef12)); 575 576 uint32_t expected_value = protection_start <= sector 577 && sector < protection_end 578 ? 0xffffffff : 0xabcdef12; 579 580 assert_page_mem(test_data, addr, expected_value); 581 } 582 } 583 584 flash_reset(test_data); 585 } 586 587 void aspeed_smc_test_write_block_protect_bottom_bit(const void *data) 588 { 589 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 590 uint32_t sector_size = 65536; 591 uint32_t n_sectors = 512; 592 593 spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs)); 594 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 595 596 /* top bottom bit is enabled */ 597 uint32_t bp_bits = 0b00100 << 3; 598 599 for (int i = 0; i < 16; i++) { 600 bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2); 601 602 spi_ctrl_start_user(test_data); 603 flash_writeb(test_data, 0, WREN); 604 flash_writeb(test_data, 0, BULK_ERASE); 605 flash_writeb(test_data, 0, WREN); 606 flash_writeb(test_data, 0, WRSR); 607 flash_writeb(test_data, 0, bp_bits); 608 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 609 flash_writeb(test_data, 0, WREN); 610 spi_ctrl_stop_user(test_data); 611 612 uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0; 613 uint32_t protection_start = 0; 614 uint32_t protection_end = num_protected_sectors; 615 616 for (int sector = 0; sector < n_sectors; sector++) { 617 uint32_t addr = sector * sector_size; 618 619 assert_page_mem(test_data, addr, 0xffffffff); 620 write_page_mem(test_data, addr, make_be32(0xabcdef12)); 621 622 uint32_t expected_value = protection_start <= sector 623 && sector < protection_end 624 ? 0xffffffff : 0xabcdef12; 625 626 assert_page_mem(test_data, addr, expected_value); 627 } 628 } 629 630 flash_reset(test_data); 631 } 632 633 void aspeed_smc_test_write_page_qpi(const void *data) 634 { 635 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data; 636 uint32_t my_page_addr = test_data->page_addr; 637 uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE; 638 uint32_t page[FLASH_PAGE_SIZE / 4]; 639 uint32_t page_pattern[] = { 640 0xebd8c134, 0x5da196bc, 0xae15e729, 0x5085ccdf 641 }; 642 int i; 643 644 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs)); 645 646 spi_ctrl_start_user(test_data); 647 flash_writeb(test_data, 0, EN_4BYTE_ADDR); 648 flash_writeb(test_data, 0, WREN); 649 flash_writeb(test_data, 0, PP); 650 flash_writel(test_data, 0, make_be32(my_page_addr)); 651 652 /* Set QPI mode */ 653 spi_ctrl_set_io_mode(test_data, CTRL_IO_QUAD_IO); 654 655 /* Fill the page pattern */ 656 for (i = 0; i < ARRAY_SIZE(page_pattern); i++) { 657 flash_writel(test_data, 0, make_be32(page_pattern[i])); 658 } 659 660 /* Fill the page with its own addresses */ 661 for (; i < FLASH_PAGE_SIZE / 4; i++) { 662 flash_writel(test_data, 0, make_be32(my_page_addr + i * 4)); 663 } 664 665 /* Restore io mode */ 666 spi_ctrl_set_io_mode(test_data, 0); 667 spi_ctrl_stop_user(test_data); 668 669 /* Check what was written */ 670 read_page(test_data, my_page_addr, page); 671 for (i = 0; i < ARRAY_SIZE(page_pattern); i++) { 672 g_assert_cmphex(page[i], ==, page_pattern[i]); 673 } 674 for (; i < FLASH_PAGE_SIZE / 4; i++) { 675 g_assert_cmphex(page[i], ==, my_page_addr + i * 4); 676 } 677 678 /* Check some other page. It should be full of 0xff */ 679 read_page(test_data, some_page_addr, page); 680 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) { 681 g_assert_cmphex(page[i], ==, 0xffffffff); 682 } 683 684 flash_reset(test_data); 685 } 686 687