- "flash write_binary" is now "flash write_bank" to clarify the focus of the
[fw/openocd] / src / flash / str9xpec.c
1 /***************************************************************************\r
2  *   Copyright (C) 2005 by Dominic Rath                                    *\r
3  *   Dominic.Rath@gmx.de                                                   *\r
4  *                                                                         *\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
9  *                                                                         *\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
14  *                                                                         *\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
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include "replacements.h"\r
25 \r
26 #include "str9xpec.h"\r
27 #include "flash.h"\r
28 #include "target.h"\r
29 #include "log.h"\r
30 #include "armv4_5.h"\r
31 #include "arm7_9_common.h"\r
32 #include "jtag.h"\r
33 #include "binarybuffer.h"\r
34 \r
35 #include <stdlib.h>\r
36 #include <string.h>\r
37 #include <unistd.h>\r
38 #include <getopt.h>\r
39 \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
53 };\r
54 \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
65 \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
69 \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
80 \r
81 flash_driver_t str9xpec_flash =\r
82 {\r
83         .name = "str9xpec",\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
94 };\r
95 \r
96 int str9xpec_register_commands(struct command_context_s *cmd_ctx)\r
97 {\r
98         command_t *str9xpec_cmd = register_command(cmd_ctx, NULL, "str9xpec", NULL, COMMAND_ANY, "str9xpec flash specific commands");\r
99         \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
122         \r
123         return ERROR_OK;\r
124 }\r
125 \r
126 int str9xpec_set_instr(int chain_pos, u32 new_instr, enum tap_state end_state)\r
127 {\r
128         jtag_device_t *device = jtag_get_device(chain_pos);\r
129         \r
130         if (device == NULL)\r
131         {\r
132                 DEBUG("Invalid Target");\r
133                 return ERROR_TARGET_INVALID;\r
134         }\r
135                 \r
136         if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)\r
137         {\r
138                 scan_field_t field;\r
139                                 \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
150                 \r
151                 jtag_add_ir_scan(1, &field, end_state, NULL);\r
152                 \r
153                 free(field.out_value);\r
154         }\r
155         \r
156         return ERROR_OK;\r
157 }\r
158 \r
159 u8 str9xpec_isc_status(int chain_pos)\r
160 {\r
161         scan_field_t field;\r
162         u8 status;\r
163         \r
164         if (str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI) != ERROR_OK)\r
165                 return ISC_STATUS_ERROR;\r
166         \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
176         \r
177         jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
178         jtag_execute_queue();\r
179         \r
180         DEBUG("status: 0x%2.2x", status);\r
181         \r
182         if (status & ISC_STATUS_SECURITY)\r
183                 INFO("Device Security Bit Set");\r
184         \r
185         return status;\r
186 }\r
187 \r
188 int str9xpec_isc_enable(struct flash_bank_s *bank)\r
189 {\r
190         u8 status;\r
191         u32 chain_pos;\r
192         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
193         \r
194         chain_pos = str9xpec_info->chain_pos;\r
195         \r
196         if (str9xpec_info->isc_enable)\r
197                 return ERROR_OK;\r
198         \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
202         \r
203         /* check ISC status */\r
204         status = str9xpec_isc_status(chain_pos);\r
205         if (status & ISC_STATUS_MODE)\r
206         {\r
207                 /* we have entered isc mode */\r
208                 str9xpec_info->isc_enable = 1;\r
209                 DEBUG("ISC_MODE Enabled");\r
210         }\r
211         \r
212         return ERROR_OK;\r
213 }\r
214 \r
215 int str9xpec_isc_disable(struct flash_bank_s *bank)\r
216 {\r
217         u8 status;\r
218         u32 chain_pos;\r
219         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
220         \r
221         chain_pos = str9xpec_info->chain_pos;\r
222         \r
223         if (!str9xpec_info->isc_enable)\r
224                 return ERROR_OK;\r
225         \r
226         if (str9xpec_set_instr(chain_pos, ISC_DISABLE, TAP_RTI) != ERROR_OK)\r
227                 return ERROR_TARGET_INVALID;\r
228         \r
229         /* delay to handle aborts */\r
230         jtag_add_sleep(50);\r
231         \r
232         /* check ISC status */\r
233         status = str9xpec_isc_status(chain_pos);\r
234         if (!(status & ISC_STATUS_MODE))\r
235         {\r
236                 /* we have left isc mode */\r
237                 str9xpec_info->isc_enable = 0;\r
238                 DEBUG("ISC_MODE Disabled");\r
239         }\r
240         \r
241         return ERROR_OK;\r
242 }\r
243 \r
244 int str9xpec_read_config(struct flash_bank_s *bank)\r
245 {\r
246         scan_field_t field;\r
247         u8 status;\r
248         u32 chain_pos;\r
249                 \r
250         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
251         \r
252         chain_pos = str9xpec_info->chain_pos;\r
253         \r
254         DEBUG("ISC_CONFIGURATION");\r
255         \r
256         /* execute ISC_CONFIGURATION command */\r
257         str9xpec_set_instr(chain_pos, ISC_CONFIGURATION, TAP_PI);\r
258         \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
268         \r
269         jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
270         jtag_execute_queue();\r
271         \r
272         status = str9xpec_isc_status(chain_pos);\r
273         \r
274         return status;\r
275 }\r
276 \r
277 int str9xpec_build_block_list(struct flash_bank_s *bank)\r
278 {\r
279         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
280         \r
281         int i;\r
282         int num_sectors = 0, b0_sectors = 0;\r
283                 \r
284         switch (bank->size)\r
285         {\r
286                 case (256 * 1024):\r
287                         b0_sectors = 4;\r
288                         break;\r
289                 case (512 * 1024):\r
290                         b0_sectors = 8;\r
291                         break;\r
292                 default:\r
293                         ERROR("BUG: unknown bank->size encountered");\r
294                         exit(-1);\r
295         }\r
296         \r
297         /* include bank 1 sectors */\r
298         num_sectors = b0_sectors + 4;\r
299         bank->size += (32 * 1024);\r
300         \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
304         \r
305         num_sectors = 0;\r
306         \r
307         for (i = 0; i < b0_sectors; i++)\r
308         {\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
314         }\r
315         \r
316         for (i = 8; i < 12; i++)\r
317         {\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
323         }\r
324         \r
325         return ERROR_OK;\r
326 }\r
327 \r
328 /* flash bank str9x <base> <size> 0 0 <target#>\r
329  */\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
331 {\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
336         \r
337         if (argc < 6)\r
338         {\r
339                 WARNING("incomplete flash_bank str9x configuration");\r
340                 return ERROR_FLASH_BANK_INVALID;\r
341         }\r
342         \r
343         str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));\r
344         bank->driver_priv = str9xpec_info;\r
345         \r
346         if (bank->base != 0x00000000)\r
347         {\r
348                 WARNING("overriding flash base address for STR91x device with 0x00000000");\r
349                 bank->base = 0x00000000;\r
350         }\r
351 \r
352         /* find out jtag position of flash controller\r
353          * it is always after the arm966 core */\r
354         \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
358         \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
362         \r
363         str9xpec_build_block_list(bank);\r
364         \r
365         /* clear option byte register */\r
366         buf_set_u32(str9xpec_info->options, 0, 64, 0);\r
367         \r
368         return ERROR_OK;\r
369 }\r
370 \r
371 int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)\r
372 {\r
373         scan_field_t field;\r
374         u8 status;\r
375         u32 chain_pos;\r
376         int i;\r
377         u8 *buffer = NULL;\r
378                 \r
379         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
380         \r
381         chain_pos = str9xpec_info->chain_pos;\r
382         \r
383         if (!str9xpec_info->isc_enable) {\r
384                 str9xpec_isc_enable( bank );\r
385         }\r
386         \r
387         if (!str9xpec_info->isc_enable) {\r
388                 return ERROR_FLASH_OPERATION_FAILED;\r
389         }\r
390         \r
391         buffer = calloc(CEIL(64, 8), 1);\r
392 \r
393         DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);\r
394         \r
395         for (i = first; i <= last; i++) {\r
396                 buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);\r
397         }\r
398         \r
399         /* execute ISC_BLANK_CHECK command */\r
400         str9xpec_set_instr(chain_pos, ISC_BLANK_CHECK, TAP_PI);\r
401         \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
411         \r
412         jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
413         jtag_add_sleep(40000);\r
414         \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
425         \r
426         jtag_add_dr_scan(1, &field, TAP_PI, NULL);\r
427         jtag_execute_queue();\r
428         \r
429         status = str9xpec_isc_status(chain_pos);\r
430         \r
431         for (i = first; i <= last; i++)\r
432         {\r
433                 if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))\r
434                         bank->sectors[i].is_erased = 0;\r
435                 else\r
436                         bank->sectors[i].is_erased = 1;\r
437         }\r
438         \r
439         free(buffer);\r
440         \r
441         str9xpec_isc_disable(bank);\r
442         \r
443         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
444                 return ERROR_FLASH_OPERATION_FAILED; \r
445         return ERROR_OK;\r
446 }\r
447 \r
448 int str9xpec_protect_check(struct flash_bank_s *bank)\r
449 {\r
450         u8 status;\r
451         int i;\r
452                 \r
453         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
454         \r
455         status = str9xpec_read_config(bank);\r
456         \r
457         for (i = 0; i < bank->num_sectors; i++)\r
458         {\r
459                 if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))\r
460                         bank->sectors[i].is_protected = 1;\r
461                 else\r
462                         bank->sectors[i].is_protected = 0;\r
463         }\r
464         \r
465         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
466                 return ERROR_FLASH_OPERATION_FAILED;\r
467         return ERROR_OK;\r
468 }\r
469 \r
470 int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)\r
471 {\r
472         scan_field_t field;\r
473         u8 status;\r
474         u32 chain_pos;\r
475         int i;\r
476         u8 *buffer = NULL;\r
477         \r
478         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
479         \r
480         chain_pos = str9xpec_info->chain_pos;\r
481         \r
482         if (!str9xpec_info->isc_enable) {\r
483                 str9xpec_isc_enable( bank );\r
484         }\r
485         \r
486         if (!str9xpec_info->isc_enable) {\r
487                 return ISC_STATUS_ERROR;\r
488         }\r
489         \r
490         buffer = calloc(CEIL(64, 8), 1);\r
491         \r
492         DEBUG("erase: first_bank: %i, last_bank: %i", first, last);\r
493         \r
494         /* last bank: 0xFF signals a full erase (unlock complete device) */\r
495         /* last bank: 0xFE signals a option byte erase */\r
496         if (last == 0xFF)\r
497         {\r
498                 for (i = 0; i < 64; i++) {\r
499                         buf_set_u32(buffer, i, 1, 1);\r
500                 }       \r
501         }\r
502         else if (last == 0xFE)\r
503         {\r
504                 buf_set_u32(buffer, 49, 1, 1);\r
505         }\r
506         else\r
507         {       \r
508                 for (i = first; i <= last; i++) {\r
509                         buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);\r
510                 }\r
511         }\r
512         \r
513         DEBUG("ISC_ERASE");\r
514         \r
515         /* execute ISC_ERASE command */\r
516         str9xpec_set_instr(chain_pos, ISC_ERASE, TAP_PI);\r
517         \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
527         \r
528         jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
529         jtag_execute_queue();\r
530         \r
531         jtag_add_sleep(10);\r
532         \r
533         /* wait for erase completion */\r
534         while (!((status = str9xpec_isc_status(chain_pos)) & ISC_STATUS_BUSY)) {\r
535                 usleep(1000);\r
536         }\r
537         \r
538         free(buffer);\r
539         \r
540         str9xpec_isc_disable(bank);\r
541         \r
542         return status;\r
543 }\r
544 \r
545 int str9xpec_erase(struct flash_bank_s *bank, int first, int last)\r
546 {\r
547         int status;\r
548         \r
549         status = str9xpec_erase_area(bank, first, last);\r
550         \r
551         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
552                 return ERROR_FLASH_OPERATION_FAILED;\r
553         \r
554         return ERROR_OK;\r
555 }\r
556 \r
557 int str9xpec_lock_device(struct flash_bank_s *bank)\r
558 {\r
559         scan_field_t field;\r
560         u8 status;\r
561         u32 chain_pos;\r
562         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
563         \r
564         str9xpec_info = bank->driver_priv;\r
565         chain_pos = str9xpec_info->chain_pos;\r
566         \r
567         if (!str9xpec_info->isc_enable) {\r
568                 str9xpec_isc_enable( bank );\r
569         }\r
570         \r
571         if (!str9xpec_info->isc_enable) {\r
572                 return ISC_STATUS_ERROR;\r
573         }\r
574         \r
575         /* set security address */\r
576         str9xpec_set_address(bank, 0x80);\r
577         \r
578         /* execute ISC_PROGRAM command */\r
579         str9xpec_set_instr(chain_pos, ISC_PROGRAM_SECURITY, TAP_RTI);\r
580         \r
581         str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
582         \r
583         do {\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
593                 \r
594                 jtag_add_dr_scan(1, &field, -1, NULL);\r
595                 jtag_execute_queue();\r
596                 \r
597         } while(!(status & ISC_STATUS_BUSY));\r
598         \r
599         str9xpec_isc_disable(bank);\r
600         \r
601         return status;\r
602 }\r
603 \r
604 int str9xpec_unlock_device(struct flash_bank_s *bank)\r
605 {\r
606         u8 status;\r
607         \r
608         status = str9xpec_erase_area(bank, 0, 255);\r
609         \r
610         return status;\r
611 }\r
612 \r
613 int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)\r
614 {\r
615         u8 status;\r
616         int i;\r
617         \r
618         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
619         \r
620         status = str9xpec_read_config(bank);\r
621         \r
622         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
623                 return ERROR_FLASH_OPERATION_FAILED;\r
624 \r
625         DEBUG("protect: first_bank: %i, last_bank: %i", first, last);\r
626         \r
627         /* last bank: 0xFF signals a full device protect */\r
628         if (last == 0xFF)\r
629         {\r
630                 if( set )\r
631                 {\r
632                         status = str9xpec_lock_device(bank);\r
633                 }\r
634                 else\r
635                 {\r
636                         /* perform full erase to unlock device */\r
637                         status = str9xpec_unlock_device(bank);\r
638                 }\r
639         }\r
640         else\r
641         {       \r
642                 for (i = first; i <= last; i++)\r
643                 {\r
644                         if( set )\r
645                                 buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);\r
646                         else\r
647                                 buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);\r
648                 }\r
649                 \r
650                 status = str9xpec_write_options(bank);\r
651         }\r
652         \r
653         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
654                 return ERROR_FLASH_OPERATION_FAILED;\r
655         \r
656         return ERROR_OK;\r
657 }\r
658 \r
659 int str9xpec_set_address(struct flash_bank_s *bank, u8 sector)\r
660 {\r
661         u32 chain_pos;\r
662         scan_field_t field;\r
663         str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
664         \r
665         chain_pos = str9xpec_info->chain_pos;\r
666         \r
667         /* set flash controller address */\r
668         str9xpec_set_instr(chain_pos, ISC_ADDRESS_SHIFT, TAP_PI);\r
669         \r
670         field.device = chain_pos;\r
671         field.num_bits = 8;\r
672         field.out_value = &sector;\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
679         \r
680         jtag_add_dr_scan(1, &field, -1, NULL);\r
681                 \r
682         return ERROR_OK;\r
683 }\r
684 \r
685 int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)\r
686 {\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
691         u8 status;\r
692         u32 check_address = offset;\r
693         u32 chain_pos;\r
694         scan_field_t field;\r
695         u8 *scanbuf;\r
696         int i;\r
697         u32 first_sector = 0;\r
698         u32 last_sector = 0;\r
699         \r
700         chain_pos = str9xpec_info->chain_pos;\r
701         \r
702         if (!str9xpec_info->isc_enable) {\r
703                 str9xpec_isc_enable(bank);\r
704         }\r
705         \r
706         if (!str9xpec_info->isc_enable) {\r
707                 return ERROR_FLASH_OPERATION_FAILED;\r
708         }\r
709         \r
710         if (offset & 0x7)\r
711         {\r
712                 WARNING("offset 0x%x breaks required 8-byte alignment", offset);\r
713                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;\r
714         }\r
715         \r
716         for (i = 0; i < bank->num_sectors; i++)\r
717         {\r
718                 u32 sec_start = bank->sectors[i].offset;\r
719                 u32 sec_end = sec_start + bank->sectors[i].size;\r
720                 \r
721                 /* check if destination falls within the current sector */\r
722                 if ((check_address >= sec_start) && (check_address < sec_end))\r
723                 {\r
724                         /* check if destination ends in the current sector */\r
725                         if (offset + count < sec_end)\r
726                                 check_address = offset + count;\r
727                         else\r
728                                 check_address = sec_end;\r
729                 }\r
730                 \r
731                 if ((offset >= sec_start) && (offset < sec_end)){\r
732                         first_sector = i;\r
733                 }\r
734                 \r
735                 if ((offset + count >= sec_start) && (offset + count < sec_end)){\r
736                         last_sector = i;\r
737                 }\r
738         }\r
739         \r
740         if (check_address != offset + count)\r
741                 return ERROR_FLASH_DST_OUT_OF_BANK;\r
742 \r
743         DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);\r
744         \r
745         scanbuf = calloc(CEIL(64, 8), 1);\r
746         \r
747         DEBUG("ISC_PROGRAM");\r
748         \r
749         for (i = first_sector; i <= last_sector; i++)\r
750         {\r
751                 str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);\r
752                 \r
753                 dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);\r
754 \r
755                 while (dwords_remaining > 0)\r
756                 {       \r
757                         str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
758                         \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
768                         \r
769                         jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
770                         \r
771                         /* small delay before polling */\r
772                         jtag_add_sleep(50);\r
773                         \r
774                         str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
775                         \r
776                         do {\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
786                                 \r
787                                 jtag_add_dr_scan(1, &field, -1, NULL);\r
788                                 jtag_execute_queue();\r
789                                 \r
790                                 status = buf_get_u32(scanbuf, 0, 8);\r
791                                 \r
792                         } while(!(status & ISC_STATUS_BUSY));\r
793                         \r
794                         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
795                                 return ERROR_FLASH_OPERATION_FAILED;\r
796                         \r
797                         //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)\r
798                         //      return ERROR_FLASH_OPERATION_FAILED;\r
799                 \r
800                         dwords_remaining--;\r
801                         bytes_written += 8;\r
802                 }\r
803         }\r
804         \r
805         if (bytes_remaining)\r
806         {\r
807                 u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
808                 int i = 0;\r
809                                 \r
810                 while(bytes_remaining > 0)\r
811                 {\r
812                         last_dword[i++] = *(buffer + bytes_written); \r
813                         bytes_remaining--;\r
814                         bytes_written++;\r
815                 }\r
816                 \r
817                 str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
818                 \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
828                 \r
829                 jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
830                 \r
831                 /* small delay before polling */\r
832                 jtag_add_sleep(50);\r
833                 \r
834                 str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
835                 \r
836                 do {\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
846                         \r
847                         jtag_add_dr_scan(1, &field, -1, NULL);\r
848                         jtag_execute_queue();\r
849                         \r
850                         status = buf_get_u32(scanbuf, 0, 8);\r
851                         \r
852                 } while(!(status & ISC_STATUS_BUSY));\r
853                 \r
854                 if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
855                         return ERROR_FLASH_OPERATION_FAILED;\r
856                 \r
857                 //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)\r
858                 //      return ERROR_FLASH_OPERATION_FAILED;\r
859         }\r
860 \r
861         free(scanbuf);\r
862 \r
863         str9xpec_isc_disable(bank);\r
864                                 \r
865         return ERROR_OK;\r
866 }\r
867 \r
868 int str9xpec_probe(struct flash_bank_s *bank)\r
869 {\r
870         return ERROR_OK;\r
871 }\r
872 \r
873 int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
874 {\r
875         flash_bank_t *bank;\r
876         scan_field_t field;\r
877         u8 *buffer = NULL;\r
878         u32 chain_pos;\r
879         u32 idcode;\r
880         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
881 \r
882         if (argc < 1)\r
883         {\r
884                 return ERROR_COMMAND_SYNTAX_ERROR;\r
885         }\r
886         \r
887         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
888         if (!bank)\r
889         {\r
890                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
891                 return ERROR_OK;\r
892         }\r
893         \r
894         str9xpec_info = bank->driver_priv;\r
895         chain_pos = str9xpec_info->chain_pos;\r
896         \r
897         buffer = calloc(CEIL(32, 8), 1);\r
898         \r
899         str9xpec_set_instr(chain_pos, ISC_IDCODE, TAP_PI);\r
900         \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
910         \r
911         jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
912         jtag_execute_queue();\r
913         \r
914         idcode = buf_get_u32(buffer, 0, 32);\r
915         \r
916         command_print(cmd_ctx, "str9xpec part id: 0x%8.8x", idcode);\r
917         \r
918         free(buffer);\r
919         \r
920         return ERROR_OK;\r
921 }\r
922 \r
923 int str9xpec_erase_check(struct flash_bank_s *bank)\r
924 {\r
925         return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);\r
926 }\r
927 \r
928 int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
929 {\r
930         snprintf(buf, buf_size, "str9xpec flash driver info" );\r
931         return ERROR_OK;\r
932 }\r
933 \r
934 int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
935 {\r
936         flash_bank_t *bank;\r
937         u8 status;\r
938         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
939         \r
940         if (argc < 1)\r
941         {\r
942                 command_print(cmd_ctx, "str9xpec options_read <bank>");\r
943                 return ERROR_OK;        \r
944         }\r
945         \r
946         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
947         if (!bank)\r
948         {\r
949                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
950                 return ERROR_OK;\r
951         }\r
952         \r
953         str9xpec_info = bank->driver_priv;\r
954         \r
955         status = str9xpec_read_config(bank);\r
956         \r
957         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
958                 return ERROR_FLASH_OPERATION_FAILED;\r
959         \r
960         /* boot bank */\r
961         if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))\r
962                 command_print(cmd_ctx, "CS Map: bank1");\r
963         else\r
964                 command_print(cmd_ctx, "CS Map: bank0");\r
965         \r
966         /* OTP lock */\r
967         if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))\r
968                 command_print(cmd_ctx, "OTP Lock: OTP Locked");\r
969         else\r
970                 command_print(cmd_ctx, "OTP Lock: OTP Unlocked");\r
971         \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
975         else\r
976                 command_print(cmd_ctx, "LVD Threshold: 2.4v");\r
977         \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
981         else\r
982                 command_print(cmd_ctx, "LVD Reset Warning: VDD Input Only");\r
983         \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
987         else\r
988                 command_print(cmd_ctx, "LVD Reset Selection: VDD Input Only");\r
989         \r
990         return ERROR_OK;\r
991 }\r
992 \r
993 int str9xpec_write_options(struct flash_bank_s *bank)\r
994 {\r
995         scan_field_t field;\r
996         u8 status;\r
997         u32 chain_pos;\r
998         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
999         \r
1000         str9xpec_info = bank->driver_priv;\r
1001         chain_pos = str9xpec_info->chain_pos;\r
1002         \r
1003         /* erase config options first */\r
1004         status = str9xpec_erase_area( bank, 0xFE, 0xFE );\r
1005         \r
1006         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
1007                 return status; \r
1008         \r
1009         if (!str9xpec_info->isc_enable) {\r
1010                 str9xpec_isc_enable( bank );\r
1011         }\r
1012         \r
1013         if (!str9xpec_info->isc_enable) {\r
1014                 return ISC_STATUS_ERROR;\r
1015         }\r
1016         \r
1017         /* according to data 64th bit has to be set */\r
1018         buf_set_u32(str9xpec_info->options, 63, 1, 1);\r
1019         \r
1020         /* set option byte address */\r
1021         str9xpec_set_address(bank, 0x50);\r
1022         \r
1023         /* execute ISC_PROGRAM command */\r
1024         str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
1025                 \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
1035         \r
1036         jtag_add_dr_scan(1, &field, TAP_RTI, NULL);\r
1037         \r
1038         /* small delay before polling */\r
1039         jtag_add_sleep(50);\r
1040         \r
1041         str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
1042         \r
1043         do {\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
1053                 \r
1054                 jtag_add_dr_scan(1, &field, -1, NULL);\r
1055                 jtag_execute_queue();\r
1056                 \r
1057         } while(!(status & ISC_STATUS_BUSY));\r
1058         \r
1059         str9xpec_isc_disable(bank);\r
1060         \r
1061         return status;\r
1062 }\r
1063 \r
1064 int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1065 {\r
1066         flash_bank_t *bank;\r
1067         u8 status;\r
1068         \r
1069         if (argc < 1)\r
1070         {\r
1071                 command_print(cmd_ctx, "str9xpec options_write <bank>");\r
1072                 return ERROR_OK;        \r
1073         }\r
1074         \r
1075         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1076         if (!bank)\r
1077         {\r
1078                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1079                 return ERROR_OK;\r
1080         }\r
1081         \r
1082         status = str9xpec_write_options(bank);\r
1083         \r
1084         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
1085                 return ERROR_FLASH_OPERATION_FAILED;\r
1086         \r
1087         return ERROR_OK;\r
1088 }\r
1089 \r
1090 int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1091 {\r
1092         flash_bank_t *bank;\r
1093         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
1094         \r
1095         if (argc < 2)\r
1096         {\r
1097                 command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0|bank1>");\r
1098                 return ERROR_OK;        \r
1099         }\r
1100         \r
1101         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1102         if (!bank)\r
1103         {\r
1104                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1105                 return ERROR_OK;\r
1106         }\r
1107         \r
1108         str9xpec_info = bank->driver_priv;\r
1109         \r
1110         if (strcmp(args[1], "bank1") == 0)\r
1111         {\r
1112                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);\r
1113         }\r
1114         else\r
1115         {\r
1116                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);\r
1117         }\r
1118         \r
1119         return ERROR_OK;\r
1120 }\r
1121 \r
1122 int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1123 {\r
1124         flash_bank_t *bank;\r
1125         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
1126         \r
1127         if (argc < 2)\r
1128         {\r
1129                 command_print(cmd_ctx, "str9xpec options_lvdthd <bank> <2.4v|2.7v>");\r
1130                 return ERROR_OK;        \r
1131         }\r
1132         \r
1133         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1134         if (!bank)\r
1135         {\r
1136                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1137                 return ERROR_OK;\r
1138         }\r
1139         \r
1140         str9xpec_info = bank->driver_priv;\r
1141         \r
1142         if (strcmp(args[1], "2.7v") == 0)\r
1143         {\r
1144                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);\r
1145         }\r
1146         else\r
1147         {\r
1148                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);\r
1149         }\r
1150         \r
1151         return ERROR_OK;\r
1152 }\r
1153 \r
1154 int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1155 {\r
1156         flash_bank_t *bank;\r
1157         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
1158         \r
1159         if (argc < 2)\r
1160         {\r
1161                 command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd|vdd_vddq>");\r
1162                 return ERROR_OK;        \r
1163         }\r
1164         \r
1165         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1166         if (!bank)\r
1167         {\r
1168                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1169                 return ERROR_OK;\r
1170         }\r
1171         \r
1172         str9xpec_info = bank->driver_priv;\r
1173         \r
1174         if (strcmp(args[1], "vdd_vddq") == 0)\r
1175         {\r
1176                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);\r
1177         }\r
1178         else\r
1179         {\r
1180                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);\r
1181         }\r
1182         \r
1183         return ERROR_OK;\r
1184 }\r
1185 \r
1186 int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1187 {\r
1188         flash_bank_t *bank;\r
1189         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
1190         \r
1191         if (argc < 2)\r
1192         {\r
1193                 command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd|vdd_vddq>");\r
1194                 return ERROR_OK;        \r
1195         }\r
1196         \r
1197         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1198         if (!bank)\r
1199         {\r
1200                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1201                 return ERROR_OK;\r
1202         }\r
1203         \r
1204         str9xpec_info = bank->driver_priv;\r
1205         \r
1206         if (strcmp(args[1], "vdd_vddq") == 0)\r
1207         {\r
1208                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);\r
1209         }\r
1210         else\r
1211         {\r
1212                 buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);\r
1213         }\r
1214         \r
1215         return ERROR_OK;\r
1216 }\r
1217 \r
1218 int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1219 {\r
1220         u8 status;\r
1221         flash_bank_t *bank;\r
1222         \r
1223         if (argc < 1)\r
1224         {\r
1225                 command_print(cmd_ctx, "str9xpec lock <bank>");\r
1226                 return ERROR_OK;        \r
1227         }\r
1228         \r
1229         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1230         if (!bank)\r
1231         {\r
1232                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1233                 return ERROR_OK;\r
1234         }\r
1235         \r
1236         status = str9xpec_lock_device(bank);\r
1237         \r
1238         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
1239                 return ERROR_FLASH_OPERATION_FAILED;\r
1240         \r
1241         return ERROR_OK;\r
1242 }\r
1243 \r
1244 int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1245 {\r
1246         u8 status;\r
1247         flash_bank_t *bank;\r
1248         \r
1249         if (argc < 1)\r
1250         {\r
1251                 command_print(cmd_ctx, "str9xpec unlock <bank>");\r
1252                 return ERROR_OK;        \r
1253         }\r
1254         \r
1255         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1256         if (!bank)\r
1257         {\r
1258                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1259                 return ERROR_OK;\r
1260         }\r
1261         \r
1262         status = str9xpec_unlock_device(bank);\r
1263         \r
1264         if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
1265                 return ERROR_FLASH_OPERATION_FAILED;\r
1266         \r
1267         return ERROR_OK;\r
1268 }\r
1269 \r
1270 int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1271 {\r
1272         flash_bank_t *bank;\r
1273         u32 chain_pos;\r
1274         jtag_device_t* dev0;\r
1275         jtag_device_t* dev2;\r
1276         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
1277         \r
1278         if (argc < 1)\r
1279         {\r
1280                 command_print(cmd_ctx, "str9xpec enable_turbo <bank>");\r
1281                 return ERROR_OK;        \r
1282         }\r
1283         \r
1284         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1285         if (!bank)\r
1286         {\r
1287                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1288                 return ERROR_OK;\r
1289         }\r
1290         \r
1291         str9xpec_info = bank->driver_priv;\r
1292         \r
1293         chain_pos = str9xpec_info->chain_pos;\r
1294         \r
1295         /* remove arm core from chain - enter turbo mode */\r
1296         \r
1297         str9xpec_set_instr(chain_pos+2, 0xD, TAP_RTI);\r
1298         jtag_execute_queue();\r
1299         \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
1306         \r
1307         return ERROR_OK;\r
1308 }\r
1309 \r
1310 int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1311 {\r
1312         flash_bank_t *bank;\r
1313         u32 chain_pos;\r
1314         jtag_device_t* dev0;\r
1315         str9xpec_flash_controller_t *str9xpec_info = NULL;\r
1316         \r
1317         if (argc < 1)\r
1318         {\r
1319                 command_print(cmd_ctx, "str9xpec disable_turbo <bank>");\r
1320                 return ERROR_OK;        \r
1321         }\r
1322         \r
1323         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
1324         if (!bank)\r
1325         {\r
1326                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
1327                 return ERROR_OK;\r
1328         }\r
1329         \r
1330         str9xpec_info = bank->driver_priv;\r
1331         \r
1332         chain_pos = str9xpec_info->chain_pos;\r
1333         \r
1334         dev0 = jtag_get_device(chain_pos);\r
1335         \r
1336         /* exit turbo mode via TLR */\r
1337         str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_TLR);\r
1338         jtag_execute_queue();\r
1339         \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
1345         }\r
1346         \r
1347         return ERROR_OK;\r
1348 }\r