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.
 
 
 
 
 
 

250 lines
6.9 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2009 by Marvell Semiconductors, Inc. *
  3. * Written by Nicolas Pitre <nico at marvell.com> *
  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. /*
  21. * NAND controller interface for Marvell Orion/Kirkwood SoCs.
  22. */
  23. #ifdef HAVE_CONFIG_H
  24. #include "config.h"
  25. #endif
  26. #include "nand.h"
  27. #include "armv4_5.h"
  28. #include "binarybuffer.h"
  29. typedef struct orion_nand_controller_s
  30. {
  31. struct target_s *target;
  32. working_area_t *copy_area;
  33. u32 cmd;
  34. u32 addr;
  35. u32 data;
  36. } orion_nand_controller_t;
  37. #define CHECK_HALTED \
  38. do { \
  39. if (target->state != TARGET_HALTED) { \
  40. LOG_ERROR("NAND flash access requires halted target"); \
  41. return ERROR_NAND_OPERATION_FAILED; \
  42. } \
  43. } while (0)
  44. static int orion_nand_command(struct nand_device_s *device, uint8_t command)
  45. {
  46. orion_nand_controller_t *hw = device->controller_priv;
  47. target_t *target = hw->target;
  48. CHECK_HALTED;
  49. target_write_u8(target, hw->cmd, command);
  50. return ERROR_OK;
  51. }
  52. static int orion_nand_address(struct nand_device_s *device, uint8_t address)
  53. {
  54. orion_nand_controller_t *hw = device->controller_priv;
  55. target_t *target = hw->target;
  56. CHECK_HALTED;
  57. target_write_u8(target, hw->addr, address);
  58. return ERROR_OK;
  59. }
  60. static int orion_nand_read(struct nand_device_s *device, void *data)
  61. {
  62. orion_nand_controller_t *hw = device->controller_priv;
  63. target_t *target = hw->target;
  64. CHECK_HALTED;
  65. target_read_u8(target, hw->data, data);
  66. return ERROR_OK;
  67. }
  68. static int orion_nand_write(struct nand_device_s *device, uint16_t data)
  69. {
  70. orion_nand_controller_t *hw = device->controller_priv;
  71. target_t *target = hw->target;
  72. CHECK_HALTED;
  73. target_write_u8(target, hw->data, data);
  74. return ERROR_OK;
  75. }
  76. static int orion_nand_slow_block_write(struct nand_device_s *device, uint8_t *data, int size)
  77. {
  78. while (size--)
  79. orion_nand_write(device, *data++);
  80. return ERROR_OK;
  81. }
  82. static int orion_nand_fast_block_write(struct nand_device_s *device, uint8_t *data, int size)
  83. {
  84. orion_nand_controller_t *hw = device->controller_priv;
  85. target_t *target = hw->target;
  86. armv4_5_algorithm_t algo;
  87. reg_param_t reg_params[3];
  88. u32 target_buf;
  89. int retval;
  90. static const u32 code[] = {
  91. 0xe4d13001, /* ldrb r3, [r1], #1 */
  92. 0xe5c03000, /* strb r3, [r0] */
  93. 0xe2522001, /* subs r2, r2, #1 */
  94. 0x1afffffb, /* bne 0 */
  95. 0xeafffffe, /* b . */
  96. };
  97. int code_size = sizeof(code);
  98. if (!hw->copy_area) {
  99. uint8_t code_buf[code_size];
  100. int i;
  101. /* make sure we have a working area */
  102. if (target_alloc_working_area(target,
  103. code_size + device->page_size,
  104. &hw->copy_area) != ERROR_OK)
  105. {
  106. return orion_nand_slow_block_write(device, data, size);
  107. }
  108. /* copy target instructions to target endianness */
  109. for (i = 0; i < code_size/4; i++)
  110. target_buffer_set_u32(target, code_buf + i*4, code[i]);
  111. /* write code to working area */
  112. retval = target_write_memory(target,
  113. hw->copy_area->address,
  114. 4, code_size/4, code_buf);
  115. if (retval != ERROR_OK)
  116. return retval;
  117. }
  118. /* copy data to target's memory */
  119. target_buf = hw->copy_area->address + code_size;
  120. retval = target_bulk_write_memory(target, target_buf, size/4, data);
  121. if (retval == ERROR_OK && size & 3) {
  122. retval = target_write_memory(target,
  123. target_buf + (size & ~3),
  124. 1, size & 3, data + (size & ~3));
  125. }
  126. if (retval != ERROR_OK)
  127. return retval;
  128. algo.common_magic = ARMV4_5_COMMON_MAGIC;
  129. algo.core_mode = ARMV4_5_MODE_SVC;
  130. algo.core_state = ARMV4_5_STATE_ARM;
  131. init_reg_param(&reg_params[0], "r0", 32, PARAM_IN);
  132. init_reg_param(&reg_params[1], "r1", 32, PARAM_IN);
  133. init_reg_param(&reg_params[2], "r2", 32, PARAM_IN);
  134. buf_set_u32(reg_params[0].value, 0, 32, hw->data);
  135. buf_set_u32(reg_params[1].value, 0, 32, target_buf);
  136. buf_set_u32(reg_params[2].value, 0, 32, size);
  137. retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
  138. hw->copy_area->address,
  139. hw->copy_area->address + code_size - 4,
  140. 1000, &algo);
  141. if (retval != ERROR_OK)
  142. LOG_ERROR("error executing hosted NAND write");
  143. destroy_reg_param(&reg_params[0]);
  144. destroy_reg_param(&reg_params[1]);
  145. destroy_reg_param(&reg_params[2]);
  146. return retval;
  147. }
  148. static int orion_nand_reset(struct nand_device_s *device)
  149. {
  150. return orion_nand_command(device, NAND_CMD_RESET);
  151. }
  152. static int orion_nand_controller_ready(struct nand_device_s *device, int timeout)
  153. {
  154. return 1;
  155. }
  156. static int orion_nand_register_commands(struct command_context_s *cmd_ctx)
  157. {
  158. return ERROR_OK;
  159. }
  160. int orion_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
  161. char **args, int argc,
  162. struct nand_device_s *device)
  163. {
  164. orion_nand_controller_t *hw;
  165. u32 base;
  166. uint8_t ale, cle;
  167. if (argc != 3) {
  168. LOG_ERROR("arguments must be: <target_number> <NAND_address>\n");
  169. return ERROR_NAND_DEVICE_INVALID;
  170. }
  171. hw = calloc(1, sizeof(*hw));
  172. if (!hw) {
  173. LOG_ERROR("no memory for nand controller\n");
  174. return ERROR_NAND_DEVICE_INVALID;
  175. }
  176. device->controller_priv = hw;
  177. hw->target = get_target(args[1]);
  178. if (!hw->target) {
  179. LOG_ERROR("target '%s' not defined", args[1]);
  180. free(hw);
  181. return ERROR_NAND_DEVICE_INVALID;
  182. }
  183. base = strtoul(args[2], NULL, 0);
  184. cle = 0;
  185. ale = 1;
  186. hw->data = base;
  187. hw->cmd = base + (1 << cle);
  188. hw->addr = base + (1 << ale);
  189. return ERROR_OK;
  190. }
  191. static int orion_nand_init(struct nand_device_s *device)
  192. {
  193. return ERROR_OK;
  194. }
  195. nand_flash_controller_t orion_nand_controller =
  196. {
  197. .name = "orion",
  198. .command = orion_nand_command,
  199. .address = orion_nand_address,
  200. .read_data = orion_nand_read,
  201. .write_data = orion_nand_write,
  202. .write_block_data = orion_nand_fast_block_write,
  203. .reset = orion_nand_reset,
  204. .controller_ready = orion_nand_controller_ready,
  205. .nand_device_command = orion_nand_device_command,
  206. .register_commands = orion_nand_register_commands,
  207. .init = orion_nand_init,
  208. };