spl_nand.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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 <fdt_support.h>
  9. #include <image.h>
  10. #include <log.h>
  11. #include <spl.h>
  12. #include <asm/io.h>
  13. #include <nand.h>
  14. #include <linux/libfdt_env.h>
  15. #include <fdt.h>
  16. uint32_t __weak spl_nand_get_uboot_raw_page(void)
  17. {
  18. return CONFIG_SYS_NAND_U_BOOT_OFFS;
  19. }
  20. #if defined(CONFIG_SPL_NAND_RAW_ONLY)
  21. static int spl_nand_load_image(struct spl_image_info *spl_image,
  22. struct spl_boot_device *bootdev)
  23. {
  24. nand_init();
  25. printf("Loading U-Boot from 0x%08x (size 0x%08x) to 0x%08x\n",
  26. CONFIG_SYS_NAND_U_BOOT_OFFS, CFG_SYS_NAND_U_BOOT_SIZE,
  27. CFG_SYS_NAND_U_BOOT_DST);
  28. nand_spl_load_image(spl_nand_get_uboot_raw_page(),
  29. CFG_SYS_NAND_U_BOOT_SIZE,
  30. (void *)CFG_SYS_NAND_U_BOOT_DST);
  31. spl_set_header_raw_uboot(spl_image);
  32. nand_deselect();
  33. return 0;
  34. }
  35. #else
  36. static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
  37. ulong size, void *dst)
  38. {
  39. int err;
  40. ulong sector;
  41. sector = *(int *)load->priv;
  42. offs *= load->bl_len;
  43. size *= load->bl_len;
  44. offs = sector + nand_spl_adjust_offset(sector, offs - sector);
  45. err = nand_spl_load_image(offs, size, dst);
  46. if (err)
  47. return 0;
  48. return size / load->bl_len;
  49. }
  50. static ulong spl_nand_legacy_read(struct spl_load_info *load, ulong offs,
  51. ulong size, void *dst)
  52. {
  53. int err;
  54. debug("%s: offs %lx, size %lx, dst %p\n",
  55. __func__, offs, size, dst);
  56. err = nand_spl_load_image(offs, size, dst);
  57. if (err)
  58. return 0;
  59. return size;
  60. }
  61. struct mtd_info * __weak nand_get_mtd(void)
  62. {
  63. return NULL;
  64. }
  65. static int spl_nand_load_element(struct spl_image_info *spl_image,
  66. struct spl_boot_device *bootdev,
  67. int offset, struct legacy_img_hdr *header)
  68. {
  69. struct mtd_info *mtd = nand_get_mtd();
  70. int bl_len = mtd ? mtd->writesize : 1;
  71. int err;
  72. err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
  73. if (err)
  74. return err;
  75. if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
  76. image_get_magic(header) == FDT_MAGIC) {
  77. struct spl_load_info load;
  78. debug("Found FIT\n");
  79. load.dev = NULL;
  80. load.priv = &offset;
  81. load.filename = NULL;
  82. load.bl_len = bl_len;
  83. load.read = spl_nand_fit_read;
  84. return spl_load_simple_fit(spl_image, &load, offset / bl_len, header);
  85. } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
  86. struct spl_load_info load;
  87. load.dev = NULL;
  88. load.priv = NULL;
  89. load.filename = NULL;
  90. load.bl_len = bl_len;
  91. load.read = spl_nand_fit_read;
  92. return spl_load_imx_container(spl_image, &load, offset / bl_len);
  93. } else if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT) &&
  94. image_get_magic(header) == IH_MAGIC) {
  95. struct spl_load_info load;
  96. debug("Found legacy image\n");
  97. load.dev = NULL;
  98. load.priv = NULL;
  99. load.filename = NULL;
  100. load.bl_len = 1;
  101. load.read = spl_nand_legacy_read;
  102. return spl_load_legacy_img(spl_image, bootdev, &load, offset, header);
  103. } else {
  104. err = spl_parse_image_header(spl_image, bootdev, header);
  105. if (err)
  106. return err;
  107. return nand_spl_load_image(offset, spl_image->size,
  108. (void *)(ulong)spl_image->load_addr);
  109. }
  110. }
  111. static int spl_nand_load_image(struct spl_image_info *spl_image,
  112. struct spl_boot_device *bootdev)
  113. {
  114. int err;
  115. struct legacy_img_hdr *header;
  116. int *src __attribute__((unused));
  117. int *dst __attribute__((unused));
  118. #ifdef CONFIG_SPL_NAND_SOFTECC
  119. debug("spl: nand - using sw ecc\n");
  120. #else
  121. debug("spl: nand - using hw ecc\n");
  122. #endif
  123. nand_init();
  124. header = spl_get_load_buffer(0, sizeof(*header));
  125. #if CONFIG_IS_ENABLED(OS_BOOT)
  126. if (!spl_start_uboot()) {
  127. /*
  128. * load parameter image
  129. * load to temp position since nand_spl_load_image reads
  130. * a whole block which is typically larger than
  131. * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
  132. * following sections like BSS
  133. */
  134. nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
  135. CONFIG_CMD_SPL_WRITE_SIZE,
  136. (void *)CONFIG_TEXT_BASE);
  137. /* copy to destintion */
  138. for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR,
  139. src = (int *)CONFIG_TEXT_BASE;
  140. src < (int *)(CONFIG_TEXT_BASE +
  141. CONFIG_CMD_SPL_WRITE_SIZE);
  142. src++, dst++) {
  143. writel(readl(src), dst);
  144. }
  145. /* load linux */
  146. nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
  147. sizeof(*header), (void *)header);
  148. err = spl_parse_image_header(spl_image, bootdev, header);
  149. if (err)
  150. return err;
  151. if (header->ih_os == IH_OS_LINUX) {
  152. /* happy - was a linux */
  153. err = nand_spl_load_image(
  154. CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
  155. spl_image->size,
  156. (void *)spl_image->load_addr);
  157. nand_deselect();
  158. return err;
  159. } else {
  160. puts("The Expected Linux image was not "
  161. "found. Please check your NAND "
  162. "configuration.\n");
  163. puts("Trying to start u-boot now...\n");
  164. }
  165. }
  166. #endif
  167. #ifdef CONFIG_NAND_ENV_DST
  168. spl_nand_load_element(spl_image, bootdev, CONFIG_ENV_OFFSET, header);
  169. #ifdef CONFIG_ENV_OFFSET_REDUND
  170. spl_nand_load_element(spl_image, bootdev, CONFIG_ENV_OFFSET_REDUND, header);
  171. #endif
  172. #endif
  173. /* Load u-boot */
  174. err = spl_nand_load_element(spl_image, bootdev, spl_nand_get_uboot_raw_page(),
  175. header);
  176. #ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
  177. #if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
  178. if (err)
  179. err = spl_nand_load_element(spl_image, bootdev,
  180. CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND,
  181. header);
  182. #endif
  183. #endif
  184. nand_deselect();
  185. return err;
  186. }
  187. #endif
  188. /* Use priorty 1 so that Ubi can override this */
  189. SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image);