spl_nand.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Copyright (C) 2011
  3. * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <config.h>
  9. #include <spl.h>
  10. #include <asm/io.h>
  11. #include <nand.h>
  12. #include <libfdt_env.h>
  13. #include <fdt.h>
  14. #if defined(CONFIG_SPL_NAND_RAW_ONLY)
  15. int spl_nand_load_image(struct spl_image_info *spl_image,
  16. struct spl_boot_device *bootdev)
  17. {
  18. nand_init();
  19. nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
  20. CONFIG_SYS_NAND_U_BOOT_SIZE,
  21. (void *)CONFIG_SYS_NAND_U_BOOT_DST);
  22. spl_set_header_raw_uboot(spl_image);
  23. nand_deselect();
  24. return 0;
  25. }
  26. #else
  27. static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
  28. ulong size, void *dst)
  29. {
  30. int ret;
  31. ret = nand_spl_load_image(offs, size, dst);
  32. if (!ret)
  33. return size;
  34. else
  35. return 0;
  36. }
  37. static int spl_nand_load_element(struct spl_image_info *spl_image,
  38. int offset, struct image_header *header)
  39. {
  40. int err;
  41. err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
  42. if (err)
  43. return err;
  44. if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
  45. image_get_magic(header) == FDT_MAGIC) {
  46. struct spl_load_info load;
  47. debug("Found FIT\n");
  48. load.dev = NULL;
  49. load.priv = NULL;
  50. load.filename = NULL;
  51. load.bl_len = 1;
  52. load.read = spl_nand_fit_read;
  53. return spl_load_simple_fit(spl_image, &load, offset, header);
  54. } else {
  55. err = spl_parse_image_header(spl_image, header);
  56. if (err)
  57. return err;
  58. return nand_spl_load_image(offset, spl_image->size,
  59. (void *)(ulong)spl_image->load_addr);
  60. }
  61. }
  62. static int spl_nand_load_image(struct spl_image_info *spl_image,
  63. struct spl_boot_device *bootdev)
  64. {
  65. int err;
  66. struct image_header *header;
  67. int *src __attribute__((unused));
  68. int *dst __attribute__((unused));
  69. #ifdef CONFIG_SPL_NAND_SOFTECC
  70. debug("spl: nand - using sw ecc\n");
  71. #else
  72. debug("spl: nand - using hw ecc\n");
  73. #endif
  74. nand_init();
  75. /*use CONFIG_SYS_TEXT_BASE as temporary storage area */
  76. header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
  77. #ifdef CONFIG_SPL_OS_BOOT
  78. if (!spl_start_uboot()) {
  79. /*
  80. * load parameter image
  81. * load to temp position since nand_spl_load_image reads
  82. * a whole block which is typically larger than
  83. * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
  84. * following sections like BSS
  85. */
  86. nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
  87. CONFIG_CMD_SPL_WRITE_SIZE,
  88. (void *)CONFIG_SYS_TEXT_BASE);
  89. /* copy to destintion */
  90. for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR,
  91. src = (int *)CONFIG_SYS_TEXT_BASE;
  92. src < (int *)(CONFIG_SYS_TEXT_BASE +
  93. CONFIG_CMD_SPL_WRITE_SIZE);
  94. src++, dst++) {
  95. writel(readl(src), dst);
  96. }
  97. /* load linux */
  98. nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
  99. sizeof(*header), (void *)header);
  100. err = spl_parse_image_header(spl_image, header);
  101. if (err)
  102. return err;
  103. if (header->ih_os == IH_OS_LINUX) {
  104. /* happy - was a linux */
  105. err = nand_spl_load_image(
  106. CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
  107. spl_image->size,
  108. (void *)spl_image->load_addr);
  109. nand_deselect();
  110. return err;
  111. } else {
  112. puts("The Expected Linux image was not "
  113. "found. Please check your NAND "
  114. "configuration.\n");
  115. puts("Trying to start u-boot now...\n");
  116. }
  117. }
  118. #endif
  119. #ifdef CONFIG_NAND_ENV_DST
  120. spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET, header);
  121. #ifdef CONFIG_ENV_OFFSET_REDUND
  122. spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET_REDUND, header);
  123. #endif
  124. #endif
  125. /* Load u-boot */
  126. err = spl_nand_load_element(spl_image, CONFIG_SYS_NAND_U_BOOT_OFFS,
  127. header);
  128. #ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
  129. #if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
  130. if (err)
  131. err = spl_nand_load_element(spl_image,
  132. CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND,
  133. header);
  134. #endif
  135. #endif
  136. nand_deselect();
  137. return err;
  138. }
  139. #endif
  140. /* Use priorty 1 so that Ubi can override this */
  141. SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image);