[ 1429825 ] EJTAG driver (partial patch - only the bus driver for now)

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@737 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Kolja Waschk 17 years ago
parent 65490c6623
commit dc2cdf8451

@ -30,6 +30,7 @@ libbus_a_SOURCES = \
buses.h \
au1500.c \
bcm1250.c \
ejtag.c \
bf533_stamp.c \
bf533_ezkit.c \
ixp425.c \

@ -32,6 +32,7 @@
const bus_driver_t *bus_drivers[] = {
&au1500_bus,
&bcm1250_bus,
&ejtag_bus,
&bf533_stamp_bus,
&bf533_ezkit_bus,
&ixp425_bus,

@ -27,6 +27,7 @@
extern const bus_driver_t au1500_bus;
extern const bus_driver_t bcm1250_bus;
extern const bus_driver_t ejtag_bus;
extern const bus_driver_t bf533_stamp_bus;
extern const bus_driver_t bf533_ezkit_bus;
extern const bus_driver_t ixp425_bus;

@ -0,0 +1,493 @@
/*
* $Id$
*
* EJTAG compatible bus driver via PrAcc
* Copyright (C) 2005, Marek Michalkiewicz
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by Marek Michalkiewicz <marekm@amelek.gda.pl>, 2005.
*
* Documentation:
* [1] MIPS Licensees, "MIPS EJTAG Debug Solution", 980818 Rev. 2.0.0
* [2] MIPS Technologies, Inc. "EJTAG Specification", 2001-02-15, Rev. 2.60
*
*/
#include "sysdep.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "part.h"
#include "bus.h"
#include "chain.h"
#include "bssignal.h"
#include "jtag.h"
#include "buses.h"
typedef struct {
chain_t *chain;
part_t *part;
int initialized;
uint32_t impcode; /* EJTAG Implementation Register */
uint16_t adr_hi; /* cached high bits of $3 */
} bus_params_t;
#define BP ((bus_params_t *) bus->params)
#define CHAIN (BP->chain)
#define PART (BP->part)
#define EJTAG_VER ((BP->impcode >> 29) & 7)
#define EJTAG_20 0
#define EJTAG_25 1
#define EJTAG_26 2
static int ejtag_bus_area( bus_t *bus, uint32_t adr, bus_area_t *area );
static void
ejtag_bus_printinfo( bus_t *bus )
{
int i;
for (i = 0; i < CHAIN->parts->len; i++)
if (PART == CHAIN->parts->parts[i])
break;
printf( _("EJTAG compatible bus driver via PrAcc (JTAG part No. %d)\n"), i );
}
/* EJTAG control register bits */
#define PerRst 20
#define PRnW 19
#define PrAcc 18
#define PrRst 16
#define ProbEn 15
#define JtagBrk 12
#define BrkSt 3
/* EJTAG 2.6 */
#define Rocc 31
#define ProbTrap 14
static uint32_t
reg_value( tap_register *reg )
{
uint32_t retval = 0;
int i;
for (i = 0; i < reg->len; i++) {
if (reg->data[i])
retval |= (1 << i);
}
return retval;
}
static uint32_t
ejtag_run_pracc( bus_t *bus, const uint32_t *code, unsigned int len )
{
data_register *ejaddr, *ejdata, *ejctrl;
int i, pass;
uint32_t addr, data, retval;
ejaddr = part_find_data_register( PART, "EJADDRESS" );
ejdata = part_find_data_register( PART, "EJDATA" );
ejctrl = part_find_data_register( PART, "EJCONTROL" );
if (!(ejaddr && ejdata && ejctrl)) {
printf( _("%s(%d) EJADDRESS, EJDATA or EJCONTROL register not found\n"),
__FILE__, __LINE__ );
return 0;
}
part_set_instruction( PART, "EJTAG_CONTROL" );
chain_shift_instructions( CHAIN );
pass = 0;
retval = 0;
for (;;) {
ejctrl->in->data[PrAcc] = 1;
chain_shift_data_registers( CHAIN, 0 );
chain_shift_data_registers( CHAIN, 1 );
// printf( "ctrl=%s\n", register_get_string( ejctrl->out ) );
if (ejctrl->out->data[Rocc]) {
printf( _("%s(%d) Reset occurred, ctrl=%s\n"),
__FILE__, __LINE__,
register_get_string( ejctrl->out ) );
BP->initialized = 0;
break;
}
if (! ejctrl->out->data[PrAcc]) {
printf( _("%s(%d) No processor access, ctrl=%s\n"),
__FILE__, __LINE__,
register_get_string( ejctrl->out ) );
BP->initialized = 0;
break;
}
part_set_instruction( PART, "EJTAG_ADDRESS" );
chain_shift_instructions( CHAIN );
chain_shift_data_registers( CHAIN, 1 );
addr = reg_value( ejaddr->out );
if (addr & 3) {
printf( _("%s(%d) PrAcc bad alignment: addr=0x%08x\n"),
__FILE__, __LINE__, addr );
addr &= ~3;
}
part_set_instruction( PART, "EJTAG_DATA" );
chain_shift_instructions( CHAIN );
register_fill( ejdata->in, 0 );
if (ejctrl->out->data[PRnW]) {
chain_shift_data_registers( CHAIN, 1 );
data = reg_value( ejdata->out );
#if 0
printf( _("%s(%d) PrAcc write: addr=0x%08x data=0x%08x\n"),
__FILE__, __LINE__, addr, data );
#endif
if (addr == UINT32_C(0xff200000)) {
/* Return value from the target CPU. */
retval = data;
} else {
printf( _("%s(%d) Unknown write addr=0x%08x data=0x%08x\n"),
__FILE__, __LINE__, addr, data );
}
} else {
if (addr == UINT32_C(0xff200200) && pass++)
break;
data = 0;
if (addr >= 0xff200200 && addr < 0xff200200 + (len << 2)) {
data = code[(addr - 0xff200200) >> 2];
for (i = 0; i < 32; i++)
ejdata->in->data[i] = (data >> i) & 1;
}
#if 0
printf( "%s(%d) PrAcc read: addr=0x%08x data=0x%08x\n",
__FILE__, __LINE__, addr, data );
#endif
chain_shift_data_registers( CHAIN, 0 );
}
part_set_instruction( PART, "EJTAG_CONTROL" );
chain_shift_instructions( CHAIN );
ejctrl->in->data[PrAcc] = 0;
chain_shift_data_registers( CHAIN, 0 );
}
return retval;
}
static void
ejtag_bus_init( bus_t *bus )
{
data_register *ejctrl, *ejimpl;
uint32_t code[4] = {
0x3c04ff20, // lui $4,0xff20
0x349f0200, // ori $31,$4,0x0200
0x03e00008, // jr $31
0x3c030000 // lui $3,0
};
ejctrl = part_find_data_register( PART, "EJCONTROL" );
ejimpl = part_find_data_register( PART, "EJIMPCODE" );
if (!(ejctrl && ejimpl)) {
printf( _("%s(%d) EJCONTROL or EJIMPCODE register not found\n"),
__FILE__, __LINE__ );
return;
}
part_set_instruction( PART, "EJTAG_IMPCODE" );
chain_shift_instructions( CHAIN );
chain_shift_data_registers( CHAIN, 0 );
chain_shift_data_registers( CHAIN, 1 );
printf( "ImpCode=%s\n", register_get_string( ejimpl->out ) );
BP->impcode = reg_value( ejimpl->out );
switch (EJTAG_VER) {
case EJTAG_20: printf( "EJTAG version: <= 2.0\n"); break;
case EJTAG_25: printf( "EJTAG version: 2.5\n"); break;
case EJTAG_26: printf( "EJTAG version: 2.6\n"); break;
default:
printf( "EJTAG version: unknown (%d)\n", EJTAG_VER );
}
printf( "EJTAG Implementation flags:%s%s%s%s%s%s%s\n",
(BP->impcode & (1 << 28)) ? " R3k" : " R4k",
(BP->impcode & (1 << 24)) ? " DINTsup" : "",
(BP->impcode & (1 << 22)) ? " ASID_8" : "",
(BP->impcode & (1 << 21)) ? " ASID_6" : "",
(BP->impcode & (1 << 16)) ? " MIPS16" : "",
(BP->impcode & (1 << 14)) ? " NoDMA" : "",
(BP->impcode & (1 )) ? " MIPS64" : " MIPS32" );
if (EJTAG_VER >= EJTAG_25) {
part_set_instruction( PART, "EJTAGBOOT" );
chain_shift_instructions( CHAIN );
}
part_set_instruction( PART, "EJTAG_CONTROL" );
chain_shift_instructions( CHAIN );
register_fill( ejctrl->in, 0 );
ejctrl->in->data[PrRst] = 1;
ejctrl->in->data[PerRst] = 1;
chain_shift_data_registers( CHAIN, 0 );
ejctrl->in->data[PrRst] = 0;
ejctrl->in->data[PerRst] = 0;
chain_shift_data_registers( CHAIN, 0 );
ejctrl->in->data[PrAcc] = 1;
ejctrl->in->data[ProbEn] = 1;
if (EJTAG_VER >= EJTAG_25) {
ejctrl->in->data[ProbTrap] = 1;
ejctrl->in->data[Rocc] = 1;
}
chain_shift_data_registers( CHAIN, 0 );
ejctrl->in->data[JtagBrk] = 1;
chain_shift_data_registers( CHAIN, 0 );
ejctrl->in->data[JtagBrk] = 0;
chain_shift_data_registers( CHAIN, 1 );
if (! ejctrl->out->data[BrkSt]) {
printf( _("%s(%d) Failed to enter debug mode, ctrl=%s\n"),
__FILE__, __LINE__,
register_get_string( ejctrl->out ) );
return;
}
if (ejctrl->out->data[Rocc]) {
ejctrl->in->data[Rocc] = 0;
chain_shift_data_registers( CHAIN, 0 );
ejctrl->in->data[Rocc] = 1;
chain_shift_data_registers( CHAIN, 1 );
}
ejtag_run_pracc( bus, code, 4 );
BP->adr_hi = 0;
BP->initialized = 1;
}
static void
ejtag_bus_prepare( bus_t *bus )
{
if (BP->initialized)
return;
ejtag_bus_init( bus );
}
static int
ejtag_gen_read( uint32_t *code, uint32_t adr )
{
uint16_t adr_hi, adr_lo;
uint32_t *p = code;
/* 16-bit signed offset, phys -> kseg1 */
adr_lo = adr & 0xffff;
adr_hi = ((adr >> 16) & 0x1fff) + (adr_lo >> 15) + 0xa000;
if (BP->adr_hi != adr_hi) {
BP->adr_hi = adr_hi;
*p++ = 0x3c030000 | adr_hi; // lui $3,adr_hi
}
switch (adr >> 29) {
case 0:
*p++ = 0x90620000 | adr_lo; // lbu $2,adr_lo($3)
break;
case 1:
*p++ = 0x94620000 | (adr_lo & ~1); // lhu $2,adr_lo($3)
break;
case 2:
*p++ = 0x8c620000 | (adr_lo & ~3); // lw $2,adr_lo($3)
break;
default: /* unknown bus width */
*p++ = 0x00001025; // move $2,$0
break;
}
*p++ = 0x03e00008; // jr $31
return p - code;
}
static void
ejtag_bus_read_start( bus_t *bus, uint32_t adr )
{
uint32_t code[3];
ejtag_run_pracc( bus, code, ejtag_gen_read( code, adr ));
// printf("bus_read_start: adr=0x%08x\n", adr);
}
static uint32_t
ejtag_bus_read_next( bus_t *bus, uint32_t adr )
{
uint32_t d;
uint32_t code[4], *p = code;
*p++ = 0xac820000; // sw $2,0($4)
p += ejtag_gen_read( p, adr );
d = ejtag_run_pracc( bus, code, p - code );
// printf("bus_read_next: adr=0x%08x data=0x%08x\n", adr, d);
return d;
}
static uint32_t
ejtag_bus_read_end( bus_t *bus )
{
uint32_t d;
static const uint32_t code[2] = {
0xac820000, // sw $2,0($4)
0x03e00008 // jr $31
};
d = ejtag_run_pracc( bus, code, 2 );
// printf("bus_read_end: data=0x%08x\n", d);
return d;
}
static uint32_t
ejtag_bus_read( bus_t *bus, uint32_t adr )
{
ejtag_bus_read_start( bus, adr );
return ejtag_bus_read_end( bus );
}
static void
ejtag_bus_write( bus_t *bus, uint32_t adr, uint32_t data )
{
uint16_t adr_hi, adr_lo;
uint32_t code[5], *p = code;
/* 16-bit signed offset, phys -> kseg1 */
adr_lo = adr & 0xffff;
adr_hi = ((adr >> 16) & 0x1fff) + (adr_lo >> 15) + 0xa000;
if (BP->adr_hi != adr_hi) {
BP->adr_hi = adr_hi;
*p++ = 0x3c030000 | adr_hi; // lui $3,adr_hi
}
switch (adr >> 29) {
case 0:
*p++ = 0x34020000 | (data & 0xff); // li $2,data
*p++ = 0xa0620000 | adr_lo; // sb $2,adr_lo($3)
break;
case 1:
*p++ = 0x34020000 | (data & 0xffff); // li $2,data
*p++ = 0xa4620000 | (adr_lo & ~1); // sh $2,adr_lo($3)
break;
case 2:
*p++ = 0x3c020000 | (data >> 16); // lui $2,data_hi
*p++ = 0x34420000 | (data & 0xffff); // ori $2,data_lo
*p++ = 0xac620000 | (adr_lo & ~3); // sw $2,adr_lo($3)
break;
}
*p++ = 0x03e00008; // jr $31
ejtag_run_pracc( bus, code, p - code );
// printf("bus_write: adr=0x%08x data=0x%08x\n", adr, data);
}
static int
ejtag_bus_area( bus_t *bus, uint32_t adr, bus_area_t *area )
{
if (adr < UINT32_C(0x20000000)) {
area->description = NULL;
area->start = UINT32_C(0x00000000);
area->length = UINT64_C(0x20000000);
area->width = 8;
} else if (adr < UINT32_C(0x40000000)) {
area->description = NULL;
area->start = UINT32_C(0x20000000);
area->length = UINT64_C(0x20000000);
area->width = 16;
} else if (adr < UINT32_C(0x60000000)) {
area->description = NULL;
area->start = UINT32_C(0x40000000);
area->length = UINT64_C(0x20000000);
area->width = 32;
} else {
area->description = NULL;
area->start = UINT32_C(0x60000000);
area->length = UINT64_C(0xa0000000);
area->width = 0;
}
return 0;
}
static void
ejtag_bus_free( bus_t *bus )
{
free( bus->params );
free( bus );
}
static bus_t *ejtag_bus_new( void );
const bus_driver_t ejtag_bus = {
"ejtag",
N_("EJTAG compatible bus driver via PrAcc"),
ejtag_bus_new,
ejtag_bus_free,
ejtag_bus_printinfo,
ejtag_bus_prepare,
ejtag_bus_area,
ejtag_bus_read_start,
ejtag_bus_read_next,
ejtag_bus_read_end,
ejtag_bus_read,
ejtag_bus_write
};
static bus_t *
ejtag_bus_new( void )
{
bus_t *bus;
if (!chain || !chain->parts || chain->parts->len <= chain->active_part || chain->active_part < 0)
return NULL;
bus = malloc( sizeof (bus_t) );
if (!bus)
return NULL;
bus->driver = &ejtag_bus;
bus->params = malloc( sizeof (bus_params_t) );
if (!bus->params) {
free( bus );
return NULL;
}
CHAIN = chain;
PART = chain->parts->parts[chain->active_part];
BP->initialized = 0;
return bus;
}

@ -167,7 +167,7 @@ ppdev_open( parport_t *parport )
return -1;
}
if ((ioctl( p->fd, PPEXCL ) == -1) || (ioctl( p->fd, PPCLAIM ) == -1)) {
if (/*(ioctl( p->fd, PPEXCL ) == -1) ||*/ (ioctl( p->fd, PPCLAIM ) == -1)) {
printf( _("Could not claim ppdev device: %s\n"), strerror(errno) );
close( p->fd );
p->fd = -1;

Loading…
Cancel
Save