summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-fsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-fsi.c')
-rw-r--r--drivers/spi/spi-fsi.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index b6c7467f0b59..e01c63d23b64 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -24,7 +24,7 @@
#define FSI2SPI_IRQ 0x20
#define SPI_FSI_BASE 0x70000
-#define SPI_FSI_INIT_TIMEOUT_MS 1000
+#define SPI_FSI_TIMEOUT_MS 1000
#define SPI_FSI_MAX_RX_SIZE 8
#define SPI_FSI_MAX_TX_SIZE 40
@@ -298,7 +298,9 @@ static void fsi_spi_sequence_init(struct fsi_spi_sequence *seq)
static int fsi_spi_transfer_data(struct fsi_spi *ctx,
struct spi_transfer *transfer)
{
+ int loops;
int rc = 0;
+ unsigned long end;
u64 status = 0ULL;
if (transfer->tx_buf) {
@@ -315,7 +317,12 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
if (rc)
return rc;
+ loops = 0;
+ end = jiffies + msecs_to_jiffies(SPI_FSI_TIMEOUT_MS);
do {
+ if (loops++ && time_after(jiffies, end))
+ return -ETIMEDOUT;
+
rc = fsi_spi_status(ctx, &status, "TX");
if (rc)
return rc;
@@ -329,7 +336,12 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
u8 *rx = transfer->rx_buf;
while (transfer->len > recv) {
+ loops = 0;
+ end = jiffies + msecs_to_jiffies(SPI_FSI_TIMEOUT_MS);
do {
+ if (loops++ && time_after(jiffies, end))
+ return -ETIMEDOUT;
+
rc = fsi_spi_status(ctx, &status, "RX");
if (rc)
return rc;
@@ -349,6 +361,7 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
static int fsi_spi_transfer_init(struct fsi_spi *ctx)
{
+ int loops = 0;
int rc;
bool reset = false;
unsigned long end;
@@ -359,9 +372,9 @@ static int fsi_spi_transfer_init(struct fsi_spi *ctx)
SPI_FSI_CLOCK_CFG_SCK_NO_DEL |
FIELD_PREP(SPI_FSI_CLOCK_CFG_SCK_DIV, 19);
- end = jiffies + msecs_to_jiffies(SPI_FSI_INIT_TIMEOUT_MS);
+ end = jiffies + msecs_to_jiffies(SPI_FSI_TIMEOUT_MS);
do {
- if (time_after(jiffies, end))
+ if (loops++ && time_after(jiffies, end))
return -ETIMEDOUT;
rc = fsi_spi_read_reg(ctx, SPI_FSI_STATUS, &status);
@@ -412,7 +425,7 @@ static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *mesg)
{
int rc;
- u8 seq_slave = SPI_FSI_SEQUENCE_SEL_SLAVE(mesg->spi->chip_select + 1);
+ u8 seq_slave = SPI_FSI_SEQUENCE_SEL_SLAVE(spi_get_chipselect(mesg->spi, 0) + 1);
unsigned int len;
struct spi_transfer *transfer;
struct fsi_spi *ctx = spi_controller_get_devdata(ctlr);
@@ -466,6 +479,19 @@ static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
shift = SPI_FSI_SEQUENCE_SHIFT_IN(next->len);
fsi_spi_sequence_add(&seq, shift);
+ } else if (next->tx_buf) {
+ if ((next->len + transfer->len) > (SPI_FSI_MAX_TX_SIZE + 8)) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ len = next->len;
+ while (len > 8) {
+ fsi_spi_sequence_add(&seq,
+ SPI_FSI_SEQUENCE_SHIFT_OUT(8));
+ len -= 8;
+ }
+ fsi_spi_sequence_add(&seq, SPI_FSI_SEQUENCE_SHIFT_OUT(len));
} else {
next = NULL;
}
@@ -529,7 +555,7 @@ static int fsi_spi_probe(struct device *dev)
if (of_property_read_u32(np, "reg", &base))
continue;
- ctlr = spi_alloc_master(dev, sizeof(*ctx));
+ ctlr = spi_alloc_host(dev, sizeof(*ctx));
if (!ctlr) {
of_node_put(np);
break;