You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

475 lines
12 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2005 by Dominic Rath *
  3. * Dominic.Rath@gmx.de *
  4. * *
  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. *
  9. * *
  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. *
  14. * *
  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. ***************************************************************************/
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "replacements.h"
  24. #include "str7x.h"
  25. #include "flash.h"
  26. #include "target.h"
  27. #include "log.h"
  28. #include "armv4_5.h"
  29. #include "algorithm.h"
  30. #include "binarybuffer.h"
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <unistd.h>
  34. str7x_mem_layout_t mem_layout[] = {
  35. {0x00000000, 0x02000, 0x01},
  36. {0x00002000, 0x02000, 0x01},
  37. {0x00004000, 0x02000, 0x01},
  38. {0x00006000, 0x02000, 0x01},
  39. {0x00008000, 0x08000, 0x01},
  40. {0x00010000, 0x10000, 0x01},
  41. {0x00020000, 0x10000, 0x01},
  42. {0x00030000, 0x10000, 0x01},
  43. {0x000C0000, 0x02000, 0x100},
  44. {0x000C2000, 0x02000, 0x100},
  45. {0,0},
  46. };
  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);
  57. flash_driver_t str7x_flash =
  58. {
  59. .name = "str7x",
  60. .register_commands = str7x_register_commands,
  61. .flash_bank_command = str7x_flash_bank_command,
  62. .erase = str7x_erase,
  63. .protect = str7x_protect,
  64. .write = str7x_write,
  65. .probe = str7x_probe,
  66. .erase_check = str7x_erase_check,
  67. .protect_check = str7x_protect_check,
  68. .info = str7x_info
  69. };
  70. int str7x_register_commands(struct command_context_s *cmd_ctx)
  71. {
  72. return ERROR_OK;
  73. }
  74. int str7x_get_flash_adr(struct flash_bank_s *bank, u32 reg)
  75. {
  76. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  77. return (str7x_info->flash_base|reg);
  78. }
  79. int str7x_build_block_list(struct flash_bank_s *bank)
  80. {
  81. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  82. int i;
  83. int num_sectors;
  84. switch (bank->size)
  85. {
  86. case 16 * 1024:
  87. num_sectors = 2;
  88. break;
  89. case 64 * 1024:
  90. num_sectors = 5;
  91. break;
  92. case 128 * 1024:
  93. num_sectors = 6;
  94. break;
  95. case 256 * 1024:
  96. num_sectors = 8;
  97. break;
  98. default:
  99. ERROR("BUG: unknown bank->size encountered");
  100. exit(-1);
  101. }
  102. if( str7x_info->bank1 == 1 )
  103. {
  104. num_sectors += 2;
  105. }
  106. bank->num_sectors = num_sectors;
  107. bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
  108. for (i = 0; i < num_sectors; i++)
  109. {
  110. bank->sectors[i].offset = mem_layout[i].sector_start;
  111. bank->sectors[i].size = mem_layout[i].sector_size;
  112. bank->sectors[i].is_erased = -1;
  113. bank->sectors[i].is_protected = 1;
  114. }
  115. return ERROR_OK;
  116. }
  117. /* flash bank str7x <base> <size> 0 0 <str71_variant> <target#>
  118. */
  119. int str7x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
  120. {
  121. str7x_flash_bank_t *str7x_info;
  122. if (argc < 7)
  123. {
  124. WARNING("incomplete flash_bank str7x configuration");
  125. return ERROR_FLASH_BANK_INVALID;
  126. }
  127. str7x_info = malloc(sizeof(str7x_flash_bank_t));
  128. bank->driver_priv = str7x_info;
  129. if (strcmp(args[5], "STR71x") == 0)
  130. {
  131. str7x_info->bank1 = 1;
  132. str7x_info->flash_base = 0x40000000;
  133. }
  134. else if (strcmp(args[5], "STR73x") == 0)
  135. {
  136. str7x_info->bank1 = 0;
  137. str7x_info->flash_base = 0x80000000;
  138. }
  139. else
  140. {
  141. ERROR("unknown STR7x variant");
  142. free(str7x_info);
  143. return ERROR_FLASH_BANK_INVALID;
  144. }
  145. str7x_info->target = get_target_by_num(strtoul(args[6], NULL, 0));
  146. if (!str7x_info->target)
  147. {
  148. ERROR("no target '%s' configured", args[6]);
  149. exit(-1);
  150. }
  151. str7x_build_block_list(bank);
  152. return ERROR_OK;
  153. }
  154. u32 str7x_status(struct flash_bank_s *bank)
  155. {
  156. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  157. target_t *target = str7x_info->target;
  158. u32 retval;
  159. target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&retval);
  160. return retval;
  161. }
  162. u32 str7x_result(struct flash_bank_s *bank)
  163. {
  164. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  165. target_t *target = str7x_info->target;
  166. u32 retval;
  167. target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_ER), 4, 1, (u8*)&retval);
  168. return retval;
  169. }
  170. int str7x_blank_check(struct flash_bank_s *bank, int first, int last)
  171. {
  172. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  173. target_t *target = str7x_info->target;
  174. u8 *buffer;
  175. int i;
  176. int nBytes;
  177. if ((first < 0) || (last > bank->num_sectors))
  178. return ERROR_FLASH_SECTOR_INVALID;
  179. if (str7x_info->target->state != TARGET_HALTED)
  180. {
  181. return ERROR_TARGET_NOT_HALTED;
  182. }
  183. buffer = malloc(256);
  184. for (i = first; i <= last; i++)
  185. {
  186. bank->sectors[i].is_erased = 1;
  187. target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, 256/4, buffer);
  188. for (nBytes = 0; nBytes < 256; nBytes++)
  189. {
  190. if (buffer[nBytes] != 0xFF)
  191. {
  192. bank->sectors[i].is_erased = 0;
  193. break;
  194. }
  195. }
  196. }
  197. free(buffer);
  198. return ERROR_OK;
  199. }
  200. int str7x_protect_check(struct flash_bank_s *bank)
  201. {
  202. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  203. target_t *target = str7x_info->target;
  204. int i;
  205. int retval;
  206. if (str7x_info->target->state != TARGET_HALTED)
  207. {
  208. return ERROR_TARGET_NOT_HALTED;
  209. }
  210. target->type->read_memory(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), 4, 1, (u8*)&retval);
  211. for (i = 0; i < bank->num_sectors; i++)
  212. {
  213. if (retval & (mem_layout[i].reg_offset << i))
  214. bank->sectors[i].is_protected = 0;
  215. else
  216. bank->sectors[i].is_protected = 1;
  217. }
  218. return ERROR_OK;
  219. }
  220. int str7x_erase(struct flash_bank_s *bank, int first, int last)
  221. {
  222. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  223. target_t *target = str7x_info->target;
  224. int i;
  225. u32 cmd;
  226. u32 retval;
  227. u32 erase_blocks;
  228. if (str7x_info->target->state != TARGET_HALTED)
  229. {
  230. return ERROR_TARGET_NOT_HALTED;
  231. }
  232. erase_blocks = 0;
  233. for (i = first; i <= last; i++)
  234. erase_blocks |= (mem_layout[i].reg_offset << i);
  235. cmd = FLASH_SER;
  236. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
  237. cmd = erase_blocks;
  238. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR1), 4, 1, (u8*)&cmd);
  239. cmd = FLASH_SER|FLASH_WMS;
  240. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
  241. while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
  242. usleep(1000);
  243. }
  244. retval = str7x_result(bank);
  245. if (retval & FLASH_ERER)
  246. return ERROR_FLASH_SECTOR_NOT_ERASED;
  247. else if (retval & FLASH_WPF)
  248. return ERROR_FLASH_OPERATION_FAILED;
  249. for (i = first; i <= last; i++)
  250. bank->sectors[i].is_erased = 1;
  251. return ERROR_OK;
  252. }
  253. int str7x_protect(struct flash_bank_s *bank, int set, int first, int last)
  254. {
  255. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  256. target_t *target = str7x_info->target;
  257. int i;
  258. u32 cmd;
  259. u32 retval;
  260. u32 protect_blocks;
  261. if (str7x_info->target->state != TARGET_HALTED)
  262. {
  263. return ERROR_TARGET_NOT_HALTED;
  264. }
  265. protect_blocks = 0xFFFFFFFF;
  266. if( set )
  267. {
  268. for (i = first; i <= last; i++)
  269. protect_blocks &= ~(mem_layout[i].reg_offset << i);
  270. }
  271. cmd = FLASH_SPR;
  272. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
  273. cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
  274. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
  275. cmd = protect_blocks;
  276. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
  277. cmd = FLASH_SPR|FLASH_WMS;
  278. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
  279. while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
  280. usleep(1000);
  281. }
  282. retval = str7x_result(bank);
  283. if (retval & FLASH_ERER)
  284. return ERROR_FLASH_SECTOR_NOT_ERASED;
  285. else if (retval & FLASH_WPF)
  286. return ERROR_FLASH_OPERATION_FAILED;
  287. return ERROR_OK;
  288. }
  289. int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
  290. {
  291. str7x_flash_bank_t *str7x_info = bank->driver_priv;
  292. target_t *target = str7x_info->target;
  293. u32 dwords_remaining = (count / 8);
  294. u32 bytes_remaining = (count & 0x00000007);
  295. u32 address = bank->base + offset;
  296. u32 *wordbuffer = (u32*)buffer;
  297. u32 bytes_written = 0;
  298. u32 cmd;
  299. u32 retval;
  300. if (str7x_info->target->state != TARGET_HALTED)
  301. {
  302. return ERROR_TARGET_NOT_HALTED;
  303. }
  304. if (offset + count > bank->size)
  305. return ERROR_FLASH_DST_OUT_OF_BANK;
  306. while (dwords_remaining > 0)
  307. {
  308. // command
  309. cmd = FLASH_DWPG;
  310. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
  311. // address
  312. cmd = address;
  313. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
  314. // data byte 1
  315. cmd = wordbuffer[bytes_written/4];
  316. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
  317. bytes_written += 4;
  318. // data byte 2
  319. cmd = wordbuffer[bytes_written/4];
  320. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, (u8*)&cmd);
  321. bytes_written += 4;
  322. /* start programming cycle */
  323. cmd = FLASH_DWPG|FLASH_WMS;
  324. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
  325. while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
  326. usleep(1000);
  327. }
  328. retval = str7x_result(bank);
  329. if (retval & FLASH_PGER)
  330. return ERROR_FLASH_OPERATION_FAILED;
  331. else if (retval & FLASH_WPF)
  332. return ERROR_FLASH_OPERATION_FAILED;
  333. dwords_remaining--;
  334. address += 8;
  335. }
  336. while( bytes_remaining > 0 )
  337. {
  338. // command
  339. cmd = FLASH_WPG;
  340. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
  341. // address
  342. cmd = address;
  343. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_AR), 4, 1, (u8*)&cmd);
  344. // data byte
  345. cmd = buffer[bytes_written];
  346. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, (u8*)&cmd);
  347. /* start programming cycle */
  348. cmd = FLASH_WPG|FLASH_WMS;
  349. target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_CR0), 4, 1, (u8*)&cmd);
  350. while (((retval = str7x_status(bank)) & (FLASH_BSYA1|FLASH_BSYA2))){
  351. usleep(1000);
  352. }
  353. retval = str7x_result(bank);
  354. if (retval & FLASH_PGER)
  355. return ERROR_FLASH_OPERATION_FAILED;
  356. else if (retval & FLASH_WPF)
  357. return ERROR_FLASH_OPERATION_FAILED;
  358. address++;
  359. bytes_remaining--;
  360. bytes_written++;
  361. }
  362. return ERROR_OK;
  363. }
  364. int str7x_probe(struct flash_bank_s *bank)
  365. {
  366. return ERROR_OK;
  367. }
  368. int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
  369. {
  370. return ERROR_OK;
  371. }
  372. int str7x_erase_check(struct flash_bank_s *bank)
  373. {
  374. return str7x_blank_check(bank, 0, bank->num_sectors - 1);
  375. }
  376. int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size)
  377. {
  378. snprintf(buf, buf_size, "str7x flash driver info" );
  379. return ERROR_OK;
  380. }