X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnand%2Fecc.c;h=25b2eb10e319b3fbcafa0de592e7beabc0f2cd3b;hp=1e103d00210a231e2f5cca96c42633f20f90eced;hb=HEAD;hpb=da3bcb392e852214b0dda878f6161c8f1e8d15f3 diff --git a/src/flash/nand/ecc.c b/src/flash/nand/ecc.c index 1e103d0021..20b8ba85dc 100644 --- a/src/flash/nand/ecc.c +++ b/src/flash/nand/ecc.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-or-later WITH eCos-exception-2.0 + /* * This file contains an ECC algorithm from Toshiba that allows for detection * and correction of 1-bit errors in a 256 byte block of data. @@ -10,38 +12,13 @@ * Toshiba America Electronics Components, Inc. * * Copyright (C) 2006 Thomas Gleixner - * - * This file is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 or (at your option) any - * later version. - * - * This file is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this file; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * As a special exception, if other files instantiate templates or use - * macros or inline functions from these files, or you compile these - * files and link them with other works to produce a work based on these - * files, these files do not by themselves cause the resulting work to be - * covered by the GNU General Public License. However the source code for - * these files must still be made available in accordance with section (3) - * of the GNU General Public License. - * - * This exception does not invalidate any other reasons why a work based on - * this file might be covered by the GNU General Public License. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include +#include "core.h" /* * Pre-calculated 256-way 1 byte column parity @@ -120,3 +97,64 @@ int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ec return 0; } + +static inline int countbits(uint32_t b) +{ + int res = 0; + + for (; b; b >>= 1) + res += b & 0x01; + return res; +} + +/** + * nand_correct_data - Detect and correct a 1 bit error for 256 byte block + */ +int nand_correct_data(struct nand_device *nand, u_char *dat, + u_char *read_ecc, u_char *calc_ecc) +{ + uint8_t s0, s1, s2; + +#ifdef NAND_ECC_SMC + s0 = calc_ecc[0] ^ read_ecc[0]; + s1 = calc_ecc[1] ^ read_ecc[1]; + s2 = calc_ecc[2] ^ read_ecc[2]; +#else + s1 = calc_ecc[0] ^ read_ecc[0]; + s0 = calc_ecc[1] ^ read_ecc[1]; + s2 = calc_ecc[2] ^ read_ecc[2]; +#endif + if ((s0 | s1 | s2) == 0) + return 0; + + /* Check for a single bit error */ + if (((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && + ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && + ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { + + uint32_t byteoffs, bitnum; + + byteoffs = (s1 << 0) & 0x80; + byteoffs |= (s1 << 1) & 0x40; + byteoffs |= (s1 << 2) & 0x20; + byteoffs |= (s1 << 3) & 0x10; + + byteoffs |= (s0 >> 4) & 0x08; + byteoffs |= (s0 >> 3) & 0x04; + byteoffs |= (s0 >> 2) & 0x02; + byteoffs |= (s0 >> 1) & 0x01; + + bitnum = (s2 >> 5) & 0x04; + bitnum |= (s2 >> 4) & 0x02; + bitnum |= (s2 >> 3) & 0x01; + + dat[byteoffs] ^= (1 << bitnum); + + return 1; + } + + if (countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 << 16)) == 1) + return 1; + + return -1; +}