spl_nand.c 4.3 KB

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