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 ***************************************************************************/
26 #include "algorithm.h"
27 #include "binarybuffer.h"
33 str7x_mem_layout_t mem_layout[] = {
34 {0x00000000, 0x02000, 0x01},
35 {0x00002000, 0x02000, 0x01},
36 {0x00004000, 0x02000, 0x01},
37 {0x00006000, 0x02000, 0x01},
38 {0x00008000, 0x08000, 0x01},
39 {0x00010000, 0x10000, 0x01},
40 {0x00020000, 0x10000, 0x01},
41 {0x00030000, 0x10000, 0x01},
42 {0x000C0000, 0x02000, 0x10},
43 {0x000C2000, 0x02000, 0x10},
47 int str7x_register_commands(struct command_context_s *cmd_ctx);
48 int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
49 int str7x_erase(struct flash_bank_s *bank, int first, int last);
50 int str7x_protect(struct flash_bank_s *bank, int set, int first, int last);
51 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
52 int str7x_probe(struct flash_bank_s *bank);
53 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
54 int str7x_protect_check(struct flash_bank_s *bank);
55 int str7x_erase_check(struct flash_bank_s *bank);
56 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size);
58 flash_driver_t str7x_flash =
61 .register_commands = str7x_register_commands,
62 .flash_bank_command = str7x_flash_bank_command,
64 .protect = str7x_protect,
67 .erase_check = str7x_erase_check,
68 .protect_check = str7x_protect_check,
72 int str7x_register_commands(struct command_context_s *cmd_ctx)
78 int str7x_get_flash_adr(struct flash_bank_s *bank, u32 reg)
80 str7x_flash_bank_t *str7x_info = bank->driver_priv;
81 return (str7x_info->flash_base|reg);
84 int str7x_build_block_list(struct flash_bank_s *bank)
86 str7x_flash_bank_t *str7x_info = bank->driver_priv;
106 ERROR("BUG: unknown bank->size encountered");
110 if( str7x_info->bank1 == 1 )
115 bank->num_sectors = num_sectors;
116 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
118 for (i = 0; i < num_sectors; i++)
120 bank->sectors[i].offset = mem_layout[i].sector_start;
121 bank->sectors[i].size = mem_layout[i].sector_size;
122 bank->sectors[i].is_erased = -1;
123 bank->sectors[i].is_protected = 1;
129 /* flash bank str7x <base> <size> 0 0 <str71_variant> <target#>
131 int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
133 str7x_flash_bank_t *str7x_info;
137 WARNING("incomplete flash_bank str7x configuration");
138 return ERROR_FLASH_BANK_INVALID;
141 str7x_info = malloc(sizeof(str7x_flash_bank_t));
142 bank->driver_priv = str7x_info;
144 if (strcmp(args[5], "STR71x") == 0)
146 str7x_info->bank1 = 1;
147 str7x_info->flash_base = 0x40000000;
149 else if (strcmp(args[5], "STR73x") == 0)
151 str7x_info->bank1 = 0;
152 str7x_info->flash_base = 0x80000000;
156 ERROR("unknown STR7x variant");
158 return ERROR_FLASH_BANK_INVALID;
161 str7x_info->target = get_target_by_num(strtoul(args[6], NULL, 0));
162 if (!str7x_info->target)
164 ERROR("no target '%i' configured", args[6]);
168 str7x_build_block_list(bank);
173 u32 str7x_status(struct flash_bank_s *bank)
175 str7x_flash_bank_t *str7x_info = bank->driver_priv;
176 target_t *target = str7x_info->target;
179 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&retval);
184 u32 str7x_result(struct flash_bank_s *bank)
186 str7x_flash_bank_t *str7x_info = bank->driver_priv;
187 target_t *target = str7x_info->target;
190 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_ER), 4, 1, (u8*)&retval);
195 int str7x_blank_check(struct flash_bank_s *bank, int first, int last)
197 str7x_flash_bank_t *str7x_info = bank->driver_priv;
198 target_t *target = str7x_info->target;
203 if ((first < 0) || (last > bank->num_sectors))
204 return ERROR_FLASH_SECTOR_INVALID;
206 if (str7x_info->target->state != TARGET_HALTED)
208 return ERROR_TARGET_NOT_HALTED;
211 buffer = malloc(256);
213 for (i = first; i <= last; i++)
215 bank->sectors[i].is_erased = 1;
217 target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, 256/4, buffer);
219 for (nBytes = 0; nBytes < 256; nBytes++)
221 if (buffer[nBytes] != 0xFF)
223 bank->sectors[i].is_erased = 0;
234 int str7x_protect_check(struct flash_bank_s *bank)
236 str7x_flash_bank_t *str7x_info = bank->driver_priv;
237 target_t *target = str7x_info->target;
242 if (str7x_info->target->state != TARGET_HALTED)
244 return ERROR_TARGET_NOT_HALTED;
247 target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), 4, 1, (u8*)&retval);
249 for (i = 0; i < bank->num_sectors; i++)
251 if (retval & (mem_layout[i].reg_offset << i))
252 bank->sectors[i].is_protected = 0;
254 bank->sectors[i].is_protected = 1;
260 int str7x_erase(struct flash_bank_s *bank, int first, int last)
262 str7x_flash_bank_t *str7x_info = bank->driver_priv;
263 target_t *target = str7x_info->target;
270 if (str7x_info->target->state != TARGET_HALTED)
272 return ERROR_TARGET_NOT_HALTED;
277 for (i = first; i <= last; i++)
278 erase_blocks |= (mem_layout[i].reg_offset << i);
281 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
284 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR1), 4, 1, (u8*)&cmd);
286 cmd = FLASH_SER|FLASH_WMS;
287 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
289 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
293 retval = str7x_result(bank);
295 if (retval & FLASH_ERER)
296 return ERROR_FLASH_SECTOR_NOT_ERASED;
297 else if (retval & FLASH_WPF)
298 return ERROR_FLASH_OPERATION_FAILED;
300 for (i = first; i <= last; i++)
301 bank->sectors[i].is_erased = 1;
306 int str7x_protect(struct flash_bank_s *bank, int set, int first, int last)
308 str7x_flash_bank_t *str7x_info = bank->driver_priv;
309 target_t *target = str7x_info->target;
315 if (str7x_info->target->state != TARGET_HALTED)
317 return ERROR_TARGET_NOT_HALTED;
320 protect_blocks = 0xFFFFFFFF;
324 for (i = first; i <= last; i++)
325 protect_blocks &= ~(mem_layout[i].reg_offset << i);
329 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
331 cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
332 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
334 cmd = protect_blocks;
335 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
337 cmd = FLASH_SPR|FLASH_WMS;
338 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
340 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
344 retval = str7x_result(bank);
346 if (retval & FLASH_ERER)
347 return ERROR_FLASH_SECTOR_NOT_ERASED;
348 else if (retval & FLASH_WPF)
349 return ERROR_FLASH_OPERATION_FAILED;
354 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
356 str7x_flash_bank_t *str7x_info = bank->driver_priv;
357 target_t *target = str7x_info->target;
358 u32 dwords_remaining = (count / 8);
359 u32 bytes_remaining = (count & 0x00000007);
360 u32 address = bank->base + offset;
361 u32 *wordbuffer = (u32*)buffer;
362 u32 bytes_written = 0;
366 if (str7x_info->target->state != TARGET_HALTED)
368 return ERROR_TARGET_NOT_HALTED;
371 if (offset + count > bank->size)
372 return ERROR_FLASH_DST_OUT_OF_BANK;
374 while (dwords_remaining > 0)
378 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
382 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
385 cmd = wordbuffer[bytes_written/4];
386 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
390 cmd = wordbuffer[bytes_written/4];
391 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, (u8*)&cmd);
394 /* start programming cycle */
395 cmd = FLASH_DWPG|FLASH_WMS;
396 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
398 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
402 retval = str7x_result(bank);
404 if (retval & FLASH_PGER)
405 return ERROR_FLASH_OPERATION_FAILED;
406 else if (retval & FLASH_WPF)
407 return ERROR_FLASH_OPERATION_FAILED;
413 while( bytes_remaining > 0 )
417 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
421 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
424 cmd = buffer[bytes_written];
425 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
427 /* start programming cycle */
428 cmd = FLASH_WPG|FLASH_WMS;
429 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
431 while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
435 retval = str7x_result(bank);
437 if (retval & FLASH_PGER)
438 return ERROR_FLASH_OPERATION_FAILED;
439 else if (retval & FLASH_WPF)
440 return ERROR_FLASH_OPERATION_FAILED;
450 int str7x_probe(struct flash_bank_s *bank)
455 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
460 int str7x_erase_check(struct flash_bank_s *bank)
462 return str7x_blank_check(bank, 0, bank->num_sectors - 1);
465 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size)
467 snprintf(buf, buf_size, "str7x flash driver info" );