318 lines
7.3 KiB
C
318 lines
7.3 KiB
C
/***************************************************************************
|
|
* Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
|
|
* *
|
|
* 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, see <http://www.gnu.org/licenses/>. *
|
|
***************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "target.h"
|
|
#include "jtag/jtag.h"
|
|
#include "avr32_jtag.h"
|
|
#include "avr32_mem.h"
|
|
|
|
int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
|
|
uint32_t addr, int count, uint32_t *buffer)
|
|
{
|
|
int i, retval;
|
|
uint32_t data;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i*4, &data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
/* XXX: Assume AVR32 is BE */
|
|
buffer[i] = be_to_h_u32((uint8_t *)&data);
|
|
}
|
|
|
|
return ERROR_OK;
|
|
}
|
|
|
|
int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
|
|
uint32_t addr, int count, uint16_t *buffer)
|
|
{
|
|
int i, retval;
|
|
uint32_t data;
|
|
|
|
i = 0;
|
|
|
|
/* any unaligned half-words? */
|
|
if (addr & 3) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i*2, &data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
/* XXX: Assume AVR32 is BE */
|
|
data = be_to_h_u32((uint8_t *)&data);
|
|
buffer[i] = (data >> 16) & 0xffff;
|
|
i++;
|
|
}
|
|
|
|
/* read all complete words */
|
|
for (; i < (count & ~1); i += 2) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i*2, &data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
/* XXX: Assume AVR32 is BE */
|
|
data = be_to_h_u32((uint8_t *)&data);
|
|
buffer[i] = data & 0xffff;
|
|
buffer[i+1] = (data >> 16) & 0xffff;
|
|
}
|
|
|
|
/* last halfword */
|
|
if (i < count) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i*2, &data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
/* XXX: Assume AVR32 is BE */
|
|
data = be_to_h_u32((uint8_t *)&data);
|
|
buffer[i] = data & 0xffff;
|
|
}
|
|
|
|
return ERROR_OK;
|
|
}
|
|
|
|
int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
|
|
uint32_t addr, int count, uint8_t *buffer)
|
|
{
|
|
int i, j, retval;
|
|
uint8_t data[4];
|
|
i = 0;
|
|
|
|
/* Do we have non-aligned bytes? */
|
|
if (addr & 3) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i, (uint32_t *)(void *)data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
for (j = addr & 3; (j < 4) && (i < count); j++, i++)
|
|
buffer[i] = data[3-j];
|
|
}
|
|
|
|
/* read all complete words */
|
|
for (; i < (count & ~3); i += 4) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i, (uint32_t *)(void *)data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
for (j = 0; j < 4; j++)
|
|
buffer[i+j] = data[3-j];
|
|
}
|
|
|
|
/* remaining bytes */
|
|
if (i < count) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i, (uint32_t *)(void *)data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
for (j = 0; i + j < count; j++)
|
|
buffer[i+j] = data[3-j];
|
|
}
|
|
|
|
return ERROR_OK;
|
|
}
|
|
|
|
int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
|
|
uint32_t addr, int count, const uint32_t *buffer)
|
|
{
|
|
int i, retval;
|
|
uint32_t data;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
/* XXX: Assume AVR32 is BE */
|
|
h_u32_to_be((uint8_t *)&data, buffer[i]);
|
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i*4, data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
}
|
|
|
|
return ERROR_OK;
|
|
}
|
|
|
|
int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
|
|
uint32_t addr, int count, const uint16_t *buffer)
|
|
{
|
|
int i, retval;
|
|
uint32_t data;
|
|
uint32_t data_out;
|
|
|
|
i = 0;
|
|
|
|
/*
|
|
* Do we have any non-aligned half-words?
|
|
*/
|
|
if (addr & 3) {
|
|
/*
|
|
* mwa_read will read whole world, no nead to fiddle
|
|
* with address. It will be truncated in set_addr
|
|
*/
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr, &data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
data = be_to_h_u32((uint8_t *)&data);
|
|
data = (buffer[i] << 16) | (data & 0xffff);
|
|
h_u32_to_be((uint8_t *)&data_out, data);
|
|
|
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr, data_out);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
i++;
|
|
}
|
|
|
|
/* write all complete words */
|
|
for (; i < (count & ~1); i += 2) {
|
|
/* XXX: Assume AVR32 is BE */
|
|
data = (buffer[i+1] << 16) | buffer[i];
|
|
h_u32_to_be((uint8_t *)&data_out, data);
|
|
|
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i*2, data_out);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
}
|
|
|
|
/* last halfword */
|
|
if (i < count) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i*2, &data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
data = be_to_h_u32((uint8_t *)&data);
|
|
data &= ~0xffff;
|
|
data |= buffer[i];
|
|
h_u32_to_be((uint8_t *)&data_out, data);
|
|
|
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i*2, data_out);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
}
|
|
|
|
return ERROR_OK;
|
|
}
|
|
|
|
int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
|
|
uint32_t addr, int count, const uint8_t *buffer)
|
|
{
|
|
int i, j, retval;
|
|
uint32_t data;
|
|
uint32_t data_out;
|
|
|
|
i = 0;
|
|
|
|
/*
|
|
* Do we have any non-aligned bytes?
|
|
*/
|
|
if (addr & 3) {
|
|
/*
|
|
* mwa_read will read whole world, no nead to fiddle
|
|
* with address. It will be truncated in set_addr
|
|
*/
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr, &data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
data = be_to_h_u32((uint8_t *)&data);
|
|
for (j = addr & 3; (j < 4) && (i < count); j++, i++) {
|
|
data &= ~(0xff << j*8);
|
|
data |= (buffer[i] << j*8);
|
|
}
|
|
|
|
h_u32_to_be((uint8_t *)&data_out, data);
|
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr, data_out);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
}
|
|
|
|
|
|
/* write all complete words */
|
|
for (; i < (count & ~3); i += 4) {
|
|
data = 0;
|
|
|
|
for (j = 0; j < 4; j++)
|
|
data |= (buffer[j+i] << j*8);
|
|
|
|
h_u32_to_be((uint8_t *)&data_out, data);
|
|
|
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i, data_out);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* Write trailing bytes
|
|
*/
|
|
if (i < count) {
|
|
retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr + i, &data);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
|
|
data = be_to_h_u32((uint8_t *)&data);
|
|
for (j = 0; i < count; j++, i++) {
|
|
data &= ~(0xff << j*8);
|
|
data |= (buffer[j+i] << j*8);
|
|
}
|
|
|
|
h_u32_to_be((uint8_t *)&data_out, data);
|
|
|
|
retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
|
|
addr+i, data_out);
|
|
|
|
if (retval != ERROR_OK)
|
|
return retval;
|
|
}
|
|
|
|
return ERROR_OK;
|
|
}
|