blob: 450e6621fae9abd1af00ded79e253f4d7b197f37 [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/*
3 * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
4 *
5 * Author: Weijie Gao <weijie.gao@mediatek.com>
6 */
7
8#include "mtk-snand-def.h"
9
10/* ECC registers */
11#define ECC_ENCCON 0x000
12#define ENC_EN BIT(0)
13
14#define ECC_ENCCNFG 0x004
15#define ENC_MS_S 16
16#define ENC_BURST_EN BIT(8)
17#define ENC_TNUM_S 0
18
19#define ECC_ENCIDLE 0x00c
20#define ENC_IDLE BIT(0)
21
22#define ECC_DECCON 0x100
23#define DEC_EN BIT(0)
24
25#define ECC_DECCNFG 0x104
26#define DEC_EMPTY_EN BIT(31)
27#define DEC_CS_S 16
28#define DEC_CON_S 12
29#define DEC_CON_CORRECT 3
30#define DEC_BURST_EN BIT(8)
31#define DEC_TNUM_S 0
32
33#define ECC_DECIDLE 0x10c
34#define DEC_IDLE BIT(0)
35
36#define ECC_DECENUM0 0x114
37#define ECC_DECENUM(n) (ECC_DECENUM0 + (n) * 4)
38
39/* ECC_ENCIDLE & ECC_DECIDLE */
40#define ECC_IDLE BIT(0)
41
42/* ENC_MODE & DEC_MODE */
43#define ECC_MODE_NFI 1
44
45#define ECC_TIMEOUT 500000
46
47static const uint8_t mt7622_ecc_caps[] = { 4, 6, 8, 10, 12 };
48
developer80309642022-08-17 10:19:17 +080049static const uint8_t mt7981_ecc_caps[] = {
50 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24
51};
52
developerfd40db22021-04-29 10:08:25 +080053static const uint8_t mt7986_ecc_caps[] = {
54 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24
55};
56
57static const uint32_t mt7622_ecc_regs[] = {
58 [ECC_DECDONE] = 0x11c,
59};
60
developer80309642022-08-17 10:19:17 +080061static const uint32_t mt7981_ecc_regs[] = {
62 [ECC_DECDONE] = 0x124,
63};
64
developerfd40db22021-04-29 10:08:25 +080065static const uint32_t mt7986_ecc_regs[] = {
66 [ECC_DECDONE] = 0x124,
67};
68
69static const struct mtk_ecc_soc_data mtk_ecc_socs[__SNAND_SOC_MAX] = {
70 [SNAND_SOC_MT7622] = {
71 .ecc_caps = mt7622_ecc_caps,
72 .num_ecc_cap = ARRAY_SIZE(mt7622_ecc_caps),
73 .regs = mt7622_ecc_regs,
74 .mode_shift = 4,
75 .errnum_bits = 5,
76 .errnum_shift = 5,
77 },
78 [SNAND_SOC_MT7629] = {
79 .ecc_caps = mt7622_ecc_caps,
80 .num_ecc_cap = ARRAY_SIZE(mt7622_ecc_caps),
81 .regs = mt7622_ecc_regs,
82 .mode_shift = 4,
83 .errnum_bits = 5,
84 .errnum_shift = 5,
85 },
developer80309642022-08-17 10:19:17 +080086 [SNAND_SOC_MT7981] = {
87 .ecc_caps = mt7981_ecc_caps,
88 .num_ecc_cap = ARRAY_SIZE(mt7981_ecc_caps),
89 .regs = mt7981_ecc_regs,
90 .mode_shift = 5,
91 .errnum_bits = 5,
92 .errnum_shift = 8,
93 },
developerfd40db22021-04-29 10:08:25 +080094 [SNAND_SOC_MT7986] = {
95 .ecc_caps = mt7986_ecc_caps,
96 .num_ecc_cap = ARRAY_SIZE(mt7986_ecc_caps),
97 .regs = mt7986_ecc_regs,
98 .mode_shift = 5,
99 .errnum_bits = 5,
100 .errnum_shift = 8,
101 },
developerdfd23622022-11-25 19:02:20 +0800102 [SNAND_SOC_MT7988] = {
103 .ecc_caps = mt7986_ecc_caps,
104 .num_ecc_cap = ARRAY_SIZE(mt7986_ecc_caps),
105 .regs = mt7986_ecc_regs,
106 .mode_shift = 5,
107 .errnum_bits = 5,
108 .errnum_shift = 8,
109 },
developerfd40db22021-04-29 10:08:25 +0800110};
111
112static inline uint32_t ecc_read32(struct mtk_snand *snf, uint32_t reg)
113{
114 return readl(snf->ecc_base + reg);
115}
116
117static inline void ecc_write32(struct mtk_snand *snf, uint32_t reg,
118 uint32_t val)
119{
120 writel(val, snf->ecc_base + reg);
121}
122
123static inline void ecc_write16(struct mtk_snand *snf, uint32_t reg,
124 uint16_t val)
125{
126 writew(val, snf->ecc_base + reg);
127}
128
129static int mtk_ecc_poll(struct mtk_snand *snf, uint32_t reg, uint32_t bits)
130{
131 uint32_t val;
132
133 return read16_poll_timeout(snf->ecc_base + reg, val, (val & bits), 0,
134 ECC_TIMEOUT);
135}
136
137static int mtk_ecc_wait_idle(struct mtk_snand *snf, uint32_t reg)
138{
139 int ret;
140
141 ret = mtk_ecc_poll(snf, reg, ECC_IDLE);
142 if (ret) {
143 snand_log_ecc(snf->pdev, "ECC engine is busy\n");
144 return -EBUSY;
145 }
146
147 return 0;
148}
149
150int mtk_ecc_setup(struct mtk_snand *snf, void *fmdaddr, uint32_t max_ecc_bytes,
151 uint32_t msg_size)
152{
153 uint32_t i, val, ecc_msg_bits, ecc_strength;
154 int ret;
155
156 snf->ecc_soc = &mtk_ecc_socs[snf->soc];
157
158 snf->ecc_parity_bits = fls(1 + 8 * msg_size);
159 ecc_strength = max_ecc_bytes * 8 / snf->ecc_parity_bits;
160
161 for (i = snf->ecc_soc->num_ecc_cap - 1; i >= 0; i--) {
162 if (snf->ecc_soc->ecc_caps[i] <= ecc_strength)
163 break;
164 }
165
166 if (unlikely(i < 0)) {
167 snand_log_ecc(snf->pdev, "Page size %u+%u is not supported\n",
168 snf->writesize, snf->oobsize);
169 return -ENOTSUPP;
170 }
171
172 snf->ecc_strength = snf->ecc_soc->ecc_caps[i];
173 snf->ecc_bytes = DIV_ROUND_UP(snf->ecc_strength * snf->ecc_parity_bits,
174 8);
175
176 /* Encoder config */
177 ecc_write16(snf, ECC_ENCCON, 0);
178 ret = mtk_ecc_wait_idle(snf, ECC_ENCIDLE);
179 if (ret)
180 return ret;
181
182 ecc_msg_bits = msg_size * 8;
183 val = (ecc_msg_bits << ENC_MS_S) |
184 (ECC_MODE_NFI << snf->ecc_soc->mode_shift) | i;
185 ecc_write32(snf, ECC_ENCCNFG, val);
186
187 /* Decoder config */
188 ecc_write16(snf, ECC_DECCON, 0);
189 ret = mtk_ecc_wait_idle(snf, ECC_DECIDLE);
190 if (ret)
191 return ret;
192
193 ecc_msg_bits += snf->ecc_strength * snf->ecc_parity_bits;
194 val = DEC_EMPTY_EN | (ecc_msg_bits << DEC_CS_S) |
195 (DEC_CON_CORRECT << DEC_CON_S) |
196 (ECC_MODE_NFI << snf->ecc_soc->mode_shift) | i;
197 ecc_write32(snf, ECC_DECCNFG, val);
198
199 return 0;
200}
201
202int mtk_snand_ecc_encoder_start(struct mtk_snand *snf)
203{
204 int ret;
205
206 ret = mtk_ecc_wait_idle(snf, ECC_ENCIDLE);
207 if (ret) {
208 ecc_write16(snf, ECC_ENCCON, 0);
209 mtk_ecc_wait_idle(snf, ECC_ENCIDLE);
210 }
211
212 ecc_write16(snf, ECC_ENCCON, ENC_EN);
213
214 return 0;
215}
216
217void mtk_snand_ecc_encoder_stop(struct mtk_snand *snf)
218{
219 mtk_ecc_wait_idle(snf, ECC_ENCIDLE);
220 ecc_write16(snf, ECC_ENCCON, 0);
221}
222
223int mtk_snand_ecc_decoder_start(struct mtk_snand *snf)
224{
225 int ret;
226
227 ret = mtk_ecc_wait_idle(snf, ECC_DECIDLE);
228 if (ret) {
229 ecc_write16(snf, ECC_DECCON, 0);
230 mtk_ecc_wait_idle(snf, ECC_DECIDLE);
231 }
232
233 ecc_write16(snf, ECC_DECCON, DEC_EN);
234
235 return 0;
236}
237
238void mtk_snand_ecc_decoder_stop(struct mtk_snand *snf)
239{
240 mtk_ecc_wait_idle(snf, ECC_DECIDLE);
241 ecc_write16(snf, ECC_DECCON, 0);
242}
243
244int mtk_ecc_wait_decoder_done(struct mtk_snand *snf)
245{
246 uint16_t val, step_mask = (1 << snf->ecc_steps) - 1;
247 uint32_t reg = snf->ecc_soc->regs[ECC_DECDONE];
248 int ret;
249
250 ret = read16_poll_timeout(snf->ecc_base + reg, val,
251 (val & step_mask) == step_mask, 0,
252 ECC_TIMEOUT);
253 if (ret)
254 snand_log_ecc(snf->pdev, "ECC decoder is busy\n");
255
256 return ret;
257}
258
developer4da1bed2021-05-08 17:30:37 +0800259int mtk_ecc_check_decode_error(struct mtk_snand *snf)
developerfd40db22021-04-29 10:08:25 +0800260{
261 uint32_t i, regi, fi, errnum;
262 uint32_t errnum_shift = snf->ecc_soc->errnum_shift;
263 uint32_t errnum_mask = (1 << snf->ecc_soc->errnum_bits) - 1;
264 int ret = 0;
265
266 for (i = 0; i < snf->ecc_steps; i++) {
267 regi = i / 4;
268 fi = i % 4;
269
270 errnum = ecc_read32(snf, ECC_DECENUM(regi));
271 errnum = (errnum >> (fi * errnum_shift)) & errnum_mask;
developerfd40db22021-04-29 10:08:25 +0800272
273 if (errnum <= snf->ecc_strength) {
developer4da1bed2021-05-08 17:30:37 +0800274 snf->sect_bf[i] = errnum;
275 } else {
276 snf->sect_bf[i] = -1;
277 ret = -EBADMSG;
developerfd40db22021-04-29 10:08:25 +0800278 }
developerfd40db22021-04-29 10:08:25 +0800279 }
280
281 return ret;
282}
developer4da1bed2021-05-08 17:30:37 +0800283
284static int mtk_ecc_check_buf_bitflips(struct mtk_snand *snf, const void *buf,
285 size_t len, uint32_t bitflips)
286{
287 const uint8_t *buf8 = buf;
288 const uint32_t *buf32;
289 uint32_t d, weight;
290
291 while (len && ((uintptr_t)buf8) % sizeof(uint32_t)) {
292 weight = hweight8(*buf8);
293 bitflips += BITS_PER_BYTE - weight;
294 buf8++;
295 len--;
296
297 if (bitflips > snf->ecc_strength)
298 return -EBADMSG;
299 }
300
301 buf32 = (const uint32_t *)buf8;
302 while (len >= sizeof(uint32_t)) {
303 d = *buf32;
304
305 if (d != ~0) {
306 weight = hweight32(d);
307 bitflips += sizeof(uint32_t) * BITS_PER_BYTE - weight;
308 }
309
310 buf32++;
311 len -= sizeof(uint32_t);
312
313 if (bitflips > snf->ecc_strength)
314 return -EBADMSG;
315 }
316
317 buf8 = (const uint8_t *)buf32;
318 while (len) {
319 weight = hweight8(*buf8);
320 bitflips += BITS_PER_BYTE - weight;
321 buf8++;
322 len--;
323
324 if (bitflips > snf->ecc_strength)
325 return -EBADMSG;
326 }
327
328 return bitflips;
329}
330
331static int mtk_ecc_check_parity_bitflips(struct mtk_snand *snf, const void *buf,
332 uint32_t bits, uint32_t bitflips)
333{
334 uint32_t len, i;
335 uint8_t b;
336 int rc;
337
338 len = bits >> 3;
339 bits &= 7;
340
341 rc = mtk_ecc_check_buf_bitflips(snf, buf, len, bitflips);
342 if (!bits || rc < 0)
343 return rc;
344
345 bitflips = rc;
346
347 /* We want a precise count of bits */
348 b = ((const uint8_t *)buf)[len];
349 for (i = 0; i < bits; i++) {
350 if (!(b & BIT(i)))
351 bitflips++;
352 }
353
354 if (bitflips > snf->ecc_strength)
355 return -EBADMSG;
356
357 return bitflips;
358}
359
360static void mtk_ecc_reset_parity(void *buf, uint32_t bits)
361{
362 uint32_t len;
363
364 len = bits >> 3;
365 bits &= 7;
366
367 memset(buf, 0xff, len);
368
369 /* Only reset bits protected by ECC to 1 */
370 if (bits)
371 ((uint8_t *)buf)[len] |= GENMASK(bits - 1, 0);
372}
373
374int mtk_ecc_fixup_empty_sector(struct mtk_snand *snf, uint32_t sect)
375{
376 uint32_t ecc_bytes = snf->spare_per_sector - snf->nfi_soc->fdm_size;
377 uint8_t *oob = snf->page_cache + snf->writesize;
378 uint8_t *data_ptr, *fdm_ptr, *ecc_ptr;
379 int bitflips = 0, ecc_bits, parity_bits;
380
381 parity_bits = fls(snf->nfi_soc->sector_size * 8);
382 ecc_bits = snf->ecc_strength * parity_bits;
383
384 data_ptr = snf->page_cache + sect * snf->nfi_soc->sector_size;
385 fdm_ptr = oob + sect * snf->nfi_soc->fdm_size;
386 ecc_ptr = oob + snf->ecc_steps * snf->nfi_soc->fdm_size +
387 sect * ecc_bytes;
388
389 /*
390 * Check whether DATA + FDM + ECC of a sector contains correctable
391 * bitflips
392 */
393 bitflips = mtk_ecc_check_buf_bitflips(snf, data_ptr,
394 snf->nfi_soc->sector_size,
395 bitflips);
396 if (bitflips < 0)
397 return -EBADMSG;
398
399 bitflips = mtk_ecc_check_buf_bitflips(snf, fdm_ptr,
400 snf->nfi_soc->fdm_ecc_size,
401 bitflips);
402 if (bitflips < 0)
403 return -EBADMSG;
404
405 bitflips = mtk_ecc_check_parity_bitflips(snf, ecc_ptr, ecc_bits,
406 bitflips);
407 if (bitflips < 0)
408 return -EBADMSG;
409
410 if (!bitflips)
411 return 0;
412
413 /* Reset the data of this sector to 0xff */
414 memset(data_ptr, 0xff, snf->nfi_soc->sector_size);
415 memset(fdm_ptr, 0xff, snf->nfi_soc->fdm_ecc_size);
416 mtk_ecc_reset_parity(ecc_ptr, ecc_bits);
417
418 return bitflips;
419}