1 /***************************************************************************
2 * Copyright (C) 2016 by Uladzimir Pylinski aka barthess *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
26 #include <jtag/jtag.h>
27 #include <helper/time_support.h>
30 ******************************************************************************
32 ******************************************************************************
35 #define SECTOR_ERASE_TIMEOUT_MS (35 * 1000)
37 #define XCF_PAGE_SIZE 32
38 #define XCF_DATA_SECTOR_SIZE (1024 * 1024)
40 #define ID_XCF01S 0x05044093
41 #define ID_XCF02S 0x05045093
42 #define ID_XCF04S 0x05046093
43 #define ID_XCF08P 0x05057093
44 #define ID_XCF16P 0x05058093
45 #define ID_XCF32P 0x05059093
46 #define ID_MEANINGFUL_MASK 0x0FFFFFFF
48 static const char * const xcf_name_list
[] = {
60 bool isc_error
; /* false == OK, true == error */
61 bool prog_error
; /* false == OK, true == error */
62 bool prog_busy
; /* false == idle, true == busy */
63 bool isc_mode
; /* false == normal mode, true == ISC mode */
67 ******************************************************************************
69 ******************************************************************************
71 static const uint8_t CMD_BYPASS
[2] = {0xFF, 0xFF};
73 static const uint8_t CMD_ISC_ADDRESS_SHIFT
[2] = {0xEB, 0x00};
74 static const uint8_t CMD_ISC_DATA_SHIFT
[2] = {0xED, 0x00};
75 static const uint8_t CMD_ISC_DISABLE
[2] = {0xF0, 0x00};
76 static const uint8_t CMD_ISC_ENABLE
[2] = {0xE8, 0x00};
77 static const uint8_t CMD_ISC_ERASE
[2] = {0xEC, 0x00};
78 static const uint8_t CMD_ISC_PROGRAM
[2] = {0xEA, 0x00};
80 static const uint8_t CMD_XSC_BLANK_CHECK
[2] = {0x0D, 0x00};
81 static const uint8_t CMD_XSC_CONFIG
[2] = {0xEE, 0x00};
82 static const uint8_t CMD_XSC_DATA_BTC
[2] = {0xF2, 0x00};
83 static const uint8_t CMD_XSC_DATA_CCB
[2] = {0x0C, 0x00};
84 static const uint8_t CMD_XSC_DATA_DONE
[2] = {0x09, 0x00};
85 static const uint8_t CMD_XSC_DATA_SUCR
[2] = {0x0E, 0x00};
86 static const uint8_t CMD_XSC_DATA_WRPT
[2] = {0xF7, 0x00};
87 static const uint8_t CMD_XSC_OP_STATUS
[2] = {0xE3, 0x00};
88 static const uint8_t CMD_XSC_READ
[2] = {0xEF, 0x00};
89 static const uint8_t CMD_XSC_UNLOCK
[2] = {0x55, 0xAA};
92 ******************************************************************************
94 ******************************************************************************
97 static const char *product_name(const struct flash_bank
*bank
)
100 switch (bank
->target
->tap
->idcode
& ID_MEANINGFUL_MASK
) {
102 return xcf_name_list
[0];
104 return xcf_name_list
[1];
106 return xcf_name_list
[2];
108 return xcf_name_list
[3];
112 static void fill_sector_table(struct flash_bank
*bank
)
114 /* Note: is_erased and is_protected fields must be set here to an unknown
115 * state, they will be correctly filled from other API calls. */
117 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
118 bank
->sectors
[i
].is_erased
= -1;
119 bank
->sectors
[i
].is_protected
= -1;
121 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
122 bank
->sectors
[i
].size
= XCF_DATA_SECTOR_SIZE
;
123 bank
->sectors
[i
].offset
= i
* XCF_DATA_SECTOR_SIZE
;
126 bank
->size
= bank
->num_sectors
* XCF_DATA_SECTOR_SIZE
;
129 static struct xcf_status
read_status(struct flash_bank
*bank
)
131 struct xcf_status ret
;
133 struct scan_field scan
;
135 scan
.check_mask
= NULL
;
136 scan
.check_value
= NULL
;
138 scan
.out_value
= CMD_BYPASS
;
139 scan
.in_value
= irdata
;
141 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
142 jtag_execute_queue();
144 ret
.isc_error
= ((irdata
[0] >> 7) & 3) == 0b01;
145 ret
.prog_error
= ((irdata
[0] >> 5) & 3) == 0b01;
146 ret
.prog_busy
= ((irdata
[0] >> 4) & 1) == 0;
147 ret
.isc_mode
= ((irdata
[0] >> 3) & 1) == 1;
152 static int isc_enter(struct flash_bank
*bank
)
155 struct xcf_status status
= read_status(bank
);
157 if (true == status
.isc_mode
)
160 struct scan_field scan
;
162 scan
.check_mask
= NULL
;
163 scan
.check_value
= NULL
;
165 scan
.out_value
= CMD_ISC_ENABLE
;
166 scan
.in_value
= NULL
;
168 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
169 jtag_execute_queue();
171 status
= read_status(bank
);
172 if (false == status
.isc_mode
) {
173 LOG_ERROR("*** XCF: FAILED to enter ISC mode");
174 return ERROR_FLASH_OPERATION_FAILED
;
181 static int isc_leave(struct flash_bank
*bank
)
184 struct xcf_status status
= read_status(bank
);
186 if (false == status
.isc_mode
)
189 struct scan_field scan
;
191 scan
.check_mask
= NULL
;
192 scan
.check_value
= NULL
;
194 scan
.out_value
= CMD_ISC_DISABLE
;
195 scan
.in_value
= NULL
;
197 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
198 jtag_execute_queue();
199 alive_sleep(1); /* device needs 50 uS to leave ISC mode */
201 status
= read_status(bank
);
202 if (true == status
.isc_mode
) {
203 LOG_ERROR("*** XCF: FAILED to leave ISC mode");
204 return ERROR_FLASH_OPERATION_FAILED
;
211 static int sector_state(uint8_t wrpt
, int sector
)
213 if (((wrpt
>> sector
) & 1) == 1)
219 static uint8_t fill_select_block(unsigned int first
, unsigned int last
)
222 for (unsigned int i
= first
; i
<= last
; i
++)
227 static int isc_read_register(struct flash_bank
*bank
, const uint8_t *cmd
,
228 uint8_t *data_buf
, int num_bits
)
230 struct scan_field scan
;
232 scan
.check_mask
= NULL
;
233 scan
.check_value
= NULL
;
234 scan
.out_value
= cmd
;
235 scan
.in_value
= NULL
;
237 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_DRSHIFT
);
239 scan
.out_value
= NULL
;
240 scan
.in_value
= data_buf
;
241 scan
.num_bits
= num_bits
;
242 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IDLE
);
244 return jtag_execute_queue();
247 static int isc_wait_erase_program(struct flash_bank
*bank
, int64_t timeout_ms
)
251 int64_t t0
= timeval_ms();
255 isc_read_register(bank
, CMD_XSC_OP_STATUS
, &isc_default
, 8);
256 if (((isc_default
>> 2) & 1) == 1)
258 dt
= timeval_ms() - t0
;
259 } while (dt
<= timeout_ms
);
260 return ERROR_FLASH_OPERATION_FAILED
;
264 * helper function for procedures without program jtag command at the end
266 static int isc_set_register(struct flash_bank
*bank
, const uint8_t *cmd
,
267 const uint8_t *data_buf
, int num_bits
, int64_t timeout_ms
)
269 struct scan_field scan
;
271 scan
.check_mask
= NULL
;
272 scan
.check_value
= NULL
;
274 scan
.out_value
= cmd
;
275 scan
.in_value
= NULL
;
276 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_DRSHIFT
);
278 scan
.num_bits
= num_bits
;
279 scan
.out_value
= data_buf
;
280 scan
.in_value
= NULL
;
281 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IDLE
);
284 return jtag_execute_queue();
286 return isc_wait_erase_program(bank
, timeout_ms
);
290 * helper function for procedures required program jtag command at the end
292 static int isc_program_register(struct flash_bank
*bank
, const uint8_t *cmd
,
293 const uint8_t *data_buf
, int num_bits
, int64_t timeout_ms
)
295 struct scan_field scan
;
297 scan
.check_mask
= NULL
;
298 scan
.check_value
= NULL
;
300 scan
.out_value
= cmd
;
301 scan
.in_value
= NULL
;
302 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_DRSHIFT
);
304 scan
.num_bits
= num_bits
;
305 scan
.out_value
= data_buf
;
306 scan
.in_value
= NULL
;
307 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IRSHIFT
);
310 scan
.out_value
= CMD_ISC_PROGRAM
;
311 scan
.in_value
= NULL
;
312 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
315 return jtag_execute_queue();
317 return isc_wait_erase_program(bank
, timeout_ms
);
320 static int isc_clear_protect(struct flash_bank
*bank
, unsigned int first
,
323 uint8_t select_block
[3] = {0x0, 0x0, 0x0};
324 select_block
[0] = fill_select_block(first
, last
);
325 return isc_set_register(bank
, CMD_XSC_UNLOCK
, select_block
, 24, 0);
328 static int isc_set_protect(struct flash_bank
*bank
, unsigned int first
,
331 uint8_t wrpt
[2] = {0xFF, 0xFF};
332 for (unsigned int i
= first
; i
<= last
; i
++)
333 wrpt
[0] &= ~(1 << i
);
335 return isc_program_register(bank
, CMD_XSC_DATA_WRPT
, wrpt
, 16, 0);
338 static int isc_erase_sectors(struct flash_bank
*bank
, unsigned int first
,
341 uint8_t select_block
[3] = {0, 0, 0};
342 select_block
[0] = fill_select_block(first
, last
);
343 int64_t timeout
= SECTOR_ERASE_TIMEOUT_MS
* (last
- first
+ 1);
344 return isc_set_register(bank
, CMD_ISC_ERASE
, select_block
, 24, timeout
);
347 static int isc_adr_shift(struct flash_bank
*bank
, int adr
)
350 h_u24_to_le(adr_buf
, adr
);
351 return isc_set_register(bank
, CMD_ISC_ADDRESS_SHIFT
, adr_buf
, 24, 0);
354 static int isc_program_data_page(struct flash_bank
*bank
, const uint8_t *page_buf
)
356 return isc_program_register(bank
, CMD_ISC_DATA_SHIFT
, page_buf
, 8 * XCF_PAGE_SIZE
, 100);
359 static void isc_data_read_out(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t count
)
362 struct scan_field scan
;
364 /* Do not change this code with isc_read_register() call because it needs
365 * transition to IDLE state before data retrieving. */
366 scan
.check_mask
= NULL
;
367 scan
.check_value
= NULL
;
369 scan
.out_value
= CMD_XSC_READ
;
370 scan
.in_value
= NULL
;
371 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
373 scan
.num_bits
= 8 * count
;
374 scan
.out_value
= NULL
;
375 scan
.in_value
= buffer
;
376 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IDLE
);
378 jtag_execute_queue();
381 static int isc_set_data_done(struct flash_bank
*bank
, int sector
)
384 done
&= ~(1 << sector
);
385 return isc_program_register(bank
, CMD_XSC_DATA_DONE
, &done
, 8, 100);
388 static void flip_u8(uint8_t *out
, const uint8_t *in
, int len
)
390 for (int i
= 0; i
< len
; i
++)
391 out
[i
] = flip_u32(in
[i
], 8);
395 * Xilinx bin file contains simple fixed header for automatic bus width detection:
397 * 4 byte sync word 0xAA995566 or (bit reversed) 0x5599AA66 in MSC file
399 * Function presumes need of bit reversing if it can not exactly detects
402 static bool need_bit_reverse(const uint8_t *buffer
)
405 uint8_t reference
[L
];
406 memset(reference
, 0xFF, 16);
407 reference
[16] = 0x55;
408 reference
[17] = 0x99;
409 reference
[18] = 0xAA;
410 reference
[19] = 0x66;
412 if (0 == memcmp(reference
, buffer
, L
))
419 * The page address to be programmed is determined by loading the
420 * internal ADDRESS Register using an ISC_ADDRESS_SHIFT instruction sequence.
421 * The page address automatically increments to the next 256-bit
422 * page address after each programming sequence until the last address
423 * in the 8 Mb block is reached. To continue programming the next block,
424 * the next 8 Mb block's starting address must be loaded into the
425 * internal ADDRESS register.
427 static int read_write_data(struct flash_bank
*bank
, const uint8_t *w_buffer
,
428 uint8_t *r_buffer
, bool write_flag
, uint32_t offset
, uint32_t count
)
430 int dbg_count
= count
;
433 uint8_t *page_buf
= malloc(XCF_PAGE_SIZE
);
437 if (offset
% XCF_PAGE_SIZE
!= 0) {
438 ret
= ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
442 if ((offset
+ count
) > (bank
->num_sectors
* XCF_DATA_SECTOR_SIZE
)) {
443 ret
= ERROR_FLASH_DST_OUT_OF_BANK
;
447 if ((write_flag
) && (0 == offset
) && (count
>= XCF_PAGE_SIZE
))
448 revbit
= need_bit_reverse(w_buffer
);
451 uint32_t sector_num
= offset
/ XCF_DATA_SECTOR_SIZE
;
452 uint32_t sector_offset
= offset
- sector_num
* XCF_DATA_SECTOR_SIZE
;
453 uint32_t sector_bytes
= XCF_DATA_SECTOR_SIZE
- sector_offset
;
454 if (count
< sector_bytes
)
455 sector_bytes
= count
;
456 isc_adr_shift(bank
, offset
);
457 offset
+= sector_bytes
;
458 count
-= sector_bytes
;
461 while (sector_bytes
> 0) {
464 if (sector_bytes
< XCF_PAGE_SIZE
) {
466 memset(page_buf
, 0xFF, XCF_PAGE_SIZE
);
471 flip_u8(page_buf
, w_buffer
, len
);
473 memcpy(page_buf
, w_buffer
, len
);
477 ret
= isc_program_data_page(bank
, page_buf
);
481 LOG_DEBUG("written %d bytes from %d", dbg_written
, dbg_count
);
486 isc_data_read_out(bank
, r_buffer
, sector_bytes
);
487 flip_u8(r_buffer
, r_buffer
, sector_bytes
);
488 r_buffer
+= sector_bytes
;
492 /* Set 'done' flags for all data sectors because driver supports
493 * only single revision. */
495 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
496 ret
= isc_set_data_done(bank
, i
);
508 static uint16_t isc_read_ccb(struct flash_bank
*bank
)
511 isc_read_register(bank
, CMD_XSC_DATA_CCB
, ccb
, 16);
512 return le_to_h_u16(ccb
);
515 static unsigned int gucr_num(const struct flash_bank
*bank
)
517 return bank
->num_sectors
;
520 static unsigned int sucr_num(const struct flash_bank
*bank
)
522 return bank
->num_sectors
+ 1;
525 static int isc_program_ccb(struct flash_bank
*bank
, uint16_t ccb
)
528 h_u16_to_le(buf
, ccb
);
529 return isc_program_register(bank
, CMD_XSC_DATA_CCB
, buf
, 16, 100);
532 static int isc_program_singe_revision_sucr(struct flash_bank
*bank
)
534 uint8_t sucr
[2] = {0xFC, 0xFF};
535 return isc_program_register(bank
, CMD_XSC_DATA_SUCR
, sucr
, 16, 100);
538 static int isc_program_single_revision_btc(struct flash_bank
*bank
)
541 uint32_t btc
= 0xFFFFFFFF;
543 btc
|= ((bank
->num_sectors
- 1) << 2);
545 h_u32_to_le(buf
, btc
);
546 return isc_program_register(bank
, CMD_XSC_DATA_BTC
, buf
, 32, 100);
549 static int fpga_configure(struct flash_bank
*bank
)
551 struct scan_field scan
;
553 scan
.check_mask
= NULL
;
554 scan
.check_value
= NULL
;
556 scan
.out_value
= CMD_XSC_CONFIG
;
557 scan
.in_value
= NULL
;
558 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
559 jtag_execute_queue();
565 ******************************************************************************
567 ******************************************************************************
570 FLASH_BANK_COMMAND_HANDLER(xcf_flash_bank_command
)
572 struct xcf_priv
*priv
;
574 priv
= malloc(sizeof(struct xcf_priv
));
576 LOG_ERROR("no memory for flash bank info");
579 bank
->driver_priv
= priv
;
580 priv
->probed
= false;
584 static int xcf_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
586 const struct xcf_priv
*priv
= bank
->driver_priv
;
588 if (false == priv
->probed
) {
589 snprintf(buf
, buf_size
, "\nXCF flash bank not probed yet\n");
592 snprintf(buf
, buf_size
, "%s", product_name(bank
));
596 static int xcf_probe(struct flash_bank
*bank
)
598 struct xcf_priv
*priv
= bank
->driver_priv
;
601 if (true == priv
->probed
)
603 priv
->probed
= false;
605 if (bank
->target
->tap
== NULL
) {
606 LOG_ERROR("Target has no JTAG tap");
610 /* check idcode and alloc memory for sector table */
611 if (!bank
->target
->tap
->hasidcode
)
612 return ERROR_FLASH_OPERATION_FAILED
;
614 /* guess number of blocks using chip ID */
615 id
= bank
->target
->tap
->idcode
;
616 switch (id
& ID_MEANINGFUL_MASK
) {
618 bank
->num_sectors
= 1;
621 bank
->num_sectors
= 2;
624 bank
->num_sectors
= 4;
627 LOG_ERROR("Unknown flash device ID 0x%" PRIX32
, id
);
631 bank
->sectors
= malloc(bank
->num_sectors
* sizeof(struct flash_sector
));
632 if (NULL
== bank
->sectors
) {
633 LOG_ERROR("No memory for sector table");
636 fill_sector_table(bank
);
639 /* REVISIT: Why is unchanged bank->driver_priv rewritten by same value? */
640 bank
->driver_priv
= priv
;
642 LOG_INFO("product name: %s", product_name(bank
));
643 LOG_INFO("device id = 0x%" PRIX32
, bank
->target
->tap
->idcode
);
644 LOG_INFO("flash size = %d configuration bits",
645 bank
->num_sectors
* XCF_DATA_SECTOR_SIZE
* 8);
646 LOG_INFO("number of sectors = %u", bank
->num_sectors
);
651 static int xcf_auto_probe(struct flash_bank
*bank
)
653 struct xcf_priv
*priv
= bank
->driver_priv
;
655 if (true == priv
->probed
)
658 return xcf_probe(bank
);
661 static int xcf_protect_check(struct flash_bank
*bank
)
666 isc_read_register(bank
, CMD_XSC_DATA_WRPT
, wrpt
, 16);
669 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
670 bank
->sectors
[i
].is_protected
= sector_state(wrpt
[0], i
);
675 static int xcf_erase_check(struct flash_bank
*bank
)
678 struct scan_field scan
;
682 /* Do not change this code with isc_read_register() call because it needs
683 * transition to IDLE state and pause before data retrieving. */
684 scan
.check_mask
= NULL
;
685 scan
.check_value
= NULL
;
687 scan
.out_value
= CMD_XSC_BLANK_CHECK
;
688 scan
.in_value
= NULL
;
689 jtag_add_ir_scan(bank
->target
->tap
, &scan
, TAP_IDLE
);
690 jtag_execute_queue();
691 alive_sleep(500); /* device needs at least 0.5s to self check */
694 scan
.in_value
= &blankreg
;
695 jtag_add_dr_scan(bank
->target
->tap
, 1, &scan
, TAP_IDLE
);
696 jtag_execute_queue();
700 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
701 bank
->sectors
[i
].is_erased
= sector_state(blankreg
, i
);
706 static int xcf_erase(struct flash_bank
*bank
, unsigned int first
,
709 if ((first
>= bank
->num_sectors
)
710 || (last
>= bank
->num_sectors
)
712 return ERROR_FLASH_SECTOR_INVALID
;
715 isc_clear_protect(bank
, first
, last
);
716 int ret
= isc_erase_sectors(bank
, first
, last
);
722 static int xcf_read(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
724 return read_write_data(bank
, NULL
, buffer
, false, offset
, count
);
727 static int xcf_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
,
730 return read_write_data(bank
, buffer
, NULL
, true, offset
, count
);
733 static int xcf_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
740 ret
= isc_set_protect(bank
, first
, last
);
742 /* write protection may be removed only with following erase */
743 isc_clear_protect(bank
, first
, last
);
744 ret
= isc_erase_sectors(bank
, first
, last
);
751 COMMAND_HANDLER(xcf_handle_ccb_command
) {
753 if (!((CMD_ARGC
== 1) || (CMD_ARGC
== 5)))
754 return ERROR_COMMAND_SYNTAX_ERROR
;
756 struct flash_bank
*bank
;
757 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
758 if (ERROR_OK
!= retval
)
761 uint16_t ccb
= 0xFFFF;
763 uint16_t old_ccb
= isc_read_ccb(bank
);
767 LOG_INFO("current CCB = 0x%X", old_ccb
);
770 /* skip over flash bank */
774 if (strcmp("external", CMD_ARGV
[0]) == 0)
776 else if (strcmp("internal", CMD_ARGV
[0]) == 0)
778 else if (strcmp("serial", CMD_ARGV
[0]) == 0)
780 else if (strcmp("parallel", CMD_ARGV
[0]) == 0)
782 else if (strcmp("slave", CMD_ARGV
[0]) == 0)
784 else if (strcmp("master", CMD_ARGV
[0]) == 0)
786 else if (strcmp("40", CMD_ARGV
[0]) == 0)
788 else if (strcmp("20", CMD_ARGV
[0]) == 0)
791 return ERROR_COMMAND_SYNTAX_ERROR
;
800 sector
= gucr_num(bank
);
801 isc_clear_protect(bank
, sector
, sector
);
802 int ret
= isc_erase_sectors(bank
, sector
, sector
);
805 ret
= isc_program_ccb(bank
, ccb
);
808 ret
= isc_program_single_revision_btc(bank
);
811 ret
= isc_set_data_done(bank
, sector
);
816 sector
= sucr_num(bank
);
817 isc_clear_protect(bank
, sector
, sector
);
818 ret
= isc_erase_sectors(bank
, sector
, sector
);
821 ret
= isc_program_singe_revision_sucr(bank
);
824 ret
= isc_set_data_done(bank
, sector
);
834 COMMAND_HANDLER(xcf_handle_configure_command
) {
837 return ERROR_COMMAND_SYNTAX_ERROR
;
839 struct flash_bank
*bank
;
840 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
841 if (ERROR_OK
!= retval
)
844 return fpga_configure(bank
);
847 static const struct command_registration xcf_exec_command_handlers
[] = {
850 .handler
= xcf_handle_configure_command
,
851 .mode
= COMMAND_EXEC
,
853 .help
= "Initiate FPGA loading procedure."
857 .handler
= xcf_handle_ccb_command
,
858 .mode
= COMMAND_EXEC
,
859 .usage
= "bank_id [('external'|'internal') "
860 "('serial'|'parallel') "
861 "('slave'|'master') "
863 .help
= "Write CCB register with supplied options and (silently) BTC "
864 "register with single revision options. Display current "
865 "CCB value when only bank_id supplied. "
866 "Following options available: "
867 "1) external or internal clock source; "
868 "2) serial or parallel bus mode; "
869 "3) slave or master mode; "
870 "4) clock frequency in MHz for internal clock in master mode;"
872 COMMAND_REGISTRATION_DONE
875 static const struct command_registration xcf_command_handlers
[] = {
879 .help
= "Xilinx platform flash command group",
881 .chain
= xcf_exec_command_handlers
883 COMMAND_REGISTRATION_DONE
886 const struct flash_driver xcf_flash
= {
889 .commands
= xcf_command_handlers
,
890 .flash_bank_command
= xcf_flash_bank_command
,
892 .protect
= xcf_protect
,
896 .auto_probe
= xcf_auto_probe
,
897 .erase_check
= xcf_erase_check
,
898 .protect_check
= xcf_protect_check
,
900 .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)