Added file missing in previous commit for EJTAG_DMA driver
git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1398 b68d4a1b-bc3d-0410-92ed-d4ac073336b7master
parent
802df5f8f7
commit
11333c16e2
@ -0,0 +1,595 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* EJTAG compatible bus driver via DMA
|
||||
* Copyright (C) 2008, Julien Aube
|
||||
* Credits goes to
|
||||
* - Marek Michalkiewicz (EJTAG Pracc driver),
|
||||
* - HairyDairyMaid for the HairyDairyMaid v48 utility,
|
||||
* - Florian Fanelli for the help on the flash interface infos,
|
||||
* - All others who contributed to the previous projetcs
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
//#define PRINT_DATA_DEBUG 1
|
||||
#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"
|
||||
#include "generic_bus.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t impcode; /* EJTAG Implementation Register */
|
||||
} bus_params_t;
|
||||
|
||||
#define BP ((bus_params_t *) bus->params)
|
||||
|
||||
#define EJTAG_VER ((BP->impcode >> 29) & 7)
|
||||
#define EJTAG_20 0
|
||||
#define EJTAG_25 1
|
||||
#define EJTAG_26 2
|
||||
|
||||
/* 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
|
||||
#define Rocc 31
|
||||
#define ProbTrap 14
|
||||
|
||||
/* DMA */
|
||||
#define DmaAcc 17
|
||||
#define DstRt 11
|
||||
#define DmaRwn 9
|
||||
#define Derr 10
|
||||
// default : DMA tranfser size BYTE
|
||||
#define DMA_HALFWORD 7
|
||||
#define DMA_WORD 8
|
||||
#define DMA_BYTE 0
|
||||
|
||||
/**
|
||||
* bus->driver->(*new_bus)
|
||||
*
|
||||
*/
|
||||
static bus_t *
|
||||
ejtag_dma_bus_new( chain_t *chain, const bus_driver_t *driver, char *cmd_params[] )
|
||||
{
|
||||
bus_t *bus;
|
||||
|
||||
bus = calloc( 1, sizeof (bus_t) );
|
||||
if (!bus)
|
||||
return NULL;
|
||||
|
||||
bus->driver = driver;
|
||||
bus->params = calloc( 1, sizeof (bus_params_t) );
|
||||
if (!bus->params) {
|
||||
free( bus );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CHAIN = chain;
|
||||
PART = chain->parts->parts[chain->active_part];
|
||||
|
||||
return bus;
|
||||
}
|
||||
|
||||
/**
|
||||
* bus->driver->(*printinfo)
|
||||
*
|
||||
*/
|
||||
static void
|
||||
ejtag_dma_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 DMA (JTAG part No. %d)\n"), i );
|
||||
}
|
||||
|
||||
/**
|
||||
* helper function
|
||||
*
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef PRINT_DATA_DEBUG
|
||||
/* Small debug helper */
|
||||
char siz_(int sz)
|
||||
{
|
||||
switch(sz) {
|
||||
case DMA_WORD: return 'w';
|
||||
case DMA_BYTE: return 'b';
|
||||
case DMA_HALFWORD: return 'h';
|
||||
default : return 'e';
|
||||
}
|
||||
return 'E';
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* low-level dma write
|
||||
*
|
||||
*/
|
||||
static void ejtag_dma_write(unsigned int addr, unsigned int data,int sz)
|
||||
{
|
||||
static data_register *ejctrl = NULL;
|
||||
static data_register *ejaddr = NULL;
|
||||
static data_register *ejdata = NULL;
|
||||
int i=0;
|
||||
int timeout=5;
|
||||
|
||||
if (ejctrl == NULL)
|
||||
ejctrl = part_find_data_register( PART, "EJCONTROL" );
|
||||
if (ejaddr == NULL)
|
||||
ejaddr = part_find_data_register( PART, "EJADDRESS" );
|
||||
if (ejdata == NULL)
|
||||
ejdata = part_find_data_register( PART, "EJDATA" );
|
||||
|
||||
switch (sz) { /* Fill the other bytes with copy of the current */
|
||||
case DMA_BYTE:
|
||||
data &= 0xff; data |= (data<<8) | (data << 16) | (data << 24);
|
||||
break;
|
||||
case DMA_HALFWORD:
|
||||
data &= 0xffff; data |= (data << 16);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
part_set_instruction( PART, "EJTAG_ADDRESS" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
for (i = 0; i < 32; i++)
|
||||
ejaddr->in->data[i] = (addr >> i) & 1;
|
||||
chain_shift_data_registers( CHAIN, 0 ); /* Push the address to write */
|
||||
#ifdef PRINT_DATA_DEBUG
|
||||
printf("Wrote to ejaddr->in =%s %08X\n",register_get_string( ejaddr->in),reg_value( ejaddr->in ) );
|
||||
#endif
|
||||
part_set_instruction( PART, "EJTAG_DATA" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
for (i = 0; i < 32; i++)
|
||||
ejdata->in->data[i] = (data >> i) & 1;
|
||||
chain_shift_data_registers( CHAIN, 0 ); /* Push the data to write */
|
||||
#ifdef PRINT_DATA_DEBUG
|
||||
printf("Wrote to edata->in(%c) =%s %08X\n",siz_(sz),register_get_string( ejdata->in),reg_value( ejdata->in ) );
|
||||
#endif
|
||||
part_set_instruction( PART, "EJTAG_CONTROL" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
register_fill( ejctrl->in, 0 );
|
||||
ejctrl->in->data[PrAcc] = 1; // Processor access
|
||||
ejctrl->in->data[ProbEn] = 1;
|
||||
ejctrl->in->data[DmaAcc] = 1; // DMA operation request */
|
||||
ejctrl->in->data[DstRt] = 1;
|
||||
if (sz)
|
||||
ejctrl->in->data[sz] = 1; // Size : can be WORD/HALFWORD or nothing for byte
|
||||
chain_shift_data_registers( CHAIN, 0 ); /* Do the operation */
|
||||
//printf("Wrote to ejctrl->in =%s %08X\n",register_get_string( ejctrl->in),reg_value( ejctrl->in ) );
|
||||
|
||||
do {
|
||||
part_set_instruction( PART, "EJTAG_CONTROL" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
register_fill( ejctrl->in, 0 );
|
||||
ejctrl->in->data[PrAcc] = 1;
|
||||
ejctrl->in->data[ProbEn] = 1;
|
||||
ejctrl->in->data[DmaAcc] = 1;
|
||||
chain_shift_data_registers( CHAIN, 1 );
|
||||
timeout--;
|
||||
if ( ! timeout)
|
||||
break;
|
||||
} while(ejctrl->out->data[DstRt] == 1); // This flag tell us the processor has completed the op
|
||||
|
||||
part_set_instruction( PART, "EJTAG_CONTROL" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
register_fill( ejctrl->in, 0 );
|
||||
ejctrl->in->data[PrAcc] = 1;
|
||||
ejctrl->in->data[ProbEn] = 1;
|
||||
chain_shift_data_registers( CHAIN, 1 ); // Disable DMA, reset state to previous one.
|
||||
if (ejctrl->out->data[Derr] == 1) { // Check for DMA error, i.e. incorrect address
|
||||
printf( _("%s(%d) Error on dma write (dma transaction failed)\n"),
|
||||
__FILE__, __LINE__ );
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
* low level dma read operation
|
||||
*
|
||||
*/
|
||||
static unsigned int ejtag_dma_read(unsigned int addr,int sz)
|
||||
{
|
||||
static data_register *ejctrl = NULL;
|
||||
static data_register *ejaddr = NULL;
|
||||
static data_register *ejdata = NULL;
|
||||
int i=0;
|
||||
int timeout=5;
|
||||
unsigned int ret;
|
||||
|
||||
if (ejctrl == NULL)
|
||||
ejctrl = part_find_data_register( PART, "EJCONTROL" );
|
||||
if (ejaddr == NULL)
|
||||
ejaddr = part_find_data_register( PART, "EJADDRESS" );
|
||||
if (ejdata == NULL)
|
||||
ejdata = part_find_data_register( PART, "EJDATA" );
|
||||
|
||||
part_set_instruction( PART, "EJTAG_ADDRESS" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
for (i = 0; i < 32; i++)
|
||||
ejaddr->in->data[i] = (addr >> i) & 1;
|
||||
chain_shift_data_registers( CHAIN, 0 ); /* Push the address to read */
|
||||
#ifdef PRINT_DATA_DEBUG
|
||||
printf("Wrote to ejaddr->in =%s %08X\n",register_get_string( ejaddr->in),reg_value( ejaddr->in ) );
|
||||
#endif
|
||||
part_set_instruction( PART, "EJTAG_CONTROL" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
register_fill( ejctrl->in, 0 );
|
||||
ejctrl->in->data[PrAcc] = 1; // Processor access
|
||||
ejctrl->in->data[ProbEn] = 1;
|
||||
ejctrl->in->data[DmaAcc] = 1; // DMA operation request */
|
||||
ejctrl->in->data[DstRt] = 1;
|
||||
if (sz)
|
||||
ejctrl->in->data[sz] = 1; // Size : can be WORD/HALFWORD or nothing for byte
|
||||
ejctrl->in->data[DmaRwn] = 1; // This is a read
|
||||
chain_shift_data_registers( CHAIN, 0 ); /* Do the operation */
|
||||
//printf("Wrote to ejctrl->in =%s %08X\n",register_get_string( ejctrl->in),reg_value( ejctrl->in ) );
|
||||
|
||||
do {
|
||||
part_set_instruction( PART, "EJTAG_CONTROL" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
register_fill( ejctrl->in, 0 );
|
||||
ejctrl->in->data[PrAcc] = 1;
|
||||
ejctrl->in->data[ProbEn] = 1;
|
||||
ejctrl->in->data[DmaAcc] = 1;
|
||||
chain_shift_data_registers( CHAIN, 1 );
|
||||
|
||||
//printf("Wrote to ejctrl->in =%s %08X\n",register_get_string( ejctrl->in),reg_value( ejctrl->in ) );
|
||||
//printf("Read from ejctrl->out =%s %08X\n",register_get_string( ejctrl->out),reg_value( ejctrl->out ) );
|
||||
timeout--;
|
||||
if ( ! timeout)
|
||||
break;
|
||||
} while(ejctrl->out->data[DstRt] == 1); // This flag tell us the processor has completed the op
|
||||
|
||||
part_set_instruction( PART, "EJTAG_DATA" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
register_fill( ejdata->in,0);
|
||||
chain_shift_data_registers( CHAIN, 1 );
|
||||
ret = reg_value(ejdata->out);
|
||||
#ifdef PRINT_DATA_DEBUG
|
||||
printf("Read from ejdata->out(%c) =%s %08X\n",siz_(sz),register_get_string( ejdata->out),reg_value( ejdata->out ) );
|
||||
#endif
|
||||
part_set_instruction( PART, "EJTAG_CONTROL" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
register_fill( ejctrl->in, 0 );
|
||||
ejctrl->in->data[PrAcc] = 1;
|
||||
ejctrl->in->data[ProbEn] = 1;
|
||||
chain_shift_data_registers( CHAIN, 1 ); // Disable DMA, reset state to previous one.
|
||||
|
||||
// printf("Wrote to ejctrl->in =%s %08X\n",register_get_string( ejctrl->in),reg_value( ejctrl->in ) );
|
||||
// printf("Read from ejctrl->out =%s %08X\n",register_get_string( ejctrl->out),reg_value( ejctrl->out ) );
|
||||
|
||||
if (ejctrl->out->data[Derr] == 1) { // Check for DMA error, i.e. incorrect address
|
||||
printf( _("%s(%d) Error on dma read (dma transaction failed)\n"),
|
||||
__FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
switch (sz) {
|
||||
case DMA_HALFWORD : ret &= ret & 0xffff; break;
|
||||
case DMA_BYTE : ret &= ret & 0xff; break;
|
||||
case DMA_WORD:
|
||||
default: break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* bus->driver->(*initbus)
|
||||
*
|
||||
*/
|
||||
int ejtag_dma_bus_init( bus_t *bus )
|
||||
{
|
||||
data_register *ejctrl=NULL, *ejimpl=NULL, *ejaddr=NULL, *ejdata=NULL;
|
||||
int timeout=100;
|
||||
|
||||
ejctrl = part_find_data_register( PART, "EJCONTROL" );
|
||||
ejimpl = part_find_data_register( PART, "EJIMPCODE" );
|
||||
ejaddr = part_find_data_register( PART, "EJADDRESS" );
|
||||
ejdata = part_find_data_register( PART, "EJDATA" );
|
||||
|
||||
if (!(ejctrl && ejimpl)) {
|
||||
printf( _("%s(%d) EJCONTROL or EJIMPCODE register not found\n"),
|
||||
__FILE__, __LINE__ );
|
||||
return URJTAG_STATUS_FAIL;
|
||||
}
|
||||
if (!(ejaddr && ejdata)) {
|
||||
printf( _("%s(%d) EJADDRESS of EJDATA register not found, DMA impossible\n"),
|
||||
__FILE__, __LINE__ );
|
||||
return URJTAG_STATUS_FAIL;
|
||||
}
|
||||
|
||||
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" : " DMA",
|
||||
(BP->impcode & (1 )) ? " MIPS64" : " MIPS32" );
|
||||
|
||||
if (BP->impcode & (1 << 14)) {
|
||||
printf( "Warning, plateform claim there are no DMA support\n");
|
||||
}
|
||||
|
||||
if (EJTAG_VER != EJTAG_20) {
|
||||
printf( "Warning, plateform has a version which is not supposed to have DMA\n");
|
||||
}
|
||||
|
||||
// The purpose of this is to make the processor break into debug mode on
|
||||
// reset rather than execute the reset vector
|
||||
part_set_instruction( PART, "EJTAGBOOT" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
|
||||
// Prepare for following instructions
|
||||
part_set_instruction( PART, "EJTAG_CONTROL" );
|
||||
chain_shift_instructions( CHAIN );
|
||||
register_fill( ejctrl->in, 0 );
|
||||
|
||||
// Reset the processor
|
||||
ejctrl->in->data[PrRst] = 1;
|
||||
ejctrl->in->data[PerRst] = 1;
|
||||
chain_shift_data_registers( CHAIN, 0 );
|
||||
|
||||
// Release reset
|
||||
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;
|
||||
ejctrl->in->data[ProbTrap] = 1;
|
||||
ejctrl->in->data[JtagBrk] = 1;
|
||||
ejctrl->in->data[Rocc] = 1;
|
||||
chain_shift_data_registers( CHAIN, 0 );
|
||||
|
||||
/* Wait until processor is in break */
|
||||
ejctrl->in->data[JtagBrk] = 0;
|
||||
do {
|
||||
chain_shift_data_registers( CHAIN, 1 );
|
||||
timeout--;
|
||||
if (!timeout) break;
|
||||
} while ( ejctrl->out->data[BrkSt] == 1 );
|
||||
|
||||
if (timeout == 0)
|
||||
{
|
||||
printf( _("%s(%d) Failed to enter debug mode, ctrl=%s\n"),
|
||||
__FILE__, __LINE__,
|
||||
register_get_string( ejctrl->out ) );
|
||||
return URJTAG_STATUS_FAIL;
|
||||
}
|
||||
|
||||
// Handle the reset bit clear, if any
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
// Clear Memory Protection Bit in DCR
|
||||
printf( _("Clear memory protection bit in DCR\n"));
|
||||
unsigned int val = ejtag_dma_read(0xff300000,DMA_WORD);
|
||||
ejtag_dma_write(0xff300000, val & ~(1<<2), DMA_WORD );
|
||||
|
||||
// Clear watchdog, if any
|
||||
printf( _("Clear Watchdog\n"));
|
||||
ejtag_dma_write(0xb8000080,0,DMA_WORD);
|
||||
|
||||
printf( _("Potential flash base address: [0x%x], [0x%x]\n"),
|
||||
ejtag_dma_read(0xfffe2000,DMA_WORD), ejtag_dma_read(0xfffe1000,DMA_WORD));
|
||||
|
||||
printf( _("Processor successfully switched in debug mode.\n"));
|
||||
|
||||
INITIALIZED = 1;
|
||||
return URJTAG_STATUS_OK;
|
||||
}
|
||||
/**
|
||||
* bus->driver->(*prepare)
|
||||
*
|
||||
*/
|
||||
void
|
||||
ejtag_dma_bus_prepare( bus_t *bus )
|
||||
{
|
||||
if (!INITIALIZED)
|
||||
bus_init( bus );
|
||||
}
|
||||
|
||||
/**
|
||||
* bus->driver->(*area)
|
||||
*
|
||||
*/
|
||||
int
|
||||
ejtag_dma_bus_area( bus_t *bus, uint32_t adr, bus_area_t *area )
|
||||
{
|
||||
|
||||
/* from MIPS.org datasheets */
|
||||
if (adr < UINT32_C(0x1E000000)) {
|
||||
area->description = "USEG : User addresses";
|
||||
area->start = UINT32_C(0x00000000);
|
||||
area->length = UINT64_C(0x1E000000);
|
||||
area->width = 32;
|
||||
} else if (adr < UINT32_C(0x20000000)) {
|
||||
area->description = "FLASH : Addresses in flash (boot=0x1FC000000)";
|
||||
area->start = UINT32_C(0x1E000000);
|
||||
area->length = UINT64_C(0x2000000);
|
||||
area->width = 16;
|
||||
} else if (adr < UINT32_C(0x80000000)) {
|
||||
area->description = "USEG : User addresses";
|
||||
area->start = UINT32_C(0x20000000);
|
||||
area->length = UINT64_C(0x60000000);
|
||||
area->width = 32;
|
||||
} else if (adr < UINT32_C(0xA0000000)) {
|
||||
area->description = "KSEG0: Kernel Unmapped Cached";
|
||||
area->start = UINT32_C(0x80000000);
|
||||
area->length = UINT64_C(0x20000000);
|
||||
area->width = 32;
|
||||
} else if (adr < UINT32_C(0xC0000000)) {
|
||||
area->description = "KSEG1: Kernel Unmapped Uncached";
|
||||
area->start = UINT32_C(0xA0000000);
|
||||
area->length = UINT64_C(0x20000000);
|
||||
area->width = 32;
|
||||
} else if (adr < UINT32_C(0xE0000000)) {
|
||||
area->description = "SSEG : Supervisor Mapped";
|
||||
area->start = UINT32_C(0xC0000000);
|
||||
area->length = UINT64_C(0x20000000);
|
||||
area->width = 32;
|
||||
} else {
|
||||
area->description = "KSEG3: Kernel Mapped";
|
||||
area->start = UINT32_C(0xE0000000);
|
||||
area->length = UINT64_C(0x20000000);
|
||||
area->width = 32;
|
||||
}
|
||||
return URJTAG_STATUS_OK;
|
||||
}
|
||||
|
||||
int get_sz(uint32_t adr)
|
||||
{
|
||||
static bus_area_t area;
|
||||
static int initialized = 0;
|
||||
|
||||
if (! initialized) {
|
||||
ejtag_dma_bus_area(NULL,adr,&area);
|
||||
initialized = 1;
|
||||
}
|
||||
switch (area.width)
|
||||
{
|
||||
case 32: return DMA_WORD;
|
||||
case 16: return DMA_HALFWORD;
|
||||
default: break;
|
||||
}
|
||||
return DMA_BYTE;
|
||||
}
|
||||
/**
|
||||
* bus->driver->(*write)
|
||||
*
|
||||
*/
|
||||
void ejtag_dma_bus_write(bus_t *bus, uint32_t adr, uint32_t data)
|
||||
{
|
||||
//printf("%s:adr=0x%x,data=0x%x\n",__FUNCTION__,adr,data);
|
||||
ejtag_dma_write(adr,data, get_sz(adr));
|
||||
}
|
||||
/**
|
||||
* bus->driver->(*read)
|
||||
*
|
||||
*/
|
||||
unsigned int ejtag_dma_bus_read(bus_t *bus, uint32_t adr)
|
||||
{
|
||||
int data = ejtag_dma_read(adr, get_sz(adr));
|
||||
//printf("%s:adr=0x%x,got=0x%x\n",__FUNCTION__,adr,data);
|
||||
return data;
|
||||
}
|
||||
|
||||
static unsigned int _data_read;
|
||||
/**
|
||||
* bus->driver->(*read_start)
|
||||
*
|
||||
*/
|
||||
void ejtag_dma_bus_read_start(bus_t *bus, uint32_t adr)
|
||||
{
|
||||
_data_read = ejtag_dma_read(adr,get_sz(adr));
|
||||
//printf("%s:adr=0x%x, got=0x%x\n",__FUNCTION__,adr,_data_read);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* bus->driver->(*read_next)
|
||||
*
|
||||
*/
|
||||
unsigned int ejtag_dma_bus_read_next(bus_t *bus, uint32_t adr)
|
||||
{
|
||||
unsigned int tmp_value = _data_read;
|
||||
_data_read = ejtag_dma_read(adr,get_sz(adr));
|
||||
//printf("%s:adr=0x%x, got=0x%x\n",__FUNCTION__,adr,_data_read);
|
||||
return tmp_value;
|
||||
}
|
||||
/**
|
||||
* bus->driver->(*read_end)
|
||||
*
|
||||
*/
|
||||
unsigned int ejtag_dma_bus_read_end(bus_t *bus)
|
||||
{
|
||||
return _data_read;
|
||||
}
|
||||
|
||||
const bus_driver_t ejtag_dma_bus = {
|
||||
"ejtag_dma",
|
||||
N_("EJTAG compatible bus driver via DMA"),
|
||||
ejtag_dma_bus_new,
|
||||
generic_bus_free,
|
||||
ejtag_dma_bus_printinfo,
|
||||
ejtag_dma_bus_prepare,
|
||||
ejtag_dma_bus_area,
|
||||
ejtag_dma_bus_read_start,
|
||||
ejtag_dma_bus_read_next,
|
||||
ejtag_dma_bus_read_end,
|
||||
ejtag_dma_bus_read,
|
||||
ejtag_dma_bus_write,
|
||||
ejtag_dma_bus_init
|
||||
};
|
||||
|
Loading…
Reference in New Issue