This is an automated email from Gerrit.

Jiri Kastner ([email protected]) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/6147

-- gerrit

commit 17da9626aac0b39cdc4aac74b652d014a5e84dfa
Author: James Murray <[email protected]>
Date:   Tue Apr 6 20:02:29 2021 +0200

    flash: nor: add mpc56xx driver
    
    add nor flash driver for mpc56xx
    
    Change-Id: I49c78c95a21e3104cb67250e63b7053688884328
    Signed-off-by: Jiri Kastner <[email protected]>

diff --git a/src/flash/nor/mpc56xx.c b/src/flash/nor/mpc56xx.c
new file mode 100644
index 0000000..487681c
--- /dev/null
+++ b/src/flash/nor/mpc56xx.c
@@ -0,0 +1,859 @@
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   [email protected]                                                   *
+ *                                                                         *
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   [email protected]                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by John McCarthy                                   *
+ *   [email protected]                                                        *
+ *                                                                         *
+ *   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, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+/* MPC version (C) 2015 James Murray */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/jtag.h>
+#include "imp.h"
+#include <target/algorithm.h>
+#include <target/mpc56xx_jtag.h>
+#include <target/mpc56xx.h>
+
+#define MPC56XX_MANUF_ID       0x029 /* will be wrong */
+
+struct mpc56xx_flash_bank { /* all unknown at the moment */
+       uint32_t *block_bits_lmlr;
+       uint32_t *block_bits_hlr;
+       uint32_t disable_bit;
+       uint32_t busy_bits;
+       uint32_t *register_base;
+       int probed;
+};
+
+struct mpc56xx_mem_layout {
+       uint32_t block_start;
+       uint32_t block_size;
+       uint32_t lmlr_bit;
+       uint32_t hlr_bit;
+};
+
+static const struct mpc56xx_mem_layout mem_layout_array0[] = {
+       {0x00000000, 0x04000, 0x01, 0x00},
+       {0x00004000, 0x04000, 0x02, 0x00},
+       {0x00008000, 0x08000, 0x04, 0x00},
+       {0x00010000, 0x08000, 0x08, 0x00},
+       {0x00018000, 0x04000, 0x10, 0x00},
+       {0x0001c000, 0x04000, 0x20, 0x00},
+       {0x00020000, 0x10000, 0x40, 0x00},
+       {0x00030000, 0x10000, 0x80, 0x00},
+       {0x00040000, 0x20000, 0x10000, 0x00}, /* NA in 768K deriv */
+       {0x00060000, 0x20000, 0x20000, 0x00}  /* NA in 768K deriv */
+};
+static const struct mpc56xx_mem_layout mem_layout_array1[] = {
+       {0x00080000, 0x20000, 0x00, 0x01},
+       {0x000a0000, 0x20000, 0x00, 0x02},
+       {0x000c0000, 0x20000, 0x00, 0x04},
+       {0x000e0000, 0x20000, 0x00, 0x08}
+};
+static const struct mpc56xx_mem_layout mem_layout_array2[] = {
+               {0x00100000, 0x20000, 0x00, 0x01}, /* NA in 768K or 1M deriv */
+               {0x00120000, 0x20000, 0x00, 0x02}, /* NA in 768K or 1M deriv */
+               {0x00140000, 0x20000, 0x00, 0x04}, /* NA in 768K or 1M deriv */
+               {0x00160000, 0x20000, 0x00, 0x08}  /* NA in 768K or 1M deriv */
+};
+
+static const uint32_t mpc56xx_flash_regs[3] = {
+               0xc3f88000,
+               0xc3fb0000,
+               0xc3fb4000
+};
+
+#define MPC56XX_BIUCR  0xc3f8801C
+#define MPC56XX_BIUAPR 0xc3f88020
+#define MPC56XX_BIUCR2 0xc3f88024
+#define MPC56XX_PFCR3  0xc3f88028
+
+#define MPC56XX_MCR_OFFSET             0x00
+#define MPC56XX_LMLR_OFFSET            0x04
+#define MPC56XX_HLR_OFFSET             0x08
+#define MPC56XX_SLMLR_OFFSET   0x0c
+#define MPC56XX_LMSR_OFFSET            0x10
+#define MPC56XX_HSR_OFFSET             0x14
+#define MPC56XX_AR_OFFSET              0x18
+
+#define MPC56XX_LMLR_LME_PASS  0xA1A11111
+#define MPC56XX_HLR_HBE_PASS   0xB2B22222
+#define MPC56XX_SLMLR_SLE_PASS 0xC3C33333
+/*
+ * DEVID values
+ */
+
+static const struct mpc56xx_devs_s {
+       uint32_t devid;
+       const char *name;
+} mpc56xx_devs[] = {
+       {0x07c2201d, "MPC5634M JTAG"}, /* Developed against this chip only. */
+       {0x00000000, NULL}
+};
+
+#if 0
+static int mpc56x_get_flash_adr(struct flash_bank *bank, uint32_t reg)
+{
+       struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;
+       return mpc56xx_info->register_base | reg;
+}
+#endif
+
+static int mpc56xx_build_block_list(struct flash_bank *bank)
+{
+       struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;
+
+       int i;
+       int num_blocks;
+       int b[3];
+       b[0] = 0;
+       b[1] = 0;
+       b[2] = 0;
+
+       switch (bank->size) {
+               case 0x180000: /* 1.5M */
+                       b[0] = 10;
+                       b[1] = 4;
+                       b[2] = 4;
+                       break;
+               case 0x100000: /* 1 M */
+                       b[0] = 10;
+                       b[1] = 4;
+                       b[2] = 0;
+                       break;
+               case 0x0c0000: /* 768M */
+                       b[0] = 8;
+                       b[1] = 4;
+                       b[2] = 0;
+                       break;
+               default:
+                       LOG_ERROR("BUG: unknown bank->size encountered. Only 
0x180000, 0x100000, 0xc0000 supported.");
+                       exit(-1);
+       }
+
+       num_blocks = b[0] + b[1] + b[2];
+
+       printf("b0=%d, b1=%d, b2=%d\n", b[0], b[1], b[2]);
+
+       bank->num_sectors = num_blocks;
+       bank->sectors = malloc(sizeof(struct flash_sector) * num_blocks);
+       mpc56xx_info->block_bits_lmlr = malloc(sizeof(uint32_t) * num_blocks);
+       mpc56xx_info->block_bits_hlr = malloc(sizeof(uint32_t) * num_blocks);
+       mpc56xx_info->register_base = malloc(sizeof(uint32_t) * num_blocks);
+
+       num_blocks = 0;
+
+       for (i = 0; i < b[0]; i++) {
+               bank->sectors[num_blocks].offset = 
mem_layout_array0[i].block_start;
+               bank->sectors[num_blocks].size = 
mem_layout_array0[i].block_size;
+               bank->sectors[num_blocks].is_erased = -1;
+               bank->sectors[num_blocks].is_protected = 1; /* protection bits 
likely set by hardware */
+               mpc56xx_info->block_bits_lmlr[num_blocks] = 
mem_layout_array0[i].lmlr_bit;
+               mpc56xx_info->block_bits_hlr[num_blocks] = 
mem_layout_array0[i].hlr_bit;
+               mpc56xx_info->register_base[num_blocks++] = 
mpc56xx_flash_regs[0]; /* base register address per block */
+       }
+
+       for (i = 0; i < b[1]; i++) {
+               bank->sectors[num_blocks].offset = 
mem_layout_array1[i].block_start;
+               bank->sectors[num_blocks].size = 
mem_layout_array1[i].block_size;
+               bank->sectors[num_blocks].is_erased = -1;
+               bank->sectors[num_blocks].is_protected = 1; /* protection bits 
likely set by hardware */
+               mpc56xx_info->block_bits_lmlr[num_blocks] = 
mem_layout_array1[i].lmlr_bit;
+               mpc56xx_info->block_bits_hlr[num_blocks] = 
mem_layout_array1[i].hlr_bit;
+               mpc56xx_info->register_base[num_blocks++] = 
mpc56xx_flash_regs[1]; /* base register address per block */
+       }
+
+       for (i = 0; i < b[2]; i++) {
+               bank->sectors[num_blocks].offset = 
mem_layout_array2[i].block_start;
+               bank->sectors[num_blocks].size = 
mem_layout_array2[i].block_size;
+               bank->sectors[num_blocks].is_erased = -1;
+               bank->sectors[num_blocks].is_protected = 1; /* protection bits 
likely set by hardware */
+               mpc56xx_info->block_bits_lmlr[num_blocks] = 
mem_layout_array2[i].lmlr_bit;
+               mpc56xx_info->block_bits_hlr[num_blocks] = 
mem_layout_array2[i].hlr_bit;
+               mpc56xx_info->register_base[num_blocks++] = 
mpc56xx_flash_regs[2]; /* base register address per block */
+       }
+
+       return ERROR_OK;
+}
+
+/* flash bank mpc56xx 0 0 0 0 <target#>
+ */
+FLASH_BANK_COMMAND_HANDLER(mpc56xx_flash_bank_command)
+{
+       struct mpc56xx_flash_bank *mpc56xx_info;
+
+       if (CMD_ARGC < 6)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       mpc56xx_info = malloc(sizeof(struct mpc56xx_flash_bank));
+       bank->driver_priv = mpc56xx_info;
+
+       mpc56xx_info->probed = 1; /* ensure probe does not occur */
+
+       /*printf("ARGV[6] = %s\n", CMD_ARGV[6]);*/
+       /* varies per bank - FIXME */
+       /*mpc56xx_info->register_base = 0xc3f80000;*/
+       /* set up other bits perhaps */
+       mpc56xx_build_block_list(bank);
+
+       return ERROR_OK;
+}
+
+static int mpc56xx_protect_check(struct flash_bank *bank)
+{
+       struct target *target = bank->target;
+       /*struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;*/
+
+       /*uint32_t config0_address;
+       uint32_t devcfg0;*/
+       int s;
+       int num_pages;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+#if 0
+       config0_address = MPC56XX_DEVCFG0;
+
+       target_read_u32(target, config0_address, &devcfg0);
+
+       if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
+               num_pages = 0xffff;                     /* All pages protected 
*/
+       else if (Virt2Phys(bank->base) == MPC56XX_PHYS_BOOT_FLASH) {
+               if (devcfg0 & (1 << 24))
+                       num_pages = 0;                  /* All pages 
unprotected */
+               else
+                       num_pages = 0xffff;             /* All pages protected 
*/
+       } else {
+               /* pgm flash */
+               num_pages = (~devcfg0 >> 12) & 0xff;
+       }
+#endif
+       num_pages = 0xffff; /* FIXME */
+
+       for (s = 0; s < bank->num_sectors && s < num_pages; s++)
+               bank->sectors[s].is_protected = 1;
+       for (; s < bank->num_sectors; s++)
+               bank->sectors[s].is_protected = 0;
+
+       return ERROR_OK;
+}
+
+static int mpc56xx_unlock_block(struct flash_bank *bank, uint32_t block_num)
+{
+       struct target *target = bank->target;
+       struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;
+       int retval;
+       uint32_t val;
+       uint32_t reg_base;
+
+       reg_base = mpc56xx_info->register_base[block_num];
+
+       /* See if this flash block uses HLR and unlock */
+       if (mpc56xx_info->block_bits_hlr[block_num]) {
+               retval = target_read_memory(target, reg_base + 
MPC56XX_HLR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Original HLR= 0x%08x\n", val);
+               if ((val & 0x80000000) == 0) {
+                       /* unlock password */
+                       retval = target_write_u32(target, reg_base + 
MPC56XX_HLR_OFFSET, MPC56XX_HLR_HBE_PASS);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       retval = target_read_memory(target, reg_base + 
MPC56XX_HLR_OFFSET, 4, 1,
+                                       (uint8_t *)&val);
+                       val = be_to_h_u32((uint8_t *)&val); /* swap ends again 
*/
+                       printf("Now HLR= 0x%08x\n", val);
+               }
+               val &= ~mpc56xx_info->block_bits_hlr[block_num]; /* Set 
appropriate bits to zero to unlock */
+               retval = target_write_u32(target, reg_base + 
MPC56XX_HLR_OFFSET, val);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = target_read_memory(target, reg_base + 
MPC56XX_HLR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Now HLR= 0x%08x\n", val);
+       }
+
+       /* See if this flash block uses LMLR and unlock */
+       if (mpc56xx_info->block_bits_lmlr[block_num]) {
+               retval = target_read_memory(target, reg_base + 
MPC56XX_LMLR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Original LMLR= 0x%08x\n", val);
+               if ((val & 0x80000000) == 0) {
+                       /* unlock password */
+                       retval = target_write_u32(target, reg_base + 
MPC56XX_LMLR_OFFSET, MPC56XX_LMLR_LME_PASS);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       retval = target_read_memory(target, reg_base + 
MPC56XX_LMLR_OFFSET, 4, 1,
+                                       (uint8_t *)&val);
+                       val = be_to_h_u32((uint8_t *)&val); /* swap ends again 
*/
+                       printf("Now LMLR= 0x%08x\n", val);
+               }
+               val &= ~mpc56xx_info->block_bits_lmlr[block_num]; /* Set 
appropriate bits to zero to unlock */
+               retval = target_write_u32(target, reg_base + 
MPC56XX_LMLR_OFFSET, val);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = target_read_memory(target, reg_base + 
MPC56XX_LMLR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Now LMLR= 0x%08x\n", val);
+
+               /* Now do same again for secondary reg */
+
+               retval = target_read_memory(target, reg_base + 
MPC56XX_SLMLR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Original SLMLR= 0x%08x\n", val);
+               if ((val & 0x80000000) == 0) {
+                       /* unlock password */
+                       retval = target_write_u32(target, reg_base + 
MPC56XX_SLMLR_OFFSET, MPC56XX_SLMLR_SLE_PASS);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       retval = target_read_memory(target, reg_base + 
MPC56XX_SLMLR_OFFSET, 4, 1,
+                                       (uint8_t *)&val);
+                       val = be_to_h_u32((uint8_t *)&val); /* swap ends again 
*/
+                       printf("Now SLMLR= 0x%08x\n", val);
+               }
+               val &= ~mpc56xx_info->block_bits_lmlr[block_num]; /* Set 
appropriate bits to zero to unlock */
+               retval = target_write_u32(target, reg_base + 
MPC56XX_SLMLR_OFFSET, val);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = target_read_memory(target, reg_base + 
MPC56XX_SLMLR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Now SLMLR= 0x%08x\n", val);
+       }
+
+       return ERROR_OK;
+}
+
+static int mpc56xx_flash_set_sr(struct flash_bank *bank, uint32_t block_num)
+{
+       struct target *target = bank->target;
+       struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;
+       int retval;
+       uint32_t val;
+       uint32_t reg_base;
+
+       reg_base = mpc56xx_info->register_base[block_num];
+
+       /* See if this flash block uses HLR / HSR */
+       if (mpc56xx_info->block_bits_hlr[block_num]) {
+               retval = target_read_memory(target, reg_base + 
MPC56XX_HSR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Original HSR= 0x%08x\n", val);
+               val |= mpc56xx_info->block_bits_hlr[block_num]; /* Set 
appropriate bits to one */
+               retval = target_write_u32(target, reg_base + 
MPC56XX_HSR_OFFSET, val);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = target_read_memory(target, reg_base + 
MPC56XX_HSR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Now HLR= 0x%08x\n", val);
+       }
+
+       /* See if this flash block uses LMLR / LMSR */
+       if (mpc56xx_info->block_bits_lmlr[block_num]) {
+               retval = target_read_memory(target, reg_base + 
MPC56XX_LMSR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Original LMSR= 0x%08x\n", val);
+               val |= mpc56xx_info->block_bits_lmlr[block_num]; /* Set 
appropriate bits to one */
+               retval = target_write_u32(target, reg_base + 
MPC56XX_LMSR_OFFSET, val);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = target_read_memory(target, reg_base + 
MPC56XX_LMSR_OFFSET, 4, 1,
+                               (uint8_t *)&val);
+               val = be_to_h_u32((uint8_t *)&val); /* swap ends again */
+               printf("Now LMSR= 0x%08x\n", val);
+       }
+
+       return ERROR_OK;
+}
+
+static int mpc56xx_erase(struct flash_bank *bank, int first, int last)
+{
+       struct target *target = bank->target;
+       struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;
+       int retval, retry;
+       uint32_t val;
+       uint32_t reg_base;
+       int block_num;
+
+       printf("Got a call to erase!\n");
+
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       for (block_num = first; block_num <= last; block_num++) {
+
+               reg_base = mpc56xx_info->register_base[block_num];
+
+               retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000000); /* Clear MCR */
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = mpc56xx_unlock_block(bank, block_num);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000004); /* select ERS operation */
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = mpc56xx_flash_set_sr(bank, block_num); /* Set LMSR or 
HSR */
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* write something to the first address in that flash bank */
+               retval = target_write_u32(target, 
bank->sectors[block_num].offset, 0xffffffff);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000005); /* select ERS+EHV operation */
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* Wait for Done=1 */
+               retry = 100; /* arbitrary limit */
+               val = 0;
+               while (retry && ((val & 0x00000400) == 0)) {
+                       retval = target_read_memory(target, reg_base + 
MPC56XX_MCR_OFFSET, 4, 1,
+                                       (uint8_t *)&val);
+                       val = be_to_h_u32((uint8_t *)&val); /* swap ends again 
*/
+                       if (retval != ERROR_OK)
+                               return retval;
+                       retry--;
+               }
+
+               retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000004); /* clear EHV */
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000000); /* clear ERS */
+               if (retval != ERROR_OK)
+                       return retval;
+
+               if ((val & 0x00000200) == 0) {
+                       LOG_ERROR("Received error on flash erase");
+                       return ERROR_FAIL;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int mpc56xx_protect(struct flash_bank *bank, int set, int first, int 
last)
+{
+       struct target *target = bank->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       return ERROR_OK;
+}
+
+/* Determines sector details give a flash address */
+static int mpc56xx_get_sect(struct flash_bank *bank, uint32_t address, 
uint32_t *start, uint32_t *end)
+{
+       int i, block_num;
+       uint32_t sec_start, sec_end;
+
+       sec_start = 0;
+       sec_end = 0;
+
+       /* Validate address */
+       block_num = -1;
+       for (i = 0; i < bank->num_sectors; i++) {
+               sec_start = bank->sectors[i].offset;
+               sec_end = sec_start + bank->sectors[i].size;
+
+               /* check if destination falls within the current sector */
+               if ((address >= sec_start) && (address < sec_end)) {
+                       block_num = i;
+                       break;
+               }
+       }
+
+       *start = sec_start;
+       *end = sec_end - 1;
+
+       return block_num;
+}
+
+static int mpc56xx_write(struct flash_bank *bank, const uint8_t *buffer, 
uint32_t offset, uint32_t count)
+{
+       struct target *target = bank->target;
+       struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;
+       uint32_t words_remaining = (count / 4);
+       uint32_t bytes_written = 0;
+       uint32_t bytes_remaining = (count & 0x00000007);
+       uint32_t address = bank->base + offset;
+       int retval, retry;
+       uint32_t val;
+       uint32_t reg_base, cur_sec_start, cur_sec_end;
+       int block_num, tail_end = 0;
+
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 
0x%8.8" PRIx32
+                       " count: 0x%8.8" PRIx32 "", bank->base, offset, count);
+
+       if (offset & 0x7) {
+               LOG_WARNING("offset 0x%" PRIx32 "breaks required 8-byte 
alignment", offset);
+               return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+               /* Could workaround this, but not presently. */
+       }
+
+       printf("Entered write_block code!\n");
+
+       block_num = -1;
+       cur_sec_start = 1; /* intentionally invalid */
+       cur_sec_end = 0;
+       reg_base = 0;
+
+       while (words_remaining) {
+               uint32_t value, value2;
+
+               if ((address < cur_sec_start) || (address > cur_sec_end)) {
+                       printf("Address = 0x%08x\n", address);
+                       if (block_num >= 0) {
+                               /* Ensure MCR for existing sector is cleared */
+                               /* reg_base will have been set */
+                               retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000000);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       }
+                       block_num = mpc56xx_get_sect(bank, address, 
&cur_sec_start, &cur_sec_end);
+
+                       if (block_num < 0)
+                               return ERROR_FLASH_DST_OUT_OF_BANK;
+
+                       reg_base = mpc56xx_info->register_base[block_num];
+
+                       retval = mpc56xx_unlock_block(bank, block_num);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       /* Ensure MCR for new sector is cleared */
+                       retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000000);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000010); /* Select PGM */
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+
+               if (tail_end) {
+                       uint8_t byte_buf[8];
+                       LOG_INFO("Tail end data flash, not sure this is 
correct. Please check.");
+                       printf("Handling the stragglers %d\n", bytes_remaining);
+                       memset(byte_buf, 0, 8);
+                       memcpy(byte_buf, buffer + bytes_written, 
sizeof(uint32_t));
+                       value = be_to_h_u32((uint8_t *)&byte_buf[0]); /* read 
from buffer BE */
+                       value2 = be_to_h_u32((uint8_t *)&byte_buf[4]);
+                       words_remaining = 2;
+                       bytes_remaining = 0;
+               } else {
+                       memcpy(&value, buffer + bytes_written, 
sizeof(uint32_t));
+                       memcpy(&value2, buffer + bytes_written + 4, 
sizeof(uint32_t));
+                       value = be_to_h_u32((uint8_t *)&value); /* swap ends 
again */
+                       value2 = be_to_h_u32((uint8_t *)&value2); /* swap ends 
again */
+               }
+
+               /* Skip writes if the data is the same as erased flash value */
+               if ((value != 0xffffffff) && (value2 != 0xffffffff)) {
+                       retval = target_write_u32(target, address, value); /* 
Write first 32bits */
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       retval = target_write_u32(target, address + 4, value2); 
/* Write second 32bits */
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000011); /* Set EHV */
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       /* Wait for Done=1 */
+                       retry = 100; /* arbitrary limit */
+                       val = 0;
+                       while (retry && ((val & 0x00000400) == 0)) {
+                               retval = target_read_memory(target, reg_base + 
MPC56XX_MCR_OFFSET, 4, 1,
+                                               (uint8_t *)&val);
+                               val = be_to_h_u32((uint8_t *)&val); /* swap 
ends again */
+                               if (retval != ERROR_OK)
+                                       return retval;
+                               retry--;
+                       }
+
+                       /* Clear EHV for each 64bit programmed */
+                       retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000010);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       if ((val & 0x00000200) == 0) {
+                               LOG_ERROR("Received error on flash erase");
+                               return ERROR_FAIL;
+                       }
+               }
+               if ((words_remaining <= 2) && (bytes_remaining))
+                       tail_end = 1;
+               bytes_written += 8;
+               words_remaining -= 2;
+               address += 8;
+       }
+
+       if (block_num >= 0) {
+               /* Ensure MCR for existing sector is cleared */
+               /* reg_base will have been set */
+               retval = target_write_u32(target, reg_base + 
MPC56XX_MCR_OFFSET, 0x00000000);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
+
+static int mpc56xx_probe(struct flash_bank *bank)
+{
+       struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;
+
+       if (mpc56xx_info->probed == 0) {
+               printf("Probe bypassed.\n");
+               LOG_DEBUG("Probe bypassed");
+       }
+
+       return ERROR_OK;
+}
+
+static int mpc56xx_auto_probe(struct flash_bank *bank)
+{
+       struct mpc56xx_flash_bank *mpc56xx_info = bank->driver_priv;
+       if (mpc56xx_info->probed)
+               return ERROR_OK;
+       return mpc56xx_probe(bank);
+}
+
+static int mpc56xx_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+       /*struct target *target = bank->target;
+       struct mpc5634_common *mpc5634 = target->arch_info;
+       struct mpc5634_jtag *jtag_info = &mpc5634->jtag;*/
+       uint32_t device_id;
+       int printed = 0, i;
+
+       /*device_id = jtag_info->idcode;*/
+       device_id = 0x87654321;
+
+       if (((device_id >> 1) & 0x7ff) != MPC56XX_MANUF_ID) {
+               snprintf(buf, buf_size,
+                                "Cannot identify target as a MPC56XX family 
(manufacturer 0x%03d != 0x%03d)\n",
+                                (unsigned)((device_id >> 1) & 0x7ff),
+                                MPC56XX_MANUF_ID);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       for (i = 0; mpc56xx_devs[i].name != NULL; i++) {
+               if (mpc56xx_devs[i].devid == (device_id & 0x0fffffff)) {
+                       printed = snprintf(buf, buf_size, "MPC56XX%s", 
mpc56xx_devs[i].name);
+                       break;
+               }
+       }
+
+       if (mpc56xx_devs[i].name == NULL)
+               printed = snprintf(buf, buf_size, "Unknown");
+
+       buf += printed;
+       buf_size -= printed;
+       snprintf(buf, buf_size, " Ver: 0x%02x",
+                       (unsigned)((device_id >> 28) & 0xf));
+
+       return ERROR_OK;
+}
+
+#if 0
+COMMAND_HANDLER(mpc56xx_handle_pgm_word_command)
+{
+       uint32_t address, value;
+       int status, res;
+
+       if (CMD_ARGC != 3)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
+
+       struct flash_bank *bank;
+       int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 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", 
CMD_ARGV[0]);
+               return ERROR_OK;
+       }
+
+       res = ERROR_OK;
+       status = mpc56xx_write_word(bank, address, value);
+       if (status & NVMCON_NVMERR)
+               res = ERROR_FLASH_OPERATION_FAILED;
+       if (status & NVMCON_LVDERR)
+               res = ERROR_FLASH_OPERATION_FAILED;
+
+       if (res == ERROR_OK)
+               command_print(CMD_CTX, "mpc56xx pgm word complete");
+       else
+               command_print(CMD_CTX, "mpc56xx pgm word failed (status = 
0x%x)", status);
+
+       return ERROR_OK;
+}
+#endif
+
+COMMAND_HANDLER(mpc56xx_handle_unlock_command)
+{
+       /*uint32_t mchip_cmd;
+       struct target *target = NULL;
+       struct mips_m4k_common *mips_m4k;
+       struct mips_ejtag *ejtag_info;
+       int timeout = 10;*/
+
+       if (CMD_ARGC < 1) {
+               command_print(CMD_CTX, "mpc56xx unlock <bank>");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       struct flash_bank *bank;
+       int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+       if (ERROR_OK != retval)
+               return retval;
+printf("Not handled!\n");
+return ERROR_FAIL;
+#if 0
+       not handled yet
+       target = bank->target;
+       mpc5634 = target_to_mpc5634(target);
+       jtag_info = &mpc5634->mpc5634.jtag_info;
+
+       /* we have to use the MTAP to perform a full erase */
+       mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP);
+       mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
+
+       /* first check status of device */
+       mchip_cmd = MCHP_STATUS;
+       mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
+       if (mchip_cmd & (1 << 7)) {
+               /* device is not locked */
+               command_print(CMD_CTX, "mpc56xx is already unlocked, erasing 
anyway");
+       }
+
+       /* unlock/erase device */
+       mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
+       jtag_add_sleep(200);
+
+       mips_ejtag_drscan_8_out(ejtag_info, MCHP_ERASE);
+
+       do {
+               mchip_cmd = MCHP_STATUS;
+               mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
+               if (timeout-- == 0) {
+                       LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", 
mchip_cmd);
+                       break;
+               }
+               alive_sleep(1);
+       } while ((mchip_cmd & (1 << 2)) || (!(mchip_cmd & (1 << 3))));
+
+       mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
+
+       /* select ejtag tap */
+       mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
+
+       command_print(CMD_CTX, "mpc56xx unlocked.\n"
+                       "INFO: a reset or power cycle is required "
+                       "for the new settings to take effect.");
+
+       return ERROR_OK;
+#endif
+}
+
+static const struct command_registration mpc56xx_exec_command_handlers[] = {
+/*     {
+               .name = "pgm_word",
+               .usage = "<addr> <value> <bank>",
+               .handler = mpc56xx_handle_pgm_word_command,
+               .mode = COMMAND_EXEC,
+               .help = "program a word",
+       },*/
+       {
+               .name = "unlock",
+               .handler = mpc56xx_handle_unlock_command,
+               .mode = COMMAND_EXEC,
+               .usage = "[bank_id]",
+               .help = "Unlock/Erase entire device.",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration mpc56xx_command_handlers[] = {
+       {
+               .name = "mpc56xx",
+               .mode = COMMAND_ANY,
+               .help = "mpc56xx flash command group",
+               .usage = "",
+               .chain = mpc56xx_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct flash_driver mpc56xx_flash = {
+       .name = "mpc56xx",
+       .commands = mpc56xx_command_handlers,
+       .flash_bank_command = mpc56xx_flash_bank_command,
+       .erase = mpc56xx_erase,
+       .protect = mpc56xx_protect,
+       .write = mpc56xx_write,
+       .read = default_flash_read,
+       .probe = mpc56xx_probe,
+       .auto_probe = mpc56xx_auto_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = mpc56xx_protect_check,
+       .info = mpc56xx_info,
+};

-- 

Reply via email to