unsik Kim <donari75@gmail.com> - mflash support
authoroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 16 Oct 2008 06:15:03 +0000 (06:15 +0000)
committeroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 16 Oct 2008 06:15:03 +0000 (06:15 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@1067 b42882b7-edfa-0310-969c-e2dbd0fdcd60

doc/openocd.texi
src/flash/Makefile.am
src/flash/mflash.c [new file with mode: 0644]
src/flash/mflash.h [new file with mode: 0644]
src/openocd.c

index 6855a0ceda65019b2cd1db44efd458a4f0c77437..472bd895c89b9cf33eb3f76464e92cb28d934461 100644 (file)
@@ -717,6 +717,26 @@ Use the standard str9 driver for programming.
 @b{flash bank aduc702x} <@var{base}> <@var{size}> 0 0 <@var{target#}>
 @*aduc702x flash plugin require the flash @var{base}, @var{size} and @var{target#}.
 
 @b{flash bank aduc702x} <@var{base}> <@var{size}> 0 0 <@var{target#}>
 @*aduc702x flash plugin require the flash @var{base}, @var{size} and @var{target#}.
 
+@section mFlash configuration
+@cindex mFlash configuration
+
+@itemize @bullet
+@item @b{mflash bank} <@var{soc}> <@var{base}> <@var{chip_width}> <@var{bus_width}>
+<@var{RST pin}> <@var{WP pin}> <@var{DPD pin}> <@var{target #}>
+@cindex mflash bank
+Configures a mflash for <@var{soc}> host bank at <@var{base}>. <@var{chip_width}> and
+<@var{bus_width}> are bytes order. Pin number format is dependent on host GPIO calling convention.
+If WP or DPD pin was not used, write -1. Currently, mflash bank support s3c2440 and pxa270.
+@end itemize
+(ex. of s3c2440) mflash <@var{RST pin}> is GPIO B1, <@var{WP pin}> and <@var{DPD pin}> are not used.
+@smallexample
+mflash bank s3c2440 0x10000000 2 2 1b -1 -1 0
+@end smallexample
+(ex. of pxa270) mflash <@var{RST pin}> is GPIO 43, <@var{DPD pin}> is not used and <@var{DPD pin}> is GPIO 51.
+@smallexample
+mflash bank pxa270 0x08000000 2 2 43 -1 51 0  
+@end smallexample
 @node Target library
 @chapter Target library
 @cindex Target library
 @node Target library
 @chapter Target library
 @cindex Target library
@@ -944,6 +964,22 @@ if the @option{erase} parameter is given.
 <@var{last}> of @option{flash bank} <@var{num}>.
 @end itemize
 
 <@var{last}> of @option{flash bank} <@var{num}>.
 @end itemize
 
+@subsection mFlash commands
+@cindex mFlash commands
+@itemize @bullet
+@item @b{mflash probe} 
+@cindex mflash probe
+Probe mflash.
+@item @b{mflash write} <@var{num}> <@var{file}> <@var{offset}>
+@cindex mflash write
+Write the binary <@var{file}> to mflash bank <@var{num}>, starting at
+<@var{offset}> bytes from the beginning of the bank.
+@item @b{mflash dump} <@var{num}> <@var{file}> <@var{offset}> <@var{size}>
+@cindex mflash dump
+Dump <size> bytes, starting at <@var{offset}> bytes from the beginning of the <@var{num}> bank 
+to a <@var{file}>.
+@end itemize
+
 @page
 @section Target Specific Commands
 @cindex Target Specific Commands
 @page
 @section Target Specific Commands
 @cindex Target Specific Commands
@@ -1049,7 +1085,7 @@ These are flash specific commands when using the stm32x driver.
 
 @subsection Stellaris specific commands
 @cindex Stellaris specific commands
 
 @subsection Stellaris specific commands
 @cindex Stellaris specific commands
-
 These are flash specific commands when using the Stellaris driver.
 @itemize @bullet
 @item @b{stellaris mass_erase} <@var{num}>
 These are flash specific commands when using the Stellaris driver.
 @itemize @bullet
 @item @b{stellaris mass_erase} <@var{num}>
index f9755c7567ca80f2d57038d264c8a7aef30aa882..db435a5d5430503afe2d37c62b3a4d8eac93a57b 100644 (file)
@@ -4,6 +4,6 @@ METASOURCES = AUTO
 noinst_LIBRARIES = libflash.a
 libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c at91sam7_old.c str7x.c str9x.c aduc702x.c nand.c lpc3180_nand_controller.c \
                                         stellaris.c str9xpec.c stm32x.c tms470.c ecos.c  \
 noinst_LIBRARIES = libflash.a
 libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c at91sam7_old.c str7x.c str9x.c aduc702x.c nand.c lpc3180_nand_controller.c \
                                         stellaris.c str9xpec.c stm32x.c tms470.c ecos.c  \
-                    s3c24xx_nand.c s3c2410_nand.c s3c2412_nand.c s3c2440_nand.c s3c2443_nand.c lpc288x.c ocl.c
+                    s3c24xx_nand.c s3c2410_nand.c s3c2412_nand.c s3c2440_nand.c s3c2443_nand.c lpc288x.c ocl.c mflash.c
 noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h at91sam7_old.h str7x.h str9x.h nand.h lpc3180_nand_controller.h \
 noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h at91sam7_old.h str7x.h str9x.h nand.h lpc3180_nand_controller.h \
-                                stellaris.h str9xpec.h stm32x.h tms470.h s3c24xx_nand.h s3c24xx_regs_nand.h lpc288x.h
+                                stellaris.h str9xpec.h stm32x.h tms470.h s3c24xx_nand.h s3c24xx_regs_nand.h lpc288x.h mflash.h
diff --git a/src/flash/mflash.c b/src/flash/mflash.c
new file mode 100644 (file)
index 0000000..52c6a9f
--- /dev/null
@@ -0,0 +1,876 @@
+/***************************************************************************\r
+ *   Copyright (C) 2007-2008 by unsik Kim <donari75@gmail.com>             *\r
+ *                                                                         *\r
+ *   This program is free software; you can redistribute it and/or modify  *\r
+ *   it under the terms of the GNU General Public License as published by  *\r
+ *   the Free Software Foundation; either version 2 of the License, or     *\r
+ *   (at your option) any later version.                                   *\r
+ *                                                                         *\r
+ *   This program is distributed in the hope that it will be useful,       *\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
+ *   GNU General Public License for more details.                          *\r
+ *                                                                         *\r
+ *   You should have received a copy of the GNU General Public License     *\r
+ *   along with this program; if not, write to the                         *\r
+ *   Free Software Foundation, Inc.,                                       *\r
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
+ ***************************************************************************/\r
+\r
+#ifdef HAVE_CONFIG_H\r
+#include "config.h"\r
+#endif\r
+\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <stdlib.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <errno.h>\r
+#include <inttypes.h>\r
+\r
+#include "command.h"\r
+#include "log.h"\r
+#include "target.h"\r
+#include "time_support.h"\r
+#include "fileio.h"\r
+#include "mflash.h"\r
+\r
+static int s3c2440_set_gpio_to_output (mflash_gpio_num_t gpio);\r
+static int s3c2440_set_gpio_output_val (mflash_gpio_num_t gpio, u8 val);\r
+static int pxa270_set_gpio_to_output (mflash_gpio_num_t gpio);\r
+static int pxa270_set_gpio_output_val (mflash_gpio_num_t gpio, u8 val);\r
+\r
+static command_t *mflash_cmd;\r
+\r
+static mflash_bank_t *mflash_bank;\r
+\r
+static mflash_gpio_drv_t pxa270_gpio = {\r
+       .name = "pxa270",\r
+       .set_gpio_to_output = pxa270_set_gpio_to_output,\r
+       .set_gpio_output_val = pxa270_set_gpio_output_val\r
+};\r
+\r
+static mflash_gpio_drv_t s3c2440_gpio = {\r
+       .name = "s3c2440",\r
+       .set_gpio_to_output = s3c2440_set_gpio_to_output,\r
+       .set_gpio_output_val = s3c2440_set_gpio_output_val\r
+};\r
+\r
+static mflash_gpio_drv_t *mflash_gpio[] =\r
+{\r
+               &pxa270_gpio,\r
+               &s3c2440_gpio,\r
+               NULL\r
+};\r
+\r
+#define PXA270_GAFR0_L 0x40E00054\r
+#define PXA270_GAFR3_U 0x40E00070\r
+#define PXA270_GAFR3_U_RESERVED_BITS  0xfffc0000u\r
+#define PXA270_GPDR0 0x40E0000C\r
+#define PXA270_GPDR3 0x40E0010C\r
+#define PXA270_GPDR3_RESERVED_BITS  0xfe000000u\r
+#define PXA270_GPSR0 0x40E00018\r
+#define PXA270_GPCR0 0x40E00024\r
+\r
+static int pxa270_set_gpio_to_output (mflash_gpio_num_t gpio)\r
+{\r
+       u32 addr, value, mask;\r
+       target_t *target = mflash_bank->target;\r
+       int ret;\r
+\r
+       // remove alternate function.\r
+       mask = 0x3u << (gpio.num & 0xF)*2;\r
+\r
+       addr = PXA270_GAFR0_L + (gpio.num >> 4) * 4;\r
+\r
+       if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)\r
+               return ret;\r
+\r
+       value &= ~mask;\r
+       if (addr == PXA270_GAFR3_U)\r
+               value &= ~PXA270_GAFR3_U_RESERVED_BITS;\r
+\r
+       if ((ret = target_write_u32(target, addr, value)) != ERROR_OK)\r
+               return ret;\r
+\r
+       // set direction to output\r
+       mask = 0x1u << (gpio.num & 0x1F);\r
+\r
+       addr = PXA270_GPDR0 + (gpio.num >> 5) * 4;\r
+\r
+       if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)\r
+               return ret;\r
+\r
+       value |= mask;\r
+       if (addr == PXA270_GPDR3)\r
+               value &= ~PXA270_GPDR3_RESERVED_BITS;\r
+\r
+       ret = target_write_u32(target, addr, value);\r
+       return ret;\r
+}\r
+\r
+static int pxa270_set_gpio_output_val (mflash_gpio_num_t gpio, u8 val)\r
+{\r
+       u32 addr, value, mask;\r
+       target_t *target = mflash_bank->target;\r
+       int ret;\r
+\r
+       mask = 0x1u << (gpio.num & 0x1F);\r
+\r
+       if (val) {\r
+               addr = PXA270_GPSR0 + (gpio.num >> 5) * 4;\r
+       } else {\r
+               addr = PXA270_GPCR0 + (gpio.num >> 5) * 4;\r
+       }\r
+\r
+       if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)\r
+               return ret;\r
+\r
+       value |= mask;\r
+\r
+       ret = target_write_u32(target, addr, value);\r
+\r
+       return ret;\r
+}\r
+\r
+#define S3C2440_GPACON 0x56000000\r
+#define S3C2440_GPADAT 0x56000004\r
+#define S3C2440_GPJCON 0x560000d0\r
+#define S3C2440_GPJDAT 0x560000d4\r
+\r
+static int s3c2440_set_gpio_to_output (mflash_gpio_num_t gpio)\r
+{\r
+       u32 data, mask, gpio_con;\r
+       target_t *target = mflash_bank->target;\r
+       int ret;\r
+\r
+       if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {\r
+               gpio_con = S3C2440_GPACON + (gpio.port[0] - 'a') * 0x10;\r
+       } else if (gpio.port[0] == 'j') {\r
+               gpio_con = S3C2440_GPJCON;\r
+       } else {\r
+               LOG_ERROR("invalid port %d%s", gpio.num, gpio.port);\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       ret = target_read_u32(target, gpio_con, &data);\r
+\r
+       if (ret == ERROR_OK) {\r
+               if (gpio.port[0] == 'a') {\r
+                       mask = 1 << gpio.num;\r
+                       data &= ~mask;\r
+               } else {\r
+                       mask = 3 << gpio.num * 2;\r
+                       data &= ~mask;\r
+                       data |= (1 << gpio.num * 2);\r
+               }\r
+\r
+               ret = target_write_u32(target, gpio_con, data);\r
+       }\r
+       return ret;\r
+}\r
+\r
+static int s3c2440_set_gpio_output_val (mflash_gpio_num_t gpio, u8 val)\r
+{\r
+       u32 data, mask, gpio_dat;\r
+       target_t *target = mflash_bank->target;\r
+       int ret;\r
+\r
+       if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {\r
+               gpio_dat = S3C2440_GPADAT + (gpio.port[0] - 'a') * 0x10;\r
+       } else if (gpio.port[0] == 'j') {\r
+               gpio_dat = S3C2440_GPJDAT;\r
+       } else {\r
+               LOG_ERROR("invalid port %d%s", gpio.num, gpio.port);\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       ret = target_read_u32(target, gpio_dat, &data);\r
+\r
+       if (ret == ERROR_OK) {\r
+               mask = 1 << gpio.num;\r
+               if (val)\r
+                       data |= mask;\r
+               else\r
+                       data &= ~mask;\r
+\r
+               ret = target_write_u32(target, gpio_dat, data);\r
+       }\r
+       return ret;\r
+}\r
+\r
+static int mflash_rst(u8 level)\r
+{\r
+       return mflash_bank->gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, level);\r
+}\r
+\r
+static int mg_dump_task_reg (void)\r
+{\r
+       target_t *target = mflash_bank->target;\r
+       u32 address = mflash_bank->base + MG_REG_OFFSET + MG_REG_ERROR;\r
+       u8 value, i;\r
+       char *reg_name[9] = {\r
+               "error                  ",\r
+               "sector count           ",\r
+               "sector num (LBA  7- 0) ",\r
+               "cyl. low   (LBA 15- 8) ",\r
+               "cyl. high  (LBA 23-16) ",\r
+               "drv/head               ",\r
+               "status                 ",\r
+               "dev control            ",\r
+               "burst control          "\r
+       };\r
+\r
+       for (i = 0; i < 9; i++) {\r
+               target_read_u8(target, address + i * 2, &value);\r
+               LOG_INFO("%s : 0x%2.2x", reg_name[i], value);\r
+       }\r
+\r
+       return ERROR_OK;\r
+\r
+}\r
+static int mflash_init_gpio (void)\r
+{\r
+       mflash_gpio_drv_t *gpio_drv = mflash_bank->gpio_drv;\r
+\r
+       gpio_drv->set_gpio_to_output(mflash_bank->rst_pin);\r
+       gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, 1);\r
+\r
+       if (mflash_bank->wp_pin.num != -1) {\r
+               gpio_drv->set_gpio_to_output(mflash_bank->wp_pin);\r
+               gpio_drv->set_gpio_output_val(mflash_bank->wp_pin, 1);\r
+       }\r
+\r
+       if (mflash_bank->dpd_pin.num != -1) {\r
+               gpio_drv->set_gpio_to_output(mflash_bank->dpd_pin);\r
+               gpio_drv->set_gpio_output_val(mflash_bank->dpd_pin, 1);\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mg_dsk_wait(mg_io_type_wait wait, u32 time)\r
+{\r
+       u8 status, error;\r
+       target_t *target = mflash_bank->target;\r
+       u32 mg_task_reg = mflash_bank->base + MG_REG_OFFSET;\r
+       duration_t duration;\r
+       long long t=0;\r
+\r
+       duration_start_measure(&duration);\r
+\r
+    while (time) {\r
+\r
+       target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);\r
+\r
+       if (status & mg_io_rbit_status_busy)\r
+           {\r
+               if (wait == mg_io_wait_bsy)\r
+                      return ERROR_OK;\r
+           } else {\r
+               switch(wait)\r
+               {\r
+                   case mg_io_wait_not_bsy:\r
+                       return ERROR_OK;\r
+                   case mg_io_wait_rdy_noerr:\r
+                       if (status & mg_io_rbit_status_ready)\r
+                           return ERROR_OK;\r
+                       break;\r
+                   case mg_io_wait_drq_noerr:\r
+                       if (status & mg_io_rbit_status_data_req)\r
+                           return ERROR_OK;\r
+                       break;\r
+                   default:\r
+                       break;\r
+               }\r
+\r
+               // Now we check the error condition!\r
+               if (status & mg_io_rbit_status_error)\r
+               {\r
+                   target_read_u8(target, mg_task_reg + MG_REG_ERROR, &error);\r
+\r
+                if (error & mg_io_rbit_err_bad_sect_num) {\r
+                       LOG_ERROR("sector not found");\r
+                    return ERROR_FAIL;\r
+                }\r
+                else if (error & (mg_io_rbit_err_bad_block | mg_io_rbit_err_uncorrectable)) {\r
+                       LOG_ERROR("bad block");\r
+                    return ERROR_FAIL;\r
+                } else {\r
+                       LOG_ERROR("disk operation fail");\r
+                       return ERROR_FAIL;\r
+                   }\r
+               }\r
+\r
+               switch (wait)\r
+               {\r
+                   case mg_io_wait_rdy:\r
+                       if (status & mg_io_rbit_status_ready)\r
+                           return ERROR_OK;\r
+\r
+                   case mg_io_wait_drq:\r
+                       if (status & mg_io_rbit_status_data_req)\r
+                           return ERROR_OK;\r
+\r
+                   default:\r
+                       break;\r
+               }\r
+           }\r
+\r
+       duration_stop_measure(&duration, NULL);\r
+\r
+               t=duration.duration.tv_usec/1000;\r
+               t+=duration.duration.tv_sec*1000;\r
+\r
+               if (t > time)\r
+            break;\r
+    }\r
+\r
+    LOG_ERROR("timeout occured");\r
+    return ERROR_FAIL;\r
+}\r
+\r
+static int mg_dsk_srst(u8 on)\r
+{\r
+       target_t *target = mflash_bank->target;\r
+       u32 mg_task_reg = mflash_bank->base + MG_REG_OFFSET;\r
+       u8 value;\r
+       int ret;\r
+\r
+       if ((ret = target_read_u8(target, mg_task_reg + MG_REG_DRV_CTRL, &value)) != ERROR_OK)\r
+               return ret;\r
+\r
+       if(on) {\r
+               value |= (mg_io_rbit_devc_srst);\r
+       } else {\r
+               value &= ~mg_io_rbit_devc_srst;\r
+       }\r
+\r
+       ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_CTRL, value);\r
+       return ret;\r
+}\r
+\r
+static int mg_dsk_io_cmd(u32 sect_num, u32 cnt, u8 cmd)\r
+{\r
+       target_t *target = mflash_bank->target;\r
+       u32 mg_task_reg = mflash_bank->base + MG_REG_OFFSET;\r
+       u8 value;\r
+\r
+       if (mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL) != ERROR_OK)\r
+               return ERROR_FAIL;\r
+\r
+       value = mg_io_rval_dev_drv_master | mg_io_rval_dev_lba_mode |((sect_num >> 24) & 0xf);\r
+\r
+       target_write_u8(target, mg_task_reg + MG_REG_DRV_HEAD, value);\r
+       target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, (u8)cnt);\r
+       target_write_u8(target, mg_task_reg + MG_REG_SECT_NUM, (u8)sect_num);\r
+       target_write_u8(target, mg_task_reg + MG_REG_CYL_LOW, (u8)(sect_num >> 8));\r
+       target_write_u8(target, mg_task_reg + MG_REG_CYL_HIGH, (u8)(sect_num >> 16));\r
+\r
+       target_write_u8(target, mg_task_reg + MG_REG_COMMAND, cmd);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mg_dsk_drv_info(void)\r
+{\r
+       target_t *target = mflash_bank->target;\r
+       u32 mg_buff = mflash_bank->base + MG_BUFFER_OFFSET;\r
+\r
+       if ( mg_dsk_io_cmd(0, 1, mg_io_cmd_identify) != ERROR_OK)\r
+               return ERROR_FAIL;\r
+\r
+       if ( mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL) != ERROR_OK)\r
+               return ERROR_FAIL;\r
+\r
+       LOG_INFO("read drive info.");\r
+\r
+       if (! mflash_bank->drv_info)\r
+               mflash_bank->drv_info = malloc(sizeof(mg_drv_info_t));\r
+\r
+       target->type->read_memory(target, mg_buff, 2, sizeof(mg_io_type_drv_info) >> 1,\r
+                       (u8 *)&mflash_bank->drv_info->drv_id);\r
+\r
+       mflash_bank->drv_info->tot_sects = (u32)(mflash_bank->drv_info->drv_id.total_user_addressable_sectors_hi << 16)\r
+                                                                       + mflash_bank->drv_info->drv_id.total_user_addressable_sectors_lo;\r
+\r
+       target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mg_mflash_probe(void)\r
+{\r
+       mflash_bank->proved = 0;\r
+\r
+       mflash_init_gpio();\r
+\r
+       LOG_INFO("reset mflash");\r
+\r
+       mflash_rst(0);\r
+\r
+       if (mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG) != ERROR_OK)\r
+               return ERROR_FAIL;\r
+\r
+       mflash_rst(1);\r
+\r
+       if (mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG) != ERROR_OK)\r
+               return ERROR_FAIL;\r
+\r
+       mg_dsk_srst(1);\r
+\r
+       if (mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG) != ERROR_OK)\r
+               return ERROR_FAIL;\r
+\r
+       mg_dsk_srst(0);\r
+\r
+       if (mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG) != ERROR_OK)\r
+               return ERROR_FAIL;\r
+\r
+       if (mg_dsk_drv_info() != ERROR_OK)\r
+               return ERROR_FAIL;\r
+\r
+       mflash_bank->proved = 1;\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mflash_probe_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       int ret;\r
+\r
+       ret = mg_mflash_probe();\r
+\r
+       if (ret == ERROR_OK) {\r
+               command_print(cmd_ctx, "mflash (total %u sectors) found at 0x%8.8x",\r
+                               mflash_bank->drv_info->tot_sects, mflash_bank->base );\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static int mg_mflash_do_read_sects(void *buff, u32 sect_num, u32 sect_cnt)\r
+{\r
+       u32 i, address;\r
+       int ret;\r
+       target_t *target = mflash_bank->target;\r
+       u8 *buff_ptr = buff;\r
+       duration_t duration;\r
+\r
+       if ( mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_read) != ERROR_OK )\r
+               return ERROR_FAIL;\r
+\r
+       address = mflash_bank->base + MG_BUFFER_OFFSET;\r
+\r
+       duration_start_measure(&duration);\r
+\r
+       for (i = 0; i < sect_cnt; i++) {\r
+               mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);\r
+\r
+               target->type->read_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);\r
+               buff_ptr += MG_MFLASH_SECTOR_SIZE;\r
+\r
+               target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read);\r
+\r
+               LOG_DEBUG("%u (0x%8.8x) sector read", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);\r
+\r
+               duration_stop_measure(&duration, NULL);\r
+\r
+               if ((duration.duration.tv_sec * 1000 + duration.duration.tv_usec / 1000) > 3000) {\r
+                       LOG_INFO("read %u'th sectors", sect_num + i);\r
+                       duration_start_measure(&duration);\r
+               }\r
+       }\r
+\r
+       ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);\r
+\r
+       return ret;\r
+}\r
+\r
+static int mg_mflash_read_sects(void *buff, u32 sect_num, u32 sect_cnt)\r
+{\r
+       u32 quotient, residue, i;\r
+       u8 *buff_ptr = buff;\r
+\r
+       quotient = sect_cnt >> 8;\r
+       residue = sect_cnt % 256;\r
+\r
+       for (i = 0; i < quotient; i++) {\r
+               LOG_DEBUG("sect num : %u buff : 0x%8.8x", sect_num, (u32)buff_ptr);\r
+               mg_mflash_do_read_sects(buff_ptr, sect_num, 256);\r
+               sect_num += 256;\r
+               buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;\r
+       }\r
+\r
+       if (residue) {\r
+               LOG_DEBUG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);\r
+               mg_mflash_do_read_sects(buff_ptr, sect_num, residue);\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mg_mflash_do_write_sects(void *buff, u32 sect_num, u32 sect_cnt)\r
+{\r
+       u32 i, address;\r
+       int ret;\r
+       target_t *target = mflash_bank->target;\r
+       u8 *buff_ptr = buff;\r
+       duration_t duration;\r
+\r
+       if ( mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_write) != ERROR_OK ) {\r
+               LOG_ERROR("mg_io_cmd_write fail");\r
+               return ERROR_FAIL;\r
+       }\r
+\r
+       address = mflash_bank->base + MG_BUFFER_OFFSET;\r
+\r
+       duration_start_measure(&duration);\r
+\r
+       for (i = 0; i < sect_cnt; i++) {\r
+               ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);\r
+               if (ret != ERROR_OK)\r
+                       LOG_ERROR("mg_io_wait_drq time out");\r
+\r
+               ret = target->type->write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);\r
+               if (ret != ERROR_OK)\r
+                       LOG_ERROR("mem write error");\r
+               buff_ptr += MG_MFLASH_SECTOR_SIZE;\r
+\r
+               ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_write);\r
+               if (ret != ERROR_OK)\r
+                       LOG_ERROR("mg_io_cmd_confirm_write error");\r
+\r
+               LOG_DEBUG("%u (0x%8.8x) sector write", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);\r
+\r
+               duration_stop_measure(&duration, NULL);\r
+\r
+               if ((duration.duration.tv_sec * 1000 + duration.duration.tv_usec / 1000) > 3000) {\r
+                       LOG_INFO("wrote %u'th sectors", sect_num + i);\r
+                       duration_start_measure(&duration);\r
+               }\r
+       }\r
+\r
+       ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);\r
+\r
+       return ret;\r
+}\r
+\r
+static int mg_mflash_write_sects(void *buff, u32 sect_num, u32 sect_cnt)\r
+{\r
+       u32 quotient, residue, i;\r
+       u8 *buff_ptr = buff;\r
+\r
+       quotient = sect_cnt >> 8;\r
+       residue = sect_cnt % 256;\r
+\r
+       for (i = 0; i < quotient; i++) {\r
+               LOG_DEBUG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);\r
+               mg_mflash_do_write_sects(buff_ptr, sect_num, 256);\r
+               sect_num += 256;\r
+               buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;\r
+       }\r
+\r
+       if (residue) {\r
+               LOG_DEBUG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);\r
+               mg_mflash_do_write_sects(buff_ptr, sect_num, residue);\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mg_mflash_read (u32 addr, u8 *buff, u32 len)\r
+{\r
+       u8 *sect_buff, *buff_ptr = buff;\r
+       u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num;\r
+\r
+       cnt = 0;\r
+       cur_addr = addr;\r
+       end_addr = addr + len;\r
+\r
+       sect_buff = malloc(MG_MFLASH_SECTOR_SIZE);\r
+\r
+       if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {\r
+\r
+               next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;\r
+               sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;\r
+               mg_mflash_read_sects(sect_buff, sect_num, 1);\r
+\r
+               if (end_addr < next_sec_addr) {\r
+                       memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), end_addr - cur_addr);\r
+                       LOG_DEBUG("copies %u byte from sector offset 0x%8.8x", end_addr - cur_addr, cur_addr);\r
+                       cur_addr = end_addr;\r
+               } else {\r
+                       memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), next_sec_addr - cur_addr);\r
+                       LOG_DEBUG("copies %u byte from sector offset 0x%8.8x", next_sec_addr - cur_addr, cur_addr);\r
+                       buff_ptr += (next_sec_addr - cur_addr);\r
+                       cur_addr = next_sec_addr;\r
+               }\r
+       }\r
+\r
+       if (cur_addr < end_addr) {\r
+\r
+               sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;\r
+               next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;\r
+\r
+               while (next_sec_addr <= end_addr) {\r
+                       cnt++;\r
+                       next_sec_addr += MG_MFLASH_SECTOR_SIZE;\r
+               }\r
+\r
+               if (cnt)\r
+                       mg_mflash_read_sects(buff_ptr, sect_num, cnt);\r
+\r
+               buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;\r
+               cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;\r
+\r
+               if (cur_addr < end_addr) {\r
+\r
+                       sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;\r
+                       mg_mflash_read_sects(sect_buff, sect_num, 1);\r
+                       memcpy(buff_ptr, sect_buff, end_addr - cur_addr);\r
+                       LOG_DEBUG("copies %u byte", end_addr - cur_addr);\r
+\r
+               }\r
+\r
+       }\r
+\r
+       free(sect_buff);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mg_mflash_write(u32 addr, u8 *buff, u32 len)\r
+{\r
+       u8 *sect_buff, *buff_ptr = buff;\r
+       u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num;\r
+\r
+       cnt = 0;\r
+       cur_addr = addr;\r
+       end_addr = addr + len;\r
+\r
+       sect_buff = malloc(MG_MFLASH_SECTOR_SIZE);\r
+\r
+       if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {\r
+\r
+               next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;\r
+               sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;\r
+               mg_mflash_read_sects(sect_buff, sect_num, 1);\r
+\r
+               if (end_addr < next_sec_addr) {\r
+                       memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, end_addr - cur_addr);\r
+                       LOG_DEBUG("copies %u byte to sector offset 0x%8.8x", end_addr - cur_addr, cur_addr);\r
+                       cur_addr = end_addr;\r
+               } else {\r
+                       memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, next_sec_addr - cur_addr);\r
+                       LOG_DEBUG("copies %u byte to sector offset 0x%8.8x", next_sec_addr - cur_addr, cur_addr);\r
+                       buff_ptr += (next_sec_addr - cur_addr);\r
+                       cur_addr = next_sec_addr;\r
+               }\r
+\r
+               mg_mflash_write_sects(sect_buff, sect_num, 1);\r
+\r
+       }\r
+\r
+       if (cur_addr < end_addr) {\r
+\r
+               sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;\r
+               next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;\r
+\r
+               while (next_sec_addr <= end_addr) {\r
+                       cnt++;\r
+                       next_sec_addr += MG_MFLASH_SECTOR_SIZE;\r
+               }\r
+\r
+               if (cnt)\r
+                       mg_mflash_write_sects(buff_ptr, sect_num, cnt);\r
+\r
+               buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;\r
+               cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;\r
+\r
+               if (cur_addr < end_addr) {\r
+\r
+                       sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;\r
+                       mg_mflash_read_sects(sect_buff, sect_num, 1);\r
+                       memcpy(sect_buff, buff_ptr, end_addr - cur_addr);\r
+                       LOG_DEBUG("copies %u byte", end_addr - cur_addr);\r
+                       mg_mflash_write_sects(sect_buff, sect_num, 1);\r
+\r
+               }\r
+\r
+       }\r
+\r
+       free(sect_buff);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mflash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       u32 address, buf_cnt;\r
+       u8 *buffer;\r
+       // TODO : multi-bank support, large file support\r
+       fileio_t fileio;\r
+       duration_t duration;\r
+       char *duration_text;\r
+       int ret;\r
+\r
+       if (argc != 3) {\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       }\r
+\r
+       address = strtoul(args[2], NULL, 0);\r
+\r
+       if (! mflash_bank->proved ) {\r
+               mg_mflash_probe();\r
+       }\r
+\r
+\r
+       if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) {\r
+               return ERROR_FAIL;\r
+       }\r
+\r
+       buffer = malloc(fileio.size);\r
+\r
+       if (fileio_read(&fileio, fileio.size, buffer, &buf_cnt) != ERROR_OK)\r
+       {\r
+               free(buffer);\r
+               fileio_close(&fileio);\r
+               return ERROR_FAIL;\r
+       }\r
+\r
+       duration_start_measure(&duration);\r
+\r
+       ret = mg_mflash_write(address, buffer, (u32)fileio.size);\r
+\r
+       duration_stop_measure(&duration, &duration_text);\r
+\r
+       command_print(cmd_ctx, "wrote %lli byte from file %s in %s (%f kB/s)",\r
+               fileio.size, args[1], duration_text,\r
+               (float)fileio.size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));\r
+\r
+       free(duration_text);\r
+\r
+       fileio_close(&fileio);\r
+\r
+       free(buffer);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mflash_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       u32 address, size_written, size;\r
+       u8 *buffer;\r
+       // TODO : multi-bank support\r
+       fileio_t fileio;\r
+       duration_t duration;\r
+       char *duration_text;\r
+\r
+       if (argc != 4) {\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       }\r
+\r
+       address = strtoul(args[2], NULL, 0);\r
+       size = strtoul(args[3], NULL, 0);\r
+\r
+       if (! mflash_bank->proved ) {\r
+                       mg_mflash_probe();\r
+       }\r
+\r
+       if (fileio_open(&fileio, args[1], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) {\r
+               return ERROR_FAIL;\r
+       }\r
+\r
+       buffer = malloc(size);\r
+\r
+       duration_start_measure(&duration);\r
+\r
+       mg_mflash_read(address, buffer, size);\r
+\r
+       duration_stop_measure(&duration, &duration_text);\r
+\r
+       fileio_write(&fileio, size, buffer, &size_written);\r
+\r
+       command_print(cmd_ctx, "dump image (address 0x%8.8x size %u) to file %s in %s (%f kB/s)",\r
+                               address, size, args[1], duration_text,\r
+                               (float)size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));\r
+\r
+       free(duration_text);\r
+\r
+       fileio_close(&fileio);\r
+\r
+       free(buffer);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+int mflash_init_drivers(struct command_context_s *cmd_ctx)\r
+{\r
+       if (mflash_bank) {\r
+               register_command(cmd_ctx, mflash_cmd, "probe", mflash_probe_command, COMMAND_EXEC, NULL);\r
+               register_command(cmd_ctx, mflash_cmd, "write", mflash_write_command, COMMAND_EXEC,\r
+                               "mflash write <num> <file> <address>");\r
+               register_command(cmd_ctx, mflash_cmd, "dump", mflash_dump_command, COMMAND_EXEC,\r
+                                               "mflash dump <num> <file> <address> <size>");\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static int mflash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       target_t *target;\r
+       char *str;\r
+       int i;\r
+\r
+       if (argc < 8)\r
+       {\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       }\r
+\r
+       if ((target = get_target_by_num(strtoul(args[7], NULL, 0))) == NULL)\r
+       {\r
+               LOG_ERROR("target %lu not defined", strtoul(args[7], NULL, 0));\r
+               return ERROR_FAIL;\r
+       }\r
+\r
+       mflash_bank = calloc(sizeof(mflash_bank_t), 1);\r
+       mflash_bank->base = strtoul(args[1], NULL, 0);\r
+       mflash_bank->chip_width = strtoul(args[2], NULL, 0);\r
+       mflash_bank->bus_width = strtoul(args[3], NULL, 0);\r
+       mflash_bank->rst_pin.num = strtoul(args[4], &str, 0);\r
+       if (*str)\r
+               mflash_bank->rst_pin.port[0] = (u16)tolower(str[0]);\r
+       mflash_bank->wp_pin.num = strtol(args[5], &str, 0);\r
+       if (*str)\r
+               mflash_bank->wp_pin.port[0] = (u16)tolower(str[0]);\r
+       mflash_bank->dpd_pin.num = strtol(args[6], &str, 0);\r
+       if (*str)\r
+               mflash_bank->dpd_pin.port[0] = (u16)tolower(str[0]);\r
+\r
+       mflash_bank->target = target;\r
+\r
+       for (i = 0; mflash_gpio[i] ; i++) {\r
+               if (! strcmp(mflash_gpio[i]->name, args[0])) {\r
+                       mflash_bank->gpio_drv = mflash_gpio[i];\r
+               }\r
+       }\r
+\r
+       if (! mflash_bank->gpio_drv) {\r
+               LOG_ERROR("%s is unsupported soc", args[0]);\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+int mflash_register_commands(struct command_context_s *cmd_ctx)\r
+{\r
+       mflash_cmd = register_command(cmd_ctx, NULL, "mflash", NULL, COMMAND_ANY, NULL);\r
+       register_command(cmd_ctx, mflash_cmd, "bank", mflash_bank_command, COMMAND_CONFIG,\r
+                       "mflash bank <soc> <base> <chip_width> <bus_width> <RST pin> <WP pin> <DPD pin> <target #>");\r
+       return ERROR_OK;\r
+}\r
diff --git a/src/flash/mflash.h b/src/flash/mflash.h
new file mode 100644 (file)
index 0000000..3fc935a
--- /dev/null
@@ -0,0 +1,245 @@
+/***************************************************************************\r
+ *   Copyright (C) 2007-2008 by unsik Kim <donari75@gmail.com>             *\r
+ *                                                                         *\r
+ *   This program is free software; you can redistribute it and/or modify  *\r
+ *   it under the terms of the GNU General Public License as published by  *\r
+ *   the Free Software Foundation; either version 2 of the License, or     *\r
+ *   (at your option) any later version.                                   *\r
+ *                                                                         *\r
+ *   This program is distributed in the hope that it will be useful,       *\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
+ *   GNU General Public License for more details.                          *\r
+ *                                                                         *\r
+ *   You should have received a copy of the GNU General Public License     *\r
+ *   along with this program; if not, write to the                         *\r
+ *   Free Software Foundation, Inc.,                                       *\r
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
+ ***************************************************************************/\r
+\r
+#ifndef _MFLASH_H\r
+#define _MFLASH_H\r
+\r
+typedef unsigned long mg_io_uint32;\r
+typedef unsigned short mg_io_uint16;\r
+typedef unsigned char mg_io_uint8;\r
+\r
+typedef struct mflash_gpio_num_s\r
+{\r
+       char port[2];\r
+       signed short num;\r
+} mflash_gpio_num_t;\r
+\r
+typedef struct mflash_gpio_drv_s\r
+{\r
+       char *name;\r
+       int (*set_gpio_to_output) (mflash_gpio_num_t gpio);\r
+       int (*set_gpio_output_val) (mflash_gpio_num_t gpio, u8 val);\r
+} mflash_gpio_drv_t;\r
+\r
+typedef struct _mg_io_type_drv_info {\r
+\r
+    mg_io_uint16 general_configuration;            // 00\r
+    mg_io_uint16 number_of_cylinders;               // 01\r
+    mg_io_uint16 reserved1;                       // 02\r
+    mg_io_uint16 number_of_heads;                   // 03\r
+    mg_io_uint16 unformatted_bytes_per_track;        // 04\r
+    mg_io_uint16 unformatted_bytes_per_sector;       // 05\r
+    mg_io_uint16 sectors_per_track;                 // 06\r
+    mg_io_uint8  vendor_unique1[6];                // 07/08/09\r
+\r
+    mg_io_uint8  serial_number[20];                // 10~19\r
+\r
+    mg_io_uint16 buffer_type;                      // 20\r
+    mg_io_uint16 buffer_sector_size;                // 21\r
+    mg_io_uint16 number_of_ecc_bytes;                // 22\r
+\r
+    mg_io_uint8  firmware_revision[8];             // 23~26\r
+    mg_io_uint8  model_number[40];                 // 27\r
+\r
+    mg_io_uint8  maximum_block_transfer;            // 47 low byte\r
+    mg_io_uint8  vendor_unique2;                   // 47 high byte\r
+    mg_io_uint16 dword_io;                    // 48\r
+\r
+    mg_io_uint16 capabilities;                    // 49\r
+    mg_io_uint16 reserved2;                       // 50\r
+\r
+    mg_io_uint8  vendor_unique3;                   // 51 low byte\r
+    mg_io_uint8  pio_cycle_timing_mode;              // 51 high byte\r
+    mg_io_uint8  vendor_unique4;                   // 52 low byte\r
+    mg_io_uint8  dma_cycle_timing_mode;              // 52 high byte\r
+    mg_io_uint16 translation_fields_valid;          // 53 (low bit)\r
+    mg_io_uint16 number_of_current_cylinders;        // 54\r
+    mg_io_uint16 number_of_current_heads;            // 55\r
+    mg_io_uint16 current_sectors_per_track;          // 56\r
+    mg_io_uint16 current_sector_capacity_lo;      // 57 & 58\r
+    mg_io_uint16 current_sector_capacity_hi;     // 57 & 58\r
+    mg_io_uint8  multi_sector_count;                // 59 low\r
+    mg_io_uint8  multi_sector_setting_valid;         // 59 high (low bit)\r
+\r
+    mg_io_uint16 total_user_addressable_sectors_lo;     // 60 & 61\r
+    mg_io_uint16 total_user_addressable_sectors_hi;     // 60 & 61\r
+\r
+    mg_io_uint8  single_dma_modes_supported;         // 62 low byte\r
+    mg_io_uint8  single_dma_transfer_active;         // 62 high byte\r
+    mg_io_uint8  multi_dma_modes_supported;          // 63 low byte\r
+    mg_io_uint8  multi_dma_transfer_active;          // 63 high byte\r
+    mg_io_uint16 adv_pio_mode;\r
+    mg_io_uint16 min_dma_cyc;\r
+    mg_io_uint16 recommend_dma_cyc;\r
+    mg_io_uint16 min_pio_cyc_no_iordy;\r
+    mg_io_uint16 min_pio_cyc_with_iordy;\r
+    mg_io_uint8  reserved3[22];\r
+    mg_io_uint16 major_ver_num;\r
+    mg_io_uint16 minor_ver_num;\r
+    mg_io_uint16 feature_cmd_set_suprt0;\r
+    mg_io_uint16 feature_cmd_set_suprt1;\r
+    mg_io_uint16 feature_cmd_set_suprt2;\r
+    mg_io_uint16 feature_cmd_set_en0;\r
+    mg_io_uint16 feature_cmd_set_en1;\r
+    mg_io_uint16 feature_cmd_set_en2;\r
+    mg_io_uint16 reserved4;\r
+    mg_io_uint16 req_time_for_security_er_done;\r
+    mg_io_uint16 req_time_for_enhan_security_er_done;\r
+    mg_io_uint16 adv_pwr_mgm_lvl_val;\r
+    mg_io_uint16 reserved5;\r
+    mg_io_uint16 re_of_hw_rst;\r
+    mg_io_uint8  reserved6[68];\r
+    mg_io_uint16 security_stas;\r
+    mg_io_uint8  vendor_uniq_bytes[62];\r
+    mg_io_uint16 cfa_pwr_mode;\r
+    mg_io_uint8  reserved7[186];\r
+\r
+    mg_io_uint16 scts_per_secure_data_unit;\r
+    mg_io_uint16 integrity_word;\r
+\r
+} mg_io_type_drv_info;\r
+\r
+typedef struct mg_drv_info_s {\r
+       mg_io_type_drv_info drv_id;\r
+       u32 tot_sects;\r
+} mg_drv_info_t;\r
+\r
+typedef struct mflash_bank_s\r
+{\r
+       u32 base;\r
+       u32 chip_width;\r
+       u32 bus_width;\r
+\r
+       mflash_gpio_num_t rst_pin;\r
+       mflash_gpio_num_t wp_pin;\r
+       mflash_gpio_num_t dpd_pin;\r
+\r
+       mflash_gpio_drv_t *gpio_drv;\r
+       target_t *target;\r
+       mg_drv_info_t *drv_info;\r
+\r
+       u8 proved;\r
+} mflash_bank_t;\r
+\r
+extern int mflash_register_commands(struct command_context_s *cmd_ctx);\r
+extern int mflash_init_drivers(struct command_context_s *cmd_ctx);\r
+\r
+#define MG_MFLASH_SECTOR_SIZE       (0x200)        //512Bytes = 2^9\r
+#define MG_MFLASH_SECTOR_SIZE_MASK  (0x200-1)\r
+#define MG_MFLASH_SECTOR_SIZE_SHIFT (9)\r
+\r
+#define MG_BUFFER_OFFSET    0x8000\r
+#define MG_REG_OFFSET          0xC000\r
+#define MG_REG_FEATURE         0x2 // write case\r
+#define MG_REG_ERROR           0x2 // read case\r
+#define MG_REG_SECT_CNT                0x4\r
+#define MG_REG_SECT_NUM                0x6\r
+#define MG_REG_CYL_LOW         0x8\r
+#define MG_REG_CYL_HIGH                0xA\r
+#define MG_REG_DRV_HEAD                0xC\r
+#define MG_REG_COMMAND         0xE // write case\r
+#define MG_REG_STATUS          0xE // read  case\r
+#define MG_REG_DRV_CTRL                0x10\r
+#define MG_REG_BURST_CTRL      0x12\r
+\r
+#define MG_OEM_DISK_WAIT_TIME_LONG   15000 // msec\r
+#define MG_OEM_DISK_WAIT_TIME_NORMAL  3000 // msec\r
+#define MG_OEM_DISK_WAIT_TIME_SHORT   1000 // msec\r
+\r
+typedef enum _mg_io_type_wait{\r
+\r
+    mg_io_wait_bsy       = 1,\r
+    mg_io_wait_not_bsy   = 2,\r
+    mg_io_wait_rdy       = 3,\r
+    mg_io_wait_drq       = 4,  // wait for data request\r
+    mg_io_wait_drq_noerr = 5,  // wait for DRQ but ignore the error status bit\r
+    mg_io_wait_rdy_noerr = 6   // wait for ready, but ignore error status bit\r
+\r
+} mg_io_type_wait;\r
+\r
+//= "Status Register" bit masks.\r
+typedef enum _mg_io_type_rbit_status{\r
+\r
+    mg_io_rbit_status_error            = 0x01, // error bit in status register\r
+    mg_io_rbit_status_corrected_error  = 0x04, // corrected error in status register\r
+    mg_io_rbit_status_data_req         = 0x08, // data request bit in status register\r
+    mg_io_rbit_status_seek_done        = 0x10, // DSC - Drive Seek Complete\r
+    mg_io_rbit_status_write_fault      = 0x20, // DWF - Drive Write Fault\r
+    mg_io_rbit_status_ready            = 0x40,\r
+    mg_io_rbit_status_busy             = 0x80\r
+\r
+} mg_io_type_rbit_status;\r
+\r
+//= "Error Register" bit masks.\r
+typedef enum _mg_io_type_rbit_error{\r
+\r
+    mg_io_rbit_err_general          = 0x01,\r
+    mg_io_rbit_err_aborted          = 0x04,\r
+    mg_io_rbit_err_bad_sect_num     = 0x10,\r
+    mg_io_rbit_err_uncorrectable    = 0x40,\r
+    mg_io_rbit_err_bad_block        = 0x80\r
+\r
+} mg_io_type_rbit_error;\r
+\r
+//= "Device Control Register" bit.\r
+typedef enum _mg_io_type_rbit_devc{\r
+\r
+    mg_io_rbit_devc_intr      = 0x02,//  interrupt enable bit (1:disable, 0:enable)\r
+    mg_io_rbit_devc_srst      = 0x04  // softwrae reset bit (1:assert, 0:de-assert)\r
+\r
+} mg_io_type_rbit_devc;\r
+\r
+// "Drive Select/Head Register" values.\r
+typedef enum _mg_io_type_rval_dev{\r
+\r
+    mg_io_rval_dev_must_be_on      =   0x80, // These 1 bits are always on\r
+    mg_io_rval_dev_drv_master      =  (0x00 | mg_io_rval_dev_must_be_on),// Master\r
+    mg_io_rval_dev_drv_slave0      =  (0x10 | mg_io_rval_dev_must_be_on),// Slave0\r
+    mg_io_rval_dev_drv_slave1      =  (0x20 | mg_io_rval_dev_must_be_on),// Slave1\r
+    mg_io_rval_dev_drv_slave2      =  (0x30 | mg_io_rval_dev_must_be_on),// Slave2\r
+    mg_io_rval_dev_lba_mode        =  (0x40 | mg_io_rval_dev_must_be_on)\r
+\r
+} mg_io_type_rval_dev;\r
+\r
+typedef enum _mg_io_type_cmd\r
+{\r
+    mg_io_cmd_read             =0x20,\r
+    mg_io_cmd_write            =0x30,\r
+\r
+    mg_io_cmd_setmul           =0xC6,\r
+    mg_io_cmd_readmul          =0xC4,\r
+    mg_io_cmd_writemul         =0xC5,\r
+\r
+    mg_io_cmd_idle             =0x97,//0xE3\r
+    mg_io_cmd_idle_immediate   =0x95,//0xE1\r
+\r
+    mg_io_cmd_setsleep         =0x99,//0xE6\r
+    mg_io_cmd_stdby            =0x96,//0xE2\r
+    mg_io_cmd_stdby_immediate  =0x94,//0xE0\r
+\r
+    mg_io_cmd_identify         =0xEC,\r
+    mg_io_cmd_set_feature      =0xEF,\r
+\r
+    mg_io_cmd_confirm_write    =0x3C,\r
+    mg_io_cmd_confirm_read     =0x40,\r
+    mg_io_cmd_wakeup           =0xC3\r
+\r
+} mg_io_type_cmd;\r
+\r
+#endif\r
index ab7db033a2dd65156013dfbf519a73e1ab41f097..13b0555965c9d02e7f0423695205861c9c2eabae 100644 (file)
@@ -39,6 +39,7 @@
 #include "flash.h"
 #include "nand.h"
 #include "pld.h"
 #include "flash.h"
 #include "nand.h"
 #include "pld.h"
+#include "mflash.h"
 
 #include "command.h"
 #include "server.h"
 
 #include "command.h"
 #include "server.h"
@@ -70,7 +71,7 @@ void print_version(void)
        /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
-       LOG_OUTPUT("$URL$\n");
+       LOG_OUTPUT( "$URL$\n");
        /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
        /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
@@ -78,6 +79,14 @@ void print_version(void)
        /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
 }
 
        /* DANGER!!! make sure that the line above does not appear in a patch, do not remove */
 }
 
+
+
+
+
+
+
+
+
 /* Give TELNET a way to find out what version this is */
 int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
 /* Give TELNET a way to find out what version this is */
 int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
@@ -145,6 +154,10 @@ int handle_init_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
                return ERROR_FAIL;
        LOG_DEBUG("flash init complete");
 
                return ERROR_FAIL;
        LOG_DEBUG("flash init complete");
 
+       if (mflash_init_drivers(cmd_ctx) != ERROR_OK)
+               return ERROR_FAIL;
+       LOG_DEBUG("mflash init complete");
+
        if (nand_init(cmd_ctx) != ERROR_OK)
                return ERROR_FAIL;
        LOG_DEBUG("NAND init complete");
        if (nand_init(cmd_ctx) != ERROR_OK)
                return ERROR_FAIL;
        LOG_DEBUG("NAND init complete");
@@ -189,7 +202,8 @@ command_context_t *setup_command_handler(void)
        flash_register_commands(cmd_ctx);
        nand_register_commands(cmd_ctx);
        pld_register_commands(cmd_ctx);
        flash_register_commands(cmd_ctx);
        nand_register_commands(cmd_ctx);
        pld_register_commands(cmd_ctx);
-       
+       mflash_register_commands(cmd_ctx);
+
        if (log_init(cmd_ctx) != ERROR_OK)
        {
                exit(-1);
        if (log_init(cmd_ctx) != ERROR_OK)
        {
                exit(-1);
@@ -216,7 +230,7 @@ int openocd_main(int argc, char *argv[])
 
        cmd_ctx = setup_command_handler();
        
 
        cmd_ctx = setup_command_handler();
        
-       LOG_OUTPUT("\n\nBUGS? Read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS\n\n\n");
+       LOG_OUTPUT( "\n\nBUGS? Read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS\n\n\n");
 
        print_version();
        
 
        print_version();
        

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)