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 */
make_be32(uint32_t data)77 static inline uint32_t make_be32(uint32_t data)
78 {
79 return bswap32(data);
80 }
81
spi_conf(uint32_t value)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
spi_conf_remove(uint32_t value)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
spi_ce_ctrl(uint32_t value)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
spi_ctrl_setmode(uint8_t mode,uint8_t cmd)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
spi_ctrl_start_user(void)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
spi_ctrl_stop_user(void)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
flash_reset(void)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
test_read_jedec(void)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
read_page(uint32_t addr,uint32_t * page)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
read_page_mem(uint32_t addr,uint32_t * page)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
write_page_mem(uint32_t addr,uint32_t write_value)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
assert_page_mem(uint32_t addr,uint32_t expected_value)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
test_erase_sector(void)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
test_erase_all(void)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
test_write_page(void)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
test_read_page_mem(void)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
test_write_page_mem(void)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
test_read_status_reg(void)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
test_status_reg_write_protection(void)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
test_write_block_protect(void)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
test_write_block_protect_bottom_bit(void)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
main(int argc,char ** argv)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