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.
 
 
 
 
 
 

723 lines
18 KiB

  1. /*
  2. * Spansion FM4 flash
  3. *
  4. * Copyright (c) 2015 Andreas Färber
  5. *
  6. * Based on S6E2DH_MN709-00013 for S6E2DH/DF/D5/D3 series
  7. * Based on S6E2CC_MN709-00007 for S6E2CC/C5/C4/C3/C2/C1 series
  8. * Based on MB9B560R_MN709-00005 for MB9BFx66/x67/x68 series
  9. * Based on MB9B560L_MN709-00006 for MB9BFx64/x65/x66 series
  10. */
  11. #ifdef HAVE_CONFIG_H
  12. #include "config.h"
  13. #endif
  14. #include "imp.h"
  15. #include <helper/binarybuffer.h>
  16. #include <target/algorithm.h>
  17. #include <target/armv7m.h>
  18. #define FLASH_BASE 0x40000000
  19. #define FASZR (FLASH_BASE + 0x000)
  20. #define DFCTRLR (FLASH_BASE + 0x030)
  21. #define DFCTRLR_DFE (1UL << 0)
  22. #define WDG_BASE 0x40011000
  23. #define WDG_CTL (WDG_BASE + 0x008)
  24. #define WDG_LCK (WDG_BASE + 0xC00)
  25. enum fm4_variant {
  26. mb9bfx64,
  27. mb9bfx65,
  28. mb9bfx66,
  29. mb9bfx67,
  30. mb9bfx68,
  31. s6e2cx8,
  32. s6e2cx9,
  33. s6e2cxa,
  34. s6e2dx,
  35. };
  36. struct fm4_flash_bank {
  37. enum fm4_variant variant;
  38. int macro_nr;
  39. bool probed;
  40. };
  41. static int fm4_disable_hw_watchdog(struct target *target)
  42. {
  43. int retval;
  44. retval = target_write_u32(target, WDG_LCK, 0x1ACCE551);
  45. if (retval != ERROR_OK)
  46. return retval;
  47. retval = target_write_u32(target, WDG_LCK, 0xE5331AAE);
  48. if (retval != ERROR_OK)
  49. return retval;
  50. retval = target_write_u32(target, WDG_CTL, 0);
  51. if (retval != ERROR_OK)
  52. return retval;
  53. return ERROR_OK;
  54. }
  55. static int fm4_enter_flash_cpu_programming_mode(struct target *target)
  56. {
  57. uint32_t u32_value;
  58. int retval;
  59. /* FASZR ASZ = CPU programming mode */
  60. retval = target_write_u32(target, FASZR, 0x00000001);
  61. if (retval != ERROR_OK)
  62. return retval;
  63. retval = target_read_u32(target, FASZR, &u32_value);
  64. if (retval != ERROR_OK)
  65. return retval;
  66. return ERROR_OK;
  67. }
  68. static int fm4_enter_flash_cpu_rom_mode(struct target *target)
  69. {
  70. uint32_t u32_value;
  71. int retval;
  72. /* FASZR ASZ = CPU ROM mode */
  73. retval = target_write_u32(target, FASZR, 0x00000002);
  74. if (retval != ERROR_OK)
  75. return retval;
  76. retval = target_read_u32(target, FASZR, &u32_value);
  77. if (retval != ERROR_OK)
  78. return retval;
  79. return ERROR_OK;
  80. }
  81. static int fm4_flash_erase(struct flash_bank *bank, int first, int last)
  82. {
  83. struct target *target = bank->target;
  84. struct working_area *workarea;
  85. struct reg_param reg_params[4];
  86. struct armv7m_algorithm armv7m_algo;
  87. unsigned i;
  88. int retval, sector;
  89. const uint8_t erase_sector_code[] = {
  90. #include "../../../contrib/loaders/flash/fm4/erase.inc"
  91. };
  92. if (target->state != TARGET_HALTED) {
  93. LOG_WARNING("Cannot communicate... target not halted.");
  94. return ERROR_TARGET_NOT_HALTED;
  95. }
  96. LOG_DEBUG("Spansion FM4 erase sectors %d to %d", first, last);
  97. retval = fm4_disable_hw_watchdog(target);
  98. if (retval != ERROR_OK)
  99. return retval;
  100. retval = fm4_enter_flash_cpu_programming_mode(target);
  101. if (retval != ERROR_OK)
  102. return retval;
  103. retval = target_alloc_working_area(target, sizeof(erase_sector_code),
  104. &workarea);
  105. if (retval != ERROR_OK) {
  106. LOG_ERROR("No working area available.");
  107. retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
  108. goto err_alloc_code;
  109. }
  110. retval = target_write_buffer(target, workarea->address,
  111. sizeof(erase_sector_code), erase_sector_code);
  112. if (retval != ERROR_OK)
  113. goto err_write_code;
  114. armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
  115. armv7m_algo.core_mode = ARM_MODE_THREAD;
  116. init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
  117. init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
  118. init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
  119. init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
  120. for (sector = first; sector <= last; sector++) {
  121. uint32_t addr = bank->base + bank->sectors[sector].offset;
  122. uint32_t result;
  123. buf_set_u32(reg_params[0].value, 0, 32, (addr & ~0xffff) | 0xAA8);
  124. buf_set_u32(reg_params[1].value, 0, 32, (addr & ~0xffff) | 0x554);
  125. buf_set_u32(reg_params[2].value, 0, 32, addr);
  126. retval = target_run_algorithm(target,
  127. 0, NULL,
  128. ARRAY_SIZE(reg_params), reg_params,
  129. workarea->address, 0,
  130. 1000, &armv7m_algo);
  131. if (retval != ERROR_OK) {
  132. LOG_ERROR("Error executing flash sector erase "
  133. "programming algorithm");
  134. retval = ERROR_FLASH_OPERATION_FAILED;
  135. goto err_run;
  136. }
  137. result = buf_get_u32(reg_params[3].value, 0, 32);
  138. if (result == 2) {
  139. LOG_ERROR("Timeout error from flash sector erase programming algorithm");
  140. retval = ERROR_FLASH_OPERATION_FAILED;
  141. goto err_run_ret;
  142. } else if (result != 0) {
  143. LOG_ERROR("Unexpected error %d from flash sector erase programming algorithm", result);
  144. retval = ERROR_FLASH_OPERATION_FAILED;
  145. goto err_run_ret;
  146. } else
  147. retval = ERROR_OK;
  148. bank->sectors[sector].is_erased = 1;
  149. }
  150. err_run_ret:
  151. err_run:
  152. for (i = 0; i < ARRAY_SIZE(reg_params); i++)
  153. destroy_reg_param(&reg_params[i]);
  154. err_write_code:
  155. target_free_working_area(target, workarea);
  156. err_alloc_code:
  157. if (retval != ERROR_OK)
  158. fm4_enter_flash_cpu_rom_mode(target);
  159. else
  160. retval = fm4_enter_flash_cpu_rom_mode(target);
  161. return retval;
  162. }
  163. static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
  164. uint32_t offset, uint32_t byte_count)
  165. {
  166. struct target *target = bank->target;
  167. struct working_area *code_workarea, *data_workarea;
  168. struct reg_param reg_params[6];
  169. struct armv7m_algorithm armv7m_algo;
  170. uint32_t halfword_count = DIV_ROUND_UP(byte_count, 2);
  171. uint32_t result;
  172. unsigned i;
  173. int retval;
  174. const uint8_t write_block_code[] = {
  175. #include "../../../contrib/loaders/flash/fm4/write.inc"
  176. };
  177. LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32 " (%" PRId32 " bytes)",
  178. offset, byte_count);
  179. if (offset & 0x1) {
  180. LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment",
  181. offset);
  182. return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
  183. }
  184. if (byte_count & 0x1) {
  185. LOG_WARNING("length %" PRId32 " is not 2-byte aligned, rounding up",
  186. byte_count);
  187. }
  188. if (target->state != TARGET_HALTED) {
  189. LOG_WARNING("Cannot communicate... target not halted.");
  190. return ERROR_TARGET_NOT_HALTED;
  191. }
  192. retval = fm4_disable_hw_watchdog(target);
  193. if (retval != ERROR_OK)
  194. return retval;
  195. retval = target_alloc_working_area(target, sizeof(write_block_code),
  196. &code_workarea);
  197. if (retval != ERROR_OK) {
  198. LOG_ERROR("No working area available for write code.");
  199. return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
  200. }
  201. retval = target_write_buffer(target, code_workarea->address,
  202. sizeof(write_block_code), write_block_code);
  203. if (retval != ERROR_OK)
  204. goto err_write_code;
  205. retval = target_alloc_working_area(target,
  206. MIN(halfword_count * 2, target_get_working_area_avail(target)),
  207. &data_workarea);
  208. if (retval != ERROR_OK) {
  209. LOG_ERROR("No working area available for write data.");
  210. retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
  211. goto err_alloc_data;
  212. }
  213. armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
  214. armv7m_algo.core_mode = ARM_MODE_THREAD;
  215. init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
  216. init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
  217. init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
  218. init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
  219. init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
  220. init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);
  221. retval = fm4_enter_flash_cpu_programming_mode(target);
  222. if (retval != ERROR_OK)
  223. goto err_flash_mode;
  224. while (byte_count > 0) {
  225. uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2);
  226. uint32_t addr = bank->base + offset;
  227. LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR,
  228. MIN(halfwords * 2, byte_count), data_workarea->address);
  229. retval = target_write_buffer(target, data_workarea->address,
  230. MIN(halfwords * 2, byte_count), buffer);
  231. if (retval != ERROR_OK) {
  232. LOG_ERROR("Error writing data buffer");
  233. retval = ERROR_FLASH_OPERATION_FAILED;
  234. goto err_write_data;
  235. }
  236. LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRId32 "x)",
  237. addr, addr + halfwords * 2 - 1, halfwords);
  238. buf_set_u32(reg_params[0].value, 0, 32, (addr & ~0xffff) | 0xAA8);
  239. buf_set_u32(reg_params[1].value, 0, 32, (addr & ~0xffff) | 0x554);
  240. buf_set_u32(reg_params[2].value, 0, 32, addr);
  241. buf_set_u32(reg_params[3].value, 0, 32, data_workarea->address);
  242. buf_set_u32(reg_params[4].value, 0, 32, halfwords);
  243. retval = target_run_algorithm(target,
  244. 0, NULL,
  245. ARRAY_SIZE(reg_params), reg_params,
  246. code_workarea->address, 0,
  247. 5 * 60 * 1000, &armv7m_algo);
  248. if (retval != ERROR_OK) {
  249. LOG_ERROR("Error executing flash sector erase "
  250. "programming algorithm");
  251. retval = ERROR_FLASH_OPERATION_FAILED;
  252. goto err_run;
  253. }
  254. result = buf_get_u32(reg_params[5].value, 0, 32);
  255. if (result == 2) {
  256. LOG_ERROR("Timeout error from flash write "
  257. "programming algorithm");
  258. retval = ERROR_FLASH_OPERATION_FAILED;
  259. goto err_run_ret;
  260. } else if (result != 0) {
  261. LOG_ERROR("Unexpected error %d from flash write "
  262. "programming algorithm", result);
  263. retval = ERROR_FLASH_OPERATION_FAILED;
  264. goto err_run_ret;
  265. } else
  266. retval = ERROR_OK;
  267. halfword_count -= halfwords;
  268. offset += halfwords * 2;
  269. buffer += halfwords * 2;
  270. byte_count -= MIN(halfwords * 2, byte_count);
  271. }
  272. err_run_ret:
  273. err_run:
  274. err_write_data:
  275. retval = fm4_enter_flash_cpu_rom_mode(target);
  276. err_flash_mode:
  277. for (i = 0; i < ARRAY_SIZE(reg_params); i++)
  278. destroy_reg_param(&reg_params[i]);
  279. target_free_working_area(target, data_workarea);
  280. err_alloc_data:
  281. err_write_code:
  282. target_free_working_area(target, code_workarea);
  283. return retval;
  284. }
  285. static int mb9bf_probe(struct flash_bank *bank)
  286. {
  287. struct fm4_flash_bank *fm4_bank = bank->driver_priv;
  288. uint32_t flash_addr = bank->base;
  289. int i;
  290. switch (fm4_bank->variant) {
  291. case mb9bfx64:
  292. bank->num_sectors = 8;
  293. break;
  294. case mb9bfx65:
  295. bank->num_sectors = 10;
  296. break;
  297. case mb9bfx66:
  298. bank->num_sectors = 12;
  299. break;
  300. case mb9bfx67:
  301. bank->num_sectors = 16;
  302. break;
  303. case mb9bfx68:
  304. bank->num_sectors = 20;
  305. break;
  306. default:
  307. return ERROR_FLASH_OPER_UNSUPPORTED;
  308. }
  309. LOG_DEBUG("%d sectors", bank->num_sectors);
  310. bank->sectors = calloc(bank->num_sectors,
  311. sizeof(struct flash_sector));
  312. for (i = 0; i < bank->num_sectors; i++) {
  313. if (i < 4)
  314. bank->sectors[i].size = 8 * 1024;
  315. else if (i == 4)
  316. bank->sectors[i].size = 32 * 1024;
  317. else
  318. bank->sectors[i].size = 64 * 1024;
  319. bank->sectors[i].offset = flash_addr - bank->base;
  320. bank->sectors[i].is_erased = -1;
  321. bank->sectors[i].is_protected = -1;
  322. bank->size += bank->sectors[i].size;
  323. flash_addr += bank->sectors[i].size;
  324. }
  325. return ERROR_OK;
  326. }
  327. static void s6e2cc_init_sector(struct flash_sector *sector, int sa)
  328. {
  329. if (sa < 8)
  330. sector->size = 8 * 1024;
  331. else if (sa == 8)
  332. sector->size = 32 * 1024;
  333. else
  334. sector->size = 64 * 1024;
  335. sector->is_erased = -1;
  336. sector->is_protected = -1;
  337. }
  338. static int s6e2cc_probe(struct flash_bank *bank)
  339. {
  340. struct target *target = bank->target;
  341. struct fm4_flash_bank *fm4_bank = bank->driver_priv;
  342. uint32_t u32_value;
  343. uint32_t flash_addr = bank->base;
  344. int i, retval, num_sectors, num_extra_sectors;
  345. retval = target_read_u32(target, DFCTRLR, &u32_value);
  346. if (retval != ERROR_OK)
  347. return retval;
  348. if (u32_value & DFCTRLR_DFE) {
  349. LOG_WARNING("Dual Flash mode is not implemented.");
  350. return ERROR_FLASH_OPER_UNSUPPORTED;
  351. }
  352. switch (fm4_bank->variant) {
  353. case s6e2cx8:
  354. num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 0;
  355. break;
  356. case s6e2cx9:
  357. num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 12;
  358. break;
  359. case s6e2cxa:
  360. num_sectors = 20;
  361. break;
  362. default:
  363. return ERROR_FLASH_OPER_UNSUPPORTED;
  364. }
  365. num_extra_sectors = (fm4_bank->macro_nr == 0) ? 1 : 4;
  366. bank->num_sectors = num_sectors + num_extra_sectors;
  367. LOG_DEBUG("%d sectors", bank->num_sectors);
  368. bank->sectors = calloc(bank->num_sectors,
  369. sizeof(struct flash_sector));
  370. for (i = 0; i < num_sectors; i++) {
  371. int sa = 4 + i;
  372. bank->sectors[i].offset = flash_addr - bank->base;
  373. s6e2cc_init_sector(&bank->sectors[i], sa);
  374. bank->size += bank->sectors[i].size;
  375. flash_addr += bank->sectors[i].size;
  376. }
  377. flash_addr = (fm4_bank->macro_nr == 0) ? 0x00406000 : 0x00408000;
  378. for (; i < bank->num_sectors; i++) {
  379. int sa = 4 - num_extra_sectors + (i - num_sectors);
  380. bank->sectors[i].offset = flash_addr - bank->base;
  381. s6e2cc_init_sector(&bank->sectors[i], sa);
  382. /*
  383. * Don't increase bank->size for these sectors
  384. * to avoid an overlap between Flash Macros #0 and #1.
  385. */
  386. flash_addr += bank->sectors[i].size;
  387. }
  388. return ERROR_OK;
  389. }
  390. static int s6e2dh_probe(struct flash_bank *bank)
  391. {
  392. uint32_t flash_addr = bank->base;
  393. int i;
  394. bank->num_sectors = 10;
  395. bank->sectors = calloc(bank->num_sectors,
  396. sizeof(struct flash_sector));
  397. for (i = 0; i < bank->num_sectors; i++) {
  398. if (i < 4)
  399. bank->sectors[i].size = 8 * 1024;
  400. else if (i == 4)
  401. bank->sectors[i].size = 32 * 1024;
  402. else
  403. bank->sectors[i].size = 64 * 1024;
  404. bank->sectors[i].offset = flash_addr - bank->base;
  405. bank->sectors[i].is_erased = -1;
  406. bank->sectors[i].is_protected = -1;
  407. bank->size += bank->sectors[i].size;
  408. flash_addr += bank->sectors[i].size;
  409. }
  410. return ERROR_OK;
  411. }
  412. static int fm4_probe(struct flash_bank *bank)
  413. {
  414. struct fm4_flash_bank *fm4_bank = bank->driver_priv;
  415. int retval;
  416. if (fm4_bank->probed)
  417. return ERROR_OK;
  418. if (bank->target->state != TARGET_HALTED) {
  419. LOG_WARNING("Cannot communicate... target not halted.");
  420. return ERROR_TARGET_NOT_HALTED;
  421. }
  422. switch (fm4_bank->variant) {
  423. case mb9bfx64:
  424. case mb9bfx65:
  425. case mb9bfx66:
  426. case mb9bfx67:
  427. case mb9bfx68:
  428. retval = mb9bf_probe(bank);
  429. break;
  430. case s6e2cx8:
  431. case s6e2cx9:
  432. case s6e2cxa:
  433. retval = s6e2cc_probe(bank);
  434. break;
  435. case s6e2dx:
  436. retval = s6e2dh_probe(bank);
  437. break;
  438. default:
  439. return ERROR_FLASH_OPER_UNSUPPORTED;
  440. }
  441. if (retval != ERROR_OK)
  442. return retval;
  443. fm4_bank->probed = true;
  444. return ERROR_OK;
  445. }
  446. static int fm4_auto_probe(struct flash_bank *bank)
  447. {
  448. struct fm4_flash_bank *fm4_bank = bank->driver_priv;
  449. if (fm4_bank->probed)
  450. return ERROR_OK;
  451. return fm4_probe(bank);
  452. }
  453. static int fm4_protect_check(struct flash_bank *bank)
  454. {
  455. return ERROR_OK;
  456. }
  457. static int fm4_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
  458. {
  459. struct fm4_flash_bank *fm4_bank = bank->driver_priv;
  460. const char *name;
  461. if (bank->target->state != TARGET_HALTED) {
  462. LOG_WARNING("Cannot communicate... target not halted.");
  463. return ERROR_TARGET_NOT_HALTED;
  464. }
  465. switch (fm4_bank->variant) {
  466. case mb9bfx64:
  467. name = "MB9BFx64";
  468. break;
  469. case mb9bfx65:
  470. name = "MB9BFx65";
  471. break;
  472. case mb9bfx66:
  473. name = "MB9BFx66";
  474. break;
  475. case mb9bfx67:
  476. name = "MB9BFx67";
  477. break;
  478. case mb9bfx68:
  479. name = "MB9BFx68";
  480. break;
  481. case s6e2cx8:
  482. name = "S6E2Cx8";
  483. break;
  484. case s6e2cx9:
  485. name = "S6E2Cx9";
  486. break;
  487. case s6e2cxa:
  488. name = "S6E2CxA";
  489. break;
  490. case s6e2dx:
  491. name = "S6E2Dx";
  492. break;
  493. default:
  494. name = "unknown";
  495. break;
  496. }
  497. switch (fm4_bank->variant) {
  498. case s6e2cx8:
  499. case s6e2cx9:
  500. case s6e2cxa:
  501. snprintf(buf, buf_size, "%s MainFlash Macro #%i",
  502. name, fm4_bank->macro_nr);
  503. break;
  504. default:
  505. snprintf(buf, buf_size, "%s MainFlash", name);
  506. break;
  507. }
  508. return ERROR_OK;
  509. }
  510. static bool fm4_name_match(const char *s, const char *pattern)
  511. {
  512. int i = 0;
  513. while (s[i]) {
  514. /* If the match string is shorter, ignore excess */
  515. if (!pattern[i])
  516. return true;
  517. /* Use x as wildcard */
  518. if (pattern[i] != 'x' && tolower(s[i]) != tolower(pattern[i]))
  519. return false;
  520. i++;
  521. }
  522. return true;
  523. }
  524. static int mb9bf_bank_setup(struct flash_bank *bank, const char *variant)
  525. {
  526. struct fm4_flash_bank *fm4_bank = bank->driver_priv;
  527. if (fm4_name_match(variant, "MB9BFx64")) {
  528. fm4_bank->variant = mb9bfx64;
  529. } else if (fm4_name_match(variant, "MB9BFx65")) {
  530. fm4_bank->variant = mb9bfx65;
  531. } else if (fm4_name_match(variant, "MB9BFx66")) {
  532. fm4_bank->variant = mb9bfx66;
  533. } else if (fm4_name_match(variant, "MB9BFx67")) {
  534. fm4_bank->variant = mb9bfx67;
  535. } else if (fm4_name_match(variant, "MB9BFx68")) {
  536. fm4_bank->variant = mb9bfx68;
  537. } else {
  538. LOG_WARNING("MB9BF variant %s not recognized.", variant);
  539. return ERROR_FLASH_OPER_UNSUPPORTED;
  540. }
  541. return ERROR_OK;
  542. }
  543. static int s6e2cc_bank_setup(struct flash_bank *bank, const char *variant)
  544. {
  545. struct fm4_flash_bank *fm4_bank = bank->driver_priv;
  546. if (fm4_name_match(variant, "S6E2Cx8")) {
  547. fm4_bank->variant = s6e2cx8;
  548. } else if (fm4_name_match(variant, "S6E2Cx9")) {
  549. fm4_bank->variant = s6e2cx9;
  550. } else if (fm4_name_match(variant, "S6E2CxA")) {
  551. fm4_bank->variant = s6e2cxa;
  552. } else {
  553. LOG_WARNING("S6E2CC variant %s not recognized.", variant);
  554. return ERROR_FLASH_OPER_UNSUPPORTED;
  555. }
  556. return ERROR_OK;
  557. }
  558. FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command)
  559. {
  560. struct fm4_flash_bank *fm4_bank;
  561. const char *variant;
  562. int ret;
  563. if (CMD_ARGC < 7)
  564. return ERROR_COMMAND_SYNTAX_ERROR;
  565. variant = CMD_ARGV[6];
  566. fm4_bank = malloc(sizeof(struct fm4_flash_bank));
  567. if (!fm4_bank)
  568. return ERROR_FLASH_OPERATION_FAILED;
  569. fm4_bank->probed = false;
  570. fm4_bank->macro_nr = (bank->base == 0x00000000) ? 0 : 1;
  571. bank->driver_priv = fm4_bank;
  572. if (fm4_name_match(variant, "MB9BF"))
  573. ret = mb9bf_bank_setup(bank, variant);
  574. else if (fm4_name_match(variant, "S6E2Cx"))
  575. ret = s6e2cc_bank_setup(bank, variant);
  576. else if (fm4_name_match(variant, "S6E2Dx")) {
  577. fm4_bank->variant = s6e2dx;
  578. ret = ERROR_OK;
  579. } else {
  580. LOG_WARNING("Family %s not recognized.", variant);
  581. ret = ERROR_FLASH_OPER_UNSUPPORTED;
  582. }
  583. if (ret != ERROR_OK)
  584. free(fm4_bank);
  585. return ret;
  586. }
  587. static const struct command_registration fm4_exec_command_handlers[] = {
  588. COMMAND_REGISTRATION_DONE
  589. };
  590. static const struct command_registration fm4_command_handlers[] = {
  591. {
  592. .name = "fm4",
  593. .mode = COMMAND_ANY,
  594. .help = "fm4 flash command group",
  595. .usage = "",
  596. .chain = fm4_exec_command_handlers,
  597. },
  598. COMMAND_REGISTRATION_DONE
  599. };
  600. struct flash_driver fm4_flash = {
  601. .name = "fm4",
  602. .commands = fm4_command_handlers,
  603. .flash_bank_command = fm4_flash_bank_command,
  604. .info = fm4_get_info_command,
  605. .probe = fm4_probe,
  606. .auto_probe = fm4_auto_probe,
  607. .protect_check = fm4_protect_check,
  608. .read = default_flash_read,
  609. .erase = fm4_flash_erase,
  610. .erase_check = default_flash_blank_check,
  611. .write = fm4_flash_write,
  612. };