|
|
|
@ -4,16 +4,54 @@ |
|
|
|
|
|
|
|
|
|
#include <spi.h> |
|
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <sys/mman.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#include <spi_flash.h> |
|
|
|
|
|
|
|
|
|
// XXX: 16 is used in other places in this file too
|
|
|
|
|
#define FLASH_SIZE (1 << 16) |
|
|
|
|
|
|
|
|
|
static int virtual_spi_tx_rx(struct spi_dev *dev, void *rx_buf, size_t rx_len, |
|
|
|
|
const void *tx_buf, size_t tx_len); |
|
|
|
|
const void *tx_buf, size_t tx_len); |
|
|
|
|
|
|
|
|
|
static struct spi_ops virtual_spi_ops = { |
|
|
|
|
.tx_rx = virtual_spi_tx_rx, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void virtual_spi_init(void) |
|
|
|
|
// XXX: make part of dev struct
|
|
|
|
|
static unsigned char *flash_map; |
|
|
|
|
|
|
|
|
|
static int virtual_spi_init(void) |
|
|
|
|
{ |
|
|
|
|
/* TODO */ |
|
|
|
|
/* TODO: close this fd */ |
|
|
|
|
FILE *flash_fd; |
|
|
|
|
int exists = 0; |
|
|
|
|
|
|
|
|
|
exists = access("flash", F_OK) != -1; |
|
|
|
|
/* XXX: treat not existing separately from existing file, since we want to
|
|
|
|
|
* null one that doesn't exist yet */ |
|
|
|
|
flash_fd = fopen("flash", "ab+"); |
|
|
|
|
if (!exists) { |
|
|
|
|
fprintf(stderr, |
|
|
|
|
"flash doesn't exist yet, creating and filling now\n"); |
|
|
|
|
char buf[FLASH_SIZE]; |
|
|
|
|
int ret = fwrite(buf, sizeof(char), FLASH_SIZE, flash_fd); |
|
|
|
|
fprintf(stderr, "fwrite ret: %d\n", ret); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (flash_fd == NULL) { |
|
|
|
|
perror("flash_open"); |
|
|
|
|
fprintf(stderr, "spi init failed\n"); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
flash_map = |
|
|
|
|
mmap(NULL, FLASH_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, |
|
|
|
|
fileno(flash_fd), 0); |
|
|
|
|
fprintf(stderr, "flash: %p\n", flash_map); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct spi_dev *spi_probe(void) |
|
|
|
@ -24,11 +62,14 @@ struct spi_dev *spi_probe(void) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
dev->ops = &virtual_spi_ops; |
|
|
|
|
/*
|
|
|
|
|
dev->dev_id = SPI1; |
|
|
|
|
/*
|
|
|
|
|
dev->dev_id = SPI1; |
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
virtual_spi_init(); |
|
|
|
|
*/ |
|
|
|
|
if (virtual_spi_init()) { |
|
|
|
|
free(dev); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return dev; |
|
|
|
|
} |
|
|
|
@ -36,10 +77,74 @@ struct spi_dev *spi_probe(void) |
|
|
|
|
void spi_release(struct spi_dev *dev) |
|
|
|
|
{ |
|
|
|
|
free(dev); |
|
|
|
|
/* TODO: close fd, close mmap */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int virtual_spi_tx_rx(struct spi_dev *dev, void *rx_buf, size_t rx_len, |
|
|
|
|
const void *tx_buf, size_t tx_len) |
|
|
|
|
const void *tx_buf, size_t tx_len) |
|
|
|
|
{ |
|
|
|
|
unsigned char *rx_buf_c = (unsigned char *)rx_buf; |
|
|
|
|
unsigned char *tx_buf_c = (unsigned char *)tx_buf; |
|
|
|
|
|
|
|
|
|
unsigned char cmd = tx_buf_c[0]; |
|
|
|
|
|
|
|
|
|
fprintf(stderr, "? RX len: %ld\n", rx_len); |
|
|
|
|
|
|
|
|
|
if (tx_buf != NULL) { |
|
|
|
|
fprintf(stderr, "? TX Command: %d\n", cmd); |
|
|
|
|
fprintf(stderr, "? TX len: %ld\n", tx_len); |
|
|
|
|
if (cmd == SPI_FLASH_JEDEC_ID) { |
|
|
|
|
if (rx_len != 3) { |
|
|
|
|
fprintf(stderr, "UNEXPECTED RX_LEN\n"); |
|
|
|
|
} |
|
|
|
|
fprintf(stderr, "SPI_FLASH_JEDEC_ID\n"); |
|
|
|
|
rx_buf_c[0] = 0x1; |
|
|
|
|
rx_buf_c[1] = 0x1; |
|
|
|
|
rx_buf_c[2] = 16; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (cmd == SPI_FLASH_READ) { |
|
|
|
|
fprintf(stderr, "SPI_FLASH_READ\n"); |
|
|
|
|
unsigned int addr = (tx_buf_c[1] << 16) + |
|
|
|
|
(tx_buf_c[2] << 8) + tx_buf_c[3]; |
|
|
|
|
fprintf(stderr, "addr: %d\n", addr); |
|
|
|
|
fprintf(stderr, "memmove: %d\n", addr); |
|
|
|
|
memmove(rx_buf_c, flash_map + addr, rx_len); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (cmd == SPI_FLASH_PAGE_PROGRAM) { |
|
|
|
|
fprintf(stderr, "SPI_FLASH_PAGE_PROGRAM\n"); |
|
|
|
|
unsigned int addr = (tx_buf_c[1] << 16) + |
|
|
|
|
(tx_buf_c[2] << 8) + tx_buf_c[3]; |
|
|
|
|
fprintf(stderr, "addr: %d\n", addr); |
|
|
|
|
fprintf(stderr, "memmove: %d\n", addr); |
|
|
|
|
memmove(flash_map + addr, tx_buf_c + 4, tx_len - 4); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (cmd == SPI_FLASH_ERASE_4K) { |
|
|
|
|
fprintf(stderr, "SPI_FLASH_ERASE_4K\n"); |
|
|
|
|
unsigned int addr = (tx_buf_c[1] << 16) + |
|
|
|
|
(tx_buf_c[2] << 8) + tx_buf_c[3]; |
|
|
|
|
fprintf(stderr, "addr: %d\n", addr); |
|
|
|
|
memset(flash_map + addr, 0, 4096); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (cmd == SPI_FLASH_READ_SR1) { |
|
|
|
|
fprintf(stderr, "SPI_FLASH_READ_SR1\n"); |
|
|
|
|
/* Just report read/write/erase as done, we are never busy with mmap */ |
|
|
|
|
rx_buf_c[0] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (cmd == SPI_FLASH_WRITE_ENABLE) { |
|
|
|
|
fprintf(stderr, "SPI_FLASH_WRITE_ENABLE\n"); |
|
|
|
|
/* These can be stubs */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (cmd == SPI_FLASH_WRITE_DISABLE) { |
|
|
|
|
fprintf(stderr, "SPI_FLASH_WRITE_DISABLE\n"); |
|
|
|
|
/* These can be stubs */ |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|