minor JTAG init messaging tweaks
[fw/openocd] / src / flash / davinci_nand.c
index 7ccd080f9092ecb09a1a82d293625ac8e0f3b885..41c2b20ab1f399f43e164efd8e6adbac96412b17 100644 (file)
@@ -28,7 +28,7 @@
 #include "config.h"
 #endif
 
-#include "nand.h"
+#include "arm_nandio.h"
 
 
 enum ecc {
@@ -51,6 +51,9 @@ struct davinci_nand {
        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_s *nand, uint32_t page,
                        uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
@@ -181,7 +184,7 @@ static int davinci_read_data(struct nand_device_s *nand, void *data)
        return ERROR_OK;
 }
 
-/* REVISIT a bit of native code should let block I/O be MUCH faster */
+/* REVISIT a bit of native code should let block reads be MUCH faster */
 
 static int davinci_read_block_data(struct nand_device_s *nand,
                uint8_t *data, int data_size)
@@ -223,10 +226,17 @@ static int davinci_write_block_data(struct nand_device_s *nand,
        target_t *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);
@@ -285,6 +295,12 @@ static int davinci_write_page(struct nand_device_s *nand, uint32_t page,
                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;
@@ -365,7 +381,7 @@ static int davinci_write_page_ecc1(struct nand_device_s *nand, uint32_t page,
        struct davinci_nand *info = nand->controller_priv;
        target_t *target = info->target;
        const uint32_t fcr_addr = info->aemif + NANDFCR;
-       const uint32_t ecc1_addr = info->aemif + NANDFECC + info->chipsel;
+       const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel);
        uint32_t fcr, ecc1;
 
        /* Write contiguous ECC bytes starting at specified offset.
@@ -663,7 +679,7 @@ static int davinci_nand_device_command(struct command_context_s *cmd_ctx,
        }
 
        aemif = strtoul(argv[4], &ep, 0);
-       if (*ep || chip == 0 || chip == ULONG_MAX) {
+       if (*ep || aemif == 0 || aemif == ULONG_MAX) {
                LOG_ERROR("Invalid AEMIF controller address %s", argv[4]);
                goto fail;
        }
@@ -675,12 +691,12 @@ static int davinci_nand_device_command(struct command_context_s *cmd_ctx,
        if (aemif == 0x01e00000                 /* dm6446, dm357 */
                        || aemif == 0x01e10000  /* dm335, dm355 */
                        || aemif == 0x01d10000  /* dm365 */
-) {
-               if (chip < 0x0200000 || chip >= 0x0a000000) {
+                       ) {
+               if (chip < 0x02000000 || chip >= 0x0a000000) {
                        LOG_ERROR("NAND address %08lx out of range?", chip);
                        goto fail;
                }
-               chipsel = (chip - 0x02000000) >> 21;
+               chipsel = (chip - 0x02000000) >> 25;
        } else {
                LOG_ERROR("unrecognized AEMIF controller address %08lx", aemif);
                goto fail;
@@ -700,6 +716,9 @@ static int davinci_nand_device_command(struct command_context_s *cmd_ctx,
 
        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.