jtag: linuxgpiod: drop extra parenthesis
[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 target_free_working_area(target, data_wa);
665 target_free_working_area(target, algorithm_wa);
666
667 /* Switch to HW mode before return to prompt */
668 if (fespi_enable_hw_mode(bank) != ERROR_OK)
669 return ERROR_FAIL;
670
671 return retval;
672 }
673
674 /* Return ID of flash device */
675 /* On exit, SW mode is kept */
676 static int fespi_read_flash_id(struct flash_bank *bank, uint32_t *id)
677 {
678 struct target *target = bank->target;
679 int retval;
680
681 if (target->state != TARGET_HALTED) {
682 LOG_ERROR("Target not halted");
683 return ERROR_TARGET_NOT_HALTED;
684 }
685
686 fespi_txwm_wait(bank);
687
688 /* poll WIP */
689 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
690 if (retval != ERROR_OK)
691 return retval;
692
693 fespi_set_dir(bank, FESPI_DIR_RX);
694
695 /* Send SPI command "read ID" */
696 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
697 return ERROR_FAIL;
698
699 fespi_tx(bank, SPIFLASH_READ_ID);
700 /* Send dummy bytes to actually read the ID.*/
701 fespi_tx(bank, 0);
702 fespi_tx(bank, 0);
703 fespi_tx(bank, 0);
704
705 /* read ID from Receive Register */
706 *id = 0;
707 if (fespi_rx(bank, NULL) != ERROR_OK)
708 return ERROR_FAIL;
709 uint8_t rx;
710 if (fespi_rx(bank, &rx) != ERROR_OK)
711 return ERROR_FAIL;
712 *id = rx;
713 if (fespi_rx(bank, &rx) != ERROR_OK)
714 return ERROR_FAIL;
715 *id |= (rx << 8);
716 if (fespi_rx(bank, &rx) != ERROR_OK)
717 return ERROR_FAIL;
718 *id |= (rx << 16);
719
720 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
721 return ERROR_FAIL;
722
723 fespi_set_dir(bank, FESPI_DIR_TX);
724
725 return ERROR_OK;
726 }
727
728 static int fespi_probe(struct flash_bank *bank)
729 {
730 struct target *target = bank->target;
731 struct fespi_flash_bank *fespi_info = bank->driver_priv;
732 struct flash_sector *sectors;
733 uint32_t id = 0; /* silence uninitialized warning */
734 const struct fespi_target *target_device;
735 int retval;
736 uint32_t sectorsize;
737
738 if (fespi_info->probed)
739 free(bank->sectors);
740 fespi_info->probed = false;
741
742 if (fespi_info->ctrl_base == 0) {
743 for (target_device = target_devices ; target_device->name ; ++target_device)
744 if (target_device->tap_idcode == target->tap->idcode)
745 break;
746
747 if (!target_device->name) {
748 LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
749 target->tap->idcode);
750 return ERROR_FAIL;
751 }
752
753 fespi_info->ctrl_base = target_device->ctrl_base;
754
755 LOG_DEBUG("Valid FESPI on device %s at address " TARGET_ADDR_FMT,
756 target_device->name, bank->base);
757
758 } else {
759 LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT
760 " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base,
761 bank->base);
762 }
763
764 /* read and decode flash ID; returns in SW mode */
765 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
766 return ERROR_FAIL;
767 fespi_set_dir(bank, FESPI_DIR_TX);
768
769 /* Disable Hardware accesses*/
770 if (fespi_disable_hw_mode(bank) != ERROR_OK)
771 return ERROR_FAIL;
772
773 retval = fespi_read_flash_id(bank, &id);
774
775 if (fespi_enable_hw_mode(bank) != ERROR_OK)
776 return ERROR_FAIL;
777 if (retval != ERROR_OK)
778 return retval;
779
780 fespi_info->dev = NULL;
781 for (const struct flash_device *p = flash_devices; p->name ; p++)
782 if (p->device_id == id) {
783 fespi_info->dev = p;
784 break;
785 }
786
787 if (!fespi_info->dev) {
788 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
789 return ERROR_FAIL;
790 }
791
792 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
793 fespi_info->dev->name, fespi_info->dev->device_id);
794
795 /* Set correct size value */
796 bank->size = fespi_info->dev->size_in_bytes;
797
798 if (bank->size <= (1UL << 16))
799 LOG_WARNING("device needs 2-byte addresses - not implemented");
800
801 /* if no sectors, treat whole bank as single sector */
802 sectorsize = fespi_info->dev->sectorsize ?
803 fespi_info->dev->sectorsize : fespi_info->dev->size_in_bytes;
804
805 /* create and fill sectors array */
806 bank->num_sectors = fespi_info->dev->size_in_bytes / sectorsize;
807 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
808 if (!sectors) {
809 LOG_ERROR("not enough memory");
810 return ERROR_FAIL;
811 }
812
813 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
814 sectors[sector].offset = sector * sectorsize;
815 sectors[sector].size = sectorsize;
816 sectors[sector].is_erased = -1;
817 sectors[sector].is_protected = 0;
818 }
819
820 bank->sectors = sectors;
821 fespi_info->probed = true;
822 return ERROR_OK;
823 }
824
825 static int fespi_auto_probe(struct flash_bank *bank)
826 {
827 struct fespi_flash_bank *fespi_info = bank->driver_priv;
828 if (fespi_info->probed)
829 return ERROR_OK;
830 return fespi_probe(bank);
831 }
832
833 static int fespi_protect_check(struct flash_bank *bank)
834 {
835 /* Nothing to do. Protection is only handled in SW. */
836 return ERROR_OK;
837 }
838
839 static int get_fespi_info(struct flash_bank *bank, struct command_invocation *cmd)
840 {
841 struct fespi_flash_bank *fespi_info = bank->driver_priv;
842
843 if (!(fespi_info->probed)) {
844 command_print_sameline(cmd, "\nFESPI flash bank not probed yet\n");
845 return ERROR_OK;
846 }
847
848 command_print_sameline(cmd, "\nFESPI flash information:\n"
849 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
850 fespi_info->dev->name, fespi_info->dev->device_id);
851
852 return ERROR_OK;
853 }
854
855 const struct flash_driver fespi_flash = {
856 .name = "fespi",
857 .flash_bank_command = fespi_flash_bank_command,
858 .erase = fespi_erase,
859 .protect = fespi_protect,
860 .write = fespi_write,
861 .read = default_flash_read,
862 .probe = fespi_probe,
863 .auto_probe = fespi_auto_probe,
864 .erase_check = default_flash_blank_check,
865 .protect_check = fespi_protect_check,
866 .info = get_fespi_info,
867 .free_driver_priv = default_flash_free_driver_priv
868 };

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)