1*a430fa06SMiquel Raynal // SPDX-License-Identifier: GPL-2.0+
2*a430fa06SMiquel Raynal /*
3*a430fa06SMiquel Raynal * Copyright (C) 2014 Panasonic Corporation
4*a430fa06SMiquel Raynal * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
5*a430fa06SMiquel Raynal */
6*a430fa06SMiquel Raynal
7*a430fa06SMiquel Raynal #include <common.h>
8*a430fa06SMiquel Raynal #include <asm/io.h>
9*a430fa06SMiquel Raynal #include <asm/unaligned.h>
10*a430fa06SMiquel Raynal #include <linux/mtd/rawnand.h>
11*a430fa06SMiquel Raynal #include "denali.h"
12*a430fa06SMiquel Raynal
13*a430fa06SMiquel Raynal #define DENALI_MAP01 (1 << 26) /* read/write pages in PIO */
14*a430fa06SMiquel Raynal #define DENALI_MAP10 (2 << 26) /* high-level control plane */
15*a430fa06SMiquel Raynal
16*a430fa06SMiquel Raynal #define INDEX_CTRL_REG 0x0
17*a430fa06SMiquel Raynal #define INDEX_DATA_REG 0x10
18*a430fa06SMiquel Raynal
19*a430fa06SMiquel Raynal #define SPARE_ACCESS 0x41
20*a430fa06SMiquel Raynal #define MAIN_ACCESS 0x42
21*a430fa06SMiquel Raynal #define PIPELINE_ACCESS 0x2000
22*a430fa06SMiquel Raynal
23*a430fa06SMiquel Raynal #define BANK(x) ((x) << 24)
24*a430fa06SMiquel Raynal
25*a430fa06SMiquel Raynal static void __iomem *denali_flash_mem =
26*a430fa06SMiquel Raynal (void __iomem *)CONFIG_SYS_NAND_DATA_BASE;
27*a430fa06SMiquel Raynal static void __iomem *denali_flash_reg =
28*a430fa06SMiquel Raynal (void __iomem *)CONFIG_SYS_NAND_REGS_BASE;
29*a430fa06SMiquel Raynal
30*a430fa06SMiquel Raynal static const int flash_bank;
31*a430fa06SMiquel Raynal static int page_size, oob_size, pages_per_block;
32*a430fa06SMiquel Raynal
index_addr(uint32_t address,uint32_t data)33*a430fa06SMiquel Raynal static void index_addr(uint32_t address, uint32_t data)
34*a430fa06SMiquel Raynal {
35*a430fa06SMiquel Raynal writel(address, denali_flash_mem + INDEX_CTRL_REG);
36*a430fa06SMiquel Raynal writel(data, denali_flash_mem + INDEX_DATA_REG);
37*a430fa06SMiquel Raynal }
38*a430fa06SMiquel Raynal
wait_for_irq(uint32_t irq_mask)39*a430fa06SMiquel Raynal static int wait_for_irq(uint32_t irq_mask)
40*a430fa06SMiquel Raynal {
41*a430fa06SMiquel Raynal unsigned long timeout = 1000000;
42*a430fa06SMiquel Raynal uint32_t intr_status;
43*a430fa06SMiquel Raynal
44*a430fa06SMiquel Raynal do {
45*a430fa06SMiquel Raynal intr_status = readl(denali_flash_reg + INTR_STATUS(flash_bank));
46*a430fa06SMiquel Raynal
47*a430fa06SMiquel Raynal if (intr_status & INTR__ECC_UNCOR_ERR) {
48*a430fa06SMiquel Raynal debug("Uncorrected ECC detected\n");
49*a430fa06SMiquel Raynal return -EBADMSG;
50*a430fa06SMiquel Raynal }
51*a430fa06SMiquel Raynal
52*a430fa06SMiquel Raynal if (intr_status & irq_mask)
53*a430fa06SMiquel Raynal break;
54*a430fa06SMiquel Raynal
55*a430fa06SMiquel Raynal udelay(1);
56*a430fa06SMiquel Raynal timeout--;
57*a430fa06SMiquel Raynal } while (timeout);
58*a430fa06SMiquel Raynal
59*a430fa06SMiquel Raynal if (!timeout) {
60*a430fa06SMiquel Raynal debug("Timeout with interrupt status %08x\n", intr_status);
61*a430fa06SMiquel Raynal return -EIO;
62*a430fa06SMiquel Raynal }
63*a430fa06SMiquel Raynal
64*a430fa06SMiquel Raynal return 0;
65*a430fa06SMiquel Raynal }
66*a430fa06SMiquel Raynal
read_data_from_flash_mem(uint8_t * buf,int len)67*a430fa06SMiquel Raynal static void read_data_from_flash_mem(uint8_t *buf, int len)
68*a430fa06SMiquel Raynal {
69*a430fa06SMiquel Raynal int i;
70*a430fa06SMiquel Raynal uint32_t *buf32;
71*a430fa06SMiquel Raynal
72*a430fa06SMiquel Raynal /* transfer the data from the flash */
73*a430fa06SMiquel Raynal buf32 = (uint32_t *)buf;
74*a430fa06SMiquel Raynal
75*a430fa06SMiquel Raynal /*
76*a430fa06SMiquel Raynal * Let's take care of unaligned access although it rarely happens.
77*a430fa06SMiquel Raynal * Avoid put_unaligned() for the normal use cases since it leads to
78*a430fa06SMiquel Raynal * a bit performance regression.
79*a430fa06SMiquel Raynal */
80*a430fa06SMiquel Raynal if ((unsigned long)buf32 % 4) {
81*a430fa06SMiquel Raynal for (i = 0; i < len / 4; i++)
82*a430fa06SMiquel Raynal put_unaligned(readl(denali_flash_mem + INDEX_DATA_REG),
83*a430fa06SMiquel Raynal buf32++);
84*a430fa06SMiquel Raynal } else {
85*a430fa06SMiquel Raynal for (i = 0; i < len / 4; i++)
86*a430fa06SMiquel Raynal *buf32++ = readl(denali_flash_mem + INDEX_DATA_REG);
87*a430fa06SMiquel Raynal }
88*a430fa06SMiquel Raynal
89*a430fa06SMiquel Raynal if (len % 4) {
90*a430fa06SMiquel Raynal u32 tmp;
91*a430fa06SMiquel Raynal
92*a430fa06SMiquel Raynal tmp = cpu_to_le32(readl(denali_flash_mem + INDEX_DATA_REG));
93*a430fa06SMiquel Raynal buf = (uint8_t *)buf32;
94*a430fa06SMiquel Raynal for (i = 0; i < len % 4; i++) {
95*a430fa06SMiquel Raynal *buf++ = tmp;
96*a430fa06SMiquel Raynal tmp >>= 8;
97*a430fa06SMiquel Raynal }
98*a430fa06SMiquel Raynal }
99*a430fa06SMiquel Raynal }
100*a430fa06SMiquel Raynal
denali_send_pipeline_cmd(int page,int ecc_en,int access_type)101*a430fa06SMiquel Raynal int denali_send_pipeline_cmd(int page, int ecc_en, int access_type)
102*a430fa06SMiquel Raynal {
103*a430fa06SMiquel Raynal uint32_t addr, cmd;
104*a430fa06SMiquel Raynal static uint32_t page_count = 1;
105*a430fa06SMiquel Raynal
106*a430fa06SMiquel Raynal writel(ecc_en, denali_flash_reg + ECC_ENABLE);
107*a430fa06SMiquel Raynal
108*a430fa06SMiquel Raynal /* clear all bits of intr_status. */
109*a430fa06SMiquel Raynal writel(0xffff, denali_flash_reg + INTR_STATUS(flash_bank));
110*a430fa06SMiquel Raynal
111*a430fa06SMiquel Raynal addr = BANK(flash_bank) | page;
112*a430fa06SMiquel Raynal
113*a430fa06SMiquel Raynal /* setup the acccess type */
114*a430fa06SMiquel Raynal cmd = DENALI_MAP10 | addr;
115*a430fa06SMiquel Raynal index_addr(cmd, access_type);
116*a430fa06SMiquel Raynal
117*a430fa06SMiquel Raynal /* setup the pipeline command */
118*a430fa06SMiquel Raynal index_addr(cmd, PIPELINE_ACCESS | page_count);
119*a430fa06SMiquel Raynal
120*a430fa06SMiquel Raynal cmd = DENALI_MAP01 | addr;
121*a430fa06SMiquel Raynal writel(cmd, denali_flash_mem + INDEX_CTRL_REG);
122*a430fa06SMiquel Raynal
123*a430fa06SMiquel Raynal return wait_for_irq(INTR__LOAD_COMP);
124*a430fa06SMiquel Raynal }
125*a430fa06SMiquel Raynal
nand_read_oob(void * buf,int page)126*a430fa06SMiquel Raynal static int nand_read_oob(void *buf, int page)
127*a430fa06SMiquel Raynal {
128*a430fa06SMiquel Raynal int ret;
129*a430fa06SMiquel Raynal
130*a430fa06SMiquel Raynal ret = denali_send_pipeline_cmd(page, 0, SPARE_ACCESS);
131*a430fa06SMiquel Raynal if (ret < 0)
132*a430fa06SMiquel Raynal return ret;
133*a430fa06SMiquel Raynal
134*a430fa06SMiquel Raynal read_data_from_flash_mem(buf, oob_size);
135*a430fa06SMiquel Raynal
136*a430fa06SMiquel Raynal return 0;
137*a430fa06SMiquel Raynal }
138*a430fa06SMiquel Raynal
nand_read_page(void * buf,int page)139*a430fa06SMiquel Raynal static int nand_read_page(void *buf, int page)
140*a430fa06SMiquel Raynal {
141*a430fa06SMiquel Raynal int ret;
142*a430fa06SMiquel Raynal
143*a430fa06SMiquel Raynal ret = denali_send_pipeline_cmd(page, 1, MAIN_ACCESS);
144*a430fa06SMiquel Raynal if (ret < 0)
145*a430fa06SMiquel Raynal return ret;
146*a430fa06SMiquel Raynal
147*a430fa06SMiquel Raynal read_data_from_flash_mem(buf, page_size);
148*a430fa06SMiquel Raynal
149*a430fa06SMiquel Raynal return 0;
150*a430fa06SMiquel Raynal }
151*a430fa06SMiquel Raynal
nand_block_isbad(void * buf,int block)152*a430fa06SMiquel Raynal static int nand_block_isbad(void *buf, int block)
153*a430fa06SMiquel Raynal {
154*a430fa06SMiquel Raynal int ret;
155*a430fa06SMiquel Raynal
156*a430fa06SMiquel Raynal ret = nand_read_oob(buf, block * pages_per_block);
157*a430fa06SMiquel Raynal if (ret < 0)
158*a430fa06SMiquel Raynal return ret;
159*a430fa06SMiquel Raynal
160*a430fa06SMiquel Raynal return *((uint8_t *)buf + CONFIG_SYS_NAND_BAD_BLOCK_POS) != 0xff;
161*a430fa06SMiquel Raynal }
162*a430fa06SMiquel Raynal
163*a430fa06SMiquel Raynal /* nand_init() - initialize data to make nand usable by SPL */
nand_init(void)164*a430fa06SMiquel Raynal void nand_init(void)
165*a430fa06SMiquel Raynal {
166*a430fa06SMiquel Raynal /* access to main area */
167*a430fa06SMiquel Raynal writel(0, denali_flash_reg + TRANSFER_SPARE_REG);
168*a430fa06SMiquel Raynal
169*a430fa06SMiquel Raynal /*
170*a430fa06SMiquel Raynal * These registers are expected to be already set by the hardware
171*a430fa06SMiquel Raynal * or earlier boot code. So we read these values out.
172*a430fa06SMiquel Raynal */
173*a430fa06SMiquel Raynal page_size = readl(denali_flash_reg + DEVICE_MAIN_AREA_SIZE);
174*a430fa06SMiquel Raynal oob_size = readl(denali_flash_reg + DEVICE_SPARE_AREA_SIZE);
175*a430fa06SMiquel Raynal pages_per_block = readl(denali_flash_reg + PAGES_PER_BLOCK);
176*a430fa06SMiquel Raynal }
177*a430fa06SMiquel Raynal
nand_spl_load_image(uint32_t offs,unsigned int size,void * dst)178*a430fa06SMiquel Raynal int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
179*a430fa06SMiquel Raynal {
180*a430fa06SMiquel Raynal int block, page, column, readlen;
181*a430fa06SMiquel Raynal int ret;
182*a430fa06SMiquel Raynal int force_bad_block_check = 1;
183*a430fa06SMiquel Raynal
184*a430fa06SMiquel Raynal page = offs / page_size;
185*a430fa06SMiquel Raynal column = offs % page_size;
186*a430fa06SMiquel Raynal
187*a430fa06SMiquel Raynal block = page / pages_per_block;
188*a430fa06SMiquel Raynal page = page % pages_per_block;
189*a430fa06SMiquel Raynal
190*a430fa06SMiquel Raynal while (size) {
191*a430fa06SMiquel Raynal if (force_bad_block_check || page == 0) {
192*a430fa06SMiquel Raynal ret = nand_block_isbad(dst, block);
193*a430fa06SMiquel Raynal if (ret < 0)
194*a430fa06SMiquel Raynal return ret;
195*a430fa06SMiquel Raynal
196*a430fa06SMiquel Raynal if (ret) {
197*a430fa06SMiquel Raynal block++;
198*a430fa06SMiquel Raynal continue;
199*a430fa06SMiquel Raynal }
200*a430fa06SMiquel Raynal }
201*a430fa06SMiquel Raynal
202*a430fa06SMiquel Raynal force_bad_block_check = 0;
203*a430fa06SMiquel Raynal
204*a430fa06SMiquel Raynal ret = nand_read_page(dst, block * pages_per_block + page);
205*a430fa06SMiquel Raynal if (ret < 0)
206*a430fa06SMiquel Raynal return ret;
207*a430fa06SMiquel Raynal
208*a430fa06SMiquel Raynal readlen = min(page_size - column, (int)size);
209*a430fa06SMiquel Raynal
210*a430fa06SMiquel Raynal if (unlikely(column)) {
211*a430fa06SMiquel Raynal /* Partial page read */
212*a430fa06SMiquel Raynal memmove(dst, dst + column, readlen);
213*a430fa06SMiquel Raynal column = 0;
214*a430fa06SMiquel Raynal }
215*a430fa06SMiquel Raynal
216*a430fa06SMiquel Raynal size -= readlen;
217*a430fa06SMiquel Raynal dst += readlen;
218*a430fa06SMiquel Raynal page++;
219*a430fa06SMiquel Raynal if (page == pages_per_block) {
220*a430fa06SMiquel Raynal block++;
221*a430fa06SMiquel Raynal page = 0;
222*a430fa06SMiquel Raynal }
223*a430fa06SMiquel Raynal }
224*a430fa06SMiquel Raynal
225*a430fa06SMiquel Raynal return 0;
226*a430fa06SMiquel Raynal }
227*a430fa06SMiquel Raynal
nand_deselect(void)228*a430fa06SMiquel Raynal void nand_deselect(void) {}
229