- add support for the majority of the Samsung ARM SoC family, S3C2410, S3C2412, S3C24...
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Tue, 19 Feb 2008 19:52:09 +0000 (19:52 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Tue, 19 Feb 2008 19:52:09 +0000 (19:52 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@311 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/flash/Makefile.am
src/flash/nand.c
src/flash/nand.h
src/flash/s3c2410_nand.c [new file with mode: 0644]
src/flash/s3c2412_nand.c [new file with mode: 0644]
src/flash/s3c2440_nand.c [new file with mode: 0644]
src/flash/s3c2443_nand.c [new file with mode: 0644]
src/flash/s3c24xx_nand.c [new file with mode: 0644]
src/flash/s3c24xx_nand.h [new file with mode: 0644]
src/flash/s3c24xx_regs_nand.h [new file with mode: 0644]

index 37dee8b539fa3699ad64ac0be7c8d717c2c040cf..90f009e9161f7eb25104b8a30f422965ad5eae05 100644 (file)
@@ -3,6 +3,7 @@ AM_CPPFLAGS = -DPKGLIBDIR=\"$(pkglibdir)\" @CPPFLAGS@
 METASOURCES = AUTO
 noinst_LIBRARIES = libflash.a
 libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c \
-                                        stellaris.c str9xpec.c stm32x.c tms470.c
+                                        stellaris.c str9xpec.c stm32x.c tms470.c \
+                    s3c24xx_nand.c s3c2410_nand.c s3c2412_nand.c s3c2440_nand.c s3c2443_nand.c
 noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h \
-                                stellaris.h str9xpec.h stm32x.h tms470.h
+                                stellaris.h str9xpec.h stm32x.h tms470.h s3c24xx_nand.h s3c24xx_regs_nand.h
index 52c923287ea01b4e1389edaf8e7139a58112529d..3c00db1dd53460f973e8151d7eb495f72b76e908 100644 (file)
@@ -63,13 +63,20 @@ int nand_write_page(struct nand_device_s *device, u32 page, u8 *data, u32 data_s
 /* NAND flash controller
  */
 extern nand_flash_controller_t lpc3180_nand_controller;
-/* extern nand_flash_controller_t s3c2410_nand_controller; */
+extern nand_flash_controller_t s3c2410_nand_controller;
+extern nand_flash_controller_t s3c2412_nand_controller;
+extern nand_flash_controller_t s3c2440_nand_controller;
+extern nand_flash_controller_t s3c2443_nand_controller;
+
 /* extern nand_flash_controller_t boundary_scan_nand_controller; */
 
 nand_flash_controller_t *nand_flash_controllers[] =
 {
        &lpc3180_nand_controller,
-/*     &s3c2410_nand_controller, */
+       &s3c2410_nand_controller,
+       &s3c2412_nand_controller,
+       &s3c2440_nand_controller,
+       &s3c2443_nand_controller,
 /*     &boundary_scan_nand_controller, */
        NULL
 };
@@ -707,7 +714,7 @@ int nand_write_page(struct nand_device_s *device, u32 page, u8 *data, u32 data_s
        if (!device->device)
                return ERROR_NAND_DEVICE_NOT_PROBED;
                
-       if (device->use_raw)
+       if (device->use_raw || device->controller->write_page == NULL)
                return nand_write_page_raw(device, page, data, data_size, oob, oob_size);
        else
                return device->controller->write_page(device, page, data, data_size, oob, oob_size);
@@ -718,7 +725,7 @@ int nand_read_page(struct nand_device_s *device, u32 page, u8 *data, u32 data_si
        if (!device->device)
                return ERROR_NAND_DEVICE_NOT_PROBED;
                
-       if (device->use_raw)
+       if (device->use_raw || device->controller->read_page == NULL)
                return nand_read_page_raw(device, page, data, data_size, oob, oob_size);
        else
                return device->controller->read_page(device, page, data, data_size, oob, oob_size);
@@ -782,38 +789,48 @@ int nand_read_page_raw(struct nand_device_s *device, u32 page, u8 *data, u32 dat
        
        if (data)
        {
-               for (i = 0; i < data_size;)
+               if (device->controller->read_block_data != NULL)
+                       (device->controller->read_block_data)(device, data, data_size);
+               else
                {
-                       if (device->device->options & NAND_BUSWIDTH_16)
-                       {
-                               device->controller->read_data(device, data);
-                               data += 2;
-                               i += 2;
-                       }
-                       else
+                       for (i = 0; i < data_size;)
                        {
-                               device->controller->read_data(device, data);
-                               data += 1;
-                               i += 1;
+                               if (device->device->options & NAND_BUSWIDTH_16)
+                               {
+                                       device->controller->read_data(device, data);
+                                       data += 2;
+                                       i += 2;
+                               }
+                               else
+                               {
+                                       device->controller->read_data(device, data);
+                                       data += 1;
+                                       i += 1;
+                               }
                        }
                }
        }
        
        if (oob)
        {
-               for (i = 0; i < oob_size;)
+               if (device->controller->read_block_data != NULL)
+                       (device->controller->read_block_data)(device, oob, oob_size);
+               else
                {
-                       if (device->device->options & NAND_BUSWIDTH_16)
+                       for (i = 0; i < oob_size;)
                        {
-                               device->controller->read_data(device, oob);
-                               oob += 2;
-                               i += 2;
-                       }
-                       else
-                       {
-                               device->controller->read_data(device, oob);
-                               oob += 1;
-                               i += 1;
+                               if (device->device->options & NAND_BUSWIDTH_16)
+                               {
+                                       device->controller->read_data(device, oob);
+                                       oob += 2;
+                                       i += 2;
+                               }
+                               else
+                               {
+                                       device->controller->read_data(device, oob);
+                                       oob += 1;
+                                       i += 1;
+                               }
                        }
                }
        }
@@ -868,40 +885,50 @@ int nand_write_page_raw(struct nand_device_s *device, u32 page, u8 *data, u32 da
        
        if (data)
        {
-               for (i = 0; i < data_size;)
+               if (device->controller->write_block_data != NULL)
+                       (device->controller->write_block_data)(device, data, data_size);
+               else
                {
-                       if (device->device->options & NAND_BUSWIDTH_16)
+                       for (i = 0; i < data_size;)
                        {
-                               u16 data_buf = le_to_h_u16(data);
-                               device->controller->write_data(device, data_buf);
-                               data += 2;
-                               i += 2;
-                       }
-                       else
-                       {
-                               device->controller->write_data(device, *data);
-                               data += 1;
-                               i += 1;
+                               if (device->device->options & NAND_BUSWIDTH_16)
+                               {
+                                       u16 data_buf = le_to_h_u16(data);
+                                       device->controller->write_data(device, data_buf);
+                                       data += 2;
+                                       i += 2;
+                               }
+                               else
+                               {
+                                       device->controller->write_data(device, *data);
+                                       data += 1;
+                                       i += 1;
+                               }
                        }
                }
        }
        
        if (oob)
        {
-               for (i = 0; i < oob_size;)
+               if (device->controller->write_block_data != NULL)
+                       (device->controller->write_block_data)(device, oob, oob_size);
+               else
                {
-                       if (device->device->options & NAND_BUSWIDTH_16)
+                       for (i = 0; i < oob_size;)
                        {
-                               u16 oob_buf = le_to_h_u16(data);
-                               device->controller->write_data(device, oob_buf);
-                               oob += 2;
-                               i += 2;
-                       }
-                       else
-                       {
-                               device->controller->write_data(device, *oob);
-                               oob += 1;
-                               i += 1;
+                               if (device->device->options & NAND_BUSWIDTH_16)
+                               {
+                                       u16 oob_buf = le_to_h_u16(data);
+                                       device->controller->write_data(device, oob_buf);
+                                       oob += 2;
+                                       i += 2;
+                               }
+                               else
+                               {
+                                       device->controller->write_data(device, *oob);
+                                       oob += 1;
+                                       i += 1;
+                               }
                        }
                }
        }
index 7161c50619dba05522a01c347d581220aaafeb30..cb18b0c8c278d0bc81b4ae596eabdfff9bd79feb 100644 (file)
@@ -42,6 +42,8 @@ typedef struct nand_flash_controller_s
        int (*address)(struct nand_device_s *device, u8 address);
        int (*write_data)(struct nand_device_s *device, u16 data);
        int (*read_data)(struct nand_device_s *device, void *data);
+       int (*write_block_data)(struct nand_device_s *device, u8 *data, int size);
+       int (*read_block_data)(struct nand_device_s *device, u8 *data, int size);
        int (*write_page)(struct nand_device_s *device, u32 page, u8 *data, u32 data_size, u8 *oob, u32 oob_size);
        int (*read_page)(struct nand_device_s *device, u32 page, u8 *data, u32 data_size, u8 *oob, u32 oob_size);
        int (*controller_ready)(struct nand_device_s *device, int timeout);
diff --git a/src/flash/s3c2410_nand.c b/src/flash/s3c2410_nand.c
new file mode 100644 (file)
index 0000000..436eb15
--- /dev/null
@@ -0,0 +1,133 @@
+/* src/flash/s3c2410_nand.c
+ *
+ * S3C2410 OpenOCD NAND Flash controller support.
+ *
+ * Copyright 2007,2008 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.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nand.h"
+#include "s3c24xx_nand.h"
+#include "target.h"
+
+int s3c2410_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
+int s3c2410_init(struct nand_device_s *device);
+int s3c2410_read_data(struct nand_device_s *device, void *data);
+int s3c2410_write_data(struct nand_device_s *device, u16 data);
+int s3c2410_nand_ready(struct nand_device_s *device, int timeout);
+
+nand_flash_controller_t s3c2410_nand_controller =
+{
+       .name                   = "s3c2410",
+       .nand_device_command    = s3c2410_nand_device_command,
+       .register_commands      = s3c24xx_register_commands,
+       .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,
+};
+
+int s3c2410_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
+                               char **args, int argc,
+                               struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *info;
+       
+       info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);
+       if (info == NULL) {
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       /* 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;
+}
+
+int s3c2410_init(struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *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;
+}
+
+int s3c2410_write_data(struct nand_device_s *device, u16 data)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               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;
+}
+
+int s3c2410_read_data(struct nand_device_s *device, void *data)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       
+       if (target->state != TARGET_HALTED) {
+               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;
+}
+
+int s3c2410_nand_ready(struct nand_device_s *device, int timeout)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u8 status;
+
+       if (target->state != TARGET_HALTED) {
+               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;
+
+               usleep(1000);           
+       } while (timeout-- > 0);
+
+       return 0;
+}
diff --git a/src/flash/s3c2412_nand.c b/src/flash/s3c2412_nand.c
new file mode 100644 (file)
index 0000000..ab7a7be
--- /dev/null
@@ -0,0 +1,87 @@
+/* src/flash/s3c2412_nand.c
+ *
+ * S3C2412 OpenOCD NAND Flash controller support.
+ *
+ * Copyright 2007,2008 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.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nand.h"
+#include "s3c24xx_nand.h"
+#include "target.h"
+
+int s3c2412_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
+int s3c2412_init(struct nand_device_s *device);
+
+nand_flash_controller_t s3c2412_nand_controller =
+{
+       .name                   = "s3c2412",
+       .nand_device_command    = s3c2412_nand_device_command,
+       .register_commands      = s3c24xx_register_commands,
+       .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,
+};
+
+int s3c2412_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
+                               char **args, int argc,
+                               struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *info;
+
+       info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);
+       if (info == NULL) {
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       /* 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;
+}
+
+int s3c2412_init(struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u32 version;
+
+       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;
+}
diff --git a/src/flash/s3c2440_nand.c b/src/flash/s3c2440_nand.c
new file mode 100644 (file)
index 0000000..fd19719
--- /dev/null
@@ -0,0 +1,179 @@
+/* src/flash/s3c2440_nand.c
+ *
+ * S3C2440 OpenOCD NAND Flash controller support.
+ *
+ * Copyright 2007,2008 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.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nand.h"
+#include "s3c24xx_nand.h"
+#include "target.h"
+
+int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
+int s3c2440_init(struct nand_device_s *device);
+int s3c2440_nand_ready(struct nand_device_s *device, int timeout);
+
+nand_flash_controller_t s3c2440_nand_controller =
+{
+       .name                   = "s3c2440",
+       .nand_device_command    = s3c2440_nand_device_command,
+       .register_commands      = s3c24xx_register_commands,
+       .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,
+};
+
+int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
+                               char **args, int argc,
+                               struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *info;
+       
+       info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);
+       if (info == NULL) {
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       /* 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;
+}
+
+int s3c2440_init(struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u32 version;
+
+       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_s *device, int timeout)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u8 status;
+
+       if (target->state != TARGET_HALTED) {
+               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;
+
+               usleep(1000);
+       } 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_s *device, u8 *data, int data_size)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u32 nfdata = s3c24xx_info->data;
+       u32 tmp;
+
+       printf("%s: reading data: %p, %p, %d\n", __func__, device, data, data_size);
+
+       if (target->state != TARGET_HALTED) {
+               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_s *device, u8 *data, int data_size)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u32 nfdata = s3c24xx_info->data;
+       u32 tmp;
+
+       if (target->state != TARGET_HALTED) {
+               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;
+}
diff --git a/src/flash/s3c2443_nand.c b/src/flash/s3c2443_nand.c
new file mode 100644 (file)
index 0000000..56e84b6
--- /dev/null
@@ -0,0 +1,89 @@
+/* src/flash/s3c2443_nand.c
+ *
+ * S3C2443 OpenOCD NAND Flash controller support.
+ *
+ * Copyright 2007,2008 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.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nand.h"
+#include "s3c24xx_nand.h"
+#include "target.h"
+
+int s3c2443_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
+int s3c2443_init(struct nand_device_s *device);
+int s3c2443_nand_ready(struct nand_device_s *device, int timeout);
+
+nand_flash_controller_t s3c2443_nand_controller =
+{
+       .name                   = "s3c2443",
+       .nand_device_command    = s3c2443_nand_device_command,
+       .register_commands      = s3c24xx_register_commands,
+       .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,
+};
+
+int s3c2443_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
+                               char **args, int argc,
+                               struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *info;
+       
+       info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);
+       if (info == NULL) {
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       /* 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;
+}
+
+int s3c2443_init(struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u32 version;
+
+       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;
+}
diff --git a/src/flash/s3c24xx_nand.c b/src/flash/s3c24xx_nand.c
new file mode 100644 (file)
index 0000000..6bde224
--- /dev/null
@@ -0,0 +1,133 @@
+/* src/flash/s3c24xx_nand.c
+ *
+ * S3C24XX Series OpenOCD NAND Flash controller support.
+ *
+ * Copyright 2007,2008 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.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nand.h"
+#include "s3c24xx_nand.h"
+#include "target.h"
+
+s3c24xx_nand_controller_t *
+s3c24xx_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
+                           char **args, int argc,
+                           struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info;
+       
+       s3c24xx_info = malloc(sizeof(s3c24xx_nand_controller_t));
+       if (s3c24xx_info == NULL) {
+               ERROR("no memory for nand controller\n");
+               return NULL;
+       }
+
+       device->controller_priv = s3c24xx_info;
+
+       s3c24xx_info->target = get_target_by_num(strtoul(args[1], NULL, 0));
+       if (s3c24xx_info->target == NULL) {
+               ERROR("no target '%s' configured", args[1]);
+               return NULL;
+       }
+               
+       return s3c24xx_info;
+}
+
+int s3c24xx_register_commands(struct command_context_s *cmd_ctx)
+{
+       return ERROR_OK;
+}
+
+int s3c24xx_reset(struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               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_s *device, u8 command)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       
+       if (target->state != TARGET_HALTED) {
+               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_s *device, u8 address)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       
+       if (target->state != TARGET_HALTED) {
+               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_s *device, u16 data)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+
+       if (target->state != TARGET_HALTED) {
+               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_s *device, void *data)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       
+       if (target->state != TARGET_HALTED) {
+               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_s *device, int timeout)
+{
+       return 1;
+}
diff --git a/src/flash/s3c24xx_nand.h b/src/flash/s3c24xx_nand.h
new file mode 100644 (file)
index 0000000..f419352
--- /dev/null
@@ -0,0 +1,51 @@
+/* src/flash/s3c24xx_nand.h
+ *
+ * S3C24XX Series OpenOCD NAND Flash controller support.
+ *
+ * Copyright 2007,2008 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.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#include "target.h"
+#include "s3c24xx_regs_nand.h"
+
+typedef struct s3c24xx_nand_controller_s
+{
+       struct target_s *target;
+       
+       /* register addresses */
+       u32              cmd;
+       u32              addr;
+       u32              data;
+       u32              nfstat; 
+} s3c24xx_nand_controller_t;
+
+/* Default to using the un-translated NAND register based address */
+#undef S3C2410_NFREG
+#define S3C2410_NFREG(x) ((x) + 0x4e000000)
+
+extern s3c24xx_nand_controller_t *s3c24xx_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
+
+extern int s3c24xx_register_commands(struct command_context_s *cmd_ctx);
+extern int s3c24xx_reset(struct nand_device_s *device);
+extern int s3c24xx_command(struct nand_device_s *device, u8 command);
+extern int s3c24xx_address(struct nand_device_s *device, u8 address);
+extern int s3c24xx_write_data(struct nand_device_s *device, u16 data);
+extern int s3c24xx_read_data(struct nand_device_s *device, void *data);
+extern int s3c24xx_controller_ready(struct nand_device_s *device, int tout);
+
+#define s3c24xx_write_page NULL
+#define s3c24xx_read_page NULL
+
+/* code shared between different controllers */
+
+extern int s3c2440_nand_ready(struct nand_device_s *device, int timeout);
+
+extern int s3c2440_read_block_data(struct nand_device_s *, u8 *data, int data_size);
+extern int s3c2440_write_block_data(struct nand_device_s *, u8 *data, int data_size);
diff --git a/src/flash/s3c24xx_regs_nand.h b/src/flash/s3c24xx_regs_nand.h
new file mode 100644 (file)
index 0000000..d742205
--- /dev/null
@@ -0,0 +1,123 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-nand.h
+ *
+ * Copyright (c) 2004,2005 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 */
+

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)