From a52a178f0b4dce6a85a45ccea348be92fc7f1b6d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 12 Jul 2014 18:11:31 +0530 Subject: [PATCH 1/5] sf: sf_ops: Stop leaking memory It's usually a common pattern to free() the memory that we allocated. Implement this here to stop leaking memory. Signed-off-by: Marek Vasut Cc: Michal Simek Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/sf_ops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index ef91b924d7..85cf22d42e 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; } From 2001b9a64165658e14f5afbe16874e0c55ddd04f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 7 Jul 2014 10:16:37 -0600 Subject: [PATCH 2/5] cros_ec: Fix two bugs in the SPI implementation An incorrect message version is passed to the EC in some cases and the parameters of one function are switched. Fix these problems. Signed-off-by: Simon Glass Tested-by: Ajay Kumar Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/misc/cros_ec_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c index 7df709cc71..015333f139 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; From a4e29db2571144a05ad09380b3674fe5b492f693 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 7 Jul 2014 10:16:38 -0600 Subject: [PATCH 3/5] exynos: spi: Fix calculation of SPI transaction start time The SPI transaction delay is supposed to be measured from the end of one transaction to the start of the next. The code does not work that way, so fix it. Signed-off-by: Simon Glass Tested-by: Ajay Kumar Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/spi/exynos_spi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c index c92276fdf7..2969184ee8 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); } From 22052c6236cbebc446ffd51ac69271fe063c654a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 7 Jul 2014 10:16:39 -0600 Subject: [PATCH 4/5] spi: Support half-duplex mode in FDT decode This parameter should also be supported. Signed-off-by: Simon Glass Tested-by: Ajay Kumar Reviewed-by: Jagannadha Sutradharudu Teki --- doc/device-tree-bindings/spi/spi-bus.txt | 2 ++ drivers/spi/spi.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/doc/device-tree-bindings/spi/spi-bus.txt b/doc/device-tree-bindings/spi/spi-bus.txt index 800dafe5b0..5c8720a820 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/spi/spi.c b/drivers/spi/spi.c index 7ddea9b026..7d81fbd7f8 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 From f659b57361c4a351ef2a5fc23b9197428e2e67f0 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Mon, 14 Jul 2014 10:22:11 +0200 Subject: [PATCH 5/5] spi, spi_mxc: do not hang in spi_xchg_single if status register do never set MXC_CSPICTRL_TC, spi_xchg_single endless loops. Add a timeout here to prevent endless hang. Signed-off-by: Heiko Schocher Cc: Dirk Behme Reviewed-by: Jagannadha Sutradharudu Teki --- README | 4 ++++ drivers/spi/mxc_spi.c | 17 +++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/README b/README index f704eb3780..c52ffd9758 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/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index f3f029d634..2d5f3850da 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(®s->ctrl, mxcs->ctrl_reg | MXC_CSPICTRL_EN | MXC_CSPICTRL_XCH); + ts = get_timer(0); + status = reg_read(®s->stat); /* Wait until the TC (Transfer completed) bit is set */ - while ((reg_read(®s->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(®s->stat); + } /* Transfer completed, clear any pending request */ reg_write(®s->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);