From ac22cdc573225fa5860f25821eed52d92ea633e7 Mon Sep 17 00:00:00 2001 From: Kevin Burke Date: Tue, 9 Feb 2021 17:27:03 -0500 Subject: [PATCH] target/adiv5: Large Physical Address Extension Provides ARM LPAE support to allow 64-bit TAR setting on MEM AP accesses. Tested on a 4-core ARM ARES Processor system using an AXI Access Port. Change-Id: I88f7a0a57a6abb58665032929194a41dd8729f6b Signed-off-by: Kevin Burke Signed-off-by: Daniel Goehring Reviewed-on: http://openocd.zylin.com/5576 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/aarch64.c | 6 +- src/target/arm_adi_v5.c | 181 +++++++++++++++++++++++++++------------- src/target/arm_adi_v5.h | 44 +++++++--- src/target/arm_dap.c | 3 + src/target/armv7a.h | 2 +- src/target/armv8.h | 2 +- src/target/cortex_a.c | 4 +- 7 files changed, 168 insertions(+), 74 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 171c286152..d43ade1ff4 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -252,7 +252,7 @@ static int aarch64_init_debug_access(struct target *target) /* Write to memory mapped registers directly with no cache or mmu handling */ static int aarch64_dap_write_memap_register_u32(struct target *target, - uint32_t address, + target_addr_t address, uint32_t value) { int retval; @@ -2571,7 +2571,7 @@ static int aarch64_examine_first(struct target *target) armv8->debug_ap->memaccess_tck = 10; if (!target->dbgbase_set) { - uint32_t dbgbase; + target_addr_t dbgbase; /* Get ROM Table base */ uint32_t apid; int32_t coreidx = target->coreid; @@ -2583,7 +2583,7 @@ static int aarch64_examine_first(struct target *target) &armv8->debug_base, &coreidx); if (retval != ERROR_OK) return retval; - LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32 + LOG_DEBUG("Detected core %" PRId32 " dbgbase: " TARGET_ADDR_FMT " apid: %08" PRIx32, coreidx, armv8->debug_base, apid); } else armv8->debug_base = target->dbgbase; diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 35d686e295..65ac053516 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -13,6 +13,8 @@ * Copyright (C) 2013 by Andreas Fritiofson * * andreas.fritiofson@gmail.com * * * + * Copyright (C) 2019-2021, Ampere Computing LLC * + * * * 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 * @@ -86,7 +88,7 @@ uint32_t tar_block_size(uint32_t address) Return the largest block starting at address that does not cross a tar block size alignment boundary */ -static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address) +static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, target_addr_t address) { return tar_autoincr_block - ((tar_autoincr_block - 1) & address); } @@ -113,11 +115,16 @@ static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw) return ERROR_OK; } -static int mem_ap_setup_tar(struct adiv5_ap *ap, uint32_t tar) +static int mem_ap_setup_tar(struct adiv5_ap *ap, target_addr_t tar) { if (!ap->tar_valid || tar != ap->tar_value) { /* LOG_DEBUG("DAP: Set TAR %x",tar); */ - int retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR, tar); + int retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR, (uint32_t)(tar & 0xffffffffUL)); + if (retval == ERROR_OK && is_64bit_ap(ap)) { + /* See if bits 63:32 of tar is different from last setting */ + if ((ap->tar_value >> 32) != (tar >> 32)) + retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR64, (uint32_t)(tar >> 32)); + } if (retval != ERROR_OK) { ap->tar_valid = false; return retval; @@ -128,9 +135,15 @@ static int mem_ap_setup_tar(struct adiv5_ap *ap, uint32_t tar) return ERROR_OK; } -static int mem_ap_read_tar(struct adiv5_ap *ap, uint32_t *tar) +static int mem_ap_read_tar(struct adiv5_ap *ap, target_addr_t *tar) { - int retval = dap_queue_ap_read(ap, MEM_AP_REG_TAR, tar); + uint32_t lower; + uint32_t upper = 0; + + int retval = dap_queue_ap_read(ap, MEM_AP_REG_TAR, &lower); + if (retval == ERROR_OK && is_64bit_ap(ap)) + retval = dap_queue_ap_read(ap, MEM_AP_REG_TAR64, &upper); + if (retval != ERROR_OK) { ap->tar_valid = false; return retval; @@ -142,6 +155,8 @@ static int mem_ap_read_tar(struct adiv5_ap *ap, uint32_t *tar) return retval; } + *tar = (((target_addr_t)upper) << 32) | (target_addr_t)lower; + ap->tar_value = *tar; ap->tar_valid = true; return ERROR_OK; @@ -198,7 +213,7 @@ static void mem_ap_update_tar_cache(struct adiv5_ap *ap) * * @return ERROR_OK if the transaction was properly queued, else a fault code. */ -static int mem_ap_setup_transfer(struct adiv5_ap *ap, uint32_t csw, uint32_t tar) +static int mem_ap_setup_transfer(struct adiv5_ap *ap, uint32_t csw, target_addr_t tar) { int retval; retval = mem_ap_setup_csw(ap, csw); @@ -221,7 +236,7 @@ static int mem_ap_setup_transfer(struct adiv5_ap *ap, uint32_t csw, uint32_t tar * * @return ERROR_OK for success. Otherwise a fault code. */ -int mem_ap_read_u32(struct adiv5_ap *ap, uint32_t address, +int mem_ap_read_u32(struct adiv5_ap *ap, target_addr_t address, uint32_t *value) { int retval; @@ -231,7 +246,7 @@ int mem_ap_read_u32(struct adiv5_ap *ap, uint32_t address, */ retval = mem_ap_setup_transfer(ap, CSW_32BIT | (ap->csw_value & CSW_ADDRINC_MASK), - address & 0xFFFFFFF0); + address & 0xFFFFFFFFFFFFFFF0ull); if (retval != ERROR_OK) return retval; @@ -250,7 +265,7 @@ int mem_ap_read_u32(struct adiv5_ap *ap, uint32_t address, * @return ERROR_OK for success; *value holds the result. * Otherwise a fault code. */ -int mem_ap_read_atomic_u32(struct adiv5_ap *ap, uint32_t address, +int mem_ap_read_atomic_u32(struct adiv5_ap *ap, target_addr_t address, uint32_t *value) { int retval; @@ -273,7 +288,7 @@ int mem_ap_read_atomic_u32(struct adiv5_ap *ap, uint32_t address, * * @return ERROR_OK for success. Otherwise a fault code. */ -int mem_ap_write_u32(struct adiv5_ap *ap, uint32_t address, +int mem_ap_write_u32(struct adiv5_ap *ap, target_addr_t address, uint32_t value) { int retval; @@ -283,7 +298,7 @@ int mem_ap_write_u32(struct adiv5_ap *ap, uint32_t address, */ retval = mem_ap_setup_transfer(ap, CSW_32BIT | (ap->csw_value & CSW_ADDRINC_MASK), - address & 0xFFFFFFF0); + address & 0xFFFFFFFFFFFFFFF0ull); if (retval != ERROR_OK) return retval; @@ -302,7 +317,7 @@ int mem_ap_write_u32(struct adiv5_ap *ap, uint32_t address, * * @return ERROR_OK for success; the data was written. Otherwise a fault code. */ -int mem_ap_write_atomic_u32(struct adiv5_ap *ap, uint32_t address, +int mem_ap_write_atomic_u32(struct adiv5_ap *ap, target_addr_t address, uint32_t value) { int retval = mem_ap_write_u32(ap, address, value); @@ -326,13 +341,13 @@ int mem_ap_write_atomic_u32(struct adiv5_ap *ap, uint32_t address, * @return ERROR_OK on success, otherwise an error code. */ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t size, uint32_t count, - uint32_t address, bool addrinc) + target_addr_t address, bool addrinc) { struct adiv5_dap *dap = ap->dap; size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; - uint32_t addr_xor; + target_addr_t addr_xor; int retval = ERROR_OK; /* TI BE-32 Quirks mode: @@ -433,9 +448,9 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz retval = dap_run(dap); if (retval != ERROR_OK) { - uint32_t tar; + target_addr_t tar; if (mem_ap_read_tar(ap, &tar) == ERROR_OK) - LOG_ERROR("Failed to write memory at 0x%08"PRIx32, tar); + LOG_ERROR("Failed to write memory at " TARGET_ADDR_FMT, tar); else LOG_ERROR("Failed to write memory and, additionally, failed to find out where"); } @@ -456,13 +471,13 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz * @return ERROR_OK on success, otherwise an error code. */ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint32_t count, - uint32_t adr, bool addrinc) + target_addr_t adr, bool addrinc) { struct adiv5_dap *dap = ap->dap; size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; - uint32_t address = adr; + target_addr_t address = adr; int retval = ERROR_OK; /* TI BE-32 Quirks mode: @@ -538,10 +553,10 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint /* If something failed, read TAR to find out how much data was successfully read, so we can * at least give the caller what we have. */ if (retval != ERROR_OK) { - uint32_t tar; + target_addr_t tar; if (mem_ap_read_tar(ap, &tar) == ERROR_OK) { /* TAR is incremented after failed transfer on some devices (eg Cortex-M4) */ - LOG_ERROR("Failed to read memory at 0x%08"PRIx32, tar); + LOG_ERROR("Failed to read memory at " TARGET_ADDR_FMT, tar); if (nbytes > tar - address) nbytes = tar - address; } else { @@ -594,25 +609,25 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint } int mem_ap_read_buf(struct adiv5_ap *ap, - uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) + uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address) { return mem_ap_read(ap, buffer, size, count, address, true); } int mem_ap_write_buf(struct adiv5_ap *ap, - const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) + const uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address) { return mem_ap_write(ap, buffer, size, count, address, true); } int mem_ap_read_buf_noincr(struct adiv5_ap *ap, - uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) + uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address) { return mem_ap_read(ap, buffer, size, count, address, false); } int mem_ap_write_buf_noincr(struct adiv5_ap *ap, - const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) + const uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address) { return mem_ap_write(ap, buffer, size, count, address, false); } @@ -761,6 +776,17 @@ int mem_ap_init(struct adiv5_ap *ap) int retval; struct adiv5_dap *dap = ap->dap; + /* Set ap->cfg_reg before calling mem_ap_setup_transfer(). */ + /* mem_ap_setup_transfer() needs to know if the MEM_AP supports LPAE. */ + retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &cfg); + if (retval != ERROR_OK) + return retval; + + retval = dap_run(dap); + if (retval != ERROR_OK) + return retval; + + ap->cfg_reg = cfg; ap->tar_valid = false; ap->csw_value = 0; /* force csw and tar write */ retval = mem_ap_setup_transfer(ap, CSW_8BIT | CSW_ADDRINC_PACKED, 0); @@ -771,10 +797,6 @@ int mem_ap_init(struct adiv5_ap *ap) if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &cfg); - if (retval != ERROR_OK) - return retval; - retval = dap_run(dap); if (retval != ERROR_OK) return retval; @@ -801,7 +823,7 @@ int mem_ap_init(struct adiv5_ap *ap) ap->unaligned_access_bad = dap->ti_be_32_quirks; LOG_DEBUG("MEM_AP CFG: large data %d, long address %d, big-endian %d", - !!(cfg & 0x04), !!(cfg & 0x02), !!(cfg & 0x01)); + !!(cfg & MEM_AP_REG_CFG_LD), !!(cfg & MEM_AP_REG_CFG_LA), !!(cfg & MEM_AP_REG_CFG_BE)); return ERROR_OK; } @@ -918,12 +940,22 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a } int dap_get_debugbase(struct adiv5_ap *ap, - uint32_t *dbgbase, uint32_t *apid) + target_addr_t *dbgbase, uint32_t *apid) { struct adiv5_dap *dap = ap->dap; int retval; + uint32_t baseptr_upper, baseptr_lower; + + baseptr_upper = 0; + + if (is_64bit_ap(ap)) { + /* Read higher order 32-bits of base address */ + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64, &baseptr_upper); + if (retval != ERROR_OK) + return retval; + } - retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, dbgbase); + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseptr_lower); if (retval != ERROR_OK) return retval; retval = dap_queue_ap_read(ap, AP_REG_IDR, apid); @@ -933,31 +965,34 @@ int dap_get_debugbase(struct adiv5_ap *ap, if (retval != ERROR_OK) return retval; + *dbgbase = (((target_addr_t)baseptr_upper) << 32) | baseptr_lower; + return ERROR_OK; } int dap_lookup_cs_component(struct adiv5_ap *ap, - uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx) + target_addr_t dbgbase, uint8_t type, target_addr_t *addr, int32_t *idx) { - uint32_t romentry, entry_offset = 0, component_base, devtype; + uint32_t romentry, entry_offset = 0, devtype; + target_addr_t component_base; int retval; + dbgbase &= 0xFFFFFFFFFFFFF000ull; *addr = 0; do { - retval = mem_ap_read_atomic_u32(ap, (dbgbase&0xFFFFF000) | + retval = mem_ap_read_atomic_u32(ap, dbgbase | entry_offset, &romentry); if (retval != ERROR_OK) return retval; - component_base = (dbgbase & 0xFFFFF000) - + (romentry & 0xFFFFF000); + component_base = dbgbase + (target_addr_t)(romentry & 0xFFFFF000); if (romentry & 0x1) { uint32_t c_cid1; retval = mem_ap_read_atomic_u32(ap, component_base | 0xff4, &c_cid1); if (retval != ERROR_OK) { - LOG_ERROR("Can't read component with base address 0x%" PRIx32 + LOG_ERROR("Can't read component with base address " TARGET_ADDR_FMT ", the corresponding core might be turned off", component_base); return retval; } @@ -970,9 +1005,7 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, return retval; } - retval = mem_ap_read_atomic_u32(ap, - (component_base & 0xfffff000) | 0xfcc, - &devtype); + retval = mem_ap_read_atomic_u32(ap, component_base | 0xfcc, &devtype); if (retval != ERROR_OK) return retval; if ((devtype & 0xff) == type) { @@ -984,7 +1017,7 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, } } entry_offset += 4; - } while (romentry > 0); + } while ((romentry > 0) && (entry_offset < 0xf00)); if (!*addr) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -992,7 +1025,7 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, return ERROR_OK; } -static int dap_read_part_id(struct adiv5_ap *ap, uint32_t component_base, uint32_t *cid, uint64_t *pid) +static int dap_read_part_id(struct adiv5_ap *ap, target_addr_t component_base, uint32_t *cid, uint64_t *pid) { assert((component_base & 0xFFF) == 0); assert(ap != NULL && cid != NULL && pid != NULL); @@ -1179,7 +1212,7 @@ static const struct { }; static int dap_rom_display(struct command_invocation *cmd, - struct adiv5_ap *ap, uint32_t dbgbase, int depth) + struct adiv5_ap *ap, target_addr_t dbgbase, int depth) { int retval; uint64_t pid; @@ -1194,8 +1227,8 @@ static int dap_rom_display(struct command_invocation *cmd, if (depth) snprintf(tabs, sizeof(tabs), "[L%02d] ", depth); - uint32_t base_addr = dbgbase & 0xFFFFF000; - command_print(cmd, "\t\tComponent base address 0x%08" PRIx32, base_addr); + target_addr_t base_addr = dbgbase & 0xFFFFFFFFFFFFF000ull; + command_print(cmd, "\t\tComponent base address " TARGET_ADDR_FMT, base_addr); retval = dap_read_part_id(ap, base_addr, &cid, &pid); if (retval != ERROR_OK) { @@ -1211,7 +1244,7 @@ static int dap_rom_display(struct command_invocation *cmd, /* component may take multiple 4K pages */ uint32_t size = (pid >> 36) & 0xf; if (size > 0) - command_print(cmd, "\t\tStart address 0x%08" PRIx32, (uint32_t)(base_addr - 0x1000 * size)); + command_print(cmd, "\t\tStart address " TARGET_ADDR_FMT, base_addr - 0x1000 * size); command_print(cmd, "\t\tPeripheral ID 0x%010" PRIx64, pid); @@ -1436,7 +1469,9 @@ int dap_info_command(struct command_invocation *cmd, struct adiv5_ap *ap) { int retval; - uint32_t dbgbase, apid; + uint32_t apid; + target_addr_t dbgbase; + target_addr_t dbgaddr; uint8_t mem_ap; /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ @@ -1476,9 +1511,14 @@ int dap_info_command(struct command_invocation *cmd, */ mem_ap = (apid & IDR_CLASS) == AP_CLASS_MEM_AP; if (mem_ap) { - command_print(cmd, "MEM-AP BASE 0x%8.8" PRIx32, dbgbase); + if (is_64bit_ap(ap)) + dbgaddr = 0xFFFFFFFFFFFFFFFFull; + else + dbgaddr = 0xFFFFFFFFul; - if (dbgbase == 0xFFFFFFFF || (dbgbase & 0x3) == 0x2) { + command_print(cmd, "MEM-AP BASE " TARGET_ADDR_FMT, dbgbase); + + if (dbgbase == dbgaddr || (dbgbase & 0x3) == 0x2) { command_print(cmd, "\tNo ROM table present"); } else { if (dbgbase & 0x01) @@ -1486,7 +1526,7 @@ int dap_info_command(struct command_invocation *cmd, else command_print(cmd, "\tROM table in legacy format"); - dap_rom_display(cmd, ap, dbgbase & 0xFFFFF000, 0); + dap_rom_display(cmd, ap, dbgbase & 0xFFFFFFFFFFFFF000ull, 0); } } @@ -1690,9 +1730,13 @@ COMMAND_HANDLER(handle_dap_info_command) COMMAND_HANDLER(dap_baseaddr_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); - uint32_t apsel, baseaddr; + uint32_t apsel, baseaddr_lower, baseaddr_upper; + struct adiv5_ap *ap; + target_addr_t baseaddr; int retval; + baseaddr_upper = 0; + switch (CMD_ARGC) { case 0: apsel = dap->apsel; @@ -1714,14 +1758,22 @@ COMMAND_HANDLER(dap_baseaddr_command) * though they're not common for now. This should * use the ID register to verify it's a MEM-AP. */ - retval = dap_queue_ap_read(dap_ap(dap, apsel), MEM_AP_REG_BASE, &baseaddr); + + ap = dap_ap(dap, apsel); + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseaddr_lower); + + if (is_64bit_ap(ap) && retval == ERROR_OK) + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64, &baseaddr_upper); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; - - command_print(CMD, "0x%8.8" PRIx32, baseaddr); + if (is_64bit_ap(ap)) { + baseaddr = (((target_addr_t)baseaddr_upper) << 32) | baseaddr_lower; + command_print(CMD, "0x%016" PRIx64, baseaddr); + } else + command_print(CMD, "0x%08" PRIx32, baseaddr_lower); return retval; } @@ -1885,8 +1937,25 @@ COMMAND_HANDLER(dap_apreg_command) ap->csw_value = value; break; case MEM_AP_REG_TAR: - ap->tar_valid = false; /* invalid, force write */ - retval = mem_ap_setup_tar(ap, value); + retval = dap_queue_ap_write(ap, reg, value); + if (retval == ERROR_OK) + ap->tar_value = (ap->tar_value & ~0xFFFFFFFFull) | value; + else { + /* To track independent writes to TAR and TAR64, two tar_valid flags */ + /* should be used. To keep it simple, tar_valid is only invalidated on a */ + /* write fail. This approach causes a later re-write of the TAR and TAR64 */ + /* if tar_valid is false. */ + ap->tar_valid = false; + } + break; + case MEM_AP_REG_TAR64: + retval = dap_queue_ap_write(ap, reg, value); + if (retval == ERROR_OK) + ap->tar_value = (ap->tar_value & 0xFFFFFFFFull) | (((target_addr_t)value) << 32); + else { + /* See above comment for the MEM_AP_REG_TAR failed write case */ + ap->tar_valid = false; + } break; default: retval = dap_queue_ap_write(ap, reg, value); diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index ce9155ae7f..7eb44f2ed5 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -31,6 +31,7 @@ #include #include "arm_jtag.h" +#include "helper/bits.h" /* three-bit ACK values for SWD access (sent LSB first) */ #define SWD_ACK_OK 0x1 @@ -149,6 +150,10 @@ /* APB: initial value of csw_default */ #define CSW_APB_DEFAULT (CSW_DBGSWENABLE) +/* Fields of the MEM-AP's CFG register */ +#define MEM_AP_REG_CFG_BE BIT(0) +#define MEM_AP_REG_CFG_LA BIT(1) +#define MEM_AP_REG_CFG_LD BIT(2) /* Fields of the MEM-AP's IDR register */ #define IDR_REV (0xFUL << 28) @@ -201,7 +206,7 @@ struct adiv5_ap { * configure the address being read or written * "-1" indicates no cached value. */ - uint32_t tar_value; + target_addr_t tar_value; /** * Configures how many extra tck clocks are added after starting a @@ -220,6 +225,9 @@ struct adiv5_ap { /* true if tar_value is in sync with TAR register */ bool tar_valid; + + /* MEM AP configuration register indicating LPAE support */ + uint32_t cfg_reg; }; @@ -359,6 +367,20 @@ enum ap_type { AP_TYPE_AHB5_AP = 0x5, /* AHB5 Memory-AP. */ }; +/* Check the ap->cfg_reg Long Address field (bit 1) + * + * 0b0: The AP only supports physical addresses 32 bits or smaller + * 0b1: The AP supports physical addresses larger than 32 bits + * + * @param ap The AP used for reading. + * + * @return true for 64 bit, false for 32 bit + */ +static inline bool is_64bit_ap(struct adiv5_ap *ap) +{ + return (ap->cfg_reg & MEM_AP_REG_CFG_LA) != 0; +} + /** * Send an adi-v5 sequence to the DAP. * @@ -528,27 +550,27 @@ static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned reg, /* Queued MEM-AP memory mapped single word transfers. */ int mem_ap_read_u32(struct adiv5_ap *ap, - uint32_t address, uint32_t *value); + target_addr_t address, uint32_t *value); int mem_ap_write_u32(struct adiv5_ap *ap, - uint32_t address, uint32_t value); + target_addr_t address, uint32_t value); /* Synchronous MEM-AP memory mapped single word transfers. */ int mem_ap_read_atomic_u32(struct adiv5_ap *ap, - uint32_t address, uint32_t *value); + target_addr_t address, uint32_t *value); int mem_ap_write_atomic_u32(struct adiv5_ap *ap, - uint32_t address, uint32_t value); + target_addr_t address, uint32_t value); /* Synchronous MEM-AP memory mapped bus block transfers. */ int mem_ap_read_buf(struct adiv5_ap *ap, - uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address); + uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address); int mem_ap_write_buf(struct adiv5_ap *ap, - const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address); + const uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address); /* Synchronous, non-incrementing buffer functions for accessing fifos. */ int mem_ap_read_buf_noincr(struct adiv5_ap *ap, - uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address); + uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address); int mem_ap_write_buf_noincr(struct adiv5_ap *ap, - const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address); + const uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address); /* Initialisation of the debug system, power domains and registers */ int dap_dp_init(struct adiv5_dap *dap); @@ -560,7 +582,7 @@ void dap_invalidate_cache(struct adiv5_dap *dap); /* Probe the AP for ROM Table location */ int dap_get_debugbase(struct adiv5_ap *ap, - uint32_t *dbgbase, uint32_t *apid); + target_addr_t *dbgbase, uint32_t *apid); /* Probe Access Ports to find a particular type */ int dap_find_ap(struct adiv5_dap *dap, @@ -574,7 +596,7 @@ static inline struct adiv5_ap *dap_ap(struct adiv5_dap *dap, uint8_t ap_num) /* Lookup CoreSight component */ int dap_lookup_cs_component(struct adiv5_ap *ap, - uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx); + target_addr_t dbgbase, uint8_t type, target_addr_t *addr, int32_t *idx); struct target; diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 747733dc94..87e232af8b 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -36,6 +36,8 @@ extern const struct dap_ops swd_dap_ops; extern const struct dap_ops jtag_dp_ops; extern struct adapter_driver *adapter_driver; +#define ADI_BAD_CFG 0xBAD00000 + /* DAP command support */ struct arm_dap_object { struct list_head lh; @@ -57,6 +59,7 @@ static void dap_instance_init(struct adiv5_dap *dap) dap->ap[i].tar_autoincr_block = (1<<10); /* default CSW value */ dap->ap[i].csw_default = CSW_AHB_DEFAULT; + dap->ap[i].cfg_reg = ADI_BAD_CFG; /* mem_ap configuration reg (large physical addr, etc.) */ } INIT_LIST_HEAD(&dap->cmd_journal); INIT_LIST_HEAD(&dap->cmd_pool); diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 7b62198218..c282554a5e 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -104,7 +104,7 @@ struct armv7a_common { /* Core Debug Unit */ struct arm_dpm dpm; - uint32_t debug_base; + target_addr_t debug_base; struct adiv5_ap *debug_ap; /* mdir */ uint8_t multi_processor_system; diff --git a/src/target/armv8.h b/src/target/armv8.h index f09f3abfdb..c30739c8c5 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -196,7 +196,7 @@ struct armv8_common { /* Core Debug Unit */ struct arm_dpm dpm; - uint32_t debug_base; + target_addr_t debug_base; struct adiv5_ap *debug_ap; const uint32_t *opcodes; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 7af0d3d7ee..2e810b5dbb 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2907,7 +2907,7 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_ap->memaccess_tck = 80; if (!target->dbgbase_set) { - uint32_t dbgbase; + target_addr_t dbgbase; /* Get ROM Table base */ uint32_t apid; int32_t coreidx = target->coreid; @@ -2924,7 +2924,7 @@ static int cortex_a_examine_first(struct target *target) target->cmd_name); return retval; } - LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32, + LOG_DEBUG("Detected core %" PRId32 " dbgbase: " TARGET_ADDR_FMT, target->coreid, armv7a->debug_base); } else armv7a->debug_base = target->dbgbase; -- 2.30.2