2 * Copyright (c) 2014, Antmicro Ltd <www.antmicro.com>
3 * Copyright (c) 2015, Turtle Solutions <www.turtle-solutions.eu>
4 * Copyright (c) 2015, Roy Spliet <rspliet@ultimaker.com>
6 * SPDX-License-Identifier: GPL-2.0+
8 * \todo Detect chip parameters (page size, ECC mode, randomisation...)
15 #include <asm/arch/cpu.h>
16 #include <asm/arch/clock.h>
17 #include <asm/arch/dma.h>
18 #include <asm/arch/nand.h>
23 struct sunxi_ccm_reg * const ccm =
24 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
25 struct sunxi_nand * const nand = (struct sunxi_nand *)SUNXI_NFC_BASE;
30 /* "un-gate" NAND clock and clock source
31 * This assumes that the clock was already correctly configured by
33 setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_NAND0));
34 #ifdef CONFIG_MACH_SUN9I
35 setbits_le32(&ccm->ahb_gate1, (1 << AHB_GATE_OFFSET_DMA));
37 setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
39 setbits_le32(&ccm->nand0_clk_cfg, 0x80000000);
41 val = readl(&nand->ctl);
42 val |= SUNXI_NAND_CTL_RST;
43 writel(val, &nand->ctl);
45 /* Wait until reset pin is deasserted */
47 val = readl(&nand->ctl);
48 if (!(val & SUNXI_NAND_CTL_RST))
52 /** \todo Chip select, currently kind of static */
53 val = readl(&nand->ctl);
55 val |= SUNXI_NAND_CTL_EN;
56 val |= SUNXI_NAND_CTL_PAGE_SIZE(CONFIG_NAND_SUNXI_PAGE_SIZE);
57 writel(val, &nand->ctl);
59 writel(0x100, &nand->timing_ctl);
60 writel(0x7ff, &nand->timing_cfg);
63 val = SUNXI_NAND_CMD_SEND_CMD1 | SUNXI_NAND_CMD_WAIT_FLAG |
65 writel(val, &nand->cmd);
67 val = readl(&nand->st);
73 printf("Nand initialised\n");
77 nand_wait_timeout(u32 *reg, u32 mask, u32 val)
79 unsigned long tmo = timer_get_us() + 1000000; /* 1s */
81 while ((readl(reg) & mask) != val) {
82 if (timer_get_us() > tmo)
90 static const uint16_t random_seed[128] = {
91 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
92 0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
93 0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
94 0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
95 0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
96 0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
97 0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
98 0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
99 0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
100 0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
101 0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
102 0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
103 0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
104 0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
105 0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
106 0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
109 uint32_t ecc_errors = 0;
112 nand_config_ecc(struct sunxi_nand *nand, uint32_t page, int syndrome)
114 static u8 strength[] = {16, 24, 28, 32, 40, 48, 56, 60, 64};
120 for (i = 0; i < ARRAY_SIZE(strength); i++) {
121 if (CONFIG_NAND_SUNXI_ECC_STRENGTH == strength[i]) {
127 if (i == ARRAY_SIZE(strength)) {
128 printf("ECC strength unsupported\n");
132 ecc = SUNXI_NAND_ECC_CTL_ECC_EN |
133 SUNXI_NAND_ECC_CTL_PIPELINE |
134 SUNXI_NAND_ECC_CTL_RND_EN |
135 SUNXI_NAND_ECC_CTL_MODE(ecc_mode);
137 if (CONFIG_NAND_SUNXI_ECC_STEP == 512)
138 ecc |= SUNXI_NAND_ECC_CTL_BS_512B;
143 seed = random_seed[page % ARRAY_SIZE(random_seed)];
145 ecc |= SUNXI_NAND_ECC_CTL_RND_SEED(seed);
147 writel(ecc, &nand->ecc_ctl);
150 /* read CONFIG_NAND_SUNXI_ECC_STEP bytes from real_addr to temp_buf */
152 nand_read_block(struct sunxi_nand *nand, phys_addr_t src, dma_addr_t dst,
155 struct sunxi_dma * const dma = (struct sunxi_dma *)SUNXI_DMA_BASE;
156 struct sunxi_dma_cfg * const dma_cfg = &dma->ddma[0];
166 page = src / CONFIG_NAND_SUNXI_PAGE_SIZE;
168 /* TODO: currently this is not supported */
169 printf("Reading from address >= %08X is not allowed.\n",
170 0xFFFF * CONFIG_NAND_SUNXI_PAGE_SIZE);
174 shift = src % CONFIG_NAND_SUNXI_PAGE_SIZE;
175 writel(0, &nand->ecc_st);
177 /* ECC_CTL, randomization */
178 ecc_bytes = CONFIG_NAND_SUNXI_ECC_STRENGTH *
179 fls(CONFIG_NAND_SUNXI_ECC_STEP * 8);
180 ecc_bytes = DIV_ROUND_UP(ecc_bytes, 8);
181 ecc_bytes += (ecc_bytes & 1); /* Align to 2-bytes */
184 nand_config_ecc(nand, page, syndrome);
186 /* shift every 1kB in syndrome */
187 shift += (shift / CONFIG_NAND_SUNXI_ECC_STEP) * ecc_bytes;
188 oob_offset = CONFIG_NAND_SUNXI_ECC_STEP + shift;
190 oob_offset = CONFIG_NAND_SUNXI_PAGE_SIZE +
191 (shift / CONFIG_NAND_SUNXI_ECC_STEP) * ecc_bytes;
194 addr = (page << 16) | shift;
197 val = readl(&nand->ctl);
198 writel(val | SUNXI_NAND_CTL_RAM_METHOD_DMA, &nand->ctl);
200 writel(oob_offset, &nand->spare_area);
203 * \todo Separate this into a tidy driver */
204 writel(0x0, &dma->irq_en); /* clear dma interrupts */
205 writel((uint32_t) &nand->io_data , &dma_cfg->src_addr);
206 writel(dst , &dma_cfg->dst_addr);
207 writel(0x00007F0F , &dma_cfg->ddma_para);
208 writel(CONFIG_NAND_SUNXI_ECC_STEP, &dma_cfg->bc);
210 val = SUNXI_DMA_CTL_SRC_DRQ(DDMA_SRC_DRQ_NAND) |
211 SUNXI_DMA_CTL_MODE_IO |
212 SUNXI_DMA_CTL_SRC_DATA_WIDTH_32 |
213 SUNXI_DMA_CTL_DST_DRQ(DDMA_DST_DRQ_SDRAM) |
214 SUNXI_DMA_CTL_DST_DATA_WIDTH_32 |
215 SUNXI_DMA_CTL_TRIGGER;
216 writel(val, &dma_cfg->ctl);
218 writel(0x00E00530, &nand->rcmd_set);
219 nand_wait_timeout(&nand->st, SUNXI_NAND_ST_FIFO_FULL, 0);
221 writel(1 , &nand->block_num);
222 writel(addr, &nand->addr_low);
223 writel(0 , &nand->addr_high);
225 /* CMD (PAGE READ) */
227 cmd |= SUNXI_NAND_CMD_ADDR_CYCLES(CONFIG_NAND_SUNXI_ADDR_CYCLES);
228 cmd |= (syndrome ? SUNXI_NAND_CMD_ORDER_SEQ :
229 SUNXI_NAND_CMD_ORDER_INTERLEAVE);
230 writel(cmd, &nand->cmd);
232 if(nand_wait_timeout(&nand->st, SUNXI_NAND_ST_DMA_INT,
233 SUNXI_NAND_ST_DMA_INT)) {
234 printf("NAND timeout reading data\n");
238 if(nand_wait_timeout(&dma_cfg->ctl, SUNXI_DMA_CTL_TRIGGER, 0)) {
239 printf("NAND timeout reading data\n");
243 if (readl(&nand->ecc_st))
248 nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
250 struct sunxi_nand * const nand = (struct sunxi_nand *)SUNXI_NFC_BASE;
251 dma_addr_t dst_block;
253 phys_addr_t addr = offs;
255 dst_end = ((dma_addr_t) dest) + size;
257 memset((void *)dest, 0x0, size);
259 for (dst_block = (dma_addr_t) dest; dst_block < dst_end;
260 dst_block += CONFIG_NAND_SUNXI_ECC_STEP,
261 addr += CONFIG_NAND_SUNXI_ECC_STEP) {
262 /* syndrome read first 4MiB to match Allwinner BootROM */
263 nand_read_block(nand, addr, dst_block, addr < 0x400000);
267 printf("Error: %d ECC failures detected\n", ecc_errors);
268 return ecc_errors == 0;