flash/nor/fespi: algorithm, large address, errors
[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 if (bank->size > 0x1000000) {
341 retval = fespi_tx(bank, sector >> 24);
342 if (retval != ERROR_OK)
343 return retval;
344 }
345 retval = fespi_tx(bank, sector >> 16);
346 if (retval != ERROR_OK)
347 return retval;
348 retval = fespi_tx(bank, sector >> 8);
349 if (retval != ERROR_OK)
350 return retval;
351 retval = fespi_tx(bank, sector);
352 if (retval != ERROR_OK)
353 return retval;
354 retval = fespi_txwm_wait(bank);
355 if (retval != ERROR_OK)
356 return retval;
357 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
358 return ERROR_FAIL;
359
360 retval = fespi_wip(bank, FESPI_MAX_TIMEOUT);
361 if (retval != ERROR_OK)
362 return retval;
363
364 return ERROR_OK;
365 }
366
367 static int fespi_erase(struct flash_bank *bank, unsigned int first,
368 unsigned int last)
369 {
370 struct target *target = bank->target;
371 struct fespi_flash_bank *fespi_info = bank->driver_priv;
372 int retval = ERROR_OK;
373
374 LOG_DEBUG("%s: from sector %u to sector %u", __func__, first, last);
375
376 if (target->state != TARGET_HALTED) {
377 LOG_ERROR("Target not halted");
378 return ERROR_TARGET_NOT_HALTED;
379 }
380
381 if ((last < first) || (last >= bank->num_sectors)) {
382 LOG_ERROR("Flash sector invalid");
383 return ERROR_FLASH_SECTOR_INVALID;
384 }
385
386 if (!(fespi_info->probed)) {
387 LOG_ERROR("Flash bank not probed");
388 return ERROR_FLASH_BANK_NOT_PROBED;
389 }
390
391 for (unsigned int sector = first; sector <= last; sector++) {
392 if (bank->sectors[sector].is_protected) {
393 LOG_ERROR("Flash sector %u protected", sector);
394 return ERROR_FAIL;
395 }
396 }
397
398 if (fespi_info->dev->erase_cmd == 0x00)
399 return ERROR_FLASH_OPER_UNSUPPORTED;
400
401 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
402 return ERROR_FAIL;
403 retval = fespi_txwm_wait(bank);
404 if (retval != ERROR_OK) {
405 LOG_ERROR("WM Didn't go high before attempting.");
406 return retval;
407 }
408
409 /* Disable Hardware accesses*/
410 if (fespi_disable_hw_mode(bank) != ERROR_OK)
411 return ERROR_FAIL;
412
413 /* poll WIP */
414 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
415 if (retval != ERROR_OK)
416 goto done;
417
418 for (unsigned int sector = first; sector <= last; sector++) {
419 retval = fespi_erase_sector(bank, sector);
420 if (retval != ERROR_OK)
421 goto done;
422 keep_alive();
423 }
424
425 /* Switch to HW mode before return to prompt */
426 done:
427 if (fespi_enable_hw_mode(bank) != ERROR_OK)
428 return ERROR_FAIL;
429 return retval;
430 }
431
432 static int fespi_protect(struct flash_bank *bank, int set,
433 unsigned int first, unsigned int last)
434 {
435 for (unsigned int sector = first; sector <= last; sector++)
436 bank->sectors[sector].is_protected = set;
437 return ERROR_OK;
438 }
439
440 static int slow_fespi_write_buffer(struct flash_bank *bank,
441 const uint8_t *buffer, uint32_t offset, uint32_t len)
442 {
443 struct fespi_flash_bank *fespi_info = bank->driver_priv;
444 uint32_t ii;
445
446 /* TODO!!! assert that len < page size */
447
448 if (fespi_tx(bank, SPIFLASH_WRITE_ENABLE) != ERROR_OK)
449 return ERROR_FAIL;
450 if (fespi_txwm_wait(bank) != ERROR_OK)
451 return ERROR_FAIL;
452
453 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
454 return ERROR_FAIL;
455
456 if (fespi_tx(bank, fespi_info->dev->pprog_cmd) != ERROR_OK)
457 return ERROR_FAIL;
458
459 if (bank->size > 0x1000000 && fespi_tx(bank, offset >> 24) != ERROR_OK)
460 return ERROR_FAIL;
461 if (fespi_tx(bank, offset >> 16) != ERROR_OK)
462 return ERROR_FAIL;
463 if (fespi_tx(bank, offset >> 8) != ERROR_OK)
464 return ERROR_FAIL;
465 if (fespi_tx(bank, offset) != ERROR_OK)
466 return ERROR_FAIL;
467
468 for (ii = 0; ii < len; ii++) {
469 if (fespi_tx(bank, buffer[ii]) != ERROR_OK)
470 return ERROR_FAIL;
471 }
472
473 if (fespi_txwm_wait(bank) != ERROR_OK)
474 return ERROR_FAIL;
475
476 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
477 return ERROR_FAIL;
478
479 keep_alive();
480
481 return ERROR_OK;
482 }
483
484 static const uint8_t riscv32_bin[] = {
485 #include "../../../contrib/loaders/flash/fespi/riscv32_fespi.inc"
486 };
487
488 static const uint8_t riscv64_bin[] = {
489 #include "../../../contrib/loaders/flash/fespi/riscv64_fespi.inc"
490 };
491
492 static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
493 uint32_t offset, uint32_t count)
494 {
495 struct target *target = bank->target;
496 struct fespi_flash_bank *fespi_info = bank->driver_priv;
497 uint32_t cur_count, page_size;
498 int retval = ERROR_OK;
499
500 LOG_DEBUG("bank->size=0x%x offset=0x%08" PRIx32 " count=0x%08" PRIx32,
501 bank->size, offset, count);
502
503 if (target->state != TARGET_HALTED) {
504 LOG_ERROR("Target not halted");
505 return ERROR_TARGET_NOT_HALTED;
506 }
507
508 if (offset + count > fespi_info->dev->size_in_bytes) {
509 LOG_WARNING("Write past end of flash. Extra data discarded.");
510 count = fespi_info->dev->size_in_bytes - offset;
511 }
512
513 /* Check sector protection */
514 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
515 /* Start offset in or before this sector? */
516 /* End offset in or behind this sector? */
517 if ((offset <
518 (bank->sectors[sector].offset + bank->sectors[sector].size))
519 && ((offset + count - 1) >= bank->sectors[sector].offset)
520 && bank->sectors[sector].is_protected) {
521 LOG_ERROR("Flash sector %u protected", sector);
522 return ERROR_FAIL;
523 }
524 }
525
526 unsigned int xlen = riscv_xlen(target);
527 struct working_area *algorithm_wa = NULL;
528 struct working_area *data_wa = NULL;
529 const uint8_t *bin;
530 size_t bin_size;
531 if (xlen == 32) {
532 bin = riscv32_bin;
533 bin_size = sizeof(riscv32_bin);
534 } else {
535 bin = riscv64_bin;
536 bin_size = sizeof(riscv64_bin);
537 }
538
539 unsigned data_wa_size = 0;
540 if (target_alloc_working_area(target, bin_size, &algorithm_wa) == ERROR_OK) {
541 retval = target_write_buffer(target, algorithm_wa->address,
542 bin_size, bin);
543 if (retval != ERROR_OK) {
544 LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
545 algorithm_wa->address, retval);
546 target_free_working_area(target, algorithm_wa);
547 algorithm_wa = NULL;
548
549 } else {
550 data_wa_size = MIN(target_get_working_area_avail(target), count);
551 if (data_wa_size < 128) {
552 LOG_WARNING("Couldn't allocate data working area.");
553 target_free_working_area(target, algorithm_wa);
554 algorithm_wa = NULL;
555 } else if (target_alloc_working_area(target, data_wa_size, &data_wa) != ERROR_OK) {
556 target_free_working_area(target, algorithm_wa);
557 algorithm_wa = NULL;
558 }
559 }
560 } else {
561 LOG_WARNING("Couldn't allocate %zd-byte working area.", bin_size);
562 algorithm_wa = NULL;
563 }
564
565 /* If no valid page_size, use reasonable default. */
566 page_size = fespi_info->dev->pagesize ?
567 fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
568
569 if (algorithm_wa) {
570 struct reg_param reg_params[6];
571 init_reg_param(&reg_params[0], "a0", xlen, PARAM_IN_OUT);
572 init_reg_param(&reg_params[1], "a1", xlen, PARAM_OUT);
573 init_reg_param(&reg_params[2], "a2", xlen, PARAM_OUT);
574 init_reg_param(&reg_params[3], "a3", xlen, PARAM_OUT);
575 init_reg_param(&reg_params[4], "a4", xlen, PARAM_OUT);
576 init_reg_param(&reg_params[5], "a5", xlen, PARAM_OUT);
577
578 while (count > 0) {
579 cur_count = MIN(count, data_wa_size);
580 buf_set_u64(reg_params[0].value, 0, xlen, fespi_info->ctrl_base);
581 buf_set_u64(reg_params[1].value, 0, xlen, page_size);
582 buf_set_u64(reg_params[2].value, 0, xlen, data_wa->address);
583 buf_set_u64(reg_params[3].value, 0, xlen, offset);
584 buf_set_u64(reg_params[4].value, 0, xlen, cur_count);
585 buf_set_u64(reg_params[5].value, 0, xlen,
586 fespi_info->dev->pprog_cmd | (bank->size > 0x1000000 ? 0x100 : 0));
587
588 retval = target_write_buffer(target, data_wa->address, cur_count,
589 buffer);
590 if (retval != ERROR_OK) {
591 LOG_DEBUG("Failed to write %d bytes to " TARGET_ADDR_FMT ": %d",
592 cur_count, data_wa->address, retval);
593 goto err;
594 }
595
596 LOG_DEBUG("write(ctrl_base=0x%" TARGET_PRIxADDR ", page_size=0x%x, "
597 "address=0x%" TARGET_PRIxADDR ", offset=0x%" PRIx32
598 ", count=0x%" PRIx32 "), buffer=%02x %02x %02x %02x %02x %02x ..." PRIx32,
599 fespi_info->ctrl_base, page_size, data_wa->address, offset, cur_count,
600 buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
601 retval = target_run_algorithm(target, 0, NULL,
602 ARRAY_SIZE(reg_params), reg_params,
603 algorithm_wa->address, 0, cur_count * 2, NULL);
604 if (retval != ERROR_OK) {
605 LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d",
606 algorithm_wa->address, retval);
607 goto err;
608 }
609
610 uint64_t algorithm_result = buf_get_u64(reg_params[0].value, 0, xlen);
611 if (algorithm_result != 0) {
612 LOG_ERROR("Algorithm returned error %" PRId64, algorithm_result);
613 retval = ERROR_FAIL;
614 goto err;
615 }
616
617 buffer += cur_count;
618 offset += cur_count;
619 count -= cur_count;
620 }
621
622 target_free_working_area(target, data_wa);
623 target_free_working_area(target, algorithm_wa);
624
625 } else {
626 fespi_txwm_wait(bank);
627
628 /* Disable Hardware accesses*/
629 if (fespi_disable_hw_mode(bank) != ERROR_OK)
630 return ERROR_FAIL;
631
632 /* poll WIP */
633 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
634 if (retval != ERROR_OK)
635 goto err;
636
637 uint32_t page_offset = offset % page_size;
638 /* central part, aligned words */
639 while (count > 0) {
640 /* clip block at page boundary */
641 if (page_offset + count > page_size)
642 cur_count = page_size - page_offset;
643 else
644 cur_count = count;
645
646 retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
647 if (retval != ERROR_OK)
648 goto err;
649
650 page_offset = 0;
651 buffer += cur_count;
652 offset += cur_count;
653 count -= cur_count;
654 }
655
656 /* Switch to HW mode before return to prompt */
657 if (fespi_enable_hw_mode(bank) != ERROR_OK)
658 return ERROR_FAIL;
659 }
660
661 return ERROR_OK;
662
663 err:
664 if (algorithm_wa) {
665 target_free_working_area(target, data_wa);
666 target_free_working_area(target, algorithm_wa);
667 }
668
669 /* Switch to HW mode before return to prompt */
670 if (fespi_enable_hw_mode(bank) != ERROR_OK)
671 return ERROR_FAIL;
672
673 return retval;
674 }
675
676 /* Return ID of flash device */
677 /* On exit, SW mode is kept */
678 static int fespi_read_flash_id(struct flash_bank *bank, uint32_t *id)
679 {
680 struct target *target = bank->target;
681 int retval;
682
683 if (target->state != TARGET_HALTED) {
684 LOG_ERROR("Target not halted");
685 return ERROR_TARGET_NOT_HALTED;
686 }
687
688 fespi_txwm_wait(bank);
689
690 /* poll WIP */
691 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
692 if (retval != ERROR_OK)
693 return retval;
694
695 fespi_set_dir(bank, FESPI_DIR_RX);
696
697 /* Send SPI command "read ID" */
698 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
699 return ERROR_FAIL;
700
701 fespi_tx(bank, SPIFLASH_READ_ID);
702 /* Send dummy bytes to actually read the ID.*/
703 fespi_tx(bank, 0);
704 fespi_tx(bank, 0);
705 fespi_tx(bank, 0);
706
707 /* read ID from Receive Register */
708 *id = 0;
709 if (fespi_rx(bank, NULL) != ERROR_OK)
710 return ERROR_FAIL;
711 uint8_t rx;
712 if (fespi_rx(bank, &rx) != ERROR_OK)
713 return ERROR_FAIL;
714 *id = rx;
715 if (fespi_rx(bank, &rx) != ERROR_OK)
716 return ERROR_FAIL;
717 *id |= (rx << 8);
718 if (fespi_rx(bank, &rx) != ERROR_OK)
719 return ERROR_FAIL;
720 *id |= (rx << 16);
721
722 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
723 return ERROR_FAIL;
724
725 fespi_set_dir(bank, FESPI_DIR_TX);
726
727 return ERROR_OK;
728 }
729
730 static int fespi_probe(struct flash_bank *bank)
731 {
732 struct target *target = bank->target;
733 struct fespi_flash_bank *fespi_info = bank->driver_priv;
734 struct flash_sector *sectors;
735 uint32_t id = 0; /* silence uninitialized warning */
736 const struct fespi_target *target_device;
737 int retval;
738 uint32_t sectorsize;
739
740 if (fespi_info->probed)
741 free(bank->sectors);
742 fespi_info->probed = false;
743
744 if (fespi_info->ctrl_base == 0) {
745 for (target_device = target_devices ; target_device->name ; ++target_device)
746 if (target_device->tap_idcode == target->tap->idcode)
747 break;
748
749 if (!target_device->name) {
750 LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
751 target->tap->idcode);
752 return ERROR_FAIL;
753 }
754
755 fespi_info->ctrl_base = target_device->ctrl_base;
756
757 LOG_DEBUG("Valid FESPI on device %s at address " TARGET_ADDR_FMT,
758 target_device->name, bank->base);
759
760 } else {
761 LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT
762 " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base,
763 bank->base);
764 }
765
766 /* read and decode flash ID; returns in SW mode */
767 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
768 return ERROR_FAIL;
769 fespi_set_dir(bank, FESPI_DIR_TX);
770
771 /* Disable Hardware accesses*/
772 if (fespi_disable_hw_mode(bank) != ERROR_OK)
773 return ERROR_FAIL;
774
775 retval = fespi_read_flash_id(bank, &id);
776
777 if (fespi_enable_hw_mode(bank) != ERROR_OK)
778 return ERROR_FAIL;
779 if (retval != ERROR_OK)
780 return retval;
781
782 fespi_info->dev = NULL;
783 for (const struct flash_device *p = flash_devices; p->name ; p++)
784 if (p->device_id == id) {
785 fespi_info->dev = p;
786 break;
787 }
788
789 if (!fespi_info->dev) {
790 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
791 return ERROR_FAIL;
792 }
793
794 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
795 fespi_info->dev->name, fespi_info->dev->device_id);
796
797 /* Set correct size value */
798 bank->size = fespi_info->dev->size_in_bytes;
799
800 if (bank->size <= (1UL << 16))
801 LOG_WARNING("device needs 2-byte addresses - not implemented");
802
803 /* if no sectors, treat whole bank as single sector */
804 sectorsize = fespi_info->dev->sectorsize ?
805 fespi_info->dev->sectorsize : fespi_info->dev->size_in_bytes;
806
807 /* create and fill sectors array */
808 bank->num_sectors = fespi_info->dev->size_in_bytes / sectorsize;
809 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
810 if (!sectors) {
811 LOG_ERROR("not enough memory");
812 return ERROR_FAIL;
813 }
814
815 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
816 sectors[sector].offset = sector * sectorsize;
817 sectors[sector].size = sectorsize;
818 sectors[sector].is_erased = -1;
819 sectors[sector].is_protected = 0;
820 }
821
822 bank->sectors = sectors;
823 fespi_info->probed = true;
824 return ERROR_OK;
825 }
826
827 static int fespi_auto_probe(struct flash_bank *bank)
828 {
829 struct fespi_flash_bank *fespi_info = bank->driver_priv;
830 if (fespi_info->probed)
831 return ERROR_OK;
832 return fespi_probe(bank);
833 }
834
835 static int fespi_protect_check(struct flash_bank *bank)
836 {
837 /* Nothing to do. Protection is only handled in SW. */
838 return ERROR_OK;
839 }
840
841 static int get_fespi_info(struct flash_bank *bank, struct command_invocation *cmd)
842 {
843 struct fespi_flash_bank *fespi_info = bank->driver_priv;
844
845 if (!(fespi_info->probed)) {
846 command_print_sameline(cmd, "\nFESPI flash bank not probed yet\n");
847 return ERROR_OK;
848 }
849
850 command_print_sameline(cmd, "\nFESPI flash information:\n"
851 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
852 fespi_info->dev->name, fespi_info->dev->device_id);
853
854 return ERROR_OK;
855 }
856
857 const struct flash_driver fespi_flash = {
858 .name = "fespi",
859 .flash_bank_command = fespi_flash_bank_command,
860 .erase = fespi_erase,
861 .protect = fespi_protect,
862 .write = fespi_write,
863 .read = default_flash_read,
864 .probe = fespi_probe,
865 .auto_probe = fespi_auto_probe,
866 .erase_check = default_flash_blank_check,
867 .protect_check = fespi_protect_check,
868 .info = get_fespi_info,
869 .free_driver_priv = default_flash_free_driver_priv
870 };

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)