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_init(llio_t *self);
void eeprom_cleanup(llio_t *self); void eeprom_cleanup(llio_t *self);
extern spi_eeprom_dev_t eeprom_access;
#endif #endif

View file

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

View file

@ -22,6 +22,7 @@
#include <string.h> #include <string.h>
#include "eeprom_local.h" #include "eeprom_local.h"
#include "eeprom.h"
#include "spi_boards.h" #include "spi_boards.h"
#include "common.h" #include "common.h"
#include "spilbp.h" #include "spilbp.h"
@ -29,6 +30,47 @@
extern board_t boards[MAX_BOARDS]; extern board_t boards[MAX_BOARDS];
extern int boards_count; 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) { static int spi_board_open(board_t *board) {
eeprom_init(&(board->llio)); eeprom_init(&(board->llio));
board->flash_id = read_flash_id(&(board->llio)); board->flash_id = read_flash_id(&(board->llio));
@ -38,6 +80,8 @@ static int spi_board_open(board_t *board) {
} else { } else {
board->flash_start_address = 0; board->flash_start_address = 0;
} }
eeprom_access.read_page = spi_read_page;
eeprom_access.write_page = spi_write_page;
return 0; return 0;
} }
@ -54,27 +98,31 @@ void spi_boards_cleanup(board_access_t *access) {
spilbp_release(); spilbp_release();
} }
void spi_read(llio_t *self, u32 off, void *buf, int sz) { static
return spilbp_read(off, buf, sz); 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) { static
return spilbp_write(off, buf, sz); 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) { void spi_boards_scan(board_access_t *access) {
u32 buf[4]; u32 buf[4];
u32 cookie[] = {0x55aacafe, 0x54534f48, 0x32544f4d}; 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))) { if(memcmp(buf, cookie, sizeof(cookie))) {
fprintf(stderr, "Unexpected cookie at 0000..000c:\n%08x %08x %08x\n", fprintf(stderr, "Unexpected cookie at 0000..000c:\n%08x %08x %08x\n",
buf[0], buf[1], buf[2]); buf[0], buf[1], buf[2]);
return 0; return;
} }
char ident[8]; 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)) { if(!memcmp(ident, "MESA7I90", 8)) {
board_t *board = &boards[boards_count]; board_t *board = &boards[boards_count];

View file

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

View file

@ -20,6 +20,7 @@
#define __SPILBP_H #define __SPILBP_H
#include "types.h" #include "types.h"
#include <stdbool.h>
#include "common.h" #include "common.h"
#define SPILBP_SENDRECV_DEBUG 0 #define SPILBP_SENDRECV_DEBUG 0
@ -40,9 +41,12 @@ typedef struct {
void spilbp_print_info(); void spilbp_print_info();
void spilbp_init(board_access_t *access); void spilbp_init(board_access_t *access);
void spilbp_release(); void spilbp_release();
int spilbp_write(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); 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 #endif