]> git.sur5r.net Git - openocd/commitdiff
move nand drivers to src/flash/nand/
authorZachary T Welch <zw@superlucidity.net>
Wed, 2 Dec 2009 06:37:11 +0000 (22:37 -0800)
committerZachary T Welch <zw@superlucidity.net>
Thu, 3 Dec 2009 07:27:09 +0000 (23:27 -0800)
Moves NAND drivers to src/flash/nand/.
Adds src/flash/nand/Makefile.am.
Builds libocdflashnand.la.

31 files changed:
configure.in
src/flash/Makefile.am
src/flash/davinci_nand.c [deleted file]
src/flash/lpc3180_nand_controller.c [deleted file]
src/flash/lpc3180_nand_controller.h [deleted file]
src/flash/mx3_nand.c [deleted file]
src/flash/mx3_nand.h [deleted file]
src/flash/nand/Makefile.am [new file with mode: 0644]
src/flash/nand/davinci.c [new file with mode: 0644]
src/flash/nand/lpc3180.c [new file with mode: 0644]
src/flash/nand/lpc3180.h [new file with mode: 0644]
src/flash/nand/mx3.c [new file with mode: 0644]
src/flash/nand/mx3.h [new file with mode: 0644]
src/flash/nand/nonce.c [new file with mode: 0644]
src/flash/nand/orion.c [new file with mode: 0644]
src/flash/nand/s3c2410.c [new file with mode: 0644]
src/flash/nand/s3c2412.c [new file with mode: 0644]
src/flash/nand/s3c2440.c [new file with mode: 0644]
src/flash/nand/s3c2443.c [new file with mode: 0644]
src/flash/nand/s3c24xx.c [new file with mode: 0644]
src/flash/nand/s3c24xx.h [new file with mode: 0644]
src/flash/nand/s3c24xx_regs.h [new file with mode: 0644]
src/flash/nonce_nand.c [deleted file]
src/flash/orion_nand.c [deleted file]
src/flash/s3c2410_nand.c [deleted file]
src/flash/s3c2412_nand.c [deleted file]
src/flash/s3c2440_nand.c [deleted file]
src/flash/s3c2443_nand.c [deleted file]
src/flash/s3c24xx_nand.c [deleted file]
src/flash/s3c24xx_nand.h [deleted file]
src/flash/s3c24xx_regs_nand.h [deleted file]

index dbddcb2bd6cdc074f274e709d4efa923ed6e9d1a..3680cac52e4daf173e7d1a0211d0deb8c44c6627 100644 (file)
@@ -1122,6 +1122,7 @@ AC_OUTPUT(dnl
     src/target/Makefile dnl
     src/server/Makefile dnl
     src/flash/Makefile dnl
+    src/flash/nand/Makefile dnl
     src/pld/Makefile dnl
     doc/Makefile dnl
   )
index 94cc86e5c7efab0913c5f9094565416fc90c14ed..353fcf1650a0eb88efddad55e39db5fc9161ae8c 100644 (file)
@@ -1,3 +1,6 @@
+SUBDIRS = \
+       nand
+
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/helper \
        -I$(top_srcdir)/src/jtag \
@@ -10,6 +13,9 @@ libflash_la_SOURCES = \
        $(NAND_SRCS) \
        mflash.c
 
+libflash_la_LIBADD = \
+       $(top_builddir)/src/flash/nand/libocdflashnand.la
+
 FLASH_SRCS = \
        common.c \
        cfi.c \
@@ -40,22 +46,8 @@ NAND_SRCS = \
        arm_nandio.c \
        nand_ecc.c \
        nand_ecc_kw.c \
-       $(NAND_DEVICES_SRCS) \
        nand.c
 
-NAND_DEVICES_SRCS = \
-       nonce_nand.c \
-       davinci_nand.c \
-       lpc3180_nand_controller.c \
-       mx3_nand.c \
-       orion_nand.c \
-       s3c24xx_nand.c \
-       s3c2410_nand.c \
-       s3c2412_nand.c \
-       s3c2440_nand.c \
-       s3c2443_nand.c
-
-
 noinst_HEADERS = \
        arm_nandio.h \
        at91sam7.h \
@@ -66,9 +58,7 @@ noinst_HEADERS = \
        flash.h \
        lpc2000.h \
        lpc288x.h \
-       lpc3180_nand_controller.h \
        mflash.h \
-       mx3_nand.h \
        non_cfi.h \
        nand.h \
        ocl.h \
@@ -78,9 +68,7 @@ noinst_HEADERS = \
        str7x.h \
        str9x.h \
        str9xpec.h \
-       tms470.h \
-       s3c24xx_nand.h \
-       s3c24xx_regs_nand.h
+       tms470.h
 
 EXTRA_DIST = startup.tcl
 
diff --git a/src/flash/davinci_nand.c b/src/flash/davinci_nand.c
deleted file mode 100644 (file)
index 72cd378..0000000
+++ /dev/null
@@ -1,756 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by David Brownell                                  *
- *                                                                         *
- *   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.             *
- ***************************************************************************/
-
-/*
- * DaVinci family NAND controller support for OpenOCD.
- *
- * This driver uses hardware ECC (1-bit or 4-bit) unless
- * the chip is accessed in "raw" mode.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm_nandio.h"
-
-
-enum ecc {
-       HWECC1,         /* all controllers support 1-bit ECC */
-       HWECC4,         /* newer chips also have 4-bit ECC hardware */
-       HWECC4_INFIX,   /* avoid this layout, except maybe for boot code */
-};
-
-struct davinci_nand {
-       struct target   *target;
-
-       uint8_t         chipsel;        /* chipselect 0..3 == CS2..CS5 */
-       uint8_t         eccmode;
-
-       /* Async EMIF controller base */
-       uint32_t                aemif;
-
-       /* NAND chip addresses */
-       uint32_t                data;           /* without CLE or ALE */
-       uint32_t                cmd;            /* with CLE */
-       uint32_t                addr;           /* with ALE */
-
-       /* write acceleration */
-       struct arm_nand_data    io;
-
-       /* page i/o for the relevant flavor of hardware ECC */
-       int (*read_page)(struct nand_device *nand, uint32_t page,
-                       uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
-       int (*write_page)(struct nand_device *nand, uint32_t page,
-                       uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
-};
-
-#define NANDFCR                0x60            /* flash control register */
-#define NANDFSR                0x64            /* flash status register */
-#define NANDFECC       0x70            /* 1-bit ECC data, CS0, 1st of 4 */
-#define NAND4BITECCLOAD        0xbc            /* 4-bit ECC, load saved values */
-#define NAND4BITECC    0xc0            /* 4-bit ECC data, 1st of 4 */
-#define NANDERRADDR    0xd0            /* 4-bit ECC err addr, 1st of 2 */
-#define NANDERRVAL     0xd8            /* 4-bit ECC err value, 1st of 2 */
-
-static int halted(struct target *target, const char *label)
-{
-       if (target->state == TARGET_HALTED)
-               return true;
-
-       LOG_ERROR("Target must be halted to use NAND controller (%s)", label);
-       return false;
-}
-
-static int davinci_init(struct nand_device *nand)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-       uint32_t nandfcr;
-
-       if (!halted(target, "init"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       /* We require something else to have configured AEMIF to talk
-        * to NAND chip in this range (including timings and width).
-        */
-       target_read_u32(target, info->aemif + NANDFCR, &nandfcr);
-       if (!(nandfcr & (1 << info->chipsel))) {
-               LOG_ERROR("chip address %08" PRIx32 " not NAND-enabled?", info->data);
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       /* REVISIT verify:  AxCR must be in 8-bit mode, since that's all we
-        * tested.  16 bit support should work too; but not with 4-bit ECC.
-        */
-
-       return ERROR_OK;
-}
-
-static int davinci_reset(struct nand_device *nand)
-{
-       return ERROR_OK;
-}
-
-static int davinci_nand_ready(struct nand_device *nand, int timeout)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-       uint32_t nandfsr;
-
-       /* NOTE: return code is zero/error, else success; not ERROR_* */
-
-       if (!halted(target, "ready"))
-               return 0;
-
-       do {
-               target_read_u32(target, info->aemif + NANDFSR, &nandfsr);
-
-               if (nandfsr & 0x01)
-                       return 1;
-
-               alive_sleep(1);
-       } while (timeout-- > 0);
-
-       return 0;
-}
-
-static int davinci_command(struct nand_device *nand, uint8_t command)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-
-       if (!halted(target, "command"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       target_write_u8(target, info->cmd, command);
-       return ERROR_OK;
-}
-
-static int davinci_address(struct nand_device *nand, uint8_t address)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-
-       if (!halted(target, "address"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       target_write_u8(target, info->addr, address);
-       return ERROR_OK;
-}
-
-static int davinci_write_data(struct nand_device *nand, uint16_t data)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-
-       if (!halted(target, "write_data"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       target_write_u8(target, info->data, data);
-       return ERROR_OK;
-}
-
-static int davinci_read_data(struct nand_device *nand, void *data)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-
-       if (!halted(target, "read_data"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       target_read_u8(target, info->data, data);
-       return ERROR_OK;
-}
-
-/* REVISIT a bit of native code should let block reads be MUCH faster */
-
-static int davinci_read_block_data(struct nand_device *nand,
-               uint8_t *data, int data_size)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-       uint32_t nfdata = info->data;
-       uint32_t tmp;
-
-       if (!halted(target, "read_block"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       while (data_size >= 4) {
-               target_read_u32(target, nfdata, &tmp);
-
-               data[0] = tmp;
-               data[1] = tmp >> 8;
-               data[2] = tmp >> 16;
-               data[3] = tmp >> 24;
-
-               data_size -= 4;
-               data += 4;
-       }
-
-       while (data_size > 0) {
-               target_read_u8(target, nfdata, data);
-
-               data_size -= 1;
-               data += 1;
-       }
-
-       return ERROR_OK;
-}
-
-static int davinci_write_block_data(struct nand_device *nand,
-               uint8_t *data, int data_size)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-       uint32_t nfdata = info->data;
-       uint32_t tmp;
-       int status;
-
-       if (!halted(target, "write_block"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       /* try the fast way first */
-       status = arm_nandwrite(&info->io, data, data_size);
-       if (status != ERROR_NAND_NO_BUFFER)
-               return status;
-
-       /* else do it slowly */
-       while (data_size >= 4) {
-               tmp = le_to_h_u32(data);
-               target_write_u32(target, nfdata, tmp);
-
-               data_size -= 4;
-               data += 4;
-       }
-
-       while (data_size > 0) {
-               target_write_u8(target, nfdata, *data);
-
-               data_size -= 1;
-               data += 1;
-       }
-
-       return ERROR_OK;
-}
-
-static int davinci_write_page(struct nand_device *nand, uint32_t page,
-               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       uint8_t *ooballoc = NULL;
-       int status;
-
-       if (!nand->device)
-               return ERROR_NAND_DEVICE_NOT_PROBED;
-       if (!halted(info->target, "write_page"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       /* Always write both data and OOB ... we are not "raw" I/O! */
-       if (!data) {
-               LOG_ERROR("Missing NAND data; try 'nand raw_access enable'\n");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       /* If we're not given OOB, write 0xff where we don't write ECC codes. */
-       switch (nand->page_size) {
-       case 512:
-               oob_size = 16;
-               break;
-       case 2048:
-               oob_size = 64;
-               break;
-       case 4096:
-               oob_size = 128;
-               break;
-       default:
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-       if (!oob) {
-               ooballoc = malloc(oob_size);
-               if (!ooballoc)
-                       return ERROR_NAND_OPERATION_FAILED;
-               oob = ooballoc;
-               memset(oob, 0x0ff, oob_size);
-       }
-
-       /* REVISIT avoid wasting SRAM:  unless nand->use_raw is set,
-        * use 512 byte chunks.  Read side support will often want
-        * to include oob_size ...
-        */
-       info->io.chunk_size = nand->page_size;
-
-       status = info->write_page(nand, page, data, data_size, oob, oob_size);
-       free(ooballoc);
-       return status;
-}
-
-static int davinci_read_page(struct nand_device *nand, uint32_t page,
-               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
-       struct davinci_nand *info = nand->controller_priv;
-
-       if (!nand->device)
-               return ERROR_NAND_DEVICE_NOT_PROBED;
-       if (!halted(info->target, "read_page"))
-               return ERROR_NAND_OPERATION_FAILED;
-
-       return info->read_page(nand, page, data, data_size, oob, oob_size);
-}
-
-static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_t page)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-       int page3 = nand->address_cycles - (nand->page_size == 512);
-
-       /* write command ({page,otp}x{read,program} */
-       target_write_u8(target, info->cmd, cmd);
-
-       /* column address (beginning-of-page) */
-       target_write_u8(target, info->addr, 0);
-       if (nand->page_size > 512)
-               target_write_u8(target, info->addr, 0);
-
-       /* page address */
-       target_write_u8(target, info->addr, page);
-       target_write_u8(target, info->addr, page >> 8);
-       if (page3)
-               target_write_u8(target, info->addr, page >> 16);
-       if (page3 == 2)
-               target_write_u8(target, info->addr, page >> 24);
-}
-
-static int davinci_writepage_tail(struct nand_device *nand,
-               uint8_t *oob, uint32_t oob_size)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-       uint8_t status;
-
-       if (oob_size)
-               davinci_write_block_data(nand, oob, oob_size);
-
-       /* non-cachemode page program */
-       target_write_u8(target, info->cmd, NAND_CMD_PAGEPROG);
-
-       if (!davinci_nand_ready(nand, 100))
-               return ERROR_NAND_OPERATION_TIMEOUT;
-
-       if (nand_read_status(nand, &status) != ERROR_OK) {
-               LOG_ERROR("couldn't read status");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (status & NAND_STATUS_FAIL) {
-               LOG_ERROR("write operation failed, status: 0x%02x", status);
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       return ERROR_OK;
-}
-
-/*
- * All DaVinci family chips support 1-bit ECC on a per-chipselect basis.
- */
-static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
-               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
-       unsigned oob_offset;
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-       const uint32_t fcr_addr = info->aemif + NANDFCR;
-       const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel);
-       uint32_t fcr, ecc1;
-
-       /* Write contiguous ECC bytes starting at specified offset.
-        * NOTE: Linux reserves twice as many bytes as we need; and
-        * for 16-bit OOB, those extra bytes are discontiguous.
-        */
-       switch (nand->page_size) {
-       case 512:
-               oob_offset = 0;
-               break;
-       case 2048:
-               oob_offset = 40;
-               break;
-       default:
-               oob_offset = 80;
-               break;
-       }
-
-       davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
-
-       /* scrub any old ECC state */
-       target_read_u32(target, ecc1_addr, &ecc1);
-
-       target_read_u32(target, fcr_addr, &fcr);
-       fcr |= 1 << (8 + info->chipsel);
-
-       do {
-               /* set "start csX 1bit ecc" bit */
-               target_write_u32(target, fcr_addr, fcr);
-
-               /* write 512 bytes */
-               davinci_write_block_data(nand, data, 512);
-               data += 512;
-               data_size -= 512;
-
-               /* read the ecc, pack to 3 bytes, and invert so the ecc
-                * in an erased block is correct
-                */
-               target_read_u32(target, ecc1_addr, &ecc1);
-               ecc1 = (ecc1 & 0x0fff) | ((ecc1 & 0x0fff0000) >> 4);
-               ecc1 = ~ecc1;
-
-               /* save correct ECC code into oob data */
-               oob[oob_offset++] = (uint8_t)(ecc1);
-               oob[oob_offset++] = (uint8_t)(ecc1 >> 8);
-               oob[oob_offset++] = (uint8_t)(ecc1 >> 16);
-
-       } while (data_size);
-
-       /* write OOB into spare area */
-       return davinci_writepage_tail(nand, oob, oob_size);
-}
-
-/*
- * Preferred "new style" ECC layout for use with 4-bit ECC.  This somewhat
- * slows down large page reads done with error correction (since the OOB
- * is read first, so its ECC data can be used incrementally), but the
- * manufacturer bad block markers are safe.  Contrast:  old "infix" style.
- */
-static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
-               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
-       static const uint8_t ecc512[] = {
-               0, 1, 2, 3, 4, /* 5== mfr badblock */
-               6, 7, /* 8..12 for BBT or JFFS2 */ 13, 14, 15,
-       };
-       static const uint8_t ecc2048[] = {
-               24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
-               34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
-               44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-               54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-       };
-       static const uint8_t ecc4096[] = {
-                48,  49,  50,  51,  52,  53,  54,  55,  56,  57,
-                58,  59,  60,  61,  62,  63,  64,  65,  66,  67,
-                68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
-                78,  79,  80,  81,  82,  83,  84,  85,  86,  87,
-                88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
-                98,  99, 100, 101, 102, 103, 104, 105, 106, 107,
-               108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
-               118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-       };
-
-       struct davinci_nand *info = nand->controller_priv;
-       const uint8_t *l;
-       struct target *target = info->target;
-       const uint32_t fcr_addr = info->aemif + NANDFCR;
-       const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
-       uint32_t fcr, ecc4;
-
-       /* Use the same ECC layout Linux uses.  For small page chips
-        * it's a bit cramped.
-        *
-        * NOTE:  at this writing, 4KB pages have issues in Linux
-        * because they need more than 64 bytes of ECC data, which
-        * the standard ECC logic can't handle.
-        */
-       switch (nand->page_size) {
-       case 512:
-               l = ecc512;
-               break;
-       case 2048:
-               l = ecc2048;
-               break;
-       default:
-               l = ecc4096;
-               break;
-       }
-
-       davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
-
-       /* scrub any old ECC state */
-       target_read_u32(target, info->aemif + NANDERRVAL, &ecc4);
-
-       target_read_u32(target, fcr_addr, &fcr);
-       fcr &= ~(0x03 << 4);
-       fcr |= (1 << 12) | (info->chipsel << 4);
-
-       do {
-               uint32_t raw_ecc[4], *p;
-               int i;
-
-               /* start 4bit ecc on csX */
-               target_write_u32(target, fcr_addr, fcr);
-
-               /* write 512 bytes */
-               davinci_write_block_data(nand, data, 512);
-               data += 512;
-               data_size -= 512;
-
-               /* read the ecc, then save it into 10 bytes in the oob */
-               for (i = 0; i < 4; i++) {
-                       target_read_u32(target, ecc4_addr + 4 * i, &raw_ecc[i]);
-                       raw_ecc[i] &= 0x03ff03ff;
-               }
-               for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
-                       oob[*l++] =   p[0]        & 0xff;
-                       oob[*l++] = ((p[0] >>  8) & 0x03) | ((p[0] >> 14) & 0xfc);
-                       oob[*l++] = ((p[0] >> 22) & 0x0f) | ((p[1] <<  4) & 0xf0);
-                       oob[*l++] = ((p[1] >>  4) & 0x3f) | ((p[1] >> 10) & 0xc0);
-                       oob[*l++] =  (p[1] >> 18) & 0xff;
-               }
-
-       } while (data_size);
-
-       /* write OOB into spare area */
-       return davinci_writepage_tail(nand, oob, oob_size);
-}
-
-/*
- * "Infix" OOB ... like Linux ECC_HW_SYNDROME.  Avoided because it trashes
- * manufacturer bad block markers, except on small page chips.  Once you
- * write to a page using this scheme, you need specialized code to update
- * it (code which ignores now-invalid bad block markers).
- *
- * This is needed *only* to support older firmware.  Older ROM Boot Loaders
- * need it to read their second stage loader (UBL) into SRAM, but from then
- * on the whole system can use the cleaner non-infix layouts.  Systems with
- * older second stage loaders (ABL/U-Boot, etc) or other system software
- * (MVL 4.x/5.x kernels, filesystems, etc) may need it more generally.
- */
-static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
-               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
-       struct davinci_nand *info = nand->controller_priv;
-       struct target *target = info->target;
-       const uint32_t fcr_addr = info->aemif + NANDFCR;
-       const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
-       uint32_t fcr, ecc4;
-
-       davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
-
-       /* scrub any old ECC state */
-       target_read_u32(target, info->aemif + NANDERRVAL, &ecc4);
-
-       target_read_u32(target, fcr_addr, &fcr);
-       fcr &= ~(0x03 << 4);
-       fcr |= (1 << 12) | (info->chipsel << 4);
-
-       do {
-               uint32_t raw_ecc[4], *p;
-               uint8_t *l;
-               int i;
-
-               /* start 4bit ecc on csX */
-               target_write_u32(target, fcr_addr, fcr);
-
-               /* write 512 bytes */
-               davinci_write_block_data(nand, data, 512);
-               data += 512;
-               data_size -= 512;
-
-               /* read the ecc */
-               for (i = 0; i < 4; i++) {
-                       target_read_u32(target, ecc4_addr + 4 * i, &raw_ecc[i]);
-                       raw_ecc[i] &= 0x03ff03ff;
-               }
-
-               /* skip 6 bytes of prepad, then pack 10 packed ecc bytes */
-               for (i = 0, l = oob + 6, p = raw_ecc; i < 2; i++, p += 2) {
-                       *l++ =   p[0]        & 0xff;
-                       *l++ = ((p[0] >>  8) & 0x03) | ((p[0] >> 14) & 0xfc);
-                       *l++ = ((p[0] >> 22) & 0x0f) | ((p[1] <<  4) & 0xf0);
-                       *l++ = ((p[1] >>  4) & 0x3f) | ((p[1] >> 10) & 0xc0);
-                       *l++ =  (p[1] >> 18) & 0xff;
-               }
-
-               /* write this "out-of-band" data -- infix */
-               davinci_write_block_data(nand, oob, 16);
-               oob += 16;
-               oob_size -= 16;
-
-       } while (data_size);
-
-       /* the last data and OOB writes included the spare area */
-       return davinci_writepage_tail(nand, NULL, 0);
-}
-
-static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
-               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
-       davinci_write_pagecmd(nand, NAND_CMD_READ0, page);
-
-       /* large page devices need a start command */
-       if (nand->page_size > 512)
-               davinci_command(nand, NAND_CMD_READSTART);
-
-       if (!davinci_nand_ready(nand, 100))
-               return ERROR_NAND_OPERATION_TIMEOUT;
-
-       /* NOTE:  not bothering to compute and use ECC data for now */
-
-       do {
-               /* write 512 bytes */
-               davinci_read_block_data(nand, data, 512);
-               data += 512;
-               data_size -= 512;
-
-               /* read this "out-of-band" data -- infix */
-               davinci_read_block_data(nand, oob, 16);
-               oob += 16;
-               oob_size -= 16;
-       } while (data_size);
-
-       return ERROR_OK;
-}
-
-NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
-{
-       struct davinci_nand *info;
-       struct target *target;
-       unsigned long chip, aemif;
-       enum ecc eccmode;
-       int chipsel;
-
-       /* arguments:
-        *  - "davinci"
-        *  - target
-        *  - nand chip address
-        *  - ecc mode
-        *  - aemif address
-        * Plus someday, optionally, ALE and CLE masks.
-        */
-       if (CMD_ARGC < 5) {
-               LOG_ERROR("parameters: %s target "
-                               "chip_addr hwecc_mode aemif_addr",
-                               CMD_ARGV[0]);
-               goto fail;
-       }
-
-       target = get_target(CMD_ARGV[1]);
-       if (!target) {
-               LOG_ERROR("invalid target %s", CMD_ARGV[1]);
-               goto fail;
-       }
-
-       COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
-       if (chip == 0) {
-               LOG_ERROR("Invalid NAND chip address %s", CMD_ARGV[2]);
-               goto fail;
-       }
-
-       if (strcmp(CMD_ARGV[3], "hwecc1") == 0)
-               eccmode = HWECC1;
-       else if (strcmp(CMD_ARGV[3], "hwecc4") == 0)
-               eccmode = HWECC4;
-       else if (strcmp(CMD_ARGV[3], "hwecc4_infix") == 0)
-               eccmode = HWECC4_INFIX;
-       else {
-               LOG_ERROR("Invalid ecc mode %s", CMD_ARGV[3]);
-               goto fail;
-       }
-
-       COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[4], aemif);
-       if (aemif == 0) {
-               LOG_ERROR("Invalid AEMIF controller address %s", CMD_ARGV[4]);
-               goto fail;
-       }
-
-       /* REVISIT what we'd *like* to do is look up valid ranges using
-        * target-specific declarations, and not even need to pass the
-        * AEMIF controller address.
-        */
-       if (aemif == 0x01e00000                 /* dm6446, dm357 */
-                       || aemif == 0x01e10000  /* dm335, dm355 */
-                       || aemif == 0x01d10000  /* dm365 */
-                       ) {
-               if (chip < 0x02000000 || chip >= 0x0a000000) {
-                       LOG_ERROR("NAND address %08lx out of range?", chip);
-                       goto fail;
-               }
-               chipsel = (chip - 0x02000000) >> 25;
-       } else {
-               LOG_ERROR("unrecognized AEMIF controller address %08lx", aemif);
-               goto fail;
-       }
-
-       info = calloc(1, sizeof *info);
-       if (info == NULL)
-               goto fail;
-
-       info->target = target;
-       info->eccmode = eccmode;
-       info->chipsel = chipsel;
-       info->aemif = aemif;
-       info->data = chip;
-       info->cmd = chip | 0x10;
-       info->addr = chip | 0x08;
-
-       nand->controller_priv = info;
-
-       info->io.target = target;
-       info->io.data = info->data;
-
-       /* NOTE:  for now we don't do any error correction on read.
-        * Nothing else in OpenOCD currently corrects read errors,
-        * and in any case it's *writing* that we care most about.
-        */
-       info->read_page = nand_read_page_raw;
-
-       switch (eccmode) {
-       case HWECC1:
-               /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
-               info->write_page = davinci_write_page_ecc1;
-               break;
-       case HWECC4:
-               /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
-               info->write_page = davinci_write_page_ecc4;
-               break;
-       case HWECC4_INFIX:
-               /* Same 4-bit ECC HW, with problematic page/ecc layout */
-               info->read_page = davinci_read_page_ecc4infix;
-               info->write_page = davinci_write_page_ecc4infix;
-               break;
-       }
-
-       return ERROR_OK;
-
-fail:
-       return ERROR_NAND_OPERATION_FAILED;
-}
-
-struct nand_flash_controller davinci_nand_controller = {
-       .name                   = "davinci",
-       .nand_device_command    = davinci_nand_device_command,
-       .init                   = davinci_init,
-       .reset                  = davinci_reset,
-       .command                = davinci_command,
-       .address                = davinci_address,
-       .write_data             = davinci_write_data,
-       .read_data              = davinci_read_data,
-       .write_page             = davinci_write_page,
-       .read_page              = davinci_read_page,
-       .write_block_data       = davinci_write_block_data,
-       .read_block_data        = davinci_read_block_data,
-       .nand_ready             = davinci_nand_ready,
-};
diff --git a/src/flash/lpc3180_nand_controller.c b/src/flash/lpc3180_nand_controller.c
deleted file mode 100644 (file)
index 146c843..0000000
+++ /dev/null
@@ -1,910 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007 by Dominic Rath                                    *
- *   Dominic.Rath@gmx.de                                                   *
- *                                                                         *
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "lpc3180_nand_controller.h"
-#include "nand.h"
-
-static int lpc3180_reset(struct nand_device *nand);
-static int lpc3180_controller_ready(struct nand_device *nand, int timeout);
-
-/* nand device lpc3180 <target#> <oscillator_frequency>
- */
-NAND_DEVICE_COMMAND_HANDLER(lpc3180_nand_device_command)
-{
-       if (CMD_ARGC < 3)
-       {
-               LOG_WARNING("incomplete 'lpc3180' nand flash configuration");
-               return ERROR_FLASH_BANK_INVALID;
-       }
-
-       struct target *target = get_target(CMD_ARGV[1]);
-       if (NULL == target)
-       {
-               LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
-               return ERROR_NAND_DEVICE_INVALID;
-       }
-
-       uint32_t osc_freq;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
-
-       struct lpc3180_nand_controller *lpc3180_info;
-       lpc3180_info = malloc(sizeof(struct lpc3180_nand_controller));
-       nand->controller_priv = lpc3180_info;
-
-       lpc3180_info->target = target;
-       lpc3180_info->osc_freq = osc_freq;
-
-       if ((lpc3180_info->osc_freq < 1000) || (lpc3180_info->osc_freq > 20000))
-       {
-               LOG_WARNING("LPC3180 oscillator frequency should be between 1000 and 20000 kHz, was %i", lpc3180_info->osc_freq);
-       }
-       lpc3180_info->selected_controller = LPC3180_NO_CONTROLLER;
-       lpc3180_info->sw_write_protection = 0;
-       lpc3180_info->sw_wp_lower_bound = 0x0;
-       lpc3180_info->sw_wp_upper_bound = 0x0;
-
-       return ERROR_OK;
-}
-
-static int lpc3180_pll(int fclkin, uint32_t pll_ctrl)
-{
-       int bypass = (pll_ctrl & 0x8000) >> 15;
-       int direct = (pll_ctrl & 0x4000) >> 14;
-       int feedback = (pll_ctrl & 0x2000) >> 13;
-       int p = (1 << ((pll_ctrl & 0x1800) >> 11) * 2);
-       int n = ((pll_ctrl & 0x0600) >> 9) + 1;
-       int m = ((pll_ctrl & 0x01fe) >> 1) + 1;
-       int lock = (pll_ctrl & 0x1);
-
-       if (!lock)
-               LOG_WARNING("PLL is not locked");
-
-       if (!bypass && direct)  /* direct mode */
-               return (m * fclkin) / n;
-
-       if (bypass && !direct)  /* bypass mode */
-               return fclkin / (2 * p);
-
-       if (bypass & direct)    /* direct bypass mode */
-               return fclkin;
-
-       if (feedback)                   /* integer mode */
-               return m * (fclkin / n);
-       else                                    /* non-integer mode */
-               return (m / (2 * p)) * (fclkin / n);
-}
-
-static float lpc3180_cycle_time(struct lpc3180_nand_controller *lpc3180_info)
-{
-       struct target *target = lpc3180_info->target;
-       uint32_t sysclk_ctrl, pwr_ctrl, hclkdiv_ctrl, hclkpll_ctrl;
-       int sysclk;
-       int hclk;
-       int hclk_pll;
-       float cycle;
-
-       /* calculate timings */
-
-       /* determine current SYSCLK (13'MHz or main oscillator) */
-       target_read_u32(target, 0x40004050, &sysclk_ctrl);
-
-       if ((sysclk_ctrl & 1) == 0)
-               sysclk = lpc3180_info->osc_freq;
-       else
-               sysclk = 13000;
-
-       /* determine selected HCLK source */
-       target_read_u32(target, 0x40004044, &pwr_ctrl);
-
-       if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
-       {
-               hclk = sysclk;
-       }
-       else
-       {
-               target_read_u32(target, 0x40004058, &hclkpll_ctrl);
-               hclk_pll = lpc3180_pll(sysclk, hclkpll_ctrl);
-
-               target_read_u32(target, 0x40004040, &hclkdiv_ctrl);
-
-               if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
-               {
-                       hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1);
-               }
-               else /* HCLK uses HCLK_PLL */
-               {
-                       hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3));
-               }
-       }
-
-       LOG_DEBUG("LPC3180 HCLK currently clocked at %i kHz", hclk);
-
-       cycle = (1.0 / hclk) * 1000000.0;
-
-       return cycle;
-}
-
-static int lpc3180_init(struct nand_device *nand)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-       int bus_width = nand->bus_width ? : 8;
-       int address_cycles = nand->address_cycles ? : 3;
-       int page_size = nand->page_size ? : 512;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       /* sanitize arguments */
-       if ((bus_width != 8) && (bus_width != 16))
-       {
-               LOG_ERROR("LPC3180 only supports 8 or 16 bit bus width, not %i", bus_width);
-               return ERROR_NAND_OPERATION_NOT_SUPPORTED;
-       }
-
-       /* The LPC3180 only brings out 8 bit NAND data bus, but the controller
-        * would support 16 bit, too, so we just warn about this for now
-        */
-       if (bus_width == 16)
-       {
-               LOG_WARNING("LPC3180 only supports 8 bit bus width");
-       }
-
-       /* inform calling code about selected bus width */
-       nand->bus_width = bus_width;
-
-       if ((address_cycles != 3) && (address_cycles != 4))
-       {
-               LOG_ERROR("LPC3180 only supports 3 or 4 address cycles, not %i", address_cycles);
-               return ERROR_NAND_OPERATION_NOT_SUPPORTED;
-       }
-
-       if ((page_size != 512) && (page_size != 2048))
-       {
-               LOG_ERROR("LPC3180 only supports 512 or 2048 byte pages, not %i", page_size);
-               return ERROR_NAND_OPERATION_NOT_SUPPORTED;
-       }
-
-       /* select MLC controller if none is currently selected */
-       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
-       {
-               LOG_DEBUG("no LPC3180 NAND flash controller selected, using default 'mlc'");
-               lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER;
-       }
-
-       if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-       {
-               uint32_t mlc_icr_value = 0x0;
-               float cycle;
-               int twp, twh, trp, treh, trhz, trbwb, tcea;
-
-               /* FLASHCLK_CTRL = 0x22 (enable clock for MLC flash controller) */
-               target_write_u32(target, 0x400040c8, 0x22);
-
-               /* MLC_CEH = 0x0 (Force nCE assert) */
-               target_write_u32(target, 0x200b804c, 0x0);
-
-               /* MLC_LOCK = 0xa25e (unlock protected registers) */
-               target_write_u32(target, 0x200b8044, 0xa25e);
-
-               /* MLC_ICR = configuration */
-               if (lpc3180_info->sw_write_protection)
-                       mlc_icr_value |= 0x8;
-               if (page_size == 2048)
-                       mlc_icr_value |= 0x4;
-               if (address_cycles == 4)
-                       mlc_icr_value |= 0x2;
-               if (bus_width == 16)
-                       mlc_icr_value |= 0x1;
-               target_write_u32(target, 0x200b8030, mlc_icr_value);
-
-               /* calculate NAND controller timings */
-               cycle = lpc3180_cycle_time(lpc3180_info);
-
-               twp = ((40 / cycle) + 1);
-               twh = ((20 / cycle) + 1);
-               trp = ((30 / cycle) + 1);
-               treh = ((15 / cycle) + 1);
-               trhz = ((30 / cycle) + 1);
-               trbwb = ((100 / cycle) + 1);
-               tcea = ((45 / cycle) + 1);
-
-               /* MLC_LOCK = 0xa25e (unlock protected registers) */
-               target_write_u32(target, 0x200b8044, 0xa25e);
-
-               /* MLC_TIME_REG */
-               target_write_u32(target, 0x200b8034, (twp & 0xf) | ((twh & 0xf) << 4) |
-                       ((trp & 0xf) << 8) | ((treh & 0xf) << 12) | ((trhz & 0x7) << 16) |
-                       ((trbwb & 0x1f) << 19) | ((tcea & 0x3) << 24));
-
-               lpc3180_reset(nand);
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-       {
-               float cycle;
-               int r_setup, r_hold, r_width, r_rdy;
-               int w_setup, w_hold, w_width, w_rdy;
-
-               /* FLASHCLK_CTRL = 0x05 (enable clock for SLC flash controller) */
-               target_write_u32(target, 0x400040c8, 0x05);
-
-               /* SLC_CFG = 0x (Force nCE assert, ECC enabled, WIDTH = bus_width) */
-               target_write_u32(target, 0x20020014, 0x28 | (bus_width == 16) ? 1 : 0);
-
-               /* calculate NAND controller timings */
-               cycle = lpc3180_cycle_time(lpc3180_info);
-
-               r_setup = w_setup = 0;
-               r_hold = w_hold = 10 / cycle;
-               r_width = 30 / cycle;
-               w_width = 40 / cycle;
-               r_rdy = w_rdy = 100 / cycle;
-
-               /* SLC_TAC: SLC timing arcs register */
-               target_write_u32(target, 0x2002002c, (r_setup & 0xf) | ((r_hold & 0xf) << 4) |
-                       ((r_width & 0xf) << 8) | ((r_rdy & 0xf) << 12) |  ((w_setup & 0xf) << 16) |
-                       ((w_hold & 0xf) << 20) | ((w_width & 0xf) << 24) | ((w_rdy & 0xf) << 28));
-
-               lpc3180_reset(nand);
-       }
-
-       return ERROR_OK;
-}
-
-static int lpc3180_reset(struct nand_device *nand)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
-       {
-               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-       {
-               /* MLC_CMD = 0xff (reset controller and NAND device) */
-               target_write_u32(target, 0x200b8000, 0xff);
-
-               if (!lpc3180_controller_ready(nand, 100))
-               {
-                       LOG_ERROR("LPC3180 NAND controller timed out after reset");
-                       return ERROR_NAND_OPERATION_TIMEOUT;
-               }
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-       {
-               /* SLC_CTRL = 0x6 (ECC_CLEAR, SW_RESET) */
-               target_write_u32(target, 0x20020010, 0x6);
-
-               if (!lpc3180_controller_ready(nand, 100))
-               {
-                       LOG_ERROR("LPC3180 NAND controller timed out after reset");
-                       return ERROR_NAND_OPERATION_TIMEOUT;
-               }
-       }
-
-       return ERROR_OK;
-}
-
-static int lpc3180_command(struct nand_device *nand, uint8_t command)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
-       {
-               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-       {
-               /* MLC_CMD = command */
-               target_write_u32(target, 0x200b8000, command);
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-       {
-               /* SLC_CMD = command */
-               target_write_u32(target, 0x20020008, command);
-       }
-
-       return ERROR_OK;
-}
-
-static int lpc3180_address(struct nand_device *nand, uint8_t address)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
-       {
-               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-       {
-               /* MLC_ADDR = address */
-               target_write_u32(target, 0x200b8004, address);
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-       {
-               /* SLC_ADDR = address */
-               target_write_u32(target, 0x20020004, address);
-       }
-
-       return ERROR_OK;
-}
-
-static int lpc3180_write_data(struct nand_device *nand, uint16_t data)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
-       {
-               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-       {
-               /* MLC_DATA = data */
-               target_write_u32(target, 0x200b0000, data);
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-       {
-               /* SLC_DATA = data */
-               target_write_u32(target, 0x20020000, data);
-       }
-
-       return ERROR_OK;
-}
-
-static int lpc3180_read_data(struct nand_device *nand, void *data)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
-       {
-               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-       {
-               /* data = MLC_DATA, use sized access */
-               if (nand->bus_width == 8)
-               {
-                       uint8_t *data8 = data;
-                       target_read_u8(target, 0x200b0000, data8);
-               }
-               else if (nand->bus_width == 16)
-               {
-                       uint16_t *data16 = data;
-                       target_read_u16(target, 0x200b0000, data16);
-               }
-               else
-               {
-                       LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
-                       return ERROR_NAND_OPERATION_FAILED;
-               }
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-       {
-               uint32_t data32;
-
-               /* data = SLC_DATA, must use 32-bit access */
-               target_read_u32(target, 0x20020000, &data32);
-
-               if (nand->bus_width == 8)
-               {
-                       uint8_t *data8 = data;
-                       *data8 = data32 & 0xff;
-               }
-               else if (nand->bus_width == 16)
-               {
-                       uint16_t *data16 = data;
-                       *data16 = data32 & 0xffff;
-               }
-               else
-               {
-                       LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
-                       return ERROR_NAND_OPERATION_FAILED;
-               }
-       }
-
-       return ERROR_OK;
-}
-
-static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-       int retval;
-       uint8_t status;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
-       {
-               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-       {
-               uint8_t *page_buffer;
-               uint8_t *oob_buffer;
-               int quarter, num_quarters;
-
-               if (!data && oob)
-               {
-                       LOG_ERROR("LPC3180 MLC controller can't write OOB data only");
-                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
-               }
-
-               if (oob && (oob_size > 6))
-               {
-                       LOG_ERROR("LPC3180 MLC controller can't write more than 6 bytes of OOB data");
-                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
-               }
-
-               if (data_size > (uint32_t)nand->page_size)
-               {
-                       LOG_ERROR("data size exceeds page size");
-                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
-               }
-
-               /* MLC_CMD = sequential input */
-               target_write_u32(target, 0x200b8000, NAND_CMD_SEQIN);
-
-               page_buffer = malloc(512);
-               oob_buffer = malloc(6);
-
-               if (nand->page_size == 512)
-               {
-                       /* MLC_ADDR = 0x0 (one column cycle) */
-                       target_write_u32(target, 0x200b8004, 0x0);
-
-                       /* MLC_ADDR = row */
-                       target_write_u32(target, 0x200b8004, page & 0xff);
-                       target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
-
-                       if (nand->address_cycles == 4)
-                               target_write_u32(target, 0x200b8004, (page >> 16) & 0xff);
-               }
-               else
-               {
-                       /* MLC_ADDR = 0x0 (two column cycles) */
-                       target_write_u32(target, 0x200b8004, 0x0);
-                       target_write_u32(target, 0x200b8004, 0x0);
-
-                       /* MLC_ADDR = row */
-                       target_write_u32(target, 0x200b8004, page & 0xff);
-                       target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
-               }
-
-               /* when using the MLC controller, we have to treat a large page device
-                * as being made out of four quarters, each the size of a small page device
-                */
-               num_quarters = (nand->page_size == 2048) ? 4 : 1;
-
-               for (quarter = 0; quarter < num_quarters; quarter++)
-               {
-                       int thisrun_data_size = (data_size > 512) ? 512 : data_size;
-                       int thisrun_oob_size = (oob_size > 6) ? 6 : oob_size;
-
-                       memset(page_buffer, 0xff, 512);
-                       if (data)
-                       {
-                               memcpy(page_buffer, data, thisrun_data_size);
-                               data_size -= thisrun_data_size;
-                               data += thisrun_data_size;
-                       }
-
-                       memset(oob_buffer, 0xff, (nand->page_size == 512) ? 6 : 24);
-                       if (oob)
-                       {
-                               memcpy(page_buffer, oob, thisrun_oob_size);
-                               oob_size -= thisrun_oob_size;
-                               oob += thisrun_oob_size;
-                       }
-
-                       /* write MLC_ECC_ENC_REG to start encode cycle */
-                       target_write_u32(target, 0x200b8008, 0x0);
-
-                       target_write_memory(target, 0x200a8000, 4, 128, page_buffer + (quarter * 512));
-                       target_write_memory(target, 0x200a8000, 1, 6, oob_buffer + (quarter * 6));
-
-                       /* write MLC_ECC_AUTO_ENC_REG to start auto encode */
-                       target_write_u32(target, 0x200b8010, 0x0);
-
-                       if (!lpc3180_controller_ready(nand, 1000))
-                       {
-                               LOG_ERROR("timeout while waiting for completion of auto encode cycle");
-                               return ERROR_NAND_OPERATION_FAILED;
-                       }
-               }
-
-               /* MLC_CMD = auto program command */
-               target_write_u32(target, 0x200b8000, NAND_CMD_PAGEPROG);
-
-               if ((retval = nand_read_status(nand, &status)) != ERROR_OK)
-               {
-                       LOG_ERROR("couldn't read status");
-                       return ERROR_NAND_OPERATION_FAILED;
-               }
-
-               if (status & NAND_STATUS_FAIL)
-               {
-                       LOG_ERROR("write operation didn't pass, status: 0x%2.2x", status);
-                       return ERROR_NAND_OPERATION_FAILED;
-               }
-
-               free(page_buffer);
-               free(oob_buffer);
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-       {
-               return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
-       }
-
-       return ERROR_OK;
-}
-
-static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
-       {
-               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-       {
-               uint8_t *page_buffer;
-               uint8_t *oob_buffer;
-               uint32_t page_bytes_done = 0;
-               uint32_t oob_bytes_done = 0;
-               uint32_t mlc_isr;
-
-#if 0
-               if (oob && (oob_size > 6))
-               {
-                       LOG_ERROR("LPC3180 MLC controller can't read more than 6 bytes of OOB data");
-                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
-               }
-#endif
-
-               if (data_size > (uint32_t)nand->page_size)
-               {
-                       LOG_ERROR("data size exceeds page size");
-                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
-               }
-
-               if (nand->page_size == 2048)
-               {
-                       page_buffer = malloc(2048);
-                       oob_buffer = malloc(64);
-               }
-               else
-               {
-                       page_buffer = malloc(512);
-                       oob_buffer = malloc(16);
-               }
-
-               if (!data && oob)
-               {
-                       /* MLC_CMD = Read OOB
-                        * we can use the READOOB command on both small and large page devices,
-                        * as the controller translates the 0x50 command to a 0x0 with appropriate
-                        * positioning of the serial buffer read pointer
-                        */
-                       target_write_u32(target, 0x200b8000, NAND_CMD_READOOB);
-               }
-               else
-               {
-                       /* MLC_CMD = Read0 */
-                       target_write_u32(target, 0x200b8000, NAND_CMD_READ0);
-               }
-
-               if (nand->page_size == 512)
-               {
-                       /* small page device */
-                       /* MLC_ADDR = 0x0 (one column cycle) */
-                       target_write_u32(target, 0x200b8004, 0x0);
-
-                       /* MLC_ADDR = row */
-                       target_write_u32(target, 0x200b8004, page & 0xff);
-                       target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
-
-                       if (nand->address_cycles == 4)
-                               target_write_u32(target, 0x200b8004, (page >> 16) & 0xff);
-               }
-               else
-               {
-                       /* large page device */
-                       /* MLC_ADDR = 0x0 (two column cycles) */
-                       target_write_u32(target, 0x200b8004, 0x0);
-                       target_write_u32(target, 0x200b8004, 0x0);
-
-                       /* MLC_ADDR = row */
-                       target_write_u32(target, 0x200b8004, page & 0xff);
-                       target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
-
-                       /* MLC_CMD = Read Start */
-                       target_write_u32(target, 0x200b8000, NAND_CMD_READSTART);
-               }
-
-               while (page_bytes_done < (uint32_t)nand->page_size)
-               {
-                       /* MLC_ECC_AUTO_DEC_REG = dummy */
-                       target_write_u32(target, 0x200b8014, 0xaa55aa55);
-
-                       if (!lpc3180_controller_ready(nand, 1000))
-                       {
-                               LOG_ERROR("timeout while waiting for completion of auto decode cycle");
-                               return ERROR_NAND_OPERATION_FAILED;
-                       }
-
-                       target_read_u32(target, 0x200b8048, &mlc_isr);
-
-                       if (mlc_isr & 0x8)
-                       {
-                               if (mlc_isr & 0x40)
-                               {
-                                       LOG_ERROR("uncorrectable error detected: 0x%2.2x", (unsigned)mlc_isr);
-                                       return ERROR_NAND_OPERATION_FAILED;
-                               }
-
-                               LOG_WARNING("%i symbol error detected and corrected", ((int)(((mlc_isr & 0x30) >> 4) + 1)));
-                       }
-
-                       if (data)
-                       {
-                               target_read_memory(target, 0x200a8000, 4, 128, page_buffer + page_bytes_done);
-                       }
-
-                       if (oob)
-                       {
-                               target_read_memory(target, 0x200a8000, 4, 4, oob_buffer + oob_bytes_done);
-                       }
-
-                       page_bytes_done += 512;
-                       oob_bytes_done += 16;
-               }
-
-               if (data)
-                       memcpy(data, page_buffer, data_size);
-
-               if (oob)
-                       memcpy(oob, oob_buffer, oob_size);
-
-               free(page_buffer);
-               free(oob_buffer);
-       }
-       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-       {
-               return nand_read_page_raw(nand, page, data, data_size, oob, oob_size);
-       }
-
-       return ERROR_OK;
-}
-
-static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-       uint8_t status = 0x0;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       do
-       {
-               if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-               {
-                       /* Read MLC_ISR, wait for controller to become ready */
-                       target_read_u8(target, 0x200b8048, &status);
-
-                       if (status & 2)
-                               return 1;
-               }
-               else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-               {
-                       /* we pretend that the SLC controller is always ready */
-                       return 1;
-               }
-
-               alive_sleep(1);
-       } while (timeout-- > 0);
-
-       return 0;
-}
-
-static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
-{
-       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
-       struct target *target = lpc3180_info->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       do
-       {
-               if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
-               {
-                       uint8_t status = 0x0;
-
-                       /* Read MLC_ISR, wait for NAND flash device to become ready */
-                       target_read_u8(target, 0x200b8048, &status);
-
-                       if (status & 1)
-                               return 1;
-               }
-               else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
-               {
-                       uint32_t status = 0x0;
-
-                       /* Read SLC_STAT and check READY bit */
-                       target_read_u32(target, 0x20020018, &status);
-
-                       if (status & 1)
-                               return 1;
-               }
-
-               alive_sleep(1);
-       } while (timeout-- > 0);
-
-       return 0;
-}
-
-COMMAND_HANDLER(handle_lpc3180_select_command)
-{
-       struct lpc3180_nand_controller *lpc3180_info = NULL;
-       char *selected[] =
-       {
-               "no", "mlc", "slc"
-       };
-
-       if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       unsigned num;
-       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], num);
-       struct nand_device *nand = get_nand_device_by_num(num);
-       if (!nand)
-       {
-               command_print(CMD_CTX, "nand device '#%s' is out of bounds", CMD_ARGV[0]);
-               return ERROR_OK;
-       }
-
-       lpc3180_info = nand->controller_priv;
-
-       if (CMD_ARGC == 2)
-       {
-               if (strcmp(CMD_ARGV[1], "mlc") == 0)
-               {
-                       lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER;
-               }
-               else if (strcmp(CMD_ARGV[1], "slc") == 0)
-               {
-                       lpc3180_info->selected_controller = LPC3180_SLC_CONTROLLER;
-               }
-               else
-               {
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-               }
-       }
-
-       command_print(CMD_CTX, "%s controller selected", selected[lpc3180_info->selected_controller]);
-
-       return ERROR_OK;
-}
-
-static const struct command_registration lpc3180_exec_command_handlers[] = {
-       {
-               .name = "select",
-               .handler = &handle_lpc3180_select_command,
-               .mode = COMMAND_EXEC,
-               .help = "select <'mlc'|'slc'> controller (default is mlc)",
-               .usage = "<device_id> (mlc|slc)",
-       },
-       COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration lpc3180_command_handler[] = {
-       {
-               .name = "lpc3180",
-               .mode = COMMAND_ANY,
-               .help = "LPC3180 NAND flash controller commands",
-               .chain = lpc3180_exec_command_handlers,
-       },
-       COMMAND_REGISTRATION_DONE
-};
-
-struct nand_flash_controller lpc3180_nand_controller = {
-               .name = "lpc3180",
-               .commands = lpc3180_command_handler,
-               .nand_device_command = lpc3180_nand_device_command,
-               .init = lpc3180_init,
-               .reset = lpc3180_reset,
-               .command = lpc3180_command,
-               .address = lpc3180_address,
-               .write_data = lpc3180_write_data,
-               .read_data = lpc3180_read_data,
-               .write_page = lpc3180_write_page,
-               .read_page = lpc3180_read_page,
-               .controller_ready = lpc3180_controller_ready,
-               .nand_ready = lpc3180_nand_ready,
-       };
diff --git a/src/flash/lpc3180_nand_controller.h b/src/flash/lpc3180_nand_controller.h
deleted file mode 100644 (file)
index 0891ced..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007 by Dominic Rath                                    *
- *   Dominic.Rath@gmx.de                                                   *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
- ***************************************************************************/
-#ifndef LPC3180_NAND_CONTROLLER_H
-#define LPC3180_NAND_CONTROLLER_H
-
-enum lpc3180_selected_controller
-{
-       LPC3180_NO_CONTROLLER,
-       LPC3180_MLC_CONTROLLER,
-       LPC3180_SLC_CONTROLLER,
-};
-
-struct lpc3180_nand_controller
-{
-       struct target *target;
-       int osc_freq;
-       enum lpc3180_selected_controller selected_controller;
-       int sw_write_protection;
-       uint32_t sw_wp_lower_bound;
-       uint32_t sw_wp_upper_bound;
-};
-
-#endif /*LPC3180_NAND_CONTROLLER_H */
diff --git a/src/flash/mx3_nand.c b/src/flash/mx3_nand.c
deleted file mode 100644 (file)
index 1dc4fcb..0000000
+++ /dev/null
@@ -1,879 +0,0 @@
-
-/***************************************************************************
- *   Copyright (C) 2009 by Alexei Babich                                   *
- *   Rezonans plc., Chelyabinsk, Russia                                    *
- *   impatt@mail.ru                                                        *
- *                                                                         *
- *   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.             *
- ***************************************************************************/
-
-/*
- * Freescale iMX3* OpenOCD NAND Flash controller support.
- *
- * Many thanks to Ben Dooks for writing s3c24xx driver.
- */
-
-/*
-driver tested with STMicro NAND512W3A @imx31
-tested "nand probe #", "nand erase # 0 #", "nand dump # file 0 #", "nand write # file 0"
-get_next_halfword_from_sram_buffer() not tested
-*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mx3_nand.h"
-
-static const char target_not_halted_err_msg[] =
-       "target must be halted to use mx3 NAND flash controller";
-static const char data_block_size_err_msg[] =
-       "minimal granularity is one half-word, %" PRId32 " is incorrect";
-static const char sram_buffer_bounds_err_msg[] =
-       "trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
-static const char get_status_register_err_msg[] = "can't get NAND status";
-static uint32_t in_sram_address;
-unsigned char sign_of_sequental_byte_read;
-
-static int test_iomux_settings (struct target * target, uint32_t value,
-                               uint32_t mask, const char *text);
-static int initialize_nf_controller (struct nand_device *nand);
-static int get_next_byte_from_sram_buffer (struct target * target, uint8_t * value);
-static int get_next_halfword_from_sram_buffer (struct target * target,
-                                              uint16_t * value);
-static int poll_for_complete_op (struct target * target, const char *text);
-static int validate_target_state (struct nand_device *nand);
-static int do_data_output (struct nand_device *nand);
-
-static int imx31_command (struct nand_device *nand, uint8_t command);
-static int imx31_address (struct nand_device *nand, uint8_t address);
-static int imx31_controller_ready (struct nand_device *nand, int tout);
-
-NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
-{
-       struct mx3_nf_controller *mx3_nf_info;
-       mx3_nf_info = malloc (sizeof (struct mx3_nf_controller));
-       if (mx3_nf_info == NULL)
-       {
-           LOG_ERROR ("no memory for nand controller");
-           return ERROR_FAIL;
-       }
-
-       nand->controller_priv = mx3_nf_info;
-
-       mx3_nf_info->target = get_target (CMD_ARGV[1]);
-       if (mx3_nf_info->target == NULL)
-       {
-           LOG_ERROR ("target '%s' not defined", CMD_ARGV[1]);
-           return ERROR_FAIL;
-       }
-       if (CMD_ARGC < 3)
-       {
-           LOG_ERROR ("use \"nand device imx31 target noecc|hwecc\"");
-           return ERROR_FAIL;
-       }
-       /*
-       * check hwecc requirements
-       */
-       {
-       int hwecc_needed;
-       hwecc_needed = strcmp (CMD_ARGV[2], "hwecc");
-       if (hwecc_needed == 0)
-           {
-               mx3_nf_info->flags.hw_ecc_enabled = 1;
-           }
-       else
-           {
-               mx3_nf_info->flags.hw_ecc_enabled = 0;
-           }
-       }
-
-       mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
-       mx3_nf_info->fin = MX3_NF_FIN_NONE;
-       mx3_nf_info->flags.target_little_endian =
-       (mx3_nf_info->target->endianness == TARGET_LITTLE_ENDIAN);
-       /*
-       * testing host endianess
-       */
-       {
-       int x = 1;
-       if (*(char *) &x == 1)
-           {
-               mx3_nf_info->flags.host_little_endian = 1;
-           }
-       else
-           {
-               mx3_nf_info->flags.host_little_endian = 0;
-           }
-       }
-       return ERROR_OK;
-}
-
-static int imx31_init (struct nand_device *nand)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-
-       {
-       /*
-        * validate target state
-        */
-       int validate_target_result;
-       validate_target_result = validate_target_state(nand);
-       if (validate_target_result != ERROR_OK)
-           {
-               return validate_target_result;
-           }
-       }
-
-       {
-       uint16_t buffsize_register_content;
-       target_read_u16 (target, MX3_NF_BUFSIZ, &buffsize_register_content);
-       mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
-       }
-
-       {
-       uint32_t pcsr_register_content;
-       target_read_u32 (target, MX3_PCSR, &pcsr_register_content);
-       if (!nand->bus_width)
-           {
-               nand->bus_width =
-                   (pcsr_register_content & 0x80000000) ? 16 : 8;
-           }
-       else
-           {
-               pcsr_register_content |=
-                   ((nand->bus_width == 16) ? 0x80000000 : 0x00000000);
-               target_write_u32 (target, MX3_PCSR, pcsr_register_content);
-           }
-
-       if (!nand->page_size)
-           {
-               nand->page_size =
-                   (pcsr_register_content & 0x40000000) ? 2048 : 512;
-           }
-       else
-           {
-               pcsr_register_content |=
-                   ((nand->page_size == 2048) ? 0x40000000 : 0x00000000);
-               target_write_u32 (target, MX3_PCSR, pcsr_register_content);
-           }
-       if (mx3_nf_info->flags.one_kb_sram && (nand->page_size == 2048))
-           {
-               LOG_ERROR
-                   ("NAND controller have only 1 kb SRAM, so pagesize 2048 is incompatible with it");
-           }
-       }
-
-       {
-       uint32_t cgr_register_content;
-       target_read_u32 (target, MX3_CCM_CGR2, &cgr_register_content);
-       if (!(cgr_register_content & 0x00000300))
-           {
-               LOG_ERROR ("clock gating to EMI disabled");
-               return ERROR_FAIL;
-           }
-       }
-
-       {
-       uint32_t gpr_register_content;
-       target_read_u32 (target, MX3_GPR, &gpr_register_content);
-       if (gpr_register_content & 0x00000060)
-           {
-               LOG_ERROR ("pins mode overrided by GPR");
-               return ERROR_FAIL;
-           }
-       }
-
-       {
-       /*
-        * testing IOMUX settings; must be in "functional-mode output and
-        * functional-mode input" mode
-        */
-       int test_iomux;
-       test_iomux = ERROR_OK;
-       test_iomux |=
-           test_iomux_settings (target, 0x43fac0c0, 0x7f7f7f00, "d0,d1,d2");
-       test_iomux |=
-           test_iomux_settings (target, 0x43fac0c4, 0x7f7f7f7f, "d3,d4,d5,d6");
-       test_iomux |=
-           test_iomux_settings (target, 0x43fac0c8, 0x0000007f, "d7");
-       if (nand->bus_width == 16)
-           {
-               test_iomux |=
-                   test_iomux_settings (target, 0x43fac0c8, 0x7f7f7f00,
-                                        "d8,d9,d10");
-               test_iomux |=
-                   test_iomux_settings (target, 0x43fac0cc, 0x7f7f7f7f,
-                                        "d11,d12,d13,d14");
-               test_iomux |=
-                   test_iomux_settings (target, 0x43fac0d0, 0x0000007f, "d15");
-           }
-       test_iomux |=
-           test_iomux_settings (target, 0x43fac0d0, 0x7f7f7f00,
-                                "nfwp,nfce,nfrb");
-       test_iomux |=
-           test_iomux_settings (target, 0x43fac0d4, 0x7f7f7f7f,
-                                "nfwe,nfre,nfale,nfcle");
-       if (test_iomux != ERROR_OK)
-           {
-               return ERROR_FAIL;
-           }
-       }
-
-       initialize_nf_controller (nand);
-
-       {
-       int retval;
-       uint16_t nand_status_content;
-       retval = ERROR_OK;
-       retval |= imx31_command (nand, NAND_CMD_STATUS);
-       retval |= imx31_address (nand, 0x00);
-       retval |= do_data_output (nand);
-       if (retval != ERROR_OK)
-           {
-               LOG_ERROR (get_status_register_err_msg);
-               return ERROR_FAIL;
-           }
-       target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
-       if (!(nand_status_content & 0x0080))
-           {
-               /*
-                * is host-big-endian correctly ??
-                */
-               LOG_INFO ("NAND read-only");
-               mx3_nf_info->flags.nand_readonly = 1;
-           }
-       else
-           {
-               mx3_nf_info->flags.nand_readonly = 0;
-           }
-       }
-       return ERROR_OK;
-}
-
-static int imx31_read_data (struct nand_device *nand, void *data)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-       {
-       /*
-        * validate target state
-        */
-       int validate_target_result;
-       validate_target_result = validate_target_state (nand);
-       if (validate_target_result != ERROR_OK)
-           {
-               return validate_target_result;
-           }
-       }
-
-       {
-       /*
-        * get data from nand chip
-        */
-       int try_data_output_from_nand_chip;
-       try_data_output_from_nand_chip = do_data_output (nand);
-       if (try_data_output_from_nand_chip != ERROR_OK)
-           {
-               return try_data_output_from_nand_chip;
-           }
-       }
-
-       if (nand->bus_width == 16)
-       {
-           get_next_halfword_from_sram_buffer (target, data);
-       }
-       else
-       {
-           get_next_byte_from_sram_buffer (target, data);
-       }
-
-       return ERROR_OK;
-}
-
-static int imx31_write_data (struct nand_device *nand, uint16_t data)
-{
-       LOG_ERROR ("write_data() not implemented");
-       return ERROR_NAND_OPERATION_FAILED;
-}
-
-static int imx31_nand_ready (struct nand_device *nand, int timeout)
-{
-       return imx31_controller_ready (nand, timeout);
-}
-
-static int imx31_reset (struct nand_device *nand)
-{
-       /*
-       * validate target state
-       */
-       int validate_target_result;
-       validate_target_result = validate_target_state (nand);
-       if (validate_target_result != ERROR_OK)
-       {
-           return validate_target_result;
-       }
-       initialize_nf_controller (nand);
-       return ERROR_OK;
-}
-
-static int imx31_command (struct nand_device *nand, uint8_t command)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-       {
-       /*
-        * validate target state
-        */
-       int validate_target_result;
-       validate_target_result = validate_target_state (nand);
-       if (validate_target_result != ERROR_OK)
-           {
-               return validate_target_result;
-           }
-       }
-
-       switch (command)
-       {
-           case NAND_CMD_READOOB:
-               command = NAND_CMD_READ0;
-               in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
-                                                        * data_read() and
-                                                        * read_block_data() to
-                                                        * spare area in SRAM
-                                                        * buffer */
-               break;
-           case NAND_CMD_READ1:
-               command = NAND_CMD_READ0;
-               /*
-                * offset == one half of page size
-                */
-               in_sram_address =
-                   MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
-           default:
-               in_sram_address = MX3_NF_MAIN_BUFFER0;
-       }
-
-       target_write_u16 (target, MX3_NF_FCMD, command);
-       /*
-       * start command input operation (set MX3_NF_BIT_OP_DONE==0)
-       */
-       target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FCI);
-       {
-       int poll_result;
-       poll_result = poll_for_complete_op (target, "command");
-       if (poll_result != ERROR_OK)
-           {
-               return poll_result;
-           }
-       }
-       /*
-       * reset cursor to begin of the buffer
-       */
-       sign_of_sequental_byte_read = 0;
-       switch (command)
-       {
-           case NAND_CMD_READID:
-               mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
-               mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
-               break;
-           case NAND_CMD_STATUS:
-               mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS;
-               mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
-               break;
-           case NAND_CMD_READ0:
-               mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
-               mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
-               break;
-           default:
-               mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
-       }
-       return ERROR_OK;
-}
-
-static int imx31_address (struct nand_device *nand, uint8_t address)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-       {
-       /*
-        * validate target state
-        */
-       int validate_target_result;
-       validate_target_result = validate_target_state (nand);
-       if (validate_target_result != ERROR_OK)
-           {
-               return validate_target_result;
-           }
-       }
-
-       target_write_u16 (target, MX3_NF_FADDR, address);
-       /*
-       * start address input operation (set MX3_NF_BIT_OP_DONE==0)
-       */
-       target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FAI);
-       {
-       int poll_result;
-       poll_result = poll_for_complete_op (target, "address");
-       if (poll_result != ERROR_OK)
-           {
-               return poll_result;
-           }
-       }
-       return ERROR_OK;
-}
-
-static int imx31_controller_ready (struct nand_device *nand, int tout)
-{
-       uint16_t poll_complete_status;
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-
-       {
-       /*
-        * validate target state
-        */
-       int validate_target_result;
-       validate_target_result = validate_target_state (nand);
-       if (validate_target_result != ERROR_OK)
-           {
-               return validate_target_result;
-           }
-       }
-
-       do
-       {
-           target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
-           if (poll_complete_status & MX3_NF_BIT_OP_DONE)
-               {
-                   return tout;
-               }
-           alive_sleep (1);
-       }
-       while (tout-- > 0);
-       return tout;
-}
-
-static int imx31_write_page (struct nand_device *nand, uint32_t page,
-                            uint8_t * data, uint32_t data_size, uint8_t * oob,
-                            uint32_t oob_size)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-
-       if (data_size % 2)
-       {
-           LOG_ERROR (data_block_size_err_msg, data_size);
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-       if (oob_size % 2)
-       {
-           LOG_ERROR (data_block_size_err_msg, oob_size);
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-       if (!data)
-       {
-           LOG_ERROR ("nothing to program");
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-       {
-       /*
-        * validate target state
-        */
-       int retval;
-       retval = validate_target_state (nand);
-       if (retval != ERROR_OK)
-           {
-               return retval;
-           }
-       }
-       {
-       int retval = ERROR_OK;
-       retval |= imx31_command(nand, NAND_CMD_SEQIN);
-       retval |= imx31_address(nand, 0x00);
-       retval |= imx31_address(nand, page & 0xff);
-       retval |= imx31_address(nand, (page >> 8) & 0xff);
-       if (nand->address_cycles >= 4)
-           {
-               retval |= imx31_address (nand, (page >> 16) & 0xff);
-               if (nand->address_cycles >= 5)
-                   {
-                       retval |= imx31_address (nand, (page >> 24) & 0xff);
-                   }
-           }
-       target_write_buffer (target, MX3_NF_MAIN_BUFFER0, data_size, data);
-       if (oob)
-           {
-               if (mx3_nf_info->flags.hw_ecc_enabled)
-                   {
-                       /*
-                        * part of spare block will be overrided by hardware
-                        * ECC generator
-                        */
-                       LOG_DEBUG
-                           ("part of spare block will be overrided by hardware ECC generator");
-                   }
-               target_write_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
-                                    oob);
-           }
-       /*
-        * start data input operation (set MX3_NF_BIT_OP_DONE==0)
-        */
-       target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI);
-       {
-           int poll_result;
-           poll_result = poll_for_complete_op (target, "data input");
-           if (poll_result != ERROR_OK)
-               {
-                   return poll_result;
-               }
-       }
-       retval |= imx31_command (nand, NAND_CMD_PAGEPROG);
-       if (retval != ERROR_OK)
-           {
-               return retval;
-           }
-
-       /*
-        * check status register
-        */
-       {
-           uint16_t nand_status_content;
-           retval = ERROR_OK;
-           retval |= imx31_command(nand, NAND_CMD_STATUS);
-           retval |= imx31_address(nand, 0x00);
-           retval |= do_data_output(nand);
-           if (retval != ERROR_OK)
-               {
-                   LOG_ERROR (get_status_register_err_msg);
-                   return retval;
-               }
-           target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
-           if (nand_status_content & 0x0001)
-               {
-                   /*
-                    * is host-big-endian correctly ??
-                    */
-                   return ERROR_NAND_OPERATION_FAILED;
-               }
-       }
-       }
-       return ERROR_OK;
-}
-
-static int imx31_read_page (struct nand_device *nand, uint32_t page,
-                           uint8_t * data, uint32_t data_size, uint8_t * oob,
-                           uint32_t oob_size)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-
-       if (data_size % 2)
-       {
-           LOG_ERROR (data_block_size_err_msg, data_size);
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-       if (oob_size % 2)
-       {
-           LOG_ERROR (data_block_size_err_msg, oob_size);
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       {
-       /*
-        * validate target state
-        */
-       int retval;
-       retval = validate_target_state(nand);
-       if (retval != ERROR_OK)
-           {
-               return retval;
-           }
-       }
-       {
-       int retval = ERROR_OK;
-       retval |= imx31_command(nand, NAND_CMD_READ0);
-       retval |= imx31_address(nand, 0x00);
-       retval |= imx31_address(nand, page & 0xff);
-       retval |= imx31_address(nand, (page >> 8) & 0xff);
-       if (nand->address_cycles >= 4)
-           {
-               retval |= imx31_address(nand, (page >> 16) & 0xff);
-               if (nand->address_cycles >= 5)
-                   {
-                       retval |= imx31_address(nand, (page >> 24) & 0xff);
-                       retval |= imx31_command(nand, NAND_CMD_READSTART);
-                   }
-           }
-       retval |= do_data_output (nand);
-       if (retval != ERROR_OK)
-           {
-               return retval;
-           }
-
-       if (data)
-           {
-               target_read_buffer (target, MX3_NF_MAIN_BUFFER0, data_size,
-                                   data);
-           }
-       if (oob)
-           {
-               target_read_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
-                                   oob);
-           }
-       }
-       return ERROR_OK;
-}
-
-static int test_iomux_settings (struct target * target, uint32_t address,
-                               uint32_t mask, const char *text)
-{
-       uint32_t register_content;
-       target_read_u32 (target, address, &register_content);
-       if ((register_content & mask) != (0x12121212 & mask))
-       {
-           LOG_ERROR ("IOMUX for {%s} is bad", text);
-           return ERROR_FAIL;
-       }
-       return ERROR_OK;
-}
-
-static int initialize_nf_controller (struct nand_device *nand)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-       /*
-       * resets NAND flash controller in zero time ? I dont know.
-       */
-       target_write_u16 (target, MX3_NF_CFG1, MX3_NF_BIT_RESET_EN);
-       {
-       uint16_t work_mode;
-       work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */
-       if (target->endianness == TARGET_BIG_ENDIAN)
-           {
-               work_mode |= MX3_NF_BIT_BE_EN;
-           }
-       if (mx3_nf_info->flags.hw_ecc_enabled)
-           {
-               work_mode |= MX3_NF_BIT_ECC_EN;
-           }
-       target_write_u16 (target, MX3_NF_CFG1, work_mode);
-       }
-       /*
-       * unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock"
-       */
-       target_write_u16 (target, MX3_NF_BUFCFG, 2);
-       {
-       uint16_t temp;
-       target_read_u16 (target, MX3_NF_FWP, &temp);
-       if ((temp & 0x0007) == 1)
-           {
-               LOG_ERROR ("NAND flash is tight-locked, reset needed");
-               return ERROR_FAIL;
-           }
-
-       }
-       /*
-       * unlock NAND flash for write
-       */
-       target_write_u16 (target, MX3_NF_FWP, 4);
-       target_write_u16 (target, MX3_NF_LOCKSTART, 0x0000);
-       target_write_u16 (target, MX3_NF_LOCKEND, 0xFFFF);
-       /*
-       * 0x0000 means that first SRAM buffer @0xB800_0000 will be used
-       */
-       target_write_u16 (target, MX3_NF_BUFADDR, 0x0000);
-       /*
-       * address of SRAM buffer
-       */
-       in_sram_address = MX3_NF_MAIN_BUFFER0;
-       sign_of_sequental_byte_read = 0;
-       return ERROR_OK;
-}
-
-static int get_next_byte_from_sram_buffer (struct target * target, uint8_t * value)
-{
-       static uint8_t even_byte = 0;
-       /*
-       * host-big_endian ??
-       */
-       if (sign_of_sequental_byte_read == 0)
-       {
-           even_byte = 0;
-       }
-       if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR)
-       {
-           LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
-           *value = 0;
-           sign_of_sequental_byte_read = 0;
-           even_byte = 0;
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-       else
-       {
-           uint16_t temp;
-           target_read_u16 (target, in_sram_address, &temp);
-           if (even_byte)
-               {
-                   *value = temp >> 8;
-                   even_byte = 0;
-                   in_sram_address += 2;
-               }
-           else
-               {
-                   *value = temp & 0xff;
-                   even_byte = 1;
-               }
-       }
-       sign_of_sequental_byte_read = 1;
-       return ERROR_OK;
-}
-
-static int get_next_halfword_from_sram_buffer (struct target * target,
-                                              uint16_t * value)
-{
-       if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR)
-       {
-           LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
-           *value = 0;
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-       else
-       {
-           target_read_u16 (target, in_sram_address, value);
-           in_sram_address += 2;
-       }
-       return ERROR_OK;
-}
-
-static int poll_for_complete_op (struct target * target, const char *text)
-{
-       uint16_t poll_complete_status;
-       for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++)
-       {
-           usleep (25);
-           target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
-           if (poll_complete_status & MX3_NF_BIT_OP_DONE)
-               {
-                   break;
-               }
-       }
-       if (!(poll_complete_status & MX3_NF_BIT_OP_DONE))
-       {
-           LOG_ERROR ("%s sending timeout", text);
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-       return ERROR_OK;
-}
-
-static int validate_target_state (struct nand_device *nand)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-           LOG_ERROR (target_not_halted_err_msg);
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       if (mx3_nf_info->flags.target_little_endian !=
-       (target->endianness == TARGET_LITTLE_ENDIAN))
-       {
-           /*
-            * endianness changed after NAND controller probed
-            */
-           return ERROR_NAND_OPERATION_FAILED;
-       }
-       return ERROR_OK;
-}
-
-static int do_data_output (struct nand_device *nand)
-{
-       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
-       struct target *target = mx3_nf_info->target;
-       switch (mx3_nf_info->fin)
-       {
-           case MX3_NF_FIN_DATAOUT:
-               /*
-                * start data output operation (set MX3_NF_BIT_OP_DONE==0)
-                */
-               target_write_u16 (target, MX3_NF_CFG2,
-                                 MX3_NF_BIT_DATAOUT_TYPE (mx3_nf_info->
-                                                          optype));
-               {
-                   int poll_result;
-                   poll_result = poll_for_complete_op (target, "data output");
-                   if (poll_result != ERROR_OK)
-                       {
-                           return poll_result;
-                       }
-               }
-               mx3_nf_info->fin = MX3_NF_FIN_NONE;
-               /*
-                * ECC stuff
-                */
-               if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE)
-                   && mx3_nf_info->flags.hw_ecc_enabled)
-                   {
-                       uint16_t ecc_status;
-                       target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
-                       switch (ecc_status & 0x000c)
-                           {
-                               case 1 << 2:
-                                   LOG_DEBUG
-                                       ("main area readed with 1 (correctable) error");
-                                   break;
-                               case 2 << 2:
-                                   LOG_DEBUG
-                                       ("main area readed with more than 1 (incorrectable) error");
-                                   return ERROR_NAND_OPERATION_FAILED;
-                                   break;
-                           }
-                       switch (ecc_status & 0x0003)
-                           {
-                               case 1:
-                                   LOG_DEBUG
-                                       ("spare area readed with 1 (correctable) error");
-                                   break;
-                               case 2:
-                                   LOG_DEBUG
-                                       ("main area readed with more than 1 (incorrectable) error");
-                                   return ERROR_NAND_OPERATION_FAILED;
-                                   break;
-                           }
-                   }
-               break;
-           case MX3_NF_FIN_NONE:
-               break;
-       }
-       return ERROR_OK;
-}
-
-struct nand_flash_controller imx31_nand_flash_controller = {
-               .name = "imx31",
-               .nand_device_command = &imx31_nand_device_command,
-               .init = &imx31_init,
-               .reset = &imx31_reset,
-               .command = &imx31_command,
-               .address = &imx31_address,
-               .write_data = &imx31_write_data,
-               .read_data = &imx31_read_data,
-               .write_page = &imx31_write_page,
-               .read_page = &imx31_read_page,
-               .controller_ready = &imx31_controller_ready,
-               .nand_ready = &imx31_nand_ready,
-       };
diff --git a/src/flash/mx3_nand.h b/src/flash/mx3_nand.h
deleted file mode 100644 (file)
index ddec92c..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-
-/***************************************************************************
- *   Copyright (C) 2009 by Alexei Babich                                   *
- *   Rezonans plc., Chelyabinsk, Russia                                    *
- *   impatt@mail.ru                                                        *
- *                                                                         *
- *   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.             *
- ***************************************************************************/
-
-/*
- * Freescale iMX3* OpenOCD NAND Flash controller support.
- *
- * Many thanks to Ben Dooks for writing s3c24xx driver.
- */
-#include <nand.h>
-
-#define                MX3_NF_BASE_ADDR                0xb8000000
-#define                MX3_NF_BUFSIZ                   (MX3_NF_BASE_ADDR + 0xe00)
-#define                MX3_NF_BUFADDR                  (MX3_NF_BASE_ADDR + 0xe04)
-#define                MX3_NF_FADDR                    (MX3_NF_BASE_ADDR + 0xe06)
-#define                MX3_NF_FCMD                             (MX3_NF_BASE_ADDR + 0xe08)
-#define                MX3_NF_BUFCFG                   (MX3_NF_BASE_ADDR + 0xe0a)
-#define                MX3_NF_ECCSTATUS                        (MX3_NF_BASE_ADDR + 0xe0c)
-#define                MX3_NF_ECCMAINPOS                       (MX3_NF_BASE_ADDR + 0xe0e)
-#define                MX3_NF_ECCSPAREPOS                      (MX3_NF_BASE_ADDR + 0xe10)
-#define                MX3_NF_FWP                      (MX3_NF_BASE_ADDR + 0xe12)
-#define                MX3_NF_LOCKSTART                        (MX3_NF_BASE_ADDR + 0xe14)
-#define                MX3_NF_LOCKEND                  (MX3_NF_BASE_ADDR + 0xe16)
-#define                MX3_NF_FWPSTATUS                        (MX3_NF_BASE_ADDR + 0xe18)
- /*
-  * all bits not marked as self-clearing bit
-  */
-#define                MX3_NF_CFG1                     (MX3_NF_BASE_ADDR + 0xe1a)
-#define                MX3_NF_CFG2                     (MX3_NF_BASE_ADDR + 0xe1c)
-
-#define                MX3_NF_MAIN_BUFFER0             (MX3_NF_BASE_ADDR + 0x0000)
-#define                MX3_NF_MAIN_BUFFER1             (MX3_NF_BASE_ADDR + 0x0200)
-#define                MX3_NF_MAIN_BUFFER2             (MX3_NF_BASE_ADDR + 0x0400)
-#define                MX3_NF_MAIN_BUFFER3             (MX3_NF_BASE_ADDR + 0x0600)
-#define                MX3_NF_SPARE_BUFFER0    (MX3_NF_BASE_ADDR + 0x0800)
-#define                MX3_NF_SPARE_BUFFER1    (MX3_NF_BASE_ADDR + 0x0810)
-#define                MX3_NF_SPARE_BUFFER2    (MX3_NF_BASE_ADDR + 0x0820)
-#define                MX3_NF_SPARE_BUFFER3    (MX3_NF_BASE_ADDR + 0x0830)
-#define                MX3_NF_MAIN_BUFFER_LEN  512
-#define                MX3_NF_SPARE_BUFFER_LEN 16
-#define                MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2)
-
-/* bits in MX3_NF_CFG1 register */
-#define                MX3_NF_BIT_SPARE_ONLY_EN        (1<<2)
-#define                MX3_NF_BIT_ECC_EN                       (1<<3)
-#define                MX3_NF_BIT_INT_DIS                      (1<<4)
-#define                MX3_NF_BIT_BE_EN                        (1<<5)
-#define                MX3_NF_BIT_RESET_EN                     (1<<6)
-#define                MX3_NF_BIT_FORCE_CE                     (1<<7)
-
-/* bits in MX3_NF_CFG2 register */
-
-/*Flash Command Input*/
-#define                MX3_NF_BIT_OP_FCI                       (1<<0)
- /*
-  * Flash Address Input
-  */
-#define                MX3_NF_BIT_OP_FAI                       (1<<1)
- /*
-  * Flash Data Input
-  */
-#define                MX3_NF_BIT_OP_FDI                       (1<<2)
-
-/* see "enum mx_dataout_type" below */
-#define                MX3_NF_BIT_DATAOUT_TYPE(x)      ((x)<<3)
-#define                MX3_NF_BIT_OP_DONE                      (1<<15)
-
-#define                MX3_CCM_CGR2            0x53f80028
-#define                MX3_GPR                         0x43fac008
-#define                MX3_PCSR                        0x53f8000c
-
-enum mx_dataout_type
-{
-       MX3_NF_DATAOUT_PAGE = 1,
-       MX3_NF_DATAOUT_NANDID = 2,
-       MX3_NF_DATAOUT_NANDSTATUS = 4,
-};
-enum mx_nf_finalize_action
-{
-       MX3_NF_FIN_NONE,
-       MX3_NF_FIN_DATAOUT,
-};
-
-struct mx3_nf_flags
-{
-       unsigned host_little_endian:1;
-       unsigned target_little_endian:1;
-       unsigned nand_readonly:1;
-       unsigned one_kb_sram:1;
-       unsigned hw_ecc_enabled:1;
-};
-
-struct mx3_nf_controller
-{
-       struct target *target;
-       enum mx_dataout_type optype;
-       enum mx_nf_finalize_action fin;
-       struct mx3_nf_flags flags;
-};
diff --git a/src/flash/nand/Makefile.am b/src/flash/nand/Makefile.am
new file mode 100644 (file)
index 0000000..e95717e
--- /dev/null
@@ -0,0 +1,27 @@
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/src/flash \
+       -I$(top_srcdir)/src/helper \
+       -I$(top_srcdir)/src/jtag \
+       -I$(top_srcdir)/src/target
+
+noinst_LTLIBRARIES = libocdflashnand.la
+
+libocdflashnand_la_SOURCES = \
+       nonce.c \
+       davinci.c \
+       lpc3180.c \
+       mx3.c \
+       orion.c \
+       s3c24xx.c \
+       s3c2410.c \
+       s3c2412.c \
+       s3c2440.c \
+       s3c2443.c
+
+noinst_HEADERS = \
+       lpc3180.h \
+       mx3.h \
+       s3c24xx.h \
+       s3c24xx_regs.h
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/flash/nand/davinci.c b/src/flash/nand/davinci.c
new file mode 100644 (file)
index 0000000..72cd378
--- /dev/null
@@ -0,0 +1,756 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by David Brownell                                  *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+/*
+ * DaVinci family NAND controller support for OpenOCD.
+ *
+ * This driver uses hardware ECC (1-bit or 4-bit) unless
+ * the chip is accessed in "raw" mode.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm_nandio.h"
+
+
+enum ecc {
+       HWECC1,         /* all controllers support 1-bit ECC */
+       HWECC4,         /* newer chips also have 4-bit ECC hardware */
+       HWECC4_INFIX,   /* avoid this layout, except maybe for boot code */
+};
+
+struct davinci_nand {
+       struct target   *target;
+
+       uint8_t         chipsel;        /* chipselect 0..3 == CS2..CS5 */
+       uint8_t         eccmode;
+
+       /* Async EMIF controller base */
+       uint32_t                aemif;
+
+       /* NAND chip addresses */
+       uint32_t                data;           /* without CLE or ALE */
+       uint32_t                cmd;            /* with CLE */
+       uint32_t                addr;           /* with ALE */
+
+       /* write acceleration */
+       struct arm_nand_data    io;
+
+       /* page i/o for the relevant flavor of hardware ECC */
+       int (*read_page)(struct nand_device *nand, uint32_t page,
+                       uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+       int (*write_page)(struct nand_device *nand, uint32_t page,
+                       uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+};
+
+#define NANDFCR                0x60            /* flash control register */
+#define NANDFSR                0x64            /* flash status register */
+#define NANDFECC       0x70            /* 1-bit ECC data, CS0, 1st of 4 */
+#define NAND4BITECCLOAD        0xbc            /* 4-bit ECC, load saved values */
+#define NAND4BITECC    0xc0            /* 4-bit ECC data, 1st of 4 */
+#define NANDERRADDR    0xd0            /* 4-bit ECC err addr, 1st of 2 */
+#define NANDERRVAL     0xd8            /* 4-bit ECC err value, 1st of 2 */
+
+static int halted(struct target *target, const char *label)
+{
+       if (target->state == TARGET_HALTED)
+               return true;
+
+       LOG_ERROR("Target must be halted to use NAND controller (%s)", label);
+       return false;
+}
+
+static int davinci_init(struct nand_device *nand)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+       uint32_t nandfcr;
+
+       if (!halted(target, "init"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       /* We require something else to have configured AEMIF to talk
+        * to NAND chip in this range (including timings and width).
+        */
+       target_read_u32(target, info->aemif + NANDFCR, &nandfcr);
+       if (!(nandfcr & (1 << info->chipsel))) {
+               LOG_ERROR("chip address %08" PRIx32 " not NAND-enabled?", info->data);
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       /* REVISIT verify:  AxCR must be in 8-bit mode, since that's all we
+        * tested.  16 bit support should work too; but not with 4-bit ECC.
+        */
+
+       return ERROR_OK;
+}
+
+static int davinci_reset(struct nand_device *nand)
+{
+       return ERROR_OK;
+}
+
+static int davinci_nand_ready(struct nand_device *nand, int timeout)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+       uint32_t nandfsr;
+
+       /* NOTE: return code is zero/error, else success; not ERROR_* */
+
+       if (!halted(target, "ready"))
+               return 0;
+
+       do {
+               target_read_u32(target, info->aemif + NANDFSR, &nandfsr);
+
+               if (nandfsr & 0x01)
+                       return 1;
+
+               alive_sleep(1);
+       } while (timeout-- > 0);
+
+       return 0;
+}
+
+static int davinci_command(struct nand_device *nand, uint8_t command)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+
+       if (!halted(target, "command"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       target_write_u8(target, info->cmd, command);
+       return ERROR_OK;
+}
+
+static int davinci_address(struct nand_device *nand, uint8_t address)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+
+       if (!halted(target, "address"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       target_write_u8(target, info->addr, address);
+       return ERROR_OK;
+}
+
+static int davinci_write_data(struct nand_device *nand, uint16_t data)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+
+       if (!halted(target, "write_data"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       target_write_u8(target, info->data, data);
+       return ERROR_OK;
+}
+
+static int davinci_read_data(struct nand_device *nand, void *data)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+
+       if (!halted(target, "read_data"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       target_read_u8(target, info->data, data);
+       return ERROR_OK;
+}
+
+/* REVISIT a bit of native code should let block reads be MUCH faster */
+
+static int davinci_read_block_data(struct nand_device *nand,
+               uint8_t *data, int data_size)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+       uint32_t nfdata = info->data;
+       uint32_t tmp;
+
+       if (!halted(target, "read_block"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       while (data_size >= 4) {
+               target_read_u32(target, nfdata, &tmp);
+
+               data[0] = tmp;
+               data[1] = tmp >> 8;
+               data[2] = tmp >> 16;
+               data[3] = tmp >> 24;
+
+               data_size -= 4;
+               data += 4;
+       }
+
+       while (data_size > 0) {
+               target_read_u8(target, nfdata, data);
+
+               data_size -= 1;
+               data += 1;
+       }
+
+       return ERROR_OK;
+}
+
+static int davinci_write_block_data(struct nand_device *nand,
+               uint8_t *data, int data_size)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+       uint32_t nfdata = info->data;
+       uint32_t tmp;
+       int status;
+
+       if (!halted(target, "write_block"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       /* try the fast way first */
+       status = arm_nandwrite(&info->io, data, data_size);
+       if (status != ERROR_NAND_NO_BUFFER)
+               return status;
+
+       /* else do it slowly */
+       while (data_size >= 4) {
+               tmp = le_to_h_u32(data);
+               target_write_u32(target, nfdata, tmp);
+
+               data_size -= 4;
+               data += 4;
+       }
+
+       while (data_size > 0) {
+               target_write_u8(target, nfdata, *data);
+
+               data_size -= 1;
+               data += 1;
+       }
+
+       return ERROR_OK;
+}
+
+static int davinci_write_page(struct nand_device *nand, uint32_t page,
+               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       uint8_t *ooballoc = NULL;
+       int status;
+
+       if (!nand->device)
+               return ERROR_NAND_DEVICE_NOT_PROBED;
+       if (!halted(info->target, "write_page"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       /* Always write both data and OOB ... we are not "raw" I/O! */
+       if (!data) {
+               LOG_ERROR("Missing NAND data; try 'nand raw_access enable'\n");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       /* If we're not given OOB, write 0xff where we don't write ECC codes. */
+       switch (nand->page_size) {
+       case 512:
+               oob_size = 16;
+               break;
+       case 2048:
+               oob_size = 64;
+               break;
+       case 4096:
+               oob_size = 128;
+               break;
+       default:
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       if (!oob) {
+               ooballoc = malloc(oob_size);
+               if (!ooballoc)
+                       return ERROR_NAND_OPERATION_FAILED;
+               oob = ooballoc;
+               memset(oob, 0x0ff, oob_size);
+       }
+
+       /* REVISIT avoid wasting SRAM:  unless nand->use_raw is set,
+        * use 512 byte chunks.  Read side support will often want
+        * to include oob_size ...
+        */
+       info->io.chunk_size = nand->page_size;
+
+       status = info->write_page(nand, page, data, data_size, oob, oob_size);
+       free(ooballoc);
+       return status;
+}
+
+static int davinci_read_page(struct nand_device *nand, uint32_t page,
+               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+{
+       struct davinci_nand *info = nand->controller_priv;
+
+       if (!nand->device)
+               return ERROR_NAND_DEVICE_NOT_PROBED;
+       if (!halted(info->target, "read_page"))
+               return ERROR_NAND_OPERATION_FAILED;
+
+       return info->read_page(nand, page, data, data_size, oob, oob_size);
+}
+
+static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_t page)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+       int page3 = nand->address_cycles - (nand->page_size == 512);
+
+       /* write command ({page,otp}x{read,program} */
+       target_write_u8(target, info->cmd, cmd);
+
+       /* column address (beginning-of-page) */
+       target_write_u8(target, info->addr, 0);
+       if (nand->page_size > 512)
+               target_write_u8(target, info->addr, 0);
+
+       /* page address */
+       target_write_u8(target, info->addr, page);
+       target_write_u8(target, info->addr, page >> 8);
+       if (page3)
+               target_write_u8(target, info->addr, page >> 16);
+       if (page3 == 2)
+               target_write_u8(target, info->addr, page >> 24);
+}
+
+static int davinci_writepage_tail(struct nand_device *nand,
+               uint8_t *oob, uint32_t oob_size)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+       uint8_t status;
+
+       if (oob_size)
+               davinci_write_block_data(nand, oob, oob_size);
+
+       /* non-cachemode page program */
+       target_write_u8(target, info->cmd, NAND_CMD_PAGEPROG);
+
+       if (!davinci_nand_ready(nand, 100))
+               return ERROR_NAND_OPERATION_TIMEOUT;
+
+       if (nand_read_status(nand, &status) != ERROR_OK) {
+               LOG_ERROR("couldn't read status");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (status & NAND_STATUS_FAIL) {
+               LOG_ERROR("write operation failed, status: 0x%02x", status);
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+/*
+ * All DaVinci family chips support 1-bit ECC on a per-chipselect basis.
+ */
+static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
+               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+{
+       unsigned oob_offset;
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+       const uint32_t fcr_addr = info->aemif + NANDFCR;
+       const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel);
+       uint32_t fcr, ecc1;
+
+       /* Write contiguous ECC bytes starting at specified offset.
+        * NOTE: Linux reserves twice as many bytes as we need; and
+        * for 16-bit OOB, those extra bytes are discontiguous.
+        */
+       switch (nand->page_size) {
+       case 512:
+               oob_offset = 0;
+               break;
+       case 2048:
+               oob_offset = 40;
+               break;
+       default:
+               oob_offset = 80;
+               break;
+       }
+
+       davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
+
+       /* scrub any old ECC state */
+       target_read_u32(target, ecc1_addr, &ecc1);
+
+       target_read_u32(target, fcr_addr, &fcr);
+       fcr |= 1 << (8 + info->chipsel);
+
+       do {
+               /* set "start csX 1bit ecc" bit */
+               target_write_u32(target, fcr_addr, fcr);
+
+               /* write 512 bytes */
+               davinci_write_block_data(nand, data, 512);
+               data += 512;
+               data_size -= 512;
+
+               /* read the ecc, pack to 3 bytes, and invert so the ecc
+                * in an erased block is correct
+                */
+               target_read_u32(target, ecc1_addr, &ecc1);
+               ecc1 = (ecc1 & 0x0fff) | ((ecc1 & 0x0fff0000) >> 4);
+               ecc1 = ~ecc1;
+
+               /* save correct ECC code into oob data */
+               oob[oob_offset++] = (uint8_t)(ecc1);
+               oob[oob_offset++] = (uint8_t)(ecc1 >> 8);
+               oob[oob_offset++] = (uint8_t)(ecc1 >> 16);
+
+       } while (data_size);
+
+       /* write OOB into spare area */
+       return davinci_writepage_tail(nand, oob, oob_size);
+}
+
+/*
+ * Preferred "new style" ECC layout for use with 4-bit ECC.  This somewhat
+ * slows down large page reads done with error correction (since the OOB
+ * is read first, so its ECC data can be used incrementally), but the
+ * manufacturer bad block markers are safe.  Contrast:  old "infix" style.
+ */
+static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
+               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+{
+       static const uint8_t ecc512[] = {
+               0, 1, 2, 3, 4, /* 5== mfr badblock */
+               6, 7, /* 8..12 for BBT or JFFS2 */ 13, 14, 15,
+       };
+       static const uint8_t ecc2048[] = {
+               24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+               34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+               44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+               54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+       };
+       static const uint8_t ecc4096[] = {
+                48,  49,  50,  51,  52,  53,  54,  55,  56,  57,
+                58,  59,  60,  61,  62,  63,  64,  65,  66,  67,
+                68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
+                78,  79,  80,  81,  82,  83,  84,  85,  86,  87,
+                88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
+                98,  99, 100, 101, 102, 103, 104, 105, 106, 107,
+               108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+               118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+       };
+
+       struct davinci_nand *info = nand->controller_priv;
+       const uint8_t *l;
+       struct target *target = info->target;
+       const uint32_t fcr_addr = info->aemif + NANDFCR;
+       const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
+       uint32_t fcr, ecc4;
+
+       /* Use the same ECC layout Linux uses.  For small page chips
+        * it's a bit cramped.
+        *
+        * NOTE:  at this writing, 4KB pages have issues in Linux
+        * because they need more than 64 bytes of ECC data, which
+        * the standard ECC logic can't handle.
+        */
+       switch (nand->page_size) {
+       case 512:
+               l = ecc512;
+               break;
+       case 2048:
+               l = ecc2048;
+               break;
+       default:
+               l = ecc4096;
+               break;
+       }
+
+       davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
+
+       /* scrub any old ECC state */
+       target_read_u32(target, info->aemif + NANDERRVAL, &ecc4);
+
+       target_read_u32(target, fcr_addr, &fcr);
+       fcr &= ~(0x03 << 4);
+       fcr |= (1 << 12) | (info->chipsel << 4);
+
+       do {
+               uint32_t raw_ecc[4], *p;
+               int i;
+
+               /* start 4bit ecc on csX */
+               target_write_u32(target, fcr_addr, fcr);
+
+               /* write 512 bytes */
+               davinci_write_block_data(nand, data, 512);
+               data += 512;
+               data_size -= 512;
+
+               /* read the ecc, then save it into 10 bytes in the oob */
+               for (i = 0; i < 4; i++) {
+                       target_read_u32(target, ecc4_addr + 4 * i, &raw_ecc[i]);
+                       raw_ecc[i] &= 0x03ff03ff;
+               }
+               for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
+                       oob[*l++] =   p[0]        & 0xff;
+                       oob[*l++] = ((p[0] >>  8) & 0x03) | ((p[0] >> 14) & 0xfc);
+                       oob[*l++] = ((p[0] >> 22) & 0x0f) | ((p[1] <<  4) & 0xf0);
+                       oob[*l++] = ((p[1] >>  4) & 0x3f) | ((p[1] >> 10) & 0xc0);
+                       oob[*l++] =  (p[1] >> 18) & 0xff;
+               }
+
+       } while (data_size);
+
+       /* write OOB into spare area */
+       return davinci_writepage_tail(nand, oob, oob_size);
+}
+
+/*
+ * "Infix" OOB ... like Linux ECC_HW_SYNDROME.  Avoided because it trashes
+ * manufacturer bad block markers, except on small page chips.  Once you
+ * write to a page using this scheme, you need specialized code to update
+ * it (code which ignores now-invalid bad block markers).
+ *
+ * This is needed *only* to support older firmware.  Older ROM Boot Loaders
+ * need it to read their second stage loader (UBL) into SRAM, but from then
+ * on the whole system can use the cleaner non-infix layouts.  Systems with
+ * older second stage loaders (ABL/U-Boot, etc) or other system software
+ * (MVL 4.x/5.x kernels, filesystems, etc) may need it more generally.
+ */
+static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
+               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+{
+       struct davinci_nand *info = nand->controller_priv;
+       struct target *target = info->target;
+       const uint32_t fcr_addr = info->aemif + NANDFCR;
+       const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
+       uint32_t fcr, ecc4;
+
+       davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
+
+       /* scrub any old ECC state */
+       target_read_u32(target, info->aemif + NANDERRVAL, &ecc4);
+
+       target_read_u32(target, fcr_addr, &fcr);
+       fcr &= ~(0x03 << 4);
+       fcr |= (1 << 12) | (info->chipsel << 4);
+
+       do {
+               uint32_t raw_ecc[4], *p;
+               uint8_t *l;
+               int i;
+
+               /* start 4bit ecc on csX */
+               target_write_u32(target, fcr_addr, fcr);
+
+               /* write 512 bytes */
+               davinci_write_block_data(nand, data, 512);
+               data += 512;
+               data_size -= 512;
+
+               /* read the ecc */
+               for (i = 0; i < 4; i++) {
+                       target_read_u32(target, ecc4_addr + 4 * i, &raw_ecc[i]);
+                       raw_ecc[i] &= 0x03ff03ff;
+               }
+
+               /* skip 6 bytes of prepad, then pack 10 packed ecc bytes */
+               for (i = 0, l = oob + 6, p = raw_ecc; i < 2; i++, p += 2) {
+                       *l++ =   p[0]        & 0xff;
+                       *l++ = ((p[0] >>  8) & 0x03) | ((p[0] >> 14) & 0xfc);
+                       *l++ = ((p[0] >> 22) & 0x0f) | ((p[1] <<  4) & 0xf0);
+                       *l++ = ((p[1] >>  4) & 0x3f) | ((p[1] >> 10) & 0xc0);
+                       *l++ =  (p[1] >> 18) & 0xff;
+               }
+
+               /* write this "out-of-band" data -- infix */
+               davinci_write_block_data(nand, oob, 16);
+               oob += 16;
+               oob_size -= 16;
+
+       } while (data_size);
+
+       /* the last data and OOB writes included the spare area */
+       return davinci_writepage_tail(nand, NULL, 0);
+}
+
+static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
+               uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+{
+       davinci_write_pagecmd(nand, NAND_CMD_READ0, page);
+
+       /* large page devices need a start command */
+       if (nand->page_size > 512)
+               davinci_command(nand, NAND_CMD_READSTART);
+
+       if (!davinci_nand_ready(nand, 100))
+               return ERROR_NAND_OPERATION_TIMEOUT;
+
+       /* NOTE:  not bothering to compute and use ECC data for now */
+
+       do {
+               /* write 512 bytes */
+               davinci_read_block_data(nand, data, 512);
+               data += 512;
+               data_size -= 512;
+
+               /* read this "out-of-band" data -- infix */
+               davinci_read_block_data(nand, oob, 16);
+               oob += 16;
+               oob_size -= 16;
+       } while (data_size);
+
+       return ERROR_OK;
+}
+
+NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
+{
+       struct davinci_nand *info;
+       struct target *target;
+       unsigned long chip, aemif;
+       enum ecc eccmode;
+       int chipsel;
+
+       /* arguments:
+        *  - "davinci"
+        *  - target
+        *  - nand chip address
+        *  - ecc mode
+        *  - aemif address
+        * Plus someday, optionally, ALE and CLE masks.
+        */
+       if (CMD_ARGC < 5) {
+               LOG_ERROR("parameters: %s target "
+                               "chip_addr hwecc_mode aemif_addr",
+                               CMD_ARGV[0]);
+               goto fail;
+       }
+
+       target = get_target(CMD_ARGV[1]);
+       if (!target) {
+               LOG_ERROR("invalid target %s", CMD_ARGV[1]);
+               goto fail;
+       }
+
+       COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
+       if (chip == 0) {
+               LOG_ERROR("Invalid NAND chip address %s", CMD_ARGV[2]);
+               goto fail;
+       }
+
+       if (strcmp(CMD_ARGV[3], "hwecc1") == 0)
+               eccmode = HWECC1;
+       else if (strcmp(CMD_ARGV[3], "hwecc4") == 0)
+               eccmode = HWECC4;
+       else if (strcmp(CMD_ARGV[3], "hwecc4_infix") == 0)
+               eccmode = HWECC4_INFIX;
+       else {
+               LOG_ERROR("Invalid ecc mode %s", CMD_ARGV[3]);
+               goto fail;
+       }
+
+       COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[4], aemif);
+       if (aemif == 0) {
+               LOG_ERROR("Invalid AEMIF controller address %s", CMD_ARGV[4]);
+               goto fail;
+       }
+
+       /* REVISIT what we'd *like* to do is look up valid ranges using
+        * target-specific declarations, and not even need to pass the
+        * AEMIF controller address.
+        */
+       if (aemif == 0x01e00000                 /* dm6446, dm357 */
+                       || aemif == 0x01e10000  /* dm335, dm355 */
+                       || aemif == 0x01d10000  /* dm365 */
+                       ) {
+               if (chip < 0x02000000 || chip >= 0x0a000000) {
+                       LOG_ERROR("NAND address %08lx out of range?", chip);
+                       goto fail;
+               }
+               chipsel = (chip - 0x02000000) >> 25;
+       } else {
+               LOG_ERROR("unrecognized AEMIF controller address %08lx", aemif);
+               goto fail;
+       }
+
+       info = calloc(1, sizeof *info);
+       if (info == NULL)
+               goto fail;
+
+       info->target = target;
+       info->eccmode = eccmode;
+       info->chipsel = chipsel;
+       info->aemif = aemif;
+       info->data = chip;
+       info->cmd = chip | 0x10;
+       info->addr = chip | 0x08;
+
+       nand->controller_priv = info;
+
+       info->io.target = target;
+       info->io.data = info->data;
+
+       /* NOTE:  for now we don't do any error correction on read.
+        * Nothing else in OpenOCD currently corrects read errors,
+        * and in any case it's *writing* that we care most about.
+        */
+       info->read_page = nand_read_page_raw;
+
+       switch (eccmode) {
+       case HWECC1:
+               /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
+               info->write_page = davinci_write_page_ecc1;
+               break;
+       case HWECC4:
+               /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
+               info->write_page = davinci_write_page_ecc4;
+               break;
+       case HWECC4_INFIX:
+               /* Same 4-bit ECC HW, with problematic page/ecc layout */
+               info->read_page = davinci_read_page_ecc4infix;
+               info->write_page = davinci_write_page_ecc4infix;
+               break;
+       }
+
+       return ERROR_OK;
+
+fail:
+       return ERROR_NAND_OPERATION_FAILED;
+}
+
+struct nand_flash_controller davinci_nand_controller = {
+       .name                   = "davinci",
+       .nand_device_command    = davinci_nand_device_command,
+       .init                   = davinci_init,
+       .reset                  = davinci_reset,
+       .command                = davinci_command,
+       .address                = davinci_address,
+       .write_data             = davinci_write_data,
+       .read_data              = davinci_read_data,
+       .write_page             = davinci_write_page,
+       .read_page              = davinci_read_page,
+       .write_block_data       = davinci_write_block_data,
+       .read_block_data        = davinci_read_block_data,
+       .nand_ready             = davinci_nand_ready,
+};
diff --git a/src/flash/nand/lpc3180.c b/src/flash/nand/lpc3180.c
new file mode 100644 (file)
index 0000000..031e6b1
--- /dev/null
@@ -0,0 +1,910 @@
+/***************************************************************************
+ *   Copyright (C) 2007 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "lpc3180.h"
+#include "nand.h"
+
+static int lpc3180_reset(struct nand_device *nand);
+static int lpc3180_controller_ready(struct nand_device *nand, int timeout);
+
+/* nand device lpc3180 <target#> <oscillator_frequency>
+ */
+NAND_DEVICE_COMMAND_HANDLER(lpc3180_nand_device_command)
+{
+       if (CMD_ARGC < 3)
+       {
+               LOG_WARNING("incomplete 'lpc3180' nand flash configuration");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       struct target *target = get_target(CMD_ARGV[1]);
+       if (NULL == target)
+       {
+               LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       uint32_t osc_freq;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
+
+       struct lpc3180_nand_controller *lpc3180_info;
+       lpc3180_info = malloc(sizeof(struct lpc3180_nand_controller));
+       nand->controller_priv = lpc3180_info;
+
+       lpc3180_info->target = target;
+       lpc3180_info->osc_freq = osc_freq;
+
+       if ((lpc3180_info->osc_freq < 1000) || (lpc3180_info->osc_freq > 20000))
+       {
+               LOG_WARNING("LPC3180 oscillator frequency should be between 1000 and 20000 kHz, was %i", lpc3180_info->osc_freq);
+       }
+       lpc3180_info->selected_controller = LPC3180_NO_CONTROLLER;
+       lpc3180_info->sw_write_protection = 0;
+       lpc3180_info->sw_wp_lower_bound = 0x0;
+       lpc3180_info->sw_wp_upper_bound = 0x0;
+
+       return ERROR_OK;
+}
+
+static int lpc3180_pll(int fclkin, uint32_t pll_ctrl)
+{
+       int bypass = (pll_ctrl & 0x8000) >> 15;
+       int direct = (pll_ctrl & 0x4000) >> 14;
+       int feedback = (pll_ctrl & 0x2000) >> 13;
+       int p = (1 << ((pll_ctrl & 0x1800) >> 11) * 2);
+       int n = ((pll_ctrl & 0x0600) >> 9) + 1;
+       int m = ((pll_ctrl & 0x01fe) >> 1) + 1;
+       int lock = (pll_ctrl & 0x1);
+
+       if (!lock)
+               LOG_WARNING("PLL is not locked");
+
+       if (!bypass && direct)  /* direct mode */
+               return (m * fclkin) / n;
+
+       if (bypass && !direct)  /* bypass mode */
+               return fclkin / (2 * p);
+
+       if (bypass & direct)    /* direct bypass mode */
+               return fclkin;
+
+       if (feedback)                   /* integer mode */
+               return m * (fclkin / n);
+       else                                    /* non-integer mode */
+               return (m / (2 * p)) * (fclkin / n);
+}
+
+static float lpc3180_cycle_time(struct lpc3180_nand_controller *lpc3180_info)
+{
+       struct target *target = lpc3180_info->target;
+       uint32_t sysclk_ctrl, pwr_ctrl, hclkdiv_ctrl, hclkpll_ctrl;
+       int sysclk;
+       int hclk;
+       int hclk_pll;
+       float cycle;
+
+       /* calculate timings */
+
+       /* determine current SYSCLK (13'MHz or main oscillator) */
+       target_read_u32(target, 0x40004050, &sysclk_ctrl);
+
+       if ((sysclk_ctrl & 1) == 0)
+               sysclk = lpc3180_info->osc_freq;
+       else
+               sysclk = 13000;
+
+       /* determine selected HCLK source */
+       target_read_u32(target, 0x40004044, &pwr_ctrl);
+
+       if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
+       {
+               hclk = sysclk;
+       }
+       else
+       {
+               target_read_u32(target, 0x40004058, &hclkpll_ctrl);
+               hclk_pll = lpc3180_pll(sysclk, hclkpll_ctrl);
+
+               target_read_u32(target, 0x40004040, &hclkdiv_ctrl);
+
+               if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
+               {
+                       hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1);
+               }
+               else /* HCLK uses HCLK_PLL */
+               {
+                       hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3));
+               }
+       }
+
+       LOG_DEBUG("LPC3180 HCLK currently clocked at %i kHz", hclk);
+
+       cycle = (1.0 / hclk) * 1000000.0;
+
+       return cycle;
+}
+
+static int lpc3180_init(struct nand_device *nand)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+       int bus_width = nand->bus_width ? : 8;
+       int address_cycles = nand->address_cycles ? : 3;
+       int page_size = nand->page_size ? : 512;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       /* sanitize arguments */
+       if ((bus_width != 8) && (bus_width != 16))
+       {
+               LOG_ERROR("LPC3180 only supports 8 or 16 bit bus width, not %i", bus_width);
+               return ERROR_NAND_OPERATION_NOT_SUPPORTED;
+       }
+
+       /* The LPC3180 only brings out 8 bit NAND data bus, but the controller
+        * would support 16 bit, too, so we just warn about this for now
+        */
+       if (bus_width == 16)
+       {
+               LOG_WARNING("LPC3180 only supports 8 bit bus width");
+       }
+
+       /* inform calling code about selected bus width */
+       nand->bus_width = bus_width;
+
+       if ((address_cycles != 3) && (address_cycles != 4))
+       {
+               LOG_ERROR("LPC3180 only supports 3 or 4 address cycles, not %i", address_cycles);
+               return ERROR_NAND_OPERATION_NOT_SUPPORTED;
+       }
+
+       if ((page_size != 512) && (page_size != 2048))
+       {
+               LOG_ERROR("LPC3180 only supports 512 or 2048 byte pages, not %i", page_size);
+               return ERROR_NAND_OPERATION_NOT_SUPPORTED;
+       }
+
+       /* select MLC controller if none is currently selected */
+       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
+       {
+               LOG_DEBUG("no LPC3180 NAND flash controller selected, using default 'mlc'");
+               lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER;
+       }
+
+       if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+       {
+               uint32_t mlc_icr_value = 0x0;
+               float cycle;
+               int twp, twh, trp, treh, trhz, trbwb, tcea;
+
+               /* FLASHCLK_CTRL = 0x22 (enable clock for MLC flash controller) */
+               target_write_u32(target, 0x400040c8, 0x22);
+
+               /* MLC_CEH = 0x0 (Force nCE assert) */
+               target_write_u32(target, 0x200b804c, 0x0);
+
+               /* MLC_LOCK = 0xa25e (unlock protected registers) */
+               target_write_u32(target, 0x200b8044, 0xa25e);
+
+               /* MLC_ICR = configuration */
+               if (lpc3180_info->sw_write_protection)
+                       mlc_icr_value |= 0x8;
+               if (page_size == 2048)
+                       mlc_icr_value |= 0x4;
+               if (address_cycles == 4)
+                       mlc_icr_value |= 0x2;
+               if (bus_width == 16)
+                       mlc_icr_value |= 0x1;
+               target_write_u32(target, 0x200b8030, mlc_icr_value);
+
+               /* calculate NAND controller timings */
+               cycle = lpc3180_cycle_time(lpc3180_info);
+
+               twp = ((40 / cycle) + 1);
+               twh = ((20 / cycle) + 1);
+               trp = ((30 / cycle) + 1);
+               treh = ((15 / cycle) + 1);
+               trhz = ((30 / cycle) + 1);
+               trbwb = ((100 / cycle) + 1);
+               tcea = ((45 / cycle) + 1);
+
+               /* MLC_LOCK = 0xa25e (unlock protected registers) */
+               target_write_u32(target, 0x200b8044, 0xa25e);
+
+               /* MLC_TIME_REG */
+               target_write_u32(target, 0x200b8034, (twp & 0xf) | ((twh & 0xf) << 4) |
+                       ((trp & 0xf) << 8) | ((treh & 0xf) << 12) | ((trhz & 0x7) << 16) |
+                       ((trbwb & 0x1f) << 19) | ((tcea & 0x3) << 24));
+
+               lpc3180_reset(nand);
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+       {
+               float cycle;
+               int r_setup, r_hold, r_width, r_rdy;
+               int w_setup, w_hold, w_width, w_rdy;
+
+               /* FLASHCLK_CTRL = 0x05 (enable clock for SLC flash controller) */
+               target_write_u32(target, 0x400040c8, 0x05);
+
+               /* SLC_CFG = 0x (Force nCE assert, ECC enabled, WIDTH = bus_width) */
+               target_write_u32(target, 0x20020014, 0x28 | (bus_width == 16) ? 1 : 0);
+
+               /* calculate NAND controller timings */
+               cycle = lpc3180_cycle_time(lpc3180_info);
+
+               r_setup = w_setup = 0;
+               r_hold = w_hold = 10 / cycle;
+               r_width = 30 / cycle;
+               w_width = 40 / cycle;
+               r_rdy = w_rdy = 100 / cycle;
+
+               /* SLC_TAC: SLC timing arcs register */
+               target_write_u32(target, 0x2002002c, (r_setup & 0xf) | ((r_hold & 0xf) << 4) |
+                       ((r_width & 0xf) << 8) | ((r_rdy & 0xf) << 12) |  ((w_setup & 0xf) << 16) |
+                       ((w_hold & 0xf) << 20) | ((w_width & 0xf) << 24) | ((w_rdy & 0xf) << 28));
+
+               lpc3180_reset(nand);
+       }
+
+       return ERROR_OK;
+}
+
+static int lpc3180_reset(struct nand_device *nand)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
+       {
+               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+       {
+               /* MLC_CMD = 0xff (reset controller and NAND device) */
+               target_write_u32(target, 0x200b8000, 0xff);
+
+               if (!lpc3180_controller_ready(nand, 100))
+               {
+                       LOG_ERROR("LPC3180 NAND controller timed out after reset");
+                       return ERROR_NAND_OPERATION_TIMEOUT;
+               }
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+       {
+               /* SLC_CTRL = 0x6 (ECC_CLEAR, SW_RESET) */
+               target_write_u32(target, 0x20020010, 0x6);
+
+               if (!lpc3180_controller_ready(nand, 100))
+               {
+                       LOG_ERROR("LPC3180 NAND controller timed out after reset");
+                       return ERROR_NAND_OPERATION_TIMEOUT;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int lpc3180_command(struct nand_device *nand, uint8_t command)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
+       {
+               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+       {
+               /* MLC_CMD = command */
+               target_write_u32(target, 0x200b8000, command);
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+       {
+               /* SLC_CMD = command */
+               target_write_u32(target, 0x20020008, command);
+       }
+
+       return ERROR_OK;
+}
+
+static int lpc3180_address(struct nand_device *nand, uint8_t address)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
+       {
+               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+       {
+               /* MLC_ADDR = address */
+               target_write_u32(target, 0x200b8004, address);
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+       {
+               /* SLC_ADDR = address */
+               target_write_u32(target, 0x20020004, address);
+       }
+
+       return ERROR_OK;
+}
+
+static int lpc3180_write_data(struct nand_device *nand, uint16_t data)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
+       {
+               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+       {
+               /* MLC_DATA = data */
+               target_write_u32(target, 0x200b0000, data);
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+       {
+               /* SLC_DATA = data */
+               target_write_u32(target, 0x20020000, data);
+       }
+
+       return ERROR_OK;
+}
+
+static int lpc3180_read_data(struct nand_device *nand, void *data)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
+       {
+               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+       {
+               /* data = MLC_DATA, use sized access */
+               if (nand->bus_width == 8)
+               {
+                       uint8_t *data8 = data;
+                       target_read_u8(target, 0x200b0000, data8);
+               }
+               else if (nand->bus_width == 16)
+               {
+                       uint16_t *data16 = data;
+                       target_read_u16(target, 0x200b0000, data16);
+               }
+               else
+               {
+                       LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
+                       return ERROR_NAND_OPERATION_FAILED;
+               }
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+       {
+               uint32_t data32;
+
+               /* data = SLC_DATA, must use 32-bit access */
+               target_read_u32(target, 0x20020000, &data32);
+
+               if (nand->bus_width == 8)
+               {
+                       uint8_t *data8 = data;
+                       *data8 = data32 & 0xff;
+               }
+               else if (nand->bus_width == 16)
+               {
+                       uint16_t *data16 = data;
+                       *data16 = data32 & 0xffff;
+               }
+               else
+               {
+                       LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
+                       return ERROR_NAND_OPERATION_FAILED;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+       int retval;
+       uint8_t status;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
+       {
+               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+       {
+               uint8_t *page_buffer;
+               uint8_t *oob_buffer;
+               int quarter, num_quarters;
+
+               if (!data && oob)
+               {
+                       LOG_ERROR("LPC3180 MLC controller can't write OOB data only");
+                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
+               }
+
+               if (oob && (oob_size > 6))
+               {
+                       LOG_ERROR("LPC3180 MLC controller can't write more than 6 bytes of OOB data");
+                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
+               }
+
+               if (data_size > (uint32_t)nand->page_size)
+               {
+                       LOG_ERROR("data size exceeds page size");
+                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
+               }
+
+               /* MLC_CMD = sequential input */
+               target_write_u32(target, 0x200b8000, NAND_CMD_SEQIN);
+
+               page_buffer = malloc(512);
+               oob_buffer = malloc(6);
+
+               if (nand->page_size == 512)
+               {
+                       /* MLC_ADDR = 0x0 (one column cycle) */
+                       target_write_u32(target, 0x200b8004, 0x0);
+
+                       /* MLC_ADDR = row */
+                       target_write_u32(target, 0x200b8004, page & 0xff);
+                       target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
+
+                       if (nand->address_cycles == 4)
+                               target_write_u32(target, 0x200b8004, (page >> 16) & 0xff);
+               }
+               else
+               {
+                       /* MLC_ADDR = 0x0 (two column cycles) */
+                       target_write_u32(target, 0x200b8004, 0x0);
+                       target_write_u32(target, 0x200b8004, 0x0);
+
+                       /* MLC_ADDR = row */
+                       target_write_u32(target, 0x200b8004, page & 0xff);
+                       target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
+               }
+
+               /* when using the MLC controller, we have to treat a large page device
+                * as being made out of four quarters, each the size of a small page device
+                */
+               num_quarters = (nand->page_size == 2048) ? 4 : 1;
+
+               for (quarter = 0; quarter < num_quarters; quarter++)
+               {
+                       int thisrun_data_size = (data_size > 512) ? 512 : data_size;
+                       int thisrun_oob_size = (oob_size > 6) ? 6 : oob_size;
+
+                       memset(page_buffer, 0xff, 512);
+                       if (data)
+                       {
+                               memcpy(page_buffer, data, thisrun_data_size);
+                               data_size -= thisrun_data_size;
+                               data += thisrun_data_size;
+                       }
+
+                       memset(oob_buffer, 0xff, (nand->page_size == 512) ? 6 : 24);
+                       if (oob)
+                       {
+                               memcpy(page_buffer, oob, thisrun_oob_size);
+                               oob_size -= thisrun_oob_size;
+                               oob += thisrun_oob_size;
+                       }
+
+                       /* write MLC_ECC_ENC_REG to start encode cycle */
+                       target_write_u32(target, 0x200b8008, 0x0);
+
+                       target_write_memory(target, 0x200a8000, 4, 128, page_buffer + (quarter * 512));
+                       target_write_memory(target, 0x200a8000, 1, 6, oob_buffer + (quarter * 6));
+
+                       /* write MLC_ECC_AUTO_ENC_REG to start auto encode */
+                       target_write_u32(target, 0x200b8010, 0x0);
+
+                       if (!lpc3180_controller_ready(nand, 1000))
+                       {
+                               LOG_ERROR("timeout while waiting for completion of auto encode cycle");
+                               return ERROR_NAND_OPERATION_FAILED;
+                       }
+               }
+
+               /* MLC_CMD = auto program command */
+               target_write_u32(target, 0x200b8000, NAND_CMD_PAGEPROG);
+
+               if ((retval = nand_read_status(nand, &status)) != ERROR_OK)
+               {
+                       LOG_ERROR("couldn't read status");
+                       return ERROR_NAND_OPERATION_FAILED;
+               }
+
+               if (status & NAND_STATUS_FAIL)
+               {
+                       LOG_ERROR("write operation didn't pass, status: 0x%2.2x", status);
+                       return ERROR_NAND_OPERATION_FAILED;
+               }
+
+               free(page_buffer);
+               free(oob_buffer);
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+       {
+               return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
+       }
+
+       return ERROR_OK;
+}
+
+static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
+       {
+               LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+       {
+               uint8_t *page_buffer;
+               uint8_t *oob_buffer;
+               uint32_t page_bytes_done = 0;
+               uint32_t oob_bytes_done = 0;
+               uint32_t mlc_isr;
+
+#if 0
+               if (oob && (oob_size > 6))
+               {
+                       LOG_ERROR("LPC3180 MLC controller can't read more than 6 bytes of OOB data");
+                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
+               }
+#endif
+
+               if (data_size > (uint32_t)nand->page_size)
+               {
+                       LOG_ERROR("data size exceeds page size");
+                       return ERROR_NAND_OPERATION_NOT_SUPPORTED;
+               }
+
+               if (nand->page_size == 2048)
+               {
+                       page_buffer = malloc(2048);
+                       oob_buffer = malloc(64);
+               }
+               else
+               {
+                       page_buffer = malloc(512);
+                       oob_buffer = malloc(16);
+               }
+
+               if (!data && oob)
+               {
+                       /* MLC_CMD = Read OOB
+                        * we can use the READOOB command on both small and large page devices,
+                        * as the controller translates the 0x50 command to a 0x0 with appropriate
+                        * positioning of the serial buffer read pointer
+                        */
+                       target_write_u32(target, 0x200b8000, NAND_CMD_READOOB);
+               }
+               else
+               {
+                       /* MLC_CMD = Read0 */
+                       target_write_u32(target, 0x200b8000, NAND_CMD_READ0);
+               }
+
+               if (nand->page_size == 512)
+               {
+                       /* small page device */
+                       /* MLC_ADDR = 0x0 (one column cycle) */
+                       target_write_u32(target, 0x200b8004, 0x0);
+
+                       /* MLC_ADDR = row */
+                       target_write_u32(target, 0x200b8004, page & 0xff);
+                       target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
+
+                       if (nand->address_cycles == 4)
+                               target_write_u32(target, 0x200b8004, (page >> 16) & 0xff);
+               }
+               else
+               {
+                       /* large page device */
+                       /* MLC_ADDR = 0x0 (two column cycles) */
+                       target_write_u32(target, 0x200b8004, 0x0);
+                       target_write_u32(target, 0x200b8004, 0x0);
+
+                       /* MLC_ADDR = row */
+                       target_write_u32(target, 0x200b8004, page & 0xff);
+                       target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
+
+                       /* MLC_CMD = Read Start */
+                       target_write_u32(target, 0x200b8000, NAND_CMD_READSTART);
+               }
+
+               while (page_bytes_done < (uint32_t)nand->page_size)
+               {
+                       /* MLC_ECC_AUTO_DEC_REG = dummy */
+                       target_write_u32(target, 0x200b8014, 0xaa55aa55);
+
+                       if (!lpc3180_controller_ready(nand, 1000))
+                       {
+                               LOG_ERROR("timeout while waiting for completion of auto decode cycle");
+                               return ERROR_NAND_OPERATION_FAILED;
+                       }
+
+                       target_read_u32(target, 0x200b8048, &mlc_isr);
+
+                       if (mlc_isr & 0x8)
+                       {
+                               if (mlc_isr & 0x40)
+                               {
+                                       LOG_ERROR("uncorrectable error detected: 0x%2.2x", (unsigned)mlc_isr);
+                                       return ERROR_NAND_OPERATION_FAILED;
+                               }
+
+                               LOG_WARNING("%i symbol error detected and corrected", ((int)(((mlc_isr & 0x30) >> 4) + 1)));
+                       }
+
+                       if (data)
+                       {
+                               target_read_memory(target, 0x200a8000, 4, 128, page_buffer + page_bytes_done);
+                       }
+
+                       if (oob)
+                       {
+                               target_read_memory(target, 0x200a8000, 4, 4, oob_buffer + oob_bytes_done);
+                       }
+
+                       page_bytes_done += 512;
+                       oob_bytes_done += 16;
+               }
+
+               if (data)
+                       memcpy(data, page_buffer, data_size);
+
+               if (oob)
+                       memcpy(oob, oob_buffer, oob_size);
+
+               free(page_buffer);
+               free(oob_buffer);
+       }
+       else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+       {
+               return nand_read_page_raw(nand, page, data, data_size, oob, oob_size);
+       }
+
+       return ERROR_OK;
+}
+
+static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+       uint8_t status = 0x0;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       do
+       {
+               if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+               {
+                       /* Read MLC_ISR, wait for controller to become ready */
+                       target_read_u8(target, 0x200b8048, &status);
+
+                       if (status & 2)
+                               return 1;
+               }
+               else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+               {
+                       /* we pretend that the SLC controller is always ready */
+                       return 1;
+               }
+
+               alive_sleep(1);
+       } while (timeout-- > 0);
+
+       return 0;
+}
+
+static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
+{
+       struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
+       struct target *target = lpc3180_info->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       do
+       {
+               if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+               {
+                       uint8_t status = 0x0;
+
+                       /* Read MLC_ISR, wait for NAND flash device to become ready */
+                       target_read_u8(target, 0x200b8048, &status);
+
+                       if (status & 1)
+                               return 1;
+               }
+               else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
+               {
+                       uint32_t status = 0x0;
+
+                       /* Read SLC_STAT and check READY bit */
+                       target_read_u32(target, 0x20020018, &status);
+
+                       if (status & 1)
+                               return 1;
+               }
+
+               alive_sleep(1);
+       } while (timeout-- > 0);
+
+       return 0;
+}
+
+COMMAND_HANDLER(handle_lpc3180_select_command)
+{
+       struct lpc3180_nand_controller *lpc3180_info = NULL;
+       char *selected[] =
+       {
+               "no", "mlc", "slc"
+       };
+
+       if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       unsigned num;
+       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], num);
+       struct nand_device *nand = get_nand_device_by_num(num);
+       if (!nand)
+       {
+               command_print(CMD_CTX, "nand device '#%s' is out of bounds", CMD_ARGV[0]);
+               return ERROR_OK;
+       }
+
+       lpc3180_info = nand->controller_priv;
+
+       if (CMD_ARGC == 2)
+       {
+               if (strcmp(CMD_ARGV[1], "mlc") == 0)
+               {
+                       lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER;
+               }
+               else if (strcmp(CMD_ARGV[1], "slc") == 0)
+               {
+                       lpc3180_info->selected_controller = LPC3180_SLC_CONTROLLER;
+               }
+               else
+               {
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+       }
+
+       command_print(CMD_CTX, "%s controller selected", selected[lpc3180_info->selected_controller]);
+
+       return ERROR_OK;
+}
+
+static const struct command_registration lpc3180_exec_command_handlers[] = {
+       {
+               .name = "select",
+               .handler = &handle_lpc3180_select_command,
+               .mode = COMMAND_EXEC,
+               .help = "select <'mlc'|'slc'> controller (default is mlc)",
+               .usage = "<device_id> (mlc|slc)",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+static const struct command_registration lpc3180_command_handler[] = {
+       {
+               .name = "lpc3180",
+               .mode = COMMAND_ANY,
+               .help = "LPC3180 NAND flash controller commands",
+               .chain = lpc3180_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct nand_flash_controller lpc3180_nand_controller = {
+               .name = "lpc3180",
+               .commands = lpc3180_command_handler,
+               .nand_device_command = lpc3180_nand_device_command,
+               .init = lpc3180_init,
+               .reset = lpc3180_reset,
+               .command = lpc3180_command,
+               .address = lpc3180_address,
+               .write_data = lpc3180_write_data,
+               .read_data = lpc3180_read_data,
+               .write_page = lpc3180_write_page,
+               .read_page = lpc3180_read_page,
+               .controller_ready = lpc3180_controller_ready,
+               .nand_ready = lpc3180_nand_ready,
+       };
diff --git a/src/flash/nand/lpc3180.h b/src/flash/nand/lpc3180.h
new file mode 100644 (file)
index 0000000..0891ced
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************
+ *   Copyright (C) 2007 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef LPC3180_NAND_CONTROLLER_H
+#define LPC3180_NAND_CONTROLLER_H
+
+enum lpc3180_selected_controller
+{
+       LPC3180_NO_CONTROLLER,
+       LPC3180_MLC_CONTROLLER,
+       LPC3180_SLC_CONTROLLER,
+};
+
+struct lpc3180_nand_controller
+{
+       struct target *target;
+       int osc_freq;
+       enum lpc3180_selected_controller selected_controller;
+       int sw_write_protection;
+       uint32_t sw_wp_lower_bound;
+       uint32_t sw_wp_upper_bound;
+};
+
+#endif /*LPC3180_NAND_CONTROLLER_H */
diff --git a/src/flash/nand/mx3.c b/src/flash/nand/mx3.c
new file mode 100644 (file)
index 0000000..21577a6
--- /dev/null
@@ -0,0 +1,879 @@
+
+/***************************************************************************
+ *   Copyright (C) 2009 by Alexei Babich                                   *
+ *   Rezonans plc., Chelyabinsk, Russia                                    *
+ *   impatt@mail.ru                                                        *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+/*
+ * Freescale iMX3* OpenOCD NAND Flash controller support.
+ *
+ * Many thanks to Ben Dooks for writing s3c24xx driver.
+ */
+
+/*
+driver tested with STMicro NAND512W3A @imx31
+tested "nand probe #", "nand erase # 0 #", "nand dump # file 0 #", "nand write # file 0"
+get_next_halfword_from_sram_buffer() not tested
+*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mx3.h"
+
+static const char target_not_halted_err_msg[] =
+       "target must be halted to use mx3 NAND flash controller";
+static const char data_block_size_err_msg[] =
+       "minimal granularity is one half-word, %" PRId32 " is incorrect";
+static const char sram_buffer_bounds_err_msg[] =
+       "trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
+static const char get_status_register_err_msg[] = "can't get NAND status";
+static uint32_t in_sram_address;
+unsigned char sign_of_sequental_byte_read;
+
+static int test_iomux_settings (struct target * target, uint32_t value,
+                               uint32_t mask, const char *text);
+static int initialize_nf_controller (struct nand_device *nand);
+static int get_next_byte_from_sram_buffer (struct target * target, uint8_t * value);
+static int get_next_halfword_from_sram_buffer (struct target * target,
+                                              uint16_t * value);
+static int poll_for_complete_op (struct target * target, const char *text);
+static int validate_target_state (struct nand_device *nand);
+static int do_data_output (struct nand_device *nand);
+
+static int imx31_command (struct nand_device *nand, uint8_t command);
+static int imx31_address (struct nand_device *nand, uint8_t address);
+static int imx31_controller_ready (struct nand_device *nand, int tout);
+
+NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
+{
+       struct mx3_nf_controller *mx3_nf_info;
+       mx3_nf_info = malloc (sizeof (struct mx3_nf_controller));
+       if (mx3_nf_info == NULL)
+       {
+           LOG_ERROR ("no memory for nand controller");
+           return ERROR_FAIL;
+       }
+
+       nand->controller_priv = mx3_nf_info;
+
+       mx3_nf_info->target = get_target (CMD_ARGV[1]);
+       if (mx3_nf_info->target == NULL)
+       {
+           LOG_ERROR ("target '%s' not defined", CMD_ARGV[1]);
+           return ERROR_FAIL;
+       }
+       if (CMD_ARGC < 3)
+       {
+           LOG_ERROR ("use \"nand device imx31 target noecc|hwecc\"");
+           return ERROR_FAIL;
+       }
+       /*
+       * check hwecc requirements
+       */
+       {
+       int hwecc_needed;
+       hwecc_needed = strcmp (CMD_ARGV[2], "hwecc");
+       if (hwecc_needed == 0)
+           {
+               mx3_nf_info->flags.hw_ecc_enabled = 1;
+           }
+       else
+           {
+               mx3_nf_info->flags.hw_ecc_enabled = 0;
+           }
+       }
+
+       mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
+       mx3_nf_info->fin = MX3_NF_FIN_NONE;
+       mx3_nf_info->flags.target_little_endian =
+       (mx3_nf_info->target->endianness == TARGET_LITTLE_ENDIAN);
+       /*
+       * testing host endianess
+       */
+       {
+       int x = 1;
+       if (*(char *) &x == 1)
+           {
+               mx3_nf_info->flags.host_little_endian = 1;
+           }
+       else
+           {
+               mx3_nf_info->flags.host_little_endian = 0;
+           }
+       }
+       return ERROR_OK;
+}
+
+static int imx31_init (struct nand_device *nand)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+
+       {
+       /*
+        * validate target state
+        */
+       int validate_target_result;
+       validate_target_result = validate_target_state(nand);
+       if (validate_target_result != ERROR_OK)
+           {
+               return validate_target_result;
+           }
+       }
+
+       {
+       uint16_t buffsize_register_content;
+       target_read_u16 (target, MX3_NF_BUFSIZ, &buffsize_register_content);
+       mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
+       }
+
+       {
+       uint32_t pcsr_register_content;
+       target_read_u32 (target, MX3_PCSR, &pcsr_register_content);
+       if (!nand->bus_width)
+           {
+               nand->bus_width =
+                   (pcsr_register_content & 0x80000000) ? 16 : 8;
+           }
+       else
+           {
+               pcsr_register_content |=
+                   ((nand->bus_width == 16) ? 0x80000000 : 0x00000000);
+               target_write_u32 (target, MX3_PCSR, pcsr_register_content);
+           }
+
+       if (!nand->page_size)
+           {
+               nand->page_size =
+                   (pcsr_register_content & 0x40000000) ? 2048 : 512;
+           }
+       else
+           {
+               pcsr_register_content |=
+                   ((nand->page_size == 2048) ? 0x40000000 : 0x00000000);
+               target_write_u32 (target, MX3_PCSR, pcsr_register_content);
+           }
+       if (mx3_nf_info->flags.one_kb_sram && (nand->page_size == 2048))
+           {
+               LOG_ERROR
+                   ("NAND controller have only 1 kb SRAM, so pagesize 2048 is incompatible with it");
+           }
+       }
+
+       {
+       uint32_t cgr_register_content;
+       target_read_u32 (target, MX3_CCM_CGR2, &cgr_register_content);
+       if (!(cgr_register_content & 0x00000300))
+           {
+               LOG_ERROR ("clock gating to EMI disabled");
+               return ERROR_FAIL;
+           }
+       }
+
+       {
+       uint32_t gpr_register_content;
+       target_read_u32 (target, MX3_GPR, &gpr_register_content);
+       if (gpr_register_content & 0x00000060)
+           {
+               LOG_ERROR ("pins mode overrided by GPR");
+               return ERROR_FAIL;
+           }
+       }
+
+       {
+       /*
+        * testing IOMUX settings; must be in "functional-mode output and
+        * functional-mode input" mode
+        */
+       int test_iomux;
+       test_iomux = ERROR_OK;
+       test_iomux |=
+           test_iomux_settings (target, 0x43fac0c0, 0x7f7f7f00, "d0,d1,d2");
+       test_iomux |=
+           test_iomux_settings (target, 0x43fac0c4, 0x7f7f7f7f, "d3,d4,d5,d6");
+       test_iomux |=
+           test_iomux_settings (target, 0x43fac0c8, 0x0000007f, "d7");
+       if (nand->bus_width == 16)
+           {
+               test_iomux |=
+                   test_iomux_settings (target, 0x43fac0c8, 0x7f7f7f00,
+                                        "d8,d9,d10");
+               test_iomux |=
+                   test_iomux_settings (target, 0x43fac0cc, 0x7f7f7f7f,
+                                        "d11,d12,d13,d14");
+               test_iomux |=
+                   test_iomux_settings (target, 0x43fac0d0, 0x0000007f, "d15");
+           }
+       test_iomux |=
+           test_iomux_settings (target, 0x43fac0d0, 0x7f7f7f00,
+                                "nfwp,nfce,nfrb");
+       test_iomux |=
+           test_iomux_settings (target, 0x43fac0d4, 0x7f7f7f7f,
+                                "nfwe,nfre,nfale,nfcle");
+       if (test_iomux != ERROR_OK)
+           {
+               return ERROR_FAIL;
+           }
+       }
+
+       initialize_nf_controller (nand);
+
+       {
+       int retval;
+       uint16_t nand_status_content;
+       retval = ERROR_OK;
+       retval |= imx31_command (nand, NAND_CMD_STATUS);
+       retval |= imx31_address (nand, 0x00);
+       retval |= do_data_output (nand);
+       if (retval != ERROR_OK)
+           {
+               LOG_ERROR (get_status_register_err_msg);
+               return ERROR_FAIL;
+           }
+       target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
+       if (!(nand_status_content & 0x0080))
+           {
+               /*
+                * is host-big-endian correctly ??
+                */
+               LOG_INFO ("NAND read-only");
+               mx3_nf_info->flags.nand_readonly = 1;
+           }
+       else
+           {
+               mx3_nf_info->flags.nand_readonly = 0;
+           }
+       }
+       return ERROR_OK;
+}
+
+static int imx31_read_data (struct nand_device *nand, void *data)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+       {
+       /*
+        * validate target state
+        */
+       int validate_target_result;
+       validate_target_result = validate_target_state (nand);
+       if (validate_target_result != ERROR_OK)
+           {
+               return validate_target_result;
+           }
+       }
+
+       {
+       /*
+        * get data from nand chip
+        */
+       int try_data_output_from_nand_chip;
+       try_data_output_from_nand_chip = do_data_output (nand);
+       if (try_data_output_from_nand_chip != ERROR_OK)
+           {
+               return try_data_output_from_nand_chip;
+           }
+       }
+
+       if (nand->bus_width == 16)
+       {
+           get_next_halfword_from_sram_buffer (target, data);
+       }
+       else
+       {
+           get_next_byte_from_sram_buffer (target, data);
+       }
+
+       return ERROR_OK;
+}
+
+static int imx31_write_data (struct nand_device *nand, uint16_t data)
+{
+       LOG_ERROR ("write_data() not implemented");
+       return ERROR_NAND_OPERATION_FAILED;
+}
+
+static int imx31_nand_ready (struct nand_device *nand, int timeout)
+{
+       return imx31_controller_ready (nand, timeout);
+}
+
+static int imx31_reset (struct nand_device *nand)
+{
+       /*
+       * validate target state
+       */
+       int validate_target_result;
+       validate_target_result = validate_target_state (nand);
+       if (validate_target_result != ERROR_OK)
+       {
+           return validate_target_result;
+       }
+       initialize_nf_controller (nand);
+       return ERROR_OK;
+}
+
+static int imx31_command (struct nand_device *nand, uint8_t command)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+       {
+       /*
+        * validate target state
+        */
+       int validate_target_result;
+       validate_target_result = validate_target_state (nand);
+       if (validate_target_result != ERROR_OK)
+           {
+               return validate_target_result;
+           }
+       }
+
+       switch (command)
+       {
+           case NAND_CMD_READOOB:
+               command = NAND_CMD_READ0;
+               in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
+                                                        * data_read() and
+                                                        * read_block_data() to
+                                                        * spare area in SRAM
+                                                        * buffer */
+               break;
+           case NAND_CMD_READ1:
+               command = NAND_CMD_READ0;
+               /*
+                * offset == one half of page size
+                */
+               in_sram_address =
+                   MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
+           default:
+               in_sram_address = MX3_NF_MAIN_BUFFER0;
+       }
+
+       target_write_u16 (target, MX3_NF_FCMD, command);
+       /*
+       * start command input operation (set MX3_NF_BIT_OP_DONE==0)
+       */
+       target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FCI);
+       {
+       int poll_result;
+       poll_result = poll_for_complete_op (target, "command");
+       if (poll_result != ERROR_OK)
+           {
+               return poll_result;
+           }
+       }
+       /*
+       * reset cursor to begin of the buffer
+       */
+       sign_of_sequental_byte_read = 0;
+       switch (command)
+       {
+           case NAND_CMD_READID:
+               mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
+               mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+               break;
+           case NAND_CMD_STATUS:
+               mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS;
+               mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+               break;
+           case NAND_CMD_READ0:
+               mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+               mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
+               break;
+           default:
+               mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
+       }
+       return ERROR_OK;
+}
+
+static int imx31_address (struct nand_device *nand, uint8_t address)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+       {
+       /*
+        * validate target state
+        */
+       int validate_target_result;
+       validate_target_result = validate_target_state (nand);
+       if (validate_target_result != ERROR_OK)
+           {
+               return validate_target_result;
+           }
+       }
+
+       target_write_u16 (target, MX3_NF_FADDR, address);
+       /*
+       * start address input operation (set MX3_NF_BIT_OP_DONE==0)
+       */
+       target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FAI);
+       {
+       int poll_result;
+       poll_result = poll_for_complete_op (target, "address");
+       if (poll_result != ERROR_OK)
+           {
+               return poll_result;
+           }
+       }
+       return ERROR_OK;
+}
+
+static int imx31_controller_ready (struct nand_device *nand, int tout)
+{
+       uint16_t poll_complete_status;
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+
+       {
+       /*
+        * validate target state
+        */
+       int validate_target_result;
+       validate_target_result = validate_target_state (nand);
+       if (validate_target_result != ERROR_OK)
+           {
+               return validate_target_result;
+           }
+       }
+
+       do
+       {
+           target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
+           if (poll_complete_status & MX3_NF_BIT_OP_DONE)
+               {
+                   return tout;
+               }
+           alive_sleep (1);
+       }
+       while (tout-- > 0);
+       return tout;
+}
+
+static int imx31_write_page (struct nand_device *nand, uint32_t page,
+                            uint8_t * data, uint32_t data_size, uint8_t * oob,
+                            uint32_t oob_size)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+
+       if (data_size % 2)
+       {
+           LOG_ERROR (data_block_size_err_msg, data_size);
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+       if (oob_size % 2)
+       {
+           LOG_ERROR (data_block_size_err_msg, oob_size);
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+       if (!data)
+       {
+           LOG_ERROR ("nothing to program");
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+       {
+       /*
+        * validate target state
+        */
+       int retval;
+       retval = validate_target_state (nand);
+       if (retval != ERROR_OK)
+           {
+               return retval;
+           }
+       }
+       {
+       int retval = ERROR_OK;
+       retval |= imx31_command(nand, NAND_CMD_SEQIN);
+       retval |= imx31_address(nand, 0x00);
+       retval |= imx31_address(nand, page & 0xff);
+       retval |= imx31_address(nand, (page >> 8) & 0xff);
+       if (nand->address_cycles >= 4)
+           {
+               retval |= imx31_address (nand, (page >> 16) & 0xff);
+               if (nand->address_cycles >= 5)
+                   {
+                       retval |= imx31_address (nand, (page >> 24) & 0xff);
+                   }
+           }
+       target_write_buffer (target, MX3_NF_MAIN_BUFFER0, data_size, data);
+       if (oob)
+           {
+               if (mx3_nf_info->flags.hw_ecc_enabled)
+                   {
+                       /*
+                        * part of spare block will be overrided by hardware
+                        * ECC generator
+                        */
+                       LOG_DEBUG
+                           ("part of spare block will be overrided by hardware ECC generator");
+                   }
+               target_write_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
+                                    oob);
+           }
+       /*
+        * start data input operation (set MX3_NF_BIT_OP_DONE==0)
+        */
+       target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI);
+       {
+           int poll_result;
+           poll_result = poll_for_complete_op (target, "data input");
+           if (poll_result != ERROR_OK)
+               {
+                   return poll_result;
+               }
+       }
+       retval |= imx31_command (nand, NAND_CMD_PAGEPROG);
+       if (retval != ERROR_OK)
+           {
+               return retval;
+           }
+
+       /*
+        * check status register
+        */
+       {
+           uint16_t nand_status_content;
+           retval = ERROR_OK;
+           retval |= imx31_command(nand, NAND_CMD_STATUS);
+           retval |= imx31_address(nand, 0x00);
+           retval |= do_data_output(nand);
+           if (retval != ERROR_OK)
+               {
+                   LOG_ERROR (get_status_register_err_msg);
+                   return retval;
+               }
+           target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
+           if (nand_status_content & 0x0001)
+               {
+                   /*
+                    * is host-big-endian correctly ??
+                    */
+                   return ERROR_NAND_OPERATION_FAILED;
+               }
+       }
+       }
+       return ERROR_OK;
+}
+
+static int imx31_read_page (struct nand_device *nand, uint32_t page,
+                           uint8_t * data, uint32_t data_size, uint8_t * oob,
+                           uint32_t oob_size)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+
+       if (data_size % 2)
+       {
+           LOG_ERROR (data_block_size_err_msg, data_size);
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+       if (oob_size % 2)
+       {
+           LOG_ERROR (data_block_size_err_msg, oob_size);
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       {
+       /*
+        * validate target state
+        */
+       int retval;
+       retval = validate_target_state(nand);
+       if (retval != ERROR_OK)
+           {
+               return retval;
+           }
+       }
+       {
+       int retval = ERROR_OK;
+       retval |= imx31_command(nand, NAND_CMD_READ0);
+       retval |= imx31_address(nand, 0x00);
+       retval |= imx31_address(nand, page & 0xff);
+       retval |= imx31_address(nand, (page >> 8) & 0xff);
+       if (nand->address_cycles >= 4)
+           {
+               retval |= imx31_address(nand, (page >> 16) & 0xff);
+               if (nand->address_cycles >= 5)
+                   {
+                       retval |= imx31_address(nand, (page >> 24) & 0xff);
+                       retval |= imx31_command(nand, NAND_CMD_READSTART);
+                   }
+           }
+       retval |= do_data_output (nand);
+       if (retval != ERROR_OK)
+           {
+               return retval;
+           }
+
+       if (data)
+           {
+               target_read_buffer (target, MX3_NF_MAIN_BUFFER0, data_size,
+                                   data);
+           }
+       if (oob)
+           {
+               target_read_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
+                                   oob);
+           }
+       }
+       return ERROR_OK;
+}
+
+static int test_iomux_settings (struct target * target, uint32_t address,
+                               uint32_t mask, const char *text)
+{
+       uint32_t register_content;
+       target_read_u32 (target, address, &register_content);
+       if ((register_content & mask) != (0x12121212 & mask))
+       {
+           LOG_ERROR ("IOMUX for {%s} is bad", text);
+           return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
+static int initialize_nf_controller (struct nand_device *nand)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+       /*
+       * resets NAND flash controller in zero time ? I dont know.
+       */
+       target_write_u16 (target, MX3_NF_CFG1, MX3_NF_BIT_RESET_EN);
+       {
+       uint16_t work_mode;
+       work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */
+       if (target->endianness == TARGET_BIG_ENDIAN)
+           {
+               work_mode |= MX3_NF_BIT_BE_EN;
+           }
+       if (mx3_nf_info->flags.hw_ecc_enabled)
+           {
+               work_mode |= MX3_NF_BIT_ECC_EN;
+           }
+       target_write_u16 (target, MX3_NF_CFG1, work_mode);
+       }
+       /*
+       * unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock"
+       */
+       target_write_u16 (target, MX3_NF_BUFCFG, 2);
+       {
+       uint16_t temp;
+       target_read_u16 (target, MX3_NF_FWP, &temp);
+       if ((temp & 0x0007) == 1)
+           {
+               LOG_ERROR ("NAND flash is tight-locked, reset needed");
+               return ERROR_FAIL;
+           }
+
+       }
+       /*
+       * unlock NAND flash for write
+       */
+       target_write_u16 (target, MX3_NF_FWP, 4);
+       target_write_u16 (target, MX3_NF_LOCKSTART, 0x0000);
+       target_write_u16 (target, MX3_NF_LOCKEND, 0xFFFF);
+       /*
+       * 0x0000 means that first SRAM buffer @0xB800_0000 will be used
+       */
+       target_write_u16 (target, MX3_NF_BUFADDR, 0x0000);
+       /*
+       * address of SRAM buffer
+       */
+       in_sram_address = MX3_NF_MAIN_BUFFER0;
+       sign_of_sequental_byte_read = 0;
+       return ERROR_OK;
+}
+
+static int get_next_byte_from_sram_buffer (struct target * target, uint8_t * value)
+{
+       static uint8_t even_byte = 0;
+       /*
+       * host-big_endian ??
+       */
+       if (sign_of_sequental_byte_read == 0)
+       {
+           even_byte = 0;
+       }
+       if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR)
+       {
+           LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
+           *value = 0;
+           sign_of_sequental_byte_read = 0;
+           even_byte = 0;
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+       else
+       {
+           uint16_t temp;
+           target_read_u16 (target, in_sram_address, &temp);
+           if (even_byte)
+               {
+                   *value = temp >> 8;
+                   even_byte = 0;
+                   in_sram_address += 2;
+               }
+           else
+               {
+                   *value = temp & 0xff;
+                   even_byte = 1;
+               }
+       }
+       sign_of_sequental_byte_read = 1;
+       return ERROR_OK;
+}
+
+static int get_next_halfword_from_sram_buffer (struct target * target,
+                                              uint16_t * value)
+{
+       if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR)
+       {
+           LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
+           *value = 0;
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+       else
+       {
+           target_read_u16 (target, in_sram_address, value);
+           in_sram_address += 2;
+       }
+       return ERROR_OK;
+}
+
+static int poll_for_complete_op (struct target * target, const char *text)
+{
+       uint16_t poll_complete_status;
+       for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++)
+       {
+           usleep (25);
+           target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
+           if (poll_complete_status & MX3_NF_BIT_OP_DONE)
+               {
+                   break;
+               }
+       }
+       if (!(poll_complete_status & MX3_NF_BIT_OP_DONE))
+       {
+           LOG_ERROR ("%s sending timeout", text);
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+       return ERROR_OK;
+}
+
+static int validate_target_state (struct nand_device *nand)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+           LOG_ERROR (target_not_halted_err_msg);
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       if (mx3_nf_info->flags.target_little_endian !=
+       (target->endianness == TARGET_LITTLE_ENDIAN))
+       {
+           /*
+            * endianness changed after NAND controller probed
+            */
+           return ERROR_NAND_OPERATION_FAILED;
+       }
+       return ERROR_OK;
+}
+
+static int do_data_output (struct nand_device *nand)
+{
+       struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
+       struct target *target = mx3_nf_info->target;
+       switch (mx3_nf_info->fin)
+       {
+           case MX3_NF_FIN_DATAOUT:
+               /*
+                * start data output operation (set MX3_NF_BIT_OP_DONE==0)
+                */
+               target_write_u16 (target, MX3_NF_CFG2,
+                                 MX3_NF_BIT_DATAOUT_TYPE (mx3_nf_info->
+                                                          optype));
+               {
+                   int poll_result;
+                   poll_result = poll_for_complete_op (target, "data output");
+                   if (poll_result != ERROR_OK)
+                       {
+                           return poll_result;
+                       }
+               }
+               mx3_nf_info->fin = MX3_NF_FIN_NONE;
+               /*
+                * ECC stuff
+                */
+               if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE)
+                   && mx3_nf_info->flags.hw_ecc_enabled)
+                   {
+                       uint16_t ecc_status;
+                       target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
+                       switch (ecc_status & 0x000c)
+                           {
+                               case 1 << 2:
+                                   LOG_DEBUG
+                                       ("main area readed with 1 (correctable) error");
+                                   break;
+                               case 2 << 2:
+                                   LOG_DEBUG
+                                       ("main area readed with more than 1 (incorrectable) error");
+                                   return ERROR_NAND_OPERATION_FAILED;
+                                   break;
+                           }
+                       switch (ecc_status & 0x0003)
+                           {
+                               case 1:
+                                   LOG_DEBUG
+                                       ("spare area readed with 1 (correctable) error");
+                                   break;
+                               case 2:
+                                   LOG_DEBUG
+                                       ("main area readed with more than 1 (incorrectable) error");
+                                   return ERROR_NAND_OPERATION_FAILED;
+                                   break;
+                           }
+                   }
+               break;
+           case MX3_NF_FIN_NONE:
+               break;
+       }
+       return ERROR_OK;
+}
+
+struct nand_flash_controller imx31_nand_flash_controller = {
+               .name = "imx31",
+               .nand_device_command = &imx31_nand_device_command,
+               .init = &imx31_init,
+               .reset = &imx31_reset,
+               .command = &imx31_command,
+               .address = &imx31_address,
+               .write_data = &imx31_write_data,
+               .read_data = &imx31_read_data,
+               .write_page = &imx31_write_page,
+               .read_page = &imx31_read_page,
+               .controller_ready = &imx31_controller_ready,
+               .nand_ready = &imx31_nand_ready,
+       };
diff --git a/src/flash/nand/mx3.h b/src/flash/nand/mx3.h
new file mode 100644 (file)
index 0000000..ddec92c
--- /dev/null
@@ -0,0 +1,117 @@
+
+/***************************************************************************
+ *   Copyright (C) 2009 by Alexei Babich                                   *
+ *   Rezonans plc., Chelyabinsk, Russia                                    *
+ *   impatt@mail.ru                                                        *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+/*
+ * Freescale iMX3* OpenOCD NAND Flash controller support.
+ *
+ * Many thanks to Ben Dooks for writing s3c24xx driver.
+ */
+#include <nand.h>
+
+#define                MX3_NF_BASE_ADDR                0xb8000000
+#define                MX3_NF_BUFSIZ                   (MX3_NF_BASE_ADDR + 0xe00)
+#define                MX3_NF_BUFADDR                  (MX3_NF_BASE_ADDR + 0xe04)
+#define                MX3_NF_FADDR                    (MX3_NF_BASE_ADDR + 0xe06)
+#define                MX3_NF_FCMD                             (MX3_NF_BASE_ADDR + 0xe08)
+#define                MX3_NF_BUFCFG                   (MX3_NF_BASE_ADDR + 0xe0a)
+#define                MX3_NF_ECCSTATUS                        (MX3_NF_BASE_ADDR + 0xe0c)
+#define                MX3_NF_ECCMAINPOS                       (MX3_NF_BASE_ADDR + 0xe0e)
+#define                MX3_NF_ECCSPAREPOS                      (MX3_NF_BASE_ADDR + 0xe10)
+#define                MX3_NF_FWP                      (MX3_NF_BASE_ADDR + 0xe12)
+#define                MX3_NF_LOCKSTART                        (MX3_NF_BASE_ADDR + 0xe14)
+#define                MX3_NF_LOCKEND                  (MX3_NF_BASE_ADDR + 0xe16)
+#define                MX3_NF_FWPSTATUS                        (MX3_NF_BASE_ADDR + 0xe18)
+ /*
+  * all bits not marked as self-clearing bit
+  */
+#define                MX3_NF_CFG1                     (MX3_NF_BASE_ADDR + 0xe1a)
+#define                MX3_NF_CFG2                     (MX3_NF_BASE_ADDR + 0xe1c)
+
+#define                MX3_NF_MAIN_BUFFER0             (MX3_NF_BASE_ADDR + 0x0000)
+#define                MX3_NF_MAIN_BUFFER1             (MX3_NF_BASE_ADDR + 0x0200)
+#define                MX3_NF_MAIN_BUFFER2             (MX3_NF_BASE_ADDR + 0x0400)
+#define                MX3_NF_MAIN_BUFFER3             (MX3_NF_BASE_ADDR + 0x0600)
+#define                MX3_NF_SPARE_BUFFER0    (MX3_NF_BASE_ADDR + 0x0800)
+#define                MX3_NF_SPARE_BUFFER1    (MX3_NF_BASE_ADDR + 0x0810)
+#define                MX3_NF_SPARE_BUFFER2    (MX3_NF_BASE_ADDR + 0x0820)
+#define                MX3_NF_SPARE_BUFFER3    (MX3_NF_BASE_ADDR + 0x0830)
+#define                MX3_NF_MAIN_BUFFER_LEN  512
+#define                MX3_NF_SPARE_BUFFER_LEN 16
+#define                MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2)
+
+/* bits in MX3_NF_CFG1 register */
+#define                MX3_NF_BIT_SPARE_ONLY_EN        (1<<2)
+#define                MX3_NF_BIT_ECC_EN                       (1<<3)
+#define                MX3_NF_BIT_INT_DIS                      (1<<4)
+#define                MX3_NF_BIT_BE_EN                        (1<<5)
+#define                MX3_NF_BIT_RESET_EN                     (1<<6)
+#define                MX3_NF_BIT_FORCE_CE                     (1<<7)
+
+/* bits in MX3_NF_CFG2 register */
+
+/*Flash Command Input*/
+#define                MX3_NF_BIT_OP_FCI                       (1<<0)
+ /*
+  * Flash Address Input
+  */
+#define                MX3_NF_BIT_OP_FAI                       (1<<1)
+ /*
+  * Flash Data Input
+  */
+#define                MX3_NF_BIT_OP_FDI                       (1<<2)
+
+/* see "enum mx_dataout_type" below */
+#define                MX3_NF_BIT_DATAOUT_TYPE(x)      ((x)<<3)
+#define                MX3_NF_BIT_OP_DONE                      (1<<15)
+
+#define                MX3_CCM_CGR2            0x53f80028
+#define                MX3_GPR                         0x43fac008
+#define                MX3_PCSR                        0x53f8000c
+
+enum mx_dataout_type
+{
+       MX3_NF_DATAOUT_PAGE = 1,
+       MX3_NF_DATAOUT_NANDID = 2,
+       MX3_NF_DATAOUT_NANDSTATUS = 4,
+};
+enum mx_nf_finalize_action
+{
+       MX3_NF_FIN_NONE,
+       MX3_NF_FIN_DATAOUT,
+};
+
+struct mx3_nf_flags
+{
+       unsigned host_little_endian:1;
+       unsigned target_little_endian:1;
+       unsigned nand_readonly:1;
+       unsigned one_kb_sram:1;
+       unsigned hw_ecc_enabled:1;
+};
+
+struct mx3_nf_controller
+{
+       struct target *target;
+       enum mx_dataout_type optype;
+       enum mx_nf_finalize_action fin;
+       struct mx3_nf_flags flags;
+};
diff --git a/src/flash/nand/nonce.c b/src/flash/nand/nonce.c
new file mode 100644 (file)
index 0000000..dae62a7
--- /dev/null
@@ -0,0 +1,80 @@
+/***************************************************************************
+ *   Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net>             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "nand.h"
+
+
+static int nonce_nand_command(struct nand_device *nand, uint8_t command)
+{
+       return ERROR_OK;
+}
+static int nonce_nand_address(struct nand_device *nand, uint8_t address)
+{
+       return ERROR_OK;
+}
+static int nonce_nand_read(struct nand_device *nand, void *data)
+{
+       return ERROR_OK;
+}
+static int nonce_nand_write(struct nand_device *nand, uint16_t data)
+{
+       return ERROR_OK;
+}
+static int nonce_nand_fast_block_write(struct nand_device *nand,
+               uint8_t *data, int size)
+{
+       return ERROR_OK;
+}
+
+static int nonce_nand_reset(struct nand_device *nand)
+{
+       return nonce_nand_command(nand, NAND_CMD_RESET);
+}
+
+static int nonce_nand_controller_ready(struct nand_device *nand, int timeout)
+{
+       return true;
+}
+
+NAND_DEVICE_COMMAND_HANDLER(nonce_nand_device_command)
+{
+       return ERROR_OK;
+}
+
+static int nonce_nand_init(struct nand_device *nand)
+{
+       return ERROR_OK;
+}
+
+struct nand_flash_controller nonce_nand_controller =
+{
+       .name                   = "nonce",
+       .nand_device_command    = &nonce_nand_device_command,
+       .init                   = &nonce_nand_init,
+       .reset                  = &nonce_nand_reset,
+       .command                = &nonce_nand_command,
+       .address                = &nonce_nand_address,
+       .read_data              = &nonce_nand_read,
+       .write_data             = &nonce_nand_write,
+       .write_block_data       = &nonce_nand_fast_block_write,
+       .controller_ready       = &nonce_nand_controller_ready,
+};
diff --git a/src/flash/nand/orion.c b/src/flash/nand/orion.c
new file mode 100644 (file)
index 0000000..77a03f2
--- /dev/null
@@ -0,0 +1,180 @@
+/***************************************************************************
+ *   Copyright (C) 2009 by Marvell Semiconductors, Inc.                    *
+ *   Written by Nicolas Pitre <nico at marvell.com>                           *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+/*
+ * NAND controller interface for Marvell Orion/Kirkwood SoCs.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm_nandio.h"
+#include "armv4_5.h"
+
+
+struct orion_nand_controller
+{
+       struct target   *target;
+
+       struct arm_nand_data    io;
+
+       uint32_t                cmd;
+       uint32_t                addr;
+       uint32_t                data;
+};
+
+#define CHECK_HALTED \
+       do { \
+               if (target->state != TARGET_HALTED) { \
+                       LOG_ERROR("NAND flash access requires halted target"); \
+                       return ERROR_NAND_OPERATION_FAILED; \
+               } \
+       } while (0)
+
+static int orion_nand_command(struct nand_device *nand, uint8_t command)
+{
+       struct orion_nand_controller *hw = nand->controller_priv;
+       struct target *target = hw->target;
+
+       CHECK_HALTED;
+       target_write_u8(target, hw->cmd, command);
+       return ERROR_OK;
+}
+
+static int orion_nand_address(struct nand_device *nand, uint8_t address)
+{
+       struct orion_nand_controller *hw = nand->controller_priv;
+       struct target *target = hw->target;
+
+       CHECK_HALTED;
+       target_write_u8(target, hw->addr, address);
+       return ERROR_OK;
+}
+
+static int orion_nand_read(struct nand_device *nand, void *data)
+{
+       struct orion_nand_controller *hw = nand->controller_priv;
+       struct target *target = hw->target;
+
+       CHECK_HALTED;
+       target_read_u8(target, hw->data, data);
+       return ERROR_OK;
+}
+
+static int orion_nand_write(struct nand_device *nand, uint16_t data)
+{
+       struct orion_nand_controller *hw = nand->controller_priv;
+       struct target *target = hw->target;
+
+       CHECK_HALTED;
+       target_write_u8(target, hw->data, data);
+       return ERROR_OK;
+}
+
+static int orion_nand_slow_block_write(struct nand_device *nand, uint8_t *data, int size)
+{
+       while (size--)
+               orion_nand_write(nand, *data++);
+       return ERROR_OK;
+}
+
+static int orion_nand_fast_block_write(struct nand_device *nand, uint8_t *data, int size)
+{
+       struct orion_nand_controller *hw = nand->controller_priv;
+       int retval;
+
+       hw->io.chunk_size = nand->page_size;
+
+       retval = arm_nandwrite(&hw->io, data, size);
+       if (retval == ERROR_NAND_NO_BUFFER)
+               retval = orion_nand_slow_block_write(nand, data, size);
+
+       return retval;
+}
+
+static int orion_nand_reset(struct nand_device *nand)
+{
+       return orion_nand_command(nand, NAND_CMD_RESET);
+}
+
+static int orion_nand_controller_ready(struct nand_device *nand, int timeout)
+{
+       return 1;
+}
+
+NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
+{
+       struct orion_nand_controller *hw;
+       uint32_t base;
+       uint8_t ale, cle;
+
+       if (CMD_ARGC != 3) {
+               LOG_ERROR("arguments must be: <target_id> <NAND_address>\n");
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       hw = calloc(1, sizeof(*hw));
+       if (!hw) {
+               LOG_ERROR("no memory for nand controller\n");
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       nand->controller_priv = hw;
+       hw->target = get_target(CMD_ARGV[1]);
+       if (!hw->target) {
+               LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
+               free(hw);
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], base);
+       cle = 0;
+       ale = 1;
+
+       hw->data = base;
+       hw->cmd = base + (1 << cle);
+       hw->addr = base + (1 << ale);
+
+       hw->io.target = hw->target;
+       hw->io.data = hw->data;
+
+       return ERROR_OK;
+}
+
+static int orion_nand_init(struct nand_device *nand)
+{
+       return ERROR_OK;
+}
+
+struct nand_flash_controller orion_nand_controller =
+{
+       .name                   = "orion",
+       .command                = orion_nand_command,
+       .address                = orion_nand_address,
+       .read_data              = orion_nand_read,
+       .write_data             = orion_nand_write,
+       .write_block_data       = orion_nand_fast_block_write,
+       .reset                  = orion_nand_reset,
+       .controller_ready       = orion_nand_controller_ready,
+       .nand_device_command    = orion_nand_device_command,
+       .init                   = orion_nand_init,
+};
+
diff --git a/src/flash/nand/s3c2410.c b/src/flash/nand/s3c2410.c
new file mode 100644 (file)
index 0000000..3c391bc
--- /dev/null
@@ -0,0 +1,123 @@
+/***************************************************************************
+ *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
+ *   ben@fluff.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.             *
+ ***************************************************************************/
+
+/*
+ * S3C2410 OpenOCD NAND Flash controller support.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3c24xx.h"
+
+NAND_DEVICE_COMMAND_HANDLER(s3c2410_nand_device_command)
+{
+       struct s3c24xx_nand_controller *info;
+       CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
+
+       /* fill in the address fields for the core device */
+       info->cmd = S3C2410_NFCMD;
+       info->addr = S3C2410_NFADDR;
+       info->data = S3C2410_NFDATA;
+       info->nfstat = S3C2410_NFSTAT;
+
+       return ERROR_OK;
+}
+
+static int s3c2410_init(struct nand_device *nand)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       target_write_u32(target, S3C2410_NFCONF,
+                        S3C2410_NFCONF_EN | S3C2410_NFCONF_TACLS(3) |
+                        S3C2410_NFCONF_TWRPH0(5) | S3C2410_NFCONF_TWRPH1(3));
+
+       return ERROR_OK;
+}
+
+static int s3c2410_write_data(struct nand_device *nand, uint16_t data)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       target_write_u32(target, S3C2410_NFDATA, data);
+       return ERROR_OK;
+}
+
+static int s3c2410_read_data(struct nand_device *nand, void *data)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       target_read_u8(target, S3C2410_NFDATA, data);
+       return ERROR_OK;
+}
+
+static int s3c2410_nand_ready(struct nand_device *nand, int timeout)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+       uint8_t status;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       do {
+               target_read_u8(target, S3C2410_NFSTAT, &status);
+
+               if (status & S3C2410_NFSTAT_BUSY)
+                       return 1;
+
+               alive_sleep(1);
+       } while (timeout-- > 0);
+
+       return 0;
+}
+
+struct nand_flash_controller s3c2410_nand_controller = {
+               .name = "s3c2410",
+               .nand_device_command = &s3c2410_nand_device_command,
+               .init = &s3c2410_init,
+               .reset = &s3c24xx_reset,
+               .command = &s3c24xx_command,
+               .address = &s3c24xx_address,
+               .write_data = &s3c2410_write_data,
+               .read_data = &s3c2410_read_data,
+               .write_page = s3c24xx_write_page,
+               .read_page = s3c24xx_read_page,
+               .controller_ready = &s3c24xx_controller_ready,
+               .nand_ready = &s3c2410_nand_ready,
+       };
diff --git a/src/flash/nand/s3c2412.c b/src/flash/nand/s3c2412.c
new file mode 100644 (file)
index 0000000..5784305
--- /dev/null
@@ -0,0 +1,79 @@
+/***************************************************************************
+ *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
+ *   ben@fluff.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.             *
+ ***************************************************************************/
+
+/*
+ * S3C2412 OpenOCD NAND Flash controller support.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3c24xx.h"
+
+NAND_DEVICE_COMMAND_HANDLER(s3c2412_nand_device_command)
+{
+       struct s3c24xx_nand_controller *info;
+       CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
+
+       /* fill in the address fields for the core device */
+       info->cmd = S3C2440_NFCMD;
+       info->addr = S3C2440_NFADDR;
+       info->data = S3C2440_NFDATA;
+       info->nfstat = S3C2412_NFSTAT;
+
+       return ERROR_OK;
+}
+
+static int s3c2412_init(struct nand_device *nand)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       target_write_u32(target, S3C2410_NFCONF,
+                        S3C2440_NFCONF_TACLS(3) |
+                        S3C2440_NFCONF_TWRPH0(7) |
+                        S3C2440_NFCONF_TWRPH1(7));
+
+       target_write_u32(target, S3C2440_NFCONT,
+                        S3C2412_NFCONT_INIT_MAIN_ECC |
+                        S3C2440_NFCONT_ENABLE);
+
+       return ERROR_OK;
+}
+
+struct nand_flash_controller s3c2412_nand_controller = {
+               .name = "s3c2412",
+               .nand_device_command = &s3c2412_nand_device_command,
+               .init = &s3c2412_init,
+               .reset = &s3c24xx_reset,
+               .command = &s3c24xx_command,
+               .address = &s3c24xx_address,
+               .write_data = &s3c24xx_write_data,
+               .read_data = &s3c24xx_read_data,
+               .write_page = s3c24xx_write_page,
+               .read_page = s3c24xx_read_page,
+               .write_block_data = &s3c2440_write_block_data,
+               .read_block_data = &s3c2440_read_block_data,
+               .controller_ready = &s3c24xx_controller_ready,
+               .nand_ready = &s3c2440_nand_ready,
+       };
diff --git a/src/flash/nand/s3c2440.c b/src/flash/nand/s3c2440.c
new file mode 100644 (file)
index 0000000..d1a421e
--- /dev/null
@@ -0,0 +1,171 @@
+/***************************************************************************
+ *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
+ *   ben@fluff.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.             *
+ ***************************************************************************/
+
+/*
+ * S3C2440 OpenOCD NAND Flash controller support.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3c24xx.h"
+
+
+NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
+{
+       struct s3c24xx_nand_controller *info;
+       CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
+
+       /* fill in the address fields for the core device */
+       info->cmd = S3C2440_NFCMD;
+       info->addr = S3C2440_NFADDR;
+       info->data = S3C2440_NFDATA;
+       info->nfstat = S3C2440_NFSTAT;
+
+       return ERROR_OK;
+}
+
+static int s3c2440_init(struct nand_device *nand)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       target_write_u32(target, S3C2410_NFCONF,
+                        S3C2440_NFCONF_TACLS(3) |
+                        S3C2440_NFCONF_TWRPH0(7) |
+                        S3C2440_NFCONF_TWRPH1(7));
+
+       target_write_u32(target, S3C2440_NFCONT,
+                        S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);
+
+       return ERROR_OK;
+}
+
+int s3c2440_nand_ready(struct nand_device *nand, int timeout)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+       uint8_t status;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       do {
+               target_read_u8(target, s3c24xx_info->nfstat, &status);
+
+               if (status & S3C2440_NFSTAT_READY)
+                       return 1;
+
+               alive_sleep(1);
+       } while (timeout-- > 0);
+
+
+       return 0;
+}
+
+/* use the fact we can read/write 4 bytes in one go via a single 32bit op */
+
+int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+       uint32_t nfdata = s3c24xx_info->data;
+       uint32_t tmp;
+
+       LOG_INFO("%s: reading data: %p, %p, %d\n", __func__, nand, data, data_size);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       while (data_size >= 4) {
+               target_read_u32(target, nfdata, &tmp);
+
+               data[0] = tmp;
+               data[1] = tmp >> 8;
+               data[2] = tmp >> 16;
+               data[3] = tmp >> 24;
+
+               data_size -= 4;
+               data += 4;
+       }
+
+       while (data_size > 0) {
+               target_read_u8(target, nfdata, data);
+
+               data_size -= 1;
+               data += 1;
+       }
+
+       return ERROR_OK;
+}
+
+int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+       uint32_t nfdata = s3c24xx_info->data;
+       uint32_t tmp;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       while (data_size >= 4) {
+               tmp = le_to_h_u32(data);
+               target_write_u32(target, nfdata, tmp);
+
+               data_size -= 4;
+               data += 4;
+       }
+
+       while (data_size > 0) {
+               target_write_u8(target, nfdata, *data);
+
+               data_size -= 1;
+               data += 1;
+       }
+
+       return ERROR_OK;
+}
+
+struct nand_flash_controller s3c2440_nand_controller = {
+               .name = "s3c2440",
+               .nand_device_command = &s3c2440_nand_device_command,
+               .init = &s3c2440_init,
+               .reset = &s3c24xx_reset,
+               .command = &s3c24xx_command,
+               .address = &s3c24xx_address,
+               .write_data = &s3c24xx_write_data,
+               .read_data = &s3c24xx_read_data,
+               .write_page = s3c24xx_write_page,
+               .read_page = s3c24xx_read_page,
+               .write_block_data = &s3c2440_write_block_data,
+               .read_block_data = &s3c2440_read_block_data,
+               .controller_ready = &s3c24xx_controller_ready,
+               .nand_ready = &s3c2440_nand_ready,
+       };
diff --git a/src/flash/nand/s3c2443.c b/src/flash/nand/s3c2443.c
new file mode 100644 (file)
index 0000000..d341477
--- /dev/null
@@ -0,0 +1,80 @@
+/***************************************************************************
+ *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
+ *   ben@fluff.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.             *
+ ***************************************************************************/
+
+/*
+ * S3C2443 OpenOCD NAND Flash controller support.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3c24xx.h"
+
+
+NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command)
+{
+       struct s3c24xx_nand_controller *info;
+       CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
+
+       /* fill in the address fields for the core device */
+       info->cmd = S3C2440_NFCMD;
+       info->addr = S3C2440_NFADDR;
+       info->data = S3C2440_NFDATA;
+       info->nfstat = S3C2412_NFSTAT;
+
+       return ERROR_OK;
+}
+
+static int s3c2443_init(struct nand_device *nand)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       target_write_u32(target, S3C2410_NFCONF,
+                        S3C2440_NFCONF_TACLS(3) |
+                        S3C2440_NFCONF_TWRPH0(7) |
+                        S3C2440_NFCONF_TWRPH1(7));
+
+       target_write_u32(target, S3C2440_NFCONT,
+                        S3C2412_NFCONT_INIT_MAIN_ECC |
+                        S3C2440_NFCONT_ENABLE);
+
+       return ERROR_OK;
+}
+
+struct nand_flash_controller s3c2443_nand_controller = {
+               .name = "s3c2443",
+               .nand_device_command = &s3c2443_nand_device_command,
+               .init = &s3c2443_init,
+               .reset = &s3c24xx_reset,
+               .command = &s3c24xx_command,
+               .address = &s3c24xx_address,
+               .write_data = &s3c24xx_write_data,
+               .read_data = &s3c24xx_read_data,
+               .write_page = s3c24xx_write_page,
+               .read_page = s3c24xx_read_page,
+               .write_block_data = &s3c2440_write_block_data,
+               .read_block_data = &s3c2440_read_block_data,
+               .controller_ready = &s3c24xx_controller_ready,
+               .nand_ready = &s3c2440_nand_ready,
+       };
diff --git a/src/flash/nand/s3c24xx.c b/src/flash/nand/s3c24xx.c
new file mode 100644 (file)
index 0000000..d305b22
--- /dev/null
@@ -0,0 +1,133 @@
+/***************************************************************************
+ *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
+ *   ben@fluff.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.             *
+ ***************************************************************************/
+
+/*
+ * S3C24XX Series OpenOCD NAND Flash controller support.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3c24xx.h"
+
+
+S3C24XX_DEVICE_COMMAND()
+{
+       *info = NULL;
+
+       struct s3c24xx_nand_controller *s3c24xx_info;
+       s3c24xx_info = malloc(sizeof(struct s3c24xx_nand_controller));
+       if (s3c24xx_info == NULL) {
+               LOG_ERROR("no memory for nand controller\n");
+               return -ENOMEM;
+       }
+
+       nand->controller_priv = s3c24xx_info;
+
+       s3c24xx_info->target = get_target(CMD_ARGV[1]);
+       if (s3c24xx_info->target == NULL) {
+               LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       *info = s3c24xx_info;
+
+       return ERROR_OK;
+}
+
+int s3c24xx_reset(struct nand_device *nand)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       target_write_u32(target, s3c24xx_info->cmd, 0xff);
+
+       return ERROR_OK;
+}
+
+int s3c24xx_command(struct nand_device *nand, uint8_t command)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       target_write_u16(target, s3c24xx_info->cmd, command);
+       return ERROR_OK;
+}
+
+
+int s3c24xx_address(struct nand_device *nand, uint8_t address)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       target_write_u16(target, s3c24xx_info->addr, address);
+       return ERROR_OK;
+}
+
+int s3c24xx_write_data(struct nand_device *nand, uint16_t data)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       target_write_u8(target, s3c24xx_info->data, data);
+       return ERROR_OK;
+}
+
+int s3c24xx_read_data(struct nand_device *nand, void *data)
+{
+       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
+       struct target *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       target_read_u8(target, s3c24xx_info->data, data);
+       return ERROR_OK;
+}
+
+int s3c24xx_controller_ready(struct nand_device *nand, int timeout)
+{
+       return 1;
+}
diff --git a/src/flash/nand/s3c24xx.h b/src/flash/nand/s3c24xx.h
new file mode 100644 (file)
index 0000000..38057b2
--- /dev/null
@@ -0,0 +1,84 @@
+/***************************************************************************
+ *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
+ *   ben@fluff.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.             *
+ ***************************************************************************/
+
+#ifndef S3C24xx_NAND_H
+#define S3C24xx_NAND_H
+
+/*
+ * S3C24XX Series OpenOCD NAND Flash controller support.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#include "nand.h"
+#include "s3c24xx_regs.h"
+
+struct s3c24xx_nand_controller
+{
+       struct target *target;
+
+       /* register addresses */
+       uint32_t                 cmd;
+       uint32_t                 addr;
+       uint32_t                 data;
+       uint32_t                 nfstat;
+};
+
+/* Default to using the un-translated NAND register based address */
+#undef S3C2410_NFREG
+#define S3C2410_NFREG(x) ((x) + 0x4e000000)
+
+#define S3C24XX_DEVICE_COMMAND() \
+               COMMAND_HELPER(s3c24xx_nand_device_command, \
+                               struct nand_device *nand, \
+                               struct s3c24xx_nand_controller **info)
+
+S3C24XX_DEVICE_COMMAND();
+
+#define CALL_S3C24XX_DEVICE_COMMAND(d, i) \
+       do { \
+               int retval = CALL_COMMAND_HANDLER(s3c24xx_nand_device_command, d, i); \
+               if (ERROR_OK != retval) \
+                       return retval; \
+       } while (0)
+
+int s3c24xx_reset(struct nand_device *nand);
+
+int s3c24xx_command(struct nand_device *nand, uint8_t command);
+int s3c24xx_address(struct nand_device *nand, uint8_t address);
+
+int s3c24xx_write_data(struct nand_device *nand, uint16_t data);
+int s3c24xx_read_data(struct nand_device *nand, void *data);
+
+int s3c24xx_controller_ready(struct nand_device *nand, int tout);
+
+#define s3c24xx_write_page NULL
+#define s3c24xx_read_page NULL
+
+/* code shared between different controllers */
+
+int s3c2440_nand_ready(struct nand_device *nand, int timeout);
+
+int s3c2440_read_block_data(struct nand_device *nand,
+               uint8_t *data, int data_size);
+int s3c2440_write_block_data(struct nand_device *nand,
+               uint8_t *data, int data_size);
+
+#endif // S3C24xx_NAND_H
diff --git a/src/flash/nand/s3c24xx_regs.h b/src/flash/nand/s3c24xx_regs.h
new file mode 100644 (file)
index 0000000..c8cbe78
--- /dev/null
@@ -0,0 +1,132 @@
+/***************************************************************************
+ *   Copyright (C) 2004, 2005 by Simtec Electronics                        *
+ *   linux@simtec.co.uk                                                    *
+ *   http://www.simtec.co.uk/products/SWLINUX/                             *
+ *                                                                         *
+ *   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; version 2 of the License.               *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+/*
+ * S3C2410 NAND register definitions
+ */
+
+#ifndef __ASM_ARM_REGS_NAND
+#define __ASM_ARM_REGS_NAND "$Id: nand.h,v 1.3 2003/12/09 11:36:29 ben Exp $"
+
+#define S3C2410_NFREG(x) (x)
+
+#define S3C2410_NFCONF  S3C2410_NFREG(0x00)
+#define S3C2410_NFCMD   S3C2410_NFREG(0x04)
+#define S3C2410_NFADDR  S3C2410_NFREG(0x08)
+#define S3C2410_NFDATA  S3C2410_NFREG(0x0C)
+#define S3C2410_NFSTAT  S3C2410_NFREG(0x10)
+#define S3C2410_NFECC   S3C2410_NFREG(0x14)
+
+#define S3C2440_NFCONT   S3C2410_NFREG(0x04)
+#define S3C2440_NFCMD    S3C2410_NFREG(0x08)
+#define S3C2440_NFADDR   S3C2410_NFREG(0x0C)
+#define S3C2440_NFDATA   S3C2410_NFREG(0x10)
+#define S3C2440_NFECCD0  S3C2410_NFREG(0x14)
+#define S3C2440_NFECCD1  S3C2410_NFREG(0x18)
+#define S3C2440_NFECCD   S3C2410_NFREG(0x1C)
+#define S3C2440_NFSTAT   S3C2410_NFREG(0x20)
+#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24)
+#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
+#define S3C2440_NFMECC0  S3C2410_NFREG(0x2C)
+#define S3C2440_NFMECC1  S3C2410_NFREG(0x30)
+#define S3C2440_NFSECC   S3C2410_NFREG(0x34)
+#define S3C2440_NFSBLK   S3C2410_NFREG(0x38)
+#define S3C2440_NFEBLK   S3C2410_NFREG(0x3C)
+
+#define S3C2412_NFSBLK         S3C2410_NFREG(0x20)
+#define S3C2412_NFEBLK         S3C2410_NFREG(0x24)
+#define S3C2412_NFSTAT         S3C2410_NFREG(0x28)
+#define S3C2412_NFMECC_ERR0    S3C2410_NFREG(0x2C)
+#define S3C2412_NFMECC_ERR1    S3C2410_NFREG(0x30)
+#define S3C2412_NFMECC0                S3C2410_NFREG(0x34)
+#define S3C2412_NFMECC1                S3C2410_NFREG(0x38)
+#define S3C2412_NFSECC         S3C2410_NFREG(0x3C)
+
+#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)
+
+#define S3C2410_NFSTAT_BUSY        (1 << 0)
+
+#define S3C2440_NFCONF_BUSWIDTH_8      (0 << 0)
+#define S3C2440_NFCONF_BUSWIDTH_16     (1 << 0)
+#define S3C2440_NFCONF_ADVFLASH                (1 << 3)
+#define S3C2440_NFCONF_TACLS(x)                ((x) << 12)
+#define S3C2440_NFCONF_TWRPH0(x)       ((x) << 8)
+#define S3C2440_NFCONF_TWRPH1(x)       ((x) << 4)
+
+#define S3C2440_NFCONT_LOCKTIGHT       (1 << 13)
+#define S3C2440_NFCONT_SOFTLOCK                (1 << 12)
+#define S3C2440_NFCONT_ILLEGALACC_EN   (1 << 10)
+#define S3C2440_NFCONT_RNBINT_EN       (1 << 9)
+#define S3C2440_NFCONT_RN_FALLING      (1 << 8)
+#define S3C2440_NFCONT_SPARE_ECCLOCK   (1 << 6)
+#define S3C2440_NFCONT_MAIN_ECCLOCK    (1 << 5)
+#define S3C2440_NFCONT_INITECC         (1 << 4)
+#define S3C2440_NFCONT_nFCE                    (1 << 1)
+#define S3C2440_NFCONT_ENABLE          (1 << 0)
+
+#define S3C2440_NFSTAT_READY           (1 << 0)
+#define S3C2440_NFSTAT_nCE                     (1 << 1)
+#define S3C2440_NFSTAT_RnB_CHANGE      (1 << 2)
+#define S3C2440_NFSTAT_ILLEGAL_ACCESS  (1 << 3)
+
+#define S3C2412_NFCONF_NANDBOOT                (1 << 31)
+#define S3C2412_NFCONF_ECCCLKCON       (1 << 30)
+#define S3C2412_NFCONF_ECC_MLC         (1 << 24)
+#define S3C2412_NFCONF_TACLS_MASK      (7 << 12)       /* 1 extra bit of Tacls */
+
+#define S3C2412_NFCONT_ECC4_DIRWR      (1 << 18)
+#define S3C2412_NFCONT_LOCKTIGHT       (1 << 17)
+#define S3C2412_NFCONT_SOFTLOCK                (1 << 16)
+#define S3C2412_NFCONT_ECC4_ENCINT     (1 << 13)
+#define S3C2412_NFCONT_ECC4_DECINT     (1 << 12)
+#define S3C2412_NFCONT_MAIN_ECC_LOCK   (1 << 7)
+#define S3C2412_NFCONT_INIT_MAIN_ECC   (1 << 5)
+#define S3C2412_NFCONT_nFCE1           (1 << 2)
+#define S3C2412_NFCONT_nFCE0           (1 << 1)
+
+#define S3C2412_NFSTAT_ECC_ENCDONE     (1 << 7)
+#define S3C2412_NFSTAT_ECC_DECDONE     (1 << 6)
+#define S3C2412_NFSTAT_ILLEGAL_ACCESS  (1 << 5)
+#define S3C2412_NFSTAT_RnB_CHANGE      (1 << 4)
+#define S3C2412_NFSTAT_nFCE1           (1 << 3)
+#define S3C2412_NFSTAT_nFCE0           (1 << 2)
+#define S3C2412_NFSTAT_Res1                    (1 << 1)
+#define S3C2412_NFSTAT_READY           (1 << 0)
+
+#define S3C2412_NFECCERR_SERRDATA(x)   (((x) >> 21) & 0xf)
+#define S3C2412_NFECCERR_SERRBIT(x)            (((x) >> 18) & 0x7)
+#define S3C2412_NFECCERR_MERRDATA(x)   (((x) >> 7) & 0x3ff)
+#define S3C2412_NFECCERR_MERRBIT(x)            (((x) >> 4) & 0x7)
+#define S3C2412_NFECCERR_SPARE_ERR(x)  (((x) >> 2) & 0x3)
+#define S3C2412_NFECCERR_MAIN_ERR(x)   (((x) >> 2) & 0x3)
+#define S3C2412_NFECCERR_NONE          (0)
+#define S3C2412_NFECCERR_1BIT          (1)
+#define S3C2412_NFECCERR_MULTIBIT      (2)
+#define S3C2412_NFECCERR_ECCAREA       (3)
+
+#endif /* __ASM_ARM_REGS_NAND */
+
diff --git a/src/flash/nonce_nand.c b/src/flash/nonce_nand.c
deleted file mode 100644 (file)
index dae62a7..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net>             *
- *                                                                         *
- *   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.             *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "nand.h"
-
-
-static int nonce_nand_command(struct nand_device *nand, uint8_t command)
-{
-       return ERROR_OK;
-}
-static int nonce_nand_address(struct nand_device *nand, uint8_t address)
-{
-       return ERROR_OK;
-}
-static int nonce_nand_read(struct nand_device *nand, void *data)
-{
-       return ERROR_OK;
-}
-static int nonce_nand_write(struct nand_device *nand, uint16_t data)
-{
-       return ERROR_OK;
-}
-static int nonce_nand_fast_block_write(struct nand_device *nand,
-               uint8_t *data, int size)
-{
-       return ERROR_OK;
-}
-
-static int nonce_nand_reset(struct nand_device *nand)
-{
-       return nonce_nand_command(nand, NAND_CMD_RESET);
-}
-
-static int nonce_nand_controller_ready(struct nand_device *nand, int timeout)
-{
-       return true;
-}
-
-NAND_DEVICE_COMMAND_HANDLER(nonce_nand_device_command)
-{
-       return ERROR_OK;
-}
-
-static int nonce_nand_init(struct nand_device *nand)
-{
-       return ERROR_OK;
-}
-
-struct nand_flash_controller nonce_nand_controller =
-{
-       .name                   = "nonce",
-       .nand_device_command    = &nonce_nand_device_command,
-       .init                   = &nonce_nand_init,
-       .reset                  = &nonce_nand_reset,
-       .command                = &nonce_nand_command,
-       .address                = &nonce_nand_address,
-       .read_data              = &nonce_nand_read,
-       .write_data             = &nonce_nand_write,
-       .write_block_data       = &nonce_nand_fast_block_write,
-       .controller_ready       = &nonce_nand_controller_ready,
-};
diff --git a/src/flash/orion_nand.c b/src/flash/orion_nand.c
deleted file mode 100644 (file)
index 77a03f2..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Marvell Semiconductors, Inc.                    *
- *   Written by Nicolas Pitre <nico at marvell.com>                           *
- *                                                                         *
- *   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.             *
- ***************************************************************************/
-
-/*
- * NAND controller interface for Marvell Orion/Kirkwood SoCs.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm_nandio.h"
-#include "armv4_5.h"
-
-
-struct orion_nand_controller
-{
-       struct target   *target;
-
-       struct arm_nand_data    io;
-
-       uint32_t                cmd;
-       uint32_t                addr;
-       uint32_t                data;
-};
-
-#define CHECK_HALTED \
-       do { \
-               if (target->state != TARGET_HALTED) { \
-                       LOG_ERROR("NAND flash access requires halted target"); \
-                       return ERROR_NAND_OPERATION_FAILED; \
-               } \
-       } while (0)
-
-static int orion_nand_command(struct nand_device *nand, uint8_t command)
-{
-       struct orion_nand_controller *hw = nand->controller_priv;
-       struct target *target = hw->target;
-
-       CHECK_HALTED;
-       target_write_u8(target, hw->cmd, command);
-       return ERROR_OK;
-}
-
-static int orion_nand_address(struct nand_device *nand, uint8_t address)
-{
-       struct orion_nand_controller *hw = nand->controller_priv;
-       struct target *target = hw->target;
-
-       CHECK_HALTED;
-       target_write_u8(target, hw->addr, address);
-       return ERROR_OK;
-}
-
-static int orion_nand_read(struct nand_device *nand, void *data)
-{
-       struct orion_nand_controller *hw = nand->controller_priv;
-       struct target *target = hw->target;
-
-       CHECK_HALTED;
-       target_read_u8(target, hw->data, data);
-       return ERROR_OK;
-}
-
-static int orion_nand_write(struct nand_device *nand, uint16_t data)
-{
-       struct orion_nand_controller *hw = nand->controller_priv;
-       struct target *target = hw->target;
-
-       CHECK_HALTED;
-       target_write_u8(target, hw->data, data);
-       return ERROR_OK;
-}
-
-static int orion_nand_slow_block_write(struct nand_device *nand, uint8_t *data, int size)
-{
-       while (size--)
-               orion_nand_write(nand, *data++);
-       return ERROR_OK;
-}
-
-static int orion_nand_fast_block_write(struct nand_device *nand, uint8_t *data, int size)
-{
-       struct orion_nand_controller *hw = nand->controller_priv;
-       int retval;
-
-       hw->io.chunk_size = nand->page_size;
-
-       retval = arm_nandwrite(&hw->io, data, size);
-       if (retval == ERROR_NAND_NO_BUFFER)
-               retval = orion_nand_slow_block_write(nand, data, size);
-
-       return retval;
-}
-
-static int orion_nand_reset(struct nand_device *nand)
-{
-       return orion_nand_command(nand, NAND_CMD_RESET);
-}
-
-static int orion_nand_controller_ready(struct nand_device *nand, int timeout)
-{
-       return 1;
-}
-
-NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
-{
-       struct orion_nand_controller *hw;
-       uint32_t base;
-       uint8_t ale, cle;
-
-       if (CMD_ARGC != 3) {
-               LOG_ERROR("arguments must be: <target_id> <NAND_address>\n");
-               return ERROR_NAND_DEVICE_INVALID;
-       }
-
-       hw = calloc(1, sizeof(*hw));
-       if (!hw) {
-               LOG_ERROR("no memory for nand controller\n");
-               return ERROR_NAND_DEVICE_INVALID;
-       }
-
-       nand->controller_priv = hw;
-       hw->target = get_target(CMD_ARGV[1]);
-       if (!hw->target) {
-               LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
-               free(hw);
-               return ERROR_NAND_DEVICE_INVALID;
-       }
-
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], base);
-       cle = 0;
-       ale = 1;
-
-       hw->data = base;
-       hw->cmd = base + (1 << cle);
-       hw->addr = base + (1 << ale);
-
-       hw->io.target = hw->target;
-       hw->io.data = hw->data;
-
-       return ERROR_OK;
-}
-
-static int orion_nand_init(struct nand_device *nand)
-{
-       return ERROR_OK;
-}
-
-struct nand_flash_controller orion_nand_controller =
-{
-       .name                   = "orion",
-       .command                = orion_nand_command,
-       .address                = orion_nand_address,
-       .read_data              = orion_nand_read,
-       .write_data             = orion_nand_write,
-       .write_block_data       = orion_nand_fast_block_write,
-       .reset                  = orion_nand_reset,
-       .controller_ready       = orion_nand_controller_ready,
-       .nand_device_command    = orion_nand_device_command,
-       .init                   = orion_nand_init,
-};
-
diff --git a/src/flash/s3c2410_nand.c b/src/flash/s3c2410_nand.c
deleted file mode 100644 (file)
index ca50c99..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
- *   ben@fluff.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.             *
- ***************************************************************************/
-
-/*
- * S3C2410 OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx_nand.h"
-
-NAND_DEVICE_COMMAND_HANDLER(s3c2410_nand_device_command)
-{
-       struct s3c24xx_nand_controller *info;
-       CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
-       /* fill in the address fields for the core device */
-       info->cmd = S3C2410_NFCMD;
-       info->addr = S3C2410_NFADDR;
-       info->data = S3C2410_NFDATA;
-       info->nfstat = S3C2410_NFSTAT;
-
-       return ERROR_OK;
-}
-
-static int s3c2410_init(struct nand_device *nand)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       target_write_u32(target, S3C2410_NFCONF,
-                        S3C2410_NFCONF_EN | S3C2410_NFCONF_TACLS(3) |
-                        S3C2410_NFCONF_TWRPH0(5) | S3C2410_NFCONF_TWRPH1(3));
-
-       return ERROR_OK;
-}
-
-static int s3c2410_write_data(struct nand_device *nand, uint16_t data)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       target_write_u32(target, S3C2410_NFDATA, data);
-       return ERROR_OK;
-}
-
-static int s3c2410_read_data(struct nand_device *nand, void *data)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       target_read_u8(target, S3C2410_NFDATA, data);
-       return ERROR_OK;
-}
-
-static int s3c2410_nand_ready(struct nand_device *nand, int timeout)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-       uint8_t status;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       do {
-               target_read_u8(target, S3C2410_NFSTAT, &status);
-
-               if (status & S3C2410_NFSTAT_BUSY)
-                       return 1;
-
-               alive_sleep(1);
-       } while (timeout-- > 0);
-
-       return 0;
-}
-
-struct nand_flash_controller s3c2410_nand_controller = {
-               .name = "s3c2410",
-               .nand_device_command = &s3c2410_nand_device_command,
-               .init = &s3c2410_init,
-               .reset = &s3c24xx_reset,
-               .command = &s3c24xx_command,
-               .address = &s3c24xx_address,
-               .write_data = &s3c2410_write_data,
-               .read_data = &s3c2410_read_data,
-               .write_page = s3c24xx_write_page,
-               .read_page = s3c24xx_read_page,
-               .controller_ready = &s3c24xx_controller_ready,
-               .nand_ready = &s3c2410_nand_ready,
-       };
diff --git a/src/flash/s3c2412_nand.c b/src/flash/s3c2412_nand.c
deleted file mode 100644 (file)
index acc6d99..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
- *   ben@fluff.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.             *
- ***************************************************************************/
-
-/*
- * S3C2412 OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx_nand.h"
-
-NAND_DEVICE_COMMAND_HANDLER(s3c2412_nand_device_command)
-{
-       struct s3c24xx_nand_controller *info;
-       CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
-       /* fill in the address fields for the core device */
-       info->cmd = S3C2440_NFCMD;
-       info->addr = S3C2440_NFADDR;
-       info->data = S3C2440_NFDATA;
-       info->nfstat = S3C2412_NFSTAT;
-
-       return ERROR_OK;
-}
-
-static int s3c2412_init(struct nand_device *nand)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       target_write_u32(target, S3C2410_NFCONF,
-                        S3C2440_NFCONF_TACLS(3) |
-                        S3C2440_NFCONF_TWRPH0(7) |
-                        S3C2440_NFCONF_TWRPH1(7));
-
-       target_write_u32(target, S3C2440_NFCONT,
-                        S3C2412_NFCONT_INIT_MAIN_ECC |
-                        S3C2440_NFCONT_ENABLE);
-
-       return ERROR_OK;
-}
-
-struct nand_flash_controller s3c2412_nand_controller = {
-               .name = "s3c2412",
-               .nand_device_command = &s3c2412_nand_device_command,
-               .init = &s3c2412_init,
-               .reset = &s3c24xx_reset,
-               .command = &s3c24xx_command,
-               .address = &s3c24xx_address,
-               .write_data = &s3c24xx_write_data,
-               .read_data = &s3c24xx_read_data,
-               .write_page = s3c24xx_write_page,
-               .read_page = s3c24xx_read_page,
-               .write_block_data = &s3c2440_write_block_data,
-               .read_block_data = &s3c2440_read_block_data,
-               .controller_ready = &s3c24xx_controller_ready,
-               .nand_ready = &s3c2440_nand_ready,
-       };
diff --git a/src/flash/s3c2440_nand.c b/src/flash/s3c2440_nand.c
deleted file mode 100644 (file)
index 556f6f1..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
- *   ben@fluff.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.             *
- ***************************************************************************/
-
-/*
- * S3C2440 OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx_nand.h"
-
-
-NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
-{
-       struct s3c24xx_nand_controller *info;
-       CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
-       /* fill in the address fields for the core device */
-       info->cmd = S3C2440_NFCMD;
-       info->addr = S3C2440_NFADDR;
-       info->data = S3C2440_NFDATA;
-       info->nfstat = S3C2440_NFSTAT;
-
-       return ERROR_OK;
-}
-
-static int s3c2440_init(struct nand_device *nand)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       target_write_u32(target, S3C2410_NFCONF,
-                        S3C2440_NFCONF_TACLS(3) |
-                        S3C2440_NFCONF_TWRPH0(7) |
-                        S3C2440_NFCONF_TWRPH1(7));
-
-       target_write_u32(target, S3C2440_NFCONT,
-                        S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);
-
-       return ERROR_OK;
-}
-
-int s3c2440_nand_ready(struct nand_device *nand, int timeout)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-       uint8_t status;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       do {
-               target_read_u8(target, s3c24xx_info->nfstat, &status);
-
-               if (status & S3C2440_NFSTAT_READY)
-                       return 1;
-
-               alive_sleep(1);
-       } while (timeout-- > 0);
-
-
-       return 0;
-}
-
-/* use the fact we can read/write 4 bytes in one go via a single 32bit op */
-
-int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-       uint32_t nfdata = s3c24xx_info->data;
-       uint32_t tmp;
-
-       LOG_INFO("%s: reading data: %p, %p, %d\n", __func__, nand, data, data_size);
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       while (data_size >= 4) {
-               target_read_u32(target, nfdata, &tmp);
-
-               data[0] = tmp;
-               data[1] = tmp >> 8;
-               data[2] = tmp >> 16;
-               data[3] = tmp >> 24;
-
-               data_size -= 4;
-               data += 4;
-       }
-
-       while (data_size > 0) {
-               target_read_u8(target, nfdata, data);
-
-               data_size -= 1;
-               data += 1;
-       }
-
-       return ERROR_OK;
-}
-
-int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-       uint32_t nfdata = s3c24xx_info->data;
-       uint32_t tmp;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       while (data_size >= 4) {
-               tmp = le_to_h_u32(data);
-               target_write_u32(target, nfdata, tmp);
-
-               data_size -= 4;
-               data += 4;
-       }
-
-       while (data_size > 0) {
-               target_write_u8(target, nfdata, *data);
-
-               data_size -= 1;
-               data += 1;
-       }
-
-       return ERROR_OK;
-}
-
-struct nand_flash_controller s3c2440_nand_controller = {
-               .name = "s3c2440",
-               .nand_device_command = &s3c2440_nand_device_command,
-               .init = &s3c2440_init,
-               .reset = &s3c24xx_reset,
-               .command = &s3c24xx_command,
-               .address = &s3c24xx_address,
-               .write_data = &s3c24xx_write_data,
-               .read_data = &s3c24xx_read_data,
-               .write_page = s3c24xx_write_page,
-               .read_page = s3c24xx_read_page,
-               .write_block_data = &s3c2440_write_block_data,
-               .read_block_data = &s3c2440_read_block_data,
-               .controller_ready = &s3c24xx_controller_ready,
-               .nand_ready = &s3c2440_nand_ready,
-       };
diff --git a/src/flash/s3c2443_nand.c b/src/flash/s3c2443_nand.c
deleted file mode 100644 (file)
index 311bb69..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
- *   ben@fluff.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.             *
- ***************************************************************************/
-
-/*
- * S3C2443 OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx_nand.h"
-
-
-NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command)
-{
-       struct s3c24xx_nand_controller *info;
-       CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
-       /* fill in the address fields for the core device */
-       info->cmd = S3C2440_NFCMD;
-       info->addr = S3C2440_NFADDR;
-       info->data = S3C2440_NFDATA;
-       info->nfstat = S3C2412_NFSTAT;
-
-       return ERROR_OK;
-}
-
-static int s3c2443_init(struct nand_device *nand)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       target_write_u32(target, S3C2410_NFCONF,
-                        S3C2440_NFCONF_TACLS(3) |
-                        S3C2440_NFCONF_TWRPH0(7) |
-                        S3C2440_NFCONF_TWRPH1(7));
-
-       target_write_u32(target, S3C2440_NFCONT,
-                        S3C2412_NFCONT_INIT_MAIN_ECC |
-                        S3C2440_NFCONT_ENABLE);
-
-       return ERROR_OK;
-}
-
-struct nand_flash_controller s3c2443_nand_controller = {
-               .name = "s3c2443",
-               .nand_device_command = &s3c2443_nand_device_command,
-               .init = &s3c2443_init,
-               .reset = &s3c24xx_reset,
-               .command = &s3c24xx_command,
-               .address = &s3c24xx_address,
-               .write_data = &s3c24xx_write_data,
-               .read_data = &s3c24xx_read_data,
-               .write_page = s3c24xx_write_page,
-               .read_page = s3c24xx_read_page,
-               .write_block_data = &s3c2440_write_block_data,
-               .read_block_data = &s3c2440_read_block_data,
-               .controller_ready = &s3c24xx_controller_ready,
-               .nand_ready = &s3c2440_nand_ready,
-       };
diff --git a/src/flash/s3c24xx_nand.c b/src/flash/s3c24xx_nand.c
deleted file mode 100644 (file)
index 1a2ece7..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
- *   ben@fluff.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.             *
- ***************************************************************************/
-
-/*
- * S3C24XX Series OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx_nand.h"
-
-
-S3C24XX_DEVICE_COMMAND()
-{
-       *info = NULL;
-
-       struct s3c24xx_nand_controller *s3c24xx_info;
-       s3c24xx_info = malloc(sizeof(struct s3c24xx_nand_controller));
-       if (s3c24xx_info == NULL) {
-               LOG_ERROR("no memory for nand controller\n");
-               return -ENOMEM;
-       }
-
-       nand->controller_priv = s3c24xx_info;
-
-       s3c24xx_info->target = get_target(CMD_ARGV[1]);
-       if (s3c24xx_info->target == NULL) {
-               LOG_ERROR("target '%s' not defined", CMD_ARGV[1]);
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       *info = s3c24xx_info;
-
-       return ERROR_OK;
-}
-
-int s3c24xx_reset(struct nand_device *nand)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       target_write_u32(target, s3c24xx_info->cmd, 0xff);
-
-       return ERROR_OK;
-}
-
-int s3c24xx_command(struct nand_device *nand, uint8_t command)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       target_write_u16(target, s3c24xx_info->cmd, command);
-       return ERROR_OK;
-}
-
-
-int s3c24xx_address(struct nand_device *nand, uint8_t address)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       target_write_u16(target, s3c24xx_info->addr, address);
-       return ERROR_OK;
-}
-
-int s3c24xx_write_data(struct nand_device *nand, uint16_t data)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       target_write_u8(target, s3c24xx_info->data, data);
-       return ERROR_OK;
-}
-
-int s3c24xx_read_data(struct nand_device *nand, void *data)
-{
-       struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
-       struct target *target = s3c24xx_info->target;
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
-               return ERROR_NAND_OPERATION_FAILED;
-       }
-
-       target_read_u8(target, s3c24xx_info->data, data);
-       return ERROR_OK;
-}
-
-int s3c24xx_controller_ready(struct nand_device *nand, int timeout)
-{
-       return 1;
-}
diff --git a/src/flash/s3c24xx_nand.h b/src/flash/s3c24xx_nand.h
deleted file mode 100644 (file)
index fad33a0..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007, 2008 by Ben Dooks                                 *
- *   ben@fluff.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.             *
- ***************************************************************************/
-
-#ifndef S3C24xx_NAND_H
-#define S3C24xx_NAND_H
-
-/*
- * S3C24XX Series OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#include "nand.h"
-#include "s3c24xx_regs_nand.h"
-
-struct s3c24xx_nand_controller
-{
-       struct target *target;
-
-       /* register addresses */
-       uint32_t                 cmd;
-       uint32_t                 addr;
-       uint32_t                 data;
-       uint32_t                 nfstat;
-};
-
-/* Default to using the un-translated NAND register based address */
-#undef S3C2410_NFREG
-#define S3C2410_NFREG(x) ((x) + 0x4e000000)
-
-#define S3C24XX_DEVICE_COMMAND() \
-               COMMAND_HELPER(s3c24xx_nand_device_command, \
-                               struct nand_device *nand, \
-                               struct s3c24xx_nand_controller **info)
-
-S3C24XX_DEVICE_COMMAND();
-
-#define CALL_S3C24XX_DEVICE_COMMAND(d, i) \
-       do { \
-               int retval = CALL_COMMAND_HANDLER(s3c24xx_nand_device_command, d, i); \
-               if (ERROR_OK != retval) \
-                       return retval; \
-       } while (0)
-
-int s3c24xx_reset(struct nand_device *nand);
-
-int s3c24xx_command(struct nand_device *nand, uint8_t command);
-int s3c24xx_address(struct nand_device *nand, uint8_t address);
-
-int s3c24xx_write_data(struct nand_device *nand, uint16_t data);
-int s3c24xx_read_data(struct nand_device *nand, void *data);
-
-int s3c24xx_controller_ready(struct nand_device *nand, int tout);
-
-#define s3c24xx_write_page NULL
-#define s3c24xx_read_page NULL
-
-/* code shared between different controllers */
-
-int s3c2440_nand_ready(struct nand_device *nand, int timeout);
-
-int s3c2440_read_block_data(struct nand_device *nand,
-               uint8_t *data, int data_size);
-int s3c2440_write_block_data(struct nand_device *nand,
-               uint8_t *data, int data_size);
-
-#endif // S3C24xx_NAND_H
diff --git a/src/flash/s3c24xx_regs_nand.h b/src/flash/s3c24xx_regs_nand.h
deleted file mode 100644 (file)
index c8cbe78..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2004, 2005 by Simtec Electronics                        *
- *   linux@simtec.co.uk                                                    *
- *   http://www.simtec.co.uk/products/SWLINUX/                             *
- *                                                                         *
- *   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; version 2 of the License.               *
- *                                                                         *
- *   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.             *
- ***************************************************************************/
-
-/*
- * S3C2410 NAND register definitions
- */
-
-#ifndef __ASM_ARM_REGS_NAND
-#define __ASM_ARM_REGS_NAND "$Id: nand.h,v 1.3 2003/12/09 11:36:29 ben Exp $"
-
-#define S3C2410_NFREG(x) (x)
-
-#define S3C2410_NFCONF  S3C2410_NFREG(0x00)
-#define S3C2410_NFCMD   S3C2410_NFREG(0x04)
-#define S3C2410_NFADDR  S3C2410_NFREG(0x08)
-#define S3C2410_NFDATA  S3C2410_NFREG(0x0C)
-#define S3C2410_NFSTAT  S3C2410_NFREG(0x10)
-#define S3C2410_NFECC   S3C2410_NFREG(0x14)
-
-#define S3C2440_NFCONT   S3C2410_NFREG(0x04)
-#define S3C2440_NFCMD    S3C2410_NFREG(0x08)
-#define S3C2440_NFADDR   S3C2410_NFREG(0x0C)
-#define S3C2440_NFDATA   S3C2410_NFREG(0x10)
-#define S3C2440_NFECCD0  S3C2410_NFREG(0x14)
-#define S3C2440_NFECCD1  S3C2410_NFREG(0x18)
-#define S3C2440_NFECCD   S3C2410_NFREG(0x1C)
-#define S3C2440_NFSTAT   S3C2410_NFREG(0x20)
-#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24)
-#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
-#define S3C2440_NFMECC0  S3C2410_NFREG(0x2C)
-#define S3C2440_NFMECC1  S3C2410_NFREG(0x30)
-#define S3C2440_NFSECC   S3C2410_NFREG(0x34)
-#define S3C2440_NFSBLK   S3C2410_NFREG(0x38)
-#define S3C2440_NFEBLK   S3C2410_NFREG(0x3C)
-
-#define S3C2412_NFSBLK         S3C2410_NFREG(0x20)
-#define S3C2412_NFEBLK         S3C2410_NFREG(0x24)
-#define S3C2412_NFSTAT         S3C2410_NFREG(0x28)
-#define S3C2412_NFMECC_ERR0    S3C2410_NFREG(0x2C)
-#define S3C2412_NFMECC_ERR1    S3C2410_NFREG(0x30)
-#define S3C2412_NFMECC0                S3C2410_NFREG(0x34)
-#define S3C2412_NFMECC1                S3C2410_NFREG(0x38)
-#define S3C2412_NFSECC         S3C2410_NFREG(0x3C)
-
-#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)
-
-#define S3C2410_NFSTAT_BUSY        (1 << 0)
-
-#define S3C2440_NFCONF_BUSWIDTH_8      (0 << 0)
-#define S3C2440_NFCONF_BUSWIDTH_16     (1 << 0)
-#define S3C2440_NFCONF_ADVFLASH                (1 << 3)
-#define S3C2440_NFCONF_TACLS(x)                ((x) << 12)
-#define S3C2440_NFCONF_TWRPH0(x)       ((x) << 8)
-#define S3C2440_NFCONF_TWRPH1(x)       ((x) << 4)
-
-#define S3C2440_NFCONT_LOCKTIGHT       (1 << 13)
-#define S3C2440_NFCONT_SOFTLOCK                (1 << 12)
-#define S3C2440_NFCONT_ILLEGALACC_EN   (1 << 10)
-#define S3C2440_NFCONT_RNBINT_EN       (1 << 9)
-#define S3C2440_NFCONT_RN_FALLING      (1 << 8)
-#define S3C2440_NFCONT_SPARE_ECCLOCK   (1 << 6)
-#define S3C2440_NFCONT_MAIN_ECCLOCK    (1 << 5)
-#define S3C2440_NFCONT_INITECC         (1 << 4)
-#define S3C2440_NFCONT_nFCE                    (1 << 1)
-#define S3C2440_NFCONT_ENABLE          (1 << 0)
-
-#define S3C2440_NFSTAT_READY           (1 << 0)
-#define S3C2440_NFSTAT_nCE                     (1 << 1)
-#define S3C2440_NFSTAT_RnB_CHANGE      (1 << 2)
-#define S3C2440_NFSTAT_ILLEGAL_ACCESS  (1 << 3)
-
-#define S3C2412_NFCONF_NANDBOOT                (1 << 31)
-#define S3C2412_NFCONF_ECCCLKCON       (1 << 30)
-#define S3C2412_NFCONF_ECC_MLC         (1 << 24)
-#define S3C2412_NFCONF_TACLS_MASK      (7 << 12)       /* 1 extra bit of Tacls */
-
-#define S3C2412_NFCONT_ECC4_DIRWR      (1 << 18)
-#define S3C2412_NFCONT_LOCKTIGHT       (1 << 17)
-#define S3C2412_NFCONT_SOFTLOCK                (1 << 16)
-#define S3C2412_NFCONT_ECC4_ENCINT     (1 << 13)
-#define S3C2412_NFCONT_ECC4_DECINT     (1 << 12)
-#define S3C2412_NFCONT_MAIN_ECC_LOCK   (1 << 7)
-#define S3C2412_NFCONT_INIT_MAIN_ECC   (1 << 5)
-#define S3C2412_NFCONT_nFCE1           (1 << 2)
-#define S3C2412_NFCONT_nFCE0           (1 << 1)
-
-#define S3C2412_NFSTAT_ECC_ENCDONE     (1 << 7)
-#define S3C2412_NFSTAT_ECC_DECDONE     (1 << 6)
-#define S3C2412_NFSTAT_ILLEGAL_ACCESS  (1 << 5)
-#define S3C2412_NFSTAT_RnB_CHANGE      (1 << 4)
-#define S3C2412_NFSTAT_nFCE1           (1 << 3)
-#define S3C2412_NFSTAT_nFCE0           (1 << 2)
-#define S3C2412_NFSTAT_Res1                    (1 << 1)
-#define S3C2412_NFSTAT_READY           (1 << 0)
-
-#define S3C2412_NFECCERR_SERRDATA(x)   (((x) >> 21) & 0xf)
-#define S3C2412_NFECCERR_SERRBIT(x)            (((x) >> 18) & 0x7)
-#define S3C2412_NFECCERR_MERRDATA(x)   (((x) >> 7) & 0x3ff)
-#define S3C2412_NFECCERR_MERRBIT(x)            (((x) >> 4) & 0x7)
-#define S3C2412_NFECCERR_SPARE_ERR(x)  (((x) >> 2) & 0x3)
-#define S3C2412_NFECCERR_MAIN_ERR(x)   (((x) >> 2) & 0x3)
-#define S3C2412_NFECCERR_NONE          (0)
-#define S3C2412_NFECCERR_1BIT          (1)
-#define S3C2412_NFECCERR_MULTIBIT      (2)
-#define S3C2412_NFECCERR_ECCAREA       (3)
-
-#endif /* __ASM_ARM_REGS_NAND */
-