target_t -> struct target
[fw/openocd] / src / flash / pic32mx.c
index c2593ce258be4923aa74d726464ec7537e8b04fd..25f90fd6b0f6c8dcdb8f003565c2c0cf0d23d299 100644 (file)
 #include "config.h"
 #endif
 
-#include "replacements.h"
-
 #include "pic32mx.h"
-#include "flash.h"
-#include "target.h"
-#include "log.h"
 #include "mips32.h"
-#include "algorithm.h"
-#include "binarybuffer.h"
 
-#include <stdlib.h>
-#include <string.h>
 
 static
 struct pic32mx_devs_s {
-       u8      devid;
+       uint8_t devid;
        char    *name;
-       u32     pfm_size;
+       uint32_t        pfm_size;
 } pic32mx_devs[] = {
        { 0x78, "460F512L USB", 512 },
        { 0x74, "460F256L USB", 256 },
@@ -66,62 +57,14 @@ struct pic32mx_devs_s {
        { 0x00, NULL, 0 }
 };
 
-int pic32mx_register_commands(struct command_context_s *cmd_ctx);
-int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
-int pic32mx_erase(struct flash_bank_s *bank, int first, int last);
-int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last);
-int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
-int pic32mx_probe(struct flash_bank_s *bank);
-int pic32mx_auto_probe(struct flash_bank_s *bank);
-int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int pic32mx_protect_check(struct flash_bank_s *bank);
-int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size);
-
-#if 0
-int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-#endif
-int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int pic32mx_chip_erase(struct flash_bank_s *bank);
-
-flash_driver_t pic32mx_flash =
-{
-       .name = "pic32mx",
-       .register_commands = pic32mx_register_commands,
-       .flash_bank_command = pic32mx_flash_bank_command,
-       .erase = pic32mx_erase,
-       .protect = pic32mx_protect,
-       .write = pic32mx_write,
-       .probe = pic32mx_probe,
-       .auto_probe = pic32mx_auto_probe,
-       .erase_check = default_flash_mem_blank_check,
-       .protect_check = pic32mx_protect_check,
-       .info = pic32mx_info
-};
-
-int pic32mx_register_commands(struct command_context_s *cmd_ctx)
-{
-       command_t *pic32mx_cmd = register_command(cmd_ctx, NULL, "pic32mx", NULL, COMMAND_ANY, "pic32mx flash specific commands");
-
-#if 0
-       register_command(cmd_ctx, pic32mx_cmd, "lock", pic32mx_handle_lock_command, COMMAND_EXEC,
-                                        "lock device");
-       register_command(cmd_ctx, pic32mx_cmd, "unlock", pic32mx_handle_unlock_command, COMMAND_EXEC,
-                                        "unlock protected device");
-#endif
-       register_command(cmd_ctx, pic32mx_cmd, "chip_erase", pic32mx_handle_chip_erase_command, COMMAND_EXEC,
-                                        "erase device");
-       register_command(cmd_ctx, pic32mx_cmd, "pgm_word", pic32mx_handle_pgm_word_command, COMMAND_EXEC,
-                                        "program a word");
-       return ERROR_OK;
-}
+static int pic32mx_write_row(struct flash_bank_s *bank, uint32_t address, uint32_t srcaddr);
+static int pic32mx_write_word(struct flash_bank_s *bank, uint32_t address, uint32_t word);
 
 /* flash bank pic32mx <base> <size> 0 0 <target#>
  */
-int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
+FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command)
 {
-       pic32mx_flash_bank_t *pic32mx_info;
+       struct pic32mx_flash_bank *pic32mx_info;
 
        if (argc < 6)
        {
@@ -129,7 +72,7 @@ int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, cha
                return ERROR_FLASH_BANK_INVALID;
        }
 
-       pic32mx_info = malloc(sizeof(pic32mx_flash_bank_t));
+       pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
        bank->driver_priv = pic32mx_info;
 
        pic32mx_info->write_algorithm = NULL;
@@ -138,38 +81,38 @@ int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, cha
        return ERROR_OK;
 }
 
-u32 pic32mx_get_flash_status(flash_bank_t *bank)
+static uint32_t pic32mx_get_flash_status(flash_bank_t *bank)
 {
-       target_t *target = bank->target;
-       u32 status;
+       struct target *target = bank->target;
+       uint32_t status;
 
        target_read_u32(target, PIC32MX_NVMCON, &status);
 
        return status;
 }
 
-u32 pic32mx_wait_status_busy(flash_bank_t *bank, int timeout)
+static uint32_t pic32mx_wait_status_busy(flash_bank_t *bank, int timeout)
 {
-       u32 status;
+       uint32_t status;
 
        /* wait for busy to clear */
        while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0))
        {
-               LOG_DEBUG("status: 0x%x", status);
+               LOG_DEBUG("status: 0x%" PRIx32, status);
                alive_sleep(1);
        }
-       if(timeout <= 0)
-               LOG_DEBUG("timeout: status: 0x%x", status);
+       if (timeout <= 0)
+               LOG_DEBUG("timeout: status: 0x%" PRIx32, status);
 
        return status;
 }
 
-int pic32mx_nvm_exec(struct flash_bank_s *bank, u32 op, u32 timeout)
+static int pic32mx_nvm_exec(struct flash_bank_s *bank, uint32_t op, uint32_t timeout)
 {
-       target_t *target = bank->target;
-       u32 status;
+       struct target *target = bank->target;
+       uint32_t status;
 
-       target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN|op);
+       target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN | op);
 
        /* unlock flash registers */
        target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1);
@@ -186,12 +129,11 @@ int pic32mx_nvm_exec(struct flash_bank_s *bank, u32 op, u32 timeout)
        return status;
 }
 
-int pic32mx_protect_check(struct flash_bank_s *bank)
+static int pic32mx_protect_check(struct flash_bank_s *bank)
 {
-       target_t *target = bank->target;
-       pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv;
+       struct target *target = bank->target;
 
-       u32 devcfg0;
+       uint32_t devcfg0;
        int s;
        int num_pages;
 
@@ -202,11 +144,11 @@ int pic32mx_protect_check(struct flash_bank_s *bank)
        }
 
        target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0);
-       if((devcfg0 & (1<<28)) == 0) /* code protect bit */
+       if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
                num_pages = 0xffff;  /* All pages protected */
-       else if(bank->base == PIC32MX_KSEG1_BOOT_FLASH)
+       else if (bank->base == PIC32MX_KSEG1_BOOT_FLASH)
        {
-               if(devcfg0 & (1<<24))
+               if (devcfg0 & (1 << 24))
                        num_pages = 0;       /* All pages unprotected */
                else
                        num_pages = 0xffff;  /* All pages protected */
@@ -221,11 +163,11 @@ int pic32mx_protect_check(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int pic32mx_erase(struct flash_bank_s *bank, int first, int last)
+static int pic32mx_erase(struct flash_bank_s *bank, int first, int last)
 {
-       target_t *target = bank->target;
+       struct target *target = bank->target;
        int i;
-       u32 status;
+       uint32_t status;
 
        if (bank->target->state != TARGET_HALTED)
        {
@@ -233,27 +175,29 @@ int pic32mx_erase(struct flash_bank_s *bank, int first, int last)
                return ERROR_TARGET_NOT_HALTED;
        }
 
-#if 0
        if ((first == 0) && (last == (bank->num_sectors - 1)) && (bank->base == PIC32MX_KSEG0_PGM_FLASH || bank->base == PIC32MX_KSEG1_PGM_FLASH))
        {
+               LOG_DEBUG("Erasing entire program flash");
                status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50);
-               if( status & NVMCON_NVMERR )
+               if (status & NVMCON_NVMERR)
                        return ERROR_FLASH_OPERATION_FAILED;
-               if( status & NVMCON_LVDERR )
+               if (status & NVMCON_LVDERR)
                        return ERROR_FLASH_OPERATION_FAILED;
                return ERROR_OK;
        }
-#endif
 
        for (i = first; i <= last; i++)
        {
-               target_write_u32(target, PIC32MX_NVMADDR, bank->base + bank->sectors[i].offset);
+               if (bank->base >= PIC32MX_KSEG1_PGM_FLASH)
+                       target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(bank->base + bank->sectors[i].offset));
+               else
+                       target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(bank->base + bank->sectors[i].offset));
 
                status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
 
-               if( status & NVMCON_NVMERR )
+               if (status & NVMCON_NVMERR)
                        return ERROR_FLASH_OPERATION_FAILED;
-               if( status & NVMCON_LVDERR )
+               if (status & NVMCON_LVDERR)
                        return ERROR_FLASH_OPERATION_FAILED;
                bank->sectors[i].is_erased = 1;
        }
@@ -261,14 +205,16 @@ int pic32mx_erase(struct flash_bank_s *bank, int first, int last)
        return ERROR_OK;
 }
 
-int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last)
+static int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last)
 {
-       pic32mx_flash_bank_t *pic32mx_info = NULL;
-       target_t *target = bank->target;
-       u16 prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
+       struct pic32mx_flash_bank *pic32mx_info = NULL;
+       struct target *target = bank->target;
+#if 0
+       uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
        int i, reg, bit;
        int status;
-       u32 protection;
+       uint32_t protection;
+#endif
 
        pic32mx_info = bank->driver_priv;
 
@@ -289,10 +235,10 @@ int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last)
         * high density - each bit refers to a 2bank protection */
        target_read_u32(target, PIC32MX_FLASH_WRPR, &protection);
 
-       prot_reg[0] = (u16)protection;
-       prot_reg[1] = (u16)(protection >> 8);
-       prot_reg[2] = (u16)(protection >> 16);
-       prot_reg[3] = (u16)(protection >> 24);
+       prot_reg[0] = (uint16_t)protection;
+       prot_reg[1] = (uint16_t)(protection >> 8);
+       prot_reg[2] = (uint16_t)(protection >> 16);
+       prot_reg[3] = (uint16_t)(protection >> 24);
 
        if (pic32mx_info->ppage_size == 2)
        {
@@ -317,7 +263,7 @@ int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last)
                        reg = (i / pic32mx_info->ppage_size) / 8;
                        bit = (i / pic32mx_info->ppage_size) - (reg * 8);
 
-                       if( set )
+                       if (set)
                                prot_reg[reg] &= ~(1 << bit);
                        else
                                prot_reg[reg] |= (1 << bit);
@@ -331,7 +277,7 @@ int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last)
                        reg = (i / pic32mx_info->ppage_size) / 8;
                        bit = (i / pic32mx_info->ppage_size) - (reg * 8);
 
-                       if( set )
+                       if (set)
                                prot_reg[reg] &= ~(1 << bit);
                        else
                                prot_reg[reg] |= (1 << bit);
@@ -352,19 +298,18 @@ int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last)
 #endif
 }
 
-int pic32mx_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
+static int pic32mx_write_block(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
 {
-       pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv;
-       target_t *target = bank->target;
-       u32 buffer_size = 8192;
-       working_area_t *source;
-       u32 address = bank->base + offset;
-       reg_param_t reg_params[4];
-#if 0
-       armv7m_algorithm_t armv7m_info;
+       struct target *target = bank->target;
+       uint32_t buffer_size = 512;
+       struct working_area *source;
+       uint32_t address = bank->base + offset;
        int retval = ERROR_OK;
+#if 0
+       struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
+       struct armv7m_algorithm armv7m_info;
 
-       u8 pic32mx_flash_write_code[] = {
+       uint8_t pic32mx_flash_write_code[] = {
                                                                        /* write: */
                0xDF, 0xF8, 0x24, 0x40,         /* ldr  r4, PIC32MX_FLASH_CR */
                0x09, 0x4D,                                     /* ldr  r5, PIC32MX_FLASH_SR */
@@ -393,44 +338,38 @@ int pic32mx_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 c
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        };
 
-       if ((retval=target_write_buffer(target, pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), pic32mx_flash_write_code))!=ERROR_OK)
+       if ((retval = target_write_buffer(target, pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), pic32mx_flash_write_code)) != ERROR_OK)
                return retval;
+#endif
 
        /* memory buffer */
-       while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
+       if (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
        {
-               buffer_size /= 2;
-               if (buffer_size <= 256)
-               {
-                       /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
-                       if (pic32mx_info->write_algorithm)
-                               target_free_working_area(target, pic32mx_info->write_algorithm);
-
-                       LOG_WARNING("no large enough working area available, can't do block memory writes");
-                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-               }
-       };
-
-       armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
-       armv7m_info.core_mode = ARMV7M_MODE_ANY;
+#if 0
+               /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
+               if (pic32mx_info->write_algorithm)
+                       target_free_working_area(target, pic32mx_info->write_algorithm);
+#endif
 
-       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
-       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
-       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
-       init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
+               LOG_WARNING("no large enough working area available, can't do block memory writes");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
 
-       while (count > 0)
+       while (count >= buffer_size/4)
        {
-               u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
+               uint32_t status;
 
-               if ((retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer))!=ERROR_OK)
+               if ((retval = target_write_buffer(target, source->address, buffer_size, buffer)) != ERROR_OK) {
+                       LOG_ERROR("Failed to write row buffer (%d words) to RAM", (int)(buffer_size/4));
                        break;
+               }
 
+#if 0
                buf_set_u32(reg_params[0].value, 0, 32, source->address);
                buf_set_u32(reg_params[1].value, 0, 32, address);
-               buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
+               buf_set_u32(reg_params[2].value, 0, 32, buffer_size/4);
 
-               if ((retval = target->type->run_algorithm(target, 0, NULL, 4, reg_params, pic32mx_info->write_algorithm->address, \
+               if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, pic32mx_info->write_algorithm->address, \
                                pic32mx_info->write_algorithm->address + (sizeof(pic32mx_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK)
                {
                        LOG_ERROR("error executing pic32mx flash write algorithm");
@@ -443,45 +382,93 @@ int pic32mx_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 c
                        retval = ERROR_FLASH_OPERATION_FAILED;
                        break;
                }
+#endif
+               status = pic32mx_write_row(bank, address, source->address);
+               if (status & NVMCON_NVMERR) {
+                       LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
+               if (status & NVMCON_LVDERR) {
+                       LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
 
-               buffer += thisrun_count * 2;
-               address += thisrun_count * 2;
-               count -= thisrun_count;
+               buffer  += buffer_size;
+               address += buffer_size;
+               count   -= buffer_size/4;
        }
 
        target_free_working_area(target, source);
-       target_free_working_area(target, pic32mx_info->write_algorithm);
 
-       destroy_reg_param(&reg_params[0]);
-       destroy_reg_param(&reg_params[1]);
-       destroy_reg_param(&reg_params[2]);
-       destroy_reg_param(&reg_params[3]);
+       while (count > 0)
+       {
+               uint32_t value;
+               memcpy(&value, buffer, sizeof(uint32_t));
+
+               uint32_t status = pic32mx_write_word(bank, address, value);
+               if (status & NVMCON_NVMERR) {
+                       LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
+               if (status & NVMCON_LVDERR) {
+                       LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
+
+               buffer  += 4;
+               address += 4;
+               count--;
+       }
 
        return retval;
-#else
-       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-#endif
 }
 
-int pic32mx_write_word(struct flash_bank_s *bank, u32 address, u32 word)
+static int pic32mx_write_word(struct flash_bank_s *bank, uint32_t address, uint32_t word)
 {
-       target_t *target = bank->target;
+       struct target *target = bank->target;
 
-       target_write_u32(target, PIC32MX_NVMADDR, address);
+       if (bank->base >= PIC32MX_KSEG1_PGM_FLASH)
+               target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(address));
+       else
+               target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(address));
        target_write_u32(target, PIC32MX_NVMDATA, word);
 
        return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5);
 }
 
-int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
+/*
+ * Write a 128 word (512 byte) row to flash address from RAM srcaddr.
+ */
+static int pic32mx_write_row(struct flash_bank_s *bank, uint32_t address, uint32_t srcaddr)
 {
-       target_t *target = bank->target;
-       u32 words_remaining = (count / 4);
-       u32 bytes_remaining = (count & 0x00000003);
-       u32 address = bank->base + offset;
-       u32 bytes_written = 0;
-       u32 status;
-       u32 retval;
+       struct target *target = bank->target;
+
+       LOG_DEBUG("addr: 0x%08" PRIx32 " srcaddr: 0x%08" PRIx32 "", address, srcaddr);
+
+       if (address >= PIC32MX_KSEG1_PGM_FLASH)
+               target_write_u32(target, PIC32MX_NVMADDR,    KS1Virt2Phys(address));
+       else
+               target_write_u32(target, PIC32MX_NVMADDR,    KS0Virt2Phys(address));
+       if (srcaddr >= PIC32MX_KSEG1_RAM)
+               target_write_u32(target, PIC32MX_NVMSRCADDR, KS1Virt2Phys(srcaddr));
+       else
+               target_write_u32(target, PIC32MX_NVMSRCADDR, KS0Virt2Phys(srcaddr));
+
+       return pic32mx_nvm_exec(bank, NVMCON_OP_ROW_PROG, 100);
+}
+
+static int pic32mx_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       uint32_t words_remaining = (count / 4);
+       uint32_t bytes_remaining = (count & 0x00000003);
+       uint32_t address = bank->base + offset;
+       uint32_t bytes_written = 0;
+       uint32_t status;
+       int retval;
 
        if (bank->target->state != TARGET_HALTED)
        {
@@ -491,7 +478,7 @@ int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
 
        if (offset & 0x3)
        {
-               LOG_WARNING("offset 0x%breaks required 4-byte alignment", offset);
+               LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
                return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
        }
 
@@ -523,11 +510,13 @@ int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
 
        while (words_remaining > 0)
        {
-               status = pic32mx_write_word(bank, address, *(u32*)(buffer + bytes_written));
+               uint32_t value;
+               memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
 
-               if( status & NVMCON_NVMERR )
+               status = pic32mx_write_word(bank, address, value);
+               if (status & NVMCON_NVMERR)
                        return ERROR_FLASH_OPERATION_FAILED;
-               if( status & NVMCON_LVDERR )
+               if (status & NVMCON_LVDERR)
                        return ERROR_FLASH_OPERATION_FAILED;
 
                bytes_written += 4;
@@ -537,62 +526,57 @@ int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
 
        if (bytes_remaining)
        {
-               u8 last_word[4] = {0xff, 0xff, 0xff, 0xff};
-               int i = 0;
+               uint32_t value = 0xffffffff;
+               memcpy(&value, buffer + bytes_written, bytes_remaining);
 
-               while(bytes_remaining > 0)
-               {
-                       /* Assumes little endian */
-                       last_word[i++] = *(buffer + bytes_written);
-                       bytes_remaining--;
-                       bytes_written++;
-               }
-
-               status = pic32mx_write_word(bank, address, *(u32*)last_word);
-
-               if( status & NVMCON_NVMERR )
+               status = pic32mx_write_word(bank, address, value);
+               if (status & NVMCON_NVMERR)
                        return ERROR_FLASH_OPERATION_FAILED;
-               if( status & NVMCON_LVDERR )
+               if (status & NVMCON_LVDERR)
                        return ERROR_FLASH_OPERATION_FAILED;
        }
 
        return ERROR_OK;
 }
 
-int pic32mx_probe(struct flash_bank_s *bank)
+static int pic32mx_probe(struct flash_bank_s *bank)
 {
-       target_t *target = bank->target;
-       pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv;
-       mips32_common_t *mips32 = target->arch_info;
-       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
+       struct target *target = bank->target;
+       struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
+       struct mips32_common *mips32 = target->arch_info;
+       struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
        int i;
-       u16 num_pages;
-       u32 device_id;
+       uint16_t num_pages = 0;
+       uint32_t device_id;
        int page_size;
 
        pic32mx_info->probed = 0;
 
        device_id = ejtag_info->idcode;
-       LOG_INFO( "device id = 0x%08x (manuf 0x%03x dev 0x%02x, ver 0x%03x)", device_id, (device_id>>1)&0x7ff, (device_id>>12)&0xff, (device_id>>20)&0xfff );
-
-       if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) {
-               LOG_WARNING( "Cannot identify target as a PIC32MX family." );
+       LOG_INFO("device id = 0x%08" PRIx32 " (manuf 0x%03x dev 0x%02x, ver 0x%03x)",
+                         device_id,
+                         (unsigned)((device_id >> 1)&0x7ff),
+                         (unsigned)((device_id >> 12)&0xff),
+                         (unsigned)((device_id >> 20)&0xfff));
+
+       if (((device_id >> 1)&0x7ff) != PIC32MX_MANUF_ID) {
+               LOG_WARNING("Cannot identify target as a PIC32MX family.");
                return ERROR_FLASH_OPERATION_FAILED;
        }
 
        page_size = 4096;
-       if(bank->base == PIC32MX_KSEG1_BOOT_FLASH || bank->base == 1) {
+       if (bank->base == PIC32MX_KSEG1_BOOT_FLASH || bank->base == 1) {
                /* 0xBFC00000: Boot flash size fixed at 12k */
                num_pages = 12;
        } else {
                /* 0xBD000000: Program flash size varies with device */
-               for(i=0; pic32mx_devs[i].name != NULL; i++)
-                       if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) {
+               for (i = 0; pic32mx_devs[i].name != NULL; i++)
+                       if (pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) {
                                num_pages = pic32mx_devs[i].pfm_size;
                                break;
                        }
-               if(pic32mx_devs[i].name == NULL) {
-                       LOG_WARNING( "Cannot identify target as a PIC32MX family." );
+               if (pic32mx_devs[i].name == NULL) {
+                       LOG_WARNING("Cannot identify target as a PIC32MX family.");
                        return ERROR_FLASH_OPERATION_FAILED;
                }
        }
@@ -612,18 +596,18 @@ int pic32mx_probe(struct flash_bank_s *bank)
        }
 #endif
 
-       LOG_INFO( "flash size = %dkbytes", num_pages );
+       LOG_INFO("flash size = %dkbytes", num_pages);
 
        /* calculate numbers of pages */
        num_pages /= (page_size / 1024);
 
-       if(bank->base == 0) bank->base = PIC32MX_KSEG1_PGM_FLASH;
-       if(bank->base == 1) bank->base = PIC32MX_KSEG1_BOOT_FLASH;
+       if (bank->base == 0) bank->base = PIC32MX_KSEG1_PGM_FLASH;
+       if (bank->base == 1) bank->base = PIC32MX_KSEG1_BOOT_FLASH;
        bank->size = (num_pages * page_size);
        bank->num_sectors = num_pages;
        bank->chip_width = 4;
        bank->bus_width  = 4;
-       bank->sectors = malloc(sizeof(flash_sector_t) * num_pages);
+       bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
 
        for (i = 0; i < num_pages; i++)
        {
@@ -638,55 +622,60 @@ int pic32mx_probe(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int pic32mx_auto_probe(struct flash_bank_s *bank)
+static int pic32mx_auto_probe(struct flash_bank_s *bank)
 {
-       pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv;
+       struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
        if (pic32mx_info->probed)
                return ERROR_OK;
        return pic32mx_probe(bank);
 }
 
-int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+#if 0
+COMMAND_HANDLER(pic32mx_handle_part_id_command)
 {
        return ERROR_OK;
 }
+#endif
 
-int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size)
+static int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size)
 {
-       target_t *target = bank->target;
-       mips32_common_t *mips32 = target->arch_info;
-       mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
-       u32 device_id;
-       int printed, i;
+       struct target *target = bank->target;
+       struct mips32_common *mips32 = target->arch_info;
+       struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
+       uint32_t device_id;
+       int printed = 0, i;
 
        device_id = ejtag_info->idcode;
 
-       if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) {
-               snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n", (device_id>>1)&0x7ff, PIC32MX_MANUF_ID);
+       if (((device_id >> 1)&0x7ff) != PIC32MX_MANUF_ID) {
+               snprintf(buf, buf_size,
+                                "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
+                                (unsigned)((device_id >> 1)&0x7ff),
+                                PIC32MX_MANUF_ID);
                return ERROR_FLASH_OPERATION_FAILED;
        }
-       for(i=0; pic32mx_devs[i].name != NULL; i++)
-               if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) {
+       for (i = 0; pic32mx_devs[i].name != NULL; i++)
+               if (pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) {
                        printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
                        break;
                }
-       if(pic32mx_devs[i].name == NULL) {
+       if (pic32mx_devs[i].name == NULL) {
                snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family\n");
                return ERROR_FLASH_OPERATION_FAILED;
        }
        buf += printed;
        buf_size -= printed;
-       printed = snprintf(buf, buf_size, "  Ver: 0x%03x", (device_id>>20)&0xfff);
+       printed = snprintf(buf, buf_size, "  Ver: 0x%03x",
+                                          (unsigned)((device_id >> 20)&0xfff));
 
        return ERROR_OK;
 }
 
 #if 0
-int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(pic32mx_handle_lock_command)
 {
-       flash_bank_t *bank;
-       target_t *target = NULL;
-       pic32mx_flash_bank_t *pic32mx_info = NULL;
+       struct target *target = NULL;
+       struct pic32mx_flash_bank *pic32mx_info = NULL;
 
        if (argc < 1)
        {
@@ -694,12 +683,10 @@ int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, ch
                return ERROR_OK;
        }
 
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
 
        pic32mx_info = bank->driver_priv;
 
@@ -731,11 +718,10 @@ int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, ch
        return ERROR_OK;
 }
 
-int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(pic32mx_handle_unlock_command)
 {
-       flash_bank_t *bank;
-       target_t *target = NULL;
-       pic32mx_flash_bank_t *pic32mx_info = NULL;
+       struct target *target = NULL;
+       struct pic32mx_flash_bank *pic32mx_info = NULL;
 
        if (argc < 1)
        {
@@ -743,12 +729,10 @@ int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd,
                return ERROR_OK;
        }
 
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
 
        pic32mx_info = bank->driver_priv;
 
@@ -778,10 +762,13 @@ int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd,
 }
 #endif
 
-int pic32mx_chip_erase(struct flash_bank_s *bank)
+#if 0
+static int pic32mx_chip_erase(struct flash_bank_s *bank)
 {
-       target_t *target = bank->target;
-       u32 status;
+       struct target *target = bank->target;
+#if 0
+       uint32_t status;
+#endif
 
        if (target->state != TARGET_HALTED)
        {
@@ -798,19 +785,19 @@ int pic32mx_chip_erase(struct flash_bank_s *bank)
 
        /* chip erase flash memory */
        target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER);
-       target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER|FLASH_STRT);
+       target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER | FLASH_STRT);
 
        status = pic32mx_wait_status_busy(bank, 10);
 
        target_write_u32(target, PIC32MX_FLASH_CR, FLASH_LOCK);
 
-       if( status & FLASH_WRPRTERR )
+       if (status & FLASH_WRPRTERR)
        {
                LOG_ERROR("pic32mx device protected");
                return ERROR_OK;
        }
 
-       if( status & FLASH_PGERR )
+       if (status & FLASH_PGERR)
        {
                LOG_ERROR("pic32mx device programming failed");
                return ERROR_OK;
@@ -819,25 +806,23 @@ int pic32mx_chip_erase(struct flash_bank_s *bank)
 
        return ERROR_OK;
 }
+#endif
 
-int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(pic32mx_handle_chip_erase_command)
 {
-       flash_bank_t *bank;
+#if 0
        int i;
 
-#if 0
        if (argc != 0)
        {
                command_print(cmd_ctx, "pic32mx chip_erase");
                return ERROR_OK;
        }
 
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-               return ERROR_OK;
-       }
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
+       if (ERROR_OK != retval)
+               return retval;
 
        if (pic32mx_chip_erase(bank) == ERROR_OK)
        {
@@ -858,11 +843,9 @@ int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *c
        return ERROR_OK;
 }
 
-int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
 {
-       flash_bank_t *bank;
-       u32 address, value;
-       int i;
+       uint32_t address, value;
        int status, res;
 
        if (argc != 3)
@@ -871,16 +854,15 @@ int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd
                return ERROR_OK;
        }
 
-       address = strtoul(args[0], NULL, 0);
-       value   = strtoul(args[1], NULL, 0);
+       COMMAND_PARSE_NUMBER(u32, args[0], address);
+       COMMAND_PARSE_NUMBER(u32, args[1], value);
 
-       bank = get_flash_bank_by_num(strtoul(args[2], NULL, 0));
-       if (!bank)
-       {
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[2]);
-               return ERROR_OK;
-       }
-       if (address < bank->base || address >= (bank->base+bank->size))
+       flash_bank_t *bank;
+       int retval = flash_command_get_bank_by_num(cmd_ctx, args[2], &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       if (address < bank->base || address >= (bank->base + bank->size))
        {
                command_print(cmd_ctx, "flash address '%s' is out of bounds", args[0]);
                return ERROR_OK;
@@ -888,15 +870,50 @@ int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd
 
        res = ERROR_OK;
        status = pic32mx_write_word(bank, address, value);
-       if( status & NVMCON_NVMERR )
+       if (status & NVMCON_NVMERR)
                res = ERROR_FLASH_OPERATION_FAILED;
-       if( status & NVMCON_LVDERR )
+       if (status & NVMCON_LVDERR)
                res = ERROR_FLASH_OPERATION_FAILED;
 
        if (res == ERROR_OK)
                command_print(cmd_ctx, "pic32mx pgm word complete");
        else
-               command_print(cmd_ctx, "pic32mx pgm word failed (status=0x%x)", status);
+               command_print(cmd_ctx, "pic32mx pgm word failed (status = 0x%x)", status);
+
+       return ERROR_OK;
+}
 
+static int pic32mx_register_commands(struct command_context_s *cmd_ctx)
+{
+       command_t *pic32mx_cmd = register_command(cmd_ctx, NULL, "pic32mx",
+                       NULL, COMMAND_ANY, "pic32mx flash specific commands");
+#if 0
+       register_command(cmd_ctx, pic32mx_cmd, "lock",
+                       pic32mx_handle_lock_command, COMMAND_EXEC,
+                       "lock device");
+       register_command(cmd_ctx, pic32mx_cmd, "unlock",
+                       pic32mx_handle_unlock_command, COMMAND_EXEC,
+                       "unlock protected device");
+#endif
+       register_command(cmd_ctx, pic32mx_cmd, "chip_erase",
+                       pic32mx_handle_chip_erase_command, COMMAND_EXEC,
+                       "erase device");
+       register_command(cmd_ctx, pic32mx_cmd, "pgm_word",
+                       pic32mx_handle_pgm_word_command, COMMAND_EXEC,
+                       "program a word");
        return ERROR_OK;
 }
+
+struct flash_driver pic32mx_flash = {
+               .name = "pic32mx",
+               .register_commands = &pic32mx_register_commands,
+               .flash_bank_command = &pic32mx_flash_bank_command,
+               .erase = &pic32mx_erase,
+               .protect = &pic32mx_protect,
+               .write = &pic32mx_write,
+               .probe = &pic32mx_probe,
+               .auto_probe = &pic32mx_auto_probe,
+               .erase_check = &default_flash_mem_blank_check,
+               .protect_check = &pic32mx_protect_check,
+               .info = &pic32mx_info,
+       };