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.

282 lines
8.5KB

  1. /***************************************************************************
  2. * Copyright (C) 2011 by Rodrigo L. Rosa *
  3. * rodrigorosa.LG@gmail.com *
  4. * *
  5. * Based on a file written by: *
  6. * Kevin McGuire *
  7. * Marcel Wijlaars *
  8. * Michael Ashton *
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. * This program is distributed in the hope that it will be useful, *
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  18. * GNU General Public License for more details. *
  19. * *
  20. * You should have received a copy of the GNU General Public License *
  21. * along with this program; if not, write to the *
  22. * Free Software Foundation, Inc., *
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
  24. ***************************************************************************/
  25. /**
  26. * @file dsp5680xx_flash.c
  27. * @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com>
  28. * @date Thu Jun 9 18:21:58 2011
  29. *
  30. * @brief This file implements the basic functions to run flashing commands
  31. * from the TCL interface.
  32. * It allows the user to flash the Freescale 5680xx DSP.
  33. *
  34. *
  35. */
  36. #ifdef HAVE_CONFIG_H
  37. #include "config.h"
  38. #endif
  39. #include "imp.h"
  40. #include <helper/binarybuffer.h>
  41. #include <helper/time_support.h>
  42. #include <target/algorithm.h>
  43. #include <target/dsp5680xx.h>
  44. static int dsp5680xx_build_sector_list(struct flash_bank *bank)
  45. {
  46. uint32_t offset = HFM_FLASH_BASE_ADDR;
  47. bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
  48. int i;
  49. for (i = 0; i < bank->num_sectors; ++i) {
  50. bank->sectors[i].offset = i * HFM_SECTOR_SIZE;
  51. bank->sectors[i].size = HFM_SECTOR_SIZE;
  52. offset += bank->sectors[i].size;
  53. bank->sectors[i].is_erased = -1;
  54. bank->sectors[i].is_protected = -1;
  55. }
  56. LOG_USER("%s not tested yet.", __func__);
  57. return ERROR_OK;
  58. }
  59. /* flash bank dsp5680xx 0 0 0 0 <target#> */
  60. FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command)
  61. {
  62. bank->base = HFM_FLASH_BASE_ADDR;
  63. bank->size = HFM_SIZE_BYTES; /* top 4k not accessible */
  64. bank->num_sectors = HFM_SECTOR_COUNT;
  65. dsp5680xx_build_sector_list(bank);
  66. return ERROR_OK;
  67. }
  68. /**
  69. * A memory mapped register (PROT) holds information regarding sector protection.
  70. * Protection refers to undesired core access.
  71. * The value in this register is loaded from flash upon reset.
  72. *
  73. * @param bank
  74. *
  75. * @return
  76. */
  77. static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
  78. {
  79. int retval = ERROR_OK;
  80. uint16_t protected = 0;
  81. retval = dsp5680xx_f_protect_check(bank->target, &protected);
  82. if (retval != ERROR_OK) {
  83. for (int i = 0; i < HFM_SECTOR_COUNT; i++)
  84. bank->sectors[i].is_protected = -1;
  85. return ERROR_OK;
  86. }
  87. for (int i = 0; i < HFM_SECTOR_COUNT / 2; i++) {
  88. if (protected & 1) {
  89. bank->sectors[2 * i].is_protected = 1;
  90. bank->sectors[2 * i + 1].is_protected = 1;
  91. } else {
  92. bank->sectors[2 * i].is_protected = 0;
  93. bank->sectors[2 * i + 1].is_protected = 0;
  94. }
  95. protected = (protected >> 1);
  96. }
  97. return retval;
  98. }
  99. /**
  100. * Protection funcionality is not implemented.
  101. * The current implementation applies/removes security on the chip.
  102. * The chip is effectively secured/unsecured after the first reset
  103. * following the execution of this function.
  104. *
  105. * @param bank
  106. * @param set Apply or remove security on the chip.
  107. * @param first This parameter is ignored.
  108. * @param last This parameter is ignored.
  109. *
  110. * @return
  111. */
  112. static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
  113. int last)
  114. {
  115. /**
  116. * This applies security to flash module after next reset, it does
  117. * not actually apply protection (protection refers to undesired access from the core)
  118. */
  119. int retval;
  120. if (set)
  121. retval = dsp5680xx_f_lock(bank->target);
  122. else {
  123. retval = dsp5680xx_f_unlock(bank->target);
  124. if (retval == ERROR_OK) {
  125. /* mark all as erased */
  126. for (int i = 0; i <= (HFM_SECTOR_COUNT - 1); i++)
  127. /* FM does not recognize it as erased if erased via JTAG. */
  128. bank->sectors[i].is_erased = 1;
  129. }
  130. }
  131. return retval;
  132. }
  133. /**
  134. * The dsp5680xx use word addressing. The "/2" that appear in the following code
  135. * are a workaround for the fact that OpenOCD uses byte addressing.
  136. *
  137. * @param bank
  138. * @param buffer Data to write to flash.
  139. * @param offset
  140. * @param count In bytes (2 bytes per address).
  141. *
  142. * @return
  143. */
  144. static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t * buffer,
  145. uint32_t offset, uint32_t count)
  146. {
  147. int retval;
  148. if ((offset + count / 2) > bank->size) {
  149. LOG_ERROR("%s: Flash bank cannot fit data.", __func__);
  150. return ERROR_FAIL;
  151. }
  152. if (offset % 2) {
  153. /**
  154. * Writing to odd addresses not supported.
  155. * This chip uses word addressing, Openocd only supports byte addressing.
  156. * The workaround results in disabling writing to odd byte addresses
  157. */
  158. LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__);
  159. return ERROR_FAIL;
  160. }
  161. retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0);
  162. uint32_t addr_word;
  163. for (addr_word = bank->base + offset / 2; addr_word < count / 2;
  164. addr_word += (HFM_SECTOR_SIZE / 2)) {
  165. if (retval == ERROR_OK)
  166. bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0;
  167. else
  168. bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1;
  169. }
  170. return retval;
  171. }
  172. static int dsp5680xx_probe(struct flash_bank *bank)
  173. {
  174. LOG_DEBUG("%s not implemented", __func__);
  175. return ERROR_OK;
  176. }
  177. static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf,
  178. int buf_size)
  179. {
  180. snprintf(buf, buf_size,
  181. "\ndsp5680xx flash driver info:\n - See comments in code.");
  182. return ERROR_OK;
  183. }
  184. /**
  185. * The flash module (FM) on the dsp5680xx supports both individual sector
  186. * and mass erase of the flash memory.
  187. * If this function is called with @first == @last == 0 or if @first is the
  188. * first sector (#0) and @last is the last sector then the mass erase command
  189. * is executed (much faster than erasing each sector individually).
  190. *
  191. * @param bank
  192. * @param first
  193. * @param last
  194. *
  195. * @return
  196. */
  197. static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last)
  198. {
  199. int retval;
  200. retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
  201. if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
  202. last = HFM_SECTOR_COUNT - 1;
  203. if (retval == ERROR_OK)
  204. for (int i = first; i <= last; i++)
  205. bank->sectors[i].is_erased = 1;
  206. else
  207. /**
  208. * If an error occurred unknown status
  209. *is set even though some sector could have been correctly erased.
  210. */
  211. for (int i = first; i <= last; i++)
  212. bank->sectors[i].is_erased = -1;
  213. return retval;
  214. }
  215. /**
  216. * The flash module (FM) on the dsp5680xx support a blank check function.
  217. * This function executes the FM's blank check functionality on each and every sector.
  218. *
  219. * @param bank
  220. *
  221. * @return
  222. */
  223. static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
  224. {
  225. int retval = ERROR_OK;
  226. uint8_t erased = 0;
  227. uint32_t i;
  228. for (i = 0; i < HFM_SECTOR_COUNT; i++) {
  229. if (bank->sectors[i].is_erased == -1) {
  230. retval = dsp5680xx_f_erase_check(bank->target, &erased, i);
  231. if (retval != ERROR_OK) {
  232. bank->sectors[i].is_erased = -1;
  233. } else {
  234. if (erased)
  235. bank->sectors[i].is_erased = 1;
  236. else
  237. bank->sectors[i].is_erased = 0;
  238. }
  239. }
  240. }
  241. return retval;
  242. }
  243. struct flash_driver dsp5680xx_flash = {
  244. .name = "dsp5680xx_flash",
  245. .flash_bank_command = dsp5680xx_flash_bank_command,
  246. .erase = dsp5680xx_flash_erase,
  247. .protect = dsp5680xx_flash_protect,
  248. .write = dsp5680xx_flash_write,
  249. /* .read = default_flash_read, */
  250. .probe = dsp5680xx_probe,
  251. .auto_probe = dsp5680xx_probe,
  252. .erase_check = dsp5680xx_flash_erase_check,
  253. .protect_check = dsp5680xx_flash_protect_check,
  254. .info = dsp5680xx_flash_info
  255. };