jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nand / ecc.c
1 /*
2 * This file contains an ECC algorithm from Toshiba that allows for detection
3 * and correction of 1-bit errors in a 256 byte block of data.
4 *
5 * [ Extracted from the initial code found in some early Linux versions.
6 * The current Linux code is bigger while being faster, but this is of
7 * no real benefit when the bottleneck largely remains the JTAG link. ]
8 *
9 * Copyright (C) 2000-2004 Steven J. Hill (sjhill at realitydiluted.com)
10 * Toshiba America Electronics Components, Inc.
11 *
12 * Copyright (C) 2006 Thomas Gleixner <tglx at linutronix.de>
13 *
14 * This file is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 or (at your option) any
17 * later version.
18 *
19 * This file is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * As a special exception, if other files instantiate templates or use
28 * macros or inline functions from these files, or you compile these
29 * files and link them with other works to produce a work based on these
30 * files, these files do not by themselves cause the resulting work to be
31 * covered by the GNU General Public License. However the source code for
32 * these files must still be made available in accordance with section (3)
33 * of the GNU General Public License.
34 *
35 * This exception does not invalidate any other reasons why a work based on
36 * this file might be covered by the GNU General Public License.
37 */
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include "core.h"
44
45 /*
46 * Pre-calculated 256-way 1 byte column parity
47 */
48 static const uint8_t nand_ecc_precalc_table[] = {
49 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
50 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
51 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
52 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
53 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
54 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
55 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
56 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
57 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
58 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
59 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
60 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
61 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
62 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
63 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
64 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
65 };
66
67 /*
68 * nand_calculate_ecc - Calculate 3-byte ECC for 256-byte block
69 */
70 int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ecc_code)
71 {
72 uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
73 int i;
74
75 /* Initialize variables */
76 reg1 = reg2 = reg3 = 0;
77
78 /* Build up column parity */
79 for (i = 0; i < 256; i++) {
80 /* Get CP0 - CP5 from table */
81 idx = nand_ecc_precalc_table[*dat++];
82 reg1 ^= (idx & 0x3f);
83
84 /* All bit XOR = 1 ? */
85 if (idx & 0x40) {
86 reg3 ^= (uint8_t) i;
87 reg2 ^= ~((uint8_t) i);
88 }
89 }
90
91 /* Create non-inverted ECC code from line parity */
92 tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */
93 tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
94 tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
95 tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
96 tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
97 tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
98 tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
99 tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
100
101 tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */
102 tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
103 tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
104 tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
105 tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
106 tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
107 tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
108 tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
109
110 /* Calculate final ECC code */
111 #ifdef NAND_ECC_SMC
112 ecc_code[0] = ~tmp2;
113 ecc_code[1] = ~tmp1;
114 #else
115 ecc_code[0] = ~tmp1;
116 ecc_code[1] = ~tmp2;
117 #endif
118 ecc_code[2] = ((~reg1) << 2) | 0x03;
119
120 return 0;
121 }
122
123 static inline int countbits(uint32_t b)
124 {
125 int res = 0;
126
127 for (; b; b >>= 1)
128 res += b & 0x01;
129 return res;
130 }
131
132 /**
133 * nand_correct_data - Detect and correct a 1 bit error for 256 byte block
134 */
135 int nand_correct_data(struct nand_device *nand, u_char *dat,
136 u_char *read_ecc, u_char *calc_ecc)
137 {
138 uint8_t s0, s1, s2;
139
140 #ifdef NAND_ECC_SMC
141 s0 = calc_ecc[0] ^ read_ecc[0];
142 s1 = calc_ecc[1] ^ read_ecc[1];
143 s2 = calc_ecc[2] ^ read_ecc[2];
144 #else
145 s1 = calc_ecc[0] ^ read_ecc[0];
146 s0 = calc_ecc[1] ^ read_ecc[1];
147 s2 = calc_ecc[2] ^ read_ecc[2];
148 #endif
149 if ((s0 | s1 | s2) == 0)
150 return 0;
151
152 /* Check for a single bit error */
153 if (((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
154 ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
155 ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
156
157 uint32_t byteoffs, bitnum;
158
159 byteoffs = (s1 << 0) & 0x80;
160 byteoffs |= (s1 << 1) & 0x40;
161 byteoffs |= (s1 << 2) & 0x20;
162 byteoffs |= (s1 << 3) & 0x10;
163
164 byteoffs |= (s0 >> 4) & 0x08;
165 byteoffs |= (s0 >> 3) & 0x04;
166 byteoffs |= (s0 >> 2) & 0x02;
167 byteoffs |= (s0 >> 1) & 0x01;
168
169 bitnum = (s2 >> 5) & 0x04;
170 bitnum |= (s2 >> 4) & 0x02;
171 bitnum |= (s2 >> 3) & 0x01;
172
173 dat[byteoffs] ^= (1 << bitnum);
174
175 return 1;
176 }
177
178 if (countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 << 16)) == 1)
179 return 1;
180
181 return -1;
182 }

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)