[U-Boot] [PATCH 02/13] S3C64XX: Switch to use readl/writel to operate nand flash

Zhong Hongbo bocui107 at gmail.com
Sat Jul 7 11:57:01 CEST 2012


From: Zhong Hongbo <bocui107 at gmail.com>

Signed-off-by: Zhong Hongbo <bocui107 at gmail.com>
---
 arch/arm/include/asm/arch-s3c64xx/nand.h    |   69 +++++++++++++++++++++++
 arch/arm/include/asm/arch-s3c64xx/s3c6400.h |   79 ++-------------------------
 board/samsung/smdk6400/lowlevel_init.S      |    8 ++--
 drivers/mtd/nand/s3c64xx.c                  |   58 +++++++++++++-------
 4 files changed, 116 insertions(+), 98 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-s3c64xx/nand.h

diff --git a/arch/arm/include/asm/arch-s3c64xx/nand.h b/arch/arm/include/asm/arch-s3c64xx/nand.h
new file mode 100644
index 0000000..51e4d34
--- /dev/null
+++ b/arch/arm/include/asm/arch-s3c64xx/nand.h
@@ -0,0 +1,69 @@
+/*
+ * (C) Copyright 2012
+ * Zhong Hongbo <bocui107 at gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 __ASM_ARCH_NAND_H__
+#define __ASM_ARCH_NAND_H__
+
+#define NFCONF_ECC_4BIT		(1<<24)
+
+#define NFCONT_ECC_ENC		(1<<18)
+#define NFCONT_WP		(1<<16)
+#define NFCONT_MECCLOCK		(1<<7)
+#define NFCONT_SECCLOCK		(1<<6)
+#define NFCONT_INITMECC		(1<<5)
+#define NFCONT_INITSECC		(1<<4)
+#define NFCONT_INITECC		(NFCONT_INITMECC | NFCONT_INITSECC)
+#define NFCONT_CS_ALT		(1<<2)
+#define NFCONT_CS		(1<<1)
+#define NFCONT_ENABLE		(1<<0)
+
+#define NFSTAT_ECCENCDONE	(1<<7)
+#define NFSTAT_ECCDECDONE	(1<<6)
+#define NFSTAT_RnB		(1<<0)
+
+#define NFESTAT0_ECCBUSY	(1<<31)
+
+#ifndef __ASSEMBLY__
+/* NAND FLASH */
+struct s3c64xx_nand {
+	u32	nfconf;
+	u32	nfcont;
+	u32	nfcmmd;
+	u32	nfaddr;
+	u32	nfdata;
+	u32	nfmeccdata0;
+	u32	nfmeccdata1;
+	u32	nfseccdata0;
+	u32	nfsblk;
+	u32	nfeblk;
+	u32	nfstat;
+	u32	nfestat0;
+	u32	nfestat1;
+	u32	nfmecc0;
+	u32	nfmecc1;
+	u32	nfsecc;
+	u32	nfmlcbitpt;
+};
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/arch-s3c64xx/s3c6400.h b/arch/arm/include/asm/arch-s3c64xx/s3c6400.h
index 10b3324..5cb8976 100644
--- a/arch/arm/include/asm/arch-s3c64xx/s3c6400.h
+++ b/arch/arm/include/asm/arch-s3c64xx/s3c6400.h
@@ -556,80 +556,6 @@
  */
 #define ELFIN_NAND_BASE		0x70200000
 
-#define NFCONF_OFFSET		0x00
-#define NFCONT_OFFSET		0x04
-#define NFCMMD_OFFSET		0x08
-#define NFADDR_OFFSET		0x0c
-#define NFDATA_OFFSET		0x10
-#define NFMECCDATA0_OFFSET	0x14
-#define NFMECCDATA1_OFFSET	0x18
-#define NFSECCDATA0_OFFSET	0x1c
-#define NFSBLK_OFFSET		0x20
-#define NFEBLK_OFFSET		0x24
-#define NFSTAT_OFFSET		0x28
-#define NFESTAT0_OFFSET		0x2c
-#define NFESTAT1_OFFSET		0x30
-#define NFMECC0_OFFSET		0x34
-#define NFMECC1_OFFSET		0x38
-#define NFSECC_OFFSET		0x3c
-#define NFMLCBITPT_OFFSET	0x40
-
-#define NFCONF			(ELFIN_NAND_BASE + NFCONF_OFFSET)
-#define NFCONT			(ELFIN_NAND_BASE + NFCONT_OFFSET)
-#define NFCMMD			(ELFIN_NAND_BASE + NFCMMD_OFFSET)
-#define NFADDR			(ELFIN_NAND_BASE + NFADDR_OFFSET)
-#define NFDATA			(ELFIN_NAND_BASE + NFDATA_OFFSET)
-#define NFMECCDATA0		(ELFIN_NAND_BASE + NFMECCDATA0_OFFSET)
-#define NFMECCDATA1		(ELFIN_NAND_BASE + NFMECCDATA1_OFFSET)
-#define NFSECCDATA0		(ELFIN_NAND_BASE + NFSECCDATA0_OFFSET)
-#define NFSBLK			(ELFIN_NAND_BASE + NFSBLK_OFFSET)
-#define NFEBLK			(ELFIN_NAND_BASE + NFEBLK_OFFSET)
-#define NFSTAT			(ELFIN_NAND_BASE + NFSTAT_OFFSET)
-#define NFESTAT0		(ELFIN_NAND_BASE + NFESTAT0_OFFSET)
-#define NFESTAT1		(ELFIN_NAND_BASE + NFESTAT1_OFFSET)
-#define NFMECC0			(ELFIN_NAND_BASE + NFMECC0_OFFSET)
-#define NFMECC1			(ELFIN_NAND_BASE + NFMECC1_OFFSET)
-#define NFSECC			(ELFIN_NAND_BASE + NFSECC_OFFSET)
-#define NFMLCBITPT		(ELFIN_NAND_BASE + NFMLCBITPT_OFFSET)
-
-#define NFCONF_REG		__REG(ELFIN_NAND_BASE + NFCONF_OFFSET)
-#define NFCONT_REG		__REG(ELFIN_NAND_BASE + NFCONT_OFFSET)
-#define NFCMD_REG		__REG(ELFIN_NAND_BASE + NFCMMD_OFFSET)
-#define NFADDR_REG		__REG(ELFIN_NAND_BASE + NFADDR_OFFSET)
-#define NFDATA_REG		__REG(ELFIN_NAND_BASE + NFDATA_OFFSET)
-#define NFDATA8_REG		__REGb(ELFIN_NAND_BASE + NFDATA_OFFSET)
-#define NFMECCDATA0_REG		__REG(ELFIN_NAND_BASE + NFMECCDATA0_OFFSET)
-#define NFMECCDATA1_REG		__REG(ELFIN_NAND_BASE + NFMECCDATA1_OFFSET)
-#define NFSECCDATA0_REG		__REG(ELFIN_NAND_BASE + NFSECCDATA0_OFFSET)
-#define NFSBLK_REG		__REG(ELFIN_NAND_BASE + NFSBLK_OFFSET)
-#define NFEBLK_REG		__REG(ELFIN_NAND_BASE + NFEBLK_OFFSET)
-#define NFSTAT_REG		__REG(ELFIN_NAND_BASE + NFSTAT_OFFSET)
-#define NFESTAT0_REG		__REG(ELFIN_NAND_BASE + NFESTAT0_OFFSET)
-#define NFESTAT1_REG		__REG(ELFIN_NAND_BASE + NFESTAT1_OFFSET)
-#define NFMECC0_REG		__REG(ELFIN_NAND_BASE + NFMECC0_OFFSET)
-#define NFMECC1_REG		__REG(ELFIN_NAND_BASE + NFMECC1_OFFSET)
-#define NFSECC_REG		__REG(ELFIN_NAND_BASE + NFSECC_OFFSET)
-#define NFMLCBITPT_REG		__REG(ELFIN_NAND_BASE + NFMLCBITPT_OFFSET)
-
-#define NFCONF_ECC_4BIT		(1<<24)
-
-#define NFCONT_ECC_ENC		(1<<18)
-#define NFCONT_WP		(1<<16)
-#define NFCONT_MECCLOCK		(1<<7)
-#define NFCONT_SECCLOCK		(1<<6)
-#define NFCONT_INITMECC		(1<<5)
-#define NFCONT_INITSECC		(1<<4)
-#define NFCONT_INITECC		(NFCONT_INITMECC | NFCONT_INITSECC)
-#define NFCONT_CS_ALT		(1<<2)
-#define NFCONT_CS		(1<<1)
-#define NFCONT_ENABLE		(1<<0)
-
-#define NFSTAT_ECCENCDONE	(1<<7)
-#define NFSTAT_ECCDECDONE	(1<<6)
-#define NFSTAT_RnB		(1<<0)
-
-#define NFESTAT0_ECCBUSY	(1<<31)
-
 /*
  * Interrupt
  */
@@ -890,6 +816,11 @@ static inline s3c64xx_uart *s3c64xx_get_base_uart(enum s3c64xx_uarts_nr nr)
 {
 	return (s3c64xx_uart *)(ELFIN_UART_BASE + (nr * 0x400));
 }
+
+static inline unsigned int s3c64xx_get_base_nand(void)
+{
+	return ELFIN_NAND_BASE;
+}
 #endif
 
 #endif /*__S3C6400_H__*/
diff --git a/board/samsung/smdk6400/lowlevel_init.S b/board/samsung/smdk6400/lowlevel_init.S
index f7ce176..4a82e4d 100644
--- a/board/samsung/smdk6400/lowlevel_init.S
+++ b/board/samsung/smdk6400/lowlevel_init.S
@@ -269,14 +269,14 @@ uart_asm_init:
  */
 nand_asm_init:
 	ldr	r0, =ELFIN_NAND_BASE
-	ldr	r1, [r0, #NFCONF_OFFSET]
+	ldr	r1, [r0, #0x0]	@NFCONF_OFFSET
 	orr	r1, r1, #0x70
 	orr	r1, r1, #0x7700
-	str	r1, [r0, #NFCONF_OFFSET]
+	str	r1, [r0, #0x0]
 
-	ldr	r1, [r0, #NFCONT_OFFSET]
+	ldr	r1, [r0, #0x04]	@NFCONT_OFFSET
 	orr	r1, r1, #0x07
-	str	r1, [r0, #NFCONT_OFFSET]
+	str	r1, [r0, #0x04]
 
 	mov	pc, lr
 #endif
diff --git a/drivers/mtd/nand/s3c64xx.c b/drivers/mtd/nand/s3c64xx.c
index 87f0341..1d6bd67 100644
--- a/drivers/mtd/nand/s3c64xx.c
+++ b/drivers/mtd/nand/s3c64xx.c
@@ -31,6 +31,7 @@
 #include <linux/mtd/nand.h>
 
 #include <asm/arch/s3c6400.h>
+#include <asm/arch/nand.h>
 
 #include <asm/io.h>
 #include <asm/errno.h>
@@ -42,6 +43,11 @@ static int nand_cs[MAX_CHIPS] = {0, 1};
 #define printf(arg...) do {} while (0)
 #endif
 
+static inline struct s3c64xx_nand *s3c_get_base_nand(void)
+{
+	return (struct s3c64xx_nand *)s3c64xx_get_base_nand();
+}
+
 /* Nand flash definition values by jsgood */
 #ifdef S3C_NAND_DEBUG
 /*
@@ -64,7 +70,8 @@ static void print_oob(const char *header, struct mtd_info *mtd)
 
 static void s3c_nand_select_chip(struct mtd_info *mtd, int chip)
 {
-	int ctrl = readl(NFCONT);
+	struct s3c64xx_nand *const nand = s3c_get_base_nand();
+	int ctrl = readl(&nand->nfcont);
 
 	switch (chip) {
 	case -1:
@@ -80,7 +87,7 @@ static void s3c_nand_select_chip(struct mtd_info *mtd, int chip)
 		return;
 	}
 
-	writel(ctrl, NFCONT);
+	writel(ctrl, &nand->nfcont);
 }
 
 /*
@@ -89,15 +96,16 @@ static void s3c_nand_select_chip(struct mtd_info *mtd, int chip)
  */
 static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
+	struct s3c64xx_nand *const nand = s3c_get_base_nand();
 	struct nand_chip *this = mtd->priv;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		if (ctrl & NAND_CLE)
-			this->IO_ADDR_W = (void __iomem *)NFCMMD;
+			this->IO_ADDR_W = (void *)&nand->nfcmmd;
 		else if (ctrl & NAND_ALE)
-			this->IO_ADDR_W = (void __iomem *)NFADDR;
+			this->IO_ADDR_W = (void *)&nand->nfaddr;
 		else
-			this->IO_ADDR_W = (void __iomem *)NFDATA;
+			this->IO_ADDR_W = (void *)&nand->nfdata;
 		if (ctrl & NAND_NCE)
 			s3c_nand_select_chip(mtd, *(int *)this->priv);
 		else
@@ -114,7 +122,9 @@ static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
  */
 static int s3c_nand_device_ready(struct mtd_info *mtdinfo)
 {
-	return !!(readl(NFSTAT) & NFSTAT_RnB);
+	struct s3c64xx_nand *const nand = s3c_get_base_nand();
+
+	return !!(readl(&nand->nfstat) & NFSTAT_RnB);
 }
 
 #ifdef CONFIG_SYS_S3C_NAND_HWECC
@@ -124,6 +134,7 @@ static int s3c_nand_device_ready(struct mtd_info *mtdinfo)
  */
 static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 {
+	struct s3c64xx_nand *const nand = s3c_get_base_nand();
 	u_long nfcont, nfconf;
 
 	/*
@@ -131,12 +142,12 @@ static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 	 * those with non-zero ID[3][3:2], which anyway only holds for ST
 	 * (Numonyx) chips
 	 */
-	nfconf = readl(NFCONF) & ~NFCONF_ECC_4BIT;
+	nfconf = readl(&nand->nfconf) & ~NFCONF_ECC_4BIT;
 
-	writel(nfconf, NFCONF);
+	writel(nfconf, &nand->nfconf);
 
 	/* Initialize & unlock */
-	nfcont = readl(NFCONT);
+	nfcont = readl(&nand->nfcont);
 	nfcont |= NFCONT_INITECC;
 	nfcont &= ~NFCONT_MECCLOCK;
 
@@ -145,7 +156,7 @@ static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 	else if (mode == NAND_ECC_READ)
 		nfcont &= ~NFCONT_ECC_ENC;
 
-	writel(nfcont, NFCONT);
+	writel(nfcont, &nand->nfcont);
 }
 
 /*
@@ -156,14 +167,15 @@ static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 static int s3c_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 				  u_char *ecc_code)
 {
+	struct s3c64xx_nand *const nand = s3c_get_base_nand();
 	u_long nfcont, nfmecc0;
 
 	/* Lock */
-	nfcont = readl(NFCONT);
+	nfcont = readl(&nand->nfcont);
 	nfcont |= NFCONT_MECCLOCK;
-	writel(nfcont, NFCONT);
+	writel(nfcont, &nand->nfcont);
 
-	nfmecc0 = readl(NFMECC0);
+	nfmecc0 = readl(&nand->nfmecc0);
 
 	ecc_code[0] = nfmecc0 & 0xff;
 	ecc_code[1] = (nfmecc0 >> 8) & 0xff;
@@ -185,18 +197,19 @@ static int s3c_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 static int s3c_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 				 u_char *read_ecc, u_char *calc_ecc)
 {
-	int ret = -1;
+	struct s3c64xx_nand *const nand = s3c_get_base_nand();
 	u_long nfestat0, nfmeccdata0, nfmeccdata1, err_byte_addr;
 	u_char err_type, repaired;
+	int ret = -1;
 
 	/* SLC: Write ecc to compare */
 	nfmeccdata0 = (calc_ecc[1] << 16) | calc_ecc[0];
 	nfmeccdata1 = (calc_ecc[3] << 16) | calc_ecc[2];
-	writel(nfmeccdata0, NFMECCDATA0);
-	writel(nfmeccdata1, NFMECCDATA1);
+	writel(nfmeccdata0, &nand->nfmeccdata0);
+	writel(nfmeccdata1, &nand->nfmeccdata1);
 
 	/* Read ecc status */
-	nfestat0 = readl(NFESTAT0);
+	nfestat0 = readl(&nand->nfestat0);
 	err_type = nfestat0 & 0x3;
 
 	switch (err_type) {
@@ -254,15 +267,20 @@ static int s3c_nand_correct_data(struct mtd_info *mtd, u_char *dat,
  */
 int board_nand_init(struct nand_chip *nand)
 {
+	struct s3c64xx_nand *const nand_reg = s3c_get_base_nand();
 	static int chip_n;
+	unsigned int nfcont;
 
 	if (chip_n >= MAX_CHIPS)
 		return -ENODEV;
 
-	NFCONT_REG = (NFCONT_REG & ~NFCONT_WP) | NFCONT_ENABLE | 0x6;
+	nfcont = readl(&nand_reg->nfcont);
+	nfcont &= ~NFCONT_WP;
+	nfcont |= NFCONT_ENABLE | 0x6;
+	writel(nfcont, &nand_reg->nfcont);
 
-	nand->IO_ADDR_R		= (void __iomem *)NFDATA;
-	nand->IO_ADDR_W		= (void __iomem *)NFDATA;
+	nand->IO_ADDR_R		= (void *)&nand_reg->nfdata;
+	nand->IO_ADDR_W		= (void *)&nand_reg->nfdata;
 	nand->cmd_ctrl		= s3c_nand_hwcontrol;
 	nand->dev_ready		= s3c_nand_device_ready;
 	nand->select_chip	= s3c_nand_select_chip;
-- 
1.7.5.4



More information about the U-Boot mailing list