[Armadeus-commitlog] SF.net SVN: armadeus: [823] branches/apf2/buildroot/target/device/armadeus/ u
Brought to you by:
sszy
|
From: <th...@us...> - 2008-06-27 12:10:31
|
Revision: 823
http://armadeus.svn.sourceforge.net/armadeus/?rev=823&view=rev
Author: thom25
Date: 2008-06-27 05:10:38 -0700 (Fri, 27 Jun 2008)
Log Message:
-----------
[UBOOT] first NAND support. tests needed
Added Paths:
-----------
branches/apf2/buildroot/target/device/armadeus/u-boot/patches/1.3.2/320-u-boot-1.3.2.imx27nand.patch
Added: branches/apf2/buildroot/target/device/armadeus/u-boot/patches/1.3.2/320-u-boot-1.3.2.imx27nand.patch
===================================================================
--- branches/apf2/buildroot/target/device/armadeus/u-boot/patches/1.3.2/320-u-boot-1.3.2.imx27nand.patch (rev 0)
+++ branches/apf2/buildroot/target/device/armadeus/u-boot/patches/1.3.2/320-u-boot-1.3.2.imx27nand.patch 2008-06-27 12:10:38 UTC (rev 823)
@@ -0,0 +1,1656 @@
+--- u-boot-1.3.2/board/pcm038/lowlevel_init.S 2008-06-25 04:12:34.000000000 +0200
++++ u-boot-new/board/pcm038/lowlevel_init.S 2008-06-14 22:15:02.000000000 +0200
+@@ -10,45 +10,138 @@
+
+
+
+-#define writel(val, reg) \
++#define writel(reg, val) \
+ ldr r0, =reg; \
+ ldr r1, =val; \
+ str r1, [r0];
+
+ #define CRM_PLL_PCTL_PARAM(pd, fd, fi, fn) (((pd-1)<<26) + ((fd-1)<<16) + (fi<<10) + (fn<<0))
+
++.macro port_init_sha
++/* PORTA */
++ writel( DR(PORTA), CFG_DR_A_VAL)
++ writel( OCR1(PORTA), CFG_OCR1_A_VAL)
++ writel( OCR2(PORTA), CFG_OCR2_A_VAL)
++ writel( ICONFA1(PORTA), CFG_ICFA1_A_VAL)
++ writel( ICONFA2(PORTA), CFG_ICFA2_A_VAL)
++ writel( ICONFB1(PORTA), CFG_ICFB1_A_VAL)
++ writel( ICONFB2(PORTA), CFG_ICFB2_A_VAL)
++ writel( ICR1(PORTA), CFG_ICR1_A_VAL)
++ writel( ICR2(PORTA), CFG_ICR2_A_VAL)
++ writel( IMR(PORTA), CFG_IMR_A_VAL)
++ writel( DDIR(PORTA), CFG_DDIR_A_VAL)
++ writel( GPR(PORTA), CFG_GPR_A_VAL)
++ writel( PUEN(PORTA), CFG_PUEN_A_VAL)
++ writel( GIUS(PORTA), CFG_GIUS_A_VAL)
++/* PORTB */
++ writel( DR(PORTB), CFG_DR_B_VAL)
++ writel( OCR1(PORTB), CFG_OCR1_B_VAL)
++ writel( OCR2(PORTB), CFG_OCR2_B_VAL)
++ writel( ICONFA1(PORTB), CFG_ICFA1_B_VAL)
++ writel( ICONFA2(PORTB), CFG_ICFA2_B_VAL)
++ writel( ICONFB1(PORTB), CFG_ICFB1_B_VAL)
++ writel( ICONFB2(PORTB), CFG_ICFB2_B_VAL)
++ writel( ICR1(PORTB), CFG_ICR1_B_VAL)
++ writel( ICR2(PORTB), CFG_ICR2_B_VAL)
++ writel( IMR(PORTB), CFG_IMR_B_VAL)
++ writel( DDIR(PORTB), CFG_DDIR_B_VAL)
++ writel( GPR(PORTB), CFG_GPR_B_VAL)
++ writel( PUEN(PORTB), CFG_PUEN_B_VAL)
++ writel( GIUS(PORTB), CFG_GIUS_B_VAL)
++/* PORTC */
++ writel( DR(PORTC), CFG_DR_C_VAL)
++ writel( OCR1(PORTC), CFG_OCR1_C_VAL)
++ writel( OCR2(PORTC), CFG_OCR2_C_VAL)
++ writel( ICONFA1(PORTC), CFG_ICFA1_C_VAL)
++ writel( ICONFA2(PORTC), CFG_ICFA2_C_VAL)
++ writel( ICONFB1(PORTC), CFG_ICFB1_C_VAL)
++ writel( ICONFB2(PORTC), CFG_ICFB2_C_VAL)
++ writel( ICR1(PORTC), CFG_ICR1_C_VAL)
++ writel( ICR2(PORTC), CFG_ICR2_C_VAL)
++ writel( IMR(PORTC), CFG_IMR_C_VAL)
++ writel( DDIR(PORTC), CFG_DDIR_C_VAL)
++ writel( GPR(PORTC), CFG_GPR_C_VAL)
++ writel( PUEN(PORTC), CFG_PUEN_C_VAL)
++ writel( GIUS(PORTC), CFG_GIUS_C_VAL)
++/* PORTD */
++ writel( DR(PORTD), CFG_DR_D_VAL)
++ writel( OCR1(PORTD), CFG_OCR1_D_VAL)
++ writel( OCR2(PORTD), CFG_OCR2_D_VAL)
++ writel( ICONFA1(PORTD), CFG_ICFA1_D_VAL)
++ writel( ICONFA2(PORTD), CFG_ICFA2_D_VAL)
++ writel( ICONFB1(PORTD), CFG_ICFB1_D_VAL)
++ writel( ICONFB2(PORTD), CFG_ICFB2_D_VAL)
++ writel( ICR1(PORTD), CFG_ICR1_D_VAL)
++ writel( ICR2(PORTD), CFG_ICR2_D_VAL)
++ writel( IMR(PORTD), CFG_IMR_D_VAL)
++ writel( DDIR(PORTD), CFG_DDIR_D_VAL)
++ writel( GPR(PORTD), CFG_GPR_D_VAL)
++ writel( PUEN(PORTD), CFG_PUEN_D_VAL)
++ writel( GIUS(PORTD), CFG_GIUS_D_VAL)
++/* PORTE */
++ writel( DR(PORTE), CFG_DR_E_VAL)
++ writel( OCR1(PORTE), CFG_OCR1_E_VAL)
++ writel( OCR2(PORTE), CFG_OCR2_E_VAL)
++ writel( ICONFA1(PORTE), CFG_ICFA1_E_VAL)
++ writel( ICONFA2(PORTE), CFG_ICFA2_E_VAL)
++ writel( ICONFB1(PORTE), CFG_ICFB1_E_VAL)
++ writel( ICONFB2(PORTE), CFG_ICFB2_E_VAL)
++ writel( ICR1(PORTE), CFG_ICR1_E_VAL)
++ writel( ICR2(PORTE), CFG_ICR2_E_VAL)
++ writel( IMR(PORTE), CFG_IMR_E_VAL)
++ writel( DDIR(PORTE), CFG_DDIR_E_VAL)
++ writel( GPR(PORTE), CFG_GPR_E_VAL)
++ writel( PUEN(PORTE), CFG_PUEN_E_VAL)
++ writel( GIUS(PORTE), CFG_GIUS_E_VAL)
++/* PORTF */
++ writel( DR(PORTF), CFG_DR_F_VAL)
++ writel( OCR1(PORTF), CFG_OCR1_F_VAL)
++ writel( OCR2(PORTF), CFG_OCR2_F_VAL)
++ writel( ICONFA1(PORTF), CFG_ICFA1_F_VAL)
++ writel( ICONFA2(PORTF), CFG_ICFA2_F_VAL)
++ writel( ICONFB1(PORTF), CFG_ICFB1_F_VAL)
++ writel( ICONFB2(PORTF), CFG_ICFB2_F_VAL)
++ writel( ICR1(PORTF), CFG_ICR1_F_VAL)
++ writel( ICR2(PORTF), CFG_ICR2_F_VAL)
++ writel( IMR(PORTF), CFG_IMR_F_VAL)
++ writel( DDIR(PORTF), CFG_DDIR_F_VAL)
++ writel( GPR(PORTF), CFG_GPR_F_VAL)
++ writel( PUEN(PORTF), CFG_PUEN_F_VAL)
++ writel( GIUS(PORTF), CFG_GIUS_F_VAL)
++.endm
++
+ .macro sdram_init_sha
+ /*
+ * DDR on CSD0
+ */
+- writel(0x00000008, 0xD8001010)
+- writel(0x55555555, 0x10027828)
+- writel(0x55555555, 0x10027830)
+- writel(0x55555555, 0x10027834)
+- writel(0x00005005, 0x10027838)
+- writel(0x15555555, 0x1002783C)
+- writel(0x00000004, 0xD8001010)
+- writel(0x006ac73a, 0xD8001004)
+- writel(0x92100000, 0xD8001000)
+- writel(0x00000000, 0xA0000F00)
+- writel(0xA2100000, 0xD8001000)
+- writel(0x00000000, 0xA0000F00)
+- writel(0x00000000, 0xA0000F00)
+- writel(0x00000000, 0xA0000F00)
+- writel(0x00000000, 0xA0000F00)
+- writel(0xA2200000, 0xD8001000)
+- writel(0x00000000, 0xA0000F00)
+- writel(0x00000000, 0xA0000F00)
+- writel(0x00000000, 0xA0000F00)
+- writel(0x00000000, 0xA0000F00)
+- writel(0xb2100000, 0xD8001000)
++ writel(0xD8001010, 0x00000008)
++ writel(0x10027828, 0x55555555)
++ writel(0x10027830, 0x55555555)
++ writel(0x10027834, 0x55555555)
++ writel(0x10027838, 0x00005005)
++ writel(0x1002783C, 0x15555555)
++ writel(0xD8001010, 0x00000004)
++ writel(0xD8001004, 0x006ac73a)
++ writel(0xD8001000, 0x92100000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xD8001000, 0xA2100000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xD8001000, 0xA2200000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xA0000F00, 0x00000000)
++ writel(0xD8001000, 0xb2100000)
+ ldr r0, =0xA0000033
+ mov r1, #0xda
+ strb r1, [r0]
+ ldr r0, =0xA1000000
+ mov r1, #0xff
+ strb r1, [r0]
+- writel(0x82226080, 0xD8001000)
++ writel(0xD8001000, 0x82226080)
+ .endm
+
+ .macro sdram_init_mx27_manual
+@@ -87,31 +180,31 @@ NORMAL_MODE .long 0x00000000 // system/
+
+ .macro sdram_init_uboot
+ /* configure 16 bit nor flash on cs0 */
+- writel(0x0000CC03, 0xd8002000)
+- writel(0xa0330D01, 0xd8002004)
+- writel(0x00220800, 0xd8002008)
++ writel(0xd8002000, 0x0000CC03)
++ writel(0xd8002004, 0xa0330D01)
++ writel(0xd8002008, 0x00220800)
+
+ /* ddr on csd0 - initial reset */
+- writel(0x00000008, 0xD8001010)
++ writel(0xD8001010, 0x00000008)
+
+ /* configure ddr on csd0 - wait 5000 cycles */
+- writel(0x00000004, 0xD8001010)
+- writel(0x006ac73a, 0xD8001004)
+- writel(0x92100000, 0xD8001000)
+- writel(0x12344321, 0xA0000f00)
+- writel(0xa2100000, 0xD8001000)
+- writel(0x12344321, 0xA0000000)
+- writel(0x12344321, 0xA0000000)
+- writel(0xb2100000, 0xD8001000)
++ writel(0xD8001010, 0x00000004)
++ writel(0xD8001004, 0x006ac73a)
++ writel(0xD8001000, 0x92100000)
++ writel(0xA0000f00, 0x12344321)
++ writel(0xD8001000, 0xa2100000)
++ writel(0xA0000000, 0x12344321)
++ writel(0xA0000000, 0x12344321)
++ writel(0xD8001000, 0xb2100000)
+ ldr r0, =0xA0000033
+ mov r1, #0xda
+ strb r1, [r0]
+ ldr r0, =0xA1000000
+ mov r1, #0xff
+ strb r1, [r0]
+- writel(0x82226080, 0xD8001000)
+- writel(0xDEADBEEF, 0xA0000000)
+- writel(0x0000000c, 0xD8001010)
++ writel(0xD8001000, 0x82226080)
++ writel(0xA0000000, 0xDEADBEEF)
++ writel(0xD8001010, 0x0000000c)
+ .endm
+
+ .globl board_init_lowlevel
+@@ -122,10 +215,10 @@ lowlevel_init:
+ mov r10, lr
+
+ /* ahb lite ip interface */
+- writel(0x20040304, AIPI1_PSR0)
+- writel(0xDFFBFCFB, AIPI1_PSR1)
+- writel(0x00000000, AIPI2_PSR0)
+- writel(0xFFFFFFFF, AIPI2_PSR1)
++ writel(AIPI1_PSR0, 0x20040304)
++ writel(AIPI1_PSR1, 0xDFFBFCFB)
++ writel(AIPI2_PSR0, 0x00000000)
++ writel(AIPI2_PSR1, 0xFFFFFFFF)
+
+ /* disable mpll/spll */
+ ldr r0, =CSCR
+@@ -140,15 +233,15 @@ lowlevel_init:
+ * with 1.2 V core voltage! Find out if this is
+ * documented somewhere.
+ */
+- writel(0x04331C23, MPCTL0) /* MPLL = 199.5*2 MHz */
+- writel(0x040C2403, SPCTL0) /* SPLL = FIXME (needs review) */
++ writel(MPCTL0, 0x04331C23) /* MPLL = 199.5*2 MHz */
++ writel(SPCTL0, 0x040C2403) /* SPLL = FIXME (needs review) */
+
+ /*
+ * ARM clock = (399 MHz / 2) / (ARM divider = 1) = 200 MHz
+ * AHB clock = (399 MHz / 3) / (AHB divider = 2) = 66.5 MHz
+ * System clock (HCLK) = 133 MHz
+ */
+- writel(0x33f38107 | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART, CSCR)
++ writel(CSCR, 0x33f38107 | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART)
+
+ /* add some delay here */
+ mov r1, #0x1000
+@@ -156,17 +249,21 @@ lowlevel_init:
+ bne 1b
+
+ /* clock gating enable */
+- writel(0x00050f08, GPCR)
++ writel(GPCR, 0x00050f08)
+
+ /* peripheral clock divider */
+- writel(0x130410c3, PCDR0) /* FIXME */
+- writel(0x09030908, PCDR1) /* PERDIV1=08 @133 MHz */
++ writel(PCDR0, 0x130410c3) /* FIXME */
++ writel(PCDR1, 0x09030908) /* PERDIV1=08 @133 MHz */
+ /* PERDIV1=04 @266 MHz */
+
+ /* configure 16 bit nor flash on cs0 */
+- writel(0x0000CC03, 0xD8002000)
+- writel(0xa0330D01, 0xD8002004)
+- writel(0x00220800, 0xD8002008)
++ writel(0xD8002000, 0x0000CC03)
++ writel(0xD8002004, 0xa0330D01)
++ writel(0xD8002008, 0x00220800)
++
++
++ //port_init_sha
++ writel(DR(PORTA), 0x00000000) /* init debug port */
+
+ /* skip sdram initialization if we run from ram */
+ cmp pc, #0xa0000000
+@@ -177,6 +274,5 @@ lowlevel_init:
+ mov pc,r10
+ 1:
+ sdram_init_sha
+-
+ mov pc,r10
+
+--- u-boot-1.3.2/common/cmd_nand.c 2008-03-09 16:20:02.000000000 +0100
++++ u-boot-new/common/cmd_nand.c 2008-06-24 21:21:14.000000000 +0200
+@@ -179,6 +179,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag,
+
+ if (strcmp(cmd, "info") == 0) {
+
++ nand_init(); /* go init the NAND */
++
+ putc('\n');
+ for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
+ if (nand_info[i].name)
+@@ -327,6 +329,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag,
+ (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
+ if (read) {
+ /* read */
++ printf("nand read opt\n");
++ udelay(10000);
+ nand_read_options_t opts;
+ memset(&opts, 0, sizeof(opts));
+ opts.buffer = (u_char*) addr;
+@@ -336,6 +340,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag,
+ ret = nand_read_opts(nand, &opts);
+ } else {
+ /* write */
++ printf("nand write opt\n");
++ udelay(10000);
+ nand_write_options_t opts;
+ memset(&opts, 0, sizeof(opts));
+ opts.buffer = (u_char*) addr;
+@@ -349,17 +355,27 @@ int do_nand(cmd_tbl_t * cmdtp, int flag,
+ }
+ } else if (s != NULL && !strcmp(s, ".oob")) {
+ /* read out-of-band data */
+- if (read)
++ if (read){
++ printf("nand read out-of-band data\n");
++ udelay(10000);
+ ret = nand->read_oob(nand, off, size, (size_t *) &size,
+ (u_char *) addr);
+- else
++ }
++ else{
++ printf("nand write out-of-band data\n");
++ udelay(10000);
+ ret = nand->write_oob(nand, off, size, (size_t *) &size,
+ (u_char *) addr);
++ }
+ } else {
+- if (read)
++ if (read){
+ ret = nand_read(nand, off, &size, (u_char *)addr);
+- else
+- ret = nand_write(nand, off, &size, (u_char *)addr);
++ }
++ else{
++ printf("nand write\n");
++ udelay(10000);
++ ret = nand_write(nand, off, &size, (u_char *)addr);
++ }
+ }
+
+ printf(" %d bytes %s: %s\n", size,
+--- u-boot-1.3.2/cpu/arm926ejs/imx27/interrupt.c 2008-06-25 04:12:35.000000000 +0200
++++ u-boot-new/cpu/arm926ejs/imx27/interrupt.c 2008-06-24 03:04:14.000000000 +0200
+@@ -100,6 +100,11 @@ void set_timer (ulong t)
+ {
+ }
+
++void reset_timer(void)
++{
++ reset_timer_masked();
++}
++
+ /*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+--- u-boot-1.3.2/cpu/arm926ejs/imx27/Makefile 2008-06-25 04:12:35.000000000 +0200
++++ u-boot-new/cpu/arm926ejs/imx27/Makefile 2008-06-23 20:04:37.000000000 +0200
+@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)lib$(SOC).a
+
+-COBJS = interrupt.o serial.o generic.o fec132.o fec_imx27.o miiphy.o
++COBJS = interrupt.o serial.o generic.o fec132.o fec_imx27.o miiphy.o nand.o
+
+ SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+ OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+--- u-boot-1.3.2/cpu/arm926ejs/imx27/nand.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-new/cpu/arm926ejs/imx27/nand.c 2008-06-24 22:58:01.000000000 +0200
+@@ -0,0 +1,975 @@
++/*
++ * (C) Copyright 2008 (nc) Armadeus Systems
++ *
++ * 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
++ */
++
++#include <common.h>
++#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
++
++#include <asm/errno.h>
++#include <nand.h>
++#include <asm/arch/imx-regs.h>
++
++#ifdef CFG_NFC_DEBUG
++# define NFC_DEBUG1(fmt, args...) printf(fmt, ##args)
++#else
++# define NFC_DEBUG1(fmt, args...)
++#endif
++
++#ifdef CONFIG_MTD_NAND_MXC_SWECC
++static int hardware_ecc = 0;
++#else
++static int hardware_ecc = 1;
++#endif
++
++/*struct nand_info {
++ bool bSpareOnly;
++ bool bStatusRequest;
++ u16 colAddr;
++ int is2k_Pagesize;
++};*/
++
++static u8 g_bSpareOnly;
++static u8 g_bStatusRequest;
++static u16 g_colAddr;
++static u8 is2k_Pagesize;
++
++ /* Macros to get byte and bit positions of ECC
++ */
++#define COLPOS(x) ((x) >> 3)
++#define BITPOS(x) ((x)& 0xf)
++
++
++#define TROP_US_DELAY 10000
++
++#define MIN(x, y) ((x < y) ? x : y)
++
++/*
++ * OOB placement block for use with hardware ecc generation
++ */
++static struct nand_oobinfo nand_hw_eccoob_8 = {
++ .useecc = MTD_NANDECC_AUTOPLACE,
++ .eccbytes = 5,
++ .eccpos = {6, 7, 8, 9, 10},
++ .oobfree = {{2, 3}, {11, 5}}
++};
++
++static struct nand_oobinfo nand_hw_eccoob_16 = {
++ .useecc = MTD_NANDECC_AUTOPLACE,
++ .eccbytes = 5,
++ .eccpos = {6, 7, 8, 9, 10},
++ .oobfree = {{0, 6}, {12, 4}}
++};
++
++
++/* These really don't belong here, as they are specific to the NAND Model */
++static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
++
++static struct nand_bbt_descr delta_bbt_descr = {
++ .options = 0,
++ .offs = 0,
++ .len = 2,
++ .pattern = scan_ff_pattern
++};
++
++
++#ifndef CONFIG_MTD_NAND_MXC_ECC_CORRECTION_OPTION2
++static int Ecc_disabled;
++#endif
++
++//static struct nand_info g_nandfc_info;
++
++/*
++ * not required for iMX27 NFC
++ */
++static void nfc_hwcontrol(struct mtd_info *mtdinfo, int cmd)
++{
++ return;
++}
++
++/*!
++ * This functions is used by upper layer to checks if device is ready
++ *
++ * @param mtd MTD structure for the NAND Flash
++ *
++ * @return 0 if device is busy else 1
++ */
++static int nfc_dev_ready(struct mtd_info *mtd)
++{
++ /*
++ * NFC handles R/B internally.Therefore,this function
++ * always returns status as ready.
++ */
++ return 1;
++}
++
++static void wait_op_done(int maxRetries, u16 param)
++{
++ while (maxRetries-- > 0) {
++ if (NFC_CONFIG2 & NFC_CONFIG2_INT) {
++ NFC_CONFIG2 &= ~NFC_CONFIG2_INT;
++ break;
++ }
++ udelay(1);
++ }
++ if (maxRetries <= 0)
++ printf("wait_op_done (%d): INT not set\n", param);
++}
++
++
++/*!
++ * This function issues the specified command to the NAND device and
++ * waits for completion.
++ *
++ * @param cmd command for NAND Flash
++ */
++static void send_cmd(u16 cmd)
++{
++ NFC_DEBUG1("send_cmd(0x%x)\n", cmd);
++
++ NFC_FLASH_CMD = (u16) cmd;
++ NFC_CONFIG2 = NFC_CONFIG2_FCMD;
++
++ /* Wait for operation to complete */
++ wait_op_done(TROP_US_DELAY, cmd);
++}
++
++/*!
++ * This function sends an address (or partial address) to the
++ * NAND device. The address is used to select the source/destination for
++ * a NAND command.
++ *
++ * @param addr address to be written to NFC.
++ */
++static void send_addr(u16 addr)
++{
++ NFC_DEBUG1("send_addr(0x%x)\n", addr);
++
++ NFC_FLASH_ADDR = addr;
++ NFC_CONFIG2 = NFC_CONFIG2_FADD;
++
++ /* Wait for operation to complete */
++ wait_op_done(TROP_US_DELAY, addr);
++}
++
++/*!
++ * This function requests the NANDFC to initate the transfer
++ * of data currently in the NANDFC RAM buffer to the NAND device.
++ *
++ * @param buf_id Specify Internal RAM Buffer number (0-3)
++ * @param bSpareOnly set 1 if only the spare area is transferred
++ */
++static void send_prog_page(u8 buf_id, u8 bSpareOnly)
++{
++ NFC_DEBUG1("send_prog_page (%d)\n", bSpareOnly);
++
++ /* NANDFC buffer 0 is used for page read/write */
++
++ NFC_BUF_ADDR = buf_id;
++
++ /* Configure spare or page+spare access */
++ if (!is2k_Pagesize) {
++ if (bSpareOnly) {
++ NFC_CONFIG1 |= NFC_CONFIG1_SP_EN;
++ } else {
++ NFC_CONFIG1 &= ~(NFC_CONFIG1_SP_EN);
++ }
++ }
++ NFC_CONFIG2 = NFC_CONFIG2_FDI;
++
++ /* Wait for operation to complete */
++ wait_op_done(TROP_US_DELAY, bSpareOnly);
++}
++
++/*!
++ * This function will correct the single bit ECC error
++ *
++ * @param buf_id Specify Internal RAM Buffer number (0-3)
++ * @param eccpos Ecc byte and bit position
++ * @param bSpareOnly set to 1 if only spare area needs correction
++ */
++
++static void nfc_correct_error(u8 buf_id, u16 eccpos, u8 bSpareOnly)
++{
++ u16 col;
++ u8 pos;
++ volatile u16 *buf;
++
++ /* Get col & bit position of error
++ these macros works for both 8 & 16 bits */
++ col = COLPOS(eccpos); /* Get half-word position */
++ pos = BITPOS(eccpos); /* Get bit position */
++
++ NFC_DEBUG1("nfc_correct_error (col=%d pos=%d)\n", col, pos);
++ /* Set the pointer for main / spare area */
++ if (!bSpareOnly) {
++ buf = (volatile u16 *)((ulong) (IMX_NFC_MAIN_AREA0 + (col >> 1) + (512 * buf_id)));
++ } else {
++ buf = (volatile u16 *)((ulong) (IMX_NFC_SPARE_AREA0 + (col >> 1) + (16 * buf_id)));
++ }
++
++ /* Fix the data */
++ *buf ^= (1 << pos);
++}
++
++
++/*!
++ * This function will maintains state of single bit Error
++ * in Main & spare area
++ *
++ * @param buf_id Specify Internal RAM Buffer number (0-3)
++ * @param spare set to true if only spare area needs correction
++ */
++static void nfc_correct_ecc(u8 buf_id, u8 spare)
++{
++#ifdef CONFIG_MTD_NAND_MXC_ECC_CORRECTION_OPTION2
++ static int lastErrMain = 0, lastErrSpare = 0; /* To maintain single bit
++ error in previous page */
++#endif
++ u16 value, ecc_status;
++ /* Read the ECC result */
++ ecc_status = NFC_ECC_STATUS_RESULT;
++
++#ifdef CONFIG_MTD_NAND_MXC_ECC_CORRECTION_OPTION2
++ /* Check for Error in Mainarea */
++ if ((ecc_status >> NFC_ECC_STAT_ERM_SHFT) == NFC_ECC_STAT_ERROR1) {
++ /* Check for error in previous page */
++ if (lastErrMain && !spare) {
++ value = NFC_ECC_RSLT_MAIN_AREA;
++ /* Correct single bit error in Mainarea
++ NFC will not correct the error in
++ current page */
++ nfc_correct_error(buf_id, value, 0);
++ } else {
++ /* Set if single bit error in current page */
++ lastErrMain = 1;
++ }
++ } else {
++ /* Reset if no single bit error in current page */
++ lastErrMain = 0;
++ }
++
++ /* Check for Error in Sparearea */
++ if ((ecc_status & NFC_ECC_STAT_ERS_MASK) == NFC_ECC_STAT_ERROR1) {
++ /* Check for error in previous page */
++ if (lastErrSpare) {
++ value = NFC_ECC_RSLT_SPARE_AREA;
++ /* Correct single bit error in Mainarea
++ NFC will not correct the error in
++ current page */&
++ nfc_correct_error(buf_id, value, 1);
++ } else {
++ /* Set if single bit error in current page */
++ lastErrSpare = 1;
++ }
++ } else {
++ /* Reset if no single bit error in current page */
++ lastErrSpare = 0;
++ }
++#else
++ if (((ecc_status >> NFC_ECC_STAT_ERM_SHFT) == NFC_ECC_STAT_ERROR1)
++ || ((ecc_status & NFC_ECC_STAT_ERS_MASK) == NFC_ECC_STAT_ERROR1)) {
++ if (Ecc_disabled) {
++ if ((ecc_status >> NFC_ECC_STAT_ERM_SHFT) == NFC_ECC_STAT_ERROR1) {
++ value = NFC_ECC_RSLT_MAIN_AREA;
++ /* Correct single bit error in Mainarea
++ NFC will not correct the error in
++ current page */
++ nfc_correct_error(buf_id, value, 0);
++ }
++ if ((ecc_status & NFC_ECC_STAT_ERS_MASK) == NFC_ECC_STAT_ERROR1) {
++ value = NFC_ECC_RSLT_SPARE_AREA;
++ /* Correct single bit error in Mainarea
++ NFC will not correct the error in
++ current page */
++ nfc_correct_error(buf_id, value, 1);
++ }
++
++ } else {
++ /* Disable ECC */
++ NFC_CONFIG1 &= ~(NFC_CONFIG1_ECC_EN);
++ Ecc_disabled = 1;
++ }
++ } else if (ecc_status == 0) {
++ if (Ecc_disabled) {
++ /* Enable ECC */
++ NFC_CONFIG1 |= NFC_CONFIG1_ECC_EN;
++ Ecc_disabled = 0;
++ }
++ } else {
++ /* 2-bit Error Do nothing */
++ }
++#endif /* CONFIG_MTD_NAND_MXC_ECC_CORRECTION_OPTION2 */
++
++}
++
++
++
++/*!
++ * This function requests the NANDFC to initated the transfer
++ * of data from the NAND device into in the NANDFC ram buffer.
++ *
++ * @param buf_id Specify Internal RAM Buffer number (0-3)
++ * @param bSpareOnly set 1 if only the spare area is transferred
++ */
++static void send_read_page(u8 buf_id, u8 bSpareOnly)
++{
++ NFC_DEBUG1("send_read_page (%d)\n", bSpareOnly);
++
++ /* NANDFC buffer 0 is used for page read/write */
++ NFC_BUF_ADDR = buf_id;
++
++ /* Configure spare or page+spare access */
++ if (!is2k_Pagesize) {
++ if (bSpareOnly) {
++ NFC_CONFIG1 |= NFC_CONFIG1_SP_EN;
++ } else {
++ NFC_CONFIG1 &= ~(NFC_CONFIG1_SP_EN);
++ }
++ }
++
++ NFC_CONFIG2 = NFC_CONFIG2_FDO_PAGE;
++
++ /* Wait for operation to complete */
++ wait_op_done(TROP_US_DELAY, bSpareOnly);
++
++ /* If there are single bit errors in
++ two consecutive page reads then
++ the error is not corrected by the
++ NFC for the second page.
++ Correct single bit error in driver */
++
++ nfc_correct_ecc(buf_id, bSpareOnly);
++}
++
++/*!
++ * This function requests the NANDFC to perform a read of the
++ * NAND device ID.
++ */
++static void send_read_id(struct mtd_info *mtd)
++{
++ struct nand_chip *this = mtd->priv;
++
++ NFC_DEBUG1("send_read_id \n");
++ /* NANDFC buffer 0 is used for device ID output */
++ NFC_BUF_ADDR = 0x0;
++
++ /* Read ID into main buffer */
++ NFC_CONFIG1 &= (~(NFC_CONFIG1_SP_EN));
++ NFC_CONFIG2 = NFC_CONFIG2_FDO_ID;
++
++ /* Wait for operation to complete */
++ wait_op_done(TROP_US_DELAY, 0);
++
++ if (this->options & NAND_BUSWIDTH_16) {
++ volatile u16 *mainBuf = (volatile u16 *)((ulong) (IMX_NFC_MAIN_AREA0));
++
++ /*
++ * Pack the every-other-byte result for 16-bit ID reads
++ * into every-byte as the generic code expects and various
++ * chips implement.
++ */
++
++ mainBuf[0] = (mainBuf[0] & 0xff) | ((mainBuf[1] & 0xff) << 8);
++ mainBuf[1] = (mainBuf[2] & 0xff) | ((mainBuf[3] & 0xff) << 8);
++ mainBuf[2] = (mainBuf[4] & 0xff) | ((mainBuf[5] & 0xff) << 8);
++ }
++}
++
++
++
++/*!
++ * This function writes data of length \b len to buffer \b buf. The data to be
++ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
++ * Operation by the NFC, the data is written to NAND Flash
++ *
++ * @param mtd MTD structure for the NAND Flash
++ * @param buf data to be written to NAND Flash
++ * @param len number of bytes to be written
++ */
++static void nfc_write_buf(struct mtd_info *mtd,
++ const u_char * buf, int len)
++{
++ int i = 0;
++ ulong p;
++ int nbbytes_main = 0, nbbytes_spare=0;
++ int bytes_multi = 0;
++
++ if (!g_bSpareOnly)
++ {
++ /* Main Area */
++ nbbytes_main = mtd->oobblock - g_colAddr;
++ if( nbbytes_main > 0 )
++ {
++ nbbytes_main = min(len, nbbytes_main);
++ bytes_multi = nbbytes_main & 0xFFFFFFFE;
++ p = (ulong)(IMX_NFC_MAIN_AREA0)+g_colAddr;
++ for( i=0; i<bytes_multi; i+=2 ){
++ *((volatile u16*)(p + i)) = *((u16*) &buf[i]);
++ }
++ if( nbbytes_main & 1 ){
++ *((volatile u16*)(p + i +1)) = buf[i];
++ i++;
++ }
++ }
++ }
++ if (g_bSpareOnly && g_colAddr < mtd->oobblock )
++ g_colAddr += mtd->oobblock;
++
++ /* Spare Area */
++ nbbytes_spare = len - nbbytes_main;
++ if( nbbytes_spare )
++ {
++ nbbytes_spare = min(mtd->oobsize - g_colAddr+mtd->oobblock, nbbytes_spare);
++ bytes_multi = nbbytes_spare & 0xFFFFFFFE;
++ p = (volatile u16*)((ulong) (IMX_NFC_SPARE_AREA0));
++ for( i=0; i<bytes_multi; i+=2 ){
++ *((volatile u16*)(p + i)) = *((u16*) &buf[nbbytes_main+i]);
++ }
++ if( nbbytes_spare & 1 )
++ *((volatile u16*)(p + i +1)) = buf[nbbytes_main+i+1];
++ }
++ g_colAddr += nbbytes_main + nbbytes_spare;
++}
++
++/*
++ * These functions are quite problematic for the NFC. Luckily they are
++ * not used in the current nand code, except for nand_command, which
++ * we've defined our own anyway.
++ */
++static void nfc_write_word(struct mtd_info *mtd, u16 word)
++{
++ printf("nfc_write_word: WARNING, this function does not work with the iMX27 NFC!\n");
++}
++static void nfc_write_byte(struct mtd_info *mtd, u_char byte)
++{
++ printf("nfc_write_byte: WARNING, this function does not work with the iMX27 NFC!\n");
++}
++
++
++/*!
++ * This function id is used to read the data buffer from the NAND Flash. To
++ * read the data from NAND Flash first the data output cycle is initiated by
++ * the NFC, which copies the data to RAMbuffer. This data of length \b len is
++ * then copied to buffer \b buf.
++ *
++ * @param mtd MTD structure for the NAND Flash
++ * @param buf data to be read from NAND Flash
++ * @param len number of bytes to be read
++ */
++static void nfc_read_buf(struct mtd_info *mtd, u_char * buf, int len)
++{
++ int i = 0;
++ ulong p;
++ int nbbytes_main = 0, nbbytes_spare=0;
++ int bytes_multi = 0;
++
++ if (!g_bSpareOnly)
++ {
++ /* Main Area */
++ nbbytes_main = mtd->oobblock - g_colAddr;
++ if( nbbytes_main > 0 )
++ {
++ nbbytes_main = min(len, nbbytes_main);
++ bytes_multi = nbbytes_main & 0xFFFFFFFE;
++ p = (ulong)(IMX_NFC_MAIN_AREA0)+g_colAddr;
++ for( i=0; i<bytes_multi; i+=2 ){
++ *((u16*) &buf[i]) = *((volatile u16*)(p + i));
++ }
++ if( nbbytes_main & 1 )
++ buf[i++] = *((volatile u16*)(p + i +1));
++ }
++ }
++ if (g_bSpareOnly && g_colAddr < mtd->oobblock )
++ g_colAddr += mtd->oobblock;
++
++ /* Spare Area */
++ nbbytes_spare = len - nbbytes_main;
++ if( nbbytes_spare )
++ {
++ nbbytes_spare = min(mtd->oobsize - g_colAddr+mtd->oobblock, nbbytes_spare);
++ bytes_multi = nbbytes_spare & 0xFFFFFFFE;
++ p = (volatile u16*)((ulong) (IMX_NFC_SPARE_AREA0));
++ for( i=0; i<bytes_multi; i+=2 ){
++ *((u16*) &buf[nbbytes_main+i]) = *((volatile u16*)(p + i));
++ }
++ if( nbbytes_spare & 1 )
++ buf[nbbytes_main+i+1] = *((volatile u16*)(p + i +1));
++ }
++ g_colAddr += nbbytes_main + nbbytes_spare;
++}
++
++/*
++ * read a word. Not implemented as not used in NAND code.
++ */
++static u16 nfc_read_word(struct mtd_info *mtd)
++{
++ printf("nfc_read_word: UNIMPLEMENTED.\n");
++ return 0;
++}
++
++static u16 get_dev_status(void)
++{
++ volatile u16 *mainBuf = (volatile u32 *)((ulong) (IMX_NFC_MAIN_AREA1));
++ u32 store;
++ u16 ret;
++ /* Issue status request to NAND device */
++
++ /* store the main area1 first word, later do recovery */
++ store = *((u32 *) mainBuf);
++ /*
++ * NANDFC buffer 1 is used for device status to prevent
++ * corruption of read/write buffer on status requests.
++ */
++ NFC_BUF_ADDR = 1;
++
++ /* Send the Read status command before reading status */
++ send_cmd(NAND_CMD_STATUS);
++
++ /* Read status into main buffer */
++ NFC_CONFIG1 &= (~(NFC_CONFIG1_SP_EN));
++ NFC_CONFIG2 = NFC_CONFIG2_FDO_STATUS;
++
++ /* Wait for operation to complete */
++ wait_op_done(TROP_US_DELAY, 0);
++
++ /* get status, then recovery area 1 data */
++ ret = mainBuf[0];
++ printf("get_dev_status %x\n", ret);
++ *((u32 *) mainBuf) = store;
++
++ /* Status is placed in first word of main buffer */
++ return ret;
++}
++
++
++/*!
++ * This function reads byte from the NAND Flash
++ *
++ * @param mtd MTD structure for the NAND Flash
++ *
++ * @return data read from the NAND Flash
++ */
++static u_char nfc_read_byte(struct mtd_info *mtd)
++{
++ u_char retVal = 0;
++ u16 col, rdWord;
++ volatile u16 *mainBuf = (volatile u16 *)((ulong) (IMX_NFC_MAIN_AREA0));
++ volatile u16 *spareBuf = (volatile u16 *)((ulong) (IMX_NFC_SPARE_AREA0));
++
++ /* Check for status request */
++ if (g_bStatusRequest) {
++ return (get_dev_status() & 0xFF);
++ }
++
++ /* Get column for 16-bit access */
++ col = g_colAddr >> 1;
++
++ /* If we are accessing the spare region */
++ if (g_bSpareOnly) {
++ rdWord = spareBuf[col];
++ } else {
++ rdWord = mainBuf[col];
++ }
++
++ /* Pick upper/lower byte of word from RAM buffer */
++ if (g_colAddr & 0x1) {
++ retVal = (rdWord >> 8) & 0xFF;
++ } else {
++ retVal = rdWord & 0xFF;
++ }
++ NFC_DEBUG1("\treval: %x, rdWord:%x \n",retVal, rdWord);
++
++ /* Update saved column address */
++ g_colAddr++;
++
++ return retVal;
++}
++
++/* this function is called after Programm and Erase Operations to
++ * check for success or failure */
++static int nfc_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
++{
++ wait_op_done(TROP_US_DELAY, 9);
++ return 0;
++}
++
++static int nfc_correct_data(struct mtd_info *mtd, u_char * dat,
++ u_char * read_ecc, u_char * calc_ecc)
++{
++ /*
++ * 1-Bit errors are automatically corrected in HW. No need for
++ * additional correction. 2-Bit errors cannot be corrected by
++ * HW ECC, so we need to return failure
++ */
++ u16 ecc_status = NFC_ECC_STATUS_RESULT;
++
++ if (((ecc_status & NFC_ECC_STAT_ERS_MASK) == NFC_ECC_STAT_ERROR2) ||
++ ((ecc_status >> NFC_ECC_STAT_ERM_SHFT) == NFC_ECC_STAT_ERROR2)) {
++ return -1;
++ }
++
++ return 0;
++}
++
++
++/*!
++ * This function is used by the upper layer to write command to NAND Flash for
++ * different operations to be carried out on NAND Flash
++ *
++ * @param mtd MTD structure for the NAND Flash
++ * @param command command for NAND Flash
++ * @param column column offset for the page read
++ * @param page_addr page to be read from NAND Flash
++ */
++static void nfc_cmdfunc(struct mtd_info *mtd, unsigned command,
++ int column, int page_addr)
++{
++ NFC_DEBUG1("nfc_cmdfunc (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
++ command, column, page_addr);
++
++ if ((FMCR & FMCR_NF_FMS) == FMCR_NF_FMS)
++ is2k_Pagesize = 1;
++
++ /*
++ * Reset command state information
++ */
++ g_bStatusRequest = 0;
++
++ /*
++ * Command pre-processing step
++ */
++ switch (command) {
++
++ case NAND_CMD_STATUS:
++ g_colAddr = 0;
++ g_bStatusRequest = 1;
++ break;
++
++ case NAND_CMD_READ0:
++ g_colAddr = column;
++ g_bSpareOnly = 0;
++ break;
++
++ case NAND_CMD_READOOB:
++ g_colAddr = column;
++ g_bSpareOnly = 1;
++ if (is2k_Pagesize)
++ command = NAND_CMD_READ0; /* only READ0 is valid */
++ break;
++
++ case NAND_CMD_SEQIN:
++ if (column >= mtd->oobblock) {
++ if (is2k_Pagesize) {
++ /**
++ * FIXME: before send SEQIN command for write OOB,
++ * We must read one page out.
++ * For K9F1GXX has no READ1 command to set current HW
++ * pointer to spare area, we must write the whole page including OOB together.
++ */
++ /* call itself to read a page */
++ nfc_cmdfunc(mtd, NAND_CMD_READ0, 0,
++ page_addr);
++ }
++ g_colAddr = column - mtd->oobblock;
++ g_bSpareOnly = 1;
++ /* Set program pointer to spare region */
++ if (!is2k_Pagesize)
++ send_cmd(NAND_CMD_READOOB);
++ } else {
++ g_bSpareOnly = 0;
++ g_colAddr = column;
++ /* Set program pointer to page start */
++ if (!is2k_Pagesize)
++ send_cmd(NAND_CMD_READ0);
++ }
++ break;
++
++ case NAND_CMD_PAGEPROG:
++#ifndef CONFIG_MTD_NAND_MXC_ECC_CORRECTION_OPTION2
++ if (Ecc_disabled) {
++ /* Enable Ecc for page writes */
++ NFC_CONFIG1 |= NFC_CONFIG1_ECC_EN;
++ }
++#endif
++
++ send_prog_page(0, g_bSpareOnly);
++
++ if (is2k_Pagesize) {
++ /* data in 4 areas datas */
++ send_prog_page(1, g_bSpareOnly);
++ send_prog_page(2, g_bSpareOnly);
++ send_prog_page(3, g_bSpareOnly);
++ }
++
++ break;
++
++ case NAND_CMD_ERASE1:break;
++ default: break;
++ }
++
++ /*
++ * Write out the command to the device.
++ */
++ send_cmd(command);
++
++ /*
++ * Write out column address, if necessary
++ */
++ if (column != -1) {
++ /*
++ * MXC NANDFC can only perform full page+spare or
++ * spare-only read/write. When the upper layers
++ * layers perform a read/write buf operation,
++ * we will used the saved column adress to index into
++ * the full page.
++ */
++ send_addr(0);
++ if (is2k_Pagesize)
++ send_addr(0); /* another col addr cycle for 2k page */
++ }
++
++ /*
++ * Write out page address, if necessary
++ */
++ if (page_addr != -1) {
++ send_addr(page_addr & 0xff); /* paddr_0 - p_addr_7 */
++
++ if (is2k_Pagesize) {
++ send_addr((page_addr >> 8) & 0xFF);
++ if (mtd->size >= 0x42000000) {
++ send_addr((page_addr >> 16) & 0xff);
++ }
++ } else {
++ /* One more address cycle for higher density devices */
++ if (mtd->size >= 0x4000000) {
++ send_addr((page_addr >> 8) & 0xff); /* paddr_8 - paddr_15 */
++ send_addr((page_addr >> 16) & 0xff);
++ } else
++ send_addr((page_addr >> 8) & 0xff); /* paddr_8 - paddr_15 */
++ }
++ }
++
++ /*
++ * Command post-processing step
++ */
++ switch (command) {
++
++ case NAND_CMD_RESET:
++ break;
++
++ case NAND_CMD_READOOB:
++ case NAND_CMD_READ0:
++ if (is2k_Pagesize) {
++ /* send read confirm command */
++ send_cmd(NAND_CMD_READSTART);
++ /* read for each AREA */
++ send_read_page(0, g_bSpareOnly);
++ send_read_page(1, g_bSpareOnly);
++ send_read_page(2, g_bSpareOnly);
++ send_read_page(3, g_bSpareOnly);
++ } else {
++ send_read_page(0, g_bSpareOnly);
++ }
++ break;
++
++ case NAND_CMD_READID:
++ send_read_id(mtd);
++ break;
++
++ case NAND_CMD_PAGEPROG:
++#ifndef CONFIG_MTD_NAND_MXC_ECC_CORRECTION_OPTION2
++ if (Ecc_disabled) {
++ /* Disble Ecc after page writes */
++ NFC_CONFIG1 &= ~(NFC_CONFIG1_ECC_EN);
++ }
++#endif
++ break;
++
++ case NAND_CMD_STATUS:
++ break;
++
++ case NAND_CMD_ERASE2:
++ break;
++ }
++}
++
++/*!
++ * This function is used by upper layer for select and deselect of the NAND
++ * chip
++ *
++ * @param mtd MTD structure for the NAND Flash
++ * @param chip val indicating select or deselect
++ */
++static void nfc_select_chip(struct mtd_info *mtd, int chip)
++{
++#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE
++ if (chip > 0) {
++ NFC_DEBUG1("ERROR: Illegal chip select (chip = %d)\n", chip);
++ return;
++ }
++
++ if (chip == -1) {
++ NFC_CONFIG1 &= (~(NFC_CONFIG1_CEn));
++ return;
++ }
++
++ NFC_CONFIG1 |= NFC_CONFIG1_CEn;
++#endif
++ NFC_DEBUG1("nfc_select_chip: %d)\n", chip);
++ switch (chip) {
++ case -1:
++ /* Disable the NFC clock */
++ PCCR1 &= ~PCCR1_NFC_BAUDEN;
++ break;
++ case 0:
++ /* Enable the NFC clock */
++ PCCR1 |= PCCR1_NFC_BAUDEN;
++ break;
++
++ default:
++ break;
++ }
++}
++
++
++static void nfc_enable_hwecc(struct mtd_info *mtd, int mode)
++{
++ /*
++ * If HW ECC is enabled, we turn it on during init. There is
++ * no need to enable again here.
++ */
++}
++
++static int nfc_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
++ u_char * ecc_code)
++{
++ /*
++ * Just return success. HW ECC does not read/write the NFC spare
++ * buffer. Only the FLASH spare area contains the calcuated ECC.
++ */
++ return 0;
++}
++
++/*!
++ * This function is used by the upper layer to verify the data in NAND Flash
++ * with the data in the \b buf.
++ *
++ * @param mtd MTD structure for the NAND Flash
++ * @param buf data to be verified
++ * @param len length of the data to be verified
++ *
++ * @return -EFAULT if error else 0
++ *
++ */
++static int nfc_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
++{
++ return -EFAULT;
++}
++
++
++
++/*
++ * Board-specific NAND initialization. The following members of the
++ * argument are board-specific (per include/linux/mtd/nand_new.h):
++ * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
++ * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
++ * - hwcontrol: hardwarespecific function for accesing control-lines
++ * - dev_ready: hardwarespecific function for accesing device ready/busy line
++ * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
++ * only be provided if a hardware ECC is available
++ * - eccmode: mode of ecc, see defines
++ * - chip_delay: chip dependent delay for transfering data from array to
++ * read regs (tR)
++ * - options: various chip options. They can partly be set to inform
++ * nand_scan about special functionality. See the defines for further
++ * explanation
++ * Members with a "?" were not set in the merged testing-NAND branch,
++ * so they are not set here either.
++ */
++int board_nand_init(struct nand_chip *nand)
++{
++ g_colAddr = 0;
++
++ //memset((char *)&g_nandfc_info, 0, sizeof(g_nandfc_info));
++ //nand->priv = g_nandfc_info;
++
++ /* 50 us command delay time */
++ nand->chip_delay = 5;
++
++ nand->hwcontrol = nfc_hwcontrol;
++ //nand->options = NAND_BUSWIDTH_16;
++ nand->waitfunc = nfc_wait; /////// tdb
++ nand->read_byte = nfc_read_byte;
++ nand->write_byte = nfc_write_byte;
++ nand->read_word = nfc_read_word;
++ nand->write_word = nfc_write_word;
++ nand->read_buf = nfc_read_buf;
++ nand->write_buf = nfc_write_buf;
++ nand->dev_ready =nfc_dev_ready;
++ nand->select_chip = nfc_select_chip;
++ nand->verify_buf = nfc_verify_buf;
++
++ nand->cmdfunc = nfc_cmdfunc;
++ nand->badblock_pattern = &delta_bbt_descr;
++
++ if (hardware_ecc) {
++ nand->calculate_ecc = nfc_calculate_ecc; //void
++ nand->enable_hwecc = nfc_enable_hwecc; // void
++ nand->correct_data = nfc_correct_data;
++ nand->eccsize = 512;
++ nand->eccbytes = 3;
++ nand->eccmode = NAND_ECC_HW3_512;
++ NFC_CONFIG1 |= NFC_CONFIG1_ECC_EN;
++ } else {
++ nand->eccmode = NAND_ECC_SOFT;
++ }
++
++ /* NAND bus width determines access funtions used by upper layer */
++ //if (flash->width == 2) {
++ // nand->options |= NAND_BUSWIDTH_16 | NAND_USE_FLASH_BBT;
++ // nand->autooob = &nand_hw_eccoob_16;
++ //} else {
++ nand->options |= 0;//NAND_USE_FLASH_BBT;
++ nand->autooob = &nand_hw_eccoob_8;
++ //}
++
++ /* preset operation */
++ /* Unlock the internal RAM Buffer */
++ NFC_CONFIG = NFC_CONFIG_UNLOCKED;
++
++ /* Blocks to be unlocked */
++ NFC_UNLOCKSTART_BLKADDR = 0x0;
++ NFC_UNLOCKEND_BLKADDR = 0x4000;
++
++ /* Unlock Block Command for given address range */
++ NFC_WRPROT = NFC_WRPROT_UNLOCKBLK;
++
++
++
++ is2k_Pagesize = 0;
++
++
++ return 0;
++}
++
++#endif
++
++
+--- u-boot-1.3.2/include/asm-arm/arch-imx27/imx-regs.h 2008-06-25 04:12:35.000000000 +0200
++++ u-boot-new/include/asm-arm/arch-imx27/imx-regs.h 2008-06-24 07:26:49.000000000 +0200
+@@ -62,8 +62,13 @@
+ #define IMX_PLL_BASE (0x27000 + IMX_IO_BASE)
+ #define IMX_SYSTEM_CTL_BASE (0x27800 + IMX_IO_BASE)
+
+-#define IMX_ESD_BASE (0xd8001000)
+-#define IMX_WEIM_BASE (0xd8002000)
++#define IMX_NFC_BASE (0xD8000000)
++#define IMX_NFC_MAIN_AREA0 (0xD8000000)
++#define IMX_NFC_MAIN_AREA1 (0xD8000200)
++#define IMX_NFC_SPARE_AREA0 (0xD8000800)
++#define IMX_ESD_BASE (0xD8001000)
++#define IMX_WEIM_BASE (0xD8002000)
++
+
+ /* AIPI */
+ #define AIPI1_PSR0 __REG(IMX_AIPI1_BASE + 0x00)
+@@ -72,7 +77,34 @@
+ #define AIPI2_PSR1 __REG(IMX_AIPI2_BASE + 0x04)
+
+ /* System Control */
++#define FMCR __REG(IMX_SYSTEM_CTL_BASE + 0x14)
+ #define GPCR __REG(IMX_SYSTEM_CTL_BASE + 0x18)
++#define WBCR __REG(IMX_SYSTEM_CTL_BASE + 0x1C)
++#define DSCR1 __REG(IMX_SYSTEM_CTL_BASE + 0x20)
++#define DSCR2 __REG(IMX_SYSTEM_CTL_BASE + 0x24)
++#define DSCR3 __REG(IMX_SYSTEM_CTL_BASE + 0x28)
++#define DSCR4 __REG(IMX_SYSTEM_CTL_BASE + 0x2C)
++#define DSCR5 __REG(IMX_SYSTEM_CTL_BASE + 0x30)
++#define DSCR6 __REG(IMX_SYSTEM_CTL_BASE + 0x34)
++#define DSCR7 __REG(IMX_SYSTEM_CTL_BASE + 0x38)
++#define DSCR8 __REG(IMX_SYSTEM_CTL_BASE + 0x3C)
++#define DSCR9 __REG(IMX_SYSTEM_CTL_BASE + 0x40)
++#define DSCR10 __REG(IMX_SYSTEM_CTL_BASE + 0x44)
++#define DSCR11 __REG(IMX_SYSTEM_CTL_BASE + 0x48)
++#define DSCR12 __REG(IMX_SYSTEM_CTL_BASE + 0x4C)
++#define DSCR13 __REG(IMX_SYSTEM_CTL_BASE + 0x50)
++#define PSCR __REG(IMX_SYSTEM_CTL_BASE + 0x54)
++#define PMCR __REG(IMX_SYSTEM_CTL_BASE + 0x58)
++#define DCVR0 __REG(IMX_SYSTEM_CTL_BASE + 0x60)
++#define DCVR1 __REG(IMX_SYSTEM_CTL_BASE + 0x64)
++#define DCVR2 __REG(IMX_SYSTEM_CTL_BASE + 0x68)
++#define DCVR3 __REG(IMX_SYSTEM_CTL_BASE + 0x6C)
++
++/* System Control bit definition*/
++#define FMCR_NF_FMS (1<<5)
++#define FMCR_NF_16BIT_SEL (1<<4)
++
++
+
+ /* Chip Select Registers */
+ #define CS0U __REG(IMX_WEIM_BASE + 0x00) /* Chip Select 0 Upper Register */
+@@ -317,6 +349,13 @@
+ * i.MX1 and i.MXL: 0 <= x <= 3
+ * i.MX27 : 0 <= x <= 5
+ */
++#define PORTA 0
++#define PORTB 1
++#define PORTC 2
++#define PORTD 3
++#define PORTE 4
++#define PORTF 5
++
+ #define DDIR(x) __REG2(IMX_GPIO_BASE + 0x00, ((x) & 7) << 8)
+ #define OCR1(x) __REG2(IMX_GPIO_BASE + 0x04, ((x) & 7) << 8)
+ #define OCR2(x) __REG2(IMX_GPIO_BASE + 0x08, ((x) & 7) << 8)
+@@ -340,12 +379,12 @@
+ #define GPIO_PORT_SHIFT 5
+ #define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
+
+-#define GPIO_PORTA (0 << GPIO_PORT_SHIFT)
+-#define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
+-#define GPIO_PORTC (2 << GPIO_PORT_SHIFT)
+-#define GPIO_PORTD (3 << GPIO_PORT_SHIFT)
+-#define GPIO_PORTE (4 << GPIO_PORT_SHIFT)
+-#define GPIO_PORTF (5 << GPIO_PORT_SHIFT)
++#define GPIO_PORTA (PORTA << GPIO_PORT_SHIFT)
++#define GPIO_PORTB (PORTB << GPIO_PORT_SHIFT)
++#define GPIO_PORTC (PORTC << GPIO_PORT_SHIFT)
++#define GPIO_PORTD (PORTD << GPIO_PORT_SHIFT)
++#define GPIO_PORTE (PORTE << GPIO_PORT_SHIFT)
++#define GPIO_PORTF (PORTF << GPIO_PORT_SHIFT)
+
+ #define GPIO_OUT (1 << 8)
+ #define GPIO_IN (0 << 8)
+@@ -398,4 +437,58 @@
+ #define I2SR_IIF (1<<1) /* I2C interrupt */
+ #define I2SR_RXAK (1<<0) /* I2C Received Acknowledge */
+
++/*
++ * NFC module
++ */
++#define NFC_BUFSIZE __REG16(IMX_NFC_BASE + 0xE00) /* Internal SRAM Size */
++#define NFC_BLCK_ADD_LOCK __REG16(IMX_NFC_BASE + 0xE02) /* NAND Flash Block
++ Address for Lock Check */
++#define NFC_BUF_ADDR __REG16(IMX_NFC_BASE + 0xE04) /* Buffer Number for Page Data Transfer To/
++ From Flash Memory */
++#define NFC_FLASH_ADDR __REG16(IMX_NFC_BASE + 0xE06) /* NAND Flash Address */
++#define NFC_FLASH_CMD __REG16(IMX_NFC_BASE + 0xE08) /* NAND Flash Command */
++#define NFC_CONFIG __REG16(IMX_NFC_BASE + 0xE0A) /* NFC Internal Buffer Lock Control */
++#define NFC_ECC_STATUS_RESULT __REG16(IMX_NFC_BASE + 0xE0C) /* Controller Status/Result of Flash Operation */
++#define NFC_ECC_RSLT_MAIN_AREA __REG16(IMX_NFC_BASE + 0xE0E) /* ECC Error Position of Main Area Data Error */
++#define NFC_ECC_RSLT_SPARE_AREA __REG16(IMX_NFC_BASE + 0xE10) /* ECC Error Position of Spare Area Data Error */
++#define NFC_WRPROT __REG16(IMX_NFC_BASE + 0xE12) /* Nand Flash Write Protection */
++#define NFC_UNLOCKSTART_BLKADDR __REG16(IMX_NFC_BASE + 0xE14) /* Start Address for Write Protection Unlock */
++#define NFC_UNLOCKEND_BLKADDR __REG16(IMX_NFC_BASE + 0xE16) /* End Address for Write Protection Unlock */
++#define NFC_WRPR_STAT __REG16(IMX_NFC_BASE + 0xE18) /* Current Nand Flash Write Protection Status */
++#define NFC_CONFIG1 __REG16(IMX_NFC_BASE + 0xE1A) /* Nand Flash Operation Configuration 1 */
++#define NFC_CONFIG2 __REG16(IMX_NFC_BASE + 0xE1C) /* Nand Flash Operation Configuration 2 */
++
++/* NFC_ECC_STATUS_RESULT Status Register Bit Fields */
++#define NFC_ECC_STAT_ERM_SHFT (2) /* ERM shift */
++#define NFC_ECC_STAT_ERS_MASK (0x03) /* ERS mask */
++#define NFC_ECC_STAT_ERROR1 (1<<0) /* correctable error */
++#define NFC_ECC_STAT_ERROR2 (1<<1) /* non correctable error */
++
++/* NFC_CONFIG Control Register Bit Fields */
++#define NFC_CONFIG_UNLOCKED (1<<1) /* unlocked */
++#define NFC_CONFIG_LOCKED (1<<0) /* locked */
++/* NFC_WRPROT Control Register Bit Fields */
++#define NFC_WRPROT_UNLOCKBLK (4<<0) /* unlock block according to given address range */
++#define NFC_WRPROT_LOCKALL (2<<0) /* lock all */
++#define NFC_WRPROT_LOCKTIGHT (1<<0) /* lock-tight locked blocks */
++/* NFC_WRPR_STAT Status Register Bit Fields */
++#define NFC_WRPR_US (1<<2) /* Unlocked status */
++#define NFC_WRPR_LS (1<<1) /* Locked status */
++#define NFC_WRPR_LTS (1<<0) /* Lock-tight Status */
++/* NFC_CONFIG1 Control Register Bit Fields */
++#define NFC_CONFIG1_CEn (1<<7) /* Flash force CE */
++#define NFC_CONFIG1_RST (1<<6) /* Reset */
++#define NFC_CONFIG1_BIG (1<<5) /* Big Endian Mode */
++#define NFC_CONFIG1_INT_MSK (1<<4) /* Mask Interrupt Bit */
++#define NFC_CONFIG1_ECC_EN (1<<3) /* ECC operation enable */
++#define NFC_CONFIG1_SP_EN (1<<2) /* Flash spare enable */
++/* NFC_CONFIG2 Control Register Bit Fields */
++#define NFC_CONFIG2_INT (1<<15) /* Interrupt */
++#define NFC_CONFIG2_FDO_STATUS (4<<3) /* Flash status output */
++#define NFC_CONFIG2_FDO_ID (2<<3) /* Flash ID output */
++#define NFC_CONFIG2_FDO_PAGE (1<<3) /* Flash data output */
++#define NFC_CONFIG2_FDI (1<<2) /* Flash data input */
++#define NFC_CONFIG2_FADD (1<<1) /* Flash address input */
++#define NFC_CONFIG2_FCMD (1<<0) /* Flash command input */
+ #endif /* _IMX_REGS_H */
++
+--- u-boot-1.3.2/include/configs/pcm038.h 2008-06-25 04:12:35.000000000 +0200
++++ u-boot-new/include/configs/pcm038.h 2008-06-24 22:12:48.000000000 +0200
+@@ -78,7 +78,7 @@
+ * neccessary in include/cmd_confdefs.h file. (Un)comment for getting
+ * functionality or size of u-boot code.
+ */
+-/*#define CONFIG_COMMANDS (CONFIG_CMD_DFL \
++#define CONFIG_COMMANDS (CONFIG_CMD_DFL \
+ | CFG_CMD_NET \
+ | CFG_CMD_PING \
+ | CFG_CMD_DHCP \
+@@ -86,11 +86,12 @@
+ | CFG_CMD_I2C \
+ | CFG_CMD_DATE \
+ | CFG_CMD_EEPROM \
++ | CFG_CMD_NAND \
+ | CONFIG_CMD_ALL \
+ )
+
+-#include <cmd_confdefs.h>
+-*/
++//#include <cmd_confdefs.h>
++
+ #include <config_cmd_default.h>
+ #define CONFIG_CMD_PING
+ #define CONFIG_CMD_DHCP
+@@ -128,7 +129,8 @@
+ #define CONFIG_DOS_PARTITION
+ /*#define CONFIG_ISO_PARTITION
+ */
+-#undef CONFIG_CMD_NAND
++#define CONFIG_CMD_NAND
++#define CONFIG_NEW_NAND_CODE
+ #undef CONFIG_CMD_ONENAND
+ #undef CONFIG_CMD_PCMCIA
+ #undef CONFIG_CMD_USB
+@@ -149,7 +151,7 @@
+ /* eval_board=evk9328
+ * Boot options. Setting delay to -1 stops autostart count down.
+ */
+-#define CONFIG_BOOTDELAY 20
++#define CONFIG_BOOTDELAY -1
+
+ #define CONFIG_BOOTARGS \
+ CONFIG_CONSOLE " root=/dev/mtdblock3 rootfstype=jffs2 "CONFIG_MTDPARTS
+@@ -277,6 +279,17 @@
+ #define CONFIG_STACKSIZE_FIQ (4<<10) /* FIQ stack */
+ #endif
+
++
++/*=====================*/
++/* Flash & Environment */
++/*=====================*/
++#define CFG_MAX_NAND_DEVICE 1
++#define NAND_MAX_CHIPS 1
++#define CFG_NAND_BASE (0xD8000000)
++//#define CONFIG_MTD_NAND_VERIFY_WRITE 1
++//#define CFG_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */
++/*=====================*/
++
+ /*
+ * Clocks configuration
+ */
+@@ -730,18 +743,15 @@
+ /*
+ * Default configuration for GPIOs and peripherals
+ */
+-#define CFG_DDIR_A_VAL 0x00000000
+-#define CFG_OCR1_A_VAL 0x00000000
+-#define CFG_OCR2_A_VAL 0x00000000
++#define CFG_DDIR_A_VAL 0x00FFFFC0 /* for debug */
++#define CFG_OCR1_A_VAL 0xFFFFF000 /* for debug */
++#define CFG_OCR2_A_VAL 0x0000FFFF
+ #define CFG_ICFA1_A_VAL 0xFFFFFFFF
+ #define CFG_ICFA2_A_VAL 0xFFFFFFFF
+ #define CFG_ICFB1_A_VAL 0xFFFFFFFF
+ #define CFG_ICFB2_A_VAL 0xFFFFFFFF
+ #define CFG_DR_A_VAL 0x00000000
+-
+-/* Setup for PA23 which is Reset Default PA23 but has to become
+- CS5 */
+-#define CFG_GIUS_A_VAL 0x00007FF8
++#define CFG_GIUS_A_VAL 0xFFFFFFFF
+ #define CFG_ICR1_A_VAL 0x00000000
+ #define CFG_ICR2_A_VAL 0x00000000
+ #define CFG_IMR_A_VAL 0x00000000
+@@ -756,7 +766,7 @@
+ #define CFG_ICFB1_B_VAL 0xFFFFFFFF
+ #define CFG_ICFB2_B_VAL 0xFFFFFFFF
+ #define CFG_DR_B_VAL 0x00000000
+-#define CFG_GIUS_B_VAL 0xFFFFFFFF
++#define CFG_GIUS_B_VAL 0xFF3FFFF3
+ #define CFG_ICR1_B_VAL 0x00000000
+ #define CFG_ICR2_B_VAL 0x00000000
+ #define CFG_IMR_B_VAL 0x00000000
+@@ -771,12 +781,12 @@
+ #define CFG_ICFB1_C_VAL 0xFFFFFFFF
+ #define CFG_ICFB2_C_VAL 0xFFFFFFFF
+ #define CFG_DR_C_VAL 0x00000000
+-#define CFG_GIUS_C_VAL 0x0007FFFF
++#define CFG_GIUS_C_VAL 0xFFFFFFFF
+ #define CFG_ICR1_C_VAL 0x00000000
+ #define CFG_ICR2_C_VAL 0x00000000
+ #define CFG_IMR_C_VAL 0x00000000
+ #define CFG_GPR_C_VAL 0x00000000
+-#define CFG_PUEN_C_VAL 0xF913FFFF
++#define CFG_PUEN_C_VAL 0xFFFFFFFF
+
+ #define CFG_DDIR_D_VAL 0x00000000
+ #define CFG_OCR1_D_VAL 0x00000000
+@@ -786,13 +796,43 @@
+ #define CFG_ICFB1_D_VAL 0xFFFFFFFF
+ #define CFG_ICFB2_D_VAL 0xFFFFFFFF
+ #define CFG_DR_D_VAL 0x00000000
+-#define CFG_GIUS_D_VAL 0xFFFFFFFF
++#define CFG_GIUS_D_VAL 0xFFFE0000
+ #define CFG_ICR1_D_VAL 0x00000000
+ #define CFG_ICR2_D_VAL 0x00000000
+ #define CFG_IMR_D_VAL 0x00000000
+ #define CFG_GPR_D_VAL 0x00000000
+ #define CFG_PUEN_D_VAL 0xFFFFFFFF
+
++#define CFG_DDIR_E_VAL 0x00000000
++#define CFG_OCR1_E_VAL 0x00000000
++#define CFG_OCR2_E_VAL 0x00000000
++#define CFG_ICFA1_E_VAL 0xFFFFFFFF
++#define CFG_ICFA2_E_VAL 0xFFFFFFFF
++#define CFG_ICFB1_E_VAL 0xFFFFFFFF
++#define CFG_ICFB2_E_VAL 0xFFFFFFFF
++#define CFG_DR_E_VAL 0x00000000
++#define CFG_GIUS_E_VAL 0xFFFC0F27
++#define CFG_ICR1_E_VAL 0x00000000
++#define CFG_ICR2_E_VAL 0x00000000
++#define CFG_IMR_E_VAL 0x00000000
++#define CFG_GPR_E_VAL 0x00000000
++#define CFG_PUEN_E_VAL 0xFFFFFFFF
++
++#define CFG_DDIR_F_VAL 0x00000000
++#define CFG_OCR1_F_VAL 0x00000000
++#define CFG_OCR2_F_VAL 0x00000000
++#define CFG_ICFA1_F_VAL 0xFFFFFFFF
++#define CFG_ICFA2_F_VAL 0xFFFFFFFF
++#define CFG_ICFB1_F_VAL 0xFFFFFFFF
++#define CFG_ICFB2_F_VAL 0xFFFFFFFF
++#define CFG_DR_F_VAL 0x00000000
++#define CFG_GIUS_F_VAL 0xFF000000
++#define CFG_ICR1_F_VAL 0x00000000
++#define CFG_ICR2_F_VAL 0x00000000
++#define CFG_IMR_F_VAL 0x00000000
++#define CFG_GPR_F_VAL 0x00000000
++#define CFG_PUEN_F_VAL 0xFFFFFFFF
++
+ #define CFG_GPCR_VAL 0x000003AB
+
+ /* FMCR Bit 1 becomes 0 to make CS3 if we have only one sdram bank*/
+--- u-boot-1.3.2/lib_arm/board.c 2008-06-25 04:12:35.000000000 +0200
++++ u-boot-new/lib_arm/board.c 2008-06-24 12:21:12.000000000 +0200
+@@ -342,7 +342,7 @@ void start_armboot (void)
+
+ #if defined(CONFIG_CMD_NAND)
+ puts ("NAND: ");
+- nand_init(); /* go init the NAND */
++ //nand_init(); /* go init the NAND */
+ #endif
+
+ #if defined(CONFIG_CMD_ONENAND)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|