Remove redundant sys/types.h #include directives (now in types.h).
[openocd.git] / src / flash / mflash.c
index 52c6a9fe4e6f626f1e82cfb67725a1ececf8d0ce..451d942b1e7717b0ea599b4a9c4ac402755f445c 100644 (file)
-/***************************************************************************\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
+/***************************************************************************
+ *   Copyright (C) 2007-2008 by unsik Kim <donari75@gmail.com>             *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include "command.h"
+#include "log.h"
+#include "target.h"
+#include "time_support.h"
+#include "fileio.h"
+#include "mflash.h"
+
+static int s3c2440_set_gpio_to_output (mflash_gpio_num_t gpio);
+static int s3c2440_set_gpio_output_val (mflash_gpio_num_t gpio, u8 val);
+static int pxa270_set_gpio_to_output (mflash_gpio_num_t gpio);
+static int pxa270_set_gpio_output_val (mflash_gpio_num_t gpio, u8 val);
+
+static command_t *mflash_cmd;
+
+static mflash_bank_t *mflash_bank;
+
+static mflash_gpio_drv_t pxa270_gpio = {
+       .name = "pxa270",
+       .set_gpio_to_output = pxa270_set_gpio_to_output,
+       .set_gpio_output_val = pxa270_set_gpio_output_val
+};
+
+static mflash_gpio_drv_t s3c2440_gpio = {
+       .name = "s3c2440",
+       .set_gpio_to_output = s3c2440_set_gpio_to_output,
+       .set_gpio_output_val = s3c2440_set_gpio_output_val
+};
+
+static mflash_gpio_drv_t *mflash_gpio[] =
+{
+               &pxa270_gpio,
+               &s3c2440_gpio,
+               NULL
+};
+
+#define PXA270_GAFR0_L 0x40E00054
+#define PXA270_GAFR3_U 0x40E00070
+#define PXA270_GAFR3_U_RESERVED_BITS  0xfffc0000u
+#define PXA270_GPDR0 0x40E0000C
+#define PXA270_GPDR3 0x40E0010C
+#define PXA270_GPDR3_RESERVED_BITS  0xfe000000u
+#define PXA270_GPSR0 0x40E00018
+#define PXA270_GPCR0 0x40E00024
+
+static int pxa270_set_gpio_to_output (mflash_gpio_num_t gpio)
+{
+       u32 addr, value, mask;
+       target_t *target = mflash_bank->target;
+       int ret;
+
+       /* remove alternate function. */
+       mask = 0x3u << (gpio.num & 0xF)*2;
+
+       addr = PXA270_GAFR0_L + (gpio.num >> 4) * 4;
+
+       if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
+               return ret;
+
+       value &= ~mask;
+       if (addr == PXA270_GAFR3_U)
+               value &= ~PXA270_GAFR3_U_RESERVED_BITS;
+
+       if ((ret = target_write_u32(target, addr, value)) != ERROR_OK)
+               return ret;
+
+       /* set direction to output */
+       mask = 0x1u << (gpio.num & 0x1F);
+
+       addr = PXA270_GPDR0 + (gpio.num >> 5) * 4;
+
+       if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
+               return ret;
+
+       value |= mask;
+       if (addr == PXA270_GPDR3)
+               value &= ~PXA270_GPDR3_RESERVED_BITS;
+
+       ret = target_write_u32(target, addr, value);
+       return ret;
+}
+
+static int pxa270_set_gpio_output_val (mflash_gpio_num_t gpio, u8 val)
+{
+       u32 addr, value, mask;
+       target_t *target = mflash_bank->target;
+       int ret;
+
+       mask = 0x1u << (gpio.num & 0x1F);
+
+       if (val) {
+               addr = PXA270_GPSR0 + (gpio.num >> 5) * 4;
+       } else {
+               addr = PXA270_GPCR0 + (gpio.num >> 5) * 4;
+       }
+
+       if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
+               return ret;
+
+       value |= mask;
+
+       ret = target_write_u32(target, addr, value);
+
+       return ret;
+}
+
+#define S3C2440_GPACON 0x56000000
+#define S3C2440_GPADAT 0x56000004
+#define S3C2440_GPJCON 0x560000d0
+#define S3C2440_GPJDAT 0x560000d4
+
+static int s3c2440_set_gpio_to_output (mflash_gpio_num_t gpio)
+{
+       u32 data, mask, gpio_con;
+       target_t *target = mflash_bank->target;
+       int ret;
+
+       if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {
+               gpio_con = S3C2440_GPACON + (gpio.port[0] - 'a') * 0x10;
+       } else if (gpio.port[0] == 'j') {
+               gpio_con = S3C2440_GPJCON;
+       } else {
+               LOG_ERROR("invalid port %d%s", gpio.num, gpio.port);
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       ret = target_read_u32(target, gpio_con, &data);
+
+       if (ret == ERROR_OK) {
+               if (gpio.port[0] == 'a') {
+                       mask = 1 << gpio.num;
+                       data &= ~mask;
+               } else {
+                       mask = 3 << gpio.num * 2;
+                       data &= ~mask;
+                       data |= (1 << gpio.num * 2);
+               }
+
+               ret = target_write_u32(target, gpio_con, data);
+       }
+       return ret;
+}
+
+static int s3c2440_set_gpio_output_val (mflash_gpio_num_t gpio, u8 val)
+{
+       u32 data, mask, gpio_dat;
+       target_t *target = mflash_bank->target;
+       int ret;
+
+       if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {
+               gpio_dat = S3C2440_GPADAT + (gpio.port[0] - 'a') * 0x10;
+       } else if (gpio.port[0] == 'j') {
+               gpio_dat = S3C2440_GPJDAT;
+       } else {
+               LOG_ERROR("invalid port %d%s", gpio.num, gpio.port);
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       ret = target_read_u32(target, gpio_dat, &data);
+
+       if (ret == ERROR_OK) {
+               mask = 1 << gpio.num;
+               if (val)
+                       data |= mask;
+               else
+                       data &= ~mask;
+
+               ret = target_write_u32(target, gpio_dat, data);
+       }
+       return ret;
+}
+
+static int mflash_rst(u8 level)
+{
+       return mflash_bank->gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, level);
+}
+
+static int mflash_init_gpio (void)
+{
+       mflash_gpio_drv_t *gpio_drv = mflash_bank->gpio_drv;
+
+       gpio_drv->set_gpio_to_output(mflash_bank->rst_pin);
+       gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, 1);
+
+       if (mflash_bank->wp_pin.num != -1) {
+               gpio_drv->set_gpio_to_output(mflash_bank->wp_pin);
+               gpio_drv->set_gpio_output_val(mflash_bank->wp_pin, 1);
+       }
+
+       if (mflash_bank->dpd_pin.num != -1) {
+               gpio_drv->set_gpio_to_output(mflash_bank->dpd_pin);
+               gpio_drv->set_gpio_output_val(mflash_bank->dpd_pin, 1);
+       }
+
+       return ERROR_OK;
+}
+
+static int mg_dsk_wait(mg_io_type_wait wait, u32 time)
+{
+       u8 status, error;
+       target_t *target = mflash_bank->target;
+       u32 mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
+       duration_t duration;
+       long long t=0;
+
+       duration_start_measure(&duration);
+
+       while (time) {
+
+               target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);
+
+               if (status & mg_io_rbit_status_busy)
+               {
+                       if (wait == mg_io_wait_bsy)
+                               return ERROR_OK;
+               } else {
+                       switch(wait)
+                       {
+                               case mg_io_wait_not_bsy:
+                                       return ERROR_OK;
+                               case mg_io_wait_rdy_noerr:
+                                       if (status & mg_io_rbit_status_ready)
+                                               return ERROR_OK;
+                                       break;
+                               case mg_io_wait_drq_noerr:
+                                       if (status & mg_io_rbit_status_data_req)
+                                               return ERROR_OK;
+                                       break;
+                               default:
+                                       break;
+                       }
+
+                       /* Now we check the error condition! */
+                       if (status & mg_io_rbit_status_error)
+                       {
+                               target_read_u8(target, mg_task_reg + MG_REG_ERROR, &error);
+
+                               if (error & mg_io_rbit_err_bad_sect_num) {
+                                       LOG_ERROR("sector not found");
+                                       return ERROR_FAIL;
+                               }
+                               else if (error & (mg_io_rbit_err_bad_block | mg_io_rbit_err_uncorrectable)) {
+                                       LOG_ERROR("bad block");
+                                       return ERROR_FAIL;
+                               } else {
+                                       LOG_ERROR("disk operation fail");
+                                       return ERROR_FAIL;
+                               }
+                       }
+
+                       switch (wait)
+                       {
+                               case mg_io_wait_rdy:
+                                       if (status & mg_io_rbit_status_ready)
+                                               return ERROR_OK;
+
+                               case mg_io_wait_drq:
+                                       if (status & mg_io_rbit_status_data_req)
+                                               return ERROR_OK;
+
+                               default:
+                                       break;
+                       }
+               }
+
+               duration_stop_measure(&duration, NULL);
+
+               t=duration.duration.tv_usec/1000;
+               t+=duration.duration.tv_sec*1000;
+
+               if (t > time)
+                       break;
+       }
+
+       LOG_ERROR("timeout occured");
+       return ERROR_FAIL;
+}
+
+static int mg_dsk_srst(u8 on)
+{
+       target_t *target = mflash_bank->target;
+       u32 mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
+       u8 value;
+       int ret;
+
+       if ((ret = target_read_u8(target, mg_task_reg + MG_REG_DRV_CTRL, &value)) != ERROR_OK)
+               return ret;
+
+       if(on) {
+               value |= (mg_io_rbit_devc_srst);
+       } else {
+               value &= ~mg_io_rbit_devc_srst;
+       }
+
+       ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_CTRL, value);
+       return ret;
+}
+
+static int mg_dsk_io_cmd(u32 sect_num, u32 cnt, u8 cmd)
+{
+       target_t *target = mflash_bank->target;
+       u32 mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
+       u8 value;
+
+       if (mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL) != ERROR_OK)
+               return ERROR_FAIL;
+
+       value = mg_io_rval_dev_drv_master | mg_io_rval_dev_lba_mode |((sect_num >> 24) & 0xf);
+
+       target_write_u8(target, mg_task_reg + MG_REG_DRV_HEAD, value);
+       target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, (u8)cnt);
+       target_write_u8(target, mg_task_reg + MG_REG_SECT_NUM, (u8)sect_num);
+       target_write_u8(target, mg_task_reg + MG_REG_CYL_LOW, (u8)(sect_num >> 8));
+       target_write_u8(target, mg_task_reg + MG_REG_CYL_HIGH, (u8)(sect_num >> 16));
+
+       target_write_u8(target, mg_task_reg + MG_REG_COMMAND, cmd);
+
+       return ERROR_OK;
+}
+
+static int mg_dsk_drv_info(void)
+{
+       target_t *target = mflash_bank->target;
+       u32 mg_buff = mflash_bank->base + MG_BUFFER_OFFSET;
+
+       if ( mg_dsk_io_cmd(0, 1, mg_io_cmd_identify) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if ( mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL) != ERROR_OK)
+               return ERROR_FAIL;
+
+       LOG_INFO("read drive info.");
+
+       if (! mflash_bank->drv_info)
+               mflash_bank->drv_info = malloc(sizeof(mg_drv_info_t));
+
+       target->type->read_memory(target, mg_buff, 2, sizeof(mg_io_type_drv_info) >> 1,
+                       (u8 *)&mflash_bank->drv_info->drv_id);
+
+       mflash_bank->drv_info->tot_sects = (u32)(mflash_bank->drv_info->drv_id.total_user_addressable_sectors_hi << 16)
+                                                                       + mflash_bank->drv_info->drv_id.total_user_addressable_sectors_lo;
+
+       target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read);
+
+       return ERROR_OK;
+}
+
+static int mg_mflash_probe(void)
+{
+       mflash_bank->proved = 0;
+
+       mflash_init_gpio();
+
+       LOG_INFO("reset mflash");
+
+       mflash_rst(0);
+
+       if (mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG) != ERROR_OK)
+               return ERROR_FAIL;
+
+       mflash_rst(1);
+
+       if (mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG) != ERROR_OK)
+               return ERROR_FAIL;
+
+       mg_dsk_srst(1);
+
+       if (mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG) != ERROR_OK)
+               return ERROR_FAIL;
+
+       mg_dsk_srst(0);
+
+       if (mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (mg_dsk_drv_info() != ERROR_OK)
+               return ERROR_FAIL;
+
+       mflash_bank->proved = 1;
+
+       return ERROR_OK;
+}
+
+static int mflash_probe_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int ret;
+
+       ret = mg_mflash_probe();
+
+       if (ret == ERROR_OK) {
+               command_print(cmd_ctx, "mflash (total %u sectors) found at 0x%8.8x",
+                               mflash_bank->drv_info->tot_sects, mflash_bank->base );
+       }
+
+       return ret;
+}
+
+static int mg_mflash_do_read_sects(void *buff, u32 sect_num, u32 sect_cnt)
+{
+       u32 i, address;
+       int ret;
+       target_t *target = mflash_bank->target;
+       u8 *buff_ptr = buff;
+       duration_t duration;
+
+       if ( mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_read) != ERROR_OK )
+               return ERROR_FAIL;
+
+       address = mflash_bank->base + MG_BUFFER_OFFSET;
+
+       duration_start_measure(&duration);
+
+       for (i = 0; i < sect_cnt; i++) {
+               mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
+
+               target->type->read_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
+               buff_ptr += MG_MFLASH_SECTOR_SIZE;
+
+               target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read);
+
+               LOG_DEBUG("%u (0x%8.8x) sector read", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
+
+               duration_stop_measure(&duration, NULL);
+
+               if ((duration.duration.tv_sec * 1000 + duration.duration.tv_usec / 1000) > 3000) {
+                       LOG_INFO("read %u'th sectors", sect_num + i);
+                       duration_start_measure(&duration);
+               }
+       }
+
+       ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
+
+       return ret;
+}
+
+static int mg_mflash_read_sects(void *buff, u32 sect_num, u32 sect_cnt)
+{
+       u32 quotient, residue, i;
+       u8 *buff_ptr = buff;
+
+       quotient = sect_cnt >> 8;
+       residue = sect_cnt % 256;
+
+       for (i = 0; i < quotient; i++) {
+               LOG_DEBUG("sect num : %u buff : 0x%0lx", sect_num, 
+                       (unsigned long)buff_ptr);
+               mg_mflash_do_read_sects(buff_ptr, sect_num, 256);
+               sect_num += 256;
+               buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
+       }
+
+       if (residue) {
+               LOG_DEBUG("sect num : %u buff : %0lx", sect_num, 
+                       (unsigned long)buff_ptr);
+               mg_mflash_do_read_sects(buff_ptr, sect_num, residue);
+       }
+
+       return ERROR_OK;
+}
+
+static int mg_mflash_do_write_sects(void *buff, u32 sect_num, u32 sect_cnt)
+{
+       u32 i, address;
+       int ret;
+       target_t *target = mflash_bank->target;
+       u8 *buff_ptr = buff;
+       duration_t duration;
+
+       if ( mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_write) != ERROR_OK ) {
+               LOG_ERROR("mg_io_cmd_write fail");
+               return ERROR_FAIL;
+       }
+
+       address = mflash_bank->base + MG_BUFFER_OFFSET;
+
+       duration_start_measure(&duration);
+
+       for (i = 0; i < sect_cnt; i++) {
+               ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
+               if (ret != ERROR_OK)
+                       LOG_ERROR("mg_io_wait_drq time out");
+
+               ret = target->type->write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
+               if (ret != ERROR_OK)
+                       LOG_ERROR("mem write error");
+               buff_ptr += MG_MFLASH_SECTOR_SIZE;
+
+               ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_write);
+               if (ret != ERROR_OK)
+                       LOG_ERROR("mg_io_cmd_confirm_write error");
+
+               LOG_DEBUG("%u (0x%8.8x) sector write", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
+
+               duration_stop_measure(&duration, NULL);
+
+               if ((duration.duration.tv_sec * 1000 + duration.duration.tv_usec / 1000) > 3000) {
+                       LOG_INFO("wrote %u'th sectors", sect_num + i);
+                       duration_start_measure(&duration);
+               }
+       }
+
+       ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
+
+       return ret;
+}
+
+static int mg_mflash_write_sects(void *buff, u32 sect_num, u32 sect_cnt)
+{
+       u32 quotient, residue, i;
+       u8 *buff_ptr = buff;
+
+       quotient = sect_cnt >> 8;
+       residue = sect_cnt % 256;
+
+       for (i = 0; i < quotient; i++) {
+               LOG_DEBUG("sect num : %u buff : %0lx", sect_num, 
+                       (unsigned long)buff_ptr);
+               mg_mflash_do_write_sects(buff_ptr, sect_num, 256);
+               sect_num += 256;
+               buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
+       }
+
+       if (residue) {
+               LOG_DEBUG("sect num : %u buff : %0lx", sect_num, 
+                       (unsigned long)buff_ptr);
+               mg_mflash_do_write_sects(buff_ptr, sect_num, residue);
+       }
+
+       return ERROR_OK;
+}
+
+static int mg_mflash_read (u32 addr, u8 *buff, u32 len)
+{
+       u8 *sect_buff, *buff_ptr = buff;
+       u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num;
+
+       cnt = 0;
+       cur_addr = addr;
+       end_addr = addr + len;
+
+       sect_buff = malloc(MG_MFLASH_SECTOR_SIZE);
+
+       if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
+
+               next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
+               sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
+               mg_mflash_read_sects(sect_buff, sect_num, 1);
+
+               if (end_addr < next_sec_addr) {
+                       memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), end_addr - cur_addr);
+                       LOG_DEBUG("copies %u byte from sector offset 0x%8.8x", end_addr - cur_addr, cur_addr);
+                       cur_addr = end_addr;
+               } else {
+                       memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), next_sec_addr - cur_addr);
+                       LOG_DEBUG("copies %u byte from sector offset 0x%8.8x", next_sec_addr - cur_addr, cur_addr);
+                       buff_ptr += (next_sec_addr - cur_addr);
+                       cur_addr = next_sec_addr;
+               }
+       }
+
+       if (cur_addr < end_addr) {
+
+               sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
+               next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
+
+               while (next_sec_addr <= end_addr) {
+                       cnt++;
+                       next_sec_addr += MG_MFLASH_SECTOR_SIZE;
+               }
+
+               if (cnt)
+                       mg_mflash_read_sects(buff_ptr, sect_num, cnt);
+
+               buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
+               cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
+
+               if (cur_addr < end_addr) {
+
+                       sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
+                       mg_mflash_read_sects(sect_buff, sect_num, 1);
+                       memcpy(buff_ptr, sect_buff, end_addr - cur_addr);
+                       LOG_DEBUG("copies %u byte", end_addr - cur_addr);
+
+               }
+       }
+
+       free(sect_buff);
+
+       return ERROR_OK;
+}
+
+static int mg_mflash_write(u32 addr, u8 *buff, u32 len)
+{
+       u8 *sect_buff, *buff_ptr = buff;
+       u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num;
+
+       cnt = 0;
+       cur_addr = addr;
+       end_addr = addr + len;
+
+       sect_buff = malloc(MG_MFLASH_SECTOR_SIZE);
+
+       if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
+
+               next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
+               sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
+               mg_mflash_read_sects(sect_buff, sect_num, 1);
+
+               if (end_addr < next_sec_addr) {
+                       memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, end_addr - cur_addr);
+                       LOG_DEBUG("copies %u byte to sector offset 0x%8.8x", end_addr - cur_addr, cur_addr);
+                       cur_addr = end_addr;
+               } else {
+                       memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, next_sec_addr - cur_addr);
+                       LOG_DEBUG("copies %u byte to sector offset 0x%8.8x", next_sec_addr - cur_addr, cur_addr);
+                       buff_ptr += (next_sec_addr - cur_addr);
+                       cur_addr = next_sec_addr;
+               }
+
+               mg_mflash_write_sects(sect_buff, sect_num, 1);
+       }
+
+       if (cur_addr < end_addr) {
+
+               sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
+               next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
+
+               while (next_sec_addr <= end_addr) {
+                       cnt++;
+                       next_sec_addr += MG_MFLASH_SECTOR_SIZE;
+               }
+
+               if (cnt)
+                       mg_mflash_write_sects(buff_ptr, sect_num, cnt);
+
+               buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
+               cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
+
+               if (cur_addr < end_addr) {
+
+                       sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
+                       mg_mflash_read_sects(sect_buff, sect_num, 1);
+                       memcpy(sect_buff, buff_ptr, end_addr - cur_addr);
+                       LOG_DEBUG("copies %u byte", end_addr - cur_addr);
+                       mg_mflash_write_sects(sect_buff, sect_num, 1);
+               }
+       }
+
+       free(sect_buff);
+
+       return ERROR_OK;
+}
+
+static int mflash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       u32 address, buf_cnt;
+       u8 *buffer;
+       /* TODO : multi-bank support, large file support */
+       fileio_t fileio;
+       duration_t duration;
+       char *duration_text;
+       int ret;
+
+       if (argc != 3) {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       address = strtoul(args[2], NULL, 0);
+
+       if (! mflash_bank->proved ) {
+               mg_mflash_probe();
+       }
+
+       if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) {
+               return ERROR_FAIL;
+       }
+
+       buffer = malloc(fileio.size);
+
+       if (fileio_read(&fileio, fileio.size, buffer, &buf_cnt) != ERROR_OK)
+       {
+               free(buffer);
+               fileio_close(&fileio);
+               return ERROR_FAIL;
+       }
+
+       duration_start_measure(&duration);
+
+       ret = mg_mflash_write(address, buffer, (u32)fileio.size);
+
+       duration_stop_measure(&duration, &duration_text);
+
+       command_print(cmd_ctx, "wrote %lli byte from file %s in %s (%f kB/s)",
+               fileio.size, args[1], duration_text,
+               (float)fileio.size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
+
+       free(duration_text);
+
+       fileio_close(&fileio);
+
+       free(buffer);
+
+       return ERROR_OK;
+}
+
+static int mflash_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       u32 address, size_written, size;
+       u8 *buffer;
+       /* TODO : multi-bank support */
+       fileio_t fileio;
+       duration_t duration;
+       char *duration_text;
+
+       if (argc != 4) {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       address = strtoul(args[2], NULL, 0);
+       size = strtoul(args[3], NULL, 0);
+
+       if (! mflash_bank->proved ) {
+                       mg_mflash_probe();
+       }
+
+       if (fileio_open(&fileio, args[1], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) {
+               return ERROR_FAIL;
+       }
+
+       buffer = malloc(size);
+
+       duration_start_measure(&duration);
+
+       mg_mflash_read(address, buffer, size);
+
+       duration_stop_measure(&duration, &duration_text);
+
+       fileio_write(&fileio, size, buffer, &size_written);
+
+       command_print(cmd_ctx, "dump image (address 0x%8.8x size %u) to file %s in %s (%f kB/s)",
+                               address, size, args[1], duration_text,
+                               (float)size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
+
+       free(duration_text);
+
+       fileio_close(&fileio);
+
+       free(buffer);
+
+       return ERROR_OK;
+}
+
+int mflash_init_drivers(struct command_context_s *cmd_ctx)
+{
+       if (mflash_bank) {
+               register_command(cmd_ctx, mflash_cmd, "probe", mflash_probe_command, COMMAND_EXEC, NULL);
+               register_command(cmd_ctx, mflash_cmd, "write", mflash_write_command, COMMAND_EXEC,
+                               "mflash write <num> <file> <address>");
+               register_command(cmd_ctx, mflash_cmd, "dump", mflash_dump_command, COMMAND_EXEC,
+                                               "mflash dump <num> <file> <address> <size>");
+       }
+
+       return ERROR_OK;
+}
+
+static int mflash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       char *str;
+       int i;
+
+       if (argc < 8)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       if ((target = get_target_by_num(strtoul(args[7], NULL, 0))) == NULL)
+       {
+               LOG_ERROR("target %lu not defined", strtoul(args[7], NULL, 0));
+               return ERROR_FAIL;
+       }
+
+       mflash_bank = calloc(sizeof(mflash_bank_t), 1);
+       mflash_bank->base = strtoul(args[1], NULL, 0);
+       mflash_bank->chip_width = strtoul(args[2], NULL, 0);
+       mflash_bank->bus_width = strtoul(args[3], NULL, 0);
+       mflash_bank->rst_pin.num = strtoul(args[4], &str, 0);
+       if (*str)
+               mflash_bank->rst_pin.port[0] = (u16)tolower(str[0]);
+       mflash_bank->wp_pin.num = strtol(args[5], &str, 0);
+       if (*str)
+               mflash_bank->wp_pin.port[0] = (u16)tolower(str[0]);
+       mflash_bank->dpd_pin.num = strtol(args[6], &str, 0);
+       if (*str)
+               mflash_bank->dpd_pin.port[0] = (u16)tolower(str[0]);
+
+       mflash_bank->target = target;
+
+       for (i = 0; mflash_gpio[i] ; i++) {
+               if (! strcmp(mflash_gpio[i]->name, args[0])) {
+                       mflash_bank->gpio_drv = mflash_gpio[i];
+               }
+       }
+
+       if (! mflash_bank->gpio_drv) {
+               LOG_ERROR("%s is unsupported soc", args[0]);
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       return ERROR_OK;
+}
+
+int mflash_register_commands(struct command_context_s *cmd_ctx)
+{
+       mflash_cmd = register_command(cmd_ctx, NULL, "mflash", NULL, COMMAND_ANY, NULL);
+       register_command(cmd_ctx, mflash_cmd, "bank", mflash_bank_command, COMMAND_CONFIG,
+                       "mflash bank <soc> <base> <chip_width> <bus_width> <RST pin> <WP pin> <DPD pin> <target #>");
+       return ERROR_OK;
+}

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)