1 /*
2 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <stdint.h>
9
10 #include <platform_def.h>
11
12 #include <arch_helpers.h>
13 #include <common/debug.h>
14 #include <drivers/io/io_block.h>
15 #include <lib/mmio.h>
16 #include <lib/utils_def.h>
17
18 #include "uniphier.h"
19
20 #define NAND_CMD_READ0 0
21 #define NAND_CMD_READSTART 0x30
22
23 #define DENALI_ECC_ENABLE 0x0e0
24 #define DENALI_PAGES_PER_BLOCK 0x150
25 #define DENALI_DEVICE_MAIN_AREA_SIZE 0x170
26 #define DENALI_DEVICE_SPARE_AREA_SIZE 0x180
27 #define DENALI_TWO_ROW_ADDR_CYCLES 0x190
28 #define DENALI_INTR_STATUS0 0x410
29 #define DENALI_INTR_ECC_UNCOR_ERR BIT(1)
30 #define DENALI_INTR_DMA_CMD_COMP BIT(2)
31 #define DENALI_INTR_INT_ACT BIT(12)
32
33 #define DENALI_DMA_ENABLE 0x700
34
35 #define DENALI_HOST_ADDR 0x00
36 #define DENALI_HOST_DATA 0x10
37
38 #define DENALI_MAP01 (1 << 26)
39 #define DENALI_MAP10 (2 << 26)
40 #define DENALI_MAP11 (3 << 26)
41
42 #define DENALI_MAP11_CMD ((DENALI_MAP11) | 0)
43 #define DENALI_MAP11_ADDR ((DENALI_MAP11) | 1)
44 #define DENALI_MAP11_DATA ((DENALI_MAP11) | 2)
45
46 #define DENALI_ACCESS_DEFAULT_AREA 0x42
47
48 #define UNIPHIER_NAND_BBT_UNKNOWN 0xff
49
50 struct uniphier_nand {
51 uintptr_t host_base;
52 uintptr_t reg_base;
53 int pages_per_block;
54 int page_size;
55 int two_row_addr_cycles;
56 uint8_t bbt[16];
57 };
58
59 struct uniphier_nand uniphier_nand;
60
uniphier_nand_host_write(struct uniphier_nand * nand,uint32_t addr,uint32_t data)61 static void uniphier_nand_host_write(struct uniphier_nand *nand,
62 uint32_t addr, uint32_t data)
63 {
64 mmio_write_32(nand->host_base + DENALI_HOST_ADDR, addr);
65 mmio_write_32(nand->host_base + DENALI_HOST_DATA, data);
66 }
67
uniphier_nand_host_read(struct uniphier_nand * nand,uint32_t addr)68 static uint32_t uniphier_nand_host_read(struct uniphier_nand *nand,
69 uint32_t addr)
70 {
71 mmio_write_32(nand->host_base + DENALI_HOST_ADDR, addr);
72 return mmio_read_32(nand->host_base + DENALI_HOST_DATA);
73 }
74
uniphier_nand_block_isbad(struct uniphier_nand * nand,int block)75 static int uniphier_nand_block_isbad(struct uniphier_nand *nand, int block)
76 {
77 int page = nand->pages_per_block * block;
78 int column = nand->page_size;
79 uint8_t bbm;
80 uint32_t status;
81 int is_bad;
82
83 /* use cache if available */
84 if (block < ARRAY_SIZE(nand->bbt) &&
85 nand->bbt[block] != UNIPHIER_NAND_BBT_UNKNOWN)
86 return nand->bbt[block];
87
88 mmio_write_32(nand->reg_base + DENALI_ECC_ENABLE, 0);
89
90 mmio_write_32(nand->reg_base + DENALI_INTR_STATUS0, -1);
91
92 uniphier_nand_host_write(nand, DENALI_MAP11_CMD, NAND_CMD_READ0);
93 uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, column & 0xff);
94 uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, (column >> 8) & 0xff);
95 uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, page & 0xff);
96 uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, (page >> 8) & 0xff);
97 if (!nand->two_row_addr_cycles)
98 uniphier_nand_host_write(nand, DENALI_MAP11_ADDR,
99 (page >> 16) & 0xff);
100 uniphier_nand_host_write(nand, DENALI_MAP11_CMD, NAND_CMD_READSTART);
101
102 do {
103 status = mmio_read_32(nand->reg_base + DENALI_INTR_STATUS0);
104 } while (!(status & DENALI_INTR_INT_ACT));
105
106 bbm = uniphier_nand_host_read(nand, DENALI_MAP11_DATA);
107
108 is_bad = bbm != 0xff;
109
110 /* if possible, save the result for future re-use */
111 if (block < ARRAY_SIZE(nand->bbt))
112 nand->bbt[block] = is_bad;
113
114 if (is_bad)
115 WARN("found bad block at %d. skip.\n", block);
116
117 return is_bad;
118 }
119
uniphier_nand_read_pages(struct uniphier_nand * nand,uintptr_t buf,int page_start,int page_count)120 static int uniphier_nand_read_pages(struct uniphier_nand *nand, uintptr_t buf,
121 int page_start, int page_count)
122 {
123 uint32_t status;
124
125 mmio_write_32(nand->reg_base + DENALI_ECC_ENABLE, 1);
126 mmio_write_32(nand->reg_base + DENALI_DMA_ENABLE, 1);
127
128 mmio_write_32(nand->reg_base + DENALI_INTR_STATUS0, -1);
129
130 /* use Data DMA (64bit) */
131 mmio_write_32(nand->host_base + DENALI_HOST_ADDR,
132 DENALI_MAP10 | page_start);
133
134 /*
135 * 1. setup transfer type, interrupt when complete,
136 * burst len = 64 bytes, the number of pages
137 */
138 mmio_write_32(nand->host_base + DENALI_HOST_DATA,
139 0x01002000 | (64 << 16) | page_count);
140
141 /* 2. set memory low address */
142 mmio_write_32(nand->host_base + DENALI_HOST_DATA, buf);
143
144 /* 3. set memory high address */
145 mmio_write_32(nand->host_base + DENALI_HOST_DATA, buf >> 32);
146
147 do {
148 status = mmio_read_32(nand->reg_base + DENALI_INTR_STATUS0);
149 } while (!(status & DENALI_INTR_DMA_CMD_COMP));
150
151 mmio_write_32(nand->reg_base + DENALI_DMA_ENABLE, 0);
152
153 if (status & DENALI_INTR_ECC_UNCOR_ERR) {
154 ERROR("uncorrectable error in page range %d-%d",
155 page_start, page_start + page_count - 1);
156 return -EBADMSG;
157 }
158
159 return 0;
160 }
161
__uniphier_nand_read(struct uniphier_nand * nand,int lba,uintptr_t buf,size_t size)162 static size_t __uniphier_nand_read(struct uniphier_nand *nand, int lba,
163 uintptr_t buf, size_t size)
164 {
165 int pages_per_block = nand->pages_per_block;
166 int page_size = nand->page_size;
167 int blocks_to_skip = lba / pages_per_block;
168 int pages_to_read = div_round_up(size, page_size);
169 int page = lba % pages_per_block;
170 int block = 0;
171 uintptr_t p = buf;
172 int page_count, ret;
173
174 while (blocks_to_skip) {
175 ret = uniphier_nand_block_isbad(nand, block);
176 if (ret < 0)
177 goto out;
178
179 if (!ret)
180 blocks_to_skip--;
181
182 block++;
183 }
184
185 while (pages_to_read) {
186 ret = uniphier_nand_block_isbad(nand, block);
187 if (ret < 0)
188 goto out;
189
190 if (ret) {
191 block++;
192 continue;
193 }
194
195 page_count = MIN(pages_per_block - page, pages_to_read);
196
197 ret = uniphier_nand_read_pages(nand, p,
198 block * pages_per_block + page,
199 page_count);
200 if (ret)
201 goto out;
202
203 block++;
204 page = 0;
205 p += page_size * page_count;
206 pages_to_read -= page_count;
207 }
208
209 out:
210 /* number of read bytes */
211 return MIN(size, p - buf);
212 }
213
uniphier_nand_read(int lba,uintptr_t buf,size_t size)214 static size_t uniphier_nand_read(int lba, uintptr_t buf, size_t size)
215 {
216 size_t count;
217
218 inv_dcache_range(buf, size);
219
220 count = __uniphier_nand_read(&uniphier_nand, lba, buf, size);
221
222 inv_dcache_range(buf, size);
223
224 return count;
225 }
226
227 static struct io_block_dev_spec uniphier_nand_dev_spec = {
228 .ops = {
229 .read = uniphier_nand_read,
230 },
231 /* fill .block_size at run-time */
232 };
233
uniphier_nand_hw_init(struct uniphier_nand * nand)234 static int uniphier_nand_hw_init(struct uniphier_nand *nand)
235 {
236 int i;
237
238 for (i = 0; i < ARRAY_SIZE(nand->bbt); i++)
239 nand->bbt[i] = UNIPHIER_NAND_BBT_UNKNOWN;
240
241 nand->reg_base = nand->host_base + 0x100000;
242
243 nand->pages_per_block =
244 mmio_read_32(nand->reg_base + DENALI_PAGES_PER_BLOCK);
245
246 nand->page_size =
247 mmio_read_32(nand->reg_base + DENALI_DEVICE_MAIN_AREA_SIZE);
248
249 if (mmio_read_32(nand->reg_base + DENALI_TWO_ROW_ADDR_CYCLES) & BIT(0))
250 nand->two_row_addr_cycles = 1;
251
252 uniphier_nand_host_write(nand, DENALI_MAP10,
253 DENALI_ACCESS_DEFAULT_AREA);
254
255 return 0;
256 }
257
258 static const uintptr_t uniphier_nand_base[] = {
259 [UNIPHIER_SOC_LD11] = 0x68000000,
260 [UNIPHIER_SOC_LD20] = 0x68000000,
261 [UNIPHIER_SOC_PXS3] = 0x68000000,
262 };
263
uniphier_nand_init(unsigned int soc,struct io_block_dev_spec ** block_dev_spec)264 int uniphier_nand_init(unsigned int soc,
265 struct io_block_dev_spec **block_dev_spec)
266 {
267 int ret;
268
269 assert(soc < ARRAY_SIZE(uniphier_nand_base));
270 uniphier_nand.host_base = uniphier_nand_base[soc];
271 if (!uniphier_nand.host_base)
272 return -ENOTSUP;
273
274 ret = uniphier_nand_hw_init(&uniphier_nand);
275 if (ret)
276 return ret;
277
278 uniphier_nand_dev_spec.block_size = uniphier_nand.page_size;
279
280 *block_dev_spec = &uniphier_nand_dev_spec;
281
282 return 0;
283 }
284