mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 23:22:37 +02:00
tree: Remove forward-declarations for spi masters
Reorder functions to avoid forward-declarations. It looks like for most of the spi masters this has already been done before, I covered remaining small ones in one patch. BUG=b:140394053 TEST=builds Change-Id: I23ff6b79d794876f73b327f18784ca7c04c32c84 Signed-off-by: Anastasia Klimchuk <aklm@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/50711 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org> Reviewed-by: Sam McNally <sammc@google.com> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
d784d484c9
commit
f1391c756f
191
buspirate_spi.c
191
buspirate_spi.c
@ -128,11 +128,6 @@ static int buspirate_wait_for_string(unsigned char *buf, const char *key)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int buspirate_spi_send_command_v1(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
|
||||||
const unsigned char *writearr, unsigned char *readarr);
|
|
||||||
static int buspirate_spi_send_command_v2(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
|
||||||
const unsigned char *writearr, unsigned char *readarr);
|
|
||||||
|
|
||||||
static struct spi_master spi_master_buspirate = {
|
static struct spi_master spi_master_buspirate = {
|
||||||
.features = SPI_MASTER_4BA,
|
.features = SPI_MASTER_4BA,
|
||||||
.max_data_read = MAX_DATA_UNSPECIFIED,
|
.max_data_read = MAX_DATA_UNSPECIFIED,
|
||||||
@ -205,6 +200,99 @@ out_shutdown:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int buspirate_spi_send_command_v1(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
||||||
|
const unsigned char *writearr, unsigned char *readarr)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
|
||||||
|
return SPI_INVALID_LENGTH;
|
||||||
|
|
||||||
|
/* 3 bytes extra for CS#, len, CS#. */
|
||||||
|
if (buspirate_commbuf_grow(writecnt + readcnt + 3))
|
||||||
|
return ERROR_OOM;
|
||||||
|
|
||||||
|
/* Assert CS# */
|
||||||
|
bp_commbuf[i++] = 0x02;
|
||||||
|
|
||||||
|
bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1);
|
||||||
|
memcpy(bp_commbuf + i, writearr, writecnt);
|
||||||
|
i += writecnt;
|
||||||
|
memset(bp_commbuf + i, 0, readcnt);
|
||||||
|
|
||||||
|
i += readcnt;
|
||||||
|
/* De-assert CS# */
|
||||||
|
bp_commbuf[i++] = 0x03;
|
||||||
|
|
||||||
|
ret = buspirate_sendrecv(bp_commbuf, i, i);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
msg_perr("Bus Pirate communication error!\n");
|
||||||
|
return SPI_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp_commbuf[0] != 0x01) {
|
||||||
|
msg_perr("Protocol error while lowering CS#!\n");
|
||||||
|
return SPI_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp_commbuf[1] != 0x01) {
|
||||||
|
msg_perr("Protocol error while reading/writing SPI!\n");
|
||||||
|
return SPI_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp_commbuf[i - 1] != 0x01) {
|
||||||
|
msg_perr("Protocol error while raising CS#!\n");
|
||||||
|
return SPI_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip CS#, length, writearr. */
|
||||||
|
memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int buspirate_spi_send_command_v2(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
||||||
|
const unsigned char *writearr, unsigned char *readarr)
|
||||||
|
{
|
||||||
|
int i = 0, ret = 0;
|
||||||
|
|
||||||
|
if (writecnt > 4096 || readcnt > 4096 || (readcnt + writecnt) > 4096)
|
||||||
|
return SPI_INVALID_LENGTH;
|
||||||
|
|
||||||
|
/* 5 bytes extra for command, writelen, readlen.
|
||||||
|
* 1 byte extra for Ack/Nack.
|
||||||
|
*/
|
||||||
|
if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1)))
|
||||||
|
return ERROR_OOM;
|
||||||
|
|
||||||
|
/* Combined SPI write/read. */
|
||||||
|
bp_commbuf[i++] = 0x04;
|
||||||
|
bp_commbuf[i++] = (writecnt >> 8) & 0xff;
|
||||||
|
bp_commbuf[i++] = writecnt & 0xff;
|
||||||
|
bp_commbuf[i++] = (readcnt >> 8) & 0xff;
|
||||||
|
bp_commbuf[i++] = readcnt & 0xff;
|
||||||
|
memcpy(bp_commbuf + i, writearr, writecnt);
|
||||||
|
|
||||||
|
ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
msg_perr("Bus Pirate communication error!\n");
|
||||||
|
return SPI_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp_commbuf[0] != 0x01) {
|
||||||
|
msg_perr("Protocol error while sending SPI write/read!\n");
|
||||||
|
return SPI_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip Ack. */
|
||||||
|
memcpy(readarr, bp_commbuf + 1, readcnt);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#define BP_FWVERSION(a,b) ((a) << 8 | (b))
|
#define BP_FWVERSION(a,b) ((a) << 8 | (b))
|
||||||
#define BP_HWVERSION(a,b) BP_FWVERSION(a,b)
|
#define BP_HWVERSION(a,b) BP_FWVERSION(a,b)
|
||||||
|
|
||||||
@ -571,96 +659,3 @@ int buspirate_spi_init(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int buspirate_spi_send_command_v1(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
|
||||||
const unsigned char *writearr, unsigned char *readarr)
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
|
|
||||||
return SPI_INVALID_LENGTH;
|
|
||||||
|
|
||||||
/* 3 bytes extra for CS#, len, CS#. */
|
|
||||||
if (buspirate_commbuf_grow(writecnt + readcnt + 3))
|
|
||||||
return ERROR_OOM;
|
|
||||||
|
|
||||||
/* Assert CS# */
|
|
||||||
bp_commbuf[i++] = 0x02;
|
|
||||||
|
|
||||||
bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1);
|
|
||||||
memcpy(bp_commbuf + i, writearr, writecnt);
|
|
||||||
i += writecnt;
|
|
||||||
memset(bp_commbuf + i, 0, readcnt);
|
|
||||||
|
|
||||||
i += readcnt;
|
|
||||||
/* De-assert CS# */
|
|
||||||
bp_commbuf[i++] = 0x03;
|
|
||||||
|
|
||||||
ret = buspirate_sendrecv(bp_commbuf, i, i);
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
msg_perr("Bus Pirate communication error!\n");
|
|
||||||
return SPI_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bp_commbuf[0] != 0x01) {
|
|
||||||
msg_perr("Protocol error while lowering CS#!\n");
|
|
||||||
return SPI_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bp_commbuf[1] != 0x01) {
|
|
||||||
msg_perr("Protocol error while reading/writing SPI!\n");
|
|
||||||
return SPI_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bp_commbuf[i - 1] != 0x01) {
|
|
||||||
msg_perr("Protocol error while raising CS#!\n");
|
|
||||||
return SPI_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip CS#, length, writearr. */
|
|
||||||
memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int buspirate_spi_send_command_v2(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
|
||||||
const unsigned char *writearr, unsigned char *readarr)
|
|
||||||
{
|
|
||||||
int i = 0, ret = 0;
|
|
||||||
|
|
||||||
if (writecnt > 4096 || readcnt > 4096 || (readcnt + writecnt) > 4096)
|
|
||||||
return SPI_INVALID_LENGTH;
|
|
||||||
|
|
||||||
/* 5 bytes extra for command, writelen, readlen.
|
|
||||||
* 1 byte extra for Ack/Nack.
|
|
||||||
*/
|
|
||||||
if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1)))
|
|
||||||
return ERROR_OOM;
|
|
||||||
|
|
||||||
/* Combined SPI write/read. */
|
|
||||||
bp_commbuf[i++] = 0x04;
|
|
||||||
bp_commbuf[i++] = (writecnt >> 8) & 0xff;
|
|
||||||
bp_commbuf[i++] = writecnt & 0xff;
|
|
||||||
bp_commbuf[i++] = (readcnt >> 8) & 0xff;
|
|
||||||
bp_commbuf[i++] = readcnt & 0xff;
|
|
||||||
memcpy(bp_commbuf + i, writearr, writecnt);
|
|
||||||
|
|
||||||
ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt);
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
msg_perr("Bus Pirate communication error!\n");
|
|
||||||
return SPI_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bp_commbuf[0] != 0x01) {
|
|
||||||
msg_perr("Protocol error while sending SPI write/read!\n");
|
|
||||||
return SPI_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip Ack. */
|
|
||||||
memcpy(readarr, bp_commbuf + 1, readcnt);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
173
ft2232_spi.c
173
ft2232_spi.c
@ -183,10 +183,93 @@ static int ft2232_shutdown(void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns 0 upon success, a negative number upon errors. */
|
||||||
static int ft2232_spi_send_command(const struct flashctx *flash,
|
static int ft2232_spi_send_command(const struct flashctx *flash,
|
||||||
unsigned int writecnt, unsigned int readcnt,
|
unsigned int writecnt, unsigned int readcnt,
|
||||||
const unsigned char *writearr,
|
const unsigned char *writearr,
|
||||||
unsigned char *readarr);
|
unsigned char *readarr)
|
||||||
|
{
|
||||||
|
struct ftdi_context *ftdic = &ftdic_context;
|
||||||
|
static unsigned char *buf = NULL;
|
||||||
|
/* failed is special. We use bitwise ops, but it is essentially bool. */
|
||||||
|
int i = 0, ret = 0, failed = 0;
|
||||||
|
size_t bufsize;
|
||||||
|
static size_t oldbufsize = 0;
|
||||||
|
|
||||||
|
if (writecnt > 65536 || readcnt > 65536)
|
||||||
|
return SPI_INVALID_LENGTH;
|
||||||
|
|
||||||
|
/* buf is not used for the response from the chip. */
|
||||||
|
bufsize = max(writecnt + 9, 260 + 9);
|
||||||
|
/* Never shrink. realloc() calls are expensive. */
|
||||||
|
if (!buf || bufsize > oldbufsize) {
|
||||||
|
buf = realloc(buf, bufsize);
|
||||||
|
if (!buf) {
|
||||||
|
msg_perr("Out of memory!\n");
|
||||||
|
/* TODO: What to do with buf? */
|
||||||
|
return SPI_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
oldbufsize = bufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Minimize USB transfers by packing as many commands as possible
|
||||||
|
* together. If we're not expecting to read, we can assert CS#, write,
|
||||||
|
* and deassert CS# all in one shot. If reading, we do three separate
|
||||||
|
* operations.
|
||||||
|
*/
|
||||||
|
msg_pspew("Assert CS#\n");
|
||||||
|
buf[i++] = SET_BITS_LOW;
|
||||||
|
buf[i++] = ~ 0x08 & pinlvl; /* assert CS (3rd) bit only */
|
||||||
|
buf[i++] = pindir;
|
||||||
|
|
||||||
|
if (writecnt) {
|
||||||
|
buf[i++] = MPSSE_DO_WRITE | MPSSE_WRITE_NEG;
|
||||||
|
buf[i++] = (writecnt - 1) & 0xff;
|
||||||
|
buf[i++] = ((writecnt - 1) >> 8) & 0xff;
|
||||||
|
memcpy(buf + i, writearr, writecnt);
|
||||||
|
i += writecnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optionally terminate this batch of commands with a
|
||||||
|
* read command, then do the fetch of the results.
|
||||||
|
*/
|
||||||
|
if (readcnt) {
|
||||||
|
buf[i++] = MPSSE_DO_READ;
|
||||||
|
buf[i++] = (readcnt - 1) & 0xff;
|
||||||
|
buf[i++] = ((readcnt - 1) >> 8) & 0xff;
|
||||||
|
ret = send_buf(ftdic, buf, i);
|
||||||
|
failed = ret;
|
||||||
|
/* We can't abort here, we still have to deassert CS#. */
|
||||||
|
if (ret)
|
||||||
|
msg_perr("send_buf failed before read: %i\n", ret);
|
||||||
|
i = 0;
|
||||||
|
if (ret == 0) {
|
||||||
|
/*
|
||||||
|
* FIXME: This is unreliable. There's no guarantee that
|
||||||
|
* we read the response directly after sending the read
|
||||||
|
* command. We may be scheduled out etc.
|
||||||
|
*/
|
||||||
|
ret = get_buf(ftdic, readarr, readcnt);
|
||||||
|
failed |= ret;
|
||||||
|
/* We can't abort here either. */
|
||||||
|
if (ret)
|
||||||
|
msg_perr("get_buf failed: %i\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_pspew("De-assert CS#\n");
|
||||||
|
buf[i++] = SET_BITS_LOW;
|
||||||
|
buf[i++] = pinlvl;
|
||||||
|
buf[i++] = pindir;
|
||||||
|
ret = send_buf(ftdic, buf, i);
|
||||||
|
failed |= ret;
|
||||||
|
if (ret)
|
||||||
|
msg_perr("send_buf failed at end: %i\n", ret);
|
||||||
|
|
||||||
|
return failed ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct spi_master spi_master_ft2232 = {
|
static const struct spi_master spi_master_ft2232 = {
|
||||||
.features = SPI_MASTER_4BA,
|
.features = SPI_MASTER_4BA,
|
||||||
@ -532,92 +615,4 @@ ftdi_err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 0 upon success, a negative number upon errors. */
|
|
||||||
static int ft2232_spi_send_command(const struct flashctx *flash,
|
|
||||||
unsigned int writecnt, unsigned int readcnt,
|
|
||||||
const unsigned char *writearr,
|
|
||||||
unsigned char *readarr)
|
|
||||||
{
|
|
||||||
struct ftdi_context *ftdic = &ftdic_context;
|
|
||||||
static unsigned char *buf = NULL;
|
|
||||||
/* failed is special. We use bitwise ops, but it is essentially bool. */
|
|
||||||
int i = 0, ret = 0, failed = 0;
|
|
||||||
size_t bufsize;
|
|
||||||
static size_t oldbufsize = 0;
|
|
||||||
|
|
||||||
if (writecnt > 65536 || readcnt > 65536)
|
|
||||||
return SPI_INVALID_LENGTH;
|
|
||||||
|
|
||||||
/* buf is not used for the response from the chip. */
|
|
||||||
bufsize = max(writecnt + 9, 260 + 9);
|
|
||||||
/* Never shrink. realloc() calls are expensive. */
|
|
||||||
if (!buf || bufsize > oldbufsize) {
|
|
||||||
buf = realloc(buf, bufsize);
|
|
||||||
if (!buf) {
|
|
||||||
msg_perr("Out of memory!\n");
|
|
||||||
/* TODO: What to do with buf? */
|
|
||||||
return SPI_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
oldbufsize = bufsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Minimize USB transfers by packing as many commands as possible
|
|
||||||
* together. If we're not expecting to read, we can assert CS#, write,
|
|
||||||
* and deassert CS# all in one shot. If reading, we do three separate
|
|
||||||
* operations.
|
|
||||||
*/
|
|
||||||
msg_pspew("Assert CS#\n");
|
|
||||||
buf[i++] = SET_BITS_LOW;
|
|
||||||
buf[i++] = ~ 0x08 & pinlvl; /* assert CS (3rd) bit only */
|
|
||||||
buf[i++] = pindir;
|
|
||||||
|
|
||||||
if (writecnt) {
|
|
||||||
buf[i++] = MPSSE_DO_WRITE | MPSSE_WRITE_NEG;
|
|
||||||
buf[i++] = (writecnt - 1) & 0xff;
|
|
||||||
buf[i++] = ((writecnt - 1) >> 8) & 0xff;
|
|
||||||
memcpy(buf + i, writearr, writecnt);
|
|
||||||
i += writecnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Optionally terminate this batch of commands with a
|
|
||||||
* read command, then do the fetch of the results.
|
|
||||||
*/
|
|
||||||
if (readcnt) {
|
|
||||||
buf[i++] = MPSSE_DO_READ;
|
|
||||||
buf[i++] = (readcnt - 1) & 0xff;
|
|
||||||
buf[i++] = ((readcnt - 1) >> 8) & 0xff;
|
|
||||||
ret = send_buf(ftdic, buf, i);
|
|
||||||
failed = ret;
|
|
||||||
/* We can't abort here, we still have to deassert CS#. */
|
|
||||||
if (ret)
|
|
||||||
msg_perr("send_buf failed before read: %i\n", ret);
|
|
||||||
i = 0;
|
|
||||||
if (ret == 0) {
|
|
||||||
/*
|
|
||||||
* FIXME: This is unreliable. There's no guarantee that
|
|
||||||
* we read the response directly after sending the read
|
|
||||||
* command. We may be scheduled out etc.
|
|
||||||
*/
|
|
||||||
ret = get_buf(ftdic, readarr, readcnt);
|
|
||||||
failed |= ret;
|
|
||||||
/* We can't abort here either. */
|
|
||||||
if (ret)
|
|
||||||
msg_perr("get_buf failed: %i\n", ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_pspew("De-assert CS#\n");
|
|
||||||
buf[i++] = SET_BITS_LOW;
|
|
||||||
buf[i++] = pinlvl;
|
|
||||||
buf[i++] = pindir;
|
|
||||||
ret = send_buf(ftdic, buf, i);
|
|
||||||
failed |= ret;
|
|
||||||
if (ret)
|
|
||||||
msg_perr("send_buf failed at end: %i\n", ret);
|
|
||||||
|
|
||||||
return failed ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
332
ichspi.c
332
ichspi.c
@ -286,12 +286,40 @@ static uint16_t REGREAD8(int X)
|
|||||||
#define REGWRITE8(off, val) mmio_writeb(val, ich_spibar+(off))
|
#define REGWRITE8(off, val) mmio_writeb(val, ich_spibar+(off))
|
||||||
|
|
||||||
/* Common SPI functions */
|
/* Common SPI functions */
|
||||||
static int find_opcode(OPCODES *op, uint8_t opcode);
|
|
||||||
static int find_preop(OPCODES *op, uint8_t preop);
|
static int find_opcode(OPCODES *op, uint8_t opcode)
|
||||||
static int generate_opcodes(OPCODES * op, enum ich_chipset ich_gen);
|
{
|
||||||
static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_gen);
|
int a;
|
||||||
static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,
|
|
||||||
uint8_t datalength, uint8_t * data);
|
if (op == NULL) {
|
||||||
|
msg_perr("\n%s: null OPCODES pointer!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = 0; a < 8; a++) {
|
||||||
|
if (op->opcode[a].opcode == opcode)
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_preop(OPCODES *op, uint8_t preop)
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
|
||||||
|
if (op == NULL) {
|
||||||
|
msg_perr("\n%s: null OPCODES pointer!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = 0; a < 2; a++) {
|
||||||
|
if (op->preop[a] == preop)
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* for pairing opcodes with their required preop */
|
/* for pairing opcodes with their required preop */
|
||||||
struct preop_opcode_pair {
|
struct preop_opcode_pair {
|
||||||
@ -497,131 +525,6 @@ static uint8_t lookup_spi_type(uint8_t opcode)
|
|||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt)
|
|
||||||
{
|
|
||||||
uint8_t spi_type;
|
|
||||||
|
|
||||||
spi_type = lookup_spi_type(opcode);
|
|
||||||
if (spi_type > 3) {
|
|
||||||
/* Try to guess spi type from read/write sizes.
|
|
||||||
* The following valid writecnt/readcnt combinations exist:
|
|
||||||
* writecnt = 4, readcnt >= 0
|
|
||||||
* writecnt = 1, readcnt >= 0
|
|
||||||
* writecnt >= 4, readcnt = 0
|
|
||||||
* writecnt >= 1, readcnt = 0
|
|
||||||
* writecnt >= 1 is guaranteed for all commands.
|
|
||||||
*/
|
|
||||||
if (readcnt == 0)
|
|
||||||
/* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS
|
|
||||||
* or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data
|
|
||||||
* bytes are actual the address, they go to the bus anyhow
|
|
||||||
*/
|
|
||||||
spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
|
|
||||||
else if (writecnt == 1) // and readcnt is > 0
|
|
||||||
spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
|
|
||||||
else if (writecnt == 4) // and readcnt is > 0
|
|
||||||
spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
|
|
||||||
else // we have an invalid case
|
|
||||||
return SPI_INVALID_LENGTH;
|
|
||||||
}
|
|
||||||
int oppos = 2; // use original JEDEC_BE_D8 offset
|
|
||||||
curopcodes->opcode[oppos].opcode = opcode;
|
|
||||||
curopcodes->opcode[oppos].spi_type = spi_type;
|
|
||||||
program_opcodes(curopcodes, 0, ich_generation);
|
|
||||||
oppos = find_opcode(curopcodes, opcode);
|
|
||||||
msg_pdbg2("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos);
|
|
||||||
return oppos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int find_opcode(OPCODES *op, uint8_t opcode)
|
|
||||||
{
|
|
||||||
int a;
|
|
||||||
|
|
||||||
if (op == NULL) {
|
|
||||||
msg_perr("\n%s: null OPCODES pointer!\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (a = 0; a < 8; a++) {
|
|
||||||
if (op->opcode[a].opcode == opcode)
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int find_preop(OPCODES *op, uint8_t preop)
|
|
||||||
{
|
|
||||||
int a;
|
|
||||||
|
|
||||||
if (op == NULL) {
|
|
||||||
msg_perr("\n%s: null OPCODES pointer!\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (a = 0; a < 2; a++) {
|
|
||||||
if (op->preop[a] == preop)
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a struct OPCODES based on what we find in the locked down chipset. */
|
|
||||||
static int generate_opcodes(OPCODES * op, enum ich_chipset ich_gen)
|
|
||||||
{
|
|
||||||
int a;
|
|
||||||
uint16_t preop, optype;
|
|
||||||
uint32_t opmenu[2];
|
|
||||||
|
|
||||||
if (op == NULL) {
|
|
||||||
msg_perr("\n%s: null OPCODES pointer!\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ich_gen) {
|
|
||||||
case CHIPSET_ICH7:
|
|
||||||
case CHIPSET_TUNNEL_CREEK:
|
|
||||||
case CHIPSET_CENTERTON:
|
|
||||||
preop = REGREAD16(ICH7_REG_PREOP);
|
|
||||||
optype = REGREAD16(ICH7_REG_OPTYPE);
|
|
||||||
opmenu[0] = REGREAD32(ICH7_REG_OPMENU);
|
|
||||||
opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4);
|
|
||||||
break;
|
|
||||||
case CHIPSET_ICH8:
|
|
||||||
default: /* Future version might behave the same */
|
|
||||||
preop = REGREAD16(swseq_data.reg_preop);
|
|
||||||
optype = REGREAD16(swseq_data.reg_optype);
|
|
||||||
opmenu[0] = REGREAD32(swseq_data.reg_opmenu);
|
|
||||||
opmenu[1] = REGREAD32(swseq_data.reg_opmenu + 4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
op->preop[0] = (uint8_t) preop;
|
|
||||||
op->preop[1] = (uint8_t) (preop >> 8);
|
|
||||||
|
|
||||||
for (a = 0; a < 8; a++) {
|
|
||||||
op->opcode[a].spi_type = (uint8_t) (optype & 0x3);
|
|
||||||
optype >>= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (a = 0; a < 4; a++) {
|
|
||||||
op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff);
|
|
||||||
opmenu[0] >>= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (a = 4; a < 8; a++) {
|
|
||||||
op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff);
|
|
||||||
opmenu[1] >>= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No preopcodes used by default. */
|
|
||||||
for (a = 0; a < 8; a++)
|
|
||||||
op->opcode[a].atomic = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_gen)
|
static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_gen)
|
||||||
{
|
{
|
||||||
uint8_t a;
|
uint8_t a;
|
||||||
@ -688,6 +591,42 @@ static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_ge
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt)
|
||||||
|
{
|
||||||
|
uint8_t spi_type;
|
||||||
|
|
||||||
|
spi_type = lookup_spi_type(opcode);
|
||||||
|
if (spi_type > 3) {
|
||||||
|
/* Try to guess spi type from read/write sizes.
|
||||||
|
* The following valid writecnt/readcnt combinations exist:
|
||||||
|
* writecnt = 4, readcnt >= 0
|
||||||
|
* writecnt = 1, readcnt >= 0
|
||||||
|
* writecnt >= 4, readcnt = 0
|
||||||
|
* writecnt >= 1, readcnt = 0
|
||||||
|
* writecnt >= 1 is guaranteed for all commands.
|
||||||
|
*/
|
||||||
|
if (readcnt == 0)
|
||||||
|
/* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS
|
||||||
|
* or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data
|
||||||
|
* bytes are actual the address, they go to the bus anyhow
|
||||||
|
*/
|
||||||
|
spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
|
||||||
|
else if (writecnt == 1) // and readcnt is > 0
|
||||||
|
spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
|
||||||
|
else if (writecnt == 4) // and readcnt is > 0
|
||||||
|
spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
|
||||||
|
else // we have an invalid case
|
||||||
|
return SPI_INVALID_LENGTH;
|
||||||
|
}
|
||||||
|
int oppos = 2; // use original JEDEC_BE_D8 offset
|
||||||
|
curopcodes->opcode[oppos].opcode = opcode;
|
||||||
|
curopcodes->opcode[oppos].spi_type = spi_type;
|
||||||
|
program_opcodes(curopcodes, 0, ich_generation);
|
||||||
|
oppos = find_opcode(curopcodes, opcode);
|
||||||
|
msg_pdbg2("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos);
|
||||||
|
return oppos;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns -1 if at least one mandatory opcode is inaccessible, 0 otherwise.
|
* Returns -1 if at least one mandatory opcode is inaccessible, 0 otherwise.
|
||||||
* FIXME: this should also check for
|
* FIXME: this should also check for
|
||||||
@ -754,49 +693,59 @@ static void ich_set_bbar(uint32_t min_addr, enum ich_chipset ich_gen)
|
|||||||
min_addr, ichspi_bbar);
|
min_addr, ichspi_bbar);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read len bytes from the fdata/spid register into the data array.
|
/* Create a struct OPCODES based on what we find in the locked down chipset. */
|
||||||
*
|
static int generate_opcodes(OPCODES * op, enum ich_chipset ich_gen)
|
||||||
* Note that using len > flash->mst->spi.max_data_read will return garbage or
|
|
||||||
* may even crash.
|
|
||||||
*/
|
|
||||||
static void ich_read_data(uint8_t *data, int len, int reg0_off)
|
|
||||||
{
|
{
|
||||||
int i;
|
int a;
|
||||||
uint32_t temp32 = 0;
|
uint16_t preop, optype;
|
||||||
|
uint32_t opmenu[2];
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
if (op == NULL) {
|
||||||
if ((i % 4) == 0)
|
msg_perr("\n%s: null OPCODES pointer!\n", __func__);
|
||||||
temp32 = REGREAD32(reg0_off + i);
|
return -1;
|
||||||
|
|
||||||
data[i] = (temp32 >> ((i % 4) * 8)) & 0xff;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill len bytes from the data array into the fdata/spid registers.
|
switch (ich_gen) {
|
||||||
*
|
case CHIPSET_ICH7:
|
||||||
* Note that using len > flash->mst->spi.max_data_write will trash the registers
|
case CHIPSET_TUNNEL_CREEK:
|
||||||
* following the data registers.
|
case CHIPSET_CENTERTON:
|
||||||
*/
|
preop = REGREAD16(ICH7_REG_PREOP);
|
||||||
static void ich_fill_data(const uint8_t *data, int len, int reg0_off)
|
optype = REGREAD16(ICH7_REG_OPTYPE);
|
||||||
{
|
opmenu[0] = REGREAD32(ICH7_REG_OPMENU);
|
||||||
uint32_t temp32 = 0;
|
opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4);
|
||||||
int i;
|
break;
|
||||||
|
case CHIPSET_ICH8:
|
||||||
if (len <= 0)
|
default: /* Future version might behave the same */
|
||||||
return;
|
preop = REGREAD16(swseq_data.reg_preop);
|
||||||
|
optype = REGREAD16(swseq_data.reg_optype);
|
||||||
for (i = 0; i < len; i++) {
|
opmenu[0] = REGREAD32(swseq_data.reg_opmenu);
|
||||||
if ((i % 4) == 0)
|
opmenu[1] = REGREAD32(swseq_data.reg_opmenu + 4);
|
||||||
temp32 = 0;
|
break;
|
||||||
|
|
||||||
temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8);
|
|
||||||
|
|
||||||
if ((i % 4) == 3) /* 32 bits are full, write them to regs. */
|
|
||||||
REGWRITE32(reg0_off + (i - (i % 4)), temp32);
|
|
||||||
}
|
}
|
||||||
i--;
|
|
||||||
if ((i % 4) != 3) /* Write remaining data to regs. */
|
op->preop[0] = (uint8_t) preop;
|
||||||
REGWRITE32(reg0_off + (i - (i % 4)), temp32);
|
op->preop[1] = (uint8_t) (preop >> 8);
|
||||||
|
|
||||||
|
for (a = 0; a < 8; a++) {
|
||||||
|
op->opcode[a].spi_type = (uint8_t) (optype & 0x3);
|
||||||
|
optype >>= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = 0; a < 4; a++) {
|
||||||
|
op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff);
|
||||||
|
opmenu[0] >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = 4; a < 8; a++) {
|
||||||
|
op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff);
|
||||||
|
opmenu[1] >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No preopcodes used by default. */
|
||||||
|
for (a = 0; a < 8; a++)
|
||||||
|
op->opcode[a].atomic = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function generates OPCODES from or programs OPCODES to ICH according to
|
/* This function generates OPCODES from or programs OPCODES to ICH according to
|
||||||
@ -834,6 +783,51 @@ static int ich_init_opcodes(enum ich_chipset ich_gen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fill len bytes from the data array into the fdata/spid registers.
|
||||||
|
*
|
||||||
|
* Note that using len > flash->mst->spi.max_data_write will trash the registers
|
||||||
|
* following the data registers.
|
||||||
|
*/
|
||||||
|
static void ich_fill_data(const uint8_t *data, int len, int reg0_off)
|
||||||
|
{
|
||||||
|
uint32_t temp32 = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (len <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if ((i % 4) == 0)
|
||||||
|
temp32 = 0;
|
||||||
|
|
||||||
|
temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8);
|
||||||
|
|
||||||
|
if ((i % 4) == 3) /* 32 bits are full, write them to regs. */
|
||||||
|
REGWRITE32(reg0_off + (i - (i % 4)), temp32);
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
if ((i % 4) != 3) /* Write remaining data to regs. */
|
||||||
|
REGWRITE32(reg0_off + (i - (i % 4)), temp32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read len bytes from the fdata/spid register into the data array.
|
||||||
|
*
|
||||||
|
* Note that using len > flash->mst->spi.max_data_read will return garbage or
|
||||||
|
* may even crash.
|
||||||
|
*/
|
||||||
|
static void ich_read_data(uint8_t *data, int len, int reg0_off)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t temp32 = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if ((i % 4) == 0)
|
||||||
|
temp32 = REGREAD32(reg0_off + i);
|
||||||
|
|
||||||
|
data[i] = (temp32 >> ((i % 4) * 8)) & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int ich7_run_opcode(OPCODE op, uint32_t offset,
|
static int ich7_run_opcode(OPCODE op, uint32_t offset,
|
||||||
uint8_t datalength, uint8_t * data, int maxdata)
|
uint8_t datalength, uint8_t * data, int maxdata)
|
||||||
{
|
{
|
||||||
|
122
linux_spi.c
122
linux_spi.c
@ -48,15 +48,65 @@ static int fd = -1;
|
|||||||
#define BUF_SIZE_FROM_SYSFS "/sys/module/spidev/parameters/bufsiz"
|
#define BUF_SIZE_FROM_SYSFS "/sys/module/spidev/parameters/bufsiz"
|
||||||
static size_t max_kernel_buf_size;
|
static size_t max_kernel_buf_size;
|
||||||
|
|
||||||
static int linux_spi_shutdown(void *data);
|
static int linux_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
|
||||||
|
{
|
||||||
|
/* Older kernels use a single buffer for combined input and output
|
||||||
|
data. So account for longest possible command + address, too. */
|
||||||
|
return spi_read_chunked(flash, buf, start, len, max_kernel_buf_size - 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
|
||||||
|
{
|
||||||
|
/* 5 bytes must be reserved for longest possible command + address. */
|
||||||
|
return spi_write_chunked(flash, buf, start, len, max_kernel_buf_size - 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int linux_spi_shutdown(void *data)
|
||||||
|
{
|
||||||
|
if (fd != -1) {
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int linux_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
|
static int linux_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
|
||||||
unsigned int readcnt,
|
unsigned int readcnt,
|
||||||
const unsigned char *txbuf,
|
const unsigned char *txbuf,
|
||||||
unsigned char *rxbuf);
|
unsigned char *rxbuf)
|
||||||
static int linux_spi_read(struct flashctx *flash, uint8_t *buf,
|
{
|
||||||
unsigned int start, unsigned int len);
|
int iocontrol_code;
|
||||||
static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf,
|
struct spi_ioc_transfer msg[2] = {
|
||||||
unsigned int start, unsigned int len);
|
{
|
||||||
|
.tx_buf = (uint64_t)(uintptr_t)txbuf,
|
||||||
|
.len = writecnt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.rx_buf = (uint64_t)(uintptr_t)rxbuf,
|
||||||
|
.len = readcnt,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
return -1;
|
||||||
|
/* The implementation currently does not support requests that
|
||||||
|
don't start with sending a command. */
|
||||||
|
if (writecnt == 0)
|
||||||
|
return SPI_INVALID_LENGTH;
|
||||||
|
|
||||||
|
/* Just submit the first (write) request in case there is nothing
|
||||||
|
to read. Otherwise submit both requests. */
|
||||||
|
if (readcnt == 0)
|
||||||
|
iocontrol_code = SPI_IOC_MESSAGE(1);
|
||||||
|
else
|
||||||
|
iocontrol_code = SPI_IOC_MESSAGE(2);
|
||||||
|
|
||||||
|
if (ioctl(fd, iocontrol_code, msg) == -1) {
|
||||||
|
msg_cerr("%s: ioctl: %s\n", __func__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct spi_master spi_master_linux = {
|
static const struct spi_master spi_master_linux = {
|
||||||
.features = SPI_MASTER_4BA,
|
.features = SPI_MASTER_4BA,
|
||||||
@ -174,64 +224,4 @@ out:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linux_spi_shutdown(void *data)
|
|
||||||
{
|
|
||||||
if (fd != -1) {
|
|
||||||
close(fd);
|
|
||||||
fd = -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int linux_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
|
|
||||||
unsigned int readcnt,
|
|
||||||
const unsigned char *txbuf,
|
|
||||||
unsigned char *rxbuf)
|
|
||||||
{
|
|
||||||
int iocontrol_code;
|
|
||||||
struct spi_ioc_transfer msg[2] = {
|
|
||||||
{
|
|
||||||
.tx_buf = (uint64_t)(uintptr_t)txbuf,
|
|
||||||
.len = writecnt,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rx_buf = (uint64_t)(uintptr_t)rxbuf,
|
|
||||||
.len = readcnt,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (fd == -1)
|
|
||||||
return -1;
|
|
||||||
/* The implementation currently does not support requests that
|
|
||||||
don't start with sending a command. */
|
|
||||||
if (writecnt == 0)
|
|
||||||
return SPI_INVALID_LENGTH;
|
|
||||||
|
|
||||||
/* Just submit the first (write) request in case there is nothing
|
|
||||||
to read. Otherwise submit both requests. */
|
|
||||||
if (readcnt == 0)
|
|
||||||
iocontrol_code = SPI_IOC_MESSAGE(1);
|
|
||||||
else
|
|
||||||
iocontrol_code = SPI_IOC_MESSAGE(2);
|
|
||||||
|
|
||||||
if (ioctl(fd, iocontrol_code, msg) == -1) {
|
|
||||||
msg_cerr("%s: ioctl: %s\n", __func__, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int linux_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
|
|
||||||
{
|
|
||||||
/* Older kernels use a single buffer for combined input and output
|
|
||||||
data. So account for longest possible command + address, too. */
|
|
||||||
return spi_read_chunked(flash, buf, start, len, max_kernel_buf_size - 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
|
|
||||||
{
|
|
||||||
/* 5 bytes must be reserved for longest possible command + address. */
|
|
||||||
return spi_write_chunked(flash, buf, start, len, max_kernel_buf_size - 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CONFIG_LINUX_SPI == 1
|
#endif // CONFIG_LINUX_SPI == 1
|
||||||
|
84
ni845x_spi.c
84
ni845x_spi.c
@ -50,10 +50,6 @@ static NiHandle configuration_handle;
|
|||||||
static uint16_t io_voltage_in_mV;
|
static uint16_t io_voltage_in_mV;
|
||||||
static bool ignore_io_voltage_limits;
|
static bool ignore_io_voltage_limits;
|
||||||
|
|
||||||
static int ni845x_spi_shutdown(void *data);
|
|
||||||
static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_handle);
|
|
||||||
static void ni845x_spi_print_available_devices(void);
|
|
||||||
|
|
||||||
// USB-8452 supported voltages, keep this array in ascending order!
|
// USB-8452 supported voltages, keep this array in ascending order!
|
||||||
static const uint8_t usb8452_io_voltages_in_100mV[5] = {
|
static const uint8_t usb8452_io_voltages_in_100mV[5] = {
|
||||||
kNi845x12Volts,
|
kNi845x12Volts,
|
||||||
@ -128,6 +124,28 @@ static void ni845x_report_warning(const char *const func, const int32 err)
|
|||||||
msg_pwarn("%s failed with: %s (%d)\n", func, buf, (int)err);
|
msg_pwarn("%s failed with: %s (%d)\n", func, buf, (int)err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ni845x_spi_open_resource
|
||||||
|
* @param resource_handle the resource handle returned by the ni845xFindDevice or ni845xFindDeviceNext
|
||||||
|
* @param opened_handle the opened handle from the ni845xOpen
|
||||||
|
* @return the 0 on successful competition, negative error code on failure positive code on warning
|
||||||
|
*/
|
||||||
|
static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_handle)
|
||||||
|
{
|
||||||
|
// NI-845x driver loads the FPGA bitfile at the first time
|
||||||
|
// which can take couple seconds
|
||||||
|
if (device_pid == USB8452)
|
||||||
|
msg_pwarn("Opening NI-8452, this might take a while for the first time\n");
|
||||||
|
|
||||||
|
int32 tmp = ni845xOpen(resource_handle, opened_handle);
|
||||||
|
|
||||||
|
if (tmp < 0)
|
||||||
|
ni845x_report_error("ni845xOpen", tmp);
|
||||||
|
else if (tmp > 0)
|
||||||
|
ni845x_report_warning("ni845xOpen", tmp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param serial a null terminated string containing the serial number of the specific device or NULL
|
* @param serial a null terminated string containing the serial number of the specific device or NULL
|
||||||
* @return the 0 on successful completition, negative error code on failure
|
* @return the 0 on successful completition, negative error code on failure
|
||||||
@ -193,28 +211,6 @@ _close_ret:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief ni845x_spi_open_resource
|
|
||||||
* @param resource_handle the resource handle returned by the ni845xFindDevice or ni845xFindDeviceNext
|
|
||||||
* @param opened_handle the opened handle from the ni845xOpen
|
|
||||||
* @return the 0 on successful competition, negative error code on failure positive code on warning
|
|
||||||
*/
|
|
||||||
static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_handle)
|
|
||||||
{
|
|
||||||
// NI-845x driver loads the FPGA bitfile at the first time
|
|
||||||
// which can take couple seconds
|
|
||||||
if (device_pid == USB8452)
|
|
||||||
msg_pwarn("Opening NI-8452, this might take a while for the first time\n");
|
|
||||||
|
|
||||||
int32 tmp = ni845xOpen(resource_handle, opened_handle);
|
|
||||||
|
|
||||||
if (tmp < 0)
|
|
||||||
ni845x_report_error("ni845xOpen", tmp);
|
|
||||||
else if (tmp > 0)
|
|
||||||
ni845x_report_warning("ni845xOpen", tmp);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usb8452_spi_set_io_voltage sets the IO voltage for the USB-8452 devices
|
* @brief usb8452_spi_set_io_voltage sets the IO voltage for the USB-8452 devices
|
||||||
* @param requested_io_voltage_mV the desired IO voltage in mVolts
|
* @param requested_io_voltage_mV the desired IO voltage in mVolts
|
||||||
@ -389,6 +385,24 @@ static void ni845x_spi_print_available_devices(void)
|
|||||||
ni845x_report_error("ni845xCloseFindDeviceHandle", tmp);
|
ni845x_report_error("ni845xCloseFindDeviceHandle", tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ni845x_spi_shutdown(void *data)
|
||||||
|
{
|
||||||
|
int32 ret = 0;
|
||||||
|
|
||||||
|
if (configuration_handle != 0) {
|
||||||
|
ret = ni845xSpiConfigurationClose(configuration_handle);
|
||||||
|
if (ret)
|
||||||
|
ni845x_report_error("ni845xSpiConfigurationClose", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device_handle != 0) {
|
||||||
|
ret = ni845xClose(device_handle);
|
||||||
|
if (ret)
|
||||||
|
ni845x_report_error("ni845xClose", ret);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ni845x_spi_init(void)
|
int ni845x_spi_init(void)
|
||||||
{
|
{
|
||||||
char *speed_str = NULL;
|
char *speed_str = NULL;
|
||||||
@ -486,24 +500,6 @@ int ni845x_spi_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ni845x_spi_shutdown(void *data)
|
|
||||||
{
|
|
||||||
int32 ret = 0;
|
|
||||||
|
|
||||||
if (configuration_handle != 0) {
|
|
||||||
ret = ni845xSpiConfigurationClose(configuration_handle);
|
|
||||||
if (ret)
|
|
||||||
ni845x_report_error("ni845xSpiConfigurationClose", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device_handle != 0) {
|
|
||||||
ret = ni845xClose(device_handle);
|
|
||||||
if (ret)
|
|
||||||
ni845x_report_error("ni845xClose", ret);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ni845x_warn_over_max_voltage(const struct flashctx *flash)
|
static void ni845x_warn_over_max_voltage(const struct flashctx *flash)
|
||||||
{
|
{
|
||||||
if (device_pid == USB8451) {
|
if (device_pid == USB8451) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user