Compare commits

...

1 commit

Author SHA1 Message Date
Jeff Epler
b3e35a54ee spi: go about 3x faster to write/verify, but layer violations galore
.. and sensitivity to Linux <=> hm2 SPI speed (works at 8MHz, not at 24MHz).
Write is now ~7.8s, verify ~6.0s
2014-09-11 19:01:16 -05:00
5 changed files with 80 additions and 21 deletions

View file

@ -59,4 +59,5 @@ int eeprom_verify(llio_t *self, char *bitfile_name, u32 start_address);
void eeprom_init(llio_t *self);
void eeprom_cleanup(llio_t *self);
extern spi_eeprom_dev_t eeprom_access;
#endif

View file

@ -38,7 +38,7 @@ extern spi_eeprom_dev_t eeprom_access;
// spi access via hm2 registers
static void wait_for_data_hm2(llio_t *self) {
void wait_for_data_hm2(llio_t *self) {
u32 i = 0;
u32 data = 0;
@ -309,13 +309,13 @@ static u8 recv_byte_epp(llio_t *self) {
// pci flash
static void send_address(llio_t *self, u32 addr) {
void send_address(llio_t *self, u32 addr) {
eeprom_access.send_byte(self, (addr >> 16) & 0xFF);
eeprom_access.send_byte(self, (addr >> 8) & 0xFF);
eeprom_access.send_byte(self, addr & 0xFF);
}
static void write_enable(llio_t *self) {
void write_enable(llio_t *self) {
eeprom_access.prefix(self);
eeprom_access.send_byte(self, SPI_CMD_WRITE_ENABLE);
eeprom_access.suffix(self);
@ -342,7 +342,7 @@ u8 read_flash_id(llio_t *self) {
return ret;
}
static void wait_for_write(llio_t *self) {
void wait_for_write(llio_t *self) {
u8 stat = read_status(self);
while ((stat & WRITE_IN_PROGRESS_MASK) != 0) {

View file

@ -22,6 +22,7 @@
#include <string.h>
#include "eeprom_local.h"
#include "eeprom.h"
#include "spi_boards.h"
#include "common.h"
#include "spilbp.h"
@ -29,6 +30,47 @@
extern board_t boards[MAX_BOARDS];
extern int boards_count;
#if (PAGE_SIZE * 16) > 4096
#error This code does not work with EEPROM pages that big
#endif
static void spi_read_page(llio_t *self, u32 addr, void *buff) {
int i, j;
u32 wide[4*PAGE_SIZE];
for(i=0, j=0; i<PAGE_SIZE; i++) {
wide[j++] = spilbp_write_command(HM2_SPI_DATA_REG, 1, false);
wide[j++] = 0;
wide[j++] = spilbp_read_command(HM2_SPI_DATA_REG, 1, false);
wide[j++] = 0;
}
eeprom_access.prefix(self);
eeprom_access.send_byte(self, SPI_CMD_READ);
send_address(self, addr);
spilbp_transact(wide, sizeof(wide));
eeprom_access.suffix(self);
for(i=0; i<PAGE_SIZE; i++) ((u8*)buff)[i] = wide[4*i+3];
}
static void spi_write_page(llio_t *self, u32 addr, void *buff) {
int i, j;
u32 wide[2*PAGE_SIZE];
for(i=0, j=0; i<PAGE_SIZE; i++) {
wide[j++] = spilbp_write_command(HM2_SPI_DATA_REG, 1, false);
wide[j++] = ((u8*)buff)[i];
}
write_enable(self);
eeprom_access.prefix(self);
eeprom_access.send_byte(self, SPI_CMD_PAGE_WRITE);
send_address(self, addr);
spilbp_transact(wide, sizeof(wide));
eeprom_access.suffix(self);
wait_for_write(self);
}
static int spi_board_open(board_t *board) {
eeprom_init(&(board->llio));
board->flash_id = read_flash_id(&(board->llio));
@ -38,6 +80,8 @@ static int spi_board_open(board_t *board) {
} else {
board->flash_start_address = 0;
}
eeprom_access.read_page = spi_read_page;
eeprom_access.write_page = spi_write_page;
return 0;
}
@ -54,27 +98,31 @@ void spi_boards_cleanup(board_access_t *access) {
spilbp_release();
}
void spi_read(llio_t *self, u32 off, void *buf, int sz) {
return spilbp_read(off, buf, sz);
static
int spi_read(llio_t *self, u32 off, void *buf, int sz) {
spilbp_read(off, buf, sz, true);
return 1;
}
void spi_write(llio_t *self, u32 off, void *buf, int sz) {
return spilbp_write(off, buf, sz);
static
int spi_write(llio_t *self, u32 off, void *buf, int sz) {
spilbp_write(off, buf, sz, true);
return 1;
}
void spi_boards_scan(board_access_t *access) {
u32 buf[4];
u32 cookie[] = {0x55aacafe, 0x54534f48, 0x32544f4d};
if(spilbp_read(0x100, &buf, sizeof(buf)) < 0) return;
if(spilbp_read(0x100, &buf, sizeof(buf), true) < 0) return;
if(memcmp(buf, cookie, sizeof(cookie))) {
fprintf(stderr, "Unexpected cookie at 0000..000c:\n%08x %08x %08x\n",
buf[0], buf[1], buf[2]);
return 0;
return;
}
char ident[8];
if(spilbp_read(buf[3] + 0xc, &ident, sizeof(ident)) < 0) return;
if(spilbp_read(buf[3] + 0xc, &ident, sizeof(ident), true) < 0) return;
if(!memcmp(ident, "MESA7I90", 8)) {
board_t *board = &boards[boards_count];

View file

@ -33,21 +33,19 @@
int sd = -1;
struct spi_ioc_transfer settings;
static u32 read_command(u16 addr, unsigned nelem) {
bool increment = true;
u32 spilbp_read_command(u16 addr, unsigned nelem, bool increment) {
return (addr << 16) | 0xA000 | (increment ? 0x800 : 0) | (nelem << 4);
}
static u32 write_command(u16 addr, unsigned nelem) {
bool increment = true;
u32 spilbp_write_command(u16 addr, unsigned nelem, bool increment) {
return (addr << 16) | 0xB000 | (increment ? 0x800 : 0) | (nelem << 4);
}
int spilbp_write(u16 addr, void *buffer, int size) {
int spilbp_write(u16 addr, void *buffer, int size, bool increment) {
if(size % 4 != 0) return -1;
u32 txbuf[1+size/4];
txbuf[0] = write_command(addr, size/4);
txbuf[0] = spilbp_write_command(addr, size/4, increment);
memcpy(txbuf + 1, buffer, size);
struct spi_ioc_transfer t;
@ -60,10 +58,10 @@ int spilbp_write(u16 addr, void *buffer, int size) {
return 0;
}
int spilbp_read(u16 addr, void *buffer, int size) {
int spilbp_read(u16 addr, void *buffer, int size, bool increment) {
if(size % 4 != 0) return -1;
u32 trxbuf[1+size/4];
trxbuf[0] = read_command(addr, size/4);
trxbuf[0] = spilbp_read_command(addr, size/4, increment);
memset(trxbuf+1, 0, size);
struct spi_ioc_transfer t;
@ -78,6 +76,14 @@ int spilbp_read(u16 addr, void *buffer, int size) {
return 0;
}
int spilbp_transact(void *buffer, size_t size) {
struct spi_ioc_transfer t;
t = settings;
t.tx_buf = t.rx_buf = (uint64_t)(intptr_t)buffer;
t.len = size;
return ioctl(sd, SPI_IOC_MESSAGE(1), &t);
}
void spilbp_print_info() {
}

View file

@ -20,6 +20,7 @@
#define __SPILBP_H
#include "types.h"
#include <stdbool.h>
#include "common.h"
#define SPILBP_SENDRECV_DEBUG 0
@ -40,9 +41,12 @@ typedef struct {
void spilbp_print_info();
void spilbp_init(board_access_t *access);
void spilbp_release();
int spilbp_write(u32 addr, void *buffer, int size);
int spilbp_read(u32 addr, void *buffer, int size);
int spilbp_write(u32 addr, void *buffer, int size, bool increment);
int spilbp_read(u32 addr, void *buffer, int size, bool increment);
u32 spilbp_read_command(u16 addr, unsigned nelem, bool increment);
u32 spilbp_write_command(u16 addr, unsigned nelem, bool increment);
int spilbp_transact(void *buffer, size_t size);
#endif