Commit 7555aa76 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/fix/armada', 'spi/fix/idr',...

Merge remote-tracking branches 'spi/fix/armada', 'spi/fix/idr', 'spi/fix/qspi', 'spi/fix/stm32' and 'spi/fix/uapi' into spi-linus
...@@ -99,11 +99,6 @@ ...@@ -99,11 +99,6 @@
/* A3700_SPI_IF_TIME_REG */ /* A3700_SPI_IF_TIME_REG */
#define A3700_SPI_CLK_CAPT_EDGE BIT(7) #define A3700_SPI_CLK_CAPT_EDGE BIT(7)
/* Flags and macros for struct a3700_spi */
#define A3700_INSTR_CNT 1
#define A3700_ADDR_CNT 3
#define A3700_DUMMY_CNT 1
struct a3700_spi { struct a3700_spi {
struct spi_master *master; struct spi_master *master;
void __iomem *base; void __iomem *base;
...@@ -117,9 +112,6 @@ struct a3700_spi { ...@@ -117,9 +112,6 @@ struct a3700_spi {
u8 byte_len; u8 byte_len;
u32 wait_mask; u32 wait_mask;
struct completion done; struct completion done;
u32 addr_cnt;
u32 instr_cnt;
size_t hdr_cnt;
}; };
static u32 spireg_read(struct a3700_spi *a3700_spi, u32 offset) static u32 spireg_read(struct a3700_spi *a3700_spi, u32 offset)
...@@ -161,7 +153,7 @@ static void a3700_spi_deactivate_cs(struct a3700_spi *a3700_spi, ...@@ -161,7 +153,7 @@ static void a3700_spi_deactivate_cs(struct a3700_spi *a3700_spi,
} }
static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
unsigned int pin_mode) unsigned int pin_mode, bool receiving)
{ {
u32 val; u32 val;
...@@ -177,6 +169,9 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, ...@@ -177,6 +169,9 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
break; break;
case SPI_NBITS_QUAD: case SPI_NBITS_QUAD:
val |= A3700_SPI_DATA_PIN1; val |= A3700_SPI_DATA_PIN1;
/* RX during address reception uses 4-pin */
if (receiving)
val |= A3700_SPI_ADDR_PIN;
break; break;
default: default:
dev_err(&a3700_spi->master->dev, "wrong pin mode %u", pin_mode); dev_err(&a3700_spi->master->dev, "wrong pin mode %u", pin_mode);
...@@ -392,7 +387,8 @@ static bool a3700_spi_wait_completion(struct spi_device *spi) ...@@ -392,7 +387,8 @@ static bool a3700_spi_wait_completion(struct spi_device *spi)
spireg_write(a3700_spi, A3700_SPI_INT_MASK_REG, 0); spireg_write(a3700_spi, A3700_SPI_INT_MASK_REG, 0);
return true; /* Timeout was reached */
return false;
} }
static bool a3700_spi_transfer_wait(struct spi_device *spi, static bool a3700_spi_transfer_wait(struct spi_device *spi,
...@@ -446,59 +442,43 @@ static void a3700_spi_set_cs(struct spi_device *spi, bool enable) ...@@ -446,59 +442,43 @@ static void a3700_spi_set_cs(struct spi_device *spi, bool enable)
static void a3700_spi_header_set(struct a3700_spi *a3700_spi) static void a3700_spi_header_set(struct a3700_spi *a3700_spi)
{ {
u32 instr_cnt = 0, addr_cnt = 0, dummy_cnt = 0; unsigned int addr_cnt;
u32 val = 0; u32 val = 0;
/* Clear the header registers */ /* Clear the header registers */
spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, 0);
spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, 0);
spireg_write(a3700_spi, A3700_SPI_IF_RMODE_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_RMODE_REG, 0);
spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, 0);
/* Set header counters */ /* Set header counters */
if (a3700_spi->tx_buf) { if (a3700_spi->tx_buf) {
if (a3700_spi->buf_len <= a3700_spi->instr_cnt) { /*
instr_cnt = a3700_spi->buf_len; * when tx data is not 4 bytes aligned, there will be unexpected
} else if (a3700_spi->buf_len <= (a3700_spi->instr_cnt + * bytes out of SPI output register, since it always shifts out
a3700_spi->addr_cnt)) { * as whole 4 bytes. This might cause incorrect transaction with
instr_cnt = a3700_spi->instr_cnt; * some devices. To avoid that, use SPI header count feature to
addr_cnt = a3700_spi->buf_len - instr_cnt; * transfer up to 3 bytes of data first, and then make the rest
} else if (a3700_spi->buf_len <= a3700_spi->hdr_cnt) { * of data 4-byte aligned.
instr_cnt = a3700_spi->instr_cnt; */
addr_cnt = a3700_spi->addr_cnt; addr_cnt = a3700_spi->buf_len % 4;
/* Need to handle the normal write case with 1 byte if (addr_cnt) {
* data val = (addr_cnt & A3700_SPI_ADDR_CNT_MASK)
*/ << A3700_SPI_ADDR_CNT_BIT;
if (!a3700_spi->tx_buf[instr_cnt + addr_cnt]) spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, val);
dummy_cnt = a3700_spi->buf_len - instr_cnt -
addr_cnt; /* Update the buffer length to be transferred */
a3700_spi->buf_len -= addr_cnt;
/* transfer 1~3 bytes through address count */
val = 0;
while (addr_cnt--) {
val = (val << 8) | a3700_spi->tx_buf[0];
a3700_spi->tx_buf++;
}
spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, val);
} }
val |= ((instr_cnt & A3700_SPI_INSTR_CNT_MASK)
<< A3700_SPI_INSTR_CNT_BIT);
val |= ((addr_cnt & A3700_SPI_ADDR_CNT_MASK)
<< A3700_SPI_ADDR_CNT_BIT);
val |= ((dummy_cnt & A3700_SPI_DUMMY_CNT_MASK)
<< A3700_SPI_DUMMY_CNT_BIT);
} }
spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, val);
/* Update the buffer length to be transferred */
a3700_spi->buf_len -= (instr_cnt + addr_cnt + dummy_cnt);
/* Set Instruction */
val = 0;
while (instr_cnt--) {
val = (val << 8) | a3700_spi->tx_buf[0];
a3700_spi->tx_buf++;
}
spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, val);
/* Set Address */
val = 0;
while (addr_cnt--) {
val = (val << 8) | a3700_spi->tx_buf[0];
a3700_spi->tx_buf++;
}
spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, val);
} }
static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi) static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi)
...@@ -512,35 +492,12 @@ static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi) ...@@ -512,35 +492,12 @@ static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi)
static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi) static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi)
{ {
u32 val; u32 val;
int i = 0;
while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) { while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) {
val = 0; val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf);
if (a3700_spi->buf_len >= 4) { spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val);
val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf); a3700_spi->buf_len -= 4;
spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); a3700_spi->tx_buf += 4;
a3700_spi->buf_len -= 4;
a3700_spi->tx_buf += 4;
} else {
/*
* If the remained buffer length is less than 4-bytes,
* we should pad the write buffer with all ones. So that
* it avoids overwrite the unexpected bytes following
* the last one.
*/
val = GENMASK(31, 0);
while (a3700_spi->buf_len) {
val &= ~(0xff << (8 * i));
val |= *a3700_spi->tx_buf++ << (8 * i);
i++;
a3700_spi->buf_len--;
spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG,
val);
}
break;
}
} }
return 0; return 0;
...@@ -645,15 +602,18 @@ static int a3700_spi_transfer_one(struct spi_master *master, ...@@ -645,15 +602,18 @@ static int a3700_spi_transfer_one(struct spi_master *master,
a3700_spi->rx_buf = xfer->rx_buf; a3700_spi->rx_buf = xfer->rx_buf;
a3700_spi->buf_len = xfer->len; a3700_spi->buf_len = xfer->len;
/* SPI transfer headers */
a3700_spi_header_set(a3700_spi);
if (xfer->tx_buf) if (xfer->tx_buf)
nbits = xfer->tx_nbits; nbits = xfer->tx_nbits;
else if (xfer->rx_buf) else if (xfer->rx_buf)
nbits = xfer->rx_nbits; nbits = xfer->rx_nbits;
a3700_spi_pin_mode_set(a3700_spi, nbits); a3700_spi_pin_mode_set(a3700_spi, nbits, xfer->rx_buf ? true : false);
/* Flush the FIFOs */
a3700_spi_fifo_flush(a3700_spi);
/* Transfer first bytes of data when buffer is not 4-byte aligned */
a3700_spi_header_set(a3700_spi);
if (xfer->rx_buf) { if (xfer->rx_buf) {
/* Set read data length */ /* Set read data length */
...@@ -733,16 +693,11 @@ static int a3700_spi_transfer_one(struct spi_master *master, ...@@ -733,16 +693,11 @@ static int a3700_spi_transfer_one(struct spi_master *master,
dev_err(&spi->dev, "wait wfifo empty timed out\n"); dev_err(&spi->dev, "wait wfifo empty timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
} else { }
/*
* If the instruction in SPI_INSTR does not require data if (!a3700_spi_transfer_wait(spi, A3700_SPI_XFER_RDY)) {
* to be written to the SPI device, wait until SPI_RDY dev_err(&spi->dev, "wait xfer ready timed out\n");
* is 1 for the SPI interface to be in idle. return -ETIMEDOUT;
*/
if (!a3700_spi_transfer_wait(spi, A3700_SPI_XFER_RDY)) {
dev_err(&spi->dev, "wait xfer ready timed out\n");
return -ETIMEDOUT;
}
} }
val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
...@@ -834,10 +789,6 @@ static int a3700_spi_probe(struct platform_device *pdev) ...@@ -834,10 +789,6 @@ static int a3700_spi_probe(struct platform_device *pdev)
memset(spi, 0, sizeof(struct a3700_spi)); memset(spi, 0, sizeof(struct a3700_spi));
spi->master = master; spi->master = master;
spi->instr_cnt = A3700_INSTR_CNT;
spi->addr_cnt = A3700_ADDR_CNT;
spi->hdr_cnt = A3700_INSTR_CNT + A3700_ADDR_CNT +
A3700_DUMMY_CNT;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi->base = devm_ioremap_resource(dev, res); spi->base = devm_ioremap_resource(dev, res);
......
...@@ -1250,7 +1250,7 @@ int bcm_qspi_probe(struct platform_device *pdev, ...@@ -1250,7 +1250,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
goto qspi_probe_err; goto qspi_probe_err;
} }
} else { } else {
goto qspi_probe_err; goto qspi_resource_err;
} }
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
...@@ -1272,7 +1272,7 @@ int bcm_qspi_probe(struct platform_device *pdev, ...@@ -1272,7 +1272,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res); qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res);
if (IS_ERR(qspi->base[CHIP_SELECT])) { if (IS_ERR(qspi->base[CHIP_SELECT])) {
ret = PTR_ERR(qspi->base[CHIP_SELECT]); ret = PTR_ERR(qspi->base[CHIP_SELECT]);
goto qspi_probe_err; goto qspi_resource_err;
} }
} }
...@@ -1280,7 +1280,7 @@ int bcm_qspi_probe(struct platform_device *pdev, ...@@ -1280,7 +1280,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
GFP_KERNEL); GFP_KERNEL);
if (!qspi->dev_ids) { if (!qspi->dev_ids) {
ret = -ENOMEM; ret = -ENOMEM;
goto qspi_probe_err; goto qspi_resource_err;
} }
for (val = 0; val < num_irqs; val++) { for (val = 0; val < num_irqs; val++) {
...@@ -1369,8 +1369,9 @@ int bcm_qspi_probe(struct platform_device *pdev, ...@@ -1369,8 +1369,9 @@ int bcm_qspi_probe(struct platform_device *pdev,
bcm_qspi_hw_uninit(qspi); bcm_qspi_hw_uninit(qspi);
clk_disable_unprepare(qspi->clk); clk_disable_unprepare(qspi->clk);
qspi_probe_err: qspi_probe_err:
spi_master_put(master);
kfree(qspi->dev_ids); kfree(qspi->dev_ids);
qspi_resource_err:
spi_master_put(master);
return ret; return ret;
} }
/* probe function to be called by SoC specific platform driver probe */ /* probe function to be called by SoC specific platform driver probe */
......
...@@ -263,8 +263,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz) ...@@ -263,8 +263,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz)
* no need to check it there. * no need to check it there.
* However, we need to ensure the following calculations. * However, we need to ensure the following calculations.
*/ */
if ((div < SPI_MBR_DIV_MIN) && if (div < SPI_MBR_DIV_MIN ||
(div > SPI_MBR_DIV_MAX)) div > SPI_MBR_DIV_MAX)
return -EINVAL; return -EINVAL;
/* Determine the first power of 2 greater than or equal to div */ /* Determine the first power of 2 greater than or equal to div */
......
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/spi.h> #include <trace/events/spi.h>
#define SPI_DYN_FIRST_BUS_NUM 0
static DEFINE_IDR(spi_master_idr); static DEFINE_IDR(spi_master_idr);
...@@ -2086,7 +2085,7 @@ int spi_register_controller(struct spi_controller *ctlr) ...@@ -2086,7 +2085,7 @@ int spi_register_controller(struct spi_controller *ctlr)
struct device *dev = ctlr->dev.parent; struct device *dev = ctlr->dev.parent;
struct boardinfo *bi; struct boardinfo *bi;
int status = -ENODEV; int status = -ENODEV;
int id; int id, first_dynamic;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
...@@ -2116,9 +2115,15 @@ int spi_register_controller(struct spi_controller *ctlr) ...@@ -2116,9 +2115,15 @@ int spi_register_controller(struct spi_controller *ctlr)
} }
} }
if (ctlr->bus_num < 0) { if (ctlr->bus_num < 0) {
first_dynamic = of_alias_get_highest_id("spi");
if (first_dynamic < 0)
first_dynamic = 0;
else
first_dynamic++;
mutex_lock(&board_lock); mutex_lock(&board_lock);
id = idr_alloc(&spi_master_idr, ctlr, SPI_DYN_FIRST_BUS_NUM, 0, id = idr_alloc(&spi_master_idr, ctlr, first_dynamic,
GFP_KERNEL); 0, GFP_KERNEL);
mutex_unlock(&board_lock); mutex_unlock(&board_lock);
if (WARN(id < 0, "couldn't get idr")) if (WARN(id < 0, "couldn't get idr"))
return id; return id;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define SPIDEV_H #define SPIDEV_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/ioctl.h>
/* User space versions of kernel symbols for SPI clocking modes, /* User space versions of kernel symbols for SPI clocking modes,
* matching <linux/spi/spi.h> * matching <linux/spi/spi.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment