1 /***************************************************************************
\r
2 * Copyright (C) 2005 by Dominic Rath *
\r
3 * Dominic.Rath@gmx.de *
\r
5 * This program is free software; you can redistribute it and/or modify *
\r
6 * it under the terms of the GNU General Public License as published by *
\r
7 * the Free Software Foundation; either version 2 of the License, or *
\r
8 * (at your option) any later version. *
\r
10 * This program is distributed in the hope that it will be useful, *
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
\r
13 * GNU General Public License for more details. *
\r
15 * You should have received a copy of the GNU General Public License *
\r
16 * along with this program; if not, write to the *
\r
17 * Free Software Foundation, Inc., *
\r
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
\r
19 ***************************************************************************/
\r
20 #ifdef HAVE_CONFIG_H
\r
24 #include "replacements.h"
\r
26 #include "str9xpec.h"
\r
30 #include "armv4_5.h"
\r
31 #include "arm7_9_common.h"
\r
33 #include "binarybuffer.h"
\r
40 str9xpec_mem_layout_t mem_layout_str9pec[] = {
\r
41 {0x00000000, 0x10000, 0},
\r
42 {0x00010000, 0x10000, 1},
\r
43 {0x00020000, 0x10000, 2},
\r
44 {0x00030000, 0x10000, 3},
\r
45 {0x00040000, 0x10000, 4},
\r
46 {0x00050000, 0x10000, 5},
\r
47 {0x00060000, 0x10000, 6},
\r
48 {0x00070000, 0x10000, 7},
\r
49 {0x00080000, 0x02000, 32},
\r
50 {0x00082000, 0x02000, 33},
\r
51 {0x00084000, 0x02000, 34},
\r
52 {0x00086000, 0x02000, 35}
\r
55 int str9xpec_register_commands(struct command_context_s *cmd_ctx);
\r
56 int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
\r
57 int str9xpec_erase(struct flash_bank_s *bank, int first, int last);
\r
58 int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last);
\r
59 int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
\r
60 int str9xpec_probe(struct flash_bank_s *bank);
\r
61 int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
62 int str9xpec_protect_check(struct flash_bank_s *bank);
\r
63 int str9xpec_erase_check(struct flash_bank_s *bank);
\r
64 int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size);
\r
66 int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last);
\r
67 int str9xpec_set_address(struct flash_bank_s *bank, u8 sector);
\r
68 int str9xpec_write_options(struct flash_bank_s *bank);
\r
70 int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
71 int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
72 int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
73 int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
74 int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
75 int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
76 int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
77 int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
78 int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
79 int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
81 flash_driver_t str9xpec_flash =
\r
84 .register_commands = str9xpec_register_commands,
\r
85 .flash_bank_command = str9xpec_flash_bank_command,
\r
86 .erase = str9xpec_erase,
\r
87 .protect = str9xpec_protect,
\r
88 .write = str9xpec_write,
\r
89 .probe = str9xpec_probe,
\r
90 .auto_probe = str9xpec_probe,
\r
91 .erase_check = str9xpec_erase_check,
\r
92 .protect_check = str9xpec_protect_check,
\r
93 .info = str9xpec_info
\r
96 int str9xpec_register_commands(struct command_context_s *cmd_ctx)
\r
98 command_t *str9xpec_cmd = register_command(cmd_ctx, NULL, "str9xpec", NULL, COMMAND_ANY, "str9xpec flash specific commands");
\r
100 register_command(cmd_ctx, str9xpec_cmd, "enable_turbo", str9xpec_handle_flash_enable_turbo_command, COMMAND_EXEC,
\r
101 "enable str9xpec turbo mode");
\r
102 register_command(cmd_ctx, str9xpec_cmd, "disable_turbo", str9xpec_handle_flash_disable_turbo_command, COMMAND_EXEC,
\r
103 "disable str9xpec turbo mode");
\r
104 register_command(cmd_ctx, str9xpec_cmd, "options_cmap", str9xpec_handle_flash_options_cmap_command, COMMAND_EXEC,
\r
105 "configure str9xpec boot sector");
\r
106 register_command(cmd_ctx, str9xpec_cmd, "options_lvdthd", str9xpec_handle_flash_options_lvdthd_command, COMMAND_EXEC,
\r
107 "configure str9xpec lvd threshold");
\r
108 register_command(cmd_ctx, str9xpec_cmd, "options_lvdsel", str9xpec_handle_flash_options_lvdsel_command, COMMAND_EXEC,
\r
109 "configure str9xpec lvd selection");
\r
110 register_command(cmd_ctx, str9xpec_cmd, "options_lvdwarn", str9xpec_handle_flash_options_lvdwarn_command, COMMAND_EXEC,
\r
111 "configure str9xpec lvd warning");
\r
112 register_command(cmd_ctx, str9xpec_cmd, "options_read", str9xpec_handle_flash_options_read_command, COMMAND_EXEC,
\r
113 "read str9xpec options");
\r
114 register_command(cmd_ctx, str9xpec_cmd, "options_write", str9xpec_handle_flash_options_write_command, COMMAND_EXEC,
\r
115 "write str9xpec options");
\r
116 register_command(cmd_ctx, str9xpec_cmd, "lock", str9xpec_handle_flash_lock_command, COMMAND_EXEC,
\r
117 "lock str9xpec device");
\r
118 register_command(cmd_ctx, str9xpec_cmd, "unlock", str9xpec_handle_flash_unlock_command, COMMAND_EXEC,
\r
119 "unlock str9xpec device");
\r
120 register_command(cmd_ctx, str9xpec_cmd, "part_id", str9xpec_handle_part_id_command, COMMAND_EXEC,
\r
121 "print part id of str9xpec flash bank <num>");
\r
126 int str9xpec_set_instr(int chain_pos, u32 new_instr, enum tap_state end_state)
\r
128 jtag_device_t *device = jtag_get_device(chain_pos);
\r
130 if (device == NULL)
\r
132 DEBUG("Invalid Target");
\r
133 return ERROR_TARGET_INVALID;
\r
136 if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
\r
138 scan_field_t field;
\r
140 field.device = chain_pos;
\r
141 field.num_bits = device->ir_length;
\r
142 field.out_value = calloc(CEIL(field.num_bits, 8), 1);
\r
143 buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
\r
144 field.out_mask = NULL;
\r
145 field.in_value = NULL;
\r
146 field.in_check_value = NULL;
\r
147 field.in_check_mask = NULL;
\r
148 field.in_handler = NULL;
\r
149 field.in_handler_priv = NULL;
\r
151 jtag_add_ir_scan(1, &field, end_state);
\r
153 free(field.out_value);
\r
159 u8 str9xpec_isc_status(int chain_pos)
\r
161 scan_field_t field;
\r
164 if (str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI) != ERROR_OK)
\r
165 return ISC_STATUS_ERROR;
\r
167 field.device = chain_pos;
\r
168 field.num_bits = 8;
\r
169 field.out_value = NULL;
\r
170 field.out_mask = NULL;
\r
171 field.in_value = &status;
\r
172 field.in_check_value = NULL;
\r
173 field.in_check_mask = NULL;
\r
174 field.in_handler = NULL;
\r
175 field.in_handler_priv = NULL;
\r
177 jtag_add_dr_scan(1, &field, TAP_RTI);
\r
178 jtag_execute_queue();
\r
180 DEBUG("status: 0x%2.2x", status);
\r
182 if (status & ISC_STATUS_SECURITY)
\r
183 INFO("Device Security Bit Set");
\r
188 int str9xpec_isc_enable(struct flash_bank_s *bank)
\r
192 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
194 chain_pos = str9xpec_info->chain_pos;
\r
196 if (str9xpec_info->isc_enable)
\r
199 /* enter isc mode */
\r
200 if (str9xpec_set_instr(chain_pos, ISC_ENABLE, TAP_RTI) != ERROR_OK)
\r
201 return ERROR_TARGET_INVALID;
\r
203 /* check ISC status */
\r
204 status = str9xpec_isc_status(chain_pos);
\r
205 if (status & ISC_STATUS_MODE)
\r
207 /* we have entered isc mode */
\r
208 str9xpec_info->isc_enable = 1;
\r
209 DEBUG("ISC_MODE Enabled");
\r
215 int str9xpec_isc_disable(struct flash_bank_s *bank)
\r
219 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
221 chain_pos = str9xpec_info->chain_pos;
\r
223 if (!str9xpec_info->isc_enable)
\r
226 if (str9xpec_set_instr(chain_pos, ISC_DISABLE, TAP_RTI) != ERROR_OK)
\r
227 return ERROR_TARGET_INVALID;
\r
229 /* delay to handle aborts */
\r
230 jtag_add_sleep(50);
\r
232 /* check ISC status */
\r
233 status = str9xpec_isc_status(chain_pos);
\r
234 if (!(status & ISC_STATUS_MODE))
\r
236 /* we have left isc mode */
\r
237 str9xpec_info->isc_enable = 0;
\r
238 DEBUG("ISC_MODE Disabled");
\r
244 int str9xpec_read_config(struct flash_bank_s *bank)
\r
246 scan_field_t field;
\r
250 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
252 chain_pos = str9xpec_info->chain_pos;
\r
254 DEBUG("ISC_CONFIGURATION");
\r
256 /* execute ISC_CONFIGURATION command */
\r
257 str9xpec_set_instr(chain_pos, ISC_CONFIGURATION, TAP_PI);
\r
259 field.device = chain_pos;
\r
260 field.num_bits = 64;
\r
261 field.out_value = NULL;
\r
262 field.out_mask = NULL;
\r
263 field.in_value = str9xpec_info->options;
\r
264 field.in_check_value = NULL;
\r
265 field.in_check_mask = NULL;
\r
266 field.in_handler = NULL;
\r
267 field.in_handler_priv = NULL;
\r
269 jtag_add_dr_scan(1, &field, TAP_RTI);
\r
270 jtag_execute_queue();
\r
272 status = str9xpec_isc_status(chain_pos);
\r
277 int str9xpec_build_block_list(struct flash_bank_s *bank)
\r
279 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
282 int num_sectors = 0, b0_sectors = 0;
\r
284 switch (bank->size)
\r
293 ERROR("BUG: unknown bank->size encountered");
\r
297 /* include bank 1 sectors */
\r
298 num_sectors = b0_sectors + 4;
\r
299 bank->size += (32 * 1024);
\r
301 bank->num_sectors = num_sectors;
\r
302 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
\r
303 str9xpec_info->sector_bits = malloc(sizeof(u32) * num_sectors);
\r
307 for (i = 0; i < b0_sectors; i++)
\r
309 bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
\r
310 bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
\r
311 bank->sectors[num_sectors].is_erased = -1;
\r
312 bank->sectors[num_sectors].is_protected = 1;
\r
313 str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
\r
316 for (i = 8; i < 12; i++)
\r
318 bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
\r
319 bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
\r
320 bank->sectors[num_sectors].is_erased = -1;
\r
321 bank->sectors[num_sectors].is_protected = 1;
\r
322 str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
\r
328 /* flash bank str9x <base> <size> 0 0 <target#>
\r
330 int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
\r
332 str9xpec_flash_controller_t *str9xpec_info;
\r
333 armv4_5_common_t *armv4_5 = NULL;
\r
334 arm7_9_common_t *arm7_9 = NULL;
\r
335 arm_jtag_t *jtag_info = NULL;
\r
339 WARNING("incomplete flash_bank str9x configuration");
\r
340 return ERROR_FLASH_BANK_INVALID;
\r
343 str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));
\r
344 bank->driver_priv = str9xpec_info;
\r
346 if (bank->base != 0x00000000)
\r
348 WARNING("overriding flash base address for STR91x device with 0x00000000");
\r
349 bank->base = 0x00000000;
\r
352 /* find out jtag position of flash controller
\r
353 * it is always after the arm966 core */
\r
355 armv4_5 = bank->target->arch_info;
\r
356 arm7_9 = armv4_5->arch_info;
\r
357 jtag_info = &arm7_9->jtag_info;
\r
359 str9xpec_info->chain_pos = (jtag_info->chain_pos - 1);
\r
360 str9xpec_info->isc_enable = 0;
\r
361 str9xpec_info->devarm = NULL;
\r
363 str9xpec_build_block_list(bank);
\r
365 /* clear option byte register */
\r
366 buf_set_u32(str9xpec_info->options, 0, 64, 0);
\r
371 int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)
\r
373 scan_field_t field;
\r
379 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
381 chain_pos = str9xpec_info->chain_pos;
\r
383 if (!str9xpec_info->isc_enable) {
\r
384 str9xpec_isc_enable( bank );
\r
387 if (!str9xpec_info->isc_enable) {
\r
388 return ERROR_FLASH_OPERATION_FAILED;
\r
391 buffer = calloc(CEIL(64, 8), 1);
\r
393 DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
\r
395 for (i = first; i <= last; i++) {
\r
396 buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
\r
399 /* execute ISC_BLANK_CHECK command */
\r
400 str9xpec_set_instr(chain_pos, ISC_BLANK_CHECK, TAP_PI);
\r
402 field.device = chain_pos;
\r
403 field.num_bits = 64;
\r
404 field.out_value = buffer;
\r
405 field.out_mask = NULL;
\r
406 field.in_value = NULL;
\r
407 field.in_check_value = NULL;
\r
408 field.in_check_mask = NULL;
\r
409 field.in_handler = NULL;
\r
410 field.in_handler_priv = NULL;
\r
412 jtag_add_dr_scan(1, &field, TAP_RTI);
\r
413 jtag_add_sleep(40000);
\r
415 /* read blank check result */
\r
416 field.device = chain_pos;
\r
417 field.num_bits = 64;
\r
418 field.out_value = NULL;
\r
419 field.out_mask = NULL;
\r
420 field.in_value = buffer;
\r
421 field.in_check_value = NULL;
\r
422 field.in_check_mask = NULL;
\r
423 field.in_handler = NULL;
\r
424 field.in_handler_priv = NULL;
\r
426 jtag_add_dr_scan(1, &field, TAP_PI);
\r
427 jtag_execute_queue();
\r
429 status = str9xpec_isc_status(chain_pos);
\r
431 for (i = first; i <= last; i++)
\r
433 if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
\r
434 bank->sectors[i].is_erased = 0;
\r
436 bank->sectors[i].is_erased = 1;
\r
441 str9xpec_isc_disable(bank);
\r
443 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
444 return ERROR_FLASH_OPERATION_FAILED;
\r
448 int str9xpec_protect_check(struct flash_bank_s *bank)
\r
453 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
455 status = str9xpec_read_config(bank);
\r
457 for (i = 0; i < bank->num_sectors; i++)
\r
459 if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
\r
460 bank->sectors[i].is_protected = 1;
\r
462 bank->sectors[i].is_protected = 0;
\r
465 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
466 return ERROR_FLASH_OPERATION_FAILED;
\r
470 int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)
\r
472 scan_field_t field;
\r
478 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
480 chain_pos = str9xpec_info->chain_pos;
\r
482 if (!str9xpec_info->isc_enable) {
\r
483 str9xpec_isc_enable( bank );
\r
486 if (!str9xpec_info->isc_enable) {
\r
487 return ISC_STATUS_ERROR;
\r
490 buffer = calloc(CEIL(64, 8), 1);
\r
492 DEBUG("erase: first_bank: %i, last_bank: %i", first, last);
\r
494 /* last bank: 0xFF signals a full erase (unlock complete device) */
\r
495 /* last bank: 0xFE signals a option byte erase */
\r
498 for (i = 0; i < 64; i++) {
\r
499 buf_set_u32(buffer, i, 1, 1);
\r
502 else if (last == 0xFE)
\r
504 buf_set_u32(buffer, 49, 1, 1);
\r
508 for (i = first; i <= last; i++) {
\r
509 buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
\r
513 DEBUG("ISC_ERASE");
\r
515 /* execute ISC_ERASE command */
\r
516 str9xpec_set_instr(chain_pos, ISC_ERASE, TAP_PI);
\r
518 field.device = chain_pos;
\r
519 field.num_bits = 64;
\r
520 field.out_value = buffer;
\r
521 field.out_mask = NULL;
\r
522 field.in_value = NULL;
\r
523 field.in_check_value = NULL;
\r
524 field.in_check_mask = NULL;
\r
525 field.in_handler = NULL;
\r
526 field.in_handler_priv = NULL;
\r
528 jtag_add_dr_scan(1, &field, TAP_RTI);
\r
529 jtag_execute_queue();
\r
531 jtag_add_sleep(10);
\r
533 /* wait for erase completion */
\r
534 while (!((status = str9xpec_isc_status(chain_pos)) & ISC_STATUS_BUSY)) {
\r
540 str9xpec_isc_disable(bank);
\r
545 int str9xpec_erase(struct flash_bank_s *bank, int first, int last)
\r
549 status = str9xpec_erase_area(bank, first, last);
\r
551 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
552 return ERROR_FLASH_OPERATION_FAILED;
\r
557 int str9xpec_lock_device(struct flash_bank_s *bank)
\r
559 scan_field_t field;
\r
562 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
564 str9xpec_info = bank->driver_priv;
\r
565 chain_pos = str9xpec_info->chain_pos;
\r
567 if (!str9xpec_info->isc_enable) {
\r
568 str9xpec_isc_enable( bank );
\r
571 if (!str9xpec_info->isc_enable) {
\r
572 return ISC_STATUS_ERROR;
\r
575 /* set security address */
\r
576 str9xpec_set_address(bank, 0x80);
\r
578 /* execute ISC_PROGRAM command */
\r
579 str9xpec_set_instr(chain_pos, ISC_PROGRAM_SECURITY, TAP_RTI);
\r
581 str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
\r
584 field.device = chain_pos;
\r
585 field.num_bits = 8;
\r
586 field.out_value = NULL;
\r
587 field.out_mask = NULL;
\r
588 field.in_value = &status;
\r
589 field.in_check_value = NULL;
\r
590 field.in_check_mask = NULL;
\r
591 field.in_handler = NULL;
\r
592 field.in_handler_priv = NULL;
\r
594 jtag_add_dr_scan(1, &field, -1);
\r
595 jtag_execute_queue();
\r
597 } while(!(status & ISC_STATUS_BUSY));
\r
599 str9xpec_isc_disable(bank);
\r
604 int str9xpec_unlock_device(struct flash_bank_s *bank)
\r
608 status = str9xpec_erase_area(bank, 0, 255);
\r
613 int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)
\r
618 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
620 status = str9xpec_read_config(bank);
\r
622 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
623 return ERROR_FLASH_OPERATION_FAILED;
\r
625 DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
\r
627 /* last bank: 0xFF signals a full device protect */
\r
632 status = str9xpec_lock_device(bank);
\r
636 /* perform full erase to unlock device */
\r
637 status = str9xpec_unlock_device(bank);
\r
642 for (i = first; i <= last; i++)
\r
645 buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
\r
647 buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);
\r
650 status = str9xpec_write_options(bank);
\r
653 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
654 return ERROR_FLASH_OPERATION_FAILED;
\r
659 int str9xpec_set_address(struct flash_bank_s *bank, u8 sector)
\r
662 scan_field_t field;
\r
663 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
665 chain_pos = str9xpec_info->chain_pos;
\r
667 /* set flash controller address */
\r
668 str9xpec_set_instr(chain_pos, ISC_ADDRESS_SHIFT, TAP_PI);
\r
670 field.device = chain_pos;
\r
671 field.num_bits = 8;
\r
672 field.out_value = §or;
\r
673 field.out_mask = NULL;
\r
674 field.in_value = NULL;
\r
675 field.in_check_value = NULL;
\r
676 field.in_check_mask = NULL;
\r
677 field.in_handler = NULL;
\r
678 field.in_handler_priv = NULL;
\r
680 jtag_add_dr_scan(1, &field, -1);
\r
685 int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
\r
687 str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
\r
688 u32 dwords_remaining = (count / 8);
\r
689 u32 bytes_remaining = (count & 0x00000007);
\r
690 u32 bytes_written = 0;
\r
692 u32 check_address = offset;
\r
694 scan_field_t field;
\r
697 u32 first_sector = 0;
\r
698 u32 last_sector = 0;
\r
700 chain_pos = str9xpec_info->chain_pos;
\r
702 if (!str9xpec_info->isc_enable) {
\r
703 str9xpec_isc_enable(bank);
\r
706 if (!str9xpec_info->isc_enable) {
\r
707 return ERROR_FLASH_OPERATION_FAILED;
\r
712 WARNING("offset 0x%x breaks required 8-byte alignment", offset);
\r
713 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
\r
716 for (i = 0; i < bank->num_sectors; i++)
\r
718 u32 sec_start = bank->sectors[i].offset;
\r
719 u32 sec_end = sec_start + bank->sectors[i].size;
\r
721 /* check if destination falls within the current sector */
\r
722 if ((check_address >= sec_start) && (check_address < sec_end))
\r
724 /* check if destination ends in the current sector */
\r
725 if (offset + count < sec_end)
\r
726 check_address = offset + count;
\r
728 check_address = sec_end;
\r
731 if ((offset >= sec_start) && (offset < sec_end)){
\r
735 if ((offset + count >= sec_start) && (offset + count < sec_end)){
\r
740 if (check_address != offset + count)
\r
741 return ERROR_FLASH_DST_OUT_OF_BANK;
\r
743 DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
\r
745 scanbuf = calloc(CEIL(64, 8), 1);
\r
747 DEBUG("ISC_PROGRAM");
\r
749 for (i = first_sector; i <= last_sector; i++)
\r
751 str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
\r
753 dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);
\r
755 while (dwords_remaining > 0)
\r
757 str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
\r
759 field.device = chain_pos;
\r
760 field.num_bits = 64;
\r
761 field.out_value = (buffer + bytes_written);
\r
762 field.out_mask = NULL;
\r
763 field.in_value = NULL;
\r
764 field.in_check_value = NULL;
\r
765 field.in_check_mask = NULL;
\r
766 field.in_handler = NULL;
\r
767 field.in_handler_priv = NULL;
\r
769 jtag_add_dr_scan(1, &field, TAP_RTI);
\r
771 /* small delay before polling */
\r
772 jtag_add_sleep(50);
\r
774 str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
\r
777 field.device = chain_pos;
\r
778 field.num_bits = 8;
\r
779 field.out_value = NULL;
\r
780 field.out_mask = NULL;
\r
781 field.in_value = scanbuf;
\r
782 field.in_check_value = NULL;
\r
783 field.in_check_mask = NULL;
\r
784 field.in_handler = NULL;
\r
785 field.in_handler_priv = NULL;
\r
787 jtag_add_dr_scan(1, &field, -1);
\r
788 jtag_execute_queue();
\r
790 status = buf_get_u32(scanbuf, 0, 8);
\r
792 } while(!(status & ISC_STATUS_BUSY));
\r
794 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
795 return ERROR_FLASH_OPERATION_FAILED;
\r
797 //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
\r
798 // return ERROR_FLASH_OPERATION_FAILED;
\r
800 dwords_remaining--;
\r
801 bytes_written += 8;
\r
805 if (bytes_remaining)
\r
807 u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
\r
810 while(bytes_remaining > 0)
\r
812 last_dword[i++] = *(buffer + bytes_written);
\r
817 str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
\r
819 field.device = chain_pos;
\r
820 field.num_bits = 64;
\r
821 field.out_value = last_dword;
\r
822 field.out_mask = NULL;
\r
823 field.in_value = NULL;
\r
824 field.in_check_value = NULL;
\r
825 field.in_check_mask = NULL;
\r
826 field.in_handler = NULL;
\r
827 field.in_handler_priv = NULL;
\r
829 jtag_add_dr_scan(1, &field, TAP_RTI);
\r
831 /* small delay before polling */
\r
832 jtag_add_sleep(50);
\r
834 str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
\r
837 field.device = chain_pos;
\r
838 field.num_bits = 8;
\r
839 field.out_value = NULL;
\r
840 field.out_mask = NULL;
\r
841 field.in_value = scanbuf;
\r
842 field.in_check_value = NULL;
\r
843 field.in_check_mask = NULL;
\r
844 field.in_handler = NULL;
\r
845 field.in_handler_priv = NULL;
\r
847 jtag_add_dr_scan(1, &field, -1);
\r
848 jtag_execute_queue();
\r
850 status = buf_get_u32(scanbuf, 0, 8);
\r
852 } while(!(status & ISC_STATUS_BUSY));
\r
854 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
855 return ERROR_FLASH_OPERATION_FAILED;
\r
857 //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
\r
858 // return ERROR_FLASH_OPERATION_FAILED;
\r
863 str9xpec_isc_disable(bank);
\r
868 int str9xpec_probe(struct flash_bank_s *bank)
\r
873 int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
875 flash_bank_t *bank;
\r
876 scan_field_t field;
\r
880 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
884 return ERROR_COMMAND_SYNTAX_ERROR;
\r
887 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
890 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
894 str9xpec_info = bank->driver_priv;
\r
895 chain_pos = str9xpec_info->chain_pos;
\r
897 buffer = calloc(CEIL(32, 8), 1);
\r
899 str9xpec_set_instr(chain_pos, ISC_IDCODE, TAP_PI);
\r
901 field.device = chain_pos;
\r
902 field.num_bits = 32;
\r
903 field.out_value = NULL;
\r
904 field.out_mask = NULL;
\r
905 field.in_value = buffer;
\r
906 field.in_check_value = NULL;
\r
907 field.in_check_mask = NULL;
\r
908 field.in_handler = NULL;
\r
909 field.in_handler_priv = NULL;
\r
911 jtag_add_dr_scan(1, &field, TAP_RTI);
\r
912 jtag_execute_queue();
\r
914 idcode = buf_get_u32(buffer, 0, 32);
\r
916 command_print(cmd_ctx, "str9xpec part id: 0x%8.8x", idcode);
\r
923 int str9xpec_erase_check(struct flash_bank_s *bank)
\r
925 return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
\r
928 int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)
\r
930 snprintf(buf, buf_size, "str9xpec flash driver info" );
\r
934 int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
936 flash_bank_t *bank;
\r
938 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
942 command_print(cmd_ctx, "str9xpec options_read <bank>");
\r
946 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
949 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
953 str9xpec_info = bank->driver_priv;
\r
955 status = str9xpec_read_config(bank);
\r
957 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
958 return ERROR_FLASH_OPERATION_FAILED;
\r
961 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))
\r
962 command_print(cmd_ctx, "CS Map: bank1");
\r
964 command_print(cmd_ctx, "CS Map: bank0");
\r
967 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))
\r
968 command_print(cmd_ctx, "OTP Lock: OTP Locked");
\r
970 command_print(cmd_ctx, "OTP Lock: OTP Unlocked");
\r
972 /* LVD Threshold */
\r
973 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))
\r
974 command_print(cmd_ctx, "LVD Threshold: 2.7v");
\r
976 command_print(cmd_ctx, "LVD Threshold: 2.4v");
\r
978 /* LVD reset warning */
\r
979 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))
\r
980 command_print(cmd_ctx, "LVD Reset Warning: VDD or VDDQ Inputs");
\r
982 command_print(cmd_ctx, "LVD Reset Warning: VDD Input Only");
\r
984 /* LVD reset select */
\r
985 if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))
\r
986 command_print(cmd_ctx, "LVD Reset Selection: VDD or VDDQ Inputs");
\r
988 command_print(cmd_ctx, "LVD Reset Selection: VDD Input Only");
\r
993 int str9xpec_write_options(struct flash_bank_s *bank)
\r
995 scan_field_t field;
\r
998 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
1000 str9xpec_info = bank->driver_priv;
\r
1001 chain_pos = str9xpec_info->chain_pos;
\r
1003 /* erase config options first */
\r
1004 status = str9xpec_erase_area( bank, 0xFE, 0xFE );
\r
1006 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
1009 if (!str9xpec_info->isc_enable) {
\r
1010 str9xpec_isc_enable( bank );
\r
1013 if (!str9xpec_info->isc_enable) {
\r
1014 return ISC_STATUS_ERROR;
\r
1017 /* according to data 64th bit has to be set */
\r
1018 buf_set_u32(str9xpec_info->options, 63, 1, 1);
\r
1020 /* set option byte address */
\r
1021 str9xpec_set_address(bank, 0x50);
\r
1023 /* execute ISC_PROGRAM command */
\r
1024 str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
\r
1026 field.device = chain_pos;
\r
1027 field.num_bits = 64;
\r
1028 field.out_value = str9xpec_info->options;
\r
1029 field.out_mask = NULL;
\r
1030 field.in_value = NULL;
\r
1031 field.in_check_value = NULL;
\r
1032 field.in_check_mask = NULL;
\r
1033 field.in_handler = NULL;
\r
1034 field.in_handler_priv = NULL;
\r
1036 jtag_add_dr_scan(1, &field, TAP_RTI);
\r
1038 /* small delay before polling */
\r
1039 jtag_add_sleep(50);
\r
1041 str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
\r
1044 field.device = chain_pos;
\r
1045 field.num_bits = 8;
\r
1046 field.out_value = NULL;
\r
1047 field.out_mask = NULL;
\r
1048 field.in_value = &status;
\r
1049 field.in_check_value = NULL;
\r
1050 field.in_check_mask = NULL;
\r
1051 field.in_handler = NULL;
\r
1052 field.in_handler_priv = NULL;
\r
1054 jtag_add_dr_scan(1, &field, -1);
\r
1055 jtag_execute_queue();
\r
1057 } while(!(status & ISC_STATUS_BUSY));
\r
1059 str9xpec_isc_disable(bank);
\r
1064 int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1066 flash_bank_t *bank;
\r
1071 command_print(cmd_ctx, "str9xpec options_write <bank>");
\r
1075 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1078 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1082 status = str9xpec_write_options(bank);
\r
1084 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
1085 return ERROR_FLASH_OPERATION_FAILED;
\r
1090 int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1092 flash_bank_t *bank;
\r
1093 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
1097 command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0|bank1>");
\r
1101 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1104 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1108 str9xpec_info = bank->driver_priv;
\r
1110 if (strcmp(args[1], "bank1") == 0)
\r
1112 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
\r
1116 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
\r
1122 int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1124 flash_bank_t *bank;
\r
1125 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
1129 command_print(cmd_ctx, "str9xpec options_lvdthd <bank> <2.4v|2.7v>");
\r
1133 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1136 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1140 str9xpec_info = bank->driver_priv;
\r
1142 if (strcmp(args[1], "2.7v") == 0)
\r
1144 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
\r
1148 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
\r
1154 int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1156 flash_bank_t *bank;
\r
1157 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
1161 command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd|vdd_vddq>");
\r
1165 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1168 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1172 str9xpec_info = bank->driver_priv;
\r
1174 if (strcmp(args[1], "vdd_vddq") == 0)
\r
1176 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
\r
1180 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
\r
1186 int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1188 flash_bank_t *bank;
\r
1189 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
1193 command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd|vdd_vddq>");
\r
1197 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1200 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1204 str9xpec_info = bank->driver_priv;
\r
1206 if (strcmp(args[1], "vdd_vddq") == 0)
\r
1208 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
\r
1212 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
\r
1218 int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1221 flash_bank_t *bank;
\r
1225 command_print(cmd_ctx, "str9xpec lock <bank>");
\r
1229 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1232 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1236 status = str9xpec_lock_device(bank);
\r
1238 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
1239 return ERROR_FLASH_OPERATION_FAILED;
\r
1244 int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1247 flash_bank_t *bank;
\r
1251 command_print(cmd_ctx, "str9xpec unlock <bank>");
\r
1255 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1258 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1262 status = str9xpec_unlock_device(bank);
\r
1264 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
\r
1265 return ERROR_FLASH_OPERATION_FAILED;
\r
1270 int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1272 flash_bank_t *bank;
\r
1274 jtag_device_t* dev0;
\r
1275 jtag_device_t* dev2;
\r
1276 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
1280 command_print(cmd_ctx, "str9xpec enable_turbo <bank>");
\r
1284 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1287 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1291 str9xpec_info = bank->driver_priv;
\r
1293 chain_pos = str9xpec_info->chain_pos;
\r
1295 /* remove arm core from chain - enter turbo mode */
\r
1297 str9xpec_set_instr(chain_pos+2, 0xD, TAP_RTI);
\r
1298 jtag_execute_queue();
\r
1300 /* modify scan chain - str9 core has been removed */
\r
1301 dev0 = jtag_get_device(chain_pos);
\r
1302 str9xpec_info->devarm = jtag_get_device(chain_pos+1);
\r
1303 dev2 = jtag_get_device(chain_pos+2);
\r
1304 dev0->next = dev2;
\r
1305 jtag_num_devices--;
\r
1310 int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
\r
1312 flash_bank_t *bank;
\r
1314 jtag_device_t* dev0;
\r
1315 str9xpec_flash_controller_t *str9xpec_info = NULL;
\r
1319 command_print(cmd_ctx, "str9xpec disable_turbo <bank>");
\r
1323 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
\r
1326 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
\r
1330 str9xpec_info = bank->driver_priv;
\r
1332 chain_pos = str9xpec_info->chain_pos;
\r
1334 dev0 = jtag_get_device(chain_pos);
\r
1336 /* exit turbo mode via TLR */
\r
1337 str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_TLR);
\r
1338 jtag_execute_queue();
\r
1340 /* restore previous scan chain */
\r
1341 if( str9xpec_info->devarm ) {
\r
1342 dev0->next = str9xpec_info->devarm;
\r
1343 jtag_num_devices++;
\r
1344 str9xpec_info->devarm = NULL;
\r