summaryrefslogtreecommitdiff
path: root/recipes/u-boot/u-boot-mkimage-openmoko-native/uboot-s3c2410-nand.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/u-boot/u-boot-mkimage-openmoko-native/uboot-s3c2410-nand.patch')
-rw-r--r--recipes/u-boot/u-boot-mkimage-openmoko-native/uboot-s3c2410-nand.patch525
1 files changed, 525 insertions, 0 deletions
diff --git a/recipes/u-boot/u-boot-mkimage-openmoko-native/uboot-s3c2410-nand.patch b/recipes/u-boot/u-boot-mkimage-openmoko-native/uboot-s3c2410-nand.patch
new file mode 100644
index 0000000000..9c10edc958
--- /dev/null
+++ b/recipes/u-boot/u-boot-mkimage-openmoko-native/uboot-s3c2410-nand.patch
@@ -0,0 +1,525 @@
+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@openmoko.org>
+
+Index: u-boot/cpu/arm920t/s3c24x0/Makefile
+===================================================================
+--- u-boot.orig/cpu/arm920t/s3c24x0/Makefile 2007-02-28 03:47:44.000000000 +0100
++++ u-boot/cpu/arm920t/s3c24x0/Makefile 2007-03-01 14:29:32.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-03-01 14:30:27.000000000 +0100
+@@ -0,0 +1,225 @@
++/*
++ * (C) Copyright 2006 Openmoko, Inc.
++ * Author: Harald Welte <laforge@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 NFECC0 __REGb(NF_BASE + 0x14)
++#define NFECC1 __REGb(NF_BASE + 0x15)
++#define NFECC2 __REGb(NF_BASE + 0x16)
++
++#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));
++}
++
++#ifdef CONFIG_S3C2410_NAND_HWECC
++void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
++{
++ DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd ,mode);
++ NFCONF |= S3C2410_NFCONF_INITECC;
++}
++
++static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
++{
++ ecc_code[0] = NFECC0;
++ ecc_code[1] = NFECC1;
++ ecc_code[2] = NFECC2;
++ DEBUGN("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n", mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
++
++ return 0;
++}
++
++int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
++{
++ if (read_ecc[0] == calc_ecc[0] &&
++ read_ecc[1] == calc_ecc[1] &&
++ read_ecc[2] == calc_ecc[2])
++ return 0;
++
++ printf("s3c2410_nand_correct_data: not implemented\n");
++ return -1;
++}
++#endif
++
++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;
++
++#ifdef CONFIG_S3C2410_NAND_HWECC
++ nand->enable_hwecc = s3c2410_nand_enable_hwecc;
++ nand->calculate_ecc = s3c2410_nand_calculate_ecc;
++ nand->correct_data = s3c2410_nand_correct_data;
++ nand->eccmode = NAND_ECC_HW3_512;
++#else
++ nand->eccmode = NAND_ECC_SOFT;
++#endif
++
++#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-28 03:51:24.000000000 +0100
+@@ -0,0 +1,98 @@
++/*
++ * 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@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@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)
++#define NAND_PAGE_SIZE 0x4000
++
++/* 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-28 03:47:44.000000000 +0100
++++ u-boot/cpu/arm920t/start.S 2007-03-01 14:29:22.000000000 +0100
+@@ -5,6 +5,10 @@
+ * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
+ * Copyright (c) 2002 Gary Jennejohn <gj@denx.de>
+ *
++ * S3C2410 NAND portions
++ * Copyright (c) 2001 MIZI Research, Inc.
++ * Copyright (c) 2006 Openmoko, Inc. (Harald Welte <laforge@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, #CFG_UBOOT_SIZE
++ 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-28 03:51:24.000000000 +0100
++++ u-boot/include/s3c2410.h 2007-03-01 14:29:22.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))