[U-Boot-Users] [PATCH] Add S3C2410 NAND support
Harald Welte
laforge at openmoko.org
Sat Feb 17 00:01:01 CET 2007
This patch adds NAND (including boot-from-NAND via steppingstone) support to
the S3C2410 SoC code in u-boot
Signed-off-by: Harald Welte <laforge at openmoko.org>
Index: u-boot/cpu/arm920t/s3c24x0/Makefile
===================================================================
--- u-boot.orig/cpu/arm920t/s3c24x0/Makefile 2007-02-16 23:23:38.000000000 +0100
+++ u-boot/cpu/arm920t/s3c24x0/Makefile 2007-02-16 23:24:10.000000000 +0100
@@ -26,7 +26,7 @@
LIB = $(obj)lib$(SOC).a
COBJS = i2c.o interrupts.o serial.o speed.o \
- usb_ohci.o
+ usb_ohci.o nand_read.o nand.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
Index: u-boot/cpu/arm920t/s3c24x0/nand.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ u-boot/cpu/arm920t/s3c24x0/nand.c 2007-02-16 23:25:05.000000000 +0100
@@ -0,0 +1,185 @@
+/*
+ * (C) Copyright 2006 OpenMoko, Inc.
+ * Author: Harald Welte <laforge at openmoko.org>
+ *
+ * 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
+ */
+
+#include <common.h>
+
+#if 0
+#define DEBUGN printf
+#else
+#define DEBUGN(x, args ...) {}
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+#if !defined(CFG_NAND_LEGACY)
+
+#include <nand.h>
+#include <s3c2410.h>
+
+#define __REGb(x) (*(volatile unsigned char *)(x))
+#define __REGi(x) (*(volatile unsigned int *)(x))
+
+#define NF_BASE 0x4e000000
+#define NFCONF __REGi(NF_BASE + 0x0)
+#define NFCMD __REGb(NF_BASE + 0x4)
+#define NFADDR __REGb(NF_BASE + 0x8)
+#define NFDATA __REGb(NF_BASE + 0xc)
+#define NFSTAT __REGb(NF_BASE + 0x10)
+
+#define S3C2410_NFCONF_EN (1<<15)
+#define S3C2410_NFCONF_512BYTE (1<<14)
+#define S3C2410_NFCONF_4STEP (1<<13)
+#define S3C2410_NFCONF_INITECC (1<<12)
+#define S3C2410_NFCONF_nFCE (1<<11)
+#define S3C2410_NFCONF_TACLS(x) ((x)<<8)
+#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
+#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0)
+
+static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ DEBUGN("hwcontrol(): 0x%02x: ", cmd);
+
+ switch (cmd) {
+ case NAND_CTL_SETNCE:
+ NFCONF &= ~S3C2410_NFCONF_nFCE;
+ DEBUGN("NFCONF=0x%08x\n", NFCONF);
+ break;
+ case NAND_CTL_CLRNCE:
+ NFCONF |= S3C2410_NFCONF_nFCE;
+ DEBUGN("NFCONF=0x%08x\n", NFCONF);
+ break;
+ case NAND_CTL_SETALE:
+ chip->IO_ADDR_W = NF_BASE + 0x8;
+ DEBUGN("SETALE\n");
+ break;
+ case NAND_CTL_SETCLE:
+ chip->IO_ADDR_W = NF_BASE + 0x4;
+ DEBUGN("SETCLE\n");
+ break;
+ default:
+ chip->IO_ADDR_W = NF_BASE + 0xc;
+ break;
+ }
+ return;
+}
+
+static int s3c2410_dev_ready(struct mtd_info *mtd)
+{
+ DEBUGN("dev_ready\n");
+ return (NFSTAT & 0x01);
+}
+
+static void s3c2410_cmdfunc(struct mtd_info *mtd, unsigned cmd,
+ int column, int page_addr)
+{
+ DEBUGN("cmdfunc(): 0x%02x, col=%d, page=%d\n", cmd, column, page_addr);
+
+ switch (cmd) {
+ case NAND_CMD_READ0:
+ case NAND_CMD_READ1:
+ case NAND_CMD_READOOB:
+ NFCMD = cmd;
+ NFADDR = column & 0xff;
+ NFADDR = page_addr & 0xff;
+ NFADDR = (page_addr >> 8) & 0xff;
+ NFADDR = (page_addr >> 16) & 0xff;
+ break;
+ case NAND_CMD_READID:
+ NFCMD = cmd;
+ NFADDR = 0;
+ break;
+ case NAND_CMD_PAGEPROG:
+ NFCMD = cmd;
+ printf("PAGEPROG not implemented\n");
+ break;
+ case NAND_CMD_ERASE1:
+ NFCMD = cmd;
+ NFADDR = page_addr & 0xff;
+ NFADDR = (page_addr >> 8) & 0xff;
+ NFADDR = (page_addr >> 16) & 0xff;
+ break;
+ case NAND_CMD_ERASE2:
+ NFCMD = cmd;
+ break;
+ case NAND_CMD_SEQIN:
+ printf("SEQIN not implemented\n");
+ break;
+ case NAND_CMD_STATUS:
+ NFCMD = cmd;
+ break;
+ case NAND_CMD_RESET:
+ NFCMD = cmd;
+ break;
+ default:
+ break;
+ }
+
+ while (!s3c2410_dev_ready(mtd));
+}
+
+int board_nand_init(struct nand_chip *nand)
+{
+ u_int32_t cfg;
+ u_int8_t tacls, twrph0, twrph1;
+ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+
+ DEBUGN("board_nand_init()\n");
+
+ clk_power->CLKCON |= (1 << 4);
+
+ /* initialize hardware */
+ twrph0 = 3; twrph1 = 0; tacls = 0;
+
+ cfg = S3C2410_NFCONF_EN;
+ cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
+ cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
+ cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
+
+ NFCONF = cfg;
+ //NFCONF = 0xf842;
+
+ /* initialize nand_chip data structure */
+ nand->IO_ADDR_R = nand->IO_ADDR_W = 0x4e00000c;
+
+ /* read_buf and write_buf are default */
+ /* read_byte and write_byte are default */
+
+ /* hwcontrol always must be implemented */
+ nand->hwcontrol = s3c2410_hwcontrol;
+
+ nand->dev_ready = s3c2410_dev_ready;
+
+ nand->eccmode = NAND_ECC_SOFT;
+#ifdef CONFIG_S3C2410_NAND_BBT
+ nand->options = NAND_USE_FLASH_BBT;
+#else
+ nand->options = 0;
+#endif
+
+ DEBUGN("end of nand_init\n");
+
+ return 0;
+}
+
+#else
+ #error "U-Boot legacy NAND support not available for S3C2410"
+#endif
+#endif
Index: u-boot/cpu/arm920t/s3c24x0/nand_read.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ u-boot/cpu/arm920t/s3c24x0/nand_read.c 2007-02-16 23:24:10.000000000 +0100
@@ -0,0 +1,97 @@
+/*
+ * nand_read.c: Simple NAND read functions for booting from NAND
+ *
+ * This is used by cpu/arm920/start.S assembler code,
+ * and the board-specific linker script must make sure this
+ * file is linked within the first 4kB of NAND flash.
+ *
+ * Taken from GPLv2 licensed vivi bootloader,
+ * Copyright (C) 2002 MIZI Research, Inc.
+ *
+ * Author: Hwang, Chideok <hwang at mizi.com>
+ * Date : $Date: 2004/02/04 10:37:37 $
+ *
+ * u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge at openmoko.org>
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_S3C2410_NAND_BOOT
+
+#define __REGb(x) (*(volatile unsigned char *)(x))
+#define __REGi(x) (*(volatile unsigned int *)(x))
+#define NF_BASE 0x4e000000
+#define NFCONF __REGi(NF_BASE + 0x0)
+#define NFCMD __REGb(NF_BASE + 0x4)
+#define NFADDR __REGb(NF_BASE + 0x8)
+#define NFDATA __REGb(NF_BASE + 0xc)
+#define NFSTAT __REGb(NF_BASE + 0x10)
+
+#define BUSY 1
+inline void wait_idle(void)
+{
+ int i;
+
+ while (!(NFSTAT & BUSY))
+ for (i=0; i<10; i++);
+}
+
+#define NAND_SECTOR_SIZE 512
+#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
+
+/* low level nand read function */
+int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
+{
+ int i, j;
+
+ if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
+ return -1; /* invalid alignment */
+
+ /* chip Enable */
+ NFCONF &= ~0x800;
+ for (i=0; i<10; i++);
+
+ for (i=start_addr; i < (start_addr + size);) {
+#ifdef CONFIG_S3C2410_NAND_SKIP_BAD
+ if (start_addr % NAND_PAGE_SIZE == 0) {
+ unsigned char data;
+ NFCMD = 0x50;
+ NFADDR = 517&0xf;
+ NFADDR = (i >> 9) & 0xff;
+ NFADDR = (i >> 17) & 0xff;
+ NFADDR = (i >> 25) & 0xff;
+ wait_idle();
+ data = (NFDATA & 0xff);
+ if (data != 0xff) {
+ /* Bad block */
+ i += NAND_PAGE_SIZE;
+ size += NAND_PAGE_SIZE;
+ continue;
+ }
+ }
+#endif
+ /* READ0 */
+ NFCMD = 0;
+
+ /* Write Address */
+ NFADDR = i & 0xff;
+ NFADDR = (i >> 9) & 0xff;
+ NFADDR = (i >> 17) & 0xff;
+ NFADDR = (i >> 25) & 0xff;
+
+ wait_idle();
+
+ for (j=0; j < NAND_SECTOR_SIZE; j++, i++) {
+ *buf = (NFDATA & 0xff);
+ buf++;
+ }
+ }
+
+ /* chip Disable */
+ NFCONF |= 0x800; /* chip disable */
+
+ return 0;
+}
+
+#endif /* CONFIG_S3C2410_NAND_BOOT */
Index: u-boot/cpu/arm920t/start.S
===================================================================
--- u-boot.orig/cpu/arm920t/start.S 2007-02-16 23:23:38.000000000 +0100
+++ u-boot/cpu/arm920t/start.S 2007-02-16 23:24:10.000000000 +0100
@@ -5,6 +5,10 @@
* Copyright (c) 2002 Alex Züpke <azu at sysgo.de>
* Copyright (c) 2002 Gary Jennejohn <gj at denx.de>
*
+ * S3C2410 NAND portions
+ * Copyright (c) 2001 MIZI Research, Inc.
+ * Copyright (c) 2006 OpenMoko, Inc. (Harald Welte <laforge at openmmoko.org>
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -27,6 +31,7 @@
#include <config.h>
#include <version.h>
+#include <s3c2410.h>
/*
@@ -161,6 +166,7 @@
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
+#ifndef CONFIG_S3C2410_NAND_BOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
@@ -177,6 +183,93 @@
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
+#else /* NAND_BOOT */
+relocate:
+copy_myself:
+ /* mov r10, lr */
+
+ @ reset NAND
+ mov r1, #S3C2410_NAND_BASE
+ ldr r2, =0xf842 @ initial value enable tacls=3,rph0=6,rph1=0
+ str r2, [r1, #oNFCONF]
+ ldr r2, [r1, #oNFCONF]
+ bic r2, r2, #0x800 @ enable chip
+ str r2, [r1, #oNFCONF]
+ mov r2, #0xff @ RESET command
+ strb r2, [r1, #oNFCMD]
+ mov r3, #0 @ wait
+1: add r3, r3, #0x1
+ cmp r3, #0xa
+ blt 1b
+2: ldr r2, [r1, #oNFSTAT] @ wait ready
+ tst r2, #0x1
+ beq 2b
+ ldr r2, [r1, #oNFCONF]
+ orr r2, r2, #0x800 @ disable chip
+ str r2, [r1, #oNFCONF]
+
+#if 0
+ @ get ready to call C functions (for nand_read())
+ ldr sp, DW_STACK_START @ setup stack pointer
+ mov fp, #0 @ no previous frame, so fp=0
+#else
+ ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
+ sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
+ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
+#ifdef CONFIG_USE_IRQ
+ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
+#endif
+ sub sp, r0, #12 /* leave 3 words for abort-stack */
+#endif
+
+ @ copy u-boot to RAM
+ ldr r0, _TEXT_BASE
+ mov r1, #0x0
+ mov r2, #0x30000
+ bl nand_read_ll
+
+ tst r0, #0x0
+ beq ok_nand_read
+#ifdef CONFIG_DEBUG_LL
+bad_nand_read:
+ ldr r0, STR_FAIL
+ ldr r1, SerBase
+ bl PrintWord
+1: b 1b @ infinite loop
+#endif
+
+ok_nand_read:
+#ifdef CONFIG_DEBUG_LL
+ ldr r0, STR_OK
+ ldr r1, SerBase
+ bl PrintWord
+#endif
+
+ @ verify
+ mov r0, #0
+ @ldr r1, =0x33f00000
+ ldr r1, _TEXT_BASE
+ mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
+go_next:
+ ldr r3, [r0], #4
+ ldr r4, [r1], #4
+ teq r3, r4
+ bne notmatch
+ subs r2, r2, #4
+ beq done_nand_read
+ bne go_next
+notmatch:
+#ifdef CONFIG_DEBUG_LL
+ sub r0, r0, #4
+ ldr r1, SerBase
+ bl PrintHexWord
+ ldr r0, STR_FAIL
+ ldr r1, SerBase
+ bl PrintWord
+#endif
+1: b 1b
+done_nand_read:
+#endif /* NAND_BOOT */
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
/* Set up the stack */
Index: u-boot/include/s3c2410.h
===================================================================
--- u-boot.orig/include/s3c2410.h 2007-02-16 23:24:07.000000000 +0100
+++ u-boot/include/s3c2410.h 2007-02-16 23:24:10.000000000 +0100
@@ -38,12 +38,6 @@
#define S3C2410_ECCSIZE 512
#define S3C2410_ECCBYTES 3
-typedef enum {
- S3C24X0_UART0,
- S3C24X0_UART1,
- S3C24X0_UART2
-} S3C24X0_UARTS_NR;
-
/* S3C2410 device base addresses */
#define S3C24X0_MEMCTL_BASE 0x48000000
#define S3C24X0_USB_HOST_BASE 0x49000000
@@ -65,9 +59,23 @@
#define S3C2410_SDI_BASE 0x5A000000
+#define oNFCONF 0x00
+#define oNFCMD 0x04
+#define oNFADDR 0x08
+#define oNFDATA 0x0C
+#define oNFSTAT 0x10
+#define oNFECC 0x14
+
+#ifndef __ASSEMBLER__
+
/* include common stuff */
#include <s3c24x0.h>
+typedef enum {
+ S3C24X0_UART0,
+ S3C24X0_UART1,
+ S3C24X0_UART2
+} S3C24X0_UARTS_NR;
static inline S3C24X0_MEMCTL * S3C24X0_GetBase_MEMCTL(void)
{
@@ -142,6 +150,7 @@
return (S3C2410_SDI * const)S3C2410_SDI_BASE;
}
+#endif
/* ISR */
#define pISR_RESET (*(unsigned *)(_ISR_STARTADDRESS+0x0))
--
- Harald Welte <laforge at openmoko.org> http://openmoko.org/
============================================================================
Software for the world's first truly open Free Software mobile phone
More information about the U-Boot
mailing list