spi: Change spi_xfer to work in units of bytes instead of bits.
Whenever spi_xfer is called and whenver it's implemented, the natural unit for the amount of data being transfered is bytes. The API expected things to be expressed in bits, however, which led to a lot of multiplying and dividing by eight, and checkes to make sure things were multiples of eight. All of that can now be removed. BUG=None TEST=Built and booted on link, falco, peach_pit and nyan and looked for SPI errors in the firmware log. Built for rambi. BRANCH=None Change-Id: I02365bdb6960a35def7be7a0cd1aa0a2cc09392f Signed-off-by: Gabe Black <gabeblack@google.com> Reviewed-on: https://chromium-review.googlesource.com/192049 Reviewed-by: Gabe Black <gabeblack@chromium.org> Tested-by: Gabe Black <gabeblack@chromium.org> Commit-Queue: Gabe Black <gabeblack@chromium.org> [km: cherry-pick from chromium] Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: http://review.coreboot.org/6175 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com> Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
This commit is contained in:
parent
1e187356e8
commit
93d9f92cfb
|
@ -258,15 +258,13 @@ int spi_claim_bus(struct spi_slave *slave)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout,
|
int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int out_bytes,
|
||||||
void *din, unsigned int bitsin)
|
void *din, unsigned int in_bytes)
|
||||||
{
|
{
|
||||||
unsigned int out_bytes = bitsout / 8, in_bytes = bitsin / 8;
|
|
||||||
uint8_t *out_ptr = (uint8_t *)dout, *in_ptr = (uint8_t *)din;
|
uint8_t *out_ptr = (uint8_t *)dout, *in_ptr = (uint8_t *)din;
|
||||||
int offset, todo, len;
|
int offset, todo, len;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ASSERT(bitsout % 8 == 0 && bitsin % 8 == 0);
|
|
||||||
len = MAX(out_bytes, in_bytes);
|
len = MAX(out_bytes, in_bytes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -28,7 +28,7 @@ static void spi_flash_addr(u32 addr, u8 *cmd)
|
||||||
|
|
||||||
int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
|
int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
|
||||||
{
|
{
|
||||||
int ret = spi_xfer(spi, &cmd, 8, response, len * 8);
|
int ret = spi_xfer(spi, &cmd, sizeof(cmd), response, len);
|
||||||
if (ret)
|
if (ret)
|
||||||
printk(BIOS_WARNING, "SF: Failed to send command %02x: %d\n", cmd, ret);
|
printk(BIOS_WARNING, "SF: Failed to send command %02x: %d\n", cmd, ret);
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
|
||||||
int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
|
int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
|
||||||
size_t cmd_len, void *data, size_t data_len)
|
size_t cmd_len, void *data, size_t data_len)
|
||||||
{
|
{
|
||||||
int ret = spi_xfer(spi, cmd, cmd_len * 8, data, data_len * 8);
|
int ret = spi_xfer(spi, cmd, cmd_len, data, data_len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(BIOS_WARNING, "SF: Failed to send read command (%zu bytes): %d\n",
|
printk(BIOS_WARNING, "SF: Failed to send read command (%zu bytes): %d\n",
|
||||||
data_len, ret);
|
data_len, ret);
|
||||||
|
@ -55,7 +55,7 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
|
||||||
memcpy(buff, cmd, cmd_len);
|
memcpy(buff, cmd, cmd_len);
|
||||||
memcpy(buff + cmd_len, data, data_len);
|
memcpy(buff + cmd_len, data, data_len);
|
||||||
|
|
||||||
ret = spi_xfer(spi, buff, (cmd_len + data_len) * 8, NULL, 0);
|
ret = spi_xfer(spi, buff, cmd_len + data_len, NULL, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(BIOS_WARNING, "SF: Failed to send write command (%zu bytes): %d\n",
|
printk(BIOS_WARNING, "SF: Failed to send write command (%zu bytes): %d\n",
|
||||||
data_len, ret);
|
data_len, ret);
|
||||||
|
|
|
@ -31,8 +31,8 @@ static int crosec_spi_io(uint8_t *write_bytes, size_t write_size,
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
spi_claim_bus(slave);
|
spi_claim_bus(slave);
|
||||||
rv = spi_xfer(slave, write_bytes, write_size * 8, read_bytes,
|
rv = spi_xfer(slave, write_bytes, write_size, read_bytes,
|
||||||
read_size * 8);
|
read_size);
|
||||||
spi_release_bus(slave);
|
spi_release_bus(slave);
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
|
|
|
@ -120,27 +120,17 @@ void spi_release_bus(struct spi_slave *slave);
|
||||||
/*-----------------------------------------------------------------------
|
/*-----------------------------------------------------------------------
|
||||||
* SPI transfer
|
* SPI transfer
|
||||||
*
|
*
|
||||||
* This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
|
|
||||||
* "bitlen" bits in the SPI MISO port. That's just the way SPI works.
|
|
||||||
*
|
|
||||||
* The source of the outgoing bits is the "dout" parameter and the
|
|
||||||
* destination of the input bits is the "din" parameter. Note that "dout"
|
|
||||||
* and "din" can point to the same memory location, in which case the
|
|
||||||
* input data overwrites the output data (since both are buffered by
|
|
||||||
* temporary variables, this is OK).
|
|
||||||
*
|
|
||||||
* spi_xfer() interface:
|
* spi_xfer() interface:
|
||||||
* slave: The SPI slave which will be sending/receiving the data.
|
* slave: The SPI slave which will be sending/receiving the data.
|
||||||
* dout: Pointer to a string of bits to send out. The bits are
|
* dout: Pointer to a string of bytes to send out.
|
||||||
* held in a byte array and are sent MSB first.
|
* bytesout: How many bytes to write.
|
||||||
* bitsout: How many bits to write.
|
* din: Pointer to a string of bytes that will be filled in.
|
||||||
* din: Pointer to a string of bits that will be filled in.
|
* bytesin: How many bytes to read.
|
||||||
* bitsin: How many bits to read.
|
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, not 0 on failure
|
* Returns: 0 on success, not 0 on failure
|
||||||
*/
|
*/
|
||||||
int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout,
|
int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout,
|
||||||
void *din, unsigned int bitsin);
|
void *din, unsigned int bytesin);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------
|
/*-----------------------------------------------------------------------
|
||||||
* Determine if a SPI chipselect is valid.
|
* Determine if a SPI chipselect is valid.
|
||||||
|
@ -196,7 +186,7 @@ static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte)
|
||||||
dout[0] = byte;
|
dout[0] = byte;
|
||||||
dout[1] = 0;
|
dout[1] = 0;
|
||||||
|
|
||||||
ret = spi_xfer(slave, dout, 16, din, 16);
|
ret = spi_xfer(slave, dout, 2, din, 2);
|
||||||
return ret < 0 ? ret : din[1];
|
return ret < 0 ? ret : din[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -500,7 +500,7 @@ static int ich_status_poll(u16 bitmask, int wait_til_set)
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_xfer(struct spi_slave *slave, const void *dout,
|
int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
unsigned int bitsout, void *din, unsigned int bitsin)
|
unsigned int bytesout, void *din, unsigned int bytesin)
|
||||||
{
|
{
|
||||||
uint16_t control;
|
uint16_t control;
|
||||||
int16_t opcode_index;
|
int16_t opcode_index;
|
||||||
|
@ -508,26 +508,21 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
spi_transaction trans = {
|
spi_transaction trans = {
|
||||||
dout, bitsout / 8,
|
dout, bytesout,
|
||||||
din, bitsin / 8,
|
din, bytesin,
|
||||||
0xff, 0xff, 0
|
0xff, 0xff, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/* There has to always at least be an opcode. */
|
/* There has to always at least be an opcode. */
|
||||||
if (!bitsout || !dout) {
|
if (!bytesout || !dout) {
|
||||||
printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n");
|
printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Make sure if we read something we have a place to put it. */
|
/* Make sure if we read something we have a place to put it. */
|
||||||
if (bitsin != 0 && !din) {
|
if (bytesin != 0 && !din) {
|
||||||
printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n");
|
printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Right now we don't support writing partial bytes. */
|
|
||||||
if (bitsout % 8 || bitsin % 8) {
|
|
||||||
printk(BIOS_DEBUG, "ICH SPI: Accessing partial bytes not supported\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ich_status_poll(SPIS_SCIP, 0) == -1)
|
if (ich_status_poll(SPIS_SCIP, 0) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -498,7 +498,7 @@ static int ich_status_poll(u16 bitmask, int wait_til_set)
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_xfer(struct spi_slave *slave, const void *dout,
|
int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
unsigned int bitsout, void *din, unsigned int bitsin)
|
unsigned int bytesout, void *din, unsigned int bytesin)
|
||||||
{
|
{
|
||||||
uint16_t control;
|
uint16_t control;
|
||||||
int16_t opcode_index;
|
int16_t opcode_index;
|
||||||
|
@ -506,26 +506,21 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
spi_transaction trans = {
|
spi_transaction trans = {
|
||||||
dout, bitsout / 8,
|
dout, bytesout,
|
||||||
din, bitsin / 8,
|
din, bytesin,
|
||||||
0xff, 0xff, 0
|
0xff, 0xff, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/* There has to always at least be an opcode. */
|
/* There has to always at least be an opcode. */
|
||||||
if (!bitsout || !dout) {
|
if (!bytesout || !dout) {
|
||||||
printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n");
|
printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Make sure if we read something we have a place to put it. */
|
/* Make sure if we read something we have a place to put it. */
|
||||||
if (bitsin != 0 && !din) {
|
if (bytesin != 0 && !din) {
|
||||||
printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n");
|
printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Right now we don't support writing partial bytes. */
|
|
||||||
if (bitsout % 8 || bitsin % 8) {
|
|
||||||
printk(BIOS_DEBUG, "ICH SPI: Accessing partial bytes not supported\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ich_status_poll(SPIS_SCIP, 0) == -1)
|
if (ich_status_poll(SPIS_SCIP, 0) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -87,21 +87,14 @@ void spi_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_xfer(struct spi_slave *slave, const void *dout,
|
int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
unsigned int bitsout, void *din, unsigned int bitsin)
|
unsigned int bytesout, void *din, unsigned int bytesin)
|
||||||
{
|
{
|
||||||
/* First byte is cmd which can not being sent through FIFO. */
|
/* First byte is cmd which can not being sent through FIFO. */
|
||||||
uint8_t cmd = *(uint8_t *)dout++;
|
u8 cmd = *(u8 *)dout++;
|
||||||
uint8_t readoffby1;
|
u8 readoffby1;
|
||||||
#if !CONFIG_SOUTHBRIDGE_AMD_AGESA_YANGTZE
|
u8 count;
|
||||||
uint8_t readwrite;
|
|
||||||
#endif
|
|
||||||
uint8_t bytesout, bytesin;
|
|
||||||
uint8_t count;
|
|
||||||
|
|
||||||
bitsout -= 8;
|
|
||||||
bytesout = bitsout / 8;
|
|
||||||
bytesin = bitsin / 8;
|
|
||||||
|
|
||||||
|
bytesout--;
|
||||||
readoffby1 = bytesout ? 0 : 1;
|
readoffby1 = bytesout ? 0 : 1;
|
||||||
|
|
||||||
#if CONFIG_SOUTHBRIDGE_AMD_AGESA_YANGTZE
|
#if CONFIG_SOUTHBRIDGE_AMD_AGESA_YANGTZE
|
||||||
|
@ -110,7 +103,7 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
spi_write(0x1E, 6);
|
spi_write(0x1E, 6);
|
||||||
spi_write(0x1F, bytesin); /* SpiExtRegIndx [6] - RxByteCount */
|
spi_write(0x1F, bytesin); /* SpiExtRegIndx [6] - RxByteCount */
|
||||||
#else
|
#else
|
||||||
readwrite = (bytesin + readoffby1) << 4 | bytesout;
|
u8 readwrite = (bytesin + readoffby1) << 4 | bytesout;
|
||||||
spi_write(SPI_REG_CNTRL01, readwrite);
|
spi_write(SPI_REG_CNTRL01, readwrite);
|
||||||
#endif
|
#endif
|
||||||
spi_write(SPI_REG_OPCODE, cmd);
|
spi_write(SPI_REG_OPCODE, cmd);
|
||||||
|
|
|
@ -57,18 +57,15 @@ void spi_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_xfer(struct spi_slave *slave, const void *dout,
|
int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
unsigned int bitsout, void *din, unsigned int bitsin)
|
unsigned int bytesout, void *din, unsigned int bytesin)
|
||||||
{
|
{
|
||||||
/* First byte is cmd which can not being sent through FIFO. */
|
/* First byte is cmd which can not being sent through FIFO. */
|
||||||
u8 cmd = *(u8 *)dout++;
|
u8 cmd = *(u8 *)dout++;
|
||||||
u8 readoffby1;
|
u8 readoffby1;
|
||||||
u8 readwrite;
|
u8 readwrite;
|
||||||
u8 bytesout, bytesin;
|
|
||||||
u8 count;
|
u8 count;
|
||||||
|
|
||||||
bitsout -= 8;
|
bytesout--;
|
||||||
bytesout = bitsout / 8;
|
|
||||||
bytesin = bitsin / 8;
|
|
||||||
|
|
||||||
readoffby1 = bytesout ? 0 : 1;
|
readoffby1 = bytesout ? 0 : 1;
|
||||||
|
|
||||||
|
|
|
@ -551,7 +551,7 @@ static int spi_is_multichip (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_xfer(struct spi_slave *slave, const void *dout,
|
int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
unsigned int bitsout, void *din, unsigned int bitsin)
|
unsigned int bytesout, void *din, unsigned int bytesin)
|
||||||
{
|
{
|
||||||
uint16_t control;
|
uint16_t control;
|
||||||
int16_t opcode_index;
|
int16_t opcode_index;
|
||||||
|
@ -559,26 +559,21 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
spi_transaction trans = {
|
spi_transaction trans = {
|
||||||
dout, bitsout / 8,
|
dout, bytesout,
|
||||||
din, bitsin / 8,
|
din, bytesin,
|
||||||
0xff, 0xff, 0
|
0xff, 0xff, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/* There has to always at least be an opcode. */
|
/* There has to always at least be an opcode. */
|
||||||
if (!bitsout || !dout) {
|
if (!bytesout || !dout) {
|
||||||
printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n");
|
printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Make sure if we read something we have a place to put it. */
|
/* Make sure if we read something we have a place to put it. */
|
||||||
if (bitsin != 0 && !din) {
|
if (bytesin != 0 && !din) {
|
||||||
printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n");
|
printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Right now we don't support writing partial bytes. */
|
|
||||||
if (bitsout % 8 || bitsin % 8) {
|
|
||||||
printk(BIOS_DEBUG, "ICH SPI: Accessing partial bytes not supported\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ich_status_poll(SPIS_SCIP, 0) == -1)
|
if (ich_status_poll(SPIS_SCIP, 0) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue