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