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.

164 lines
4.6KB

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