fsl_ifc_spl.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * NAND boot for Freescale Integrated Flash Controller, NAND FCM
  3. *
  4. * Copyright 2011 Freescale Semiconductor, Inc.
  5. * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
  6. *
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. #include <common.h>
  10. #include <asm/io.h>
  11. #include <fsl_ifc.h>
  12. #include <linux/mtd/nand.h>
  13. static inline int is_blank(uchar *addr, int page_size)
  14. {
  15. int i;
  16. for (i = 0; i < page_size; i++) {
  17. if (__raw_readb(&addr[i]) != 0xff)
  18. return 0;
  19. }
  20. /*
  21. * For the SPL, don't worry about uncorrectable errors
  22. * where the main area is all FFs but shouldn't be.
  23. */
  24. return 1;
  25. }
  26. /* returns nonzero if entire page is blank */
  27. static inline int check_read_ecc(uchar *buf, u32 *eccstat,
  28. unsigned int bufnum, int page_size)
  29. {
  30. u32 reg = eccstat[bufnum / 4];
  31. int errors = (reg >> ((3 - bufnum % 4) * 8)) & 0xf;
  32. if (errors == 0xf) { /* uncorrectable */
  33. /* Blank pages fail hw ECC checks */
  34. if (is_blank(buf, page_size))
  35. return 1;
  36. puts("ecc error\n");
  37. for (;;)
  38. ;
  39. }
  40. return 0;
  41. }
  42. static inline void nand_wait(uchar *buf, int bufnum, int page_size)
  43. {
  44. struct fsl_ifc *ifc = IFC_BASE_ADDR;
  45. u32 status;
  46. u32 eccstat[4];
  47. int bufperpage = page_size / 512;
  48. int bufnum_end, i;
  49. bufnum *= bufperpage;
  50. bufnum_end = bufnum + bufperpage - 1;
  51. do {
  52. status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
  53. } while (!(status & IFC_NAND_EVTER_STAT_OPC));
  54. if (status & IFC_NAND_EVTER_STAT_FTOER) {
  55. puts("flash time out error\n");
  56. for (;;)
  57. ;
  58. }
  59. for (i = bufnum / 4; i <= bufnum_end / 4; i++)
  60. eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
  61. for (i = bufnum; i <= bufnum_end; i++) {
  62. if (check_read_ecc(buf, eccstat, i, page_size))
  63. break;
  64. }
  65. ifc_out32(&ifc->ifc_nand.nand_evter_stat, status);
  66. }
  67. static inline int bad_block(uchar *marker, int port_size)
  68. {
  69. if (port_size == 8)
  70. return __raw_readb(marker) != 0xff;
  71. else
  72. return __raw_readw((u16 *)marker) != 0xffff;
  73. }
  74. int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
  75. {
  76. struct fsl_ifc *ifc = IFC_BASE_ADDR;
  77. uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
  78. int page_size;
  79. int port_size;
  80. int pages_per_blk;
  81. int blk_size;
  82. int bad_marker = 0;
  83. int bufnum_mask, bufnum, ver = 0;
  84. int csor, cspr;
  85. int pos = 0;
  86. int j = 0;
  87. int sram_addr;
  88. int pg_no;
  89. uchar *dst = vdst;
  90. /* Get NAND Flash configuration */
  91. csor = CONFIG_SYS_NAND_CSOR;
  92. cspr = CONFIG_SYS_NAND_CSPR;
  93. port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8;
  94. if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_8K) {
  95. page_size = 8192;
  96. bufnum_mask = 0x0;
  97. } else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_4K) {
  98. page_size = 4096;
  99. bufnum_mask = 0x1;
  100. } else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_2K) {
  101. page_size = 2048;
  102. bufnum_mask = 0x3;
  103. } else {
  104. page_size = 512;
  105. bufnum_mask = 0xf;
  106. if (port_size == 8)
  107. bad_marker = 5;
  108. }
  109. ver = ifc_in32(&ifc->ifc_rev);
  110. if (ver >= FSL_IFC_V2_0_0)
  111. bufnum_mask = (bufnum_mask * 2) + 1;
  112. pages_per_blk =
  113. 32 << ((csor & CSOR_NAND_PB_MASK) >> CSOR_NAND_PB_SHIFT);
  114. blk_size = pages_per_blk * page_size;
  115. /* Open Full SRAM mapping for spare are access */
  116. ifc_out32(&ifc->ifc_nand.ncfgr, 0x0);
  117. /* Clear Boot events */
  118. ifc_out32(&ifc->ifc_nand.nand_evter_stat, 0xffffffff);
  119. /* Program FIR/FCR for Large/Small page */
  120. if (page_size > 512) {
  121. ifc_out32(&ifc->ifc_nand.nand_fir0,
  122. (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
  123. (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
  124. (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
  125. (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
  126. (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP4_SHIFT));
  127. ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
  128. ifc_out32(&ifc->ifc_nand.nand_fcr0,
  129. (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
  130. (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
  131. } else {
  132. ifc_out32(&ifc->ifc_nand.nand_fir0,
  133. (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
  134. (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
  135. (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
  136. (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP3_SHIFT));
  137. ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
  138. ifc_out32(&ifc->ifc_nand.nand_fcr0,
  139. NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
  140. }
  141. /* Program FBCR = 0 for full page read */
  142. ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
  143. /* Read and copy u-boot on SDRAM from NAND device, In parallel
  144. * check for Bad block if found skip it and read continue to
  145. * next Block
  146. */
  147. while (pos < uboot_size) {
  148. int i = 0;
  149. do {
  150. pg_no = offs / page_size;
  151. bufnum = pg_no & bufnum_mask;
  152. sram_addr = bufnum * page_size * 2;
  153. ifc_out32(&ifc->ifc_nand.row0, pg_no);
  154. ifc_out32(&ifc->ifc_nand.col0, 0);
  155. /* start read */
  156. ifc_out32(&ifc->ifc_nand.nandseq_strt,
  157. IFC_NAND_SEQ_STRT_FIR_STRT);
  158. /* wait for read to complete */
  159. nand_wait(&buf[sram_addr], bufnum, page_size);
  160. /*
  161. * If either of the first two pages are marked bad,
  162. * continue to the next block.
  163. */
  164. if (i++ < 2 &&
  165. bad_block(&buf[sram_addr + page_size + bad_marker],
  166. port_size)) {
  167. puts("skipping\n");
  168. offs = (offs + blk_size) & ~(blk_size - 1);
  169. pos &= ~(blk_size - 1);
  170. break;
  171. }
  172. for (j = 0; j < page_size; j++)
  173. dst[pos + j] = __raw_readb(&buf[sram_addr + j]);
  174. pos += page_size;
  175. offs += page_size;
  176. } while ((offs & (blk_size - 1)) && (pos < uboot_size));
  177. }
  178. return 0;
  179. }
  180. /*
  181. * Main entrypoint for NAND Boot. It's necessary that SDRAM is already
  182. * configured and available since this code loads the main U-boot image
  183. * from NAND into SDRAM and starts from there.
  184. */
  185. void nand_boot(void)
  186. {
  187. __attribute__((noreturn)) void (*uboot)(void);
  188. /*
  189. * Load U-Boot image from NAND into RAM
  190. */
  191. nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
  192. CONFIG_SYS_NAND_U_BOOT_SIZE,
  193. (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
  194. #ifdef CONFIG_NAND_ENV_DST
  195. nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
  196. (uchar *)CONFIG_NAND_ENV_DST);
  197. #ifdef CONFIG_ENV_OFFSET_REDUND
  198. nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
  199. (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
  200. #endif
  201. #endif
  202. /*
  203. * Jump to U-Boot image
  204. */
  205. #ifdef CONFIG_SPL_FLUSH_IMAGE
  206. /*
  207. * Clean d-cache and invalidate i-cache, to
  208. * make sure that no stale data is executed.
  209. */
  210. flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
  211. #endif
  212. uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
  213. uboot();
  214. }
  215. #ifndef CONFIG_SPL_NAND_INIT
  216. void nand_init(void)
  217. {
  218. }
  219. void nand_deselect(void)
  220. {
  221. }
  222. #endif