jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nand / ecc.c
1 // SPDX-License-Identifier: GPL-2.0-or-later WITH eCos-exception-2.0
2
3 /*
4 * This file contains an ECC algorithm from Toshiba that allows for detection
5 * and correction of 1-bit errors in a 256 byte block of data.
6 *
7 * [ Extracted from the initial code found in some early Linux versions.
8 * The current Linux code is bigger while being faster, but this is of
9 * no real benefit when the bottleneck largely remains the JTAG link. ]
10 *
11 * Copyright (C) 2000-2004 Steven J. Hill (sjhill at realitydiluted.com)
12 * Toshiba America Electronics Components, Inc.
13 *
14 * Copyright (C) 2006 Thomas Gleixner <tglx at linutronix.de>
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include "core.h"
22
23 /*
24 * Pre-calculated 256-way 1 byte column parity
25 */
26 static const uint8_t nand_ecc_precalc_table[] = {
27 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
28 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
29 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
30 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
31 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
32 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
33 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
34 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
35 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
36 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
37 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
38 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
39 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
40 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
41 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
42 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
43 };
44
45 /*
46 * nand_calculate_ecc - Calculate 3-byte ECC for 256-byte block
47 */
48 int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ecc_code)
49 {
50 uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
51 int i;
52
53 /* Initialize variables */
54 reg1 = reg2 = reg3 = 0;
55
56 /* Build up column parity */
57 for (i = 0; i < 256; i++) {
58 /* Get CP0 - CP5 from table */
59 idx = nand_ecc_precalc_table[*dat++];
60 reg1 ^= (idx & 0x3f);
61
62 /* All bit XOR = 1 ? */
63 if (idx & 0x40) {
64 reg3 ^= (uint8_t) i;
65 reg2 ^= ~((uint8_t) i);
66 }
67 }
68
69 /* Create non-inverted ECC code from line parity */
70 tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */
71 tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
72 tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
73 tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
74 tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
75 tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
76 tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
77 tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
78
79 tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */
80 tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
81 tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
82 tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
83 tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
84 tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
85 tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
86 tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
87
88 /* Calculate final ECC code */
89 #ifdef NAND_ECC_SMC
90 ecc_code[0] = ~tmp2;
91 ecc_code[1] = ~tmp1;
92 #else
93 ecc_code[0] = ~tmp1;
94 ecc_code[1] = ~tmp2;
95 #endif
96 ecc_code[2] = ((~reg1) << 2) | 0x03;
97
98 return 0;
99 }
100
101 static inline int countbits(uint32_t b)
102 {
103 int res = 0;
104
105 for (; b; b >>= 1)
106 res += b & 0x01;
107 return res;
108 }
109
110 /**
111 * nand_correct_data - Detect and correct a 1 bit error for 256 byte block
112 */
113 int nand_correct_data(struct nand_device *nand, u_char *dat,
114 u_char *read_ecc, u_char *calc_ecc)
115 {
116 uint8_t s0, s1, s2;
117
118 #ifdef NAND_ECC_SMC
119 s0 = calc_ecc[0] ^ read_ecc[0];
120 s1 = calc_ecc[1] ^ read_ecc[1];
121 s2 = calc_ecc[2] ^ read_ecc[2];
122 #else
123 s1 = calc_ecc[0] ^ read_ecc[0];
124 s0 = calc_ecc[1] ^ read_ecc[1];
125 s2 = calc_ecc[2] ^ read_ecc[2];
126 #endif
127 if ((s0 | s1 | s2) == 0)
128 return 0;
129
130 /* Check for a single bit error */
131 if (((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
132 ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
133 ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
134
135 uint32_t byteoffs, bitnum;
136
137 byteoffs = (s1 << 0) & 0x80;
138 byteoffs |= (s1 << 1) & 0x40;
139 byteoffs |= (s1 << 2) & 0x20;
140 byteoffs |= (s1 << 3) & 0x10;
141
142 byteoffs |= (s0 >> 4) & 0x08;
143 byteoffs |= (s0 >> 3) & 0x04;
144 byteoffs |= (s0 >> 2) & 0x02;
145 byteoffs |= (s0 >> 1) & 0x01;
146
147 bitnum = (s2 >> 5) & 0x04;
148 bitnum |= (s2 >> 4) & 0x02;
149 bitnum |= (s2 >> 3) & 0x01;
150
151 dat[byteoffs] ^= (1 << bitnum);
152
153 return 1;
154 }
155
156 if (countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 << 16)) == 1)
157 return 1;
158
159 return -1;
160 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)