jtagdev, pif, mehfet: refactor device_class ops to be unified under jtagdev instead of using separate implementations
This commit is contained in:
parent
0a8ebf4a66
commit
ddfffa06fb
|
@ -35,10 +35,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "jtaglib.h"
|
#include "jtaglib.h"
|
||||||
#include "output.h"
|
|
||||||
#include "jtaglib_defs.h"
|
#include "jtaglib_defs.h"
|
||||||
|
|
||||||
|
#include "output.h"
|
||||||
|
#include "ctrlc.h"
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
/* Reset target JTAG interface and perform fuse-HW check */
|
/* Reset target JTAG interface and perform fuse-HW check */
|
||||||
static void jtag_default_reset_tap(struct jtdev *p)
|
static void jtag_default_reset_tap(struct jtdev *p)
|
||||||
{
|
{
|
||||||
|
@ -525,7 +529,7 @@ int jtag_is_fuse_blown (struct jtdev *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p)
|
int jtag_refresh_bps(device_t dev, struct jtdev *p)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -536,9 +540,8 @@ int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p)
|
||||||
for (i = 0; i < dev->max_breakpoints; i++) {
|
for (i = 0; i < dev->max_breakpoints; i++) {
|
||||||
bp = &dev->breakpoints[i];
|
bp = &dev->breakpoints[i];
|
||||||
|
|
||||||
printc_dbg("%s: refresh breakpoint %d: type=%d "
|
printc_dbg("jtaglib: refresh breakpoint %d: type=%d "
|
||||||
"addr=%04x flags=%04x\n", module,
|
"addr=%04x flags=%04x\n", i, bp->type, bp->addr, bp->flags);
|
||||||
i, bp->type, bp->addr, bp->flags);
|
|
||||||
|
|
||||||
if ( (bp->flags & DEVICE_BP_DIRTY) &&
|
if ( (bp->flags & DEVICE_BP_DIRTY) &&
|
||||||
(bp->type == DEVICE_BPTYPE_BREAK) ) {
|
(bp->type == DEVICE_BPTYPE_BREAK) ) {
|
||||||
|
@ -549,8 +552,7 @@ int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( jtag_set_breakpoint (p, i, addr) == 0) {
|
if ( jtag_set_breakpoint (p, i, addr) == 0) {
|
||||||
printc_err("%s: failed to refresh "
|
printc_err("jtaglib: failed to refresh breakpoint #%d\n", i);
|
||||||
"breakpoint #%d\n", module, i);
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else {
|
} else {
|
||||||
bp->flags &= ~DEVICE_BP_DIRTY;
|
bp->flags &= ~DEVICE_BP_DIRTY;
|
||||||
|
@ -561,3 +563,184 @@ int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
static int write_ram_word(struct jtdev *p, address_t addr, uint16_t value)
|
||||||
|
{
|
||||||
|
jtag_write_mem(p, 16, addr, value);
|
||||||
|
|
||||||
|
return p->failed ? -1 : 0;
|
||||||
|
}
|
||||||
|
static int write_flash_block(struct jtdev *p, address_t addr,
|
||||||
|
address_t len, const uint8_t *data)
|
||||||
|
{
|
||||||
|
uint16_t* word = malloc( len / 2 * sizeof(*word) );
|
||||||
|
if (!word) {
|
||||||
|
pr_error("jtaglib: failed to allocate memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < len/2; i++) {
|
||||||
|
word[i] = data[2*i] + (((uint16_t)data[2*i+1]) << 8);
|
||||||
|
}
|
||||||
|
jtag_write_flash(p, addr, len/2, word);
|
||||||
|
|
||||||
|
free(word);
|
||||||
|
|
||||||
|
return p->failed ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_words(device_t dev_base, const struct chipinfo_memory *m,
|
||||||
|
address_t addr, address_t len, uint8_t *data) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
|
||||||
|
for (unsigned int index = 0; index < len; index += 2) {
|
||||||
|
unsigned int word = jtag_read_mem(p, 16, addr+index);
|
||||||
|
data[index ] = word & 0x00ff;
|
||||||
|
data[index+1] = (word >> 8) & 0x00ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p->failed ? -1 : len;
|
||||||
|
}
|
||||||
|
static int write_words(device_t dev_base, const struct chipinfo_memory *m,
|
||||||
|
address_t addr, address_t len, const uint8_t *data) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (m->type != CHIPINFO_MEMTYPE_FLASH) {
|
||||||
|
len = 2;
|
||||||
|
r = write_ram_word(p, addr, r16le(data));
|
||||||
|
} else {
|
||||||
|
r = write_flash_block(p, addr, len, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
printc_err("jtaglib: write_words at address 0x%x failed\n", addr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;}
|
||||||
|
|
||||||
|
int jtag_dev_readmem(device_t dev_base, address_t addr, uint8_t *mem, address_t len) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
p->failed = 0;
|
||||||
|
return readmem(dev_base, addr, mem, len, read_words);
|
||||||
|
}
|
||||||
|
int jtag_dev_writemem(device_t dev_base, address_t addr, const uint8_t *mem, address_t len) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
p->failed = 0;
|
||||||
|
return writemem(dev_base, addr, mem, len, write_words, read_words);
|
||||||
|
}
|
||||||
|
int jtag_dev_erase(device_t dev_base, device_erase_type_t type, address_t addr) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
|
||||||
|
p->failed = 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DEVICE_ERASE_MAIN:
|
||||||
|
jtag_erase_flash(p, JTAG_ERASE_MAIN, addr);
|
||||||
|
break;
|
||||||
|
case DEVICE_ERASE_ALL:
|
||||||
|
jtag_erase_flash(p, JTAG_ERASE_MASS, addr);
|
||||||
|
break;
|
||||||
|
case DEVICE_ERASE_SEGMENT:
|
||||||
|
jtag_erase_flash(p, JTAG_ERASE_SGMT, addr);
|
||||||
|
break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p->failed ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jtag_dev_getregs(device_t dev_base, address_t *regs) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
|
||||||
|
p->failed = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < DEVICE_NUM_REGS; i++) {
|
||||||
|
regs[i] = jtag_read_reg(p, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p->failed ? -1 : 0;
|
||||||
|
}
|
||||||
|
int jtag_dev_setregs(device_t dev_base, const address_t *regs) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
|
||||||
|
p->failed = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < DEVICE_NUM_REGS; i++) {
|
||||||
|
jtag_write_reg(p, i, regs[i]);
|
||||||
|
}
|
||||||
|
return p->failed ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jtag_dev_ctl(device_t dev_base, device_ctl_t type) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
|
||||||
|
p->failed = 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DEVICE_CTL_RESET:
|
||||||
|
/* perform soft reset */
|
||||||
|
jtag_execute_puc(p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEVICE_CTL_RUN:
|
||||||
|
/* transfer changed breakpoints to device */
|
||||||
|
if (jtag_refresh_bps(&p->base, p) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* start program execution at current PC */
|
||||||
|
jtag_release_device(p, 0xffff);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEVICE_CTL_HALT:
|
||||||
|
/* take device under JTAG control */
|
||||||
|
jtag_get_device(p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEVICE_CTL_STEP:
|
||||||
|
/* execute next instruction at current PC */
|
||||||
|
jtag_single_step(p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printc_err("mehfet: unsupported operation %d\n", type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p->failed ? -1 : 0;
|
||||||
|
}
|
||||||
|
device_status_t jtag_dev_poll(device_t dev_base) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
|
||||||
|
if (delay_ms(100) < 0 || ctrlc_check())
|
||||||
|
return DEVICE_STATUS_INTR;
|
||||||
|
|
||||||
|
int r = jtag_cpu_state(p);
|
||||||
|
|
||||||
|
if (r == 1) return DEVICE_STATUS_HALTED;
|
||||||
|
|
||||||
|
return DEVICE_STATUS_RUNNING;
|
||||||
|
}
|
||||||
|
int jtag_dev_getconfigfuses(device_t dev_base) {
|
||||||
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
|
||||||
|
return jtag_get_config_fuses(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int jtag_dev_init(struct jtdev *p) {
|
||||||
|
unsigned int jtagid = jtag_init(p);
|
||||||
|
if (p->failed) return -1;
|
||||||
|
|
||||||
|
printc("JTAG ID: 0x%02x\n", jtagid);
|
||||||
|
// TODO: validate JTAG ID in a better way!
|
||||||
|
if (jtagid != 0x89 && jtagid != 0x91) {
|
||||||
|
printc_err("mehfet: unexpected JTAG ID: 0x%02x\n", jtagid);
|
||||||
|
jtag_release_device(p, 0xfffe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,11 +40,6 @@
|
||||||
#include "jtdev.h"
|
#include "jtdev.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/* Flash erasing modes */
|
|
||||||
#define JTAG_ERASE_MASS 0xA506
|
|
||||||
#define JTAG_ERASE_MAIN 0xA504
|
|
||||||
#define JTAG_ERASE_SGMT 0xA502
|
|
||||||
|
|
||||||
/* Colleciton of functions that need different implementation for different
|
/* Colleciton of functions that need different implementation for different
|
||||||
* CPU types (that is, 16-bit vs CPUX vs Xv2) */
|
* CPU types (that is, 16-bit vs CPUX vs Xv2) */
|
||||||
struct jtaglib_funcs {
|
struct jtaglib_funcs {
|
||||||
|
@ -167,6 +162,16 @@ uint32_t jtag_default_dr_shift_20(struct jtdev *p, uint32_t dr);
|
||||||
void jtag_default_tms_sequence(struct jtdev *p, int bits, unsigned int value);
|
void jtag_default_tms_sequence(struct jtdev *p, int bits, unsigned int value);
|
||||||
void jtag_default_init_dap(struct jtdev *p);
|
void jtag_default_init_dap(struct jtdev *p);
|
||||||
|
|
||||||
int jtag_refresh_bps(const char *driver, device_t dev, struct jtdev *p);
|
int jtag_refresh_bps(device_t dev, struct jtdev *p);
|
||||||
|
|
||||||
|
int jtag_dev_readmem(device_t dev_base, address_t addr, uint8_t *mem, address_t len);
|
||||||
|
int jtag_dev_writemem(device_t dev_base, address_t addr, const uint8_t *mem, address_t len);
|
||||||
|
int jtag_dev_getregs(device_t dev_base, address_t *regs);
|
||||||
|
int jtag_dev_setregs(device_t dev_base, const address_t *regs);
|
||||||
|
int jtag_dev_ctl(device_t dev_base, device_ctl_t type);
|
||||||
|
device_status_t jtag_dev_poll(device_t dev_base);
|
||||||
|
int jtag_dev_erase(device_t dev_base, device_erase_type_t, address_t addr);
|
||||||
|
int jtag_dev_getconfigfuses(device_t dev_base);
|
||||||
|
int jtag_dev_init(struct jtdev *p);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
#include "jtaglib.h"
|
#include "jtaglib.h"
|
||||||
#include "eem_defs.h"
|
#include "eem_defs.h"
|
||||||
|
|
||||||
|
/* Flash erasing modes */
|
||||||
|
#define JTAG_ERASE_MASS 0xA506
|
||||||
|
#define JTAG_ERASE_MAIN 0xA504
|
||||||
|
#define JTAG_ERASE_SGMT 0xA502
|
||||||
|
|
||||||
/* JTAG identification value for all existing Flash-based MSP430 devices
|
/* JTAG identification value for all existing Flash-based MSP430 devices
|
||||||
*/
|
*/
|
||||||
#define JTAG_ID_CPU16 0x89
|
#define JTAG_ID_CPU16 0x89
|
||||||
|
|
301
drivers/mehfet.c
301
drivers/mehfet.c
|
@ -223,257 +223,6 @@ static const struct jtdev_func jtdev_func_mehfet = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
// TODO: these five are kinda copied from pif.c, should be deduplicated
|
|
||||||
|
|
||||||
static int read_words(device_t dev_base, const struct chipinfo_memory *m,
|
|
||||||
address_t addr, address_t len, uint8_t *data)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: read_words: addr=0x%04x, len=0x%x\n", addr, len);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
struct jtdev *p = &dev->jtag;
|
|
||||||
|
|
||||||
for (unsigned int index = 0; index < len; index += 2) {
|
|
||||||
unsigned int word = jtag_read_mem(p, 16, addr+index);
|
|
||||||
data[index ] = word & 0x00ff;
|
|
||||||
data[index+1] = (word >> 8) & 0x00ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p->failed ? -1 : len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int write_ram_word(struct jtdev *p, address_t addr, uint16_t value)
|
|
||||||
{
|
|
||||||
jtag_write_mem(p, 16, addr, value);
|
|
||||||
|
|
||||||
return p->failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int write_flash_block(struct jtdev *p, address_t addr,
|
|
||||||
address_t len, const uint8_t *data)
|
|
||||||
{
|
|
||||||
uint16_t* word = malloc( len / 2 * sizeof(*word) );
|
|
||||||
if (!word) {
|
|
||||||
pr_error("mehfet: failed to allocate memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < len/2; i++) {
|
|
||||||
word[i]=data[2*i] + (((uint16_t)data[2*i+1]) << 8);
|
|
||||||
}
|
|
||||||
jtag_write_flash(p, addr, len/2, word);
|
|
||||||
|
|
||||||
free(word);
|
|
||||||
|
|
||||||
return p->failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write a word-aligned block to any kind of memory.
|
|
||||||
* returns the number of bytes written or -1 on failure
|
|
||||||
*/
|
|
||||||
static int write_words(device_t dev_base, const struct chipinfo_memory *m,
|
|
||||||
address_t addr, address_t len, const uint8_t *data)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
struct jtdev *p = &dev->jtag;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (m->type != CHIPINFO_MEMTYPE_FLASH) {
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: write_words: addr=0x%04x, len=0x%x data=0x%04x\n",
|
|
||||||
addr, len, r16le(data));
|
|
||||||
if (len != 2) {
|
|
||||||
printc_dbg("mehfet: WARN: write_words: len != 2! but 0x%04x\n", len);
|
|
||||||
__builtin_trap();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
len = 2;
|
|
||||||
r = write_ram_word(p, addr, r16le(data));
|
|
||||||
} else {
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: write_flash_block: addr=0x%04x, len=0x%x\n", addr, len);
|
|
||||||
#endif
|
|
||||||
r = write_flash_block(p, addr, len, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r < 0) {
|
|
||||||
printc_err("mehfet: write_words at address 0x%x failed\n", addr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static int mehfet_readmem(device_t dev_base, address_t addr,
|
|
||||||
uint8_t *mem, address_t len)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
return readmem(dev_base, addr, mem, len, read_words);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mehfet_writemem(device_t dev_base, address_t addr,
|
|
||||||
const uint8_t *mem, address_t len)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
return writemem(dev_base, addr, mem, len, write_words, read_words);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mehfet_setregs(device_t dev_base, const address_t *regs)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: set regs\n");
|
|
||||||
#endif
|
|
||||||
for (int i = 0; i < DEVICE_NUM_REGS; i++) {
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: [%d] = 0x%04x\n", i, regs[i]);
|
|
||||||
#endif
|
|
||||||
jtag_write_reg(&dev->jtag, i, regs[i]);
|
|
||||||
}
|
|
||||||
return dev->jtag.failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mehfet_getregs(device_t dev_base, address_t *regs)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: get regs\n");
|
|
||||||
#endif
|
|
||||||
for (int i = 0; i < DEVICE_NUM_REGS; i++) {
|
|
||||||
regs[i] = jtag_read_reg(&dev->jtag, i);
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: [%d] = 0x%04x\n", i, regs[i]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return dev->jtag.failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mehfet_ctl(device_t dev_base, device_ctl_t type)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case DEVICE_CTL_RESET:
|
|
||||||
/* perform soft reset */
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: soft reset (PUC)\n");
|
|
||||||
#endif
|
|
||||||
jtag_execute_puc(&dev->jtag);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEVICE_CTL_RUN:
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: set breakpoints\n");
|
|
||||||
#endif
|
|
||||||
/* transfer changed breakpoints to device */
|
|
||||||
if (jtag_refresh_bps("mehfet", &dev->jtag.base, &dev->jtag) < 0) return -1;
|
|
||||||
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: run @ current PC\n");
|
|
||||||
#endif
|
|
||||||
/* start program execution at current PC */
|
|
||||||
jtag_release_device(&dev->jtag, 0xffff);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEVICE_CTL_HALT:
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: halt\n");
|
|
||||||
#endif
|
|
||||||
/* take device under JTAG control */
|
|
||||||
jtag_get_device(&dev->jtag);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEVICE_CTL_STEP:
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: single-step\n");
|
|
||||||
#endif
|
|
||||||
/* execute next instruction at current PC */
|
|
||||||
jtag_single_step(&dev->jtag);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printc_err("mehfet: unsupported operation %d\n", type);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dev->jtag.failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static device_status_t mehfet_poll(device_t dev_base)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
|
|
||||||
if (delay_ms(100) < 0 || ctrlc_check())
|
|
||||||
return DEVICE_STATUS_INTR;
|
|
||||||
|
|
||||||
int r = jtag_cpu_state(&dev->jtag);
|
|
||||||
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: cpu state: %d\n", r);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (r == 1) return DEVICE_STATUS_HALTED;
|
|
||||||
|
|
||||||
return DEVICE_STATUS_RUNNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mehfet_erase(device_t dev_base, device_erase_type_t type,
|
|
||||||
address_t addr)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case DEVICE_ERASE_MAIN:
|
|
||||||
jtag_erase_flash(&dev->jtag, JTAG_ERASE_MAIN, addr);
|
|
||||||
break;
|
|
||||||
case DEVICE_ERASE_ALL:
|
|
||||||
jtag_erase_flash(&dev->jtag, JTAG_ERASE_MASS, addr);
|
|
||||||
break;
|
|
||||||
case DEVICE_ERASE_SEGMENT:
|
|
||||||
jtag_erase_flash(&dev->jtag, JTAG_ERASE_SGMT, addr);
|
|
||||||
break;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: erase flash %d at %04x: %s\n", type, addr, dev->jtag.failed ? "failed" : "succeeded");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return dev->jtag.failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mehfet_getconfigfuses(device_t dev_base)
|
|
||||||
{
|
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
|
||||||
|
|
||||||
int r = jtag_get_config_fuses(&dev->jtag);
|
|
||||||
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
|
||||||
printc_dbg("mehfet: get_config_fuses: %d\n", r);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int check_dev_ok(struct mehfet_device* dev, const struct device_args* args,
|
static int check_dev_ok(struct mehfet_device* dev, const struct device_args* args,
|
||||||
|
@ -529,32 +278,6 @@ static int check_dev_ok(struct mehfet_device* dev, const struct device_args* arg
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_device(struct mehfet_device* dev) {
|
|
||||||
printc_dbg("Starting JTAG\n");
|
|
||||||
|
|
||||||
unsigned int jtagid = jtag_init(&dev->jtag);
|
|
||||||
if (dev->jtag.failed) return -1;
|
|
||||||
|
|
||||||
printc("JTAG ID: 0x%02x\n", jtagid);
|
|
||||||
if (jtagid != 0x89 && jtagid != 0x91) {
|
|
||||||
printc_err("mehfet: unexpected JTAG ID: 0x%02x\n", jtagid);
|
|
||||||
jtag_release_device(&dev->jtag, 0xfffe);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// JTAG fuse check has been performed, so we can now switch to a
|
|
||||||
// higher-speed physical transport suitable for ~350 kHz TCLK strobes used
|
|
||||||
// in (and required for) flash programming
|
|
||||||
int r = mehfet_cmd_set_clkspeed(dev->trans, true);
|
|
||||||
if (r < 0) {
|
|
||||||
jtag_release_device(&dev->jtag, 0xfffe);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void mehfet_destroy(device_t dev_base) {
|
static void mehfet_destroy(device_t dev_base) {
|
||||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
||||||
|
|
||||||
|
@ -619,7 +342,13 @@ static device_t mehfet_open(const struct device_args* args) {
|
||||||
goto FAIL;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = init_device(dev);
|
r = jtag_dev_init(&dev->jtag);
|
||||||
|
if (r < 0) goto FAIL;
|
||||||
|
|
||||||
|
// JTAG fuse check has been performed, so we can now switch to a
|
||||||
|
// higher-speed physical transport suitable for ~350 kHz TCLK strobes used
|
||||||
|
// in (and required for) flash programming
|
||||||
|
r = mehfet_cmd_set_clkspeed(dev->trans, true);
|
||||||
if (r < 0) goto FAIL;
|
if (r < 0) goto FAIL;
|
||||||
|
|
||||||
#ifdef DEBUG_MEHFET_DRIVER
|
#ifdef DEBUG_MEHFET_DRIVER
|
||||||
|
@ -638,13 +367,13 @@ const struct device_class device_mehfet = {
|
||||||
.help = "MehFET USB JTAG/SBW device",
|
.help = "MehFET USB JTAG/SBW device",
|
||||||
.open = mehfet_open,
|
.open = mehfet_open,
|
||||||
.destroy = mehfet_destroy,
|
.destroy = mehfet_destroy,
|
||||||
.readmem = mehfet_readmem,
|
.readmem = jtag_dev_readmem,
|
||||||
.writemem = mehfet_writemem,
|
.writemem = jtag_dev_writemem,
|
||||||
.getregs = mehfet_getregs,
|
.getregs = jtag_dev_getregs,
|
||||||
.setregs = mehfet_setregs,
|
.setregs = jtag_dev_setregs,
|
||||||
.ctl = mehfet_ctl,
|
.ctl = jtag_dev_ctl,
|
||||||
.poll = mehfet_poll,
|
.poll = jtag_dev_poll,
|
||||||
.erase = mehfet_erase,
|
.erase = jtag_dev_erase,
|
||||||
.getconfigfuses = mehfet_getconfigfuses
|
.getconfigfuses = jtag_dev_getconfigfuses
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
299
drivers/pif.c
299
drivers/pif.c
|
@ -38,252 +38,7 @@ struct pif_device {
|
||||||
struct jtdev jtag;
|
struct jtdev jtag;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*============================================================================*/
|
|
||||||
/* pif MSP430 JTAG operations */
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
/* Read a word-aligned block from any kind of memory
|
|
||||||
* returns the number of bytes read or -1 on failure
|
|
||||||
*/
|
|
||||||
static int read_words(device_t dev, const struct chipinfo_memory *m,
|
|
||||||
address_t addr, address_t len, uint8_t *data)
|
|
||||||
{
|
|
||||||
struct pif_device *pif = (struct pif_device *)dev;
|
|
||||||
struct jtdev *p = &pif->jtag;
|
|
||||||
unsigned int index;
|
|
||||||
unsigned int word;
|
|
||||||
|
|
||||||
for ( index = 0; index < len; index += 2 ) {
|
|
||||||
word = jtag_read_mem( p, 16, addr+index );
|
|
||||||
data[index] = word & 0x00ff;
|
|
||||||
data[index+1] = (word >> 8) & 0x00ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p->failed ? -1 : len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Write a word to RAM */
|
|
||||||
static int write_ram_word( struct jtdev *p, address_t addr,
|
|
||||||
uint16_t value )
|
|
||||||
{
|
|
||||||
jtag_write_mem( p, 16, addr, value );
|
|
||||||
|
|
||||||
return p->failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Write a word-aligned flash block. */
|
|
||||||
/* The starting address must be within the flash memory range. */
|
|
||||||
|
|
||||||
static int write_flash_block( struct jtdev *p, address_t addr,
|
|
||||||
address_t len,
|
|
||||||
const uint8_t *data)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
uint16_t *word;
|
|
||||||
|
|
||||||
word = malloc( len / 2 * sizeof(*word) );
|
|
||||||
if (!word) {
|
|
||||||
pr_error("pif: failed to allocate memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < len/2; i++) {
|
|
||||||
word[i]=data[2*i] + (((uint16_t)data[2*i+1]) << 8);
|
|
||||||
}
|
|
||||||
jtag_write_flash( p, addr, len/2, word );
|
|
||||||
|
|
||||||
free(word);
|
|
||||||
|
|
||||||
return p->failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write a word-aligned block to any kind of memory.
|
|
||||||
* returns the number of bytes written or -1 on failure
|
|
||||||
*/
|
|
||||||
static int write_words(device_t dev, const struct chipinfo_memory *m,
|
|
||||||
address_t addr, address_t len, const uint8_t *data)
|
|
||||||
{
|
|
||||||
struct pif_device *pif = (struct pif_device *)dev;
|
|
||||||
struct jtdev *p = &pif->jtag;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (m->type != CHIPINFO_MEMTYPE_FLASH) {
|
|
||||||
len = 2;
|
|
||||||
r = write_ram_word(p, addr, r16le(data));
|
|
||||||
} else {
|
|
||||||
r = write_flash_block(p, addr, len, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r < 0) {
|
|
||||||
printc_err("pif: write_words at address 0x%x failed\n", addr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static int init_device(struct jtdev *p)
|
|
||||||
{
|
|
||||||
unsigned int jtag_id;
|
|
||||||
|
|
||||||
printc_dbg("Starting JTAG\n");
|
|
||||||
jtag_id = jtag_init(p);
|
|
||||||
printc("JTAG ID: 0x%02x\n", jtag_id);
|
|
||||||
if (jtag_id != 0x89 && jtag_id != 0x91) {
|
|
||||||
printc_err("pif: unexpected JTAG ID: 0x%02x\n", jtag_id);
|
|
||||||
jtag_release_device(p, 0xfffe);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===== MSPDebug Device interface ============================================*/
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static int pif_readmem( device_t dev_base,
|
|
||||||
address_t addr,
|
|
||||||
uint8_t* mem,
|
|
||||||
address_t len )
|
|
||||||
{
|
|
||||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
return readmem(dev_base, addr, mem, len, read_words);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static int pif_writemem( device_t dev_base,
|
|
||||||
address_t addr,
|
|
||||||
const uint8_t* mem,
|
|
||||||
address_t len )
|
|
||||||
{
|
|
||||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
return writemem(dev_base, addr, mem, len, write_words, read_words);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static int pif_getregs(device_t dev_base, address_t *regs)
|
|
||||||
{
|
|
||||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < DEVICE_NUM_REGS; i++)
|
|
||||||
regs[i] = jtag_read_reg(&dev->jtag, i);
|
|
||||||
|
|
||||||
return dev->jtag.failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static int pif_setregs( device_t dev_base, const address_t* regs )
|
|
||||||
{
|
|
||||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < DEVICE_NUM_REGS; i++) {
|
|
||||||
jtag_write_reg( &dev->jtag, i, regs[i] );
|
|
||||||
}
|
|
||||||
return dev->jtag.failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static int pif_ctl(device_t dev_base, device_ctl_t type)
|
|
||||||
{
|
|
||||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
|
||||||
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case DEVICE_CTL_RESET:
|
|
||||||
/* perform soft reset */
|
|
||||||
jtag_execute_puc(&dev->jtag);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEVICE_CTL_RUN:
|
|
||||||
/* transfer changed breakpoints to device */
|
|
||||||
if (jtag_refresh_bps("pif", &dev->jtag.base, &dev->jtag) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* start program execution at current PC */
|
|
||||||
jtag_release_device(&dev->jtag, 0xffff);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEVICE_CTL_HALT:
|
|
||||||
/* take device under JTAG control */
|
|
||||||
jtag_get_device(&dev->jtag);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEVICE_CTL_STEP:
|
|
||||||
/* execute next instruction at current PC */
|
|
||||||
jtag_single_step(&dev->jtag);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printc_err("pif: unsupported operation\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dev->jtag.failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static device_status_t pif_poll(device_t dev_base)
|
|
||||||
{
|
|
||||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
|
||||||
|
|
||||||
if (delay_ms(100) < 0 || ctrlc_check())
|
|
||||||
return DEVICE_STATUS_INTR;
|
|
||||||
|
|
||||||
if (jtag_cpu_state(&dev->jtag) == 1) {
|
|
||||||
return DEVICE_STATUS_HALTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DEVICE_STATUS_RUNNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static int pif_erase( device_t dev_base,
|
|
||||||
device_erase_type_t type,
|
|
||||||
address_t addr )
|
|
||||||
{
|
|
||||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
|
||||||
|
|
||||||
dev->jtag.failed = 0;
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case DEVICE_ERASE_MAIN:
|
|
||||||
jtag_erase_flash ( &dev->jtag, JTAG_ERASE_MAIN, addr );
|
|
||||||
break;
|
|
||||||
case DEVICE_ERASE_ALL:
|
|
||||||
jtag_erase_flash ( &dev->jtag, JTAG_ERASE_MASS, addr );
|
|
||||||
break;
|
|
||||||
case DEVICE_ERASE_SEGMENT:
|
|
||||||
jtag_erase_flash ( &dev->jtag, JTAG_ERASE_SGMT, addr );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dev->jtag.failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
static int pif_getconfigfuses(device_t dev_base)
|
|
||||||
{
|
|
||||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
|
||||||
|
|
||||||
return jtag_get_config_fuses(&dev->jtag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
static device_t pif_open(const struct device_args *args)
|
static device_t pif_open(const struct device_args *args)
|
||||||
{
|
{
|
||||||
|
@ -317,7 +72,7 @@ static device_t pif_open(const struct device_args *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_device(&dev->jtag) < 0) {
|
if (jtag_dev_init(&dev->jtag) < 0) {
|
||||||
printc_err("pif: initialization failed\n");
|
printc_err("pif: initialization failed\n");
|
||||||
free(dev);
|
free(dev);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -360,7 +115,7 @@ static device_t gpio_open(const struct device_args *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_device(&dev->jtag) < 0) {
|
if (jtag_dev_init(&dev->jtag) < 0) {
|
||||||
printc_err("gpio: initialization failed\n");
|
printc_err("gpio: initialization failed\n");
|
||||||
free(dev);
|
free(dev);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -404,7 +159,7 @@ static device_t bp_open(const struct device_args *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_device(&dev->jtag) < 0) {
|
if (jtag_dev_init(&dev->jtag) < 0) {
|
||||||
printc_err("bp: initialization failed\n");
|
printc_err("bp: initialization failed\n");
|
||||||
free(dev);
|
free(dev);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -431,14 +186,14 @@ const struct device_class device_pif = {
|
||||||
.help = "Parallel Port JTAG",
|
.help = "Parallel Port JTAG",
|
||||||
.open = pif_open,
|
.open = pif_open,
|
||||||
.destroy = pif_destroy,
|
.destroy = pif_destroy,
|
||||||
.readmem = pif_readmem,
|
.readmem = jtag_dev_readmem,
|
||||||
.writemem = pif_writemem,
|
.writemem = jtag_dev_writemem,
|
||||||
.getregs = pif_getregs,
|
.getregs = jtag_dev_getregs,
|
||||||
.setregs = pif_setregs,
|
.setregs = jtag_dev_setregs,
|
||||||
.ctl = pif_ctl,
|
.ctl = jtag_dev_ctl,
|
||||||
.poll = pif_poll,
|
.poll = jtag_dev_poll,
|
||||||
.erase = pif_erase,
|
.erase = jtag_dev_erase,
|
||||||
.getconfigfuses = pif_getconfigfuses
|
.getconfigfuses = jtag_dev_getconfigfuses
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct device_class device_gpio = {
|
const struct device_class device_gpio = {
|
||||||
|
@ -446,14 +201,14 @@ const struct device_class device_gpio = {
|
||||||
.help = "/sys/class/gpio direct connect",
|
.help = "/sys/class/gpio direct connect",
|
||||||
.open = gpio_open,
|
.open = gpio_open,
|
||||||
.destroy = pif_destroy,
|
.destroy = pif_destroy,
|
||||||
.readmem = pif_readmem,
|
.readmem = jtag_dev_readmem,
|
||||||
.writemem = pif_writemem,
|
.writemem = jtag_dev_writemem,
|
||||||
.getregs = pif_getregs,
|
.getregs = jtag_dev_getregs,
|
||||||
.setregs = pif_setregs,
|
.setregs = jtag_dev_setregs,
|
||||||
.ctl = pif_ctl,
|
.ctl = jtag_dev_ctl,
|
||||||
.poll = pif_poll,
|
.poll = jtag_dev_poll,
|
||||||
.erase = pif_erase,
|
.erase = jtag_dev_erase,
|
||||||
.getconfigfuses = pif_getconfigfuses
|
.getconfigfuses = jtag_dev_getconfigfuses
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct device_class device_bp = {
|
const struct device_class device_bp = {
|
||||||
|
@ -461,12 +216,12 @@ const struct device_class device_bp = {
|
||||||
.help = "Bus Pirate JTAG, MISO-TDO, MOSI-TDI, CS-TMS, AUX-RESET, CLK-TCK",
|
.help = "Bus Pirate JTAG, MISO-TDO, MOSI-TDI, CS-TMS, AUX-RESET, CLK-TCK",
|
||||||
.open = bp_open,
|
.open = bp_open,
|
||||||
.destroy = pif_destroy,
|
.destroy = pif_destroy,
|
||||||
.readmem = pif_readmem,
|
.readmem = jtag_dev_readmem,
|
||||||
.writemem = pif_writemem,
|
.writemem = jtag_dev_writemem,
|
||||||
.getregs = pif_getregs,
|
.getregs = jtag_dev_getregs,
|
||||||
.setregs = pif_setregs,
|
.setregs = jtag_dev_setregs,
|
||||||
.ctl = pif_ctl,
|
.ctl = jtag_dev_ctl,
|
||||||
.poll = pif_poll,
|
.poll = jtag_dev_poll,
|
||||||
.erase = pif_erase,
|
.erase = jtag_dev_erase,
|
||||||
.getconfigfuses = pif_getconfigfuses
|
.getconfigfuses = jtag_dev_getconfigfuses
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue