bfin: add support for using ITEST MMRs to access memory regions which DTEST MMRs cannot

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1936 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Mike Frysinger 13 years ago
parent 44d5afb3a3
commit df1a7602ec

@ -43,6 +43,11 @@
* src/cmd/cmd_debug.c: Drop local log level converters and use new
common helpers.
* include/urjtag/bfin.h, src/bfin/bfin-part-bfin.c: Rewrite test_command
support to dynamically look up the set of MMRs needed in order to access
the requested memory. Some parts can only use ITEST, so hardcoding the
DTEST MMRs no longer works.
2011-06-27 Jie Zhang <jie.zhang@analog.com>
* include/urjtag/Makefile.am (nodist_pkginclude_HEADERS): New and

@ -75,17 +75,15 @@ struct emu_oab
void (*dbgctl_init) (urj_part_t *part, uint16_t value);
uint16_t (*dbgstat_value) (urj_part_t *part);
/* Generate TEST_COMMAND from ADDR and W(rite). */
uint32_t (*test_command) (uint32_t addr, int w);
/* For existing Blackfin processors, it's actually DTEST_COMMAND
address. */
uint32_t test_command_addr;
/* For existing Blackfin processors, they are actually DTEST_DATA
addresses. */
uint32_t test_data0_addr;
uint32_t test_data1_addr;
/* Get the MMRs needed to access this L1 address. */
void (*test_command_mmrs) (urj_part_t *part, uint32_t addr, int icache,
uint32_t *command_addr,
uint32_t *data0_addr, uint32_t *data1_addr);
/* Generate TEST_COMMAND from ADDR and W(rite), and return the MMRs
that need to be used for this access. */
void (*test_command) (urj_part_t *part, uint32_t addr, int w,
uint32_t command_addr, uint32_t *command_value);
/* No existing Blackfin processors use this. It should be 0. */
int dbgctl_dbgstat_in_one_chain;

@ -46,27 +46,110 @@ bfin_dbgstat_value (urj_part_t *part)
return urj_tap_register_get_value (part->active_instruction->data_register->out);
}
static uint32_t
bfin_test_command (uint32_t addr, int w)
static void
bfin_test_command_mmrs (urj_part_t *part, uint32_t addr, int icache,
uint32_t *command_addr,
uint32_t *data0_addr, uint32_t *data1_addr)
{
uint32_t test_command;
/* We can only access [15:0] range. */
if ((addr & 0xf0000) != 0)
return 0;
test_command =
(addr & 0x0800) << 15 /* Address bit 11 */
| (addr & 0x8000) << 8 /* Address bit 15 */
| (addr & 0x3000) << 4 /* Address bits [13:12] */
| (addr & 0x47f8) /* Address bits 14 and [10:3] */
| 0x1000000 /* Access instruction */
| 0x4; /* Access data array */
if (w)
test_command |= 0x2; /* Write */
if (icache) {
*command_addr = ITEST_COMMAND;
*data0_addr = ITEST_DATA0;
*data1_addr = ITEST_DATA1;
} else {
*command_addr = DTEST_COMMAND;
*data0_addr = DTEST_DATA0;
*data1_addr = DTEST_DATA1;
}
}
return test_command;
static void
bfin_test_command (urj_part_t *part, uint32_t addr, int w,
uint32_t command_addr, uint32_t *command_value)
{
/* The shifting here is a bit funky, but should be straight forward and
easier to maintain than hand coded masks. So, start with the break
down of the [DI]TEST_COMMAND MMR in the HRM and follow along:
We need to put bit 11 of the address into bit 26 of the MMR. So first
we mask off ADDR[11] with:
(addr & (1 << 11))
Then we shift it from its current position (11) to its new one (26):
((...) << (26 - 11))
*/
/* Start with the bits ITEST/DTEST share. */
*command_value =
((addr & (0x03 << 12)) << (16 - 12)) | /* ADDR[13:12] -> MMR[17:16] */
((addr & (0x01 << 14)) << (14 - 14)) | /* ADDR[14] -> MMR[14] */
((addr & (0xff << 3)) << ( 3 - 3)) | /* ADDR[10:3] -> MMR[10:3] */
(1 << 2) | /* 1 (data) -> MMR[2] */
(w << 1); /* read/write -> MMR[1] */
/* Now for the bits that aren't the same. */
if (command_addr == ITEST_COMMAND)
*command_value |=
((addr & (0x03 << 10)) << (26 - 10)); /* ADDR[11:10] -> MMR[27:26] */
else
*command_value |=
((addr & (0x01 << 11)) << (26 - 11)) | /* ADDR[11] -> MMR[26] */
((addr & (0x01 << 21)) << (24 - 21)); /* ADDR[21] -> MMR[24] */
/* Now, just for fun, some parts are slightly different. */
if (command_addr == DTEST_COMMAND)
{
/* BF50x has no additional needs. */
if (!strcmp (part->part, "BF518"))
{
/* MMR[23]:
0 - Data Bank A (0xff800000) / Inst Bank A (0xffa00000)
1 - Data Bank B (0xff900000) / Inst Bank B (0xffa04000)
*/
if ((addr & 0xfff04000) == 0xffa04000 ||
(addr & 0xfff00000) == 0xff900000)
*command_value |= (1 << 23);
}
else if (!strcmp (part->part, "BF526") ||
!strcmp (part->part, "BF527") ||
!strcmp (part->part, "BF533") ||
!strcmp (part->part, "BF534") ||
!strcmp (part->part, "BF537") ||
!strcmp (part->part, "BF538") ||
!strcmp (part->part, "BF548") ||
!strcmp (part->part, "BF548M"))
{
/* MMR[23]:
0 - Data Bank A (0xff800000) / Inst Bank A (0xffa00000)
1 - Data Bank B (0xff900000) / Inst Bank B (0xffa08000)
*/
if ((addr & 0xfff08000) == 0xffa08000 ||
(addr & 0xfff00000) == 0xff900000)
*command_value |= (1 << 23);
}
else if (!strcmp (part->part, "BF561"))
{
/* MMR[23]:
0 - Data Bank A (Core A: 0xff800000 Core B: 0xff400000)
Inst Bank A (Core A: 0xffa00000 Core B: 0xff600000)
1 - Data Bank B (Core A: 0xff900000 Core B: 0xff500000)
N/A for Inst (no Bank B)
*/
uint32_t hi = (addr >> 20);
if (hi == 0xff9 || hi == 0xff5)
*command_value |= (1 << 23);
}
else if (!strcmp (part->part, "BF592"))
{
/* ADDR[15] -> MMR[15]
MMR[22]:
0 - L1 Inst (0xffa00000)
1 - L1 ROM (0xffa10000)
*/
*command_value |= (addr & (1 << 15));
if ((addr >> 16) == 0xffa1)
*command_value |= (1 << 22);
}
}
}
struct emu_oab bfin_emu_oab =
@ -74,12 +157,9 @@ struct emu_oab bfin_emu_oab =
bfin_dbgctl_init,
bfin_dbgstat_value,
bfin_test_command_mmrs,
bfin_test_command,
DTEST_COMMAND,
DTEST_DATA0,
DTEST_DATA1,
0, /* dbgctl_dbgstat_in_one_chain */
0, /* sticky_in_reset */
@ -200,7 +280,7 @@ bfin_part_init (urj_part_t *part)
extern void bfin_init (void);
void
bfin_init ()
bfin_init (void)
{
/* Keep in sync with data/analog/PARTS */
urj_part_init_register ("BF506", bfin_part_init);

Loading…
Cancel
Save