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/6143

-- gerrit

commit fb64faee89a77a76cfbdbd37051cbe012801c92b
Author: Jiri Kastner <[email protected]>
Date:   Tue Apr 6 20:55:56 2021 +0200

    target: add mpc5xxx common files
    
    Change-Id: Iee16f2a9d970a39c23f18a0538fd850dfdbc8c07
    Signed-off-by: Jiri Kastner <[email protected]>

diff --git a/src/target/mpc5xxx.c b/src/target/mpc5xxx.c
new file mode 100644
index 0000000..7681591
--- /dev/null
+++ b/src/target/mpc5xxx.c
@@ -0,0 +1,660 @@
+/***************************************************************************
+ *   Copyright (C) 2017 by James Murray <[email protected]                   *
+ *   Based on code:                                                        *
+ *       Copyright (C) 2010 by Oleksandr Tymoshenko <[email protected]>   *
+ *   Based on mips_m4k code:                                               *
+ *       Copyright (C) 2008 by Spencer Oliver <[email protected]>       *
+ *       Copyright (C) 2008 by David T.L. Wong                             *
+ *                                                                         *
+ *   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/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "jtag/jtag.h"
+#include "register.h"
+#include "algorithm.h"
+#include "target.h"
+#include "breakpoints.h"
+#include "target_type.h"
+#include "mpc5xxx_jtag.h"
+#include "mpc5xxx.h"
+#include "jtag/interface.h"
+
+const char * const mpc5xxx_core_reg_list[] = {
+       "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
+       "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
+       "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+       "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+       "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
+       "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
+       "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
+       "r56", "r57", "r58", "r59", "r60", "r61", "r62", "r63",
+       "pc",  "msr", "cnd", "lr",  "cnt", "xer", "mq",  "r71",
+};
+
+static const struct mpc5xxx_core_reg
+       mpc56xx_core_reg_list_arch_info[MPC5XXX_NUMCOREREGS] = {
+       {0, NULL, NULL},
+       {1, NULL, NULL},
+       {2, NULL, NULL},
+       {3, NULL, NULL},
+       {4, NULL, NULL},
+       {5, NULL, NULL},
+       {6, NULL, NULL},
+       {7, NULL, NULL},
+       {8, NULL, NULL},
+       {9, NULL, NULL},
+       {10, NULL, NULL},
+       {11, NULL, NULL},
+       {12, NULL, NULL},
+       {13, NULL, NULL},
+       {14, NULL, NULL},
+       {15, NULL, NULL},
+       {16, NULL, NULL},
+       {17, NULL, NULL},
+       {18, NULL, NULL},
+       {19, NULL, NULL},
+       {20, NULL, NULL},
+       {21, NULL, NULL},
+       {22, NULL, NULL},
+       {23, NULL, NULL},
+       {24, NULL, NULL},
+       {25, NULL, NULL},
+       {26, NULL, NULL},
+       {27, NULL, NULL},
+       {28, NULL, NULL},
+       {29, NULL, NULL},
+       {30, NULL, NULL},
+       {31, NULL, NULL},
+       {32, NULL, NULL},
+       {33, NULL, NULL},
+       {34, NULL, NULL},
+       {35, NULL, NULL},
+       {36, NULL, NULL},
+       {37, NULL, NULL},
+       {38, NULL, NULL},
+       {39, NULL, NULL},
+       {40, NULL, NULL},
+       {41, NULL, NULL},
+       {42, NULL, NULL},
+       {43, NULL, NULL},
+       {44, NULL, NULL},
+       {45, NULL, NULL},
+       {46, NULL, NULL},
+       {47, NULL, NULL},
+       {48, NULL, NULL},
+       {49, NULL, NULL},
+       {50, NULL, NULL},
+       {51, NULL, NULL},
+       {52, NULL, NULL},
+       {53, NULL, NULL},
+       {54, NULL, NULL},
+       {55, NULL, NULL},
+       {56, NULL, NULL},
+       {57, NULL, NULL},
+       {58, NULL, NULL},
+       {59, NULL, NULL},
+       {60, NULL, NULL},
+       {61, NULL, NULL},
+       {62, NULL, NULL},
+       {63, NULL, NULL},
+       {64, NULL, NULL},
+       {65, NULL, NULL},
+       {66, NULL, NULL},
+       {67, NULL, NULL},
+       {68, NULL, NULL},
+       {69, NULL, NULL},
+       {70, NULL, NULL},
+       {71, NULL, NULL},
+};
+
+int mpc5xxx_read_core_reg(struct target *target, int num)
+{
+       uint32_t reg_value;
+
+       /* get pointers to arch-specific information */
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+
+       if ((num < 0) || (num >= MPC5XXX_NUMCOREREGS))
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       reg_value = mpc56xx->core_regs[num];
+       buf_set_u32(mpc56xx->core_cache->reg_list[num].value, 0, 32, reg_value);
+       mpc56xx->core_cache->reg_list[num].valid = 1;
+       mpc56xx->core_cache->reg_list[num].dirty = 0;
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_write_core_reg(struct target *target, int num)
+{
+       uint32_t reg_value;
+
+       /* get pointers to arch-specific information */
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+
+       if ((num < 0) || (num >= MPC5XXX_NUMCOREREGS))
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       reg_value = buf_get_u32(mpc56xx->core_cache->reg_list[num].value, 0, 
32);
+       mpc56xx->core_regs[num] = reg_value;
+       LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
+       mpc56xx->core_cache->reg_list[num].valid = 1;
+       mpc56xx->core_cache->reg_list[num].dirty = 0;
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_get_core_reg(struct reg *reg)
+{
+       int retval;
+       struct mpc5xxx_core_reg *mpc56xx_reg = reg->arch_info;
+       struct target *target = mpc56xx_reg->target;
+
+       if (target->state != TARGET_HALTED)
+               return ERROR_TARGET_NOT_HALTED;
+
+       retval = mpc5xxx_read_core_reg(target, mpc56xx_reg->num);
+
+       return retval;
+}
+
+int mpc5xxx_set_core_reg(struct reg *reg, uint8_t *buf)
+{
+       struct mpc5xxx_core_reg *mpc56xx_reg = reg->arch_info;
+       struct target *target = mpc56xx_reg->target;
+       uint32_t value = buf_get_u32(buf, 0, 32);
+
+       if (target->state != TARGET_HALTED)
+               return ERROR_TARGET_NOT_HALTED;
+
+       buf_set_u32(reg->value, 0, 32, value);
+       reg->dirty = 1;
+       reg->valid = 1;
+
+       return ERROR_OK;
+}
+
+const struct reg_arch_type mpc5xxx_reg_type = {
+       .get = mpc5xxx_get_core_reg,
+       .set = mpc5xxx_set_core_reg,
+};
+
+struct reg_cache *mpc5xxx_build_reg_cache(struct target *target)
+{
+       int num_regs = MPC5XXX_NUMCOREREGS;
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+       struct reg_cache **cache_p = 
register_get_last_cache_p(&target->reg_cache);
+       struct reg_cache *cache = malloc(sizeof(struct reg_cache));
+       struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
+       struct mpc5xxx_core_reg *arch_info =
+               malloc(sizeof(struct mpc5xxx_core_reg) * num_regs);
+       int i;
+
+       /* Build the process context cache */
+       cache->name = "mpc5xxx registers";
+       cache->next = NULL;
+       cache->reg_list = reg_list;
+       cache->num_regs = num_regs;
+       (*cache_p) = cache;
+       mpc56xx->core_cache = cache;
+
+       for (i = 0; i < num_regs; i++) {
+               arch_info[i] = mpc56xx_core_reg_list_arch_info[i];
+               arch_info[i].target = target;
+               arch_info[i].mpc56xx_common = mpc56xx;
+               reg_list[i].name = mpc5xxx_core_reg_list[i];
+               reg_list[i].size = 32;
+               reg_list[i].value = calloc(1, 4);
+               reg_list[i].dirty = 0;
+               reg_list[i].valid = 0;
+               reg_list[i].type = &mpc5xxx_reg_type;
+               reg_list[i].arch_info = &arch_info[i];
+       }
+
+       return cache;
+}
+
+int mpc5xxx_assert_reset(struct target *target)
+{
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+       int retval;
+
+       printf("mpc56xx_assert_reset\n");
+
+       adapter_assert_reset();
+
+       /* Init code wants to be talking to JTAGC. */
+       retval = mpc5xxx_jtag_access_jtagc(&mpc56xx->jtag);
+       if (retval)
+               return retval;
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_read_memory(struct target *target, target_addr_t address,
+       uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+
+       LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 
0x%8.8" PRIx32 "",
+               (unsigned int)address,
+               size,
+               count);
+
+       /* sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || 
!(buffer))
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 
0x1u)))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       switch (size) {
+               case 4:
+                       return mpc5xxx_jtag_read_memory32(&mpc56xx->jtag, 
address, count,
+                               (uint32_t *)(void *)buffer);
+                       break;
+               case 2:
+                       return mpc5xxx_jtag_read_memory16(&mpc56xx->jtag, 
address, count,
+                               (uint16_t *)(void *)buffer);
+                       break;
+               case 1:
+                       return mpc5xxx_jtag_read_memory8(&mpc56xx->jtag, 
address, count, buffer);
+                       break;
+               default:
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_write_memory(struct target *target, target_addr_t address,
+       uint32_t size, uint32_t count, const uint8_t *buffer)
+{
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+
+       LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 
0x%8.8" PRIx32 "",
+               (unsigned int)address,
+               size,
+               count);
+
+       /* sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || 
!(buffer))
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 
0x1u)))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       switch (size) {
+               case 4:
+                       return mpc5xxx_jtag_write_memory32(&mpc56xx->jtag, 
address, count,
+                               (uint32_t *)(void *)buffer);
+                       break;
+               case 2:
+                       return mpc5xxx_jtag_write_memory16(&mpc56xx->jtag, 
address, count,
+                               (uint16_t *)(void *)buffer);
+                       break;
+               case 1:
+                       return mpc5xxx_jtag_write_memory8(&mpc56xx->jtag, 
address, count, buffer);
+                       break;
+               default:
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_init_target(struct command_context *cmd_ctx,
+       struct target *target)
+{
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+       printf("init_target\n");
+       mpc56xx->jtag.tap = target->tap; /* why? */
+       mpc5xxx_build_reg_cache(target);
+       /* mpc56xx->num_inst_bpoints_avail = 2; */
+       return ERROR_OK;
+}
+
+int mpc5xxx_examine(struct target *target)
+{
+       uint32_t osr;
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+       printf("examine\n");
+       if (!target_was_examined(target)) {
+
+               target_set_examined(target);
+
+               /* we will configure later */
+               mpc56xx->bp_scanned = 0;
+               mpc56xx->num_inst_bpoints = 0;
+               mpc56xx->num_data_bpoints = 0;
+               mpc56xx->num_inst_bpoints_avail = 0;
+               mpc56xx->num_data_bpoints_avail = 0;
+
+               /* Check if processor halted. */
+               mpc5xxx_once_osr_read(&mpc56xx->jtag, &osr);
+               if (osr & MPC5XXX_OSR_HALT_DEBUG) { /* FIXME say halted if in 
DEBUG mode */
+                       LOG_INFO("target is halted/debug");
+                       target->state = TARGET_HALTED;
+               } else
+                       target->state = TARGET_RUNNING;
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_arch_state(struct target *target)
+{
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+
+       LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
+               debug_reason_name(target), mpc56xx->jtag.dpc);
+
+       return ERROR_OK;
+}
+
+/* This next function derived from mips32.c */
+int mpc5xxx_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
+               int *reg_list_size, enum target_register_class reg_class)
+{
+       /* get pointers to arch-specific information */
+       struct mpc5xxx_common *mpc56xx = target_to_mpc5xxx(target);
+       unsigned int i;
+
+       /* include floating point registers */
+       *reg_list_size = MPC5XXX_NUMCOREREGS;
+       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+
+       for (i = 0; i < MPC5XXX_NUMCOREREGS; i++)
+               (*reg_list)[i] = &mpc56xx->core_cache->reg_list[i];
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_read_memory32(struct mpc5xxx_jtag *jtag_info,
+       uint32_t addr, int count, uint32_t *buffer)
+{
+       int i, retval;
+       uint32_t data;
+
+       for (i = 0; i < count; i++) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i*4, &data, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* XXX: Assume PPC32 is BE */
+               buffer[i] = be_to_h_u32((uint8_t *)&data);
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_read_memory16(struct mpc5xxx_jtag *jtag_info,
+       uint32_t addr, int count, uint16_t *buffer)
+{
+       int i, retval;
+       uint32_t data;
+
+       i = 0;
+
+       /* any unaligned half-words? */
+       if (addr & 3) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i*2, &data, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* XXX: Assume PPC32 is BE */
+               data = be_to_h_u32((uint8_t *)&data);
+               buffer[i] = (data >> 16) & 0xffff;
+               i++;
+       }
+
+       /* read all complete words */
+       for (; i < (count & ~1); i += 2) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i*2, &data, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* XXX: Assume PPC32 is BE */
+               data = be_to_h_u32((uint8_t *)&data);
+               buffer[i] = data & 0xffff;
+               buffer[i+1] = (data >> 16) & 0xffff;
+       }
+
+       /* last halfword */
+       if (i < count) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i*2, &data, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* XXX: Assume PPC32 is BE */
+               data = be_to_h_u32((uint8_t *)&data);
+               buffer[i] = data & 0xffff;
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_read_memory8(struct mpc5xxx_jtag *jtag_info,
+       uint32_t addr, int count, uint8_t *buffer)
+{
+       int i, j, retval;
+       uint8_t data[4];
+       i = 0;
+
+       /* Do we have non-aligned bytes? */
+       if (addr & 3) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i, (uint32_t 
*)(void *)data, 32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               for (j = addr & 3; (j < 4) && (i < count); j++, i++)
+                       buffer[i] = data[3-j];
+       }
+
+       /* read all complete words */
+       for (; i < (count & ~3); i += 4) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i, (uint32_t 
*)(void *)data, 32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               for (j = 0; j < 4; j++)
+                       buffer[i+j] = data[3-j];
+       }
+
+       /* remaining bytes */
+       if (i < count) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i, (uint32_t 
*)(void *)data, 32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               for (j = 0; i + j < count; j++)
+                       buffer[i+j] = data[3-j];
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_write_memory32(struct mpc5xxx_jtag *jtag_info,
+       uint32_t addr, int count, const uint32_t *buffer)
+{
+       int i, retval;
+       uint32_t data;
+
+       for (i = 0; i < count; i++) {
+               /* XXX: Assume PPC32 is BE */
+               h_u32_to_be((uint8_t *)&data, buffer[i]);
+               retval = mpc5xxx_once_nexus_write(jtag_info, addr + i*4, data, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_write_memory16(struct mpc5xxx_jtag *jtag_info,
+       uint32_t addr, int count, const uint16_t *buffer)
+{
+       int i, retval;
+       uint32_t data;
+       uint32_t data_out;
+
+       i = 0;
+
+       /*
+        * Do we have any non-aligned half-words?
+        */
+       if (addr & 3) {
+               /*
+                * _read will read whole world, no need to fiddle
+                * with address. It will be truncated in set_addr ???? JSM
+                */
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr, &data, 32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               data = be_to_h_u32((uint8_t *)&data);
+               data = (buffer[i] << 16) | (data & 0xffff);
+               h_u32_to_be((uint8_t *)&data_out, data);
+
+               retval = mpc5xxx_once_nexus_write(jtag_info, addr, data_out, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               i++;
+       }
+
+       /* write all complete words */
+       for (; i < (count & ~1); i += 2) {
+               /* XXX: Assume PPC32 is BE */
+               data = (buffer[i+1] << 16) | buffer[i];
+               h_u32_to_be((uint8_t *)&data_out, data);
+
+               retval = mpc5xxx_once_nexus_write(jtag_info, addr + i*2, 
data_out, 32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       /* last halfword */
+       if (i < count) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i*2, &data, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               data = be_to_h_u32((uint8_t *)&data);
+               data &= ~0xffff;
+               data |= buffer[i];
+               h_u32_to_be((uint8_t *)&data_out, data);
+
+               retval = mpc5xxx_once_nexus_write(jtag_info, addr + i*2, 
data_out, 32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_write_memory8(struct mpc5xxx_jtag *jtag_info,
+       uint32_t addr, int count, const uint8_t *buffer)
+{
+       int i, j, retval;
+       uint32_t data;
+       uint32_t data_out;
+
+       i = 0;
+
+       /*
+        * Do we have any non-aligned bytes?
+        */
+       if (addr & 3) {
+               /*
+                * mwa_read will read whole world, no nead to fiddle
+                * with address. It will be truncated in set_addr
+                */
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr, &data, 32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               data = be_to_h_u32((uint8_t *)&data);
+               for (j = addr & 3; (j < 4) && (i < count); j++, i++) {
+                       data &= ~(0xff << j*8);
+                       data |= (buffer[i] << j*8);
+               }
+
+               h_u32_to_be((uint8_t *)&data_out, data);
+               retval = mpc5xxx_once_nexus_write(jtag_info, addr, data_out, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+
+       /* write all complete words */
+       for (; i < (count & ~3); i += 4) {
+               data = 0;
+
+               for (j = 0; j < 4; j++)
+                       data |= (buffer[j+i] << j*8);
+
+               h_u32_to_be((uint8_t *)&data_out, data);
+
+               retval = mpc5xxx_once_nexus_write(jtag_info, addr + i, 
data_out, 32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       /*
+        * Write trailing bytes
+        */
+       if (i < count) {
+               retval = mpc5xxx_once_nexus_read(jtag_info, addr + i, &data, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               data = be_to_h_u32((uint8_t *)&data);
+               for (j = 0; i < count; j++, i++) {
+                       data &= ~(0xff << j*8);
+                       data |= (buffer[j+i] << j*8);
+               }
+
+               h_u32_to_be((uint8_t *)&data_out, data);
+
+               retval = mpc5xxx_once_nexus_write(jtag_info, addr+i, data_out, 
32);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
diff --git a/src/target/mpc5xxx.h b/src/target/mpc5xxx.h
new file mode 100644
index 0000000..d9743a7
--- /dev/null
+++ b/src/target/mpc5xxx.h
@@ -0,0 +1,177 @@
+/***************************************************************************
+ *   Copyright (C) 2017 by James Murray <[email protected]                   *
+ *   Based on code:                                                        *
+ *       Copyright (C) 2010 by Oleksandr Tymoshenko <[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/>. *
+ ***************************************************************************/
+
+#ifndef MPC5XXX
+#define MPC5XXX
+
+struct target;
+
+#define        MPC5XXX_NUMCOREREGS     72 /* GDB/Zylin CDT asks for high 
non-existent regs */
+
+enum mpc5xxx_reg_nums {
+       MPC5XXX_REG_R0 = 0,
+       MPC5XXX_REG_R1, /* also SP ? */
+       MPC5XXX_REG_R2,
+       MPC5XXX_REG_R3,
+       MPC5XXX_REG_R4,
+       MPC5XXX_REG_R5,
+       MPC5XXX_REG_R6,
+       MPC5XXX_REG_R7,
+       MPC5XXX_REG_R8,
+       MPC5XXX_REG_R9,
+       MPC5XXX_REG_R10,
+       MPC5XXX_REG_R11,
+       MPC5XXX_REG_R12,
+       MPC5XXX_REG_R13,
+       MPC5XXX_REG_R14,
+       MPC5XXX_REG_R15,
+       MPC5XXX_REG_R16,
+       MPC5XXX_REG_R17,
+       MPC5XXX_REG_R18,
+       MPC5XXX_REG_R19,
+       MPC5XXX_REG_R20,
+       MPC5XXX_REG_R21,
+       MPC5XXX_REG_R22,
+       MPC5XXX_REG_R23,
+       MPC5XXX_REG_R24,
+       MPC5XXX_REG_R25,
+       MPC5XXX_REG_R26,
+       MPC5XXX_REG_R27,
+       MPC5XXX_REG_R28,
+       MPC5XXX_REG_R29,
+       MPC5XXX_REG_R30,
+       MPC5XXX_REG_R31,
+       MPC5XXX_REG_R32,
+       MPC5XXX_REG_R33,
+       MPC5XXX_REG_R34,
+       MPC5XXX_REG_R35,
+       MPC5XXX_REG_R36,
+       MPC5XXX_REG_R37,
+       MPC5XXX_REG_R38,
+       MPC5XXX_REG_R39,
+       MPC5XXX_REG_R40,
+       MPC5XXX_REG_R41,
+       MPC5XXX_REG_R42,
+       MPC5XXX_REG_R43,
+       MPC5XXX_REG_R44,
+       MPC5XXX_REG_R45,
+       MPC5XXX_REG_R46,
+       MPC5XXX_REG_R47,
+       MPC5XXX_REG_R48,
+       MPC5XXX_REG_R49,
+       MPC5XXX_REG_R50,
+       MPC5XXX_REG_R51,
+       MPC5XXX_REG_R52,
+       MPC5XXX_REG_R53,
+       MPC5XXX_REG_R54,
+       MPC5XXX_REG_R55,
+       MPC5XXX_REG_R56,
+       MPC5XXX_REG_R57,
+       MPC5XXX_REG_R58,
+       MPC5XXX_REG_R59,
+       MPC5XXX_REG_R60,
+       MPC5XXX_REG_R61,
+       MPC5XXX_REG_R62,
+       MPC5XXX_REG_R63,
+       MPC5XXX_REG_PC,
+       MPC5XXX_REG_MSR,
+       MPC5XXX_REG_CND,
+       MPC5XXX_REG_LR,
+       MPC5XXX_REG_CNT,
+       MPC5XXX_REG_XER,
+       MPC5XXX_REG_MQ,
+       MPC5XXX_REG_R71,
+};
+
+struct mpc5xxx_comparator {
+       int used;
+       uint32_t bp_value;
+       uint32_t reg_address;
+};
+
+struct mpc5xxx_common {
+       int common_magic;
+       struct mpc5xxx_jtag jtag;
+       struct reg_cache *core_cache;
+       uint32_t core_regs[MPC5XXX_NUMCOREREGS];
+
+       int bp_scanned;
+       int num_inst_bpoints;
+       int num_data_bpoints;
+       int num_inst_bpoints_avail;
+       int num_data_bpoints_avail;
+       struct mpc5xxx_comparator *inst_break_list;
+       struct mpc5xxx_comparator *data_break_list;
+       int jtag_state;
+       uint32_t saved_ctl ;
+       uint32_t saved_msr ;
+       uint32_t ctl_on_entry ;
+       uint32_t msr_on_entry ;
+};
+
+static inline struct mpc5xxx_common *
+target_to_mpc5xxx(struct target *target)
+{
+       return (struct mpc5xxx_common *)target->arch_info;
+}
+
+struct mpc5xxx_core_reg {
+       uint32_t num;
+       struct target *target;
+       struct mpc5xxx_common *mpc56xx_common;
+};
+
+extern const char * const mpc5xxx_core_reg_list[];
+extern const struct mpc5xxx_core_reg
+       mpc5xxx_core_reg_list_arch_info[];
+
+extern const struct reg_arch_type mpc5xxx_reg_type;
+
+int mpc5xxx_read_core_reg(struct target *target, int num);
+int mpc5xxx_write_core_reg(struct target *target, int num);
+int mpc5xxx_get_core_reg(struct reg *reg);
+int mpc5xxx_set_core_reg(struct reg *reg, uint8_t *buf);
+struct reg_cache *mpc5xxx_build_reg_cache(struct target *target);
+int mpc5xxx_assert_reset(struct target *target);
+int mpc5xxx_read_memory(struct target *target, target_addr_t address,
+       uint32_t size, uint32_t count, uint8_t *buffer);
+int mpc5xxx_write_memory(struct target *target, target_addr_t address,
+       uint32_t size, uint32_t count, const uint8_t *buffer);
+int mpc5xxx_init_target(struct command_context *cmd_ctx,
+       struct target *target);
+int mpc5xxx_examine(struct target *target);
+int mpc5xxx_arch_state(struct target *target);
+int mpc5xxx_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
+       int *reg_list_size, enum target_register_class reg_class);
+
+int mpc5xxx_jtag_read_memory32(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, int count, uint32_t *buffer);
+int mpc5xxx_jtag_read_memory16(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, int count, uint16_t *buffer);
+int mpc5xxx_jtag_read_memory8(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, int count, uint8_t *buffer);
+
+int mpc5xxx_jtag_write_memory32(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, int count, const uint32_t *buffer);
+int mpc5xxx_jtag_write_memory16(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, int count, const uint16_t *buffer);
+int mpc5xxx_jtag_write_memory8(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, int count, const uint8_t *buffer);
+
+#endif
diff --git a/src/target/mpc5xxx_jtag.c b/src/target/mpc5xxx_jtag.c
new file mode 100644
index 0000000..ec19bda
--- /dev/null
+++ b/src/target/mpc5xxx_jtag.c
@@ -0,0 +1,624 @@
+/***************************************************************************
+ *   Copyright (C) 2017 by James Murray <[email protected]                   *
+ *   Based on code:                                                        *
+ *       Copyright (C) 2010 by Oleksandr Tymoshenko <[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/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "target.h"
+#include "jtag/jtag.h"
+#include "mpc5xxx_jtag.h"
+#include "jtag/interface.h"
+
+#define READ_MAXLOOPS 500
+
+int mpc5xxx_jtag_set_instr(struct mpc5xxx_jtag *jtag_info, int new_instr)
+{
+       struct jtag_tap *tap;
+       int busy = 0;
+
+       tap = jtag_info->tap;
+       if (tap == NULL)
+               return ERROR_FAIL;
+
+       if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != 
(uint32_t)new_instr) {
+               do {
+                       struct scan_field field;
+                       uint8_t t[4];
+                       uint8_t ret[4];
+
+                       field.num_bits = tap->ir_length;
+                       field.out_value = t;
+                       buf_set_u32(t, 0, field.num_bits, new_instr);
+                       field.in_value = ret;
+
+                       jtag_add_ir_scan(tap, &field, TAP_IDLE);
+                       if (jtag_execute_queue() != ERROR_OK) {
+                               LOG_ERROR("%s: setting address failed", 
__func__);
+                               return ERROR_FAIL;
+                       }
+                       busy = buf_get_u32(ret, 2, 1);
+               } while (busy); /* check for busy bit */
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_read_data(struct mpc5xxx_jtag *jtag_info,
+       uint32_t *pdata, uint32_t size)
+{
+
+       struct scan_field field;
+       uint8_t data_buf[4];
+       uint8_t busy_buf[4];
+       int busy;
+
+       if (size > 32)
+               size = 32;
+
+
+       do {
+               int jterr;
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+
+               field.num_bits = size;
+               field.out_value = NULL;
+               field.in_value = data_buf;
+
+               jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+               jterr = jtag_execute_queue();
+               if (jterr != ERROR_OK) {
+                       LOG_ERROR("%s: reading data failed with error %d", 
__func__, jterr);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 1);
+       } while (busy);
+
+       *pdata = buf_get_u32(data_buf, 0, 32);
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_write_data(struct mpc5xxx_jtag *jtag_info,
+               uint32_t data, uint32_t size)
+{
+
+       struct scan_field field;
+       uint8_t data_buf[4];
+       uint8_t busy_buf[4];
+       int busy;
+
+       if (size > 32)
+               size = 32;
+
+
+       do {
+               int jterr ;
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+
+               buf_set_u32(data_buf, 0, size, data);
+               field.num_bits = size;
+               field.in_value = NULL;
+               field.out_value = data_buf;
+
+               jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+               jterr = jtag_execute_queue();
+               if (jterr != ERROR_OK) {
+                       LOG_ERROR("%s: write data failed with error %d", 
__func__, jterr);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 0);
+       } while (busy);
+
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_access_once(struct mpc5xxx_jtag *jtag_info)
+{
+       int res;
+       uint32_t did;
+
+       if (jtag_info->once == MPC5XXX_TAP_INVALID) {
+               printf("OnCE not yet set.\n");
+               return ERROR_FAIL;
+       }
+
+       if (jtag_info->current_tap == jtag_info->once)
+                       return ERROR_OK;
+
+       if (jtag_info->current_tap != MPC5XXX_TAP_JTAG) {
+               /* Revert to JTAGC first */
+               res = mpc5xxx_jtag_access_jtagc(jtag_info);
+               if (res)
+                       return res;
+       }
+
+       printf("Switching to ONCE, (TAP id = 0x%02x)\n", jtag_info->once);
+
+       res = mpc5xxx_jtag_set_instr(jtag_info, jtag_info->once);
+       if (res)
+               return res;
+
+       jtag_info->current_tap = jtag_info->once;
+       /* OnCE uses 10 bits */
+       jtag_info->tap->ir_length = 10;
+
+               /* Read the OnCE JTAG ID for info */
+               res = mpc5xxx_once_read(jtag_info, MPC5XXX_ONCE_DID, &did, 32);
+       if (res)
+               return res;
+
+       if (did != jtag_info->tap->expected_ids[1]) {
+               printf("Serious JTAG problem! Didn't find OnCE ID (0x%08x), 
found 0x%08x.\n",
+                               jtag_info->tap->expected_ids[1], did);
+               printf("Exiting!!!\n");
+               exit(2);
+               return ERROR_FAIL;
+       }
+printf("Switched to ONCE ok.\n");
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtag_access_jtagc(struct mpc5xxx_jtag *jtag_info)
+{
+       int res;
+       uint32_t did;
+
+#define JTAG_TAP_ID 0x3e
+
+       if (jtag_info->current_tap == MPC5XXX_TAP_JTAG)
+
+               return ERROR_OK;
+
+       printf("Switching to JTAGC\n");
+       (void)interface_jtag_add_reset(0, 0);
+
+       /* Get out of whatever TAP we were in and return to JTAGC */
+       res = jtag_add_statemove(TAP_DRPAUSE);
+       if (res)
+               return res;
+
+       /* Run-test/idle for JTAGC */
+       res = jtag_add_statemove(TAP_IDLE);
+       if (res)
+               return res;
+
+       jtag_info->current_tap = MPC5XXX_TAP_JTAG;
+       jtag_info->tap->ir_length = jtag_info->jtag_irlen;
+
+       /* Validate that the correct IDcode is here */
+       res = mpc5xxx_jtagc_read(jtag_info, MPC5XXX_INST_IDCODE, &did, 32);
+       if (res)
+               return res;
+       if (did != jtag_info->tap->expected_ids[0]) {
+               printf("Serious JTAG problem! Didn't find JTAG ID (0x%08x), 
found 0x%08x.\n",
+                               jtag_info->tap->expected_ids[0], did);
+               printf("Exiting!!!\n");
+               exit(2);
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtagc_read(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t *value, uint32_t size)
+{
+       int res;
+
+       res = mpc5xxx_jtag_access_jtagc(jtag_info);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_set_instr(jtag_info, addr);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_read_data(jtag_info, value, size);
+       if (res)
+               return res;
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_jtagc_write(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t value, uint32_t size)
+{
+       int res;
+
+       res = mpc5xxx_jtag_access_jtagc(jtag_info);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_set_instr(jtag_info, addr);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_write_data(jtag_info, value, size);
+       if (res)
+               return res;
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_once_read(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t *value, uint32_t size)
+{
+       int res;
+
+       res = mpc5xxx_jtag_access_once(jtag_info);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_set_instr(jtag_info, MPC5XXX_ONCE_READ | addr);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_read_data(jtag_info, value, size);
+       if (res)
+               return res;
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_once_write(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t value, uint32_t size)
+{
+       int res;
+
+       res = mpc5xxx_jtag_access_once(jtag_info);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_set_instr(jtag_info, addr);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_write_data(jtag_info, value, size);
+       if (res)
+               return res;
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_once_osr_read(struct mpc5xxx_jtag *jtag_info, uint32_t *in)
+{
+#define OSR_SIZE 10
+       struct scan_field field;
+       uint8_t data_buf[4];
+       uint8_t busy_buf[4];
+       uint8_t in_buf[4];
+       int busy, res;
+
+       res = mpc5xxx_jtag_access_once(jtag_info);
+       if (res)
+               return res;
+
+       do {
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+               memset(in_buf, 0, sizeof(in_buf));
+
+               buf_set_u32(data_buf, 0, OSR_SIZE, MPC5XXX_ONCE_READ | 
MPC5XXX_ONCE_NOREG);
+               field.num_bits = OSR_SIZE;
+               field.in_value = in_buf;
+               field.out_value = data_buf;
+
+               jtag_add_ir_scan(jtag_info->tap, &field, TAP_IDLE);
+
+               if (jtag_execute_queue() != ERROR_OK) {
+                       LOG_ERROR("%s: reading data  failed", __func__);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 0);
+       } while (busy);
+
+       *in = buf_get_u32(in_buf, 0, OSR_SIZE);
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_once_check_edm(struct mpc5xxx_jtag *jtag_info)
+{
+       int retval;
+       uint32_t val;
+
+       retval = mpc5xxx_once_read(jtag_info, MPC5XXX_ONCE_DBCR0, &val, 32);
+       if (retval != ERROR_OK)
+               return retval;
+       printf("Value returned from DBCR0 was 0x%x\n", val);
+       if ((val & MPC5XXX_ONCE_DBCR0_EDM) == 0) {
+               printf("EDM bit not set, try to set it\n");
+
+               retval = mpc5xxx_once_write(jtag_info, MPC5XXX_ONCE_DBCR0, 
MPC5XXX_ONCE_DBCR0_EDM, 32);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* See if it was actually set */
+               retval = mpc5xxx_once_read(jtag_info, MPC5XXX_ONCE_DBCR0, &val, 
32);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               if ((val & MPC5XXX_ONCE_DBCR0_EDM) == 0) {
+                       printf("Seems we are unable to set the EDM bit. 
Arse!\n");
+                       exit(1);
+               } else {
+                       printf("IS OK NOW!\n");
+               }
+       }
+       return ERROR_OK;
+}
+
+#define CPUSCR_SIZE 192
+/* reads 6 * 32bits from CPUSCR */
+int mpc5xxx_once_cpuscr_read(struct mpc5xxx_jtag *jtag_info, struct 
mpc5xxx_cpuscr *cpuscr)
+{
+       struct scan_field field;
+       uint8_t data_buf[24];
+       uint8_t busy_buf[24];
+       uint8_t in_buf[24];
+       int busy, res;
+
+       res = mpc5xxx_jtag_access_once(jtag_info);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_set_instr(jtag_info, MPC5XXX_ONCE_READ | 
MPC5XXX_ONCE_CPUSCR);
+       if (res)
+               return res;
+
+       do {
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+               memset(in_buf, 0, sizeof(in_buf));
+
+               field.num_bits = CPUSCR_SIZE;
+               field.in_value = in_buf;
+               field.out_value = NULL;
+
+               jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+               if (jtag_execute_queue() != ERROR_OK) {
+                       LOG_ERROR("%s: reading data  failed", __func__);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 0);
+       } while (busy);
+
+       cpuscr->wbbrl = buf_get_u32(in_buf, 0, 32);
+       cpuscr->wbbrh = buf_get_u32(in_buf, 32, 32);
+       cpuscr->msr = buf_get_u32(in_buf, 64, 32);
+       cpuscr->pc = buf_get_u32(in_buf, 96, 32);
+       cpuscr->ir = buf_get_u32(in_buf, 128, 32);
+       cpuscr->ctl = buf_get_u32(in_buf, 160, 32);
+       /* printf("CPU MSR=0x%08x\n", cpuscr->msr); */
+
+       return ERROR_OK;
+}
+
+/* writes 6 * 32bits to CPUSCR */
+int mpc5xxx_once_cpuscr_write(struct mpc5xxx_jtag *jtag_info, struct 
mpc5xxx_cpuscr *cpuscr)
+{
+       struct scan_field field;
+       uint8_t data_buf[24];
+       uint8_t busy_buf[24];
+       int busy, res;
+
+       res = mpc5xxx_jtag_access_once(jtag_info);
+       if (res)
+               return res;
+
+       res = mpc5xxx_jtag_set_instr(jtag_info, MPC5XXX_ONCE_CPUSCR);
+       if (res)
+               return res;
+
+       do {
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+               memcpy(data_buf, cpuscr, CPUSCR_SIZE / 8);
+
+               field.num_bits = CPUSCR_SIZE;
+               field.in_value = NULL;
+               field.out_value = data_buf;
+
+               jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+               if (jtag_execute_queue() != ERROR_OK) {
+                       LOG_ERROR("%s: reading data  failed", __func__);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 0);
+       } while (busy);
+
+       return ERROR_OK;
+}
+
+int mpc5xxx_once_nexus_read(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t *value, uint32_t size)
+{
+       int res;
+       uint32_t val, count;
+
+       res = mpc5xxx_jtag_access_once(jtag_info);
+       if (res)
+               return res;
+
+       /* Tell ONCE to access NEXUS.
+        * Note: The code already checks if this is the current instruction, so
+        * this won't waste JTAG clocks.
+        */
+       res = mpc5xxx_jtag_set_instr(jtag_info, MPC5XXX_ONCE_NEXUS);
+       if (res)
+               return res;
+
+       /* Set up RWA with the desired address
+        * Next is write */
+       mpc5xxx_jtag_write_data(jtag_info, MPC5XXX_ONCE_NEXUS_RWA | 
MPC5XXX_ONCE_NEXUS_WRITE, 8);
+       mpc5xxx_jtag_write_data(jtag_info, addr, 32);
+
+       /* Now programme the RWCS reg to initiate the read
+        * Next is write */
+       mpc5xxx_jtag_write_data(jtag_info, MPC5XXX_ONCE_NEXUS_RWCS | 
MPC5XXX_ONCE_NEXUS_WRITE, 8);
+       if (size == 8) {
+               val = MPC5XXX_ONCE_NEXUS_RWCS_READ1_8;
+       } else if (size == 16) {
+               val = MPC5XXX_ONCE_NEXUS_RWCS_READ1_16;
+       } else {
+               val = MPC5XXX_ONCE_NEXUS_RWCS_READ1_32;
+               size = 32;
+       }
+
+       mpc5xxx_jtag_write_data(jtag_info, val, 32);
+
+       /* Now poll RWCS until the read completed */
+       val = 0;
+       count = 0;
+       while (((val & MPC5XXX_ONCE_NEXUS_RWCS_MASK) == 0) && (count < 
READ_MAXLOOPS)) {
+               /* next is read */
+               mpc5xxx_jtag_write_data(jtag_info, MPC5XXX_ONCE_NEXUS_RWCS, 8);
+               mpc5xxx_jtag_read_data(jtag_info, &val, 32);
+               count++;
+       }
+       if (((val & MPC5XXX_ONCE_NEXUS_RWCS_MASK) != 
MPC5XXX_ONCE_NEXUS_RWCS_READOK)
+               || (count >= READ_MAXLOOPS)) {
+               LOG_ERROR("Failed to read memory!");
+               return ERROR_FAIL;
+       }
+
+       /* Now read the actual data
+        * next is read */
+       mpc5xxx_jtag_write_data(jtag_info, MPC5XXX_ONCE_NEXUS_RWD, 8);
+
+       mpc5xxx_jtag_read_data(jtag_info, &val, size);
+
+       /* Byte swap for endianism target is BE, but Nexus reads are
+        * supposed to be LE. Appears that something is converting
+        * in the middle?
+        * How do we know that host is LE ?
+        */
+       if (size == 8) {
+               *value = val;
+       } else if (size == 16) {
+               *value = ((val & 0x00ff) << 8) | ((val & 0xff00) >> 8);
+       } else {
+               *value = ((val & 0x000000ff) << 24)
+                               | ((val & 0x0000ff00) << 8)
+                               | ((val & 0x00ff0000) >> 8)
+                               | ((val & 0xff000000) >> 24);
+       }
+       return ERROR_OK;
+}
+
+int mpc5xxx_once_nexus_write(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t value, uint32_t size)
+{
+       int res;
+       uint32_t val, count;
+
+       /* Byte swap for endianism target is BE, but Nexus reads are
+        * supposed to be LE. Appears that something is converting
+        * in the middle?
+        * How do we know that host is LE ?
+        */
+       if (size == 8) {
+               /* no change */
+       } else if (size == 16) {
+               value = ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8);
+       } else {
+               value = ((value & 0x000000ff) << 24)
+                               | ((value & 0x0000ff00) << 8)
+                               | ((value & 0x00ff0000) >> 8)
+                               | ((value & 0xff000000) >> 24);
+       }
+
+       res = mpc5xxx_jtag_access_once(jtag_info);
+       if (res)
+               return res;
+
+       /* Tell ONCE to access NEXUS. */
+       res = mpc5xxx_jtag_set_instr(jtag_info, MPC5XXX_ONCE_NEXUS);
+       if (res)
+               return res;
+
+       /* Set up RWA with the desired address
+        * Next is write */
+       res = mpc5xxx_jtag_write_data(jtag_info, MPC5XXX_ONCE_NEXUS_RWA | 
MPC5XXX_ONCE_NEXUS_WRITE, 8);
+       if (res)
+               return res;
+       res = mpc5xxx_jtag_write_data(jtag_info, addr, 32);
+       if (res)
+               return res;
+
+       /* Now programme the RWCS reg to prepare the write
+        * Next is write */
+       res = mpc5xxx_jtag_write_data(jtag_info, MPC5XXX_ONCE_NEXUS_RWCS | 
MPC5XXX_ONCE_NEXUS_WRITE, 8);
+       if (res)
+               return res;
+       if (size == 8) {
+               val = MPC5XXX_ONCE_NEXUS_RWCS_WRITE1_8;
+       } else if (size == 16) {
+               val = MPC5XXX_ONCE_NEXUS_RWCS_WRITE1_16;
+       } else {
+               val = MPC5XXX_ONCE_NEXUS_RWCS_WRITE1_32;
+               size = 32;
+       }
+
+       res = mpc5xxx_jtag_write_data(jtag_info, val, 32);
+       if (res)
+               return res;
+
+       /* Now programme the RWD reg to initiate the write
+        * Next is write */
+       res = mpc5xxx_jtag_write_data(jtag_info, MPC5XXX_ONCE_NEXUS_RWD | 
MPC5XXX_ONCE_NEXUS_WRITE, 8);
+       if (res)
+               return res;
+       res = mpc5xxx_jtag_write_data(jtag_info, value, size);
+       if (res)
+               return res;
+
+       /* Now poll RWCS until the read completed */
+       val = 0;
+       count = 0;
+       while (((val & MPC5XXX_ONCE_NEXUS_RWCS_DVMASK) != 0) && (count < 
READ_MAXLOOPS)) {
+               /* next is read */
+               res = mpc5xxx_jtag_write_data(jtag_info, 
MPC5XXX_ONCE_NEXUS_RWCS, 8);
+               if (res)
+                       return res;
+               res = mpc5xxx_jtag_read_data(jtag_info, &val, 32);
+               if (res)
+                       return res;
+       }
+       if (((val & MPC5XXX_ONCE_NEXUS_RWCS_MASK) != 
MPC5XXX_ONCE_NEXUS_RWCS_WRITEOK)
+               || (count >= READ_MAXLOOPS)) {
+               LOG_ERROR("Failed to read!");
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
diff --git a/src/target/mpc5xxx_jtag.h b/src/target/mpc5xxx_jtag.h
new file mode 100644
index 0000000..c0e9731
--- /dev/null
+++ b/src/target/mpc5xxx_jtag.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ *   Copyright (C) 2017 by James Murray <[email protected]                   *
+ *   Based on code:                                                        *
+ *       Copyright (C) 2010 by Oleksandr Tymoshenko <[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/>. *
+ ***************************************************************************/
+
+#ifndef MPC5XXX_JTAG
+#define MPC5XXX_JTAG
+
+#define MPC5XXX_INST_IDCODE    0x01
+#define MPC5XXX_TAP_JTAG    0x01 /* Not TAP number, but used to identify JTAG 
*/
+#define MPC5XXX_TAP_INVALID    -1
+
+#define MPC5XXX_ONCE_NEXUS_RWCS        (0x07 << 1)     /* 32bit control reg */
+#define MPC5XXX_ONCE_NEXUS_RWA (0x09 << 1)     /* 32bit address reg */
+#define MPC5XXX_ONCE_NEXUS_RWD (0x0a << 1)     /* 32bit data reg */
+#define MPC5XXX_ONCE_NEXUS_WRITE       1                       /* lsb 
determines read=0 or write=1 */
+#define MPC5XXX_ONCE_NEXUS_RWCS_READ1_32       0x90000000      /* single 32bit 
read */
+#define MPC5XXX_ONCE_NEXUS_RWCS_READ1_16       0x88000000      /* single 16bit 
read */
+#define MPC5XXX_ONCE_NEXUS_RWCS_READ1_8        0x80000000      /* single 8bit 
read */
+#define MPC5XXX_ONCE_NEXUS_RWCS_WRITE1_32      0xd0000000      /* single 32bit 
write */
+#define MPC5XXX_ONCE_NEXUS_RWCS_WRITE1_16      0xc8000000      /* single 16bit 
write */
+#define MPC5XXX_ONCE_NEXUS_RWCS_WRITE1_8       0xc0000000      /* single 8bit 
write */
+#define MPC5XXX_ONCE_NEXUS_RWCS_MASK   0x00000003      /* ERR, DV mask */
+#define MPC5XXX_ONCE_NEXUS_RWCS_DVMASK 0x00000001      /* DV mask */
+#define MPC5XXX_ONCE_NEXUS_RWCS_READOK 0x00000001
+#define MPC5XXX_ONCE_NEXUS_RWCS_WRITEOK 0x00000000
+#define MPC5XXX_OCR_DEBUG1     0x05
+#define MPC5XXX_OCR_DEBUG2     0x06
+#define MPC5XXX_OCR_DEBUG_OFF  0x04 /* Still leave WKUP bit set */
+#define MPC5XXX_OCR_FDB        0x02 /* Allow SW BPs */
+
+/* Some ONCE registers are the same */
+#define MPC5XXX_ONCE_DID       0b0000010
+#define MPC5XXX_ONCE_CPUSCR    0b0010000
+#define MPC5XXX_ONCE_NOREG     0b0010001
+#define MPC5XXX_ONCE_OCR       0b0010010
+#define MPC5XXX_ONCE_DBCR0     0b0110001
+#define MPC5XXX_ONCE_NEXUS     0b1111100 /* access Nexus registers via OnCE, 
56xx and 57xx */
+
+#define MPC5XXX_ONCE_DBCR0_EDM 0x80000000      /* EDM bit */
+
+#define MPC5XXX_ONCE_EX                0b0010000000 /* EX mask. EXit debug */
+#define MPC5XXX_ONCE_GO                0b0100000000 /* GO mask. Execute 
command */
+#define MPC5XXX_ONCE_READ      0b1000000000 /* READ mask. */
+
+#define MPC5XXX_OSR_HALT       0x20
+#define MPC5XXX_OSR_DEBUG      0x08
+#define MPC5XXX_OSR_HALT_DEBUG 0x28
+#define MPC5XXX_OSR_ERR        0x100
+
+#define MPC5XXX_MSR_EE 0x8000
+#define MPC5XXX_MSR_CE 0x20000
+
+#define MPC5XXX_CPUSCR_CTL_FFRA 0x00000400
+#define MPC5XXX_CPUSCR_CTL_PCOFST4 0x00001000
+
+struct mpc5xxx_jtag {
+       struct jtag_tap *tap;
+       uint32_t dpc; /* Debug PC value */
+       int once; /* Which Once we are talking to */
+       int current_tap; /* Which Jtag tap we are talking to */
+       int jtag_irlen; /* irlen used for Jtag TAP. Ignores command line 
option. */
+};
+
+struct mpc5xxx_cpuscr {
+       uint32_t wbbrl, wbbrh,  msr, pc, ir, ctl;
+};
+int mpc5xxx_jtag_set_instr(struct mpc5xxx_jtag *jtag_info, int new_instr);
+int mpc5xxx_jtag_read_data(struct mpc5xxx_jtag *jtag_info,
+       uint32_t *pdata, uint32_t size);
+int mpc5xxx_jtag_write_data(struct mpc5xxx_jtag *jtag_info,
+               uint32_t data, uint32_t size);
+int mpc5xxx_jtag_access_jtagc(struct mpc5xxx_jtag *jtag_info);
+int mpc5xxx_jtag_access_once(struct mpc5xxx_jtag *jtag_info);
+int mpc5xxx_jtagc_read(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t *value, uint32_t size);
+int mpc5xxx_jtagc_write(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t value, uint32_t size);
+int mpc5xxx_once_read(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t *value, uint32_t size);
+int mpc5xxx_once_write(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t value, uint32_t size);
+int mpc5xxx_once_nexus_read(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t *value, uint32_t size);
+int mpc5xxx_once_nexus_write(struct mpc5xxx_jtag *jtag_info,
+               uint32_t addr, uint32_t value, uint32_t size);
+int mpc5xxx_once_osr_read(struct mpc5xxx_jtag *jtag_info, uint32_t *in);
+int mpc5xxx_once_cpuscr_read(struct mpc5xxx_jtag *jtag_info, struct 
mpc5xxx_cpuscr *in);
+int mpc5xxx_once_cpuscr_write(struct mpc5xxx_jtag *jtag_info, struct 
mpc5xxx_cpuscr *in);
+
+
+#endif /* MPC56XX_JTAG */

-- 

Reply via email to