jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / fespi.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
5 * Modified by Megan Wachs <megan@sifive.com> from the original stmsmi.c *
6 ***************************************************************************/
7
8 /* The Freedom E SPI controller is a SPI bus controller
9 * specifically designed for SPI Flash Memories on Freedom E platforms.
10 *
11 * Two working modes are available:
12 * - SW mode: the SPI is controlled by SW. Any custom commands can be sent
13 * on the bus. Writes are only possible in this mode.
14 * - HW mode: Memory content is directly
15 * accessible in CPU memory space. CPU can read and execute memory content.
16 */
17
18 /* ATTENTION:
19 * To have flash memory mapped in CPU memory space, the controller
20 * must have "HW mode" enabled.
21 * 1) The command "reset init" has to initialize the controller and put
22 * it in HW mode (this is actually the default out of reset for Freedom E systems).
23 * 2) every command in this file have to return to prompt in HW mode. */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "imp.h"
30 #include "spi.h"
31 #include <jtag/jtag.h>
32 #include <helper/time_support.h>
33 #include <target/algorithm.h>
34 #include "target/riscv/riscv.h"
35
36 /* Register offsets */
37
38 #define FESPI_REG_SCKDIV 0x00
39 #define FESPI_REG_SCKMODE 0x04
40 #define FESPI_REG_CSID 0x10
41 #define FESPI_REG_CSDEF 0x14
42 #define FESPI_REG_CSMODE 0x18
43
44 #define FESPI_REG_DCSSCK 0x28
45 #define FESPI_REG_DSCKCS 0x2a
46 #define FESPI_REG_DINTERCS 0x2c
47 #define FESPI_REG_DINTERXFR 0x2e
48
49 #define FESPI_REG_FMT 0x40
50 #define FESPI_REG_TXFIFO 0x48
51 #define FESPI_REG_RXFIFO 0x4c
52 #define FESPI_REG_TXCTRL 0x50
53 #define FESPI_REG_RXCTRL 0x54
54
55 #define FESPI_REG_FCTRL 0x60
56 #define FESPI_REG_FFMT 0x64
57
58 #define FESPI_REG_IE 0x70
59 #define FESPI_REG_IP 0x74
60
61 /* Fields */
62
63 #define FESPI_SCK_POL 0x1
64 #define FESPI_SCK_PHA 0x2
65
66 #define FESPI_FMT_PROTO(x) ((x) & 0x3)
67 #define FESPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
68 #define FESPI_FMT_DIR(x) (((x) & 0x1) << 3)
69 #define FESPI_FMT_LEN(x) (((x) & 0xf) << 16)
70
71 /* TXCTRL register */
72 #define FESPI_TXWM(x) ((x) & 0xffff)
73 /* RXCTRL register */
74 #define FESPI_RXWM(x) ((x) & 0xffff)
75
76 #define FESPI_IP_TXWM 0x1
77 #define FESPI_IP_RXWM 0x2
78
79 #define FESPI_FCTRL_EN 0x1
80
81 #define FESPI_INSN_CMD_EN 0x1
82 #define FESPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
83 #define FESPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
84 #define FESPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
85 #define FESPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
86 #define FESPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
87 #define FESPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
88 #define FESPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
89
90 /* Values */
91
92 #define FESPI_CSMODE_AUTO 0
93 #define FESPI_CSMODE_HOLD 2
94 #define FESPI_CSMODE_OFF 3
95
96 #define FESPI_DIR_RX 0
97 #define FESPI_DIR_TX 1
98
99 #define FESPI_PROTO_S 0
100 #define FESPI_PROTO_D 1
101 #define FESPI_PROTO_Q 2
102
103 #define FESPI_ENDIAN_MSB 0
104 #define FESPI_ENDIAN_LSB 1
105
106
107 /* Timeout in ms */
108 #define FESPI_CMD_TIMEOUT (100)
109 #define FESPI_PROBE_TIMEOUT (100)
110 #define FESPI_MAX_TIMEOUT (3000)
111
112
113 struct fespi_flash_bank {
114 bool probed;
115 target_addr_t ctrl_base;
116 const struct flash_device *dev;
117 };
118
119 struct fespi_target {
120 char *name;
121 uint32_t tap_idcode;
122 uint32_t ctrl_base;
123 };
124
125 /* TODO !!! What is the right naming convention here? */
126 static const struct fespi_target target_devices[] = {
127 /* name, tap_idcode, ctrl_base */
128 { "Freedom E310-G000 SPI Flash", 0x10e31913, 0x10014000 },
129 { "Freedom E310-G002 SPI Flash", 0x20000913, 0x10014000 },
130 { NULL, 0, 0 }
131 };
132
133 FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command)
134 {
135 struct fespi_flash_bank *fespi_info;
136
137 LOG_DEBUG("%s", __func__);
138
139 if (CMD_ARGC < 6)
140 return ERROR_COMMAND_SYNTAX_ERROR;
141
142 fespi_info = malloc(sizeof(struct fespi_flash_bank));
143 if (!fespi_info) {
144 LOG_ERROR("not enough memory");
145 return ERROR_FAIL;
146 }
147
148 bank->driver_priv = fespi_info;
149 fespi_info->probed = false;
150 fespi_info->ctrl_base = 0;
151 if (CMD_ARGC >= 7) {
152 COMMAND_PARSE_ADDRESS(CMD_ARGV[6], fespi_info->ctrl_base);
153 LOG_DEBUG("ASSUMING FESPI device at ctrl_base = " TARGET_ADDR_FMT,
154 fespi_info->ctrl_base);
155 }
156
157 return ERROR_OK;
158 }
159
160 static int fespi_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_t address)
161 {
162 struct target *target = bank->target;
163 struct fespi_flash_bank *fespi_info = bank->driver_priv;
164
165 int result = target_read_u32(target, fespi_info->ctrl_base + address, value);
166 if (result != ERROR_OK) {
167 LOG_ERROR("fespi_read_reg() error at " TARGET_ADDR_FMT,
168 fespi_info->ctrl_base + address);
169 return result;
170 }
171 return ERROR_OK;
172 }
173
174 static int fespi_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value)
175 {
176 struct target *target = bank->target;
177 struct fespi_flash_bank *fespi_info = bank->driver_priv;
178
179 int result = target_write_u32(target, fespi_info->ctrl_base + address, value);
180 if (result != ERROR_OK) {
181 LOG_ERROR("fespi_write_reg() error writing 0x%" PRIx32 " to " TARGET_ADDR_FMT,
182 value, fespi_info->ctrl_base + address);
183 return result;
184 }
185 return ERROR_OK;
186 }
187
188 static int fespi_disable_hw_mode(struct flash_bank *bank)
189 {
190 uint32_t fctrl;
191 if (fespi_read_reg(bank, &fctrl, FESPI_REG_FCTRL) != ERROR_OK)
192 return ERROR_FAIL;
193 return fespi_write_reg(bank, FESPI_REG_FCTRL, fctrl & ~FESPI_FCTRL_EN);
194 }
195
196 static int fespi_enable_hw_mode(struct flash_bank *bank)
197 {
198 uint32_t fctrl;
199 if (fespi_read_reg(bank, &fctrl, FESPI_REG_FCTRL) != ERROR_OK)
200 return ERROR_FAIL;
201 return fespi_write_reg(bank, FESPI_REG_FCTRL, fctrl | FESPI_FCTRL_EN);
202 }
203
204 static int fespi_set_dir(struct flash_bank *bank, bool dir)
205 {
206 uint32_t fmt;
207 if (fespi_read_reg(bank, &fmt, FESPI_REG_FMT) != ERROR_OK)
208 return ERROR_FAIL;
209
210 return fespi_write_reg(bank, FESPI_REG_FMT,
211 (fmt & ~(FESPI_FMT_DIR(0xFFFFFFFF))) | FESPI_FMT_DIR(dir));
212 }
213
214 static int fespi_txwm_wait(struct flash_bank *bank)
215 {
216 int64_t start = timeval_ms();
217
218 while (1) {
219 uint32_t ip;
220 if (fespi_read_reg(bank, &ip, FESPI_REG_IP) != ERROR_OK)
221 return ERROR_FAIL;
222 if (ip & FESPI_IP_TXWM)
223 break;
224 int64_t now = timeval_ms();
225 if (now - start > 1000) {
226 LOG_ERROR("ip.txwm didn't get set.");
227 return ERROR_TARGET_TIMEOUT;
228 }
229 }
230
231 return ERROR_OK;
232 }
233
234 static int fespi_tx(struct flash_bank *bank, uint8_t in)
235 {
236 int64_t start = timeval_ms();
237
238 while (1) {
239 uint32_t txfifo;
240 if (fespi_read_reg(bank, &txfifo, FESPI_REG_TXFIFO) != ERROR_OK)
241 return ERROR_FAIL;
242 if (!(txfifo >> 31))
243 break;
244 int64_t now = timeval_ms();
245 if (now - start > 1000) {
246 LOG_ERROR("txfifo stayed negative.");
247 return ERROR_TARGET_TIMEOUT;
248 }
249 }
250
251 return fespi_write_reg(bank, FESPI_REG_TXFIFO, in);
252 }
253
254 static int fespi_rx(struct flash_bank *bank, uint8_t *out)
255 {
256 int64_t start = timeval_ms();
257 uint32_t value;
258
259 while (1) {
260 if (fespi_read_reg(bank, &value, FESPI_REG_RXFIFO) != ERROR_OK)
261 return ERROR_FAIL;
262 if (!(value >> 31))
263 break;
264 int64_t now = timeval_ms();
265 if (now - start > 1000) {
266 LOG_ERROR("rxfifo didn't go positive (value=0x%" PRIx32 ").", value);
267 return ERROR_TARGET_TIMEOUT;
268 }
269 }
270
271 if (out)
272 *out = value & 0xff;
273
274 return ERROR_OK;
275 }
276
277 /* TODO!!! Why don't we need to call this after writing? */
278 static int fespi_wip(struct flash_bank *bank, int timeout)
279 {
280 int64_t endtime;
281
282 fespi_set_dir(bank, FESPI_DIR_RX);
283
284 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
285 return ERROR_FAIL;
286 endtime = timeval_ms() + timeout;
287
288 fespi_tx(bank, SPIFLASH_READ_STATUS);
289 if (fespi_rx(bank, NULL) != ERROR_OK)
290 return ERROR_FAIL;
291
292 do {
293 alive_sleep(1);
294
295 fespi_tx(bank, 0);
296 uint8_t rx;
297 if (fespi_rx(bank, &rx) != ERROR_OK)
298 return ERROR_FAIL;
299 if ((rx & SPIFLASH_BSY_BIT) == 0) {
300 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
301 return ERROR_FAIL;
302 fespi_set_dir(bank, FESPI_DIR_TX);
303 return ERROR_OK;
304 }
305 } while (timeval_ms() < endtime);
306
307 LOG_ERROR("timeout");
308 return ERROR_FAIL;
309 }
310
311 static int fespi_erase_sector(struct flash_bank *bank, int sector)
312 {
313 struct fespi_flash_bank *fespi_info = bank->driver_priv;
314 int retval;
315
316 retval = fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
317 if (retval != ERROR_OK)
318 return retval;
319 retval = fespi_txwm_wait(bank);
320 if (retval != ERROR_OK)
321 return retval;
322
323 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
324 return ERROR_FAIL;
325 retval = fespi_tx(bank, fespi_info->dev->erase_cmd);
326 if (retval != ERROR_OK)
327 return retval;
328 sector = bank->sectors[sector].offset;
329 if (bank->size > 0x1000000) {
330 retval = fespi_tx(bank, sector >> 24);
331 if (retval != ERROR_OK)
332 return retval;
333 }
334 retval = fespi_tx(bank, sector >> 16);
335 if (retval != ERROR_OK)
336 return retval;
337 retval = fespi_tx(bank, sector >> 8);
338 if (retval != ERROR_OK)
339 return retval;
340 retval = fespi_tx(bank, sector);
341 if (retval != ERROR_OK)
342 return retval;
343 retval = fespi_txwm_wait(bank);
344 if (retval != ERROR_OK)
345 return retval;
346 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
347 return ERROR_FAIL;
348
349 retval = fespi_wip(bank, FESPI_MAX_TIMEOUT);
350 if (retval != ERROR_OK)
351 return retval;
352
353 return ERROR_OK;
354 }
355
356 static int fespi_erase(struct flash_bank *bank, unsigned int first,
357 unsigned int last)
358 {
359 struct target *target = bank->target;
360 struct fespi_flash_bank *fespi_info = bank->driver_priv;
361 int retval = ERROR_OK;
362
363 LOG_DEBUG("%s: from sector %u to sector %u", __func__, first, last);
364
365 if (target->state != TARGET_HALTED) {
366 LOG_ERROR("Target not halted");
367 return ERROR_TARGET_NOT_HALTED;
368 }
369
370 if ((last < first) || (last >= bank->num_sectors)) {
371 LOG_ERROR("Flash sector invalid");
372 return ERROR_FLASH_SECTOR_INVALID;
373 }
374
375 if (!(fespi_info->probed)) {
376 LOG_ERROR("Flash bank not probed");
377 return ERROR_FLASH_BANK_NOT_PROBED;
378 }
379
380 for (unsigned int sector = first; sector <= last; sector++) {
381 if (bank->sectors[sector].is_protected) {
382 LOG_ERROR("Flash sector %u protected", sector);
383 return ERROR_FAIL;
384 }
385 }
386
387 if (fespi_info->dev->erase_cmd == 0x00)
388 return ERROR_FLASH_OPER_UNSUPPORTED;
389
390 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
391 return ERROR_FAIL;
392 retval = fespi_txwm_wait(bank);
393 if (retval != ERROR_OK) {
394 LOG_ERROR("WM Didn't go high before attempting.");
395 return retval;
396 }
397
398 /* Disable Hardware accesses*/
399 if (fespi_disable_hw_mode(bank) != ERROR_OK)
400 return ERROR_FAIL;
401
402 /* poll WIP */
403 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
404 if (retval != ERROR_OK)
405 goto done;
406
407 for (unsigned int sector = first; sector <= last; sector++) {
408 retval = fespi_erase_sector(bank, sector);
409 if (retval != ERROR_OK)
410 goto done;
411 keep_alive();
412 }
413
414 /* Switch to HW mode before return to prompt */
415 done:
416 if (fespi_enable_hw_mode(bank) != ERROR_OK)
417 return ERROR_FAIL;
418 return retval;
419 }
420
421 static int fespi_protect(struct flash_bank *bank, int set,
422 unsigned int first, unsigned int last)
423 {
424 for (unsigned int sector = first; sector <= last; sector++)
425 bank->sectors[sector].is_protected = set;
426 return ERROR_OK;
427 }
428
429 static int slow_fespi_write_buffer(struct flash_bank *bank,
430 const uint8_t *buffer, uint32_t offset, uint32_t len)
431 {
432 struct fespi_flash_bank *fespi_info = bank->driver_priv;
433 uint32_t ii;
434
435 /* TODO!!! assert that len < page size */
436
437 if (fespi_tx(bank, SPIFLASH_WRITE_ENABLE) != ERROR_OK)
438 return ERROR_FAIL;
439 if (fespi_txwm_wait(bank) != ERROR_OK)
440 return ERROR_FAIL;
441
442 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
443 return ERROR_FAIL;
444
445 if (fespi_tx(bank, fespi_info->dev->pprog_cmd) != ERROR_OK)
446 return ERROR_FAIL;
447
448 if (bank->size > 0x1000000 && fespi_tx(bank, offset >> 24) != ERROR_OK)
449 return ERROR_FAIL;
450 if (fespi_tx(bank, offset >> 16) != ERROR_OK)
451 return ERROR_FAIL;
452 if (fespi_tx(bank, offset >> 8) != ERROR_OK)
453 return ERROR_FAIL;
454 if (fespi_tx(bank, offset) != ERROR_OK)
455 return ERROR_FAIL;
456
457 for (ii = 0; ii < len; ii++) {
458 if (fespi_tx(bank, buffer[ii]) != ERROR_OK)
459 return ERROR_FAIL;
460 }
461
462 if (fespi_txwm_wait(bank) != ERROR_OK)
463 return ERROR_FAIL;
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 riscv32_bin[] = {
474 #include "../../../contrib/loaders/flash/fespi/riscv32_fespi.inc"
475 };
476
477 static const uint8_t riscv64_bin[] = {
478 #include "../../../contrib/loaders/flash/fespi/riscv64_fespi.inc"
479 };
480
481 static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
482 uint32_t offset, uint32_t count)
483 {
484 struct target *target = bank->target;
485 struct fespi_flash_bank *fespi_info = bank->driver_priv;
486 uint32_t cur_count, page_size;
487 int retval = ERROR_OK;
488
489 LOG_DEBUG("bank->size=0x%x offset=0x%08" PRIx32 " count=0x%08" PRIx32,
490 bank->size, offset, count);
491
492 if (target->state != TARGET_HALTED) {
493 LOG_ERROR("Target not halted");
494 return ERROR_TARGET_NOT_HALTED;
495 }
496
497 if (offset + count > fespi_info->dev->size_in_bytes) {
498 LOG_WARNING("Write past end of flash. Extra data discarded.");
499 count = fespi_info->dev->size_in_bytes - offset;
500 }
501
502 /* Check sector protection */
503 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
504 /* Start offset in or before this sector? */
505 /* End offset in or behind this sector? */
506 if ((offset <
507 (bank->sectors[sector].offset + bank->sectors[sector].size))
508 && ((offset + count - 1) >= bank->sectors[sector].offset)
509 && bank->sectors[sector].is_protected) {
510 LOG_ERROR("Flash sector %u protected", sector);
511 return ERROR_FAIL;
512 }
513 }
514
515 struct riscv_info *riscv = riscv_info(target);
516 if (!is_riscv(riscv)) {
517 LOG_ERROR("Unexpected target type");
518 return ERROR_FAIL;
519 }
520
521 unsigned int xlen = riscv_xlen(target);
522 struct working_area *algorithm_wa = NULL;
523 struct working_area *data_wa = NULL;
524 const uint8_t *bin;
525 size_t bin_size;
526 if (xlen == 32) {
527 bin = riscv32_bin;
528 bin_size = sizeof(riscv32_bin);
529 } else {
530 bin = riscv64_bin;
531 bin_size = sizeof(riscv64_bin);
532 }
533
534 unsigned data_wa_size = 0;
535 if (target_alloc_working_area(target, bin_size, &algorithm_wa) == ERROR_OK) {
536 retval = target_write_buffer(target, algorithm_wa->address,
537 bin_size, bin);
538 if (retval != ERROR_OK) {
539 LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
540 algorithm_wa->address, retval);
541 target_free_working_area(target, algorithm_wa);
542 algorithm_wa = NULL;
543
544 } else {
545 data_wa_size = MIN(target_get_working_area_avail(target), count);
546 if (data_wa_size < 128) {
547 LOG_WARNING("Couldn't allocate data working area.");
548 target_free_working_area(target, algorithm_wa);
549 algorithm_wa = NULL;
550 } else if (target_alloc_working_area(target, data_wa_size, &data_wa) != ERROR_OK) {
551 target_free_working_area(target, algorithm_wa);
552 algorithm_wa = NULL;
553 }
554 }
555 } else {
556 LOG_WARNING("Couldn't allocate %zd-byte working area.", bin_size);
557 algorithm_wa = NULL;
558 }
559
560 /* If no valid page_size, use reasonable default. */
561 page_size = fespi_info->dev->pagesize ?
562 fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
563
564 if (algorithm_wa) {
565 struct reg_param reg_params[6];
566 init_reg_param(&reg_params[0], "a0", xlen, PARAM_IN_OUT);
567 init_reg_param(&reg_params[1], "a1", xlen, PARAM_OUT);
568 init_reg_param(&reg_params[2], "a2", xlen, PARAM_OUT);
569 init_reg_param(&reg_params[3], "a3", xlen, PARAM_OUT);
570 init_reg_param(&reg_params[4], "a4", xlen, PARAM_OUT);
571 init_reg_param(&reg_params[5], "a5", xlen, PARAM_OUT);
572
573 while (count > 0) {
574 cur_count = MIN(count, data_wa_size);
575 buf_set_u64(reg_params[0].value, 0, xlen, fespi_info->ctrl_base);
576 buf_set_u64(reg_params[1].value, 0, xlen, page_size);
577 buf_set_u64(reg_params[2].value, 0, xlen, data_wa->address);
578 buf_set_u64(reg_params[3].value, 0, xlen, offset);
579 buf_set_u64(reg_params[4].value, 0, xlen, cur_count);
580 buf_set_u64(reg_params[5].value, 0, xlen,
581 fespi_info->dev->pprog_cmd | (bank->size > 0x1000000 ? 0x100 : 0));
582
583 retval = target_write_buffer(target, data_wa->address, cur_count,
584 buffer);
585 if (retval != ERROR_OK) {
586 LOG_DEBUG("Failed to write %d bytes to " TARGET_ADDR_FMT ": %d",
587 cur_count, data_wa->address, retval);
588 goto err;
589 }
590
591 LOG_DEBUG("write(ctrl_base=0x%" TARGET_PRIxADDR ", page_size=0x%x, "
592 "address=0x%" TARGET_PRIxADDR ", offset=0x%" PRIx32
593 ", count=0x%" PRIx32 "), buffer=%02x %02x %02x %02x %02x %02x ..." PRIx32,
594 fespi_info->ctrl_base, page_size, data_wa->address, offset, cur_count,
595 buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
596 retval = target_run_algorithm(target, 0, NULL,
597 ARRAY_SIZE(reg_params), reg_params,
598 algorithm_wa->address, 0, cur_count * 2, NULL);
599 if (retval != ERROR_OK) {
600 LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d",
601 algorithm_wa->address, retval);
602 goto err;
603 }
604
605 uint64_t algorithm_result = buf_get_u64(reg_params[0].value, 0, xlen);
606 if (algorithm_result != 0) {
607 LOG_ERROR("Algorithm returned error %" PRId64, algorithm_result);
608 retval = ERROR_FAIL;
609 goto err;
610 }
611
612 buffer += cur_count;
613 offset += cur_count;
614 count -= cur_count;
615 }
616
617 target_free_working_area(target, data_wa);
618 target_free_working_area(target, algorithm_wa);
619
620 } else {
621 fespi_txwm_wait(bank);
622
623 /* Disable Hardware accesses*/
624 if (fespi_disable_hw_mode(bank) != ERROR_OK)
625 return ERROR_FAIL;
626
627 /* poll WIP */
628 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
629 if (retval != ERROR_OK)
630 goto err;
631
632 uint32_t page_offset = offset % page_size;
633 /* central part, aligned words */
634 while (count > 0) {
635 /* clip block at page boundary */
636 if (page_offset + count > page_size)
637 cur_count = page_size - page_offset;
638 else
639 cur_count = count;
640
641 retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
642 if (retval != ERROR_OK)
643 goto err;
644
645 page_offset = 0;
646 buffer += cur_count;
647 offset += cur_count;
648 count -= cur_count;
649 }
650
651 /* Switch to HW mode before return to prompt */
652 if (fespi_enable_hw_mode(bank) != ERROR_OK)
653 return ERROR_FAIL;
654 }
655
656 return ERROR_OK;
657
658 err:
659 target_free_working_area(target, data_wa);
660 target_free_working_area(target, algorithm_wa);
661
662 /* Switch to HW mode before return to prompt */
663 if (fespi_enable_hw_mode(bank) != ERROR_OK)
664 return ERROR_FAIL;
665
666 return retval;
667 }
668
669 /* Return ID of flash device */
670 /* On exit, SW mode is kept */
671 static int fespi_read_flash_id(struct flash_bank *bank, uint32_t *id)
672 {
673 struct target *target = bank->target;
674 int retval;
675
676 if (target->state != TARGET_HALTED) {
677 LOG_ERROR("Target not halted");
678 return ERROR_TARGET_NOT_HALTED;
679 }
680
681 fespi_txwm_wait(bank);
682
683 /* poll WIP */
684 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
685 if (retval != ERROR_OK)
686 return retval;
687
688 fespi_set_dir(bank, FESPI_DIR_RX);
689
690 /* Send SPI command "read ID" */
691 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
692 return ERROR_FAIL;
693
694 fespi_tx(bank, SPIFLASH_READ_ID);
695 /* Send dummy bytes to actually read the ID.*/
696 fespi_tx(bank, 0);
697 fespi_tx(bank, 0);
698 fespi_tx(bank, 0);
699
700 /* read ID from Receive Register */
701 *id = 0;
702 if (fespi_rx(bank, NULL) != ERROR_OK)
703 return ERROR_FAIL;
704 uint8_t rx;
705 if (fespi_rx(bank, &rx) != ERROR_OK)
706 return ERROR_FAIL;
707 *id = rx;
708 if (fespi_rx(bank, &rx) != ERROR_OK)
709 return ERROR_FAIL;
710 *id |= (rx << 8);
711 if (fespi_rx(bank, &rx) != ERROR_OK)
712 return ERROR_FAIL;
713 *id |= (rx << 16);
714
715 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
716 return ERROR_FAIL;
717
718 fespi_set_dir(bank, FESPI_DIR_TX);
719
720 return ERROR_OK;
721 }
722
723 static int fespi_probe(struct flash_bank *bank)
724 {
725 struct target *target = bank->target;
726 struct fespi_flash_bank *fespi_info = bank->driver_priv;
727 struct flash_sector *sectors;
728 uint32_t id = 0; /* silence uninitialized warning */
729 const struct fespi_target *target_device;
730 int retval;
731 uint32_t sectorsize;
732
733 if (fespi_info->probed)
734 free(bank->sectors);
735 fespi_info->probed = false;
736
737 if (fespi_info->ctrl_base == 0) {
738 for (target_device = target_devices ; target_device->name ; ++target_device)
739 if (target_device->tap_idcode == target->tap->idcode)
740 break;
741
742 if (!target_device->name) {
743 LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
744 target->tap->idcode);
745 return ERROR_FAIL;
746 }
747
748 fespi_info->ctrl_base = target_device->ctrl_base;
749
750 LOG_DEBUG("Valid FESPI on device %s at address " TARGET_ADDR_FMT,
751 target_device->name, bank->base);
752
753 } else {
754 LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT
755 " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base,
756 bank->base);
757 }
758
759 /* read and decode flash ID; returns in SW mode */
760 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
761 return ERROR_FAIL;
762 fespi_set_dir(bank, FESPI_DIR_TX);
763
764 /* Disable Hardware accesses*/
765 if (fespi_disable_hw_mode(bank) != ERROR_OK)
766 return ERROR_FAIL;
767
768 retval = fespi_read_flash_id(bank, &id);
769
770 if (fespi_enable_hw_mode(bank) != ERROR_OK)
771 return ERROR_FAIL;
772 if (retval != ERROR_OK)
773 return retval;
774
775 fespi_info->dev = NULL;
776 for (const struct flash_device *p = flash_devices; p->name ; p++)
777 if (p->device_id == id) {
778 fespi_info->dev = p;
779 break;
780 }
781
782 if (!fespi_info->dev) {
783 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
784 return ERROR_FAIL;
785 }
786
787 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
788 fespi_info->dev->name, fespi_info->dev->device_id);
789
790 /* Set correct size value */
791 bank->size = fespi_info->dev->size_in_bytes;
792
793 if (bank->size <= (1UL << 16))
794 LOG_WARNING("device needs 2-byte addresses - not implemented");
795
796 /* if no sectors, treat whole bank as single sector */
797 sectorsize = fespi_info->dev->sectorsize ?
798 fespi_info->dev->sectorsize : fespi_info->dev->size_in_bytes;
799
800 /* create and fill sectors array */
801 bank->num_sectors = fespi_info->dev->size_in_bytes / sectorsize;
802 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
803 if (!sectors) {
804 LOG_ERROR("not enough memory");
805 return ERROR_FAIL;
806 }
807
808 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
809 sectors[sector].offset = sector * sectorsize;
810 sectors[sector].size = sectorsize;
811 sectors[sector].is_erased = -1;
812 sectors[sector].is_protected = 0;
813 }
814
815 bank->sectors = sectors;
816 fespi_info->probed = true;
817 return ERROR_OK;
818 }
819
820 static int fespi_auto_probe(struct flash_bank *bank)
821 {
822 struct fespi_flash_bank *fespi_info = bank->driver_priv;
823 if (fespi_info->probed)
824 return ERROR_OK;
825 return fespi_probe(bank);
826 }
827
828 static int fespi_protect_check(struct flash_bank *bank)
829 {
830 /* Nothing to do. Protection is only handled in SW. */
831 return ERROR_OK;
832 }
833
834 static int get_fespi_info(struct flash_bank *bank, struct command_invocation *cmd)
835 {
836 struct fespi_flash_bank *fespi_info = bank->driver_priv;
837
838 if (!(fespi_info->probed)) {
839 command_print_sameline(cmd, "\nFESPI flash bank not probed yet\n");
840 return ERROR_OK;
841 }
842
843 command_print_sameline(cmd, "\nFESPI flash information:\n"
844 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
845 fespi_info->dev->name, fespi_info->dev->device_id);
846
847 return ERROR_OK;
848 }
849
850 const struct flash_driver fespi_flash = {
851 .name = "fespi",
852 .flash_bank_command = fespi_flash_bank_command,
853 .erase = fespi_erase,
854 .protect = fespi_protect,
855 .write = fespi_write,
856 .read = default_flash_read,
857 .probe = fespi_probe,
858 .auto_probe = fespi_auto_probe,
859 .erase_check = default_flash_blank_check,
860 .protect_check = fespi_protect_check,
861 .info = get_fespi_info,
862 .free_driver_priv = default_flash_free_driver_priv
863 };

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)