diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/arm926ejs/davinci/nand.c | 58 | ||||
-rw-r--r-- | cpu/mpc83xx/nand_init.c | 112 | ||||
-rw-r--r-- | cpu/mpc83xx/start.S | 152 | ||||
-rw-r--r-- | cpu/ppc4xx/ndfc.c | 112 |
4 files changed, 241 insertions, 193 deletions
diff --git a/cpu/arm926ejs/davinci/nand.c b/cpu/arm926ejs/davinci/nand.c index 36468e6..8fd784e 100644 --- a/cpu/arm926ejs/davinci/nand.c +++ b/cpu/arm926ejs/davinci/nand.c @@ -42,6 +42,7 @@ */ #include <common.h> +#include <asm/io.h> #ifdef CFG_USE_NAND #if !defined(CFG_NAND_LEGACY) @@ -52,23 +53,23 @@ extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; -static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd) +static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *this = mtd->priv; u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W; IO_ADDR_W &= ~(MASK_ALE|MASK_CLE); - switch (cmd) { - case NAND_CTL_SETCLE: + if (ctrl & NAND_CTRL_CHANGE) { + if ( ctrl & NAND_CLE ) IO_ADDR_W |= MASK_CLE; - break; - case NAND_CTL_SETALE: + if ( ctrl & NAND_ALE ) IO_ADDR_W |= MASK_ALE; - break; + this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; } - this->IO_ADDR_W = (void *)IO_ADDR_W; + if (cmd != NAND_CMD_NONE) + writeb(cmd, this->IO_ADDR_W); } /* Set WP on deselect, write enable on select */ @@ -88,18 +89,27 @@ static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) #ifdef CFG_NAND_HW_ECC #ifdef CFG_NAND_LARGEPAGE -static struct nand_oobinfo davinci_nand_oobinfo = { +static struct nand_ecclayout davinci_nand_ecclayout = { .useecc = MTD_NANDECC_AUTOPLACE, .eccbytes = 12, .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, - .oobfree = { {2, 6}, {12, 12}, {28, 12}, {44, 12}, {60, 4} } + .oobfree = { + {.offset = 2, .length = 6}, + {.offset = 12, .length = 12}, + {.offset = 28, .length = 12}, + {.offset = 44, .length = 12}, + {.offset = 60, .length = 4} + } }; #elif defined(CFG_NAND_SMALLPAGE) -static struct nand_oobinfo davinci_nand_oobinfo = { +static struct nand_ecclayout davinci_nand_ecclayout = { .useecc = MTD_NANDECC_AUTOPLACE, .eccbytes = 3, .eccpos = {0, 1, 2}, - .oobfree = { {6, 2}, {8, 8} } + .oobfree = { + {.offset = 6, .length = 2}, + {.offset = 8, .length = 8} + } }; #else #error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!" @@ -145,7 +155,7 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u int region, n; struct nand_chip *this = mtd->priv; - n = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1; + n = (this->ecc.size/512); region = 1; while (n--) { @@ -281,7 +291,7 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char * int block_count = 0, i, rc; this = mtd->priv; - block_count = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1; + block_count = (this->ecc.size/512); for (i = 0; i < block_count; i++) { if (memcmp(read_ecc, calc_ecc, 3) != 0) { rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat); @@ -306,7 +316,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd) return(emif_addr->NANDFSR & 0x1); } -static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state) +static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { while(!nand_davinci_dev_ready(mtd)) {;} *NAND_CE0CLE = NAND_STATUS; @@ -362,22 +372,26 @@ int board_nand_init(struct nand_chip *nand) #endif #ifdef CFG_NAND_HW_ECC #ifdef CFG_NAND_LARGEPAGE - nand->eccmode = NAND_ECC_HW12_2048; + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.size = 2048; + nand->ecc.bytes = 12; #elif defined(CFG_NAND_SMALLPAGE) - nand->eccmode = NAND_ECC_HW3_512; + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.size = 512; + nand->ecc.bytes = 3; #else #error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!" #endif - nand->autooob = &davinci_nand_oobinfo; - nand->calculate_ecc = nand_davinci_calculate_ecc; - nand->correct_data = nand_davinci_correct_data; - nand->enable_hwecc = nand_davinci_enable_hwecc; + nand->ecc.layout = &davinci_nand_ecclayout; + nand->ecc.calculate = nand_davinci_calculate_ecc; + nand->ecc.correct = nand_davinci_correct_data; + nand->ecc.hwctl = nand_davinci_enable_hwecc; #else - nand->eccmode = NAND_ECC_SOFT; + nand->ecc.mode = NAND_ECC_SOFT; #endif /* Set address of hardware control function */ - nand->hwcontrol = nand_davinci_hwcontrol; + nand->cmd_ctrl = nand_davinci_hwcontrol; nand->dev_ready = nand_davinci_dev_ready; nand->waitfunc = nand_davinci_waitfunc; diff --git a/cpu/mpc83xx/nand_init.c b/cpu/mpc83xx/nand_init.c new file mode 100644 index 0000000..e92f230 --- /dev/null +++ b/cpu/mpc83xx/nand_init.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2004-2008 Freescale Semiconductor, Inc. + * + * 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> +#include <mpc83xx.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Breathe some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers, + * initialize the UPM's + */ +void cpu_init_f (volatile immap_t * im) +{ + int i; + + /* Pointer is writable since we allocated a register for it */ + gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET); + + /* Clear initial global data */ + for (i = 0; i < sizeof(gd_t); i++) + ((char *)gd)[i] = 0; + + /* system performance tweaking */ + +#ifdef CFG_ACR_PIPE_DEP + /* Arbiter pipeline depth */ + im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) | + (CFG_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT); +#endif + +#ifdef CFG_ACR_RPTCNT + /* Arbiter repeat count */ + im->arbiter.acr = (im->arbiter.acr & ~(ACR_RPTCNT)) | + (CFG_ACR_RPTCNT << ACR_RPTCNT_SHIFT); +#endif + +#ifdef CFG_SPCR_OPT + /* Optimize transactions between CSB and other devices */ + im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_OPT) | + (CFG_SPCR_OPT << SPCR_OPT_SHIFT); +#endif + + /* Enable Time Base & Decrimenter (so we will have udelay()) */ + im->sysconf.spcr |= SPCR_TBEN; + + /* DDR control driver register */ +#ifdef CFG_DDRCDR + im->sysconf.ddrcdr = CFG_DDRCDR; +#endif + /* Output buffer impedance register */ +#ifdef CFG_OBIR + im->sysconf.obir = CFG_OBIR; +#endif + + /* + * Memory Controller: + */ + + /* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary + * addresses - these have to be modified later when FLASH size + * has been determined + */ + +#if defined(CFG_NAND_BR_PRELIM) \ + && defined(CFG_NAND_OR_PRELIM) \ + && defined(CFG_NAND_LBLAWBAR_PRELIM) \ + && defined(CFG_NAND_LBLAWAR_PRELIM) + im->lbus.bank[0].br = CFG_NAND_BR_PRELIM; + im->lbus.bank[0].or = CFG_NAND_OR_PRELIM; + im->sysconf.lblaw[0].bar = CFG_NAND_LBLAWBAR_PRELIM; + im->sysconf.lblaw[0].ar = CFG_NAND_LBLAWAR_PRELIM; +#else +#error CFG_NAND_BR_PRELIM, CFG_NAND_OR_PRELIM, CFG_NAND_LBLAWBAR_PRELIM & CFG_NAND_LBLAWAR_PRELIM must be defined +#endif +} + +/* + * Get timebase clock frequency (like cpu_clk in Hz) + */ +unsigned long get_tbclk(void) +{ + return (gd->bus_clk + 3L) / 4L; +} + +void puts(const char *str) +{ + while (*str) + putc(*str++); +} diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index c182174..16ed494 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -2,7 +2,7 @@ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de> - * Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved. + * Copyright Freescale Semiconductor, Inc. 2004, 2006, 2008. * * See file CREDITS for list of people who contributed to this * project. @@ -57,6 +57,10 @@ #define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI) #endif +#if !defined(CONFIG_NAND_SPL) && !defined(CFG_RAMBOOT) +#define CFG_FLASHBOOT +#endif + /* * Set up GOT: Global Offset Table * @@ -64,16 +68,16 @@ */ START_GOT GOT_ENTRY(_GOT2_TABLE_) - GOT_ENTRY(_FIXUP_TABLE_) + GOT_ENTRY(__bss_start) + GOT_ENTRY(_end) +#ifndef CONFIG_NAND_SPL + GOT_ENTRY(_FIXUP_TABLE_) GOT_ENTRY(_start) GOT_ENTRY(_start_of_vectors) GOT_ENTRY(_end_of_vectors) GOT_ENTRY(transfer_to_handler) - - GOT_ENTRY(__init_end) - GOT_ENTRY(_end) - GOT_ENTRY(__bss_start) +#endif END_GOT /* @@ -165,7 +169,7 @@ boot_warm: /* time t 5 */ bl init_e300_core -#ifndef CFG_RAMBOOT +#ifdef CFG_FLASHBOOT /* Inflate flash location so it appears everywhere, calculate */ /* the absolute address in final location of the FLASH, jump */ @@ -181,7 +185,7 @@ in_flash: #if 1 /* Remapping flash with LAW0. */ bl remap_flash_by_law0 #endif -#endif /* CFG_RAMBOOT */ +#endif /* CFG_FLASHBOOT */ /* setup the bats */ bl setup_bats @@ -239,6 +243,7 @@ in_flash: /* run 1st part of board init code (in Flash)*/ bl board_init_f +#ifndef CONFIG_NAND_SPL /* * Vector Table */ @@ -428,6 +433,7 @@ int_return: lwz r1,GPR1(r1) SYNC rfi +#endif /* !CONFIG_NAND_SPL */ /* * This code initialises the E300 processor core @@ -496,88 +502,10 @@ init_e300_core: /* time t 10 */ SYNC mtspr HID2, r3 - /* clear all BAT's */ - /*----------------------------------*/ - - xor r0, r0, r0 - mtspr DBAT0U, r0 - mtspr DBAT0L, r0 - mtspr DBAT1U, r0 - mtspr DBAT1L, r0 - mtspr DBAT2U, r0 - mtspr DBAT2L, r0 - mtspr DBAT3U, r0 - mtspr DBAT3L, r0 - mtspr IBAT0U, r0 - mtspr IBAT0L, r0 - mtspr IBAT1U, r0 - mtspr IBAT1L, r0 - mtspr IBAT2U, r0 - mtspr IBAT2L, r0 - mtspr IBAT3U, r0 - mtspr IBAT3L, r0 - SYNC - - /* invalidate all tlb's - * - * From the 603e User Manual: "The 603e provides the ability to - * invalidate a TLB entry. The TLB Invalidate Entry (tlbie) - * instruction invalidates the TLB entry indexed by the EA, and - * operates on both the instruction and data TLBs simultaneously - * invalidating four TLB entries (both sets in each TLB). The - * index corresponds to bits 15-19 of the EA. To invalidate all - * entries within both TLBs, 32 tlbie instructions should be - * issued, incrementing this field by one each time." - * - * "Note that the tlbia instruction is not implemented on the - * 603e." - * - * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 - * incrementing by 0x1000 each time. The code below is sort of - * based on code in "flush_tlbs" from arch/ppc/kernel/head.S - * - */ - - li r3, 32 - mtctr r3 - li r3, 0 -1: tlbie r3 - addi r3, r3, 0x1000 - bdnz 1b - SYNC - /* Done! */ /*------------------------------*/ blr - .globl invalidate_bats -invalidate_bats: - /* invalidate BATs */ - mtspr IBAT0U, r0 - mtspr IBAT1U, r0 - mtspr IBAT2U, r0 - mtspr IBAT3U, r0 -#ifdef CONFIG_HIGH_BATS - mtspr IBAT4U, r0 - mtspr IBAT5U, r0 - mtspr IBAT6U, r0 - mtspr IBAT7U, r0 -#endif - isync - mtspr DBAT0U, r0 - mtspr DBAT1U, r0 - mtspr DBAT2U, r0 - mtspr DBAT3U, r0 -#ifdef CONFIG_HIGH_BATS - mtspr DBAT4U, r0 - mtspr DBAT5U, r0 - mtspr DBAT6U, r0 - mtspr DBAT7U, r0 -#endif - isync - sync - blr - /* setup_bats - set them up to some initial state */ .globl setup_bats setup_bats: @@ -590,7 +518,6 @@ setup_bats: ori r3, r3, CFG_IBAT0U@l mtspr IBAT0L, r4 mtspr IBAT0U, r3 - isync /* DBAT 0 */ addis r4, r0, CFG_DBAT0L@h @@ -599,7 +526,6 @@ setup_bats: ori r3, r3, CFG_DBAT0U@l mtspr DBAT0L, r4 mtspr DBAT0U, r3 - isync /* IBAT 1 */ addis r4, r0, CFG_IBAT1L@h @@ -608,7 +534,6 @@ setup_bats: ori r3, r3, CFG_IBAT1U@l mtspr IBAT1L, r4 mtspr IBAT1U, r3 - isync /* DBAT 1 */ addis r4, r0, CFG_DBAT1L@h @@ -617,7 +542,6 @@ setup_bats: ori r3, r3, CFG_DBAT1U@l mtspr DBAT1L, r4 mtspr DBAT1U, r3 - isync /* IBAT 2 */ addis r4, r0, CFG_IBAT2L@h @@ -626,7 +550,6 @@ setup_bats: ori r3, r3, CFG_IBAT2U@l mtspr IBAT2L, r4 mtspr IBAT2U, r3 - isync /* DBAT 2 */ addis r4, r0, CFG_DBAT2L@h @@ -635,7 +558,6 @@ setup_bats: ori r3, r3, CFG_DBAT2U@l mtspr DBAT2L, r4 mtspr DBAT2U, r3 - isync /* IBAT 3 */ addis r4, r0, CFG_IBAT3L@h @@ -644,7 +566,6 @@ setup_bats: ori r3, r3, CFG_IBAT3U@l mtspr IBAT3L, r4 mtspr IBAT3U, r3 - isync /* DBAT 3 */ addis r4, r0, CFG_DBAT3L@h @@ -653,7 +574,6 @@ setup_bats: ori r3, r3, CFG_DBAT3U@l mtspr DBAT3L, r4 mtspr DBAT3U, r3 - isync #ifdef CONFIG_HIGH_BATS /* IBAT 4 */ @@ -663,7 +583,6 @@ setup_bats: ori r3, r3, CFG_IBAT4U@l mtspr IBAT4L, r4 mtspr IBAT4U, r3 - isync /* DBAT 4 */ addis r4, r0, CFG_DBAT4L@h @@ -672,7 +591,6 @@ setup_bats: ori r3, r3, CFG_DBAT4U@l mtspr DBAT4L, r4 mtspr DBAT4U, r3 - isync /* IBAT 5 */ addis r4, r0, CFG_IBAT5L@h @@ -681,7 +599,6 @@ setup_bats: ori r3, r3, CFG_IBAT5U@l mtspr IBAT5L, r4 mtspr IBAT5U, r3 - isync /* DBAT 5 */ addis r4, r0, CFG_DBAT5L@h @@ -690,7 +607,6 @@ setup_bats: ori r3, r3, CFG_DBAT5U@l mtspr DBAT5L, r4 mtspr DBAT5U, r3 - isync /* IBAT 6 */ addis r4, r0, CFG_IBAT6L@h @@ -699,7 +615,6 @@ setup_bats: ori r3, r3, CFG_IBAT6U@l mtspr IBAT6L, r4 mtspr IBAT6U, r3 - isync /* DBAT 6 */ addis r4, r0, CFG_DBAT6L@h @@ -708,7 +623,6 @@ setup_bats: ori r3, r3, CFG_DBAT6U@l mtspr DBAT6L, r4 mtspr DBAT6U, r3 - isync /* IBAT 7 */ addis r4, r0, CFG_IBAT7L@h @@ -717,7 +631,6 @@ setup_bats: ori r3, r3, CFG_IBAT7U@l mtspr IBAT7L, r4 mtspr IBAT7U, r3 - isync /* DBAT 7 */ addis r4, r0, CFG_DBAT7L@h @@ -726,12 +639,28 @@ setup_bats: ori r3, r3, CFG_DBAT7U@l mtspr DBAT7L, r4 mtspr DBAT7U, r3 - isync #endif - /* Invalidate TLBs. - * -> for (val = 0; val < 0x20000; val+=0x1000) - * -> tlbie(val); + isync + + /* invalidate all tlb's + * + * From the 603e User Manual: "The 603e provides the ability to + * invalidate a TLB entry. The TLB Invalidate Entry (tlbie) + * instruction invalidates the TLB entry indexed by the EA, and + * operates on both the instruction and data TLBs simultaneously + * invalidating four TLB entries (both sets in each TLB). The + * index corresponds to bits 15-19 of the EA. To invalidate all + * entries within both TLBs, 32 tlbie instructions should be + * issued, incrementing this field by one each time." + * + * "Note that the tlbia instruction is not implemented on the + * 603e." + * + * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 + * incrementing by 0x1000 each time. The code below is sort of + * based on code in "flush_tlbs" from arch/ppc/kernel/head.S + * */ lis r3, 0 lis r5, 2 @@ -874,7 +803,7 @@ relocate_code: mr r3, r5 /* Destination Address */ lis r4, CFG_MONITOR_BASE@h /* Source Address */ ori r4, r4, CFG_MONITOR_BASE@l - lwz r5, GOT(__init_end) + lwz r5, GOT(__bss_start) sub r5, r5, r4 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */ @@ -987,6 +916,7 @@ in_ram: stw r0,0(r3) bdnz 1b +#ifndef CONFIG_NAND_SPL /* * Now adjust the fixups and the pointers to the fixups * in case we need to move ourselves again. @@ -1004,6 +934,8 @@ in_ram: stw r0,0(r4) bdnz 3b 4: +#endif + clear_bss: /* * Now clear BSS segment @@ -1037,6 +969,7 @@ clear_bss: mr r4, r10 /* Destination Address */ bl board_init_r +#ifndef CONFIG_NAND_SPL /* * Copy exception vector code to low memory * @@ -1119,6 +1052,7 @@ trap_reloc: stw r0, 4(r7) blr +#endif /* !CONFIG_NAND_SPL */ #ifdef CFG_INIT_RAM_LOCK lock_ram_in_cache: @@ -1142,6 +1076,7 @@ lock_ram_in_cache: sync blr +#ifndef CONFIG_NAND_SPL .globl unlock_ram_in_cache unlock_ram_in_cache: /* invalidate the INIT_RAM section */ @@ -1165,8 +1100,10 @@ unlock_ram_in_cache: mtspr HID0, r3 /* no invalidate, unlock */ sync blr -#endif +#endif /* !CONFIG_NAND_SPL */ +#endif /* CFG_INIT_RAM_LOCK */ +#ifdef CFG_FLASHBOOT map_flash_by_law1: /* When booting from ROM (Flash or EPROM), clear the */ /* Address Mask in OR0 so ROM appears everywhere */ @@ -1245,3 +1182,4 @@ remap_flash_by_law0: stw r4, LBLAWBAR1(r3) stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */ blr +#endif /* CFG_FLASHBOOT */ diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c index 5b2ae88..4f083d9 100644 --- a/cpu/ppc4xx/ndfc.c +++ b/cpu/ppc4xx/ndfc.c @@ -44,65 +44,39 @@ #include <asm/io.h> #include <ppc4xx.h> -static u8 hwctl = 0; +/* + * We need to store the info, which chip-select (CS) is used for the + * chip number. For example on Sequoia NAND chip #0 uses + * CS #3. + */ +static int ndfc_cs[NDFC_MAX_BANKS]; -static void ndfc_hwcontrol(struct mtd_info *mtdinfo, int cmd) +static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - switch (cmd) { - case NAND_CTL_SETCLE: - hwctl |= 0x1; - break; - - case NAND_CTL_CLRCLE: - hwctl &= ~0x1; - break; - - case NAND_CTL_SETALE: - hwctl |= 0x2; - break; - - case NAND_CTL_CLRALE: - hwctl &= ~0x2; - break; - } -} + struct nand_chip *this = mtd->priv; + ulong base = (ulong) this->IO_ADDR_W & 0xffffff00; -static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte) -{ - struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + if (cmd == NAND_CMD_NONE) + return; - if (hwctl & 0x1) - out_8((u8 *)(base + NDFC_CMD), byte); - else if (hwctl & 0x2) - out_8((u8 *)(base + NDFC_ALE), byte); + if (ctrl & NAND_CLE) + out_8((u8 *)(base + NDFC_CMD), cmd & 0xFF); else - out_8((u8 *)(base + NDFC_DATA), byte); -} - -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 (in_8((u8 *)(base + NDFC_DATA))); + out_8((u8 *)(base + NDFC_ALE), cmd & 0xFF); } static int ndfc_dev_ready(struct mtd_info *mtdinfo) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; - - while (!(in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY)) - ; + ulong base = (ulong) this->IO_ADDR_W & 0xffffff00; - return 1; + return (in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY); } 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; + ulong base = (ulong) this->IO_ADDR_W & 0xffffff00; u32 ccr; ccr = in_be32((u32 *)(base + NDFC_CCR)); @@ -114,7 +88,7 @@ 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; + ulong base = (ulong) this->IO_ADDR_W & 0xffffff00; u32 ecc; u8 *p = (u8 *)&ecc; @@ -139,7 +113,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtdinfo, static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + ulong base = (ulong) this->IO_ADDR_W & 0xffffff00; uint32_t *p = (uint32_t *) buf; for (;len > 0; len -= 4) @@ -154,7 +128,7 @@ static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len) static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + ulong base = (ulong) this->IO_ADDR_W & 0xffffff00; uint32_t *p = (uint32_t *) buf; for (; len > 0; len -= 4) @@ -164,7 +138,7 @@ static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + ulong base = (ulong) this->IO_ADDR_W & 0xffffff00; uint32_t *p = (uint32_t *) buf; for (; len > 0; len -= 4) @@ -181,29 +155,43 @@ void board_nand_select_device(struct nand_chip *nand, int chip) * Don't use "chip" to address the NAND device, * generate the cs from the address where it is encoded. */ - int cs = (ulong)nand->IO_ADDR_W & 0x00000003; - ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc; + ulong base = (ulong)nand->IO_ADDR_W & 0xffffff00; + int cs = ndfc_cs[chip]; /* Set NandFlash Core Configuration Register */ /* 1 col x 2 rows */ out_be32((u32 *)(base + NDFC_CCR), 0x00000000 | (cs << 24)); + out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222); } int board_nand_init(struct nand_chip *nand) { int cs = (ulong)nand->IO_ADDR_W & 0x00000003; - ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc; + ulong base = (ulong)nand->IO_ADDR_W & 0xffffff00; + static int chip = 0; - 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; + /* + * Save chip-select for this chip # + */ + ndfc_cs[chip] = cs; - nand->eccmode = NAND_ECC_HW3_256; - nand->enable_hwecc = ndfc_enable_hwecc; - nand->calculate_ecc = ndfc_calculate_ecc; - nand->correct_data = nand_correct_data; + /* + * Select required NAND chip in NDFC + */ + board_nand_select_device(nand, chip); + + nand->IO_ADDR_R = (void __iomem *)(base + NDFC_DATA); + nand->IO_ADDR_W = (void __iomem *)(base + NDFC_DATA); + nand->cmd_ctrl = ndfc_hwcontrol; + nand->chip_delay = 50; + nand->read_buf = ndfc_read_buf; + nand->dev_ready = ndfc_dev_ready; + nand->ecc.correct = nand_correct_data; + nand->ecc.hwctl = ndfc_enable_hwecc; + nand->ecc.calculate = ndfc_calculate_ecc; + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.size = 256; + nand->ecc.bytes = 3; #ifndef CONFIG_NAND_SPL nand->write_buf = ndfc_write_buf; @@ -218,11 +206,7 @@ int board_nand_init(struct nand_chip *nand) mtebc(pb0ap, CFG_EBC_PB0AP); #endif - /* - * Select required NAND chip in NDFC - */ - board_nand_select_device(nand, cs); - out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222); + chip++; return 0; } |