diff options
Diffstat (limited to 'cpu/ppc4xx/ndfc.c')
| -rw-r--r-- | cpu/ppc4xx/ndfc.c | 74 | 
1 files changed, 54 insertions, 20 deletions
| diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c index 08dfc3295..f63fc79f6 100644 --- a/cpu/ppc4xx/ndfc.c +++ b/cpu/ppc4xx/ndfc.c @@ -3,7 +3,7 @@   *   Platform independend driver for NDFC (NanD Flash Controller)   *   integrated into EP440 cores   * - * (C) Copyright 2006 + * (C) Copyright 2006-2007   * Stefan Roese, DENX Software Engineering, sr@denx.de.   *   * Based on original work by @@ -38,7 +38,9 @@  #include <nand.h>  #include <linux/mtd/ndfc.h> +#include <linux/mtd/nand_ecc.h>  #include <asm/processor.h> +#include <asm/io.h>  #include <ppc4xx.h>  static u8 hwctl = 0; @@ -70,11 +72,11 @@ static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte)  	ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;  	if (hwctl & 0x1) -		out8(base + NDFC_CMD, byte); +		out_8((u8 *)(base + NDFC_CMD), byte);  	else if (hwctl & 0x2) -		out8(base + NDFC_ALE, byte); +		out_8((u8 *)(base + NDFC_ALE), byte);  	else -		out8(base + NDFC_DATA, byte); +		out_8((u8 *)(base + NDFC_DATA), byte);  }  static u_char ndfc_read_byte(struct mtd_info *mtdinfo) @@ -82,7 +84,7 @@ static u_char ndfc_read_byte(struct mtd_info *mtdinfo)  	struct nand_chip *this = mtdinfo->priv;  	ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; -	return (in8(base + NDFC_DATA)); +	return (in_8((u8 *)(base + NDFC_DATA)));  }  static int ndfc_dev_ready(struct mtd_info *mtdinfo) @@ -90,17 +92,41 @@ static int ndfc_dev_ready(struct mtd_info *mtdinfo)  	struct nand_chip *this = mtdinfo->priv;  	ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; -	while (!(in32(base + NDFC_STAT) & NDFC_STAT_IS_READY)) +	while (!(in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY))  		;  	return 1;  } -#ifndef CONFIG_NAND_SPL -/* - * Don't use these speedup functions in NAND boot image, since the image - * has to fit into 4kByte. - */ +static void ndfc_enable_hwecc(struct mtd_info *mtdinfo, int mode) +{ +	struct nand_chip *this = mtdinfo->priv; +	ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; +	u32 ccr; + +	ccr = in_be32((u32 *)(base + NDFC_CCR)); +	ccr |= NDFC_CCR_RESET_ECC; +	out_be32((u32 *)(base + NDFC_CCR), ccr); +} + +static int ndfc_calculate_ecc(struct mtd_info *mtdinfo, +			      const u_char *dat, u_char *ecc_code) +{ +	struct nand_chip *this = mtdinfo->priv; +	ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; +	u32 ecc; +	u8 *p = (u8 *)&ecc; + +	ecc = in_be32((u32 *)(base + NDFC_ECC)); + +	/* The NDFC uses Smart Media (SMC) bytes order +	 */ +	ecc_code[0] = p[2]; +	ecc_code[1] = p[1]; +	ecc_code[2] = p[3]; + +	return 0; +}  /*   * Speedups for buffer read/write/verify @@ -116,9 +142,14 @@ static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)  	uint32_t *p = (uint32_t *) buf;  	for (;len > 0; len -= 4) -		*p++ = in32(base + NDFC_DATA); +		*p++ = in_be32((u32 *)(base + NDFC_DATA));  } +#ifndef CONFIG_NAND_SPL +/* + * Don't use these speedup functions in NAND boot image, since the image + * has to fit into 4kByte. + */  static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)  {  	struct nand_chip *this = mtdinfo->priv; @@ -126,7 +157,7 @@ static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len  	uint32_t *p = (uint32_t *) buf;  	for (; len > 0; len -= 4) -		out32(base + NDFC_DATA, *p++); +		out_be32((u32 *)(base + NDFC_DATA), *p++);  }  static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) @@ -136,7 +167,7 @@ static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len  	uint32_t *p = (uint32_t *) buf;  	for (; len > 0; len -= 4) -		if (*p++ != in32(base + NDFC_DATA)) +		if (*p++ != in_be32((u32 *)(base + NDFC_DATA)))  			return -1;  	return 0; @@ -153,8 +184,8 @@ void board_nand_select_device(struct nand_chip *nand, int chip)  	ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc;  	/* Set NandFlash Core Configuration Register */ -	/* 1col x 2 rows */ -	out32(base + NDFC_CCR, 0x00000000 | (cs << 24)); +	/* 1 col x 2 rows */ +	out_be32((u32 *)(base + NDFC_CCR), 0x00000000 | (cs << 24));  }  int board_nand_init(struct nand_chip *nand) @@ -162,16 +193,19 @@ int board_nand_init(struct nand_chip *nand)  	int cs = (ulong)nand->IO_ADDR_W & 0x00000003;  	ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc; -	nand->eccmode = NAND_ECC_SOFT; -  	nand->hwcontrol  = ndfc_hwcontrol;  	nand->read_byte  = ndfc_read_byte; +	nand->read_buf   = ndfc_read_buf;  	nand->write_byte = ndfc_write_byte;  	nand->dev_ready  = ndfc_dev_ready; +	nand->eccmode = NAND_ECC_HW3_256; +	nand->enable_hwecc = ndfc_enable_hwecc; +	nand->calculate_ecc = ndfc_calculate_ecc; +	nand->correct_data = nand_correct_data; +  #ifndef CONFIG_NAND_SPL  	nand->write_buf  = ndfc_write_buf; -	nand->read_buf   = ndfc_read_buf;  	nand->verify_buf = ndfc_verify_buf;  #else  	/* @@ -187,7 +221,7 @@ int board_nand_init(struct nand_chip *nand)  	 * Select required NAND chip in NDFC  	 */  	board_nand_select_device(nand, cs); -	out32(base + NDFC_BCFG0 + (cs << 2), 0x80002222); +	out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222);  	return 0;  } |