master
c 930 lines 27.7 KB
Raw
1 /*
2 * QTest testcase for the M25P80 Flash (Using the Aspeed SPI
3 * Controller)
4 *
5 * Copyright (C) 2016 IBM Corp.
6 *
7 * SPDX-License-Identifier: MIT
8 */
9
10 #include "qemu/osdep.h"
11 #include "qemu/bswap.h"
12 #include "libqtest-single.h"
13 #include "qemu/bitops.h"
14 #include "aspeed-smc-utils.h"
15
16 /*
17 * Use an explicit bswap for the values read/wrote to the flash region
18 * as they are BE and the Aspeed CPU is LE.
19 */
20 static inline uint32_t make_be32(uint32_t data)
21 {
22 return bswap32(data);
23 }
24
25 static inline void spi_writel(const AspeedSMCTestData *data, uint64_t offset,
26 uint32_t value)
27 {
28 qtest_writel(data->s, data->spi_base + offset, value);
29 }
30
31 static inline uint32_t spi_readl(const AspeedSMCTestData *data, uint64_t offset)
32 {
33 return qtest_readl(data->s, data->spi_base + offset);
34 }
35
36 static inline void flash_writeb(const AspeedSMCTestData *data, uint64_t offset,
37 uint8_t value)
38 {
39 qtest_writeb(data->s, data->flash_base + offset, value);
40 }
41
42 static inline void flash_writel(const AspeedSMCTestData *data, uint64_t offset,
43 uint32_t value)
44 {
45 qtest_writel(data->s, data->flash_base + offset, value);
46 }
47
48 static inline uint8_t flash_readb(const AspeedSMCTestData *data,
49 uint64_t offset)
50 {
51 return qtest_readb(data->s, data->flash_base + offset);
52 }
53
54 static inline uint32_t flash_readl(const AspeedSMCTestData *data,
55 uint64_t offset)
56 {
57 return qtest_readl(data->s, data->flash_base + offset);
58 }
59
60 /*
61 * Data FIFO port, in spi_base's register bank (not flash_base). Accesses
62 * through the FIFO require the complete user-mode transaction (opcode,
63 * address, and data). Assumes CS0, whose FIFO slot is at R_DATA_FIFO.
64 */
65 static inline void datafifo_writeb(const AspeedSMCTestData *data,
66 uint8_t value)
67 {
68 qtest_writeb(data->s, data->spi_base + R_DATA_FIFO, value);
69 }
70
71 static inline void datafifo_writel(const AspeedSMCTestData *data,
72 uint32_t value)
73 {
74 spi_writel(data, R_DATA_FIFO, value);
75 }
76
77 static inline uint32_t datafifo_readl(const AspeedSMCTestData *data)
78 {
79 return spi_readl(data, R_DATA_FIFO);
80 }
81
82 static void spi_conf(const AspeedSMCTestData *data, uint32_t value)
83 {
84 uint32_t conf = spi_readl(data, R_CONF);
85
86 conf |= value;
87 spi_writel(data, R_CONF, conf);
88 }
89
90 static void spi_conf_remove(const AspeedSMCTestData *data, uint32_t value)
91 {
92 uint32_t conf = spi_readl(data, R_CONF);
93
94 conf &= ~value;
95 spi_writel(data, R_CONF, conf);
96 }
97
98 static void spi_ce_ctrl(const AspeedSMCTestData *data, uint32_t value)
99 {
100 uint32_t conf = spi_readl(data, R_CE_CTRL);
101
102 conf |= value;
103 spi_writel(data, R_CE_CTRL, conf);
104 }
105
106 static void spi_ctrl_setmode(const AspeedSMCTestData *data, uint8_t mode,
107 uint8_t cmd)
108 {
109 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4;
110 uint32_t ctrl = spi_readl(data, ctrl_reg);
111 ctrl &= ~(CTRL_USERMODE | 0xff << 16);
112 ctrl |= mode | (cmd << 16);
113 spi_writel(data, ctrl_reg, ctrl);
114 }
115
116 /* Set FREADMODE with a fast read command and 1 dummy byte */
117 static void spi_ctrl_set_fast_read(const AspeedSMCTestData *data, uint8_t cmd)
118 {
119 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4;
120 uint32_t ctrl = spi_readl(data, ctrl_reg);
121 uint32_t iomode = 0;
122
123 if (cmd == DOR) {
124 iomode = CTRL_IO_DUAL_DATA;
125 } else if (cmd == QOR) {
126 iomode = CTRL_IO_QUAD_DATA;
127 }
128
129 ctrl &= ~(CTRL_USERMODE | (0xff << 16) |
130 (0x3 << CTRL_DUMMY_LOW_SHIFT) |
131 (0x1 << CTRL_DUMMY_HIGH_SHIFT) |
132 CTRL_IO_MODE_MASK);
133 ctrl |= CTRL_FREADMODE | (cmd << 16) |
134 (1 << CTRL_DUMMY_LOW_SHIFT) |
135 iomode;
136 spi_writel(data, ctrl_reg, ctrl);
137 }
138
139 static void spi_ctrl_start_user(const AspeedSMCTestData *data)
140 {
141 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4;
142 uint32_t ctrl = spi_readl(data, ctrl_reg);
143
144 ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
145 spi_writel(data, ctrl_reg, ctrl);
146
147 ctrl &= ~CTRL_CE_STOP_ACTIVE;
148 spi_writel(data, ctrl_reg, ctrl);
149 }
150
151 static void spi_ctrl_stop_user(const AspeedSMCTestData *data)
152 {
153 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4;
154 uint32_t ctrl = spi_readl(data, ctrl_reg);
155
156 ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
157 spi_writel(data, ctrl_reg, ctrl);
158 }
159
160 static void spi_ctrl_set_io_mode(const AspeedSMCTestData *data, uint32_t value)
161 {
162 uint32_t ctrl_reg = R_CTRL0 + data->cs * 4;
163 uint32_t ctrl = spi_readl(data, ctrl_reg);
164 uint32_t mode;
165
166 mode = value & CTRL_IO_MODE_MASK;
167 ctrl &= ~CTRL_IO_MODE_MASK;
168 ctrl |= mode;
169 spi_writel(data, ctrl_reg, ctrl);
170 }
171
172 static void flash_reset(const AspeedSMCTestData *data)
173 {
174 spi_conf(data, 1 << (CONF_ENABLE_W0 + data->cs));
175
176 spi_ctrl_start_user(data);
177 flash_writeb(data, 0, RESET_ENABLE);
178 flash_writeb(data, 0, RESET_MEMORY);
179 flash_writeb(data, 0, WREN);
180 flash_writeb(data, 0, BULK_ERASE);
181 flash_writeb(data, 0, WRDI);
182 spi_ctrl_stop_user(data);
183
184 spi_conf_remove(data, 1 << (CONF_ENABLE_W0 + data->cs));
185 }
186
187 static void read_page(const AspeedSMCTestData *data, uint32_t addr,
188 uint32_t *page)
189 {
190 int i;
191
192 spi_ctrl_start_user(data);
193
194 flash_writeb(data, 0, EN_4BYTE_ADDR);
195 flash_writeb(data, 0, READ);
196 flash_writel(data, 0, make_be32(addr));
197
198 /* Continuous read are supported */
199 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
200 page[i] = make_be32(flash_readl(data, 0));
201 }
202 spi_ctrl_stop_user(data);
203 }
204
205 static void read_page_mem(const AspeedSMCTestData *data, uint32_t addr,
206 uint32_t *page)
207 {
208 int i;
209
210 /* move out USER mode to use direct reads from the AHB bus */
211 spi_ctrl_setmode(data, CTRL_READMODE, READ);
212
213 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
214 page[i] = make_be32(flash_readl(data, addr + i * 4));
215 }
216 }
217
218 typedef void (*read_page_mem_fn)(const AspeedSMCTestData *data,
219 uint32_t addr, uint32_t *page);
220
221 static void write_page_mem(const AspeedSMCTestData *data, uint32_t addr,
222 uint32_t write_value)
223 {
224 spi_ctrl_setmode(data, CTRL_WRITEMODE, PP);
225
226 for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
227 flash_writel(data, addr + i * 4, write_value);
228 }
229 }
230
231 static void assert_page_mem(const AspeedSMCTestData *data, uint32_t addr,
232 uint32_t expected_value)
233 {
234 uint32_t page[FLASH_PAGE_SIZE / 4];
235 read_page_mem(data, addr, page);
236 for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
237 g_assert_cmphex(page[i], ==, expected_value);
238 }
239 }
240
241 void aspeed_smc_test_read_jedec(const void *data)
242 {
243 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
244 uint32_t jedec = 0x0;
245
246 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
247
248 spi_ctrl_start_user(test_data);
249 flash_writeb(test_data, 0, JEDEC_READ);
250 jedec |= flash_readb(test_data, 0) << 16;
251 jedec |= flash_readb(test_data, 0) << 8;
252 jedec |= flash_readb(test_data, 0);
253 spi_ctrl_stop_user(test_data);
254
255 flash_reset(test_data);
256
257 g_assert_cmphex(jedec, ==, test_data->jedec_id);
258 }
259
260 void aspeed_smc_test_erase_sector(const void *data)
261 {
262 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
263 uint32_t some_page_addr = test_data->page_addr;
264 uint32_t page[FLASH_PAGE_SIZE / 4];
265 int i;
266
267 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
268
269 /*
270 * Previous page should be full of 0xffs after backend is
271 * initialized
272 */
273 read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page);
274 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
275 g_assert_cmphex(page[i], ==, 0xffffffff);
276 }
277
278 spi_ctrl_start_user(test_data);
279 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
280 flash_writeb(test_data, 0, WREN);
281 flash_writeb(test_data, 0, PP);
282 flash_writel(test_data, 0, make_be32(some_page_addr));
283
284 /* Fill the page with its own addresses */
285 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
286 flash_writel(test_data, 0, make_be32(some_page_addr + i * 4));
287 }
288 spi_ctrl_stop_user(test_data);
289
290 /* Check the page is correctly written */
291 read_page(test_data, some_page_addr, page);
292 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
293 g_assert_cmphex(page[i], ==, some_page_addr + i * 4);
294 }
295
296 spi_ctrl_start_user(test_data);
297 flash_writeb(test_data, 0, WREN);
298 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
299 flash_writeb(test_data, 0, ERASE_SECTOR);
300 flash_writel(test_data, 0, make_be32(some_page_addr));
301 spi_ctrl_stop_user(test_data);
302
303 /* Check the page is erased */
304 read_page(test_data, some_page_addr, page);
305 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
306 g_assert_cmphex(page[i], ==, 0xffffffff);
307 }
308
309 flash_reset(test_data);
310 }
311
312 void aspeed_smc_test_erase_all(const void *data)
313 {
314 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
315 uint32_t some_page_addr = test_data->page_addr;
316 uint32_t page[FLASH_PAGE_SIZE / 4];
317 int i;
318
319 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
320
321 /*
322 * Previous page should be full of 0xffs after backend is
323 * initialized
324 */
325 read_page(test_data, some_page_addr - FLASH_PAGE_SIZE, page);
326 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
327 g_assert_cmphex(page[i], ==, 0xffffffff);
328 }
329
330 spi_ctrl_start_user(test_data);
331 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
332 flash_writeb(test_data, 0, WREN);
333 flash_writeb(test_data, 0, PP);
334 flash_writel(test_data, 0, make_be32(some_page_addr));
335
336 /* Fill the page with its own addresses */
337 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
338 flash_writel(test_data, 0, make_be32(some_page_addr + i * 4));
339 }
340 spi_ctrl_stop_user(test_data);
341
342 /* Check the page is correctly written */
343 read_page(test_data, some_page_addr, page);
344 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
345 g_assert_cmphex(page[i], ==, some_page_addr + i * 4);
346 }
347
348 spi_ctrl_start_user(test_data);
349 flash_writeb(test_data, 0, WREN);
350 flash_writeb(test_data, 0, BULK_ERASE);
351 spi_ctrl_stop_user(test_data);
352
353 /* Check the page is erased */
354 read_page(test_data, some_page_addr, page);
355 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
356 g_assert_cmphex(page[i], ==, 0xffffffff);
357 }
358
359 flash_reset(test_data);
360 }
361
362 static void test_write_page(const AspeedSMCTestData *test_data,
363 read_page_mem_fn reader)
364 {
365 uint32_t my_page_addr = test_data->page_addr;
366 uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE;
367 uint32_t page[FLASH_PAGE_SIZE / 4];
368 int i;
369
370 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
371
372 spi_ctrl_start_user(test_data);
373 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
374 flash_writeb(test_data, 0, WREN);
375 flash_writeb(test_data, 0, PP);
376 flash_writel(test_data, 0, make_be32(my_page_addr));
377
378 /* Fill the page with its own addresses */
379 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
380 flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
381 }
382 spi_ctrl_stop_user(test_data);
383
384 /* Check what was written */
385 reader(test_data, my_page_addr, page);
386 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
387 g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
388 }
389
390 /* Check some other page. It should be full of 0xff */
391 reader(test_data, some_page_addr, page);
392 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
393 g_assert_cmphex(page[i], ==, 0xffffffff);
394 }
395
396 flash_reset(test_data);
397 }
398
399 void aspeed_smc_test_write_page(const void *data)
400 {
401 test_write_page(data, read_page);
402 }
403
404 static void test_read_page_mem(const AspeedSMCTestData *test_data,
405 read_page_mem_fn reader)
406 {
407 uint32_t my_page_addr = test_data->page_addr;
408 uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE;
409 uint32_t page[FLASH_PAGE_SIZE / 4];
410 int i;
411
412 /*
413 * Enable 4BYTE mode for controller.
414 */
415 spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs));
416
417 /* Enable 4BYTE mode for flash. */
418 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
419 spi_ctrl_start_user(test_data);
420 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
421 flash_writeb(test_data, 0, WREN);
422 flash_writeb(test_data, 0, PP);
423 flash_writel(test_data, 0, make_be32(my_page_addr));
424
425 /* Fill the page with its own addresses */
426 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
427 flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
428 }
429 spi_ctrl_stop_user(test_data);
430 spi_conf_remove(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
431
432 /* Check what was written */
433 reader(test_data, my_page_addr, page);
434 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
435 g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
436 }
437
438 /* Check some other page. It should be full of 0xff */
439 reader(test_data, some_page_addr, page);
440 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
441 g_assert_cmphex(page[i], ==, 0xffffffff);
442 }
443
444 flash_reset(test_data);
445 }
446
447 void aspeed_smc_test_read_page_mem(const void *data)
448 {
449 test_read_page_mem(data, read_page_mem);
450 }
451
452 void aspeed_smc_test_write_page_mem(const void *data)
453 {
454 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
455 uint32_t my_page_addr = test_data->page_addr;
456 uint32_t page[FLASH_PAGE_SIZE / 4];
457 int i;
458
459 /*
460 * Enable 4BYTE mode for controller.
461 */
462 spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs));
463
464 /* Enable 4BYTE mode for flash. */
465 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
466 spi_ctrl_start_user(test_data);
467 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
468 flash_writeb(test_data, 0, WREN);
469 spi_ctrl_stop_user(test_data);
470
471 /* move out USER mode to use direct writes to the AHB bus */
472 spi_ctrl_setmode(test_data, CTRL_WRITEMODE, PP);
473
474 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
475 flash_writel(test_data, my_page_addr + i * 4,
476 make_be32(my_page_addr + i * 4));
477 }
478
479 /* Check what was written */
480 read_page_mem(test_data, my_page_addr, page);
481 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
482 g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
483 }
484
485 flash_reset(test_data);
486 }
487
488 void aspeed_smc_test_read_status_reg(const void *data)
489 {
490 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
491 uint8_t r;
492
493 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
494
495 spi_ctrl_start_user(test_data);
496 flash_writeb(test_data, 0, RDSR);
497 r = flash_readb(test_data, 0);
498 spi_ctrl_stop_user(test_data);
499
500 g_assert_cmphex(r & SR_WEL, ==, 0);
501 g_assert(!qtest_qom_get_bool
502 (test_data->s, test_data->node, "write-enable"));
503
504 spi_ctrl_start_user(test_data);
505 flash_writeb(test_data, 0, WREN);
506 flash_writeb(test_data, 0, RDSR);
507 r = flash_readb(test_data, 0);
508 spi_ctrl_stop_user(test_data);
509
510 g_assert_cmphex(r & SR_WEL, ==, SR_WEL);
511 g_assert(qtest_qom_get_bool
512 (test_data->s, test_data->node, "write-enable"));
513
514 spi_ctrl_start_user(test_data);
515 flash_writeb(test_data, 0, WRDI);
516 flash_writeb(test_data, 0, RDSR);
517 r = flash_readb(test_data, 0);
518 spi_ctrl_stop_user(test_data);
519
520 g_assert_cmphex(r & SR_WEL, ==, 0);
521 g_assert(!qtest_qom_get_bool
522 (test_data->s, test_data->node, "write-enable"));
523
524 flash_reset(test_data);
525 }
526
527 void aspeed_smc_test_status_reg_write_protection(const void *data)
528 {
529 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
530 uint8_t r;
531
532 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
533
534 /* default case: WP# is high and SRWD is low -> status register writable */
535 spi_ctrl_start_user(test_data);
536 flash_writeb(test_data, 0, WREN);
537 /* test ability to write SRWD */
538 flash_writeb(test_data, 0, WRSR);
539 flash_writeb(test_data, 0, SRWD);
540 flash_writeb(test_data, 0, RDSR);
541 r = flash_readb(test_data, 0);
542 spi_ctrl_stop_user(test_data);
543 g_assert_cmphex(r & SRWD, ==, SRWD);
544
545 /* WP# high and SRWD high -> status register writable */
546 spi_ctrl_start_user(test_data);
547 flash_writeb(test_data, 0, WREN);
548 /* test ability to write SRWD */
549 flash_writeb(test_data, 0, WRSR);
550 flash_writeb(test_data, 0, 0);
551 flash_writeb(test_data, 0, RDSR);
552 r = flash_readb(test_data, 0);
553 spi_ctrl_stop_user(test_data);
554 g_assert_cmphex(r & SRWD, ==, 0);
555
556 /* WP# low and SRWD low -> status register writable */
557 qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 0);
558 spi_ctrl_start_user(test_data);
559 flash_writeb(test_data, 0, WREN);
560 /* test ability to write SRWD */
561 flash_writeb(test_data, 0, WRSR);
562 flash_writeb(test_data, 0, SRWD);
563 flash_writeb(test_data, 0, RDSR);
564 r = flash_readb(test_data, 0);
565 spi_ctrl_stop_user(test_data);
566 g_assert_cmphex(r & SRWD, ==, SRWD);
567
568 /* WP# low and SRWD high -> status register NOT writable */
569 spi_ctrl_start_user(test_data);
570 flash_writeb(test_data, 0 , WREN);
571 /* test ability to write SRWD */
572 flash_writeb(test_data, 0, WRSR);
573 flash_writeb(test_data, 0, 0);
574 flash_writeb(test_data, 0, RDSR);
575 r = flash_readb(test_data, 0);
576 spi_ctrl_stop_user(test_data);
577 /* write is not successful */
578 g_assert_cmphex(r & SRWD, ==, SRWD);
579
580 qtest_set_irq_in(test_data->s, test_data->node, "WP#", 0, 1);
581 flash_reset(test_data);
582 }
583
584 void aspeed_smc_test_write_block_protect(const void *data)
585 {
586 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
587 uint32_t sector_size = 65536;
588 uint32_t n_sectors = 512;
589
590 spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs));
591 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
592
593 uint32_t bp_bits = 0b0;
594
595 for (int i = 0; i < 16; i++) {
596 bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2);
597
598 spi_ctrl_start_user(test_data);
599 flash_writeb(test_data, 0, WREN);
600 flash_writeb(test_data, 0, BULK_ERASE);
601 flash_writeb(test_data, 0, WREN);
602 flash_writeb(test_data, 0, WRSR);
603 flash_writeb(test_data, 0, bp_bits);
604 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
605 flash_writeb(test_data, 0, WREN);
606 spi_ctrl_stop_user(test_data);
607
608 uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
609 uint32_t protection_start = n_sectors - num_protected_sectors;
610 uint32_t protection_end = n_sectors;
611
612 for (int sector = 0; sector < n_sectors; sector++) {
613 uint32_t addr = sector * sector_size;
614
615 assert_page_mem(test_data, addr, 0xffffffff);
616 write_page_mem(test_data, addr, make_be32(0xabcdef12));
617
618 uint32_t expected_value = protection_start <= sector
619 && sector < protection_end
620 ? 0xffffffff : 0xabcdef12;
621
622 assert_page_mem(test_data, addr, expected_value);
623 }
624 }
625
626 flash_reset(test_data);
627 }
628
629 void aspeed_smc_test_write_block_protect_bottom_bit(const void *data)
630 {
631 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
632 uint32_t sector_size = 65536;
633 uint32_t n_sectors = 512;
634
635 spi_ce_ctrl(test_data, 1 << (CRTL_EXTENDED0 + test_data->cs));
636 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
637
638 /* top bottom bit is enabled */
639 uint32_t bp_bits = 0b00100 << 3;
640
641 for (int i = 0; i < 16; i++) {
642 bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2);
643
644 spi_ctrl_start_user(test_data);
645 flash_writeb(test_data, 0, WREN);
646 flash_writeb(test_data, 0, BULK_ERASE);
647 flash_writeb(test_data, 0, WREN);
648 flash_writeb(test_data, 0, WRSR);
649 flash_writeb(test_data, 0, bp_bits);
650 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
651 flash_writeb(test_data, 0, WREN);
652 spi_ctrl_stop_user(test_data);
653
654 uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
655 uint32_t protection_start = 0;
656 uint32_t protection_end = num_protected_sectors;
657
658 for (int sector = 0; sector < n_sectors; sector++) {
659 uint32_t addr = sector * sector_size;
660
661 assert_page_mem(test_data, addr, 0xffffffff);
662 write_page_mem(test_data, addr, make_be32(0xabcdef12));
663
664 uint32_t expected_value = protection_start <= sector
665 && sector < protection_end
666 ? 0xffffffff : 0xabcdef12;
667
668 assert_page_mem(test_data, addr, expected_value);
669 }
670 }
671
672 flash_reset(test_data);
673 }
674
675 void aspeed_smc_test_write_page_qpi(const void *data)
676 {
677 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
678 uint32_t my_page_addr = test_data->page_addr;
679 uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE;
680 uint32_t page[FLASH_PAGE_SIZE / 4];
681 uint32_t page_pattern[] = {
682 0xebd8c134, 0x5da196bc, 0xae15e729, 0x5085ccdf
683 };
684 int i;
685
686 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
687
688 spi_ctrl_start_user(test_data);
689 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
690 flash_writeb(test_data, 0, WREN);
691 flash_writeb(test_data, 0, PP);
692 flash_writel(test_data, 0, make_be32(my_page_addr));
693
694 /* Set QPI mode */
695 spi_ctrl_set_io_mode(test_data, CTRL_IO_QUAD_IO);
696
697 /* Fill the page pattern */
698 for (i = 0; i < ARRAY_SIZE(page_pattern); i++) {
699 flash_writel(test_data, 0, make_be32(page_pattern[i]));
700 }
701
702 /* Fill the page with its own addresses */
703 for (; i < FLASH_PAGE_SIZE / 4; i++) {
704 flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
705 }
706
707 /* Restore io mode */
708 spi_ctrl_set_io_mode(test_data, 0);
709 spi_ctrl_stop_user(test_data);
710
711 /* Check what was written */
712 read_page(test_data, my_page_addr, page);
713 for (i = 0; i < ARRAY_SIZE(page_pattern); i++) {
714 g_assert_cmphex(page[i], ==, page_pattern[i]);
715 }
716 for (; i < FLASH_PAGE_SIZE / 4; i++) {
717 g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
718 }
719
720 /* Check some other page. It should be full of 0xff */
721 read_page(test_data, some_page_addr, page);
722 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
723 g_assert_cmphex(page[i], ==, 0xffffffff);
724 }
725
726 flash_reset(test_data);
727 }
728
729 static void read_page_mem_fast_read(const AspeedSMCTestData *data,
730 uint32_t addr, uint32_t *page)
731 {
732 int i;
733
734 spi_ctrl_set_fast_read(data, FAST_READ);
735
736 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
737 page[i] = make_be32(flash_readl(data, addr + i * 4));
738 }
739 }
740
741 void aspeed_smc_test_read_page_mem_fast_read(const void *data)
742 {
743 test_read_page_mem(data, read_page_mem_fast_read);
744 }
745
746 static void read_page_fast_read(const AspeedSMCTestData *data,
747 uint32_t addr, uint32_t *page)
748 {
749 int i;
750
751 spi_ctrl_start_user(data);
752
753 flash_writeb(data, 0, EN_4BYTE_ADDR);
754 flash_writeb(data, 0, FAST_READ);
755 flash_writel(data, 0, make_be32(addr));
756 /* 1 dummy byte for standard SPI fast-read */
757 flash_writeb(data, 0, 0x00);
758
759 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
760 page[i] = make_be32(flash_readl(data, 0));
761 }
762 spi_ctrl_stop_user(data);
763 }
764
765 void aspeed_smc_test_write_page_fast_read(const void *data)
766 {
767 test_write_page(data, read_page_fast_read);
768 }
769
770 static void read_page_mem_dor(const AspeedSMCTestData *data,
771 uint32_t addr, uint32_t *page)
772 {
773 int i;
774
775 spi_ctrl_set_fast_read(data, DOR);
776
777 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
778 page[i] = make_be32(flash_readl(data, addr + i * 4));
779 }
780 }
781
782 void aspeed_smc_test_read_page_mem_dor(const void *data)
783 {
784 test_read_page_mem(data, read_page_mem_dor);
785 }
786
787 static void read_page_dor(const AspeedSMCTestData *data,
788 uint32_t addr, uint32_t *page)
789 {
790 int i;
791
792 spi_ctrl_start_user(data);
793
794 flash_writeb(data, 0, EN_4BYTE_ADDR);
795 flash_writeb(data, 0, DOR);
796 flash_writel(data, 0, make_be32(addr));
797 /* 1 dummy byte for standard SPI DOR */
798 flash_writeb(data, 0, 0x00);
799
800 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
801 page[i] = make_be32(flash_readl(data, 0));
802 }
803 spi_ctrl_stop_user(data);
804 }
805
806 void aspeed_smc_test_write_page_dor(const void *data)
807 {
808 test_write_page(data, read_page_dor);
809 }
810
811 static void read_page_mem_qor(const AspeedSMCTestData *data,
812 uint32_t addr, uint32_t *page)
813 {
814 int i;
815
816 spi_ctrl_set_fast_read(data, QOR);
817
818 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
819 page[i] = make_be32(flash_readl(data, addr + i * 4));
820 }
821 }
822
823 void aspeed_smc_test_read_page_mem_qor(const void *data)
824 {
825 test_read_page_mem(data, read_page_mem_qor);
826 }
827
828 static void read_page_qor(const AspeedSMCTestData *data,
829 uint32_t addr, uint32_t *page)
830 {
831 int i;
832
833 spi_ctrl_start_user(data);
834
835 flash_writeb(data, 0, EN_4BYTE_ADDR);
836 flash_writeb(data, 0, QOR);
837 flash_writel(data, 0, make_be32(addr));
838 /* 1 dummy byte for standard SPI QOR */
839 flash_writeb(data, 0, 0x00);
840
841 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
842 page[i] = make_be32(flash_readl(data, 0));
843 }
844 spi_ctrl_stop_user(data);
845 }
846
847 void aspeed_smc_test_write_page_qor(const void *data)
848 {
849 test_write_page(data, read_page_qor);
850 }
851
852 void aspeed_smc_test_write_page_datafifo(const void *data)
853 {
854 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
855 uint32_t my_page_addr = test_data->page_addr;
856 uint32_t some_page_addr = my_page_addr + FLASH_PAGE_SIZE;
857 uint32_t page[FLASH_PAGE_SIZE / 4];
858 int i;
859
860 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
861
862 /*
863 * Send the complete user-mode transaction (opcode, address, data)
864 * through the Data FIFO port.
865 */
866 spi_ctrl_start_user(test_data);
867 datafifo_writeb(test_data, EN_4BYTE_ADDR);
868 datafifo_writeb(test_data, WREN);
869 datafifo_writeb(test_data, PP);
870 datafifo_writel(test_data, make_be32(my_page_addr));
871
872 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
873 datafifo_writel(test_data, make_be32(my_page_addr + i * 4));
874 }
875 spi_ctrl_stop_user(test_data);
876
877 /* Check what was written, using the regular read path */
878 read_page(test_data, my_page_addr, page);
879 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
880 g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
881 }
882
883 /* Check some other page. It should be full of 0xff */
884 read_page(test_data, some_page_addr, page);
885 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
886 g_assert_cmphex(page[i], ==, 0xffffffff);
887 }
888
889 flash_reset(test_data);
890 }
891
892 void aspeed_smc_test_read_page_datafifo(const void *data)
893 {
894 const AspeedSMCTestData *test_data = (const AspeedSMCTestData *)data;
895 uint32_t my_page_addr = test_data->page_addr;
896 uint32_t page[FLASH_PAGE_SIZE / 4];
897 int i;
898
899 spi_conf(test_data, 1 << (CONF_ENABLE_W0 + test_data->cs));
900
901 /* Write the page the regular way */
902 spi_ctrl_start_user(test_data);
903 flash_writeb(test_data, 0, EN_4BYTE_ADDR);
904 flash_writeb(test_data, 0, WREN);
905 flash_writeb(test_data, 0, PP);
906 flash_writel(test_data, 0, make_be32(my_page_addr));
907 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
908 flash_writel(test_data, 0, make_be32(my_page_addr + i * 4));
909 }
910 spi_ctrl_stop_user(test_data);
911
912 /*
913 * Read it back through the data FIFO port, again sending the whole
914 * transaction (opcode, address, data) through it.
915 */
916 spi_ctrl_start_user(test_data);
917 datafifo_writeb(test_data, EN_4BYTE_ADDR);
918 datafifo_writeb(test_data, READ);
919 datafifo_writel(test_data, make_be32(my_page_addr));
920 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
921 page[i] = make_be32(datafifo_readl(test_data));
922 }
923 spi_ctrl_stop_user(test_data);
924
925 for (i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
926 g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
927 }
928
929 flash_reset(test_data);
930 }