flash/nor: use command_print() in command "flash banks"
[openocd.git] / src / flash / nor / fespi.c
1 /***************************************************************************
2 * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
3 * Modified by Megan Wachs <megan@sifive.com> from the original stmsmi.c *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 /* The Freedom E SPI controller is a SPI bus controller
20 * specifically designed for SPI Flash Memories on Freedom E platforms.
21 *
22 * Two working modes are available:
23 * - SW mode: the SPI is controlled by SW. Any custom commands can be sent
24 * on the bus. Writes are only possible in this mode.
25 * - HW mode: Memory content is directly
26 * accessible in CPU memory space. CPU can read and execute memory content.
27 */
28
29 /* ATTENTION:
30 * To have flash memory mapped in CPU memory space, the controller
31 * must have "HW mode" enabled.
32 * 1) The command "reset init" has to initialize the controller and put
33 * it in HW mode (this is actually the default out of reset for Freedom E systems).
34 * 2) every command in this file have to return to prompt in HW mode. */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "imp.h"
41 #include "spi.h"
42 #include <jtag/jtag.h>
43 #include <helper/time_support.h>
44 #include <target/algorithm.h>
45 #include "target/riscv/riscv.h"
46
47 /* Register offsets */
48
49 #define FESPI_REG_SCKDIV 0x00
50 #define FESPI_REG_SCKMODE 0x04
51 #define FESPI_REG_CSID 0x10
52 #define FESPI_REG_CSDEF 0x14
53 #define FESPI_REG_CSMODE 0x18
54
55 #define FESPI_REG_DCSSCK 0x28
56 #define FESPI_REG_DSCKCS 0x2a
57 #define FESPI_REG_DINTERCS 0x2c
58 #define FESPI_REG_DINTERXFR 0x2e
59
60 #define FESPI_REG_FMT 0x40
61 #define FESPI_REG_TXFIFO 0x48
62 #define FESPI_REG_RXFIFO 0x4c
63 #define FESPI_REG_TXCTRL 0x50
64 #define FESPI_REG_RXCTRL 0x54
65
66 #define FESPI_REG_FCTRL 0x60
67 #define FESPI_REG_FFMT 0x64
68
69 #define FESPI_REG_IE 0x70
70 #define FESPI_REG_IP 0x74
71
72 /* Fields */
73
74 #define FESPI_SCK_POL 0x1
75 #define FESPI_SCK_PHA 0x2
76
77 #define FESPI_FMT_PROTO(x) ((x) & 0x3)
78 #define FESPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
79 #define FESPI_FMT_DIR(x) (((x) & 0x1) << 3)
80 #define FESPI_FMT_LEN(x) (((x) & 0xf) << 16)
81
82 /* TXCTRL register */
83 #define FESPI_TXWM(x) ((x) & 0xffff)
84 /* RXCTRL register */
85 #define FESPI_RXWM(x) ((x) & 0xffff)
86
87 #define FESPI_IP_TXWM 0x1
88 #define FESPI_IP_RXWM 0x2
89
90 #define FESPI_FCTRL_EN 0x1
91
92 #define FESPI_INSN_CMD_EN 0x1
93 #define FESPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
94 #define FESPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
95 #define FESPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
96 #define FESPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
97 #define FESPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
98 #define FESPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
99 #define FESPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
100
101 /* Values */
102
103 #define FESPI_CSMODE_AUTO 0
104 #define FESPI_CSMODE_HOLD 2
105 #define FESPI_CSMODE_OFF 3
106
107 #define FESPI_DIR_RX 0
108 #define FESPI_DIR_TX 1
109
110 #define FESPI_PROTO_S 0
111 #define FESPI_PROTO_D 1
112 #define FESPI_PROTO_Q 2
113
114 #define FESPI_ENDIAN_MSB 0
115 #define FESPI_ENDIAN_LSB 1
116
117
118 /* Timeout in ms */
119 #define FESPI_CMD_TIMEOUT (100)
120 #define FESPI_PROBE_TIMEOUT (100)
121 #define FESPI_MAX_TIMEOUT (3000)
122
123
124 struct fespi_flash_bank {
125 int probed;
126 target_addr_t ctrl_base;
127 const struct flash_device *dev;
128 };
129
130 struct fespi_target {
131 char *name;
132 uint32_t tap_idcode;
133 uint32_t ctrl_base;
134 };
135
136 /* TODO !!! What is the right naming convention here? */
137 static const struct fespi_target target_devices[] = {
138 /* name, tap_idcode, ctrl_base */
139 { "Freedom E300 SPI Flash", 0x10e31913 , 0x10014000 },
140 { NULL, 0, 0 }
141 };
142
143 FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command)
144 {
145 struct fespi_flash_bank *fespi_info;
146
147 LOG_DEBUG("%s", __func__);
148
149 if (CMD_ARGC < 6)
150 return ERROR_COMMAND_SYNTAX_ERROR;
151
152 fespi_info = malloc(sizeof(struct fespi_flash_bank));
153 if (fespi_info == NULL) {
154 LOG_ERROR("not enough memory");
155 return ERROR_FAIL;
156 }
157
158 bank->driver_priv = fespi_info;
159 fespi_info->probed = 0;
160 fespi_info->ctrl_base = 0;
161 if (CMD_ARGC >= 7) {
162 COMMAND_PARSE_ADDRESS(CMD_ARGV[6], fespi_info->ctrl_base);
163 LOG_DEBUG("ASSUMING FESPI device at ctrl_base = " TARGET_ADDR_FMT,
164 fespi_info->ctrl_base);
165 }
166
167 return ERROR_OK;
168 }
169
170 static int fespi_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_t address)
171 {
172 struct target *target = bank->target;
173 struct fespi_flash_bank *fespi_info = bank->driver_priv;
174
175 int result = target_read_u32(target, fespi_info->ctrl_base + address, value);
176 if (result != ERROR_OK) {
177 LOG_ERROR("fespi_read_reg() error at " TARGET_ADDR_FMT,
178 fespi_info->ctrl_base + address);
179 return result;
180 }
181 return ERROR_OK;
182 }
183
184 static int fespi_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value)
185 { \
186 struct target *target = bank->target;
187 struct fespi_flash_bank *fespi_info = bank->driver_priv;
188
189 int result = target_write_u32(target, fespi_info->ctrl_base + address, value);
190 if (result != ERROR_OK) {
191 LOG_ERROR("fespi_write_reg() error writing 0x%x to " TARGET_ADDR_FMT,
192 value, fespi_info->ctrl_base + address);
193 return result;
194 }
195 return ERROR_OK;
196 }
197
198 static int fespi_disable_hw_mode(struct flash_bank *bank)
199 {
200 uint32_t fctrl;
201 if (fespi_read_reg(bank, &fctrl, FESPI_REG_FCTRL) != ERROR_OK)
202 return ERROR_FAIL;
203 return fespi_write_reg(bank, FESPI_REG_FCTRL, fctrl & ~FESPI_FCTRL_EN);
204 }
205
206 static int fespi_enable_hw_mode(struct flash_bank *bank)
207 {
208 uint32_t fctrl;
209 if (fespi_read_reg(bank, &fctrl, FESPI_REG_FCTRL) != ERROR_OK)
210 return ERROR_FAIL;
211 return fespi_write_reg(bank, FESPI_REG_FCTRL, fctrl | FESPI_FCTRL_EN);
212 }
213
214 static int fespi_set_dir(struct flash_bank *bank, bool dir)
215 {
216 uint32_t fmt;
217 if (fespi_read_reg(bank, &fmt, FESPI_REG_FMT) != ERROR_OK)
218 return ERROR_FAIL;
219
220 return fespi_write_reg(bank, FESPI_REG_FMT,
221 (fmt & ~(FESPI_FMT_DIR(0xFFFFFFFF))) | FESPI_FMT_DIR(dir));
222 }
223
224 static int fespi_txwm_wait(struct flash_bank *bank)
225 {
226 int64_t start = timeval_ms();
227
228 while (1) {
229 uint32_t ip;
230 if (fespi_read_reg(bank, &ip, FESPI_REG_IP) != ERROR_OK)
231 return ERROR_FAIL;
232 if (ip & FESPI_IP_TXWM)
233 break;
234 int64_t now = timeval_ms();
235 if (now - start > 1000) {
236 LOG_ERROR("ip.txwm didn't get set.");
237 return ERROR_TARGET_TIMEOUT;
238 }
239 }
240
241 return ERROR_OK;
242 }
243
244 static int fespi_tx(struct flash_bank *bank, uint8_t in)
245 {
246 int64_t start = timeval_ms();
247
248 while (1) {
249 uint32_t txfifo;
250 if (fespi_read_reg(bank, &txfifo, FESPI_REG_TXFIFO) != ERROR_OK)
251 return ERROR_FAIL;
252 if (!(txfifo >> 31))
253 break;
254 int64_t now = timeval_ms();
255 if (now - start > 1000) {
256 LOG_ERROR("txfifo stayed negative.");
257 return ERROR_TARGET_TIMEOUT;
258 }
259 }
260
261 return fespi_write_reg(bank, FESPI_REG_TXFIFO, in);
262 }
263
264 static int fespi_rx(struct flash_bank *bank, uint8_t *out)
265 {
266 int64_t start = timeval_ms();
267 uint32_t value;
268
269 while (1) {
270 if (fespi_read_reg(bank, &value, FESPI_REG_RXFIFO) != ERROR_OK)
271 return ERROR_FAIL;
272 if (!(value >> 31))
273 break;
274 int64_t now = timeval_ms();
275 if (now - start > 1000) {
276 LOG_ERROR("rxfifo didn't go positive (value=0x%x).", value);
277 return ERROR_TARGET_TIMEOUT;
278 }
279 }
280
281 if (out)
282 *out = value & 0xff;
283
284 return ERROR_OK;
285 }
286
287 /* TODO!!! Why don't we need to call this after writing? */
288 static int fespi_wip(struct flash_bank *bank, int timeout)
289 {
290 int64_t endtime;
291
292 fespi_set_dir(bank, FESPI_DIR_RX);
293
294 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
295 return ERROR_FAIL;
296 endtime = timeval_ms() + timeout;
297
298 fespi_tx(bank, SPIFLASH_READ_STATUS);
299 if (fespi_rx(bank, NULL) != ERROR_OK)
300 return ERROR_FAIL;
301
302 do {
303 alive_sleep(1);
304
305 fespi_tx(bank, 0);
306 uint8_t rx;
307 if (fespi_rx(bank, &rx) != ERROR_OK)
308 return ERROR_FAIL;
309 if ((rx & SPIFLASH_BSY_BIT) == 0) {
310 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
311 return ERROR_FAIL;
312 fespi_set_dir(bank, FESPI_DIR_TX);
313 return ERROR_OK;
314 }
315 } while (timeval_ms() < endtime);
316
317 LOG_ERROR("timeout");
318 return ERROR_FAIL;
319 }
320
321 static int fespi_erase_sector(struct flash_bank *bank, int sector)
322 {
323 struct fespi_flash_bank *fespi_info = bank->driver_priv;
324 int retval;
325
326 retval = fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
327 if (retval != ERROR_OK)
328 return retval;
329 retval = fespi_txwm_wait(bank);
330 if (retval != ERROR_OK)
331 return retval;
332
333 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
334 return ERROR_FAIL;
335 retval = fespi_tx(bank, fespi_info->dev->erase_cmd);
336 if (retval != ERROR_OK)
337 return retval;
338 sector = bank->sectors[sector].offset;
339 retval = fespi_tx(bank, sector >> 16);
340 if (retval != ERROR_OK)
341 return retval;
342 retval = fespi_tx(bank, sector >> 8);
343 if (retval != ERROR_OK)
344 return retval;
345 retval = fespi_tx(bank, sector);
346 if (retval != ERROR_OK)
347 return retval;
348 retval = fespi_txwm_wait(bank);
349 if (retval != ERROR_OK)
350 return retval;
351 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
352 return ERROR_FAIL;
353
354 retval = fespi_wip(bank, FESPI_MAX_TIMEOUT);
355 if (retval != ERROR_OK)
356 return retval;
357
358 return ERROR_OK;
359 }
360
361 static int fespi_erase(struct flash_bank *bank, int first, int last)
362 {
363 struct target *target = bank->target;
364 struct fespi_flash_bank *fespi_info = bank->driver_priv;
365 int retval = ERROR_OK;
366 int sector;
367
368 LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last);
369
370 if (target->state != TARGET_HALTED) {
371 LOG_ERROR("Target not halted");
372 return ERROR_TARGET_NOT_HALTED;
373 }
374
375 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
376 LOG_ERROR("Flash sector invalid");
377 return ERROR_FLASH_SECTOR_INVALID;
378 }
379
380 if (!(fespi_info->probed)) {
381 LOG_ERROR("Flash bank not probed");
382 return ERROR_FLASH_BANK_NOT_PROBED;
383 }
384
385 for (sector = first; sector <= last; sector++) {
386 if (bank->sectors[sector].is_protected) {
387 LOG_ERROR("Flash sector %d protected", sector);
388 return ERROR_FAIL;
389 }
390 }
391
392 if (fespi_info->dev->erase_cmd == 0x00)
393 return ERROR_FLASH_OPER_UNSUPPORTED;
394
395 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
396 return ERROR_FAIL;
397 retval = fespi_txwm_wait(bank);
398 if (retval != ERROR_OK) {
399 LOG_ERROR("WM Didn't go high before attempting.");
400 return retval;
401 }
402
403 /* Disable Hardware accesses*/
404 if (fespi_disable_hw_mode(bank) != ERROR_OK)
405 return ERROR_FAIL;
406
407 /* poll WIP */
408 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
409 if (retval != ERROR_OK)
410 goto done;
411
412 for (sector = first; sector <= last; sector++) {
413 retval = fespi_erase_sector(bank, sector);
414 if (retval != ERROR_OK)
415 goto done;
416 keep_alive();
417 }
418
419 /* Switch to HW mode before return to prompt */
420 done:
421 if (fespi_enable_hw_mode(bank) != ERROR_OK)
422 return ERROR_FAIL;
423 return retval;
424 }
425
426 static int fespi_protect(struct flash_bank *bank, int set,
427 int first, int last)
428 {
429 int sector;
430
431 for (sector = first; sector <= last; sector++)
432 bank->sectors[sector].is_protected = set;
433 return ERROR_OK;
434 }
435
436 static int slow_fespi_write_buffer(struct flash_bank *bank,
437 const uint8_t *buffer, uint32_t offset, uint32_t len)
438 {
439 uint32_t ii;
440
441 if (offset & 0xFF000000) {
442 LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x",
443 offset);
444 return ERROR_FAIL;
445 }
446
447 /* TODO!!! assert that len < page size */
448
449 fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
450 fespi_txwm_wait(bank);
451
452 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
453 return ERROR_FAIL;
454
455 fespi_tx(bank, SPIFLASH_PAGE_PROGRAM);
456
457 fespi_tx(bank, offset >> 16);
458 fespi_tx(bank, offset >> 8);
459 fespi_tx(bank, offset);
460
461 for (ii = 0; ii < len; ii++)
462 fespi_tx(bank, buffer[ii]);
463
464 fespi_txwm_wait(bank);
465
466 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
467 return ERROR_FAIL;
468
469 keep_alive();
470
471 return ERROR_OK;
472 }
473
474 static const uint8_t algorithm_bin[] = {
475 #include "../../../contrib/loaders/flash/fespi/fespi.inc"
476 };
477 #define STEP_EXIT 4
478 #define STEP_TX 8
479 #define STEP_TXWM_WAIT 12
480 #define STEP_WRITE_REG 16
481 #define STEP_WIP_WAIT 20
482 #define STEP_SET_DIR 24
483 #define STEP_NOP 0xff
484
485 struct algorithm_steps {
486 unsigned size;
487 unsigned used;
488 uint8_t **steps;
489 };
490
491 static struct algorithm_steps *as_new(void)
492 {
493 struct algorithm_steps *as = calloc(1, sizeof(struct algorithm_steps));
494 as->size = 8;
495 as->steps = malloc(as->size * sizeof(as->steps[0]));
496 return as;
497 }
498
499 static struct algorithm_steps *as_delete(struct algorithm_steps *as)
500 {
501 for (unsigned step = 0; step < as->used; step++) {
502 free(as->steps[step]);
503 as->steps[step] = NULL;
504 }
505 free(as->steps);
506 free(as);
507 return NULL;
508 }
509
510 static int as_empty(struct algorithm_steps *as)
511 {
512 for (unsigned s = 0; s < as->used; s++) {
513 if (as->steps[s][0] != STEP_NOP)
514 return 0;
515 }
516 return 1;
517 }
518
519 /* Return size of compiled program. */
520 static unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
521 unsigned target_size)
522 {
523 unsigned offset = 0;
524 bool finish_early = false;
525 for (unsigned s = 0; s < as->used && !finish_early; s++) {
526 unsigned bytes_left = target_size - offset;
527 switch (as->steps[s][0]) {
528 case STEP_NOP:
529 break;
530 case STEP_TX:
531 {
532 unsigned size = as->steps[s][1];
533 if (size + 3 > bytes_left) {
534 finish_early = true;
535 break;
536 }
537 memcpy(target + offset, as->steps[s], size + 2);
538 offset += size + 2;
539 break;
540 }
541 case STEP_WRITE_REG:
542 if (4 > bytes_left) {
543 finish_early = true;
544 break;
545 }
546 memcpy(target + offset, as->steps[s], 3);
547 offset += 3;
548 break;
549 case STEP_SET_DIR:
550 if (3 > bytes_left) {
551 finish_early = true;
552 break;
553 }
554 memcpy(target + offset, as->steps[s], 2);
555 offset += 2;
556 break;
557 case STEP_TXWM_WAIT:
558 case STEP_WIP_WAIT:
559 if (2 > bytes_left) {
560 finish_early = true;
561 break;
562 }
563 memcpy(target + offset, as->steps[s], 1);
564 offset += 1;
565 break;
566 default:
567 assert(0);
568 }
569 if (!finish_early)
570 as->steps[s][0] = STEP_NOP;
571 }
572 assert(offset + 1 <= target_size);
573 target[offset++] = STEP_EXIT;
574
575 LOG_DEBUG("%d-byte program:", offset);
576 for (unsigned i = 0; i < offset;) {
577 char buf[80];
578 for (unsigned x = 0; i < offset && x < 16; x++, i++)
579 sprintf(buf + x*3, "%02x ", target[i]);
580 LOG_DEBUG("%s", buf);
581 }
582
583 return offset;
584 }
585
586 static void as_add_step(struct algorithm_steps *as, uint8_t *step)
587 {
588 if (as->used == as->size) {
589 as->size *= 2;
590 as->steps = realloc(as->steps, sizeof(as->steps[0]) * as->size);
591 LOG_DEBUG("Increased size to 0x%x", as->size);
592 }
593 as->steps[as->used] = step;
594 as->used++;
595 }
596
597 static void as_add_tx(struct algorithm_steps *as, unsigned count, const uint8_t *data)
598 {
599 LOG_DEBUG("count=%d", count);
600 while (count > 0) {
601 unsigned step_count = MIN(count, 255);
602 uint8_t *step = malloc(step_count + 2);
603 step[0] = STEP_TX;
604 step[1] = step_count;
605 memcpy(step + 2, data, step_count);
606 as_add_step(as, step);
607 data += step_count;
608 count -= step_count;
609 }
610 }
611
612 static void as_add_tx1(struct algorithm_steps *as, uint8_t byte)
613 {
614 uint8_t data[1];
615 data[0] = byte;
616 as_add_tx(as, 1, data);
617 }
618
619 static void as_add_write_reg(struct algorithm_steps *as, uint8_t offset, uint8_t data)
620 {
621 uint8_t *step = malloc(3);
622 step[0] = STEP_WRITE_REG;
623 step[1] = offset;
624 step[2] = data;
625 as_add_step(as, step);
626 }
627
628 static void as_add_txwm_wait(struct algorithm_steps *as)
629 {
630 uint8_t *step = malloc(1);
631 step[0] = STEP_TXWM_WAIT;
632 as_add_step(as, step);
633 }
634
635 static void as_add_wip_wait(struct algorithm_steps *as)
636 {
637 uint8_t *step = malloc(1);
638 step[0] = STEP_WIP_WAIT;
639 as_add_step(as, step);
640 }
641
642 static void as_add_set_dir(struct algorithm_steps *as, bool dir)
643 {
644 uint8_t *step = malloc(2);
645 step[0] = STEP_SET_DIR;
646 step[1] = FESPI_FMT_DIR(dir);
647 as_add_step(as, step);
648 }
649
650 /* This should write something less than or equal to a page.*/
651 static int steps_add_buffer_write(struct algorithm_steps *as,
652 const uint8_t *buffer, uint32_t chip_offset, uint32_t len)
653 {
654 if (chip_offset & 0xFF000000) {
655 LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x",
656 chip_offset);
657 return ERROR_FAIL;
658 }
659
660 as_add_tx1(as, SPIFLASH_WRITE_ENABLE);
661 as_add_txwm_wait(as);
662 as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
663
664 uint8_t setup[] = {
665 SPIFLASH_PAGE_PROGRAM,
666 chip_offset >> 16,
667 chip_offset >> 8,
668 chip_offset,
669 };
670 as_add_tx(as, sizeof(setup), setup);
671
672 as_add_tx(as, len, buffer);
673 as_add_txwm_wait(as);
674 as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
675
676 /* fespi_wip() */
677 as_add_set_dir(as, FESPI_DIR_RX);
678 as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
679 as_add_wip_wait(as);
680 as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
681 as_add_set_dir(as, FESPI_DIR_TX);
682
683 return ERROR_OK;
684 }
685
686 static int steps_execute(struct algorithm_steps *as,
687 struct flash_bank *bank, struct working_area *algorithm_wa,
688 struct working_area *data_wa)
689 {
690 struct target *target = bank->target;
691 struct fespi_flash_bank *fespi_info = bank->driver_priv;
692 uint32_t ctrl_base = fespi_info->ctrl_base;
693 int xlen = riscv_xlen(target);
694
695 struct reg_param reg_params[2];
696 init_reg_param(&reg_params[0], "a0", xlen, PARAM_OUT);
697 init_reg_param(&reg_params[1], "a1", xlen, PARAM_OUT);
698 buf_set_u64(reg_params[0].value, 0, xlen, ctrl_base);
699 buf_set_u64(reg_params[1].value, 0, xlen, data_wa->address);
700
701 int retval = ERROR_OK;
702 while (!as_empty(as)) {
703 keep_alive();
704 uint8_t *data_buf = malloc(data_wa->size);
705 unsigned bytes = as_compile(as, data_buf, data_wa->size);
706 retval = target_write_buffer(target, data_wa->address, bytes,
707 data_buf);
708 free(data_buf);
709 if (retval != ERROR_OK) {
710 LOG_ERROR("Failed to write data to " TARGET_ADDR_FMT ": %d",
711 data_wa->address, retval);
712 goto exit;
713 }
714
715 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
716 algorithm_wa->address, algorithm_wa->address + 4,
717 10000, NULL);
718 if (retval != ERROR_OK) {
719 LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d",
720 algorithm_wa->address, retval);
721 goto exit;
722 }
723 }
724
725 exit:
726 destroy_reg_param(&reg_params[1]);
727 destroy_reg_param(&reg_params[0]);
728 return retval;
729 }
730
731 static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
732 uint32_t offset, uint32_t count)
733 {
734 struct target *target = bank->target;
735 struct fespi_flash_bank *fespi_info = bank->driver_priv;
736 uint32_t cur_count, page_size, page_offset;
737 int sector;
738 int retval = ERROR_OK;
739
740 LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
741 __func__, offset, count);
742
743 if (target->state != TARGET_HALTED) {
744 LOG_ERROR("Target not halted");
745 return ERROR_TARGET_NOT_HALTED;
746 }
747
748 if (offset + count > fespi_info->dev->size_in_bytes) {
749 LOG_WARNING("Write past end of flash. Extra data discarded.");
750 count = fespi_info->dev->size_in_bytes - offset;
751 }
752
753 /* Check sector protection */
754 for (sector = 0; sector < bank->num_sectors; sector++) {
755 /* Start offset in or before this sector? */
756 /* End offset in or behind this sector? */
757 if ((offset <
758 (bank->sectors[sector].offset + bank->sectors[sector].size))
759 && ((offset + count - 1) >= bank->sectors[sector].offset)
760 && bank->sectors[sector].is_protected) {
761 LOG_ERROR("Flash sector %d protected", sector);
762 return ERROR_FAIL;
763 }
764 }
765
766 struct working_area *algorithm_wa;
767 if (target_alloc_working_area(target, sizeof(algorithm_bin),
768 &algorithm_wa) != ERROR_OK) {
769 LOG_WARNING("Couldn't allocate %zd-byte working area.",
770 sizeof(algorithm_bin));
771 algorithm_wa = NULL;
772 } else {
773 retval = target_write_buffer(target, algorithm_wa->address,
774 sizeof(algorithm_bin), algorithm_bin);
775 if (retval != ERROR_OK) {
776 LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
777 algorithm_wa->address, retval);
778 target_free_working_area(target, algorithm_wa);
779 algorithm_wa = NULL;
780 }
781 }
782
783 struct working_area *data_wa = NULL;
784 unsigned data_wa_size = 2 * count;
785 while (1) {
786 if (data_wa_size < 128) {
787 LOG_WARNING("Couldn't allocate data working area.");
788 target_free_working_area(target, algorithm_wa);
789 algorithm_wa = NULL;
790 }
791 if (target_alloc_working_area_try(target, data_wa_size, &data_wa) ==
792 ERROR_OK) {
793 break;
794 }
795
796 data_wa_size /= 2;
797 }
798
799 /* If no valid page_size, use reasonable default. */
800 page_size = fespi_info->dev->pagesize ?
801 fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
802
803 fespi_txwm_wait(bank);
804
805 /* Disable Hardware accesses*/
806 if (fespi_disable_hw_mode(bank) != ERROR_OK)
807 return ERROR_FAIL;
808
809 struct algorithm_steps *as = as_new();
810
811 /* poll WIP */
812 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
813 if (retval != ERROR_OK)
814 goto err;
815
816 page_offset = offset % page_size;
817 /* central part, aligned words */
818 while (count > 0) {
819 /* clip block at page boundary */
820 if (page_offset + count > page_size)
821 cur_count = page_size - page_offset;
822 else
823 cur_count = count;
824
825 if (algorithm_wa)
826 retval = steps_add_buffer_write(as, buffer, offset, cur_count);
827 else
828 retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
829 if (retval != ERROR_OK)
830 goto err;
831
832 page_offset = 0;
833 buffer += cur_count;
834 offset += cur_count;
835 count -= cur_count;
836 }
837
838 if (algorithm_wa)
839 retval = steps_execute(as, bank, algorithm_wa, data_wa);
840
841 err:
842 if (algorithm_wa) {
843 target_free_working_area(target, data_wa);
844 target_free_working_area(target, algorithm_wa);
845 }
846
847 as_delete(as);
848
849 /* Switch to HW mode before return to prompt */
850 if (fespi_enable_hw_mode(bank) != ERROR_OK)
851 return ERROR_FAIL;
852 return retval;
853 }
854
855 /* Return ID of flash device */
856 /* On exit, SW mode is kept */
857 static int fespi_read_flash_id(struct flash_bank *bank, uint32_t *id)
858 {
859 struct target *target = bank->target;
860 int retval;
861
862 if (target->state != TARGET_HALTED) {
863 LOG_ERROR("Target not halted");
864 return ERROR_TARGET_NOT_HALTED;
865 }
866
867 fespi_txwm_wait(bank);
868
869 /* poll WIP */
870 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
871 if (retval != ERROR_OK)
872 return retval;
873
874 fespi_set_dir(bank, FESPI_DIR_RX);
875
876 /* Send SPI command "read ID" */
877 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
878 return ERROR_FAIL;
879
880 fespi_tx(bank, SPIFLASH_READ_ID);
881 /* Send dummy bytes to actually read the ID.*/
882 fespi_tx(bank, 0);
883 fespi_tx(bank, 0);
884 fespi_tx(bank, 0);
885
886 /* read ID from Receive Register */
887 *id = 0;
888 if (fespi_rx(bank, NULL) != ERROR_OK)
889 return ERROR_FAIL;
890 uint8_t rx;
891 if (fespi_rx(bank, &rx) != ERROR_OK)
892 return ERROR_FAIL;
893 *id = rx;
894 if (fespi_rx(bank, &rx) != ERROR_OK)
895 return ERROR_FAIL;
896 *id |= (rx << 8);
897 if (fespi_rx(bank, &rx) != ERROR_OK)
898 return ERROR_FAIL;
899 *id |= (rx << 16);
900
901 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
902 return ERROR_FAIL;
903
904 fespi_set_dir(bank, FESPI_DIR_TX);
905
906 return ERROR_OK;
907 }
908
909 static int fespi_probe(struct flash_bank *bank)
910 {
911 struct target *target = bank->target;
912 struct fespi_flash_bank *fespi_info = bank->driver_priv;
913 struct flash_sector *sectors;
914 uint32_t id = 0; /* silence uninitialized warning */
915 const struct fespi_target *target_device;
916 int retval;
917 uint32_t sectorsize;
918
919 if (fespi_info->probed)
920 free(bank->sectors);
921 fespi_info->probed = 0;
922
923 if (fespi_info->ctrl_base == 0) {
924 for (target_device = target_devices ; target_device->name ; ++target_device)
925 if (target_device->tap_idcode == target->tap->idcode)
926 break;
927
928 if (!target_device->name) {
929 LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
930 target->tap->idcode);
931 return ERROR_FAIL;
932 }
933
934 fespi_info->ctrl_base = target_device->ctrl_base;
935
936 LOG_DEBUG("Valid FESPI on device %s at address " TARGET_ADDR_FMT,
937 target_device->name, bank->base);
938
939 } else {
940 LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT
941 " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base,
942 bank->base);
943 }
944
945 /* read and decode flash ID; returns in SW mode */
946 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
947 return ERROR_FAIL;
948 fespi_set_dir(bank, FESPI_DIR_TX);
949
950 /* Disable Hardware accesses*/
951 if (fespi_disable_hw_mode(bank) != ERROR_OK)
952 return ERROR_FAIL;
953
954 retval = fespi_read_flash_id(bank, &id);
955
956 if (fespi_enable_hw_mode(bank) != ERROR_OK)
957 return ERROR_FAIL;
958 if (retval != ERROR_OK)
959 return retval;
960
961 fespi_info->dev = NULL;
962 for (const struct flash_device *p = flash_devices; p->name ; p++)
963 if (p->device_id == id) {
964 fespi_info->dev = p;
965 break;
966 }
967
968 if (!fespi_info->dev) {
969 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
970 return ERROR_FAIL;
971 }
972
973 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
974 fespi_info->dev->name, fespi_info->dev->device_id);
975
976 /* Set correct size value */
977 bank->size = fespi_info->dev->size_in_bytes;
978
979 if (bank->size <= (1UL << 16))
980 LOG_WARNING("device needs 2-byte addresses - not implemented");
981 if (bank->size > (1UL << 24))
982 LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
983
984 /* if no sectors, treat whole bank as single sector */
985 sectorsize = fespi_info->dev->sectorsize ?
986 fespi_info->dev->sectorsize : fespi_info->dev->size_in_bytes;
987
988 /* create and fill sectors array */
989 bank->num_sectors = fespi_info->dev->size_in_bytes / sectorsize;
990 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
991 if (sectors == NULL) {
992 LOG_ERROR("not enough memory");
993 return ERROR_FAIL;
994 }
995
996 for (int sector = 0; sector < bank->num_sectors; sector++) {
997 sectors[sector].offset = sector * sectorsize;
998 sectors[sector].size = sectorsize;
999 sectors[sector].is_erased = -1;
1000 sectors[sector].is_protected = 0;
1001 }
1002
1003 bank->sectors = sectors;
1004 fespi_info->probed = 1;
1005 return ERROR_OK;
1006 }
1007
1008 static int fespi_auto_probe(struct flash_bank *bank)
1009 {
1010 struct fespi_flash_bank *fespi_info = bank->driver_priv;
1011 if (fespi_info->probed)
1012 return ERROR_OK;
1013 return fespi_probe(bank);
1014 }
1015
1016 static int fespi_protect_check(struct flash_bank *bank)
1017 {
1018 /* Nothing to do. Protection is only handled in SW. */
1019 return ERROR_OK;
1020 }
1021
1022 static int get_fespi_info(struct flash_bank *bank, char *buf, int buf_size)
1023 {
1024 struct fespi_flash_bank *fespi_info = bank->driver_priv;
1025
1026 if (!(fespi_info->probed)) {
1027 snprintf(buf, buf_size,
1028 "\nFESPI flash bank not probed yet\n");
1029 return ERROR_OK;
1030 }
1031
1032 snprintf(buf, buf_size, "\nFESPI flash information:\n"
1033 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
1034 fespi_info->dev->name, fespi_info->dev->device_id);
1035
1036 return ERROR_OK;
1037 }
1038
1039 const struct flash_driver fespi_flash = {
1040 .name = "fespi",
1041 .flash_bank_command = fespi_flash_bank_command,
1042 .erase = fespi_erase,
1043 .protect = fespi_protect,
1044 .write = fespi_write,
1045 .read = default_flash_read,
1046 .probe = fespi_probe,
1047 .auto_probe = fespi_auto_probe,
1048 .erase_check = default_flash_blank_check,
1049 .protect_check = fespi_protect_check,
1050 .info = get_fespi_info,
1051 .free_driver_priv = default_flash_free_driver_priv
1052 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)