1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2016 by Uladzimir Pylinski aka barthess *
6 ***************************************************************************/
15 #include <jtag/jtag.h>
16 #include <helper/time_support.h>
19 ******************************************************************************
21 ******************************************************************************
24 #define SECTOR_ERASE_TIMEOUT_MS (35 * 1000)
26 #define XCF_PAGE_SIZE 32
27 #define XCF_DATA_SECTOR_SIZE (1024 * 1024)
29 #define ID_XCF01S 0x05044093
30 #define ID_XCF02S 0x05045093
31 #define ID_XCF04S 0x05046093
32 #define ID_XCF08P 0x05057093
33 #define ID_XCF16P 0x05058093
34 #define ID_XCF32P 0x05059093
35 #define ID_MEANINGFUL_MASK 0x0FFFFFFF
37 static const char * const xcf_name_list
[] = {
49 bool isc_error
; /* false == OK, true == error */
50 bool prog_error
; /* false == OK, true == error */
51 bool prog_busy
; /* false == idle, true == busy */
52 bool isc_mode
; /* false == normal mode, true == ISC mode */
56 ******************************************************************************
58 ******************************************************************************
60 static const uint8_t cmd_bypass
[2] = {0xFF, 0xFF};
62 static const uint8_t cmd_isc_address_shift
[2] = {0xEB, 0x00};
63 static const uint8_t cmd_isc_data_shift
[2] = {0xED, 0x00};
64 static const uint8_t cmd_isc_disable
[2] = {0xF0, 0x00};
65 static const uint8_t cmd_isc_enable
[2] = {0xE8, 0x00};
66 static const uint8_t cmd_isc_erase
[2] = {0xEC, 0x00};
67 static const uint8_t cmd_isc_program
[2] = {0xEA, 0x00};
69 static const uint8_t cmd_xsc_blank_check
[2] = {0x0D, 0x00};
70 static const uint8_t cmd_xsc_config
[2] = {0xEE, 0x00};
71 static const uint8_t cmd_xsc_data_btc
[2] = {0xF2, 0x00};
72 static const uint8_t cmd_xsc_data_ccb
[2] = {0x0C, 0x00};
73 static const uint8_t cmd_xsc_data_done
[2] = {0x09, 0x00};
74 static const uint8_t cmd_xsc_data_sucr
[2] = {0x0E, 0x00};
75 static const uint8_t cmd_xsc_data_wrpt
[2] = {0xF7, 0x00};
76 static const uint8_t cmd_xsc_op_status
[2] = {0xE3, 0x00};
77 static const uint8_t cmd_xsc_read
[2] = {0xEF, 0x00};
78 static const uint8_t cmd_xsc_unlock
[2] = {0x55, 0xAA};
81 ******************************************************************************
83 ******************************************************************************
86 static const char *product_name(const struct flash_bank
*bank
)
89 switch (bank
->target
->tap
->idcode
& ID_MEANINGFUL_MASK
) {
91 return xcf_name_list
[0];
93 return xcf_name_list
[1];
95 return xcf_name_list
[2];
97 return xcf_name_list
[3];
101 static void fill_sector_table(struct flash_bank
*bank
)
103 /* Note: is_erased and is_protected fields must be set here to an unknown
104 * state, they will be correctly filled from other API calls. */
106 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
107 bank
->sectors
[i
].is_erased
= -1;
108 bank
->sectors
[i
].is_protected
= -1;
110 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
111 bank
->sectors
[i
].size
= XCF_DATA_SECTOR_SIZE
;
112 bank
->sectors
[i
].offset
= i
* XCF_DATA_SECTOR_SIZE
;
115 bank
->size
= bank
->num_sectors
* XCF_DATA_SECTOR_SIZE
;
118 static struct xcf_status
read_status(struct flash_bank
*bank
)
120 struct xcf_status ret
;
122 struct scan_field scan
;
124 scan
.check_mask
= NULL
;
125 scan
.check_value
= NULL
;
127 scan
.out_value
= cmd_bypass
;
128 scan
.in_value
= irdata
;
130 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
131 jtag_execute_queue();
133 ret
.isc_error
= ((irdata
[0] >> 7) & 3) == 1;
134 ret
.prog_error
= ((irdata
[0] >> 5) & 3) == 1;
135 ret
.prog_busy
= ((irdata
[0] >> 4) & 1) == 0;
136 ret
.isc_mode
= ((irdata
[0] >> 3) & 1) == 1;
141 static int isc_enter(struct flash_bank
*bank
)
144 struct xcf_status status
= read_status(bank
);
146 if (true == status
.isc_mode
)
149 struct scan_field scan
;
151 scan
.check_mask
= NULL
;
152 scan
.check_value
= NULL
;
154 scan
.out_value
= cmd_isc_enable
;
155 scan
.in_value
= NULL
;
157 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
158 jtag_execute_queue();
160 status
= read_status(bank
);
161 if (!status
.isc_mode
) {
162 LOG_ERROR("*** XCF: FAILED to enter ISC mode");
163 return ERROR_FLASH_OPERATION_FAILED
;
170 static int isc_leave(struct flash_bank
*bank
)
173 struct xcf_status status
= read_status(bank
);
175 if (!status
.isc_mode
)
178 struct scan_field scan
;
180 scan
.check_mask
= NULL
;
181 scan
.check_value
= NULL
;
183 scan
.out_value
= cmd_isc_disable
;
184 scan
.in_value
= NULL
;
186 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
187 jtag_execute_queue();
188 alive_sleep(1); /* device needs 50 uS to leave ISC mode */
190 status
= read_status(bank
);
191 if (status
.isc_mode
) {
192 LOG_ERROR("*** XCF: FAILED to leave ISC mode");
193 return ERROR_FLASH_OPERATION_FAILED
;
200 static int sector_state(uint8_t wrpt
, int sector
)
202 if (((wrpt
>> sector
) & 1) == 1)
208 static uint8_t fill_select_block(unsigned int first
, unsigned int last
)
211 for (unsigned int i
= first
; i
<= last
; i
++)
216 static int isc_read_register(struct flash_bank
*bank
, const uint8_t *cmd
,
217 uint8_t *data_buf
, int num_bits
)
219 struct scan_field scan
;
221 scan
.check_mask
= NULL
;
222 scan
.check_value
= NULL
;
223 scan
.out_value
= cmd
;
224 scan
.in_value
= NULL
;
226 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_DRSHIFT
);
228 scan
.out_value
= NULL
;
229 scan
.in_value
= data_buf
;
230 scan
.num_bits
= num_bits
;
231 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IDLE
);
233 return jtag_execute_queue();
236 static int isc_wait_erase_program(struct flash_bank
*bank
, int64_t timeout_ms
)
240 int64_t t0
= timeval_ms();
244 isc_read_register(bank
, cmd_xsc_op_status
, &isc_default
, 8);
245 if (((isc_default
>> 2) & 1) == 1)
247 dt
= timeval_ms() - t0
;
248 } while (dt
<= timeout_ms
);
249 return ERROR_FLASH_OPERATION_FAILED
;
253 * helper function for procedures without program jtag command at the end
255 static int isc_set_register(struct flash_bank
*bank
, const uint8_t *cmd
,
256 const uint8_t *data_buf
, int num_bits
, int64_t timeout_ms
)
258 struct scan_field scan
;
260 scan
.check_mask
= NULL
;
261 scan
.check_value
= NULL
;
263 scan
.out_value
= cmd
;
264 scan
.in_value
= NULL
;
265 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_DRSHIFT
);
267 scan
.num_bits
= num_bits
;
268 scan
.out_value
= data_buf
;
269 scan
.in_value
= NULL
;
270 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IDLE
);
273 return jtag_execute_queue();
275 return isc_wait_erase_program(bank
, timeout_ms
);
279 * helper function for procedures required program jtag command at the end
281 static int isc_program_register(struct flash_bank
*bank
, const uint8_t *cmd
,
282 const uint8_t *data_buf
, int num_bits
, int64_t timeout_ms
)
284 struct scan_field scan
;
286 scan
.check_mask
= NULL
;
287 scan
.check_value
= NULL
;
289 scan
.out_value
= cmd
;
290 scan
.in_value
= NULL
;
291 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_DRSHIFT
);
293 scan
.num_bits
= num_bits
;
294 scan
.out_value
= data_buf
;
295 scan
.in_value
= NULL
;
296 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IRSHIFT
);
299 scan
.out_value
= cmd_isc_program
;
300 scan
.in_value
= NULL
;
301 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
304 return jtag_execute_queue();
306 return isc_wait_erase_program(bank
, timeout_ms
);
309 static int isc_clear_protect(struct flash_bank
*bank
, unsigned int first
,
312 uint8_t select_block
[3] = {0x0, 0x0, 0x0};
313 select_block
[0] = fill_select_block(first
, last
);
314 return isc_set_register(bank
, cmd_xsc_unlock
, select_block
, 24, 0);
317 static int isc_set_protect(struct flash_bank
*bank
, unsigned int first
,
320 uint8_t wrpt
[2] = {0xFF, 0xFF};
321 for (unsigned int i
= first
; i
<= last
; i
++)
322 wrpt
[0] &= ~(1 << i
);
324 return isc_program_register(bank
, cmd_xsc_data_wrpt
, wrpt
, 16, 0);
327 static int isc_erase_sectors(struct flash_bank
*bank
, unsigned int first
,
330 uint8_t select_block
[3] = {0, 0, 0};
331 select_block
[0] = fill_select_block(first
, last
);
332 int64_t timeout
= SECTOR_ERASE_TIMEOUT_MS
* (last
- first
+ 1);
333 return isc_set_register(bank
, cmd_isc_erase
, select_block
, 24, timeout
);
336 static int isc_adr_shift(struct flash_bank
*bank
, int adr
)
339 h_u24_to_le(adr_buf
, adr
);
340 return isc_set_register(bank
, cmd_isc_address_shift
, adr_buf
, 24, 0);
343 static int isc_program_data_page(struct flash_bank
*bank
, const uint8_t *page_buf
)
345 return isc_program_register(bank
, cmd_isc_data_shift
, page_buf
, 8 * XCF_PAGE_SIZE
, 100);
348 static void isc_data_read_out(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t count
)
351 struct scan_field scan
;
353 /* Do not change this code with isc_read_register() call because it needs
354 * transition to IDLE state before data retrieving. */
355 scan
.check_mask
= NULL
;
356 scan
.check_value
= NULL
;
358 scan
.out_value
= cmd_xsc_read
;
359 scan
.in_value
= NULL
;
360 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
362 scan
.num_bits
= 8 * count
;
363 scan
.out_value
= NULL
;
364 scan
.in_value
= buffer
;
365 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IDLE
);
367 jtag_execute_queue();
370 static int isc_set_data_done(struct flash_bank
*bank
, int sector
)
373 done
&= ~(1 << sector
);
374 return isc_program_register(bank
, cmd_xsc_data_done
, &done
, 8, 100);
377 static void flip_u8(uint8_t *out
, const uint8_t *in
, int len
)
379 for (int i
= 0; i
< len
; i
++)
380 out
[i
] = flip_u32(in
[i
], 8);
384 * Xilinx bin file contains simple fixed header for automatic bus width detection:
386 * 4 byte sync word 0xAA995566 or (bit reversed) 0x5599AA66 in MSC file
388 * Function presumes need of bit reversing if it can not exactly detects
391 static bool need_bit_reverse(const uint8_t *buffer
)
394 uint8_t reference
[L
];
395 memset(reference
, 0xFF, 16);
396 reference
[16] = 0x55;
397 reference
[17] = 0x99;
398 reference
[18] = 0xAA;
399 reference
[19] = 0x66;
401 if (memcmp(reference
, buffer
, L
) == 0)
408 * The page address to be programmed is determined by loading the
409 * internal ADDRESS Register using an ISC_ADDRESS_SHIFT instruction sequence.
410 * The page address automatically increments to the next 256-bit
411 * page address after each programming sequence until the last address
412 * in the 8 Mb block is reached. To continue programming the next block,
413 * the next 8 Mb block's starting address must be loaded into the
414 * internal ADDRESS register.
416 static int read_write_data(struct flash_bank
*bank
, const uint8_t *w_buffer
,
417 uint8_t *r_buffer
, bool write_flag
, uint32_t offset
, uint32_t count
)
419 int dbg_count
= count
;
422 uint8_t *page_buf
= malloc(XCF_PAGE_SIZE
);
426 if (offset
% XCF_PAGE_SIZE
!= 0) {
427 ret
= ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
431 if ((offset
+ count
) > (bank
->num_sectors
* XCF_DATA_SECTOR_SIZE
)) {
432 ret
= ERROR_FLASH_DST_OUT_OF_BANK
;
436 if ((write_flag
) && (offset
== 0) && (count
>= XCF_PAGE_SIZE
))
437 revbit
= need_bit_reverse(w_buffer
);
440 uint32_t sector_num
= offset
/ XCF_DATA_SECTOR_SIZE
;
441 uint32_t sector_offset
= offset
- sector_num
* XCF_DATA_SECTOR_SIZE
;
442 uint32_t sector_bytes
= XCF_DATA_SECTOR_SIZE
- sector_offset
;
443 if (count
< sector_bytes
)
444 sector_bytes
= count
;
445 isc_adr_shift(bank
, offset
);
446 offset
+= sector_bytes
;
447 count
-= sector_bytes
;
450 while (sector_bytes
> 0) {
453 if (sector_bytes
< XCF_PAGE_SIZE
) {
455 memset(page_buf
, 0xFF, XCF_PAGE_SIZE
);
460 flip_u8(page_buf
, w_buffer
, len
);
462 memcpy(page_buf
, w_buffer
, len
);
466 ret
= isc_program_data_page(bank
, page_buf
);
470 LOG_DEBUG("written %d bytes from %d", dbg_written
, dbg_count
);
475 isc_data_read_out(bank
, r_buffer
, sector_bytes
);
476 flip_u8(r_buffer
, r_buffer
, sector_bytes
);
477 r_buffer
+= sector_bytes
;
481 /* Set 'done' flags for all data sectors because driver supports
482 * only single revision. */
484 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
485 ret
= isc_set_data_done(bank
, i
);
497 static uint16_t isc_read_ccb(struct flash_bank
*bank
)
500 isc_read_register(bank
, cmd_xsc_data_ccb
, ccb
, 16);
501 return le_to_h_u16(ccb
);
504 static unsigned int gucr_num(const struct flash_bank
*bank
)
506 return bank
->num_sectors
;
509 static unsigned int sucr_num(const struct flash_bank
*bank
)
511 return bank
->num_sectors
+ 1;
514 static int isc_program_ccb(struct flash_bank
*bank
, uint16_t ccb
)
517 h_u16_to_le(buf
, ccb
);
518 return isc_program_register(bank
, cmd_xsc_data_ccb
, buf
, 16, 100);
521 static int isc_program_singe_revision_sucr(struct flash_bank
*bank
)
523 uint8_t sucr
[2] = {0xFC, 0xFF};
524 return isc_program_register(bank
, cmd_xsc_data_sucr
, sucr
, 16, 100);
527 static int isc_program_single_revision_btc(struct flash_bank
*bank
)
530 uint32_t btc
= 0xFFFFFFFF;
532 btc
|= ((bank
->num_sectors
- 1) << 2);
534 h_u32_to_le(buf
, btc
);
535 return isc_program_register(bank
, cmd_xsc_data_btc
, buf
, 32, 100);
538 static int fpga_configure(struct flash_bank
*bank
)
540 struct scan_field scan
;
542 scan
.check_mask
= NULL
;
543 scan
.check_value
= NULL
;
545 scan
.out_value
= cmd_xsc_config
;
546 scan
.in_value
= NULL
;
547 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
548 jtag_execute_queue();
554 ******************************************************************************
556 ******************************************************************************
559 FLASH_BANK_COMMAND_HANDLER(xcf_flash_bank_command
)
561 struct xcf_priv
*priv
;
563 priv
= malloc(sizeof(struct xcf_priv
));
565 LOG_ERROR("no memory for flash bank info");
568 bank
->driver_priv
= priv
;
569 priv
->probed
= false;
573 static int xcf_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
575 const struct xcf_priv
*priv
= bank
->driver_priv
;
578 command_print_sameline(cmd
, "\nXCF flash bank not probed yet\n");
581 command_print_sameline(cmd
, "%s", product_name(bank
));
585 static int xcf_probe(struct flash_bank
*bank
)
587 struct xcf_priv
*priv
= bank
->driver_priv
;
592 priv
->probed
= false;
594 if (!bank
->target
->tap
) {
595 LOG_ERROR("Target has no JTAG tap");
599 /* check idcode and alloc memory for sector table */
600 if (!bank
->target
->tap
->has_idcode
)
601 return ERROR_FLASH_OPERATION_FAILED
;
603 /* guess number of blocks using chip ID */
604 id
= bank
->target
->tap
->idcode
;
605 switch (id
& ID_MEANINGFUL_MASK
) {
607 bank
->num_sectors
= 1;
610 bank
->num_sectors
= 2;
613 bank
->num_sectors
= 4;
616 LOG_ERROR("Unknown flash device ID 0x%" PRIX32
, id
);
620 bank
->sectors
= malloc(bank
->num_sectors
* sizeof(struct flash_sector
));
621 if (!bank
->sectors
) {
622 LOG_ERROR("No memory for sector table");
625 fill_sector_table(bank
);
628 /* REVISIT: Why is unchanged bank->driver_priv rewritten by same value? */
629 bank
->driver_priv
= priv
;
631 LOG_INFO("product name: %s", product_name(bank
));
632 LOG_INFO("device id = 0x%" PRIX32
, bank
->target
->tap
->idcode
);
633 LOG_INFO("flash size = %d configuration bits",
634 bank
->num_sectors
* XCF_DATA_SECTOR_SIZE
* 8);
635 LOG_INFO("number of sectors = %u", bank
->num_sectors
);
640 static int xcf_auto_probe(struct flash_bank
*bank
)
642 struct xcf_priv
*priv
= bank
->driver_priv
;
647 return xcf_probe(bank
);
650 static int xcf_protect_check(struct flash_bank
*bank
)
655 isc_read_register(bank
, cmd_xsc_data_wrpt
, wrpt
, 16);
658 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
659 bank
->sectors
[i
].is_protected
= sector_state(wrpt
[0], i
);
664 static int xcf_erase_check(struct flash_bank
*bank
)
667 struct scan_field scan
;
671 /* Do not change this code with isc_read_register() call because it needs
672 * transition to IDLE state and pause before data retrieving. */
673 scan
.check_mask
= NULL
;
674 scan
.check_value
= NULL
;
676 scan
.out_value
= cmd_xsc_blank_check
;
677 scan
.in_value
= NULL
;
678 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
679 jtag_execute_queue();
680 alive_sleep(500); /* device needs at least 0.5s to self check */
683 scan
.in_value
= &blankreg
;
684 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IDLE
);
685 jtag_execute_queue();
689 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
690 bank
->sectors
[i
].is_erased
= sector_state(blankreg
, i
);
695 static int xcf_erase(struct flash_bank
*bank
, unsigned int first
,
698 if ((first
>= bank
->num_sectors
)
699 || (last
>= bank
->num_sectors
)
701 return ERROR_FLASH_SECTOR_INVALID
;
704 isc_clear_protect(bank
, first
, last
);
705 int ret
= isc_erase_sectors(bank
, first
, last
);
711 static int xcf_read(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
713 return read_write_data(bank
, NULL
, buffer
, false, offset
, count
);
716 static int xcf_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
,
719 return read_write_data(bank
, buffer
, NULL
, true, offset
, count
);
722 static int xcf_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
729 ret
= isc_set_protect(bank
, first
, last
);
731 /* write protection may be removed only with following erase */
732 isc_clear_protect(bank
, first
, last
);
733 ret
= isc_erase_sectors(bank
, first
, last
);
740 COMMAND_HANDLER(xcf_handle_ccb_command
) {
742 if (!((CMD_ARGC
== 1) || (CMD_ARGC
== 5)))
743 return ERROR_COMMAND_SYNTAX_ERROR
;
745 struct flash_bank
*bank
;
746 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
747 if (retval
!= ERROR_OK
)
750 uint16_t ccb
= 0xFFFF;
752 uint16_t old_ccb
= isc_read_ccb(bank
);
756 LOG_INFO("current CCB = 0x%X", old_ccb
);
759 /* skip over flash bank */
763 if (strcmp("external", CMD_ARGV
[0]) == 0)
765 else if (strcmp("internal", CMD_ARGV
[0]) == 0)
767 else if (strcmp("serial", CMD_ARGV
[0]) == 0)
769 else if (strcmp("parallel", CMD_ARGV
[0]) == 0)
771 else if (strcmp("slave", CMD_ARGV
[0]) == 0)
773 else if (strcmp("master", CMD_ARGV
[0]) == 0)
775 else if (strcmp("40", CMD_ARGV
[0]) == 0)
777 else if (strcmp("20", CMD_ARGV
[0]) == 0)
780 return ERROR_COMMAND_SYNTAX_ERROR
;
789 sector
= gucr_num(bank
);
790 isc_clear_protect(bank
, sector
, sector
);
791 int ret
= isc_erase_sectors(bank
, sector
, sector
);
794 ret
= isc_program_ccb(bank
, ccb
);
797 ret
= isc_program_single_revision_btc(bank
);
800 ret
= isc_set_data_done(bank
, sector
);
805 sector
= sucr_num(bank
);
806 isc_clear_protect(bank
, sector
, sector
);
807 ret
= isc_erase_sectors(bank
, sector
, sector
);
810 ret
= isc_program_singe_revision_sucr(bank
);
813 ret
= isc_set_data_done(bank
, sector
);
823 COMMAND_HANDLER(xcf_handle_configure_command
) {
826 return ERROR_COMMAND_SYNTAX_ERROR
;
828 struct flash_bank
*bank
;
829 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
830 if (retval
!= ERROR_OK
)
833 return fpga_configure(bank
);
836 static const struct command_registration xcf_exec_command_handlers
[] = {
839 .handler
= xcf_handle_configure_command
,
840 .mode
= COMMAND_EXEC
,
842 .help
= "Initiate FPGA loading procedure."
846 .handler
= xcf_handle_ccb_command
,
847 .mode
= COMMAND_EXEC
,
848 .usage
= "bank_id [('external'|'internal') "
849 "('serial'|'parallel') "
850 "('slave'|'master') "
852 .help
= "Write CCB register with supplied options and (silently) BTC "
853 "register with single revision options. Display current "
854 "CCB value when only bank_id supplied. "
855 "Following options available: "
856 "1) external or internal clock source; "
857 "2) serial or parallel bus mode; "
858 "3) slave or master mode; "
859 "4) clock frequency in MHz for internal clock in master mode;"
861 COMMAND_REGISTRATION_DONE
864 static const struct command_registration xcf_command_handlers
[] = {
868 .help
= "Xilinx platform flash command group",
870 .chain
= xcf_exec_command_handlers
872 COMMAND_REGISTRATION_DONE
875 const struct flash_driver xcf_flash
= {
878 .commands
= xcf_command_handlers
,
879 .flash_bank_command
= xcf_flash_bank_command
,
881 .protect
= xcf_protect
,
885 .auto_probe
= xcf_auto_probe
,
886 .erase_check
= xcf_erase_check
,
887 .protect_check
= xcf_protect_check
,
889 .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)