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 */
make_be32(uint32_t data)36 static inline uint32_t make_be32(uint32_t data)
37 {
38 return bswap32(data);
39 }
40
spi_writel(const AspeedSMCTestData * data,uint64_t offset,uint32_t value)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
spi_readl(const AspeedSMCTestData * data,uint64_t offset)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
flash_writeb(const AspeedSMCTestData * data,uint64_t offset,uint8_t value)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
flash_writel(const AspeedSMCTestData * data,uint64_t offset,uint32_t value)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
flash_readb(const AspeedSMCTestData * data,uint64_t offset)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
flash_readl(const AspeedSMCTestData * data,uint64_t offset)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
spi_conf(const AspeedSMCTestData * data,uint32_t value)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
spi_conf_remove(const AspeedSMCTestData * data,uint32_t value)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
spi_ce_ctrl(const AspeedSMCTestData * data,uint32_t value)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
spi_ctrl_setmode(const AspeedSMCTestData * data,uint8_t mode,uint8_t cmd)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
spi_ctrl_start_user(const AspeedSMCTestData * data)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
spi_ctrl_stop_user(const AspeedSMCTestData * data)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
spi_ctrl_set_io_mode(const AspeedSMCTestData * data,uint32_t value)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
flash_reset(const AspeedSMCTestData * data)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
read_page(const AspeedSMCTestData * data,uint32_t addr,uint32_t * page)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
read_page_mem(const AspeedSMCTestData * data,uint32_t addr,uint32_t * page)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
write_page_mem(const AspeedSMCTestData * data,uint32_t addr,uint32_t write_value)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
assert_page_mem(const AspeedSMCTestData * data,uint32_t addr,uint32_t expected_value)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
aspeed_smc_test_read_jedec(const void * data)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
aspeed_smc_test_erase_sector(const void * data)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
aspeed_smc_test_erase_all(const void * data)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
aspeed_smc_test_write_page(const void * data)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
aspeed_smc_test_read_page_mem(const void * data)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
aspeed_smc_test_write_page_mem(const void * data)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
aspeed_smc_test_read_status_reg(const void * data)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
aspeed_smc_test_status_reg_write_protection(const void * data)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
aspeed_smc_test_write_block_protect(const void * data)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
aspeed_smc_test_write_block_protect_bottom_bit(const void * data)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
aspeed_smc_test_write_page_qpi(const void * data)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