flash/stm32l4x: add support of STM32WB1x
[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 bool 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 E310-G000 SPI Flash", 0x10e31913, 0x10014000 },
140 { "Freedom E310-G002 SPI Flash", 0x20000913, 0x10014000 },
141 { NULL, 0, 0 }
142 };
143
144 FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command)
145 {
146 struct fespi_flash_bank *fespi_info;
147
148 LOG_DEBUG("%s", __func__);
149
150 if (CMD_ARGC < 6)
151 return ERROR_COMMAND_SYNTAX_ERROR;
152
153 fespi_info = malloc(sizeof(struct fespi_flash_bank));
154 if (!fespi_info) {
155 LOG_ERROR("not enough memory");
156 return ERROR_FAIL;
157 }
158
159 bank->driver_priv = fespi_info;
160 fespi_info->probed = false;
161 fespi_info->ctrl_base = 0;
162 if (CMD_ARGC >= 7) {
163 COMMAND_PARSE_ADDRESS(CMD_ARGV[6], fespi_info->ctrl_base);
164 LOG_DEBUG("ASSUMING FESPI device at ctrl_base = " TARGET_ADDR_FMT,
165 fespi_info->ctrl_base);
166 }
167
168 return ERROR_OK;
169 }
170
171 static int fespi_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_t address)
172 {
173 struct target *target = bank->target;
174 struct fespi_flash_bank *fespi_info = bank->driver_priv;
175
176 int result = target_read_u32(target, fespi_info->ctrl_base + address, value);
177 if (result != ERROR_OK) {
178 LOG_ERROR("fespi_read_reg() error at " TARGET_ADDR_FMT,
179 fespi_info->ctrl_base + address);
180 return result;
181 }
182 return ERROR_OK;
183 }
184
185 static int fespi_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value)
186 {
187 struct target *target = bank->target;
188 struct fespi_flash_bank *fespi_info = bank->driver_priv;
189
190 int result = target_write_u32(target, fespi_info->ctrl_base + address, value);
191 if (result != ERROR_OK) {
192 LOG_ERROR("fespi_write_reg() error writing 0x%" PRIx32 " to " TARGET_ADDR_FMT,
193 value, fespi_info->ctrl_base + address);
194 return result;
195 }
196 return ERROR_OK;
197 }
198
199 static int fespi_disable_hw_mode(struct flash_bank *bank)
200 {
201 uint32_t fctrl;
202 if (fespi_read_reg(bank, &fctrl, FESPI_REG_FCTRL) != ERROR_OK)
203 return ERROR_FAIL;
204 return fespi_write_reg(bank, FESPI_REG_FCTRL, fctrl & ~FESPI_FCTRL_EN);
205 }
206
207 static int fespi_enable_hw_mode(struct flash_bank *bank)
208 {
209 uint32_t fctrl;
210 if (fespi_read_reg(bank, &fctrl, FESPI_REG_FCTRL) != ERROR_OK)
211 return ERROR_FAIL;
212 return fespi_write_reg(bank, FESPI_REG_FCTRL, fctrl | FESPI_FCTRL_EN);
213 }
214
215 static int fespi_set_dir(struct flash_bank *bank, bool dir)
216 {
217 uint32_t fmt;
218 if (fespi_read_reg(bank, &fmt, FESPI_REG_FMT) != ERROR_OK)
219 return ERROR_FAIL;
220
221 return fespi_write_reg(bank, FESPI_REG_FMT,
222 (fmt & ~(FESPI_FMT_DIR(0xFFFFFFFF))) | FESPI_FMT_DIR(dir));
223 }
224
225 static int fespi_txwm_wait(struct flash_bank *bank)
226 {
227 int64_t start = timeval_ms();
228
229 while (1) {
230 uint32_t ip;
231 if (fespi_read_reg(bank, &ip, FESPI_REG_IP) != ERROR_OK)
232 return ERROR_FAIL;
233 if (ip & FESPI_IP_TXWM)
234 break;
235 int64_t now = timeval_ms();
236 if (now - start > 1000) {
237 LOG_ERROR("ip.txwm didn't get set.");
238 return ERROR_TARGET_TIMEOUT;
239 }
240 }
241
242 return ERROR_OK;
243 }
244
245 static int fespi_tx(struct flash_bank *bank, uint8_t in)
246 {
247 int64_t start = timeval_ms();
248
249 while (1) {
250 uint32_t txfifo;
251 if (fespi_read_reg(bank, &txfifo, FESPI_REG_TXFIFO) != ERROR_OK)
252 return ERROR_FAIL;
253 if (!(txfifo >> 31))
254 break;
255 int64_t now = timeval_ms();
256 if (now - start > 1000) {
257 LOG_ERROR("txfifo stayed negative.");
258 return ERROR_TARGET_TIMEOUT;
259 }
260 }
261
262 return fespi_write_reg(bank, FESPI_REG_TXFIFO, in);
263 }
264
265 static int fespi_rx(struct flash_bank *bank, uint8_t *out)
266 {
267 int64_t start = timeval_ms();
268 uint32_t value;
269
270 while (1) {
271 if (fespi_read_reg(bank, &value, FESPI_REG_RXFIFO) != ERROR_OK)
272 return ERROR_FAIL;
273 if (!(value >> 31))
274 break;
275 int64_t now = timeval_ms();
276 if (now - start > 1000) {
277 LOG_ERROR("rxfifo didn't go positive (value=0x%" PRIx32 ").", value);
278 return ERROR_TARGET_TIMEOUT;
279 }
280 }
281
282 if (out)
283 *out = value & 0xff;
284
285 return ERROR_OK;
286 }
287
288 /* TODO!!! Why don't we need to call this after writing? */
289 static int fespi_wip(struct flash_bank *bank, int timeout)
290 {
291 int64_t endtime;
292
293 fespi_set_dir(bank, FESPI_DIR_RX);
294
295 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
296 return ERROR_FAIL;
297 endtime = timeval_ms() + timeout;
298
299 fespi_tx(bank, SPIFLASH_READ_STATUS);
300 if (fespi_rx(bank, NULL) != ERROR_OK)
301 return ERROR_FAIL;
302
303 do {
304 alive_sleep(1);
305
306 fespi_tx(bank, 0);
307 uint8_t rx;
308 if (fespi_rx(bank, &rx) != ERROR_OK)
309 return ERROR_FAIL;
310 if ((rx & SPIFLASH_BSY_BIT) == 0) {
311 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
312 return ERROR_FAIL;
313 fespi_set_dir(bank, FESPI_DIR_TX);
314 return ERROR_OK;
315 }
316 } while (timeval_ms() < endtime);
317
318 LOG_ERROR("timeout");
319 return ERROR_FAIL;
320 }
321
322 static int fespi_erase_sector(struct flash_bank *bank, int sector)
323 {
324 struct fespi_flash_bank *fespi_info = bank->driver_priv;
325 int retval;
326
327 retval = fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
328 if (retval != ERROR_OK)
329 return retval;
330 retval = fespi_txwm_wait(bank);
331 if (retval != ERROR_OK)
332 return retval;
333
334 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
335 return ERROR_FAIL;
336 retval = fespi_tx(bank, fespi_info->dev->erase_cmd);
337 if (retval != ERROR_OK)
338 return retval;
339 sector = bank->sectors[sector].offset;
340 retval = fespi_tx(bank, sector >> 16);
341 if (retval != ERROR_OK)
342 return retval;
343 retval = fespi_tx(bank, sector >> 8);
344 if (retval != ERROR_OK)
345 return retval;
346 retval = fespi_tx(bank, sector);
347 if (retval != ERROR_OK)
348 return retval;
349 retval = fespi_txwm_wait(bank);
350 if (retval != ERROR_OK)
351 return retval;
352 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
353 return ERROR_FAIL;
354
355 retval = fespi_wip(bank, FESPI_MAX_TIMEOUT);
356 if (retval != ERROR_OK)
357 return retval;
358
359 return ERROR_OK;
360 }
361
362 static int fespi_erase(struct flash_bank *bank, unsigned int first,
363 unsigned int last)
364 {
365 struct target *target = bank->target;
366 struct fespi_flash_bank *fespi_info = bank->driver_priv;
367 int retval = ERROR_OK;
368
369 LOG_DEBUG("%s: from sector %u to sector %u", __func__, first, last);
370
371 if (target->state != TARGET_HALTED) {
372 LOG_ERROR("Target not halted");
373 return ERROR_TARGET_NOT_HALTED;
374 }
375
376 if ((last < first) || (last >= bank->num_sectors)) {
377 LOG_ERROR("Flash sector invalid");
378 return ERROR_FLASH_SECTOR_INVALID;
379 }
380
381 if (!(fespi_info->probed)) {
382 LOG_ERROR("Flash bank not probed");
383 return ERROR_FLASH_BANK_NOT_PROBED;
384 }
385
386 for (unsigned int sector = first; sector <= last; sector++) {
387 if (bank->sectors[sector].is_protected) {
388 LOG_ERROR("Flash sector %u protected", sector);
389 return ERROR_FAIL;
390 }
391 }
392
393 if (fespi_info->dev->erase_cmd == 0x00)
394 return ERROR_FLASH_OPER_UNSUPPORTED;
395
396 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
397 return ERROR_FAIL;
398 retval = fespi_txwm_wait(bank);
399 if (retval != ERROR_OK) {
400 LOG_ERROR("WM Didn't go high before attempting.");
401 return retval;
402 }
403
404 /* Disable Hardware accesses*/
405 if (fespi_disable_hw_mode(bank) != ERROR_OK)
406 return ERROR_FAIL;
407
408 /* poll WIP */
409 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
410 if (retval != ERROR_OK)
411 goto done;
412
413 for (unsigned int sector = first; sector <= last; sector++) {
414 retval = fespi_erase_sector(bank, sector);
415 if (retval != ERROR_OK)
416 goto done;
417 keep_alive();
418 }
419
420 /* Switch to HW mode before return to prompt */
421 done:
422 if (fespi_enable_hw_mode(bank) != ERROR_OK)
423 return ERROR_FAIL;
424 return retval;
425 }
426
427 static int fespi_protect(struct flash_bank *bank, int set,
428 unsigned int first, unsigned int last)
429 {
430 for (unsigned int sector = first; sector <= last; sector++)
431 bank->sectors[sector].is_protected = set;
432 return ERROR_OK;
433 }
434
435 static int slow_fespi_write_buffer(struct flash_bank *bank,
436 const uint8_t *buffer, uint32_t offset, uint32_t len)
437 {
438 uint32_t ii;
439
440 if (offset & 0xFF000000) {
441 LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%" PRIx32,
442 offset);
443 return ERROR_FAIL;
444 }
445
446 /* TODO!!! assert that len < page size */
447
448 fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
449 fespi_txwm_wait(bank);
450
451 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
452 return ERROR_FAIL;
453
454 fespi_tx(bank, SPIFLASH_PAGE_PROGRAM);
455
456 fespi_tx(bank, offset >> 16);
457 fespi_tx(bank, offset >> 8);
458 fespi_tx(bank, offset);
459
460 for (ii = 0; ii < len; ii++)
461 fespi_tx(bank, buffer[ii]);
462
463 fespi_txwm_wait(bank);
464
465 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
466 return ERROR_FAIL;
467
468 keep_alive();
469
470 return ERROR_OK;
471 }
472
473 static const uint8_t algorithm_bin[] = {
474 #include "../../../contrib/loaders/flash/fespi/fespi.inc"
475 };
476 #define STEP_EXIT 4
477 #define STEP_TX 8
478 #define STEP_TXWM_WAIT 12
479 #define STEP_WRITE_REG 16
480 #define STEP_WIP_WAIT 20
481 #define STEP_SET_DIR 24
482 #define STEP_NOP 0xff
483
484 struct algorithm_steps {
485 unsigned size;
486 unsigned used;
487 uint8_t **steps;
488 };
489
490 static struct algorithm_steps *as_new(void)
491 {
492 struct algorithm_steps *as = calloc(1, sizeof(struct algorithm_steps));
493 as->size = 8;
494 as->steps = malloc(as->size * sizeof(as->steps[0]));
495 return as;
496 }
497
498 static struct algorithm_steps *as_delete(struct algorithm_steps *as)
499 {
500 for (unsigned step = 0; step < as->used; step++) {
501 free(as->steps[step]);
502 as->steps[step] = NULL;
503 }
504 free(as->steps);
505 free(as);
506 return NULL;
507 }
508
509 static int as_empty(struct algorithm_steps *as)
510 {
511 for (unsigned s = 0; s < as->used; s++) {
512 if (as->steps[s][0] != STEP_NOP)
513 return 0;
514 }
515 return 1;
516 }
517
518 /* Return size of compiled program. */
519 static unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
520 unsigned target_size)
521 {
522 unsigned offset = 0;
523 bool finish_early = false;
524 for (unsigned s = 0; s < as->used && !finish_early; s++) {
525 unsigned bytes_left = target_size - offset;
526 switch (as->steps[s][0]) {
527 case STEP_NOP:
528 break;
529 case STEP_TX:
530 {
531 unsigned size = as->steps[s][1];
532 if (size + 3 > bytes_left) {
533 finish_early = true;
534 break;
535 }
536 memcpy(target + offset, as->steps[s], size + 2);
537 offset += size + 2;
538 break;
539 }
540 case STEP_WRITE_REG:
541 if (bytes_left < 4) {
542 finish_early = true;
543 break;
544 }
545 memcpy(target + offset, as->steps[s], 3);
546 offset += 3;
547 break;
548 case STEP_SET_DIR:
549 if (bytes_left < 3) {
550 finish_early = true;
551 break;
552 }
553 memcpy(target + offset, as->steps[s], 2);
554 offset += 2;
555 break;
556 case STEP_TXWM_WAIT:
557 case STEP_WIP_WAIT:
558 if (bytes_left < 2) {
559 finish_early = true;
560 break;
561 }
562 memcpy(target + offset, as->steps[s], 1);
563 offset += 1;
564 break;
565 default:
566 assert(0);
567 }
568 if (!finish_early)
569 as->steps[s][0] = STEP_NOP;
570 }
571 assert(offset + 1 <= target_size);
572 target[offset++] = STEP_EXIT;
573
574 LOG_DEBUG("%d-byte program:", offset);
575 for (unsigned i = 0; i < offset;) {
576 char buf[80];
577 for (unsigned x = 0; i < offset && x < 16; x++, i++)
578 sprintf(buf + x*3, "%02x ", target[i]);
579 LOG_DEBUG("%s", buf);
580 }
581
582 return offset;
583 }
584
585 static void as_add_step(struct algorithm_steps *as, uint8_t *step)
586 {
587 if (as->used == as->size) {
588 as->size *= 2;
589 as->steps = realloc(as->steps, sizeof(as->steps[0]) * as->size);
590 LOG_DEBUG("Increased size to 0x%x", as->size);
591 }
592 as->steps[as->used] = step;
593 as->used++;
594 }
595
596 static void as_add_tx(struct algorithm_steps *as, unsigned count, const uint8_t *data)
597 {
598 LOG_DEBUG("count=%d", count);
599 while (count > 0) {
600 unsigned step_count = MIN(count, 255);
601 uint8_t *step = malloc(step_count + 2);
602 step[0] = STEP_TX;
603 step[1] = step_count;
604 memcpy(step + 2, data, step_count);
605 as_add_step(as, step);
606 data += step_count;
607 count -= step_count;
608 }
609 }
610
611 static void as_add_tx1(struct algorithm_steps *as, uint8_t byte)
612 {
613 uint8_t data[1];
614 data[0] = byte;
615 as_add_tx(as, 1, data);
616 }
617
618 static void as_add_write_reg(struct algorithm_steps *as, uint8_t offset, uint8_t data)
619 {
620 uint8_t *step = malloc(3);
621 step[0] = STEP_WRITE_REG;
622 step[1] = offset;
623 step[2] = data;
624 as_add_step(as, step);
625 }
626
627 static void as_add_txwm_wait(struct algorithm_steps *as)
628 {
629 uint8_t *step = malloc(1);
630 step[0] = STEP_TXWM_WAIT;
631 as_add_step(as, step);
632 }
633
634 static void as_add_wip_wait(struct algorithm_steps *as)
635 {
636 uint8_t *step = malloc(1);
637 step[0] = STEP_WIP_WAIT;
638 as_add_step(as, step);
639 }
640
641 static void as_add_set_dir(struct algorithm_steps *as, bool dir)
642 {
643 uint8_t *step = malloc(2);
644 step[0] = STEP_SET_DIR;
645 step[1] = FESPI_FMT_DIR(dir);
646 as_add_step(as, step);
647 }
648
649 /* This should write something less than or equal to a page.*/
650 static int steps_add_buffer_write(struct algorithm_steps *as,
651 const uint8_t *buffer, uint32_t chip_offset, uint32_t len)
652 {
653 if (chip_offset & 0xFF000000) {
654 LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%" PRIx32,
655 chip_offset);
656 return ERROR_FAIL;
657 }
658
659 as_add_tx1(as, SPIFLASH_WRITE_ENABLE);
660 as_add_txwm_wait(as);
661 as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
662
663 uint8_t setup[] = {
664 SPIFLASH_PAGE_PROGRAM,
665 chip_offset >> 16,
666 chip_offset >> 8,
667 chip_offset,
668 };
669 as_add_tx(as, sizeof(setup), setup);
670
671 as_add_tx(as, len, buffer);
672 as_add_txwm_wait(as);
673 as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
674
675 /* fespi_wip() */
676 as_add_set_dir(as, FESPI_DIR_RX);
677 as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
678 as_add_wip_wait(as);
679 as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
680 as_add_set_dir(as, FESPI_DIR_TX);
681
682 return ERROR_OK;
683 }
684
685 static int steps_execute(struct algorithm_steps *as,
686 struct flash_bank *bank, struct working_area *algorithm_wa,
687 struct working_area *data_wa)
688 {
689 struct target *target = bank->target;
690 struct fespi_flash_bank *fespi_info = bank->driver_priv;
691 uint32_t ctrl_base = fespi_info->ctrl_base;
692 int xlen = riscv_xlen(target);
693
694 struct reg_param reg_params[2];
695 init_reg_param(&reg_params[0], "a0", xlen, PARAM_OUT);
696 init_reg_param(&reg_params[1], "a1", xlen, PARAM_OUT);
697 buf_set_u64(reg_params[0].value, 0, xlen, ctrl_base);
698 buf_set_u64(reg_params[1].value, 0, xlen, data_wa->address);
699
700 int retval = ERROR_OK;
701 while (!as_empty(as)) {
702 keep_alive();
703 uint8_t *data_buf = malloc(data_wa->size);
704 unsigned bytes = as_compile(as, data_buf, data_wa->size);
705 retval = target_write_buffer(target, data_wa->address, bytes,
706 data_buf);
707 free(data_buf);
708 if (retval != ERROR_OK) {
709 LOG_ERROR("Failed to write data to " TARGET_ADDR_FMT ": %d",
710 data_wa->address, retval);
711 goto exit;
712 }
713
714 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
715 algorithm_wa->address, algorithm_wa->address + 4,
716 10000, NULL);
717 if (retval != ERROR_OK) {
718 LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d",
719 algorithm_wa->address, retval);
720 goto exit;
721 }
722 }
723
724 exit:
725 destroy_reg_param(&reg_params[1]);
726 destroy_reg_param(&reg_params[0]);
727 return retval;
728 }
729
730 static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
731 uint32_t offset, uint32_t count)
732 {
733 struct target *target = bank->target;
734 struct fespi_flash_bank *fespi_info = bank->driver_priv;
735 uint32_t cur_count, page_size, page_offset;
736 int retval = ERROR_OK;
737
738 LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
739 __func__, offset, count);
740
741 if (target->state != TARGET_HALTED) {
742 LOG_ERROR("Target not halted");
743 return ERROR_TARGET_NOT_HALTED;
744 }
745
746 if (offset + count > fespi_info->dev->size_in_bytes) {
747 LOG_WARNING("Write past end of flash. Extra data discarded.");
748 count = fespi_info->dev->size_in_bytes - offset;
749 }
750
751 /* Check sector protection */
752 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
753 /* Start offset in or before this sector? */
754 /* End offset in or behind this sector? */
755 if ((offset <
756 (bank->sectors[sector].offset + bank->sectors[sector].size))
757 && ((offset + count - 1) >= bank->sectors[sector].offset)
758 && bank->sectors[sector].is_protected) {
759 LOG_ERROR("Flash sector %u protected", sector);
760 return ERROR_FAIL;
761 }
762 }
763
764 struct working_area *algorithm_wa;
765 if (target_alloc_working_area(target, sizeof(algorithm_bin),
766 &algorithm_wa) != ERROR_OK) {
767 LOG_WARNING("Couldn't allocate %zd-byte working area.",
768 sizeof(algorithm_bin));
769 algorithm_wa = NULL;
770 } else {
771 retval = target_write_buffer(target, algorithm_wa->address,
772 sizeof(algorithm_bin), algorithm_bin);
773 if (retval != ERROR_OK) {
774 LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
775 algorithm_wa->address, retval);
776 target_free_working_area(target, algorithm_wa);
777 algorithm_wa = NULL;
778 }
779 }
780
781 struct working_area *data_wa = NULL;
782 unsigned data_wa_size = 2 * count;
783 while (1) {
784 if (data_wa_size < 128) {
785 LOG_WARNING("Couldn't allocate data working area.");
786 target_free_working_area(target, algorithm_wa);
787 algorithm_wa = NULL;
788 }
789 if (target_alloc_working_area_try(target, data_wa_size, &data_wa) ==
790 ERROR_OK) {
791 break;
792 }
793
794 data_wa_size /= 2;
795 }
796
797 /* If no valid page_size, use reasonable default. */
798 page_size = fespi_info->dev->pagesize ?
799 fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
800
801 fespi_txwm_wait(bank);
802
803 /* Disable Hardware accesses*/
804 if (fespi_disable_hw_mode(bank) != ERROR_OK)
805 return ERROR_FAIL;
806
807 struct algorithm_steps *as = as_new();
808
809 /* poll WIP */
810 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
811 if (retval != ERROR_OK)
812 goto err;
813
814 page_offset = offset % page_size;
815 /* central part, aligned words */
816 while (count > 0) {
817 /* clip block at page boundary */
818 if (page_offset + count > page_size)
819 cur_count = page_size - page_offset;
820 else
821 cur_count = count;
822
823 if (algorithm_wa)
824 retval = steps_add_buffer_write(as, buffer, offset, cur_count);
825 else
826 retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
827 if (retval != ERROR_OK)
828 goto err;
829
830 page_offset = 0;
831 buffer += cur_count;
832 offset += cur_count;
833 count -= cur_count;
834 }
835
836 if (algorithm_wa)
837 retval = steps_execute(as, bank, algorithm_wa, data_wa);
838
839 err:
840 if (algorithm_wa) {
841 target_free_working_area(target, data_wa);
842 target_free_working_area(target, algorithm_wa);
843 }
844
845 as_delete(as);
846
847 /* Switch to HW mode before return to prompt */
848 if (fespi_enable_hw_mode(bank) != ERROR_OK)
849 return ERROR_FAIL;
850 return retval;
851 }
852
853 /* Return ID of flash device */
854 /* On exit, SW mode is kept */
855 static int fespi_read_flash_id(struct flash_bank *bank, uint32_t *id)
856 {
857 struct target *target = bank->target;
858 int retval;
859
860 if (target->state != TARGET_HALTED) {
861 LOG_ERROR("Target not halted");
862 return ERROR_TARGET_NOT_HALTED;
863 }
864
865 fespi_txwm_wait(bank);
866
867 /* poll WIP */
868 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
869 if (retval != ERROR_OK)
870 return retval;
871
872 fespi_set_dir(bank, FESPI_DIR_RX);
873
874 /* Send SPI command "read ID" */
875 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
876 return ERROR_FAIL;
877
878 fespi_tx(bank, SPIFLASH_READ_ID);
879 /* Send dummy bytes to actually read the ID.*/
880 fespi_tx(bank, 0);
881 fespi_tx(bank, 0);
882 fespi_tx(bank, 0);
883
884 /* read ID from Receive Register */
885 *id = 0;
886 if (fespi_rx(bank, NULL) != ERROR_OK)
887 return ERROR_FAIL;
888 uint8_t rx;
889 if (fespi_rx(bank, &rx) != ERROR_OK)
890 return ERROR_FAIL;
891 *id = rx;
892 if (fespi_rx(bank, &rx) != ERROR_OK)
893 return ERROR_FAIL;
894 *id |= (rx << 8);
895 if (fespi_rx(bank, &rx) != ERROR_OK)
896 return ERROR_FAIL;
897 *id |= (rx << 16);
898
899 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
900 return ERROR_FAIL;
901
902 fespi_set_dir(bank, FESPI_DIR_TX);
903
904 return ERROR_OK;
905 }
906
907 static int fespi_probe(struct flash_bank *bank)
908 {
909 struct target *target = bank->target;
910 struct fespi_flash_bank *fespi_info = bank->driver_priv;
911 struct flash_sector *sectors;
912 uint32_t id = 0; /* silence uninitialized warning */
913 const struct fespi_target *target_device;
914 int retval;
915 uint32_t sectorsize;
916
917 if (fespi_info->probed)
918 free(bank->sectors);
919 fespi_info->probed = false;
920
921 if (fespi_info->ctrl_base == 0) {
922 for (target_device = target_devices ; target_device->name ; ++target_device)
923 if (target_device->tap_idcode == target->tap->idcode)
924 break;
925
926 if (!target_device->name) {
927 LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
928 target->tap->idcode);
929 return ERROR_FAIL;
930 }
931
932 fespi_info->ctrl_base = target_device->ctrl_base;
933
934 LOG_DEBUG("Valid FESPI on device %s at address " TARGET_ADDR_FMT,
935 target_device->name, bank->base);
936
937 } else {
938 LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT
939 " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base,
940 bank->base);
941 }
942
943 /* read and decode flash ID; returns in SW mode */
944 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
945 return ERROR_FAIL;
946 fespi_set_dir(bank, FESPI_DIR_TX);
947
948 /* Disable Hardware accesses*/
949 if (fespi_disable_hw_mode(bank) != ERROR_OK)
950 return ERROR_FAIL;
951
952 retval = fespi_read_flash_id(bank, &id);
953
954 if (fespi_enable_hw_mode(bank) != ERROR_OK)
955 return ERROR_FAIL;
956 if (retval != ERROR_OK)
957 return retval;
958
959 fespi_info->dev = NULL;
960 for (const struct flash_device *p = flash_devices; p->name ; p++)
961 if (p->device_id == id) {
962 fespi_info->dev = p;
963 break;
964 }
965
966 if (!fespi_info->dev) {
967 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
968 return ERROR_FAIL;
969 }
970
971 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
972 fespi_info->dev->name, fespi_info->dev->device_id);
973
974 /* Set correct size value */
975 bank->size = fespi_info->dev->size_in_bytes;
976
977 if (bank->size <= (1UL << 16))
978 LOG_WARNING("device needs 2-byte addresses - not implemented");
979 if (bank->size > (1UL << 24))
980 LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
981
982 /* if no sectors, treat whole bank as single sector */
983 sectorsize = fespi_info->dev->sectorsize ?
984 fespi_info->dev->sectorsize : fespi_info->dev->size_in_bytes;
985
986 /* create and fill sectors array */
987 bank->num_sectors = fespi_info->dev->size_in_bytes / sectorsize;
988 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
989 if (!sectors) {
990 LOG_ERROR("not enough memory");
991 return ERROR_FAIL;
992 }
993
994 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
995 sectors[sector].offset = sector * sectorsize;
996 sectors[sector].size = sectorsize;
997 sectors[sector].is_erased = -1;
998 sectors[sector].is_protected = 0;
999 }
1000
1001 bank->sectors = sectors;
1002 fespi_info->probed = true;
1003 return ERROR_OK;
1004 }
1005
1006 static int fespi_auto_probe(struct flash_bank *bank)
1007 {
1008 struct fespi_flash_bank *fespi_info = bank->driver_priv;
1009 if (fespi_info->probed)
1010 return ERROR_OK;
1011 return fespi_probe(bank);
1012 }
1013
1014 static int fespi_protect_check(struct flash_bank *bank)
1015 {
1016 /* Nothing to do. Protection is only handled in SW. */
1017 return ERROR_OK;
1018 }
1019
1020 static int get_fespi_info(struct flash_bank *bank, struct command_invocation *cmd)
1021 {
1022 struct fespi_flash_bank *fespi_info = bank->driver_priv;
1023
1024 if (!(fespi_info->probed)) {
1025 command_print_sameline(cmd, "\nFESPI flash bank not probed yet\n");
1026 return ERROR_OK;
1027 }
1028
1029 command_print_sameline(cmd, "\nFESPI flash information:\n"
1030 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
1031 fespi_info->dev->name, fespi_info->dev->device_id);
1032
1033 return ERROR_OK;
1034 }
1035
1036 const struct flash_driver fespi_flash = {
1037 .name = "fespi",
1038 .flash_bank_command = fespi_flash_bank_command,
1039 .erase = fespi_erase,
1040 .protect = fespi_protect,
1041 .write = fespi_write,
1042 .read = default_flash_read,
1043 .probe = fespi_probe,
1044 .auto_probe = fespi_auto_probe,
1045 .erase_check = default_flash_blank_check,
1046 .protect_check = fespi_protect_check,
1047 .info = get_fespi_info,
1048 .free_driver_priv = default_flash_free_driver_priv
1049 };

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)