1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Renesas RCar Gen3 RPC Hyperflash driver
5 * Based on U-Boot RPC Hyperflash driver
7 * Copyright (C) 2016 Renesas Electronics Corporation
8 * Copyright (C) 2016 Cogent Embedded, Inc.
9 * Copyright (C) 2017-2019 Marek Vasut <marek.vasut@gmail.com>
19 #include <helper/binarybuffer.h>
20 #include <helper/bits.h>
21 #include <helper/time_support.h>
23 #define RPC_CMNCR 0x0000 /* R/W */
24 #define RPC_CMNCR_MD BIT(31)
25 #define RPC_CMNCR_MOIIO0(val) (((val) & 0x3) << 16)
26 #define RPC_CMNCR_MOIIO1(val) (((val) & 0x3) << 18)
27 #define RPC_CMNCR_MOIIO2(val) (((val) & 0x3) << 20)
28 #define RPC_CMNCR_MOIIO3(val) (((val) & 0x3) << 22)
29 #define RPC_CMNCR_MOIIO_HIZ (RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
30 RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
31 #define RPC_CMNCR_IO0FV(val) (((val) & 0x3) << 8)
32 #define RPC_CMNCR_IO2FV(val) (((val) & 0x3) << 12)
33 #define RPC_CMNCR_IO3FV(val) (((val) & 0x3) << 14)
34 #define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
36 #define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
38 #define RPC_SSLDR 0x0004 /* R/W */
39 #define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
40 #define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
41 #define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
43 #define RPC_DRCR 0x000C /* R/W */
44 #define RPC_DRCR_SSLN BIT(24)
45 #define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16)
46 #define RPC_DRCR_RCF BIT(9)
47 #define RPC_DRCR_RBE BIT(8)
48 #define RPC_DRCR_SSLE BIT(0)
50 #define RPC_DRCMR 0x0010 /* R/W */
51 #define RPC_DRCMR_CMD(c) (((c) & 0xFF) << 16)
52 #define RPC_DRCMR_OCMD(c) (((c) & 0xFF) << 0)
54 #define RPC_DREAR 0x0014 /* R/W */
55 #define RPC_DREAR_EAV(v) (((v) & 0xFF) << 16)
56 #define RPC_DREAR_EAC(v) (((v) & 0x7) << 0)
58 #define RPC_DROPR 0x0018 /* R/W */
59 #define RPC_DROPR_OPD3(o) (((o) & 0xFF) << 24)
60 #define RPC_DROPR_OPD2(o) (((o) & 0xFF) << 16)
61 #define RPC_DROPR_OPD1(o) (((o) & 0xFF) << 8)
62 #define RPC_DROPR_OPD0(o) (((o) & 0xFF) << 0)
64 #define RPC_DRENR 0x001C /* R/W */
65 #define RPC_DRENR_CDB(o) (uint32_t)((((o) & 0x3) << 30))
66 #define RPC_DRENR_OCDB(o) (((o) & 0x3) << 28)
67 #define RPC_DRENR_ADB(o) (((o) & 0x3) << 24)
68 #define RPC_DRENR_OPDB(o) (((o) & 0x3) << 20)
69 #define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
70 #define RPC_DRENR_DME BIT(15)
71 #define RPC_DRENR_CDE BIT(14)
72 #define RPC_DRENR_OCDE BIT(12)
73 #define RPC_DRENR_ADE(v) (((v) & 0xF) << 8)
74 #define RPC_DRENR_OPDE(v) (((v) & 0xF) << 4)
76 #define RPC_SMCR 0x0020 /* R/W */
77 #define RPC_SMCR_SSLKP BIT(8)
78 #define RPC_SMCR_SPIRE BIT(2)
79 #define RPC_SMCR_SPIWE BIT(1)
80 #define RPC_SMCR_SPIE BIT(0)
82 #define RPC_SMCMR 0x0024 /* R/W */
83 #define RPC_SMCMR_CMD(c) (((c) & 0xFF) << 16)
84 #define RPC_SMCMR_OCMD(c) (((c) & 0xFF) << 0)
86 #define RPC_SMADR 0x0028 /* R/W */
87 #define RPC_SMOPR 0x002C /* R/W */
88 #define RPC_SMOPR_OPD0(o) (((o) & 0xFF) << 0)
89 #define RPC_SMOPR_OPD1(o) (((o) & 0xFF) << 8)
90 #define RPC_SMOPR_OPD2(o) (((o) & 0xFF) << 16)
91 #define RPC_SMOPR_OPD3(o) (((o) & 0xFF) << 24)
93 #define RPC_SMENR 0x0030 /* R/W */
94 #define RPC_SMENR_CDB(o) (((o) & 0x3) << 30)
95 #define RPC_SMENR_OCDB(o) (((o) & 0x3) << 28)
96 #define RPC_SMENR_ADB(o) (((o) & 0x3) << 24)
97 #define RPC_SMENR_OPDB(o) (((o) & 0x3) << 20)
98 #define RPC_SMENR_SPIDB(o) (((o) & 0x3) << 16)
99 #define RPC_SMENR_DME BIT(15)
100 #define RPC_SMENR_CDE BIT(14)
101 #define RPC_SMENR_OCDE BIT(12)
102 #define RPC_SMENR_ADE(v) (((v) & 0xF) << 8)
103 #define RPC_SMENR_OPDE(v) (((v) & 0xF) << 4)
104 #define RPC_SMENR_SPIDE(v) (((v) & 0xF) << 0)
106 #define RPC_SMRDR0 0x0038 /* R */
107 #define RPC_SMRDR1 0x003C /* R */
108 #define RPC_SMWDR0 0x0040 /* R/W */
109 #define RPC_SMWDR1 0x0044 /* R/W */
110 #define RPC_CMNSR 0x0048 /* R */
111 #define RPC_CMNSR_SSLF BIT(1)
112 #define RPC_CMNSR_TEND BIT(0)
114 #define RPC_DRDMCR 0x0058 /* R/W */
115 #define RPC_DRDMCR_DMCYC(v) (((v) & 0xF) << 0)
117 #define RPC_DRDRENR 0x005C /* R/W */
118 #define RPC_DRDRENR_HYPE (0x5 << 12)
119 #define RPC_DRDRENR_ADDRE BIT(8)
120 #define RPC_DRDRENR_OPDRE BIT(4)
121 #define RPC_DRDRENR_DRDRE BIT(0)
123 #define RPC_SMDMCR 0x0060 /* R/W */
124 #define RPC_SMDMCR_DMCYC(v) (((v) & 0xF) << 0)
126 #define RPC_SMDRENR 0x0064 /* R/W */
127 #define RPC_SMDRENR_HYPE (0x5 << 12)
128 #define RPC_SMDRENR_ADDRE BIT(8)
129 #define RPC_SMDRENR_OPDRE BIT(4)
130 #define RPC_SMDRENR_SPIDRE BIT(0)
132 #define RPC_PHYCNT 0x007C /* R/W */
133 #define RPC_PHYCNT_CAL BIT(31)
134 #define PRC_PHYCNT_OCTA_AA BIT(22)
135 #define PRC_PHYCNT_OCTA_SA BIT(23)
136 #define PRC_PHYCNT_EXDS BIT(21)
137 #define RPC_PHYCNT_OCT BIT(20)
138 #define RPC_PHYCNT_WBUF2 BIT(4)
139 #define RPC_PHYCNT_WBUF BIT(2)
140 #define RPC_PHYCNT_MEM(v) (((v) & 0x3) << 0)
142 #define RPC_PHYINT 0x0088 /* R/W */
143 #define RPC_PHYINT_RSTEN BIT(18)
144 #define RPC_PHYINT_WPEN BIT(17)
145 #define RPC_PHYINT_INTEN BIT(16)
146 #define RPC_PHYINT_RST BIT(2)
147 #define RPC_PHYINT_WP BIT(1)
148 #define RPC_PHYINT_INT BIT(0)
150 #define RPC_WBUF 0x8000 /* R/W size=4/8/16/32/64Bytes */
151 #define RPC_WBUF_SIZE 0x100
153 static uint32_t rpc_base
= 0xee200000;
154 static uint32_t mem_base
= 0x08000000;
157 RPC_HF_SIZE_16BIT
= RPC_SMENR_SPIDE(0x8),
158 RPC_HF_SIZE_32BIT
= RPC_SMENR_SPIDE(0xC),
159 RPC_HF_SIZE_64BIT
= RPC_SMENR_SPIDE(0xF),
162 static int rpc_hf_wait_tend(struct target
*target
)
164 uint32_t reg
= rpc_base
+ RPC_CMNSR
;
166 unsigned long timeout
= 1000;
170 endtime
= timeval_ms() + timeout
;
172 ret
= target_read_u32(target
, reg
, &val
);
176 if (val
& RPC_CMNSR_TEND
)
180 } while (timeval_ms() < endtime
);
182 LOG_ERROR("timeout");
183 return ERROR_TIMEOUT_REACHED
;
186 static int clrsetbits_u32(struct target
*target
, uint32_t reg
,
187 uint32_t clr
, uint32_t set
)
192 ret
= target_read_u32(target
, reg
, &val
);
199 return target_write_u32(target
, reg
, val
);
202 static int rpc_hf_mode(struct target
*target
, bool manual
)
207 ret
= rpc_hf_wait_tend(target
);
208 if (ret
!= ERROR_OK
) {
209 LOG_ERROR("Mode TEND timeout");
213 ret
= clrsetbits_u32(target
, rpc_base
+ RPC_PHYCNT
,
214 RPC_PHYCNT_WBUF
| RPC_PHYCNT_WBUF2
|
215 RPC_PHYCNT_CAL
| RPC_PHYCNT_MEM(3),
216 RPC_PHYCNT_CAL
| RPC_PHYCNT_MEM(3));
220 ret
= clrsetbits_u32(target
, rpc_base
+ RPC_CMNCR
,
221 RPC_CMNCR_MD
| RPC_CMNCR_BSZ(3),
222 RPC_CMNCR_MOIIO_HIZ
| RPC_CMNCR_IOFV_HIZ
|
223 (manual
? RPC_CMNCR_MD
: 0) | RPC_CMNCR_BSZ(1));
230 ret
= target_write_u32(target
, rpc_base
+ RPC_DRCR
,
231 RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF
|
236 ret
= target_write_u32(target
, rpc_base
+ RPC_DRCMR
,
237 RPC_DRCMR_CMD(0xA0));
240 ret
= target_write_u32(target
, rpc_base
+ RPC_DRENR
,
241 RPC_DRENR_CDB(2) | RPC_DRENR_OCDB(2) |
242 RPC_DRENR_ADB(2) | RPC_DRENR_SPIDB(2) |
243 RPC_DRENR_CDE
| RPC_DRENR_OCDE
|
248 ret
= target_write_u32(target
, rpc_base
+ RPC_DRDMCR
,
249 RPC_DRDMCR_DMCYC(0xE));
253 ret
= target_write_u32(target
, rpc_base
+ RPC_DRDRENR
,
254 RPC_DRDRENR_HYPE
| RPC_DRDRENR_ADDRE
|
260 return target_read_u32(target
, rpc_base
+ RPC_DRCR
, &val
);
263 static int rpc_hf_xfer(struct target
*target
, target_addr_t addr
,
264 uint32_t wdata
, uint32_t *rdata
, enum rpc_hf_size size
,
265 bool write
, const uint8_t *wbuf
, unsigned int wbuf_size
)
270 if (wbuf_size
!= 0) {
271 ret
= rpc_hf_wait_tend(target
);
272 if (ret
!= ERROR_OK
) {
273 LOG_ERROR("Xfer TEND timeout");
277 /* Write calibration magic */
278 ret
= target_write_u32(target
, rpc_base
+ RPC_DRCR
, 0x01FF0301);
282 ret
= target_write_u32(target
, rpc_base
+ RPC_PHYCNT
, 0x80030277);
286 ret
= target_write_memory(target
, rpc_base
| RPC_WBUF
, 4,
287 wbuf_size
/ 4, wbuf
);
291 ret
= clrsetbits_u32(target
, rpc_base
+ RPC_CMNCR
,
292 RPC_CMNCR_MD
| RPC_CMNCR_BSZ(3),
293 RPC_CMNCR_MOIIO_HIZ
| RPC_CMNCR_IOFV_HIZ
|
294 RPC_CMNCR_MD
| RPC_CMNCR_BSZ(1));
298 ret
= rpc_hf_mode(target
, 1);
303 /* Submit HF address, SMCMR CMD[7] ~= CA Bit# 47 (R/nW) */
304 ret
= target_write_u32(target
, rpc_base
+ RPC_SMCMR
,
305 write
? 0 : RPC_SMCMR_CMD(0x80));
309 ret
= target_write_u32(target
, rpc_base
+ RPC_SMADR
,
314 ret
= target_write_u32(target
, rpc_base
+ RPC_SMOPR
, 0x0);
318 ret
= target_write_u32(target
, rpc_base
+ RPC_SMDRENR
,
319 RPC_SMDRENR_HYPE
| RPC_SMDRENR_ADDRE
|
324 val
= RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) |
325 RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) |
326 (wbuf_size
? RPC_SMENR_OPDB(2) : 0) |
327 RPC_SMENR_CDE
| RPC_SMENR_OCDE
| RPC_SMENR_ADE(4) | size
;
330 ret
= target_write_u32(target
, rpc_base
+ RPC_SMENR
, val
);
334 if (wbuf_size
== 0) {
335 buf_bswap32((uint8_t *)&wdata
, (uint8_t *)&wdata
, 4);
336 ret
= target_write_u32(target
, rpc_base
+ RPC_SMWDR0
,
342 ret
= target_write_u32(target
, rpc_base
+ RPC_SMCR
,
343 RPC_SMCR_SPIWE
| RPC_SMCR_SPIE
);
347 val
|= RPC_SMENR_DME
;
349 ret
= target_write_u32(target
, rpc_base
+ RPC_SMDMCR
,
350 RPC_SMDMCR_DMCYC(0xE));
354 ret
= target_write_u32(target
, rpc_base
+ RPC_SMENR
, val
);
358 ret
= target_write_u32(target
, rpc_base
+ RPC_SMCR
,
359 RPC_SMCR_SPIRE
| RPC_SMCR_SPIE
);
363 ret
= rpc_hf_wait_tend(target
);
368 ret
= target_read_u32(target
, rpc_base
+ RPC_SMRDR0
, &val32
);
371 buf_bswap32((uint8_t *)&val32
, (uint8_t *)&val32
, 4);
375 ret
= rpc_hf_mode(target
, 0);
377 LOG_ERROR("Xfer done TEND timeout");
381 static int rpchf_target_write_memory(struct flash_bank
*bank
, target_addr_t addr
,
382 uint32_t count
, const uint8_t *buffer
)
384 struct target
*target
= bank
->target
;
390 wdata
= buffer
[0] | (buffer
[1] << 8);
392 return rpc_hf_xfer(target
, addr
, wdata
, NULL
, RPC_HF_SIZE_16BIT
,
396 static int rpchf_target_read_memory(struct flash_bank
*bank
, target_addr_t addr
,
397 uint32_t count
, uint8_t *buffer
)
399 struct target
*target
= bank
->target
;
403 for (i
= 0; i
< count
; i
++) {
404 ret
= rpc_hf_xfer(target
, addr
+ (2 * i
), 0, &rdata
,
405 RPC_HF_SIZE_16BIT
, false, NULL
, 0);
408 buffer
[(2 * i
) + 0] = rdata
& 0xff;
409 buffer
[(2 * i
) + 1] = (rdata
>> 8) & 0xff;
415 FLASH_BANK_COMMAND_HANDLER(rpchf_flash_bank_command
)
417 struct cfi_flash_bank
*cfi_info
;
420 ret
= cfi_flash_bank_cmd(bank
, CMD_ARGC
, CMD_ARGV
);
424 cfi_info
= bank
->driver_priv
;
425 cfi_info
->read_mem
= rpchf_target_read_memory
;
426 cfi_info
->write_mem
= rpchf_target_write_memory
;
431 static int rpchf_spansion_write_words(struct flash_bank
*bank
, const uint8_t *word
,
432 uint32_t wordcount
, uint32_t address
)
435 struct cfi_flash_bank
*cfi_info
= bank
->driver_priv
;
436 struct cfi_spansion_pri_ext
*pri_ext
= cfi_info
->pri_ext
;
438 /* Calculate buffer size and boundary mask
439 * buffersize is (buffer size per chip) * (number of chips)
440 * bufferwsize is buffersize in words */
441 uint32_t buffersize
= RPC_WBUF_SIZE
;
442 uint32_t buffermask
= buffersize
- 1;
443 uint32_t bufferwsize
= buffersize
/ 2;
445 /* Check for valid range */
446 if (address
& buffermask
) {
447 LOG_ERROR("Write address at base " TARGET_ADDR_FMT
448 ", address 0x%" PRIx32
" not aligned to 2^%d boundary",
449 bank
->base
, address
, cfi_info
->max_buf_write_size
);
450 return ERROR_FLASH_OPERATION_FAILED
;
453 /* Check for valid size */
454 if (wordcount
> bufferwsize
) {
455 LOG_ERROR("Number of data words %" PRIu32
" exceeds available buffersize %"
456 PRIu32
, wordcount
, buffersize
);
457 return ERROR_FLASH_OPERATION_FAILED
;
461 retval
= cfi_spansion_unlock_seq(bank
);
462 if (retval
!= ERROR_OK
)
465 retval
= cfi_send_command(bank
, 0xa0, cfi_flash_address(bank
, 0, pri_ext
->_unlock1
));
466 if (retval
!= ERROR_OK
)
469 retval
= rpc_hf_xfer(bank
->target
, address
, 0, NULL
, RPC_HF_SIZE_64BIT
, true, word
, wordcount
* 2);
470 if (retval
!= ERROR_OK
)
473 if (cfi_spansion_wait_status_busy(bank
, cfi_info
->word_write_timeout
) != ERROR_OK
) {
474 retval
= cfi_send_command(bank
, 0xf0, cfi_flash_address(bank
, 0, 0x0));
475 if (retval
!= ERROR_OK
)
478 LOG_ERROR("couldn't write block at base " TARGET_ADDR_FMT
479 ", address 0x%" PRIx32
", size 0x%" PRIx32
, bank
->base
, address
,
481 return ERROR_FLASH_OPERATION_FAILED
;
487 static int rpchf_write_words(struct flash_bank
*bank
, const uint8_t *word
,
488 uint32_t wordcount
, uint32_t address
)
490 return rpchf_spansion_write_words(bank
, word
, wordcount
, address
);
493 static int rpchf_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
, uint32_t count
)
495 struct cfi_flash_bank
*cfi_info
= bank
->driver_priv
;
496 uint32_t address
= bank
->base
+ offset
; /* address of first byte to be programmed */
498 int align
; /* number of unaligned bytes */
499 uint8_t current_word
[CFI_MAX_BUS_WIDTH
* 4]; /* word (bus_width size) currently being
503 if (bank
->target
->state
!= TARGET_HALTED
) {
504 LOG_ERROR("Target not halted");
505 return ERROR_TARGET_NOT_HALTED
;
508 if (offset
+ count
> bank
->size
)
509 return ERROR_FLASH_DST_OUT_OF_BANK
;
511 if (cfi_info
->qry
[0] != 'Q')
512 return ERROR_FLASH_BANK_NOT_PROBED
;
514 /* start at the first byte of the first word (bus_width size) */
515 write_p
= address
& ~(bank
->bus_width
- 1);
516 align
= address
- write_p
;
518 LOG_INFO("Fixup %d unaligned head bytes", align
);
520 /* read a complete word from flash */
521 retval
= cfi_target_read_memory(bank
, write_p
, 1, current_word
);
522 if (retval
!= ERROR_OK
)
525 /* replace only bytes that must be written */
526 for (unsigned int i
= align
; (i
< bank
->bus_width
) && (count
> 0); i
++, count
--) {
527 if (cfi_info
->data_swap
)
528 /* data bytes are swapped (reverse endianness) */
529 current_word
[bank
->bus_width
- i
] = *buffer
++;
531 current_word
[i
] = *buffer
++;
534 retval
= cfi_write_word(bank
, current_word
, write_p
);
535 if (retval
!= ERROR_OK
)
537 write_p
+= bank
->bus_width
;
540 /* Calculate buffer size and boundary mask
541 * buffersize is (buffer size per chip) * (number of chips)
542 * bufferwsize is buffersize in words */
543 uint32_t buffersize
= RPC_WBUF_SIZE
;
544 uint32_t buffermask
= buffersize
-1;
545 uint32_t bufferwsize
= buffersize
/ bank
->bus_width
;
547 /* fall back to memory writes */
548 while (count
>= (uint32_t)bank
->bus_width
) {
550 if ((write_p
& 0xff) == 0) {
551 LOG_INFO("Programming at 0x%08" PRIx32
", count 0x%08"
552 PRIx32
" bytes remaining", write_p
, count
);
555 if ((bufferwsize
> 0) && (count
>= buffersize
) &&
556 !(write_p
& buffermask
)) {
557 retval
= rpchf_write_words(bank
, buffer
, bufferwsize
, write_p
);
558 if (retval
== ERROR_OK
) {
559 buffer
+= buffersize
;
560 write_p
+= buffersize
;
563 } else if (retval
!= ERROR_FLASH_OPER_UNSUPPORTED
)
566 /* try the slow way? */
568 for (unsigned int i
= 0; i
< bank
->bus_width
; i
++)
569 current_word
[i
] = *buffer
++;
571 retval
= cfi_write_word(bank
, current_word
, write_p
);
572 if (retval
!= ERROR_OK
)
575 write_p
+= bank
->bus_width
;
576 count
-= bank
->bus_width
;
580 /* return to read array mode, so we can read from flash again for padding */
581 retval
= cfi_reset(bank
);
582 if (retval
!= ERROR_OK
)
585 /* handle unaligned tail bytes */
587 LOG_INFO("Fixup %" PRIu32
" unaligned tail bytes", count
);
589 /* read a complete word from flash */
590 retval
= cfi_target_read_memory(bank
, write_p
, 1, current_word
);
591 if (retval
!= ERROR_OK
)
594 /* replace only bytes that must be written */
595 for (unsigned int i
= 0; (i
< bank
->bus_width
) && (count
> 0); i
++, count
--)
596 if (cfi_info
->data_swap
)
597 /* data bytes are swapped (reverse endianness) */
598 current_word
[bank
->bus_width
- i
] = *buffer
++;
600 current_word
[i
] = *buffer
++;
602 retval
= cfi_write_word(bank
, current_word
, write_p
);
603 if (retval
!= ERROR_OK
)
607 /* return to read array mode */
608 return cfi_reset(bank
);
611 static int rpchf_read(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
613 struct cfi_flash_bank
*cfi_info
= bank
->driver_priv
;
614 struct target
*target
= bank
->target
;
616 LOG_DEBUG("reading buffer of %" PRIu32
" byte at 0x%8.8" PRIx32
,
619 if (bank
->target
->state
!= TARGET_HALTED
) {
620 LOG_ERROR("Target not halted");
621 return ERROR_TARGET_NOT_HALTED
;
624 if (offset
+ count
> bank
->size
)
625 return ERROR_FLASH_DST_OUT_OF_BANK
;
627 if (cfi_info
->qry
[0] != 'Q')
628 return ERROR_FLASH_BANK_NOT_PROBED
;
630 return target_read_memory(target
, offset
| mem_base
,
631 4, count
/ 4, buffer
);
634 const struct flash_driver renesas_rpchf_flash
= {
636 .flash_bank_command
= rpchf_flash_bank_command
,
638 .protect
= cfi_protect
,
639 .write
= rpchf_write
,
642 .auto_probe
= cfi_auto_probe
,
643 .erase_check
= default_flash_blank_check
,
644 .protect_check
= cfi_protect_check
,
645 .info
= cfi_get_info
,
646 .free_driver_priv
= default_flash_free_driver_priv
,
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)