blob: 885dec3de0ce8ad6323d17b9573abf7ae669b64a [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 },
102};
103
104static inline uint32_t ecc_read32(struct mtk_snand *snf, uint32_t reg)
105{
106 return readl(snf->ecc_base + reg);
107}
108
109static inline void ecc_write32(struct mtk_snand *snf, uint32_t reg,
110 uint32_t val)
111{
112 writel(val, snf->ecc_base + reg);
113}
114
115static inline void ecc_write16(struct mtk_snand *snf, uint32_t reg,
116 uint16_t val)
117{
118 writew(val, snf->ecc_base + reg);
119}
120
121static int mtk_ecc_poll(struct mtk_snand *snf, uint32_t reg, uint32_t bits)
122{
123 uint32_t val;
124
125 return read16_poll_timeout(snf->ecc_base + reg, val, (val & bits), 0,
126 ECC_TIMEOUT);
127}
128
129static int mtk_ecc_wait_idle(struct mtk_snand *snf, uint32_t reg)
130{
131 int ret;
132
133 ret = mtk_ecc_poll(snf, reg, ECC_IDLE);
134 if (ret) {
135 snand_log_ecc(snf->pdev, "ECC engine is busy\n");
136 return -EBUSY;
137 }
138
139 return 0;
140}
141
142int mtk_ecc_setup(struct mtk_snand *snf, void *fmdaddr, uint32_t max_ecc_bytes,
143 uint32_t msg_size)
144{
145 uint32_t i, val, ecc_msg_bits, ecc_strength;
146 int ret;
147
148 snf->ecc_soc = &mtk_ecc_socs[snf->soc];
149
150 snf->ecc_parity_bits = fls(1 + 8 * msg_size);
151 ecc_strength = max_ecc_bytes * 8 / snf->ecc_parity_bits;
152
153 for (i = snf->ecc_soc->num_ecc_cap - 1; i >= 0; i--) {
154 if (snf->ecc_soc->ecc_caps[i] <= ecc_strength)
155 break;
156 }
157
158 if (unlikely(i < 0)) {
159 snand_log_ecc(snf->pdev, "Page size %u+%u is not supported\n",
160 snf->writesize, snf->oobsize);
161 return -ENOTSUPP;
162 }
163
164 snf->ecc_strength = snf->ecc_soc->ecc_caps[i];
165 snf->ecc_bytes = DIV_ROUND_UP(snf->ecc_strength * snf->ecc_parity_bits,
166 8);
167
168 /* Encoder config */
169 ecc_write16(snf, ECC_ENCCON, 0);
170 ret = mtk_ecc_wait_idle(snf, ECC_ENCIDLE);
171 if (ret)
172 return ret;
173
174 ecc_msg_bits = msg_size * 8;
175 val = (ecc_msg_bits << ENC_MS_S) |
176 (ECC_MODE_NFI << snf->ecc_soc->mode_shift) | i;
177 ecc_write32(snf, ECC_ENCCNFG, val);
178
179 /* Decoder config */
180 ecc_write16(snf, ECC_DECCON, 0);
181 ret = mtk_ecc_wait_idle(snf, ECC_DECIDLE);
182 if (ret)
183 return ret;
184
185 ecc_msg_bits += snf->ecc_strength * snf->ecc_parity_bits;
186 val = DEC_EMPTY_EN | (ecc_msg_bits << DEC_CS_S) |
187 (DEC_CON_CORRECT << DEC_CON_S) |
188 (ECC_MODE_NFI << snf->ecc_soc->mode_shift) | i;
189 ecc_write32(snf, ECC_DECCNFG, val);
190
191 return 0;
192}
193
194int mtk_snand_ecc_encoder_start(struct mtk_snand *snf)
195{
196 int ret;
197
198 ret = mtk_ecc_wait_idle(snf, ECC_ENCIDLE);
199 if (ret) {
200 ecc_write16(snf, ECC_ENCCON, 0);
201 mtk_ecc_wait_idle(snf, ECC_ENCIDLE);
202 }
203
204 ecc_write16(snf, ECC_ENCCON, ENC_EN);
205
206 return 0;
207}
208
209void mtk_snand_ecc_encoder_stop(struct mtk_snand *snf)
210{
211 mtk_ecc_wait_idle(snf, ECC_ENCIDLE);
212 ecc_write16(snf, ECC_ENCCON, 0);
213}
214
215int mtk_snand_ecc_decoder_start(struct mtk_snand *snf)
216{
217 int ret;
218
219 ret = mtk_ecc_wait_idle(snf, ECC_DECIDLE);
220 if (ret) {
221 ecc_write16(snf, ECC_DECCON, 0);
222 mtk_ecc_wait_idle(snf, ECC_DECIDLE);
223 }
224
225 ecc_write16(snf, ECC_DECCON, DEC_EN);
226
227 return 0;
228}
229
230void mtk_snand_ecc_decoder_stop(struct mtk_snand *snf)
231{
232 mtk_ecc_wait_idle(snf, ECC_DECIDLE);
233 ecc_write16(snf, ECC_DECCON, 0);
234}
235
236int mtk_ecc_wait_decoder_done(struct mtk_snand *snf)
237{
238 uint16_t val, step_mask = (1 << snf->ecc_steps) - 1;
239 uint32_t reg = snf->ecc_soc->regs[ECC_DECDONE];
240 int ret;
241
242 ret = read16_poll_timeout(snf->ecc_base + reg, val,
243 (val & step_mask) == step_mask, 0,
244 ECC_TIMEOUT);
245 if (ret)
246 snand_log_ecc(snf->pdev, "ECC decoder is busy\n");
247
248 return ret;
249}
250
developer4da1bed2021-05-08 17:30:37 +0800251int mtk_ecc_check_decode_error(struct mtk_snand *snf)
developerfd40db22021-04-29 10:08:25 +0800252{
253 uint32_t i, regi, fi, errnum;
254 uint32_t errnum_shift = snf->ecc_soc->errnum_shift;
255 uint32_t errnum_mask = (1 << snf->ecc_soc->errnum_bits) - 1;
256 int ret = 0;
257
258 for (i = 0; i < snf->ecc_steps; i++) {
259 regi = i / 4;
260 fi = i % 4;
261
262 errnum = ecc_read32(snf, ECC_DECENUM(regi));
263 errnum = (errnum >> (fi * errnum_shift)) & errnum_mask;
developerfd40db22021-04-29 10:08:25 +0800264
265 if (errnum <= snf->ecc_strength) {
developer4da1bed2021-05-08 17:30:37 +0800266 snf->sect_bf[i] = errnum;
267 } else {
268 snf->sect_bf[i] = -1;
269 ret = -EBADMSG;
developerfd40db22021-04-29 10:08:25 +0800270 }
developerfd40db22021-04-29 10:08:25 +0800271 }
272
273 return ret;
274}
developer4da1bed2021-05-08 17:30:37 +0800275
276static int mtk_ecc_check_buf_bitflips(struct mtk_snand *snf, const void *buf,
277 size_t len, uint32_t bitflips)
278{
279 const uint8_t *buf8 = buf;
280 const uint32_t *buf32;
281 uint32_t d, weight;
282
283 while (len && ((uintptr_t)buf8) % sizeof(uint32_t)) {
284 weight = hweight8(*buf8);
285 bitflips += BITS_PER_BYTE - weight;
286 buf8++;
287 len--;
288
289 if (bitflips > snf->ecc_strength)
290 return -EBADMSG;
291 }
292
293 buf32 = (const uint32_t *)buf8;
294 while (len >= sizeof(uint32_t)) {
295 d = *buf32;
296
297 if (d != ~0) {
298 weight = hweight32(d);
299 bitflips += sizeof(uint32_t) * BITS_PER_BYTE - weight;
300 }
301
302 buf32++;
303 len -= sizeof(uint32_t);
304
305 if (bitflips > snf->ecc_strength)
306 return -EBADMSG;
307 }
308
309 buf8 = (const uint8_t *)buf32;
310 while (len) {
311 weight = hweight8(*buf8);
312 bitflips += BITS_PER_BYTE - weight;
313 buf8++;
314 len--;
315
316 if (bitflips > snf->ecc_strength)
317 return -EBADMSG;
318 }
319
320 return bitflips;
321}
322
323static int mtk_ecc_check_parity_bitflips(struct mtk_snand *snf, const void *buf,
324 uint32_t bits, uint32_t bitflips)
325{
326 uint32_t len, i;
327 uint8_t b;
328 int rc;
329
330 len = bits >> 3;
331 bits &= 7;
332
333 rc = mtk_ecc_check_buf_bitflips(snf, buf, len, bitflips);
334 if (!bits || rc < 0)
335 return rc;
336
337 bitflips = rc;
338
339 /* We want a precise count of bits */
340 b = ((const uint8_t *)buf)[len];
341 for (i = 0; i < bits; i++) {
342 if (!(b & BIT(i)))
343 bitflips++;
344 }
345
346 if (bitflips > snf->ecc_strength)
347 return -EBADMSG;
348
349 return bitflips;
350}
351
352static void mtk_ecc_reset_parity(void *buf, uint32_t bits)
353{
354 uint32_t len;
355
356 len = bits >> 3;
357 bits &= 7;
358
359 memset(buf, 0xff, len);
360
361 /* Only reset bits protected by ECC to 1 */
362 if (bits)
363 ((uint8_t *)buf)[len] |= GENMASK(bits - 1, 0);
364}
365
366int mtk_ecc_fixup_empty_sector(struct mtk_snand *snf, uint32_t sect)
367{
368 uint32_t ecc_bytes = snf->spare_per_sector - snf->nfi_soc->fdm_size;
369 uint8_t *oob = snf->page_cache + snf->writesize;
370 uint8_t *data_ptr, *fdm_ptr, *ecc_ptr;
371 int bitflips = 0, ecc_bits, parity_bits;
372
373 parity_bits = fls(snf->nfi_soc->sector_size * 8);
374 ecc_bits = snf->ecc_strength * parity_bits;
375
376 data_ptr = snf->page_cache + sect * snf->nfi_soc->sector_size;
377 fdm_ptr = oob + sect * snf->nfi_soc->fdm_size;
378 ecc_ptr = oob + snf->ecc_steps * snf->nfi_soc->fdm_size +
379 sect * ecc_bytes;
380
381 /*
382 * Check whether DATA + FDM + ECC of a sector contains correctable
383 * bitflips
384 */
385 bitflips = mtk_ecc_check_buf_bitflips(snf, data_ptr,
386 snf->nfi_soc->sector_size,
387 bitflips);
388 if (bitflips < 0)
389 return -EBADMSG;
390
391 bitflips = mtk_ecc_check_buf_bitflips(snf, fdm_ptr,
392 snf->nfi_soc->fdm_ecc_size,
393 bitflips);
394 if (bitflips < 0)
395 return -EBADMSG;
396
397 bitflips = mtk_ecc_check_parity_bitflips(snf, ecc_ptr, ecc_bits,
398 bitflips);
399 if (bitflips < 0)
400 return -EBADMSG;
401
402 if (!bitflips)
403 return 0;
404
405 /* Reset the data of this sector to 0xff */
406 memset(data_ptr, 0xff, snf->nfi_soc->sector_size);
407 memset(fdm_ptr, 0xff, snf->nfi_soc->fdm_ecc_size);
408 mtk_ecc_reset_parity(ecc_ptr, ecc_bits);
409
410 return bitflips;
411}