314 lines
10 KiB
C
314 lines
10 KiB
C
/*
|
|
* This file is part of the Black Magic Debug project.
|
|
*
|
|
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
|
*
|
|
* 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 3 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 __ADIV5_H
|
|
#define __ADIV5_H
|
|
|
|
#include "jtag_scan.h"
|
|
|
|
#define ADIV5_APnDP 0x100
|
|
#define ADIV5_DP_REG(x) (x)
|
|
#define ADIV5_AP_REG(x) (ADIV5_APnDP | (x))
|
|
|
|
#define ADIV5_DP_BANK0 0x00
|
|
#define ADIV5_DP_BANK1 0x10
|
|
#define ADIV5_DP_BANK2 0x20
|
|
#define ADIV5_DP_BANK3 0x30
|
|
#define ADIV5_DP_BANK4 0x40
|
|
|
|
/* ADIv5 DP Register addresses */
|
|
#define ADIV5_DP_IDCODE ADIV5_DP_REG(0x0)
|
|
#define ADIV5_DP_ABORT ADIV5_DP_REG(0x0)
|
|
#define ADIV5_DP_CTRLSTAT ADIV5_DP_REG(0x4)
|
|
#define ADIV5_DP_TARGETID (ADIV5_DP_BANK2 | ADIV5_DP_REG(0x4))
|
|
#define ADIV5_DP_SELECT ADIV5_DP_REG(0x8)
|
|
#define ADIV5_DP_RDBUFF ADIV5_DP_REG(0xC)
|
|
#define ADIV5_DP_TARGETSEL ADIV5_DP_REG(0xC)
|
|
|
|
#define ADIV5_DP_VERSION_MASK 0xf000
|
|
#define ADIV5_DPv1 0x1000
|
|
#define ADIV5_DPv2 0x2000
|
|
#define ADIV5_MINDP 0x10000
|
|
|
|
/* AP Abort Register (ABORT) */
|
|
/* Bits 31:5 - Reserved */
|
|
#define ADIV5_DP_ABORT_ORUNERRCLR (1 << 4)
|
|
#define ADIV5_DP_ABORT_WDERRCLR (1 << 3)
|
|
#define ADIV5_DP_ABORT_STKERRCLR (1 << 2)
|
|
#define ADIV5_DP_ABORT_STKCMPCLR (1 << 1)
|
|
/* Bits 5:1 - SW-DP only, reserved in JTAG-DP */
|
|
#define ADIV5_DP_ABORT_DAPABORT (1 << 0)
|
|
|
|
/* Control/Status Register (CTRLSTAT) */
|
|
#define ADIV5_DP_CTRLSTAT_CSYSPWRUPACK (1u << 31)
|
|
#define ADIV5_DP_CTRLSTAT_CSYSPWRUPREQ (1u << 30)
|
|
#define ADIV5_DP_CTRLSTAT_CDBGPWRUPACK (1u << 29)
|
|
#define ADIV5_DP_CTRLSTAT_CDBGPWRUPREQ (1u << 28)
|
|
#define ADIV5_DP_CTRLSTAT_CDBGRSTACK (1u << 27)
|
|
#define ADIV5_DP_CTRLSTAT_CDBGRSTREQ (1u << 26)
|
|
/* Bits 25:24 - Reserved */
|
|
/* Bits 23:12 - TRNCNT */
|
|
#define ADIV5_DP_CTRLSTAT_TRNCNT (1u << 12)
|
|
/* Bits 11:8 - MASKLANE */
|
|
#define ADIV5_DP_CTRLSTAT_MASKLANE
|
|
/* Bits 7:6 - Reserved in JTAG-DP */
|
|
#define ADIV5_DP_CTRLSTAT_WDATAERR (1u << 7)
|
|
#define ADIV5_DP_CTRLSTAT_READOK (1u << 6)
|
|
#define ADIV5_DP_CTRLSTAT_STICKYERR (1u << 5)
|
|
#define ADIV5_DP_CTRLSTAT_STICKYCMP (1u << 4)
|
|
#define ADIV5_DP_CTRLSTAT_TRNMODE_MASK (3u << 2)
|
|
#define ADIV5_DP_CTRLSTAT_STICKYORUN (1u << 1)
|
|
#define ADIV5_DP_CTRLSTAT_ORUNDETECT (1u << 0)
|
|
|
|
|
|
/* ADIv5 MEM-AP Registers */
|
|
#define ADIV5_AP_CSW ADIV5_AP_REG(0x00)
|
|
#define ADIV5_AP_TAR ADIV5_AP_REG(0x04)
|
|
/* 0x08 - Reserved */
|
|
#define ADIV5_AP_DRW ADIV5_AP_REG(0x0C)
|
|
#define ADIV5_AP_DB(x) ADIV5_AP_REG(0x10 + (4*(x)))
|
|
/* 0x20:0xF0 - Reserved */
|
|
#define ADIV5_AP_CFG ADIV5_AP_REG(0xF4)
|
|
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
|
|
#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC)
|
|
|
|
/* Known designers seen in SYSROM-PIDR. Ignore Bit 0 from
|
|
* the designer bits to get JEDEC Ids with bit 7 ignored.*/
|
|
#define AP_DESIGNER_FREESCALE 0x00e
|
|
#define AP_DESIGNER_TEXAS 0x017
|
|
#define AP_DESIGNER_ATMEL 0x01f
|
|
#define AP_DESIGNER_STM 0x020
|
|
#define AP_DESIGNER_CYPRESS 0x034
|
|
#define AP_DESIGNER_INFINEON 0x041
|
|
#define AP_DESIGNER_NORDIC 0x244
|
|
#define AP_DESIGNER_ARM 0x43b
|
|
/*LPC845 with designer 501. Strange!? */
|
|
#define AP_DESIGNER_SPECULAR 0x501
|
|
#define AP_DESIGNER_CS 0x555
|
|
#define AP_DESIGNER_ENERGY_MICRO 0x673
|
|
#define AP_DESIGNER_GIGADEVICE 0x751
|
|
#define AP_DESIGNER_RASPBERRY 0x927
|
|
|
|
/* AP Control and Status Word (CSW) */
|
|
#define ADIV5_AP_CSW_DBGSWENABLE (1u << 31)
|
|
/* Bits 30:24 - Prot, Implementation defined, for Cortex-M3: */
|
|
#define ADIV5_AP_CSW_MASTERTYPE_DEBUG (1u << 29)
|
|
#define ADIV5_AP_CSW_HPROT1 (1u << 25)
|
|
#define ADIV5_AP_CSW_SPIDEN (1u << 23)
|
|
/* Bits 22:12 - Reserved */
|
|
/* Bits 11:8 - Mode, must be zero */
|
|
#define ADIV5_AP_CSW_TRINPROG (1u << 7)
|
|
#define ADIV5_AP_CSW_DEVICEEN (1u << 6)
|
|
#define ADIV5_AP_CSW_ADDRINC_NONE (0u << 4)
|
|
#define ADIV5_AP_CSW_ADDRINC_SINGLE (1u << 4)
|
|
#define ADIV5_AP_CSW_ADDRINC_PACKED (2u << 4)
|
|
#define ADIV5_AP_CSW_ADDRINC_MASK (3u << 4)
|
|
/* Bit 3 - Reserved */
|
|
#define ADIV5_AP_CSW_SIZE_BYTE (0u << 0)
|
|
#define ADIV5_AP_CSW_SIZE_HALFWORD (1u << 0)
|
|
#define ADIV5_AP_CSW_SIZE_WORD (2u << 0)
|
|
#define ADIV5_AP_CSW_SIZE_MASK (7u << 0)
|
|
|
|
/* AP Debug Base Address Register (BASE) */
|
|
#define ADIV5_AP_BASE_BASEADDR (0xFFFFF000u)
|
|
#define ADIV5_AP_BASE_PRESENT (1u << 0)
|
|
|
|
|
|
/* ADIv5 Class 0x1 ROM Table Registers */
|
|
#define ADIV5_ROM_MEMTYPE 0xFCC
|
|
#define ADIV5_ROM_MEMTYPE_SYSMEM (1u << 0)
|
|
#define ADIV5_ROM_ROMENTRY_PRESENT (1u << 0)
|
|
#define ADIV5_ROM_ROMENTRY_OFFSET (0xFFFFF000u)
|
|
|
|
|
|
/* Constants to make RnW parameters more clear in code */
|
|
#define ADIV5_LOW_WRITE 0
|
|
#define ADIV5_LOW_READ 1
|
|
|
|
#define SWDP_ACK_OK 0x01
|
|
#define SWDP_ACK_WAIT 0x02
|
|
#define SWDP_ACK_FAULT 0x04
|
|
|
|
enum align {
|
|
ALIGN_BYTE = 0,
|
|
ALIGN_HALFWORD = 1,
|
|
ALIGN_WORD = 2,
|
|
ALIGN_DWORD = 3
|
|
};
|
|
|
|
typedef struct ADIv5_AP_s ADIv5_AP_t;
|
|
|
|
/* Try to keep this somewhat absract for later adding SW-DP */
|
|
typedef struct ADIv5_DP_s {
|
|
int refcnt;
|
|
|
|
uint32_t idcode;
|
|
uint32_t targetid; /* Contains IDCODE for DPv2 devices.*/
|
|
|
|
void (*seq_out)(uint32_t MS, int ticks);
|
|
void (*seq_out_parity)(uint32_t MS, int ticks);
|
|
uint32_t (*seq_in)(int ticks);
|
|
bool (*seq_in_parity)(uint32_t *ret, int ticks);
|
|
/* dp_low_write returns true if no OK resonse, but ignores errors */
|
|
bool (*dp_low_write)(struct ADIv5_DP_s *dp, uint16_t addr,
|
|
const uint32_t data);
|
|
uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint16_t addr);
|
|
uint32_t (*error)(struct ADIv5_DP_s *dp);
|
|
uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t RnW,
|
|
uint16_t addr, uint32_t value);
|
|
void (*abort)(struct ADIv5_DP_s *dp, uint32_t abort);
|
|
|
|
#if PC_HOSTED == 1
|
|
bmp_type_t dp_bmp_type;
|
|
bool (*ap_setup)(int i);
|
|
void (*ap_cleanup)(int i);
|
|
void (*ap_regs_read)(ADIv5_AP_t *ap, void *data);
|
|
uint32_t(*ap_reg_read)(ADIv5_AP_t *ap, int num);
|
|
void (*ap_reg_write)(ADIv5_AP_t *ap, int num, uint32_t value);
|
|
void (*read_block)(uint32_t addr, uint8_t *data, int size);
|
|
void (*dap_write_block_sized)(uint32_t addr, uint8_t *data,
|
|
int size, enum align align);
|
|
#endif
|
|
uint32_t (*ap_read)(ADIv5_AP_t *ap, uint16_t addr);
|
|
void (*ap_write)(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
|
|
|
|
void (*mem_read)(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len);
|
|
void (*mem_write_sized)(ADIv5_AP_t *ap, uint32_t dest, const void *src,
|
|
size_t len, enum align align);
|
|
uint8_t dp_jd_index;
|
|
uint8_t fault;
|
|
} ADIv5_DP_t;
|
|
|
|
struct ADIv5_AP_s {
|
|
int refcnt;
|
|
|
|
ADIv5_DP_t *dp;
|
|
uint8_t apsel;
|
|
|
|
uint32_t idr;
|
|
uint32_t base;
|
|
uint32_t csw;
|
|
uint32_t ap_cortexm_demcr; /* Copy of demcr when starting */
|
|
uint32_t ap_storage; /* E.g to hold STM32F7 initial DBGMCU_CR value.*/
|
|
uint16_t ap_designer;
|
|
uint16_t ap_partno;
|
|
};
|
|
|
|
unsigned int make_packet_request(uint8_t RnW, uint16_t addr);
|
|
|
|
#if PC_HOSTED == 0
|
|
static inline uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr)
|
|
{
|
|
return dp->dp_read(dp, addr);
|
|
}
|
|
|
|
static inline uint32_t adiv5_dp_error(ADIv5_DP_t *dp)
|
|
{
|
|
return dp->error(dp);
|
|
}
|
|
|
|
static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
|
|
uint16_t addr, uint32_t value)
|
|
{
|
|
return dp->low_access(dp, RnW, addr, value);
|
|
}
|
|
|
|
static inline void adiv5_dp_abort(struct ADIv5_DP_s *dp, uint32_t abort)
|
|
{
|
|
return dp->abort(dp, abort);
|
|
}
|
|
|
|
static inline uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
|
|
{
|
|
return ap->dp->ap_read(ap, addr);
|
|
}
|
|
|
|
static inline void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
|
|
{
|
|
return ap->dp->ap_write(ap, addr, value);
|
|
}
|
|
|
|
static inline void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src,
|
|
size_t len)
|
|
{
|
|
return ap->dp->mem_read(ap, dest, src, len);
|
|
}
|
|
|
|
static inline void adiv5_mem_write_sized(
|
|
ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len,
|
|
enum align align)
|
|
{
|
|
return ap->dp->mem_write_sized(ap, dest, src, len, align);
|
|
}
|
|
|
|
static inline void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value)
|
|
{
|
|
dp->low_access(dp, ADIV5_LOW_WRITE, addr, value);
|
|
}
|
|
|
|
#else
|
|
uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr);
|
|
uint32_t adiv5_dp_error(ADIv5_DP_t *dp);
|
|
uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
|
|
uint16_t addr, uint32_t value);
|
|
void adiv5_dp_abort(struct ADIv5_DP_s *dp, uint32_t abort);
|
|
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr);
|
|
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
|
|
void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len);
|
|
void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest,
|
|
const void *src, size_t len, enum align align);
|
|
void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value);
|
|
#endif
|
|
|
|
void adiv5_dp_init(ADIv5_DP_t *dp);
|
|
void platform_adiv5_dp_defaults(ADIv5_DP_t *dp);
|
|
ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel);
|
|
void remote_jtag_dev(const jtag_dev_t *jtag_dev);
|
|
void adiv5_ap_ref(ADIv5_AP_t *ap);
|
|
void adiv5_ap_unref(ADIv5_AP_t *ap);
|
|
void platform_add_jtag_dev(const int dev_index, const jtag_dev_t *jtag_dev);
|
|
|
|
void adiv5_jtag_dp_handler(uint8_t jd_index);
|
|
int platform_jtag_dp_init(ADIv5_DP_t *dp);
|
|
int swdptap_init(ADIv5_DP_t *dp);
|
|
|
|
void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len);
|
|
uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr);
|
|
void * extract(void *dest, uint32_t src, uint32_t val, enum align align);
|
|
|
|
void firmware_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
|
|
size_t len, enum align align);
|
|
void firmware_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src,
|
|
size_t len);
|
|
void firmware_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
|
|
uint32_t firmware_ap_read(ADIv5_AP_t *ap, uint16_t addr);
|
|
uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
|
uint16_t addr, uint32_t value);
|
|
uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
|
uint16_t addr, uint32_t value);
|
|
uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr);
|
|
uint32_t fw_adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr);
|
|
|
|
uint32_t firmware_swdp_error(ADIv5_DP_t *dp);
|
|
|
|
void firmware_swdp_abort(ADIv5_DP_t *dp, uint32_t abort);
|
|
void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort);
|
|
#endif
|