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.
 
 
 
 
 
 

162 lines
4.4 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, see <http://www.gnu.org/licenses/>. *
  17. ***************************************************************************/
  18. /*
  19. * NAND controller interface for Marvell Orion/Kirkwood SoCs.
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include "imp.h"
  25. #include "arm_io.h"
  26. #include <target/arm.h>
  27. struct orion_nand_controller {
  28. struct arm_nand_data io;
  29. uint32_t cmd;
  30. uint32_t addr;
  31. uint32_t data;
  32. };
  33. #define CHECK_HALTED \
  34. do { \
  35. if (target->state != TARGET_HALTED) { \
  36. LOG_ERROR("NAND flash access requires halted target"); \
  37. return ERROR_NAND_OPERATION_FAILED; \
  38. } \
  39. } while (0)
  40. static int orion_nand_command(struct nand_device *nand, uint8_t command)
  41. {
  42. struct orion_nand_controller *hw = nand->controller_priv;
  43. struct target *target = nand->target;
  44. CHECK_HALTED;
  45. target_write_u8(target, hw->cmd, command);
  46. return ERROR_OK;
  47. }
  48. static int orion_nand_address(struct nand_device *nand, uint8_t address)
  49. {
  50. struct orion_nand_controller *hw = nand->controller_priv;
  51. struct target *target = nand->target;
  52. CHECK_HALTED;
  53. target_write_u8(target, hw->addr, address);
  54. return ERROR_OK;
  55. }
  56. static int orion_nand_read(struct nand_device *nand, void *data)
  57. {
  58. struct orion_nand_controller *hw = nand->controller_priv;
  59. struct target *target = nand->target;
  60. CHECK_HALTED;
  61. target_read_u8(target, hw->data, data);
  62. return ERROR_OK;
  63. }
  64. static int orion_nand_write(struct nand_device *nand, uint16_t data)
  65. {
  66. struct orion_nand_controller *hw = nand->controller_priv;
  67. struct target *target = nand->target;
  68. CHECK_HALTED;
  69. target_write_u8(target, hw->data, data);
  70. return ERROR_OK;
  71. }
  72. static int orion_nand_slow_block_write(struct nand_device *nand, uint8_t *data, int size)
  73. {
  74. while (size--)
  75. orion_nand_write(nand, *data++);
  76. return ERROR_OK;
  77. }
  78. static int orion_nand_fast_block_write(struct nand_device *nand, uint8_t *data, int size)
  79. {
  80. struct orion_nand_controller *hw = nand->controller_priv;
  81. int retval;
  82. hw->io.chunk_size = nand->page_size;
  83. retval = arm_nandwrite(&hw->io, data, size);
  84. if (retval == ERROR_NAND_NO_BUFFER)
  85. retval = orion_nand_slow_block_write(nand, data, size);
  86. return retval;
  87. }
  88. static int orion_nand_reset(struct nand_device *nand)
  89. {
  90. return orion_nand_command(nand, NAND_CMD_RESET);
  91. }
  92. NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
  93. {
  94. struct orion_nand_controller *hw;
  95. uint32_t base;
  96. uint8_t ale, cle;
  97. if (CMD_ARGC != 3)
  98. return ERROR_COMMAND_SYNTAX_ERROR;
  99. hw = calloc(1, sizeof(*hw));
  100. if (!hw) {
  101. LOG_ERROR("no memory for nand controller");
  102. return ERROR_NAND_DEVICE_INVALID;
  103. }
  104. nand->controller_priv = hw;
  105. COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], base);
  106. cle = 0;
  107. ale = 1;
  108. hw->data = base;
  109. hw->cmd = base + (1 << cle);
  110. hw->addr = base + (1 << ale);
  111. hw->io.target = nand->target;
  112. hw->io.data = hw->data;
  113. hw->io.op = ARM_NAND_NONE;
  114. return ERROR_OK;
  115. }
  116. static int orion_nand_init(struct nand_device *nand)
  117. {
  118. return ERROR_OK;
  119. }
  120. struct nand_flash_controller orion_nand_controller = {
  121. .name = "orion",
  122. .usage = "<target_id> <NAND_address>",
  123. .command = orion_nand_command,
  124. .address = orion_nand_address,
  125. .read_data = orion_nand_read,
  126. .write_data = orion_nand_write,
  127. .write_block_data = orion_nand_fast_block_write,
  128. .reset = orion_nand_reset,
  129. .nand_device_command = orion_nand_device_command,
  130. .init = orion_nand_init,
  131. };