lpc32xx: Flash driver

Based on the lpc3180 driver, but released as a separate driver for two reasons:
 1) I don't have an lpc3180 to test it against, so it might unintentionally break compatibility.
 2) It's using a different OOB layout than lpc3180.

Rewritten so that it no longer borrows code from the NXP CDL library.  Instead borrowing code from the u-boot port to lpc32xx, written by Kevin Wells.

Tested on lpc3250 (Hitex LPC3250-Stick).  OOB layout is compatible with LPCLinux.
This commit is contained in:
Bjarne Steinsbo 2011-02-15 20:23:40 +01:00 committed by Øyvind Harboe
parent fe0894015f
commit 3f4b9e334b
5 changed files with 1932 additions and 0 deletions

View File

@ -16,6 +16,7 @@ NAND_DRIVERS = \
nonce.c \
davinci.c \
lpc3180.c \
lpc32xx.c \
mx2.c \
mx3.c \
orion.c \
@ -35,6 +36,7 @@ noinst_HEADERS = \
fileio.h \
imp.h \
lpc3180.h \
lpc32xx.h \
mx2.h \
mx3.h \
s3c24xx.h \

View File

@ -31,6 +31,7 @@
extern struct nand_flash_controller nonce_nand_controller;
extern struct nand_flash_controller davinci_nand_controller;
extern struct nand_flash_controller lpc3180_nand_controller;
extern struct nand_flash_controller lpc32xx_nand_controller;
extern struct nand_flash_controller orion_nand_controller;
extern struct nand_flash_controller s3c2410_nand_controller;
extern struct nand_flash_controller s3c2412_nand_controller;
@ -49,6 +50,7 @@ static struct nand_flash_controller *nand_flash_controllers[] =
&nonce_nand_controller,
&davinci_nand_controller,
&lpc3180_nand_controller,
&lpc32xx_nand_controller,
&orion_nand_controller,
&s3c2410_nand_controller,
&s3c2412_nand_controller,

View File

@ -120,3 +120,64 @@ int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ec
return 0;
}
static inline int countbits(uint32_t byte)
{
int res = 0;
for (;byte; byte >>= 1)
res += byte & 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;
}

1828
src/flash/nand/lpc32xx.c Normal file

File diff suppressed because it is too large Load Diff

39
src/flash/nand/lpc32xx.h Normal file
View File

@ -0,0 +1,39 @@
/***************************************************************************
* Copyright (C) 2007 by Dominic Rath *
* Dominic.Rath@gmx.de *
* *
* This program 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 of the License, or *
* (at your option) any later version. *
* *
* This program 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 program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef LPC32xx_NAND_CONTROLLER_H
#define LPC32xx_NAND_CONTROLLER_H
enum lpc32xx_selected_controller
{
LPC32xx_NO_CONTROLLER,
LPC32xx_MLC_CONTROLLER,
LPC32xx_SLC_CONTROLLER,
};
struct lpc32xx_nand_controller
{
int osc_freq;
enum lpc32xx_selected_controller selected_controller;
int sw_write_protection;
uint32_t sw_wp_lower_bound;
uint32_t sw_wp_upper_bound;
};
#endif /*LPC32xx_NAND_CONTROLLER_H */