1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
24 #include "replacements.h"
31 #include "algorithm.h"
32 #include "binarybuffer.h"
38 str7x_mem_layout_t mem_layout[] = {
39 {0x00000000, 0x02000, 0x01},
40 {0x00002000, 0x02000, 0x01},
41 {0x00004000, 0x02000, 0x01},
42 {0x00006000, 0x02000, 0x01},
43 {0x00008000, 0x08000, 0x01},
44 {0x00010000, 0x10000, 0x01},
45 {0x00020000, 0x10000, 0x01},
46 {0x00030000, 0x10000, 0x01},
47 {0x000C0000, 0x02000, 0x10},
48 {0x000C2000, 0x02000, 0x10},
52 int str7x_register_commands(struct command_context_s *cmd_ctx);
53 int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
54 int str7x_erase(struct flash_bank_s *bank, int first, int last);
55 int str7x_protect(struct flash_bank_s *bank, int set, int first, int last);
56 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
57 int str7x_probe(struct flash_bank_s *bank);
58 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
59 int str7x_protect_check(struct flash_bank_s *bank);
60 int str7x_erase_check(struct flash_bank_s *bank);
61 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size);
63 flash_driver_t str7x_flash =
66 .register_commands = str7x_register_commands,
67 .flash_bank_command = str7x_flash_bank_command,
69 .protect = str7x_protect,
72 .erase_check = str7x_erase_check,
73 .protect_check = str7x_protect_check,
77 int str7x_register_commands(struct command_context_s *cmd_ctx)
83 int str7x_get_flash_adr(struct flash_bank_s *bank, u32 reg)
85 str7x_flash_bank_t *str7x_info = bank->driver_priv;
86 return (str7x_info->flash_base|reg);
89 int str7x_build_block_list(struct flash_bank_s *bank)
91 str7x_flash_bank_t *str7x_info = bank->driver_priv;
111 ERROR("BUG: unknown bank->size encountered");
115 if( str7x_info->bank1 == 1 )
120 bank->num_sectors = num_sectors;
121 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
123 for (i = 0; i < num_sectors; i++)
125 bank->sectors[i].offset = mem_layout[i].sector_start;
126 bank->sectors[i].size = mem_layout[i].sector_size;
127 bank->sectors[i].is_erased = -1;
128 bank->sectors[i].is_protected = 1;
134 /* flash bank str7x <base> <size> 0 0 <str71_variant> <target#>
136 int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
138 str7x_flash_bank_t *str7x_info;
142 WARNING("incomplete flash_bank str7x configuration");
143 return ERROR_FLASH_BANK_INVALID;
146 str7x_info = malloc(sizeof(str7x_flash_bank_t));
147 bank->driver_priv = str7x_info;
149 if (strcmp(args[5], "STR71x") == 0)
151 str7x_info->bank1 = 1;
152 str7x_info->flash_base = 0x40000000;
154 else if (strcmp(args[5], "STR73x") == 0)
156 str7x_info->bank1 = 0;
157 str7x_info->flash_base = 0x80000000;
161 ERROR("unknown STR7x variant");
163 return ERROR_FLASH_BANK_INVALID;
166 str7x_info->target = get_target_by_num(strtoul(args[6], NULL, 0));
167 if (!str7x_info->target)
169 ERROR("no target '%s' configured", args[6]);
173 str7x_build_block_list(bank);
178 u32 str7x_status(struct flash_bank_s *bank)
180 str7x_flash_bank_t *str7x_info = bank->driver_priv;
181 target_t *target = str7x_info->target;
184 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&retval);
189 u32 str7x_result(struct flash_bank_s *bank)
191 str7x_flash_bank_t *str7x_info = bank->driver_priv;
192 target_t *target = str7x_info->target;
195 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_ER), 4, 1, (u8*)&retval);
200 int str7x_blank_check(struct flash_bank_s *bank, int first, int last)
202 str7x_flash_bank_t *str7x_info = bank->driver_priv;
203 target_t *target = str7x_info->target;
208 if ((first < 0) || (last > bank->num_sectors))
209 return ERROR_FLASH_SECTOR_INVALID;
211 if (str7x_info->target->state != TARGET_HALTED)
213 return ERROR_TARGET_NOT_HALTED;
216 buffer = malloc(256);
218 for (i = first; i <= last; i++)
220 bank->sectors[i].is_erased = 1;
222 target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, 256/4, buffer);
224 for (nBytes = 0; nBytes < 256; nBytes++)
226 if (buffer[nBytes] != 0xFF)
228 bank->sectors[i].is_erased = 0;
239 int str7x_protect_check(struct flash_bank_s *bank)
241 str7x_flash_bank_t *str7x_info = bank->driver_priv;
242 target_t *target = str7x_info->target;
247 if (str7x_info->target->state != TARGET_HALTED)
249 return ERROR_TARGET_NOT_HALTED;
252 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), 4, 1, (u8*)&retval);
254 for (i = 0; i < bank->num_sectors; i++)
256 if (retval & (mem_layout[i].reg_offset << i))
257 bank->sectors[i].is_protected = 0;
259 bank->sectors[i].is_protected = 1;
265 int str7x_erase(struct flash_bank_s *bank, int first, int last)
267 str7x_flash_bank_t *str7x_info = bank->driver_priv;
268 target_t *target = str7x_info->target;
275 if (str7x_info->target->state != TARGET_HALTED)
277 return ERROR_TARGET_NOT_HALTED;
282 for (i = first; i <= last; i++)
283 erase_blocks |= (mem_layout[i].reg_offset << i);
286 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
289 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR1), 4, 1, (u8*)&cmd);
291 cmd = FLASH_SER|FLASH_WMS;
292 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
294 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
298 retval = str7x_result(bank);
300 if (retval & FLASH_ERER)
301 return ERROR_FLASH_SECTOR_NOT_ERASED;
302 else if (retval & FLASH_WPF)
303 return ERROR_FLASH_OPERATION_FAILED;
305 for (i = first; i <= last; i++)
306 bank->sectors[i].is_erased = 1;
311 int str7x_protect(struct flash_bank_s *bank, int set, int first, int last)
313 str7x_flash_bank_t *str7x_info = bank->driver_priv;
314 target_t *target = str7x_info->target;
320 if (str7x_info->target->state != TARGET_HALTED)
322 return ERROR_TARGET_NOT_HALTED;
325 protect_blocks = 0xFFFFFFFF;
329 for (i = first; i <= last; i++)
330 protect_blocks &= ~(mem_layout[i].reg_offset << i);
334 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
336 cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
337 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
339 cmd = protect_blocks;
340 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
342 cmd = FLASH_SPR|FLASH_WMS;
343 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
345 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
349 retval = str7x_result(bank);
351 if (retval & FLASH_ERER)
352 return ERROR_FLASH_SECTOR_NOT_ERASED;
353 else if (retval & FLASH_WPF)
354 return ERROR_FLASH_OPERATION_FAILED;
359 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
361 str7x_flash_bank_t *str7x_info = bank->driver_priv;
362 target_t *target = str7x_info->target;
363 u32 dwords_remaining = (count / 8);
364 u32 bytes_remaining = (count & 0x00000007);
365 u32 address = bank->base + offset;
366 u32 *wordbuffer = (u32*)buffer;
367 u32 bytes_written = 0;
371 if (str7x_info->target->state != TARGET_HALTED)
373 return ERROR_TARGET_NOT_HALTED;
376 if (offset + count > bank->size)
377 return ERROR_FLASH_DST_OUT_OF_BANK;
379 while (dwords_remaining > 0)
383 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
387 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
390 cmd = wordbuffer[bytes_written/4];
391 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
395 cmd = wordbuffer[bytes_written/4];
396 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, (u8*)&cmd);
399 /* start programming cycle */
400 cmd = FLASH_DWPG|FLASH_WMS;
401 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
403 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
407 retval = str7x_result(bank);
409 if (retval & FLASH_PGER)
410 return ERROR_FLASH_OPERATION_FAILED;
411 else if (retval & FLASH_WPF)
412 return ERROR_FLASH_OPERATION_FAILED;
418 while( bytes_remaining > 0 )
422 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
426 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
429 cmd = buffer[bytes_written];
430 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
432 /* start programming cycle */
433 cmd = FLASH_WPG|FLASH_WMS;
434 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
436 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
440 retval = str7x_result(bank);
442 if (retval & FLASH_PGER)
443 return ERROR_FLASH_OPERATION_FAILED;
444 else if (retval & FLASH_WPF)
445 return ERROR_FLASH_OPERATION_FAILED;
455 int str7x_probe(struct flash_bank_s *bank)
460 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
465 int str7x_erase_check(struct flash_bank_s *bank)
467 return str7x_blank_check(bank, 0, bank->num_sectors - 1);
470 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size)
472 snprintf(buf, buf_size, "str7x flash driver info" );