d33c5260c7e2042653f4dd890abae072744ce9a1
[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 unsigned int xlen = riscv_xlen(target);
516 struct working_area *algorithm_wa = NULL;
517 struct working_area *data_wa = NULL;
518 const uint8_t *bin;
519 size_t bin_size;
520 if (xlen == 32) {
521 bin = riscv32_bin;
522 bin_size = sizeof(riscv32_bin);
523 } else {
524 bin = riscv64_bin;
525 bin_size = sizeof(riscv64_bin);
526 }
527
528 unsigned data_wa_size = 0;
529 if (target_alloc_working_area(target, bin_size, &algorithm_wa) == ERROR_OK) {
530 retval = target_write_buffer(target, algorithm_wa->address,
531 bin_size, bin);
532 if (retval != ERROR_OK) {
533 LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
534 algorithm_wa->address, retval);
535 target_free_working_area(target, algorithm_wa);
536 algorithm_wa = NULL;
537
538 } else {
539 data_wa_size = MIN(target_get_working_area_avail(target), count);
540 if (data_wa_size < 128) {
541 LOG_WARNING("Couldn't allocate data working area.");
542 target_free_working_area(target, algorithm_wa);
543 algorithm_wa = NULL;
544 } else if (target_alloc_working_area(target, data_wa_size, &data_wa) != ERROR_OK) {
545 target_free_working_area(target, algorithm_wa);
546 algorithm_wa = NULL;
547 }
548 }
549 } else {
550 LOG_WARNING("Couldn't allocate %zd-byte working area.", bin_size);
551 algorithm_wa = NULL;
552 }
553
554 /* If no valid page_size, use reasonable default. */
555 page_size = fespi_info->dev->pagesize ?
556 fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
557
558 if (algorithm_wa) {
559 struct reg_param reg_params[6];
560 init_reg_param(&reg_params[0], "a0", xlen, PARAM_IN_OUT);
561 init_reg_param(&reg_params[1], "a1", xlen, PARAM_OUT);
562 init_reg_param(&reg_params[2], "a2", xlen, PARAM_OUT);
563 init_reg_param(&reg_params[3], "a3", xlen, PARAM_OUT);
564 init_reg_param(&reg_params[4], "a4", xlen, PARAM_OUT);
565 init_reg_param(&reg_params[5], "a5", xlen, PARAM_OUT);
566
567 while (count > 0) {
568 cur_count = MIN(count, data_wa_size);
569 buf_set_u64(reg_params[0].value, 0, xlen, fespi_info->ctrl_base);
570 buf_set_u64(reg_params[1].value, 0, xlen, page_size);
571 buf_set_u64(reg_params[2].value, 0, xlen, data_wa->address);
572 buf_set_u64(reg_params[3].value, 0, xlen, offset);
573 buf_set_u64(reg_params[4].value, 0, xlen, cur_count);
574 buf_set_u64(reg_params[5].value, 0, xlen,
575 fespi_info->dev->pprog_cmd | (bank->size > 0x1000000 ? 0x100 : 0));
576
577 retval = target_write_buffer(target, data_wa->address, cur_count,
578 buffer);
579 if (retval != ERROR_OK) {
580 LOG_DEBUG("Failed to write %d bytes to " TARGET_ADDR_FMT ": %d",
581 cur_count, data_wa->address, retval);
582 goto err;
583 }
584
585 LOG_DEBUG("write(ctrl_base=0x%" TARGET_PRIxADDR ", page_size=0x%x, "
586 "address=0x%" TARGET_PRIxADDR ", offset=0x%" PRIx32
587 ", count=0x%" PRIx32 "), buffer=%02x %02x %02x %02x %02x %02x ..." PRIx32,
588 fespi_info->ctrl_base, page_size, data_wa->address, offset, cur_count,
589 buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
590 retval = target_run_algorithm(target, 0, NULL,
591 ARRAY_SIZE(reg_params), reg_params,
592 algorithm_wa->address, 0, cur_count * 2, NULL);
593 if (retval != ERROR_OK) {
594 LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d",
595 algorithm_wa->address, retval);
596 goto err;
597 }
598
599 uint64_t algorithm_result = buf_get_u64(reg_params[0].value, 0, xlen);
600 if (algorithm_result != 0) {
601 LOG_ERROR("Algorithm returned error %" PRId64, algorithm_result);
602 retval = ERROR_FAIL;
603 goto err;
604 }
605
606 buffer += cur_count;
607 offset += cur_count;
608 count -= cur_count;
609 }
610
611 target_free_working_area(target, data_wa);
612 target_free_working_area(target, algorithm_wa);
613
614 } else {
615 fespi_txwm_wait(bank);
616
617 /* Disable Hardware accesses*/
618 if (fespi_disable_hw_mode(bank) != ERROR_OK)
619 return ERROR_FAIL;
620
621 /* poll WIP */
622 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
623 if (retval != ERROR_OK)
624 goto err;
625
626 uint32_t page_offset = offset % page_size;
627 /* central part, aligned words */
628 while (count > 0) {
629 /* clip block at page boundary */
630 if (page_offset + count > page_size)
631 cur_count = page_size - page_offset;
632 else
633 cur_count = count;
634
635 retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
636 if (retval != ERROR_OK)
637 goto err;
638
639 page_offset = 0;
640 buffer += cur_count;
641 offset += cur_count;
642 count -= cur_count;
643 }
644
645 /* Switch to HW mode before return to prompt */
646 if (fespi_enable_hw_mode(bank) != ERROR_OK)
647 return ERROR_FAIL;
648 }
649
650 return ERROR_OK;
651
652 err:
653 target_free_working_area(target, data_wa);
654 target_free_working_area(target, algorithm_wa);
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 return retval;
661 }
662
663 /* Return ID of flash device */
664 /* On exit, SW mode is kept */
665 static int fespi_read_flash_id(struct flash_bank *bank, uint32_t *id)
666 {
667 struct target *target = bank->target;
668 int retval;
669
670 if (target->state != TARGET_HALTED) {
671 LOG_ERROR("Target not halted");
672 return ERROR_TARGET_NOT_HALTED;
673 }
674
675 fespi_txwm_wait(bank);
676
677 /* poll WIP */
678 retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
679 if (retval != ERROR_OK)
680 return retval;
681
682 fespi_set_dir(bank, FESPI_DIR_RX);
683
684 /* Send SPI command "read ID" */
685 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK)
686 return ERROR_FAIL;
687
688 fespi_tx(bank, SPIFLASH_READ_ID);
689 /* Send dummy bytes to actually read the ID.*/
690 fespi_tx(bank, 0);
691 fespi_tx(bank, 0);
692 fespi_tx(bank, 0);
693
694 /* read ID from Receive Register */
695 *id = 0;
696 if (fespi_rx(bank, NULL) != ERROR_OK)
697 return ERROR_FAIL;
698 uint8_t rx;
699 if (fespi_rx(bank, &rx) != ERROR_OK)
700 return ERROR_FAIL;
701 *id = rx;
702 if (fespi_rx(bank, &rx) != ERROR_OK)
703 return ERROR_FAIL;
704 *id |= (rx << 8);
705 if (fespi_rx(bank, &rx) != ERROR_OK)
706 return ERROR_FAIL;
707 *id |= (rx << 16);
708
709 if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK)
710 return ERROR_FAIL;
711
712 fespi_set_dir(bank, FESPI_DIR_TX);
713
714 return ERROR_OK;
715 }
716
717 static int fespi_probe(struct flash_bank *bank)
718 {
719 struct target *target = bank->target;
720 struct fespi_flash_bank *fespi_info = bank->driver_priv;
721 struct flash_sector *sectors;
722 uint32_t id = 0; /* silence uninitialized warning */
723 const struct fespi_target *target_device;
724 int retval;
725 uint32_t sectorsize;
726
727 if (fespi_info->probed)
728 free(bank->sectors);
729 fespi_info->probed = false;
730
731 if (fespi_info->ctrl_base == 0) {
732 for (target_device = target_devices ; target_device->name ; ++target_device)
733 if (target_device->tap_idcode == target->tap->idcode)
734 break;
735
736 if (!target_device->name) {
737 LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
738 target->tap->idcode);
739 return ERROR_FAIL;
740 }
741
742 fespi_info->ctrl_base = target_device->ctrl_base;
743
744 LOG_DEBUG("Valid FESPI on device %s at address " TARGET_ADDR_FMT,
745 target_device->name, bank->base);
746
747 } else {
748 LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT
749 " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base,
750 bank->base);
751 }
752
753 /* read and decode flash ID; returns in SW mode */
754 if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
755 return ERROR_FAIL;
756 fespi_set_dir(bank, FESPI_DIR_TX);
757
758 /* Disable Hardware accesses*/
759 if (fespi_disable_hw_mode(bank) != ERROR_OK)
760 return ERROR_FAIL;
761
762 retval = fespi_read_flash_id(bank, &id);
763
764 if (fespi_enable_hw_mode(bank) != ERROR_OK)
765 return ERROR_FAIL;
766 if (retval != ERROR_OK)
767 return retval;
768
769 fespi_info->dev = NULL;
770 for (const struct flash_device *p = flash_devices; p->name ; p++)
771 if (p->device_id == id) {
772 fespi_info->dev = p;
773 break;
774 }
775
776 if (!fespi_info->dev) {
777 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
778 return ERROR_FAIL;
779 }
780
781 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
782 fespi_info->dev->name, fespi_info->dev->device_id);
783
784 /* Set correct size value */
785 bank->size = fespi_info->dev->size_in_bytes;
786
787 if (bank->size <= (1UL << 16))
788 LOG_WARNING("device needs 2-byte addresses - not implemented");
789
790 /* if no sectors, treat whole bank as single sector */
791 sectorsize = fespi_info->dev->sectorsize ?
792 fespi_info->dev->sectorsize : fespi_info->dev->size_in_bytes;
793
794 /* create and fill sectors array */
795 bank->num_sectors = fespi_info->dev->size_in_bytes / sectorsize;
796 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
797 if (!sectors) {
798 LOG_ERROR("not enough memory");
799 return ERROR_FAIL;
800 }
801
802 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
803 sectors[sector].offset = sector * sectorsize;
804 sectors[sector].size = sectorsize;
805 sectors[sector].is_erased = -1;
806 sectors[sector].is_protected = 0;
807 }
808
809 bank->sectors = sectors;
810 fespi_info->probed = true;
811 return ERROR_OK;
812 }
813
814 static int fespi_auto_probe(struct flash_bank *bank)
815 {
816 struct fespi_flash_bank *fespi_info = bank->driver_priv;
817 if (fespi_info->probed)
818 return ERROR_OK;
819 return fespi_probe(bank);
820 }
821
822 static int fespi_protect_check(struct flash_bank *bank)
823 {
824 /* Nothing to do. Protection is only handled in SW. */
825 return ERROR_OK;
826 }
827
828 static int get_fespi_info(struct flash_bank *bank, struct command_invocation *cmd)
829 {
830 struct fespi_flash_bank *fespi_info = bank->driver_priv;
831
832 if (!(fespi_info->probed)) {
833 command_print_sameline(cmd, "\nFESPI flash bank not probed yet\n");
834 return ERROR_OK;
835 }
836
837 command_print_sameline(cmd, "\nFESPI flash information:\n"
838 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
839 fespi_info->dev->name, fespi_info->dev->device_id);
840
841 return ERROR_OK;
842 }
843
844 const struct flash_driver fespi_flash = {
845 .name = "fespi",
846 .flash_bank_command = fespi_flash_bank_command,
847 .erase = fespi_erase,
848 .protect = fespi_protect,
849 .write = fespi_write,
850 .read = default_flash_read,
851 .probe = fespi_probe,
852 .auto_probe = fespi_auto_probe,
853 .erase_check = default_flash_blank_check,
854 .protect_check = fespi_protect_check,
855 .info = get_fespi_info,
856 .free_driver_priv = default_flash_free_driver_priv
857 };

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)