summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README4
-rw-r--r--doc/device-tree-bindings/spi/spi-bus.txt2
-rw-r--r--drivers/misc/cros_ec_spi.c4
-rw-r--r--drivers/mtd/spi/sf_ops.c1
-rw-r--r--drivers/spi/exynos_spi.c9
-rw-r--r--drivers/spi/mxc_spi.c17
-rw-r--r--drivers/spi/spi.c2
7 files changed, 31 insertions, 8 deletions
diff --git a/README b/README
index 31e08fc..0d295a7 100644
--- a/README
+++ b/README
@@ -2597,6 +2597,10 @@ CBFS (Coreboot Filesystem) support
Enables the driver for the SPI controllers on i.MX and MXC
SoCs. Currently i.MX31/35/51 are supported.
+ CONFIG_SYS_SPI_MXC_WAIT
+ Timeout for waiting until spi transfer completed.
+ default: (CONFIG_SYS_HZ/100) /* 10 ms */
+
- FPGA Support: CONFIG_FPGA
Enables FPGA subsystem.
diff --git a/doc/device-tree-bindings/spi/spi-bus.txt b/doc/device-tree-bindings/spi/spi-bus.txt
index 800dafe..5c8720a 100644
--- a/doc/device-tree-bindings/spi/spi-bus.txt
+++ b/doc/device-tree-bindings/spi/spi-bus.txt
@@ -59,6 +59,8 @@ contain the following properties.
used for MOSI. Defaults to 1 if not present.
- spi-rx-bus-width - (optional) The bus width(number of data wires) that
used for MISO. Defaults to 1 if not present.
+- spi-half-duplex - (optional) Indicates that the SPI bus should wait for
+ a header byte before reading data from the slave.
Some SPI controllers and devices support Dual and Quad SPI transfer mode.
It allows data in SPI system transfered in 2 wires(DUAL) or 4 wires(QUAD).
diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
index 7df709c..015333f 100644
--- a/drivers/misc/cros_ec_spi.c
+++ b/drivers/misc/cros_ec_spi.c
@@ -98,7 +98,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
}
out = dev->dout;
- out[0] = cmd_version;
+ out[0] = EC_CMD_VERSION0 + cmd_version;
out[1] = cmd;
out[2] = (uint8_t)dout_len;
memcpy(out + 3, dout, dout_len);
@@ -165,7 +165,7 @@ int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
*/
int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
{
- dev->spi = spi_setup_slave_fdt(blob, dev->parent_node, dev->node);
+ dev->spi = spi_setup_slave_fdt(blob, dev->node, dev->parent_node);
if (!dev->spi) {
debug("%s: Could not setup SPI slave\n", __func__);
return -1;
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index ef91b92..85cf22d 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -421,6 +421,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
data += read_len;
}
+ free(cmd);
return ret;
}
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index c92276f..2969184 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -428,10 +428,6 @@ void spi_cs_activate(struct spi_slave *slave)
clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
debug("Activate CS, bus %d\n", spi_slave->slave.bus);
spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
-
- /* Remember time of this transaction so we can honour the bus delay */
- if (spi_slave->bus->deactivate_delay_us)
- spi_slave->last_transaction_us = timer_get_us();
}
/**
@@ -445,6 +441,11 @@ void spi_cs_deactivate(struct spi_slave *slave)
struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
setbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+
+ /* Remember time of this transaction so we can honour the bus delay */
+ if (spi_slave->bus->deactivate_delay_us)
+ spi_slave->last_transaction_us = timer_get_us();
+
debug("Deactivate CS, bus %d\n", spi_slave->slave.bus);
}
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index f3f029d..2d5f385 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -30,6 +30,10 @@ static unsigned long spi_bases[] = {
#define reg_read readl
#define reg_write(a, v) writel(v, a)
+#if !defined(CONFIG_SYS_SPI_MXC_WAIT)
+#define CONFIG_SYS_SPI_MXC_WAIT (CONFIG_SYS_HZ/100) /* 10 ms */
+#endif
+
struct mxc_spi_slave {
struct spi_slave slave;
unsigned long base;
@@ -212,6 +216,8 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
int nbytes = DIV_ROUND_UP(bitlen, 8);
u32 data, cnt, i;
struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
+ u32 ts;
+ int status;
debug("%s: bitlen %d dout 0x%x din 0x%x\n",
__func__, bitlen, (u32)dout, (u32)din);
@@ -272,9 +278,16 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
reg_write(&regs->ctrl, mxcs->ctrl_reg |
MXC_CSPICTRL_EN | MXC_CSPICTRL_XCH);
+ ts = get_timer(0);
+ status = reg_read(&regs->stat);
/* Wait until the TC (Transfer completed) bit is set */
- while ((reg_read(&regs->stat) & MXC_CSPICTRL_TC) == 0)
- ;
+ while ((status & MXC_CSPICTRL_TC) == 0) {
+ if (get_timer(ts) > CONFIG_SYS_SPI_MXC_WAIT) {
+ printf("spi_xchg_single: Timeout!\n");
+ return -1;
+ }
+ status = reg_read(&regs->stat);
+ }
/* Transfer completed, clear any pending request */
reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 7ddea9b..7d81fbd 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -53,6 +53,8 @@ struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum,
mode |= SPI_CPHA;
if (fdtdec_get_bool(blob, node, "spi-cs-high"))
mode |= SPI_CS_HIGH;
+ if (fdtdec_get_bool(blob, node, "spi-half-duplex"))
+ mode |= SPI_PREAMBLE;
return spi_setup_slave(busnum, cs, max_hz, mode);
}
#endif