Commit aa62325d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'spi-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi updates from Mark Brown:
 "The big theme for this release has been performance, we've had a
  series of unrelated overhauls of a few drivers all with a big
  peformance component.

  Otherwise it's been relatively quiet, highlights include:

   - A big overhaul of the spi-fsl-dspi driver improving the code
     quality, performance and stability from Vladimir Oltean.

   - A big performance enhancement for the bc2835 (Raspberry Pi) driver
     for unidirectional transfers from Lukas Wunner.

   - Improved performance on small transfers for the uniphier driver
     from Keiji Hayashibara.

   - Lots of coccinelle generated cleanups from Yue Haibing.

   - New device support for Freescale ls2080a and Nuvoton NPCM FIU"

* tag 'spi-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (102 commits)
  spi: mediatek: support large PA
  spi: mediatek: add spi support for mt6765 IC
  dt-bindings: spi: update bindings for MT6765 SoC
  spi: bcm2835: Speed up RX-only DMA transfers by zero-filling TX FIFO
  spi: bcm2835: Speed up TX-only DMA transfers by clearing RX FIFO
  dmaengine: bcm2835: Avoid accessing memory when copying zeroes
  spi: bcm2835: Cache CS register value for ->prepare_message()
  dmaengine: bcm2835: Document struct bcm2835_dmadev
  spi: Guarantee cacheline alignment of driver-private data
  dmaengine: bcm2835: Allow reusable descriptors
  dmaengine: bcm2835: Allow cyclic transactions without interrupt
  spi: bcm2835: Drop dma_pending flag
  spi: bcm2835: Work around DONE bit erratum
  spi-gpio: Use PTR_ERR_OR_ZERO() in spi_gpio_request()
  spi: Use an abbreviated pointer to ctlr->cur_msg in __spi_pump_messages
  spi: npcm-fiu: remove set but not used variable 'retlen'
  spi: fsl-spi: use devm_platform_ioremap_resource() to simplify code
  spi: zynq-qspi: use devm_platform_ioremap_resource() to simplify code
  spi: zynqmp: use devm_platform_ioremap_resource() to simplify code
  spi: xlp: use devm_platform_ioremap_resource() to simplify code
  ...
parents c4d11ccb b769c5ba
...@@ -410,7 +410,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) ...@@ -410,7 +410,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "failed to get irq (%d)\n", irq);
ret = irq; ret = irq;
goto err_put_ctlr; goto err_put_ctlr;
} }
......
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
#define BIT_WDG_EN BIT(2) #define BIT_WDG_EN BIT(2)
/* Definition of PMIC reset status register */ /* Definition of PMIC reset status register */
#define HWRST_STATUS_SECURITY 0x02
#define HWRST_STATUS_RECOVERY 0x20 #define HWRST_STATUS_RECOVERY 0x20
#define HWRST_STATUS_NORMAL 0x40 #define HWRST_STATUS_NORMAL 0x40
#define HWRST_STATUS_ALARM 0x50 #define HWRST_STATUS_ALARM 0x50
...@@ -97,6 +98,8 @@ ...@@ -97,6 +98,8 @@
#define HWRST_STATUS_AUTODLOADER 0xa0 #define HWRST_STATUS_AUTODLOADER 0xa0
#define HWRST_STATUS_IQMODE 0xb0 #define HWRST_STATUS_IQMODE 0xb0
#define HWRST_STATUS_SPRDISK 0xc0 #define HWRST_STATUS_SPRDISK 0xc0
#define HWRST_STATUS_FACTORYTEST 0xe0
#define HWRST_STATUS_WATCHDOG 0xf0
/* Use default timeout 50 ms that converts to watchdog values */ /* Use default timeout 50 ms that converts to watchdog values */
#define WDG_LOAD_VAL ((50 * 1000) / 32768) #define WDG_LOAD_VAL ((50 * 1000) / 32768)
...@@ -162,14 +165,16 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) ...@@ -162,14 +165,16 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val)
int read_timeout = ADI_READ_TIMEOUT; int read_timeout = ADI_READ_TIMEOUT;
unsigned long flags; unsigned long flags;
u32 val, rd_addr; u32 val, rd_addr;
int ret; int ret = 0;
ret = hwspin_lock_timeout_irqsave(sadi->hwlock, if (sadi->hwlock) {
ADI_HWSPINLOCK_TIMEOUT, ret = hwspin_lock_timeout_irqsave(sadi->hwlock,
&flags); ADI_HWSPINLOCK_TIMEOUT,
if (ret) { &flags);
dev_err(sadi->dev, "get the hw lock failed\n"); if (ret) {
return ret; dev_err(sadi->dev, "get the hw lock failed\n");
return ret;
}
} }
/* /*
...@@ -216,7 +221,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) ...@@ -216,7 +221,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val)
*read_val = val & RD_VALUE_MASK; *read_val = val & RD_VALUE_MASK;
out: out:
hwspin_unlock_irqrestore(sadi->hwlock, &flags); if (sadi->hwlock)
hwspin_unlock_irqrestore(sadi->hwlock, &flags);
return ret; return ret;
} }
...@@ -227,12 +233,14 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) ...@@ -227,12 +233,14 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val)
unsigned long flags; unsigned long flags;
int ret; int ret;
ret = hwspin_lock_timeout_irqsave(sadi->hwlock, if (sadi->hwlock) {
ADI_HWSPINLOCK_TIMEOUT, ret = hwspin_lock_timeout_irqsave(sadi->hwlock,
&flags); ADI_HWSPINLOCK_TIMEOUT,
if (ret) { &flags);
dev_err(sadi->dev, "get the hw lock failed\n"); if (ret) {
return ret; dev_err(sadi->dev, "get the hw lock failed\n");
return ret;
}
} }
ret = sprd_adi_drain_fifo(sadi); ret = sprd_adi_drain_fifo(sadi);
...@@ -258,7 +266,8 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) ...@@ -258,7 +266,8 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val)
} }
out: out:
hwspin_unlock_irqrestore(sadi->hwlock, &flags); if (sadi->hwlock)
hwspin_unlock_irqrestore(sadi->hwlock, &flags);
return ret; return ret;
} }
...@@ -307,6 +316,18 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, ...@@ -307,6 +316,18 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr,
return 0; return 0;
} }
static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi)
{
#ifdef CONFIG_SPRD_WATCHDOG
u32 val;
/* Set default watchdog reboot mode */
sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val);
val |= HWRST_STATUS_WATCHDOG;
sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val);
#endif
}
static int sprd_adi_restart_handler(struct notifier_block *this, static int sprd_adi_restart_handler(struct notifier_block *this,
unsigned long mode, void *cmd) unsigned long mode, void *cmd)
{ {
...@@ -336,11 +357,16 @@ static int sprd_adi_restart_handler(struct notifier_block *this, ...@@ -336,11 +357,16 @@ static int sprd_adi_restart_handler(struct notifier_block *this,
reboot_mode = HWRST_STATUS_IQMODE; reboot_mode = HWRST_STATUS_IQMODE;
else if (!strncmp(cmd, "sprdisk", 7)) else if (!strncmp(cmd, "sprdisk", 7))
reboot_mode = HWRST_STATUS_SPRDISK; reboot_mode = HWRST_STATUS_SPRDISK;
else if (!strncmp(cmd, "tospanic", 8))
reboot_mode = HWRST_STATUS_SECURITY;
else if (!strncmp(cmd, "factorytest", 11))
reboot_mode = HWRST_STATUS_FACTORYTEST;
else else
reboot_mode = HWRST_STATUS_NORMAL; reboot_mode = HWRST_STATUS_NORMAL;
/* Record the reboot mode */ /* Record the reboot mode */
sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val);
val &= ~HWRST_STATUS_WATCHDOG;
val |= reboot_mode; val |= reboot_mode;
sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val);
...@@ -380,9 +406,6 @@ static void sprd_adi_hw_init(struct sprd_adi *sadi) ...@@ -380,9 +406,6 @@ static void sprd_adi_hw_init(struct sprd_adi *sadi)
const __be32 *list; const __be32 *list;
u32 tmp; u32 tmp;
/* Address bits select default 12 bits */
writel_relaxed(0, sadi->base + REG_ADI_CTRL0);
/* Set all channels as default priority */ /* Set all channels as default priority */
writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIL); writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIL);
writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIH); writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIH);
...@@ -459,19 +482,30 @@ static int sprd_adi_probe(struct platform_device *pdev) ...@@ -459,19 +482,30 @@ static int sprd_adi_probe(struct platform_device *pdev)
sadi->slave_pbase = res->start + ADI_SLAVE_OFFSET; sadi->slave_pbase = res->start + ADI_SLAVE_OFFSET;
sadi->ctlr = ctlr; sadi->ctlr = ctlr;
sadi->dev = &pdev->dev; sadi->dev = &pdev->dev;
ret = of_hwspin_lock_get_id_byname(np, "adi"); ret = of_hwspin_lock_get_id(np, 0);
if (ret < 0) { if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) {
dev_err(&pdev->dev, "can not get the hardware spinlock\n"); sadi->hwlock =
goto put_ctlr; devm_hwspin_lock_request_specific(&pdev->dev, ret);
} if (!sadi->hwlock) {
ret = -ENXIO;
sadi->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, ret); goto put_ctlr;
if (!sadi->hwlock) { }
ret = -ENXIO; } else {
goto put_ctlr; switch (ret) {
case -ENOENT:
dev_info(&pdev->dev, "no hardware spinlock supplied\n");
break;
default:
dev_err(&pdev->dev,
"failed to find hwlock id, %d\n", ret);
/* fall-through */
case -EPROBE_DEFER:
goto put_ctlr;
}
} }
sprd_adi_hw_init(sadi); sprd_adi_hw_init(sadi);
sprd_adi_set_wdt_rst_mode(sadi);
ctlr->dev.of_node = pdev->dev.of_node; ctlr->dev.of_node = pdev->dev.of_node;
ctlr->bus_num = pdev->id; ctlr->bus_num = pdev->id;
......
...@@ -843,10 +843,8 @@ static int sprd_spi_irq_init(struct platform_device *pdev, struct sprd_spi *ss) ...@@ -843,10 +843,8 @@ static int sprd_spi_irq_init(struct platform_device *pdev, struct sprd_spi *ss)
int ret; int ret;
ss->irq = platform_get_irq(pdev, 0); ss->irq = platform_get_irq(pdev, 0);
if (ss->irq < 0) { if (ss->irq < 0)
dev_err(&pdev->dev, "failed to get irq resource\n");
return ss->irq; return ss->irq;
}
ret = devm_request_irq(&pdev->dev, ss->irq, sprd_spi_handle_irq, ret = devm_request_irq(&pdev->dev, ss->irq, sprd_spi_handle_irq,
0, pdev->name, ss); 0, pdev->name, ss);
......
...@@ -298,7 +298,6 @@ static int spi_st_probe(struct platform_device *pdev) ...@@ -298,7 +298,6 @@ static int spi_st_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct spi_master *master; struct spi_master *master;
struct resource *res;
struct spi_st *spi_st; struct spi_st *spi_st;
int irq, ret = 0; int irq, ret = 0;
u32 var; u32 var;
...@@ -331,8 +330,7 @@ static int spi_st_probe(struct platform_device *pdev) ...@@ -331,8 +330,7 @@ static int spi_st_probe(struct platform_device *pdev)
init_completion(&spi_st->done); init_completion(&spi_st->done);
/* Get resources */ /* Get resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi_st->base = devm_platform_ioremap_resource(pdev, 0);
spi_st->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(spi_st->base)) { if (IS_ERR(spi_st->base)) {
ret = PTR_ERR(spi_st->base); ret = PTR_ERR(spi_st->base);
goto clk_disable; goto clk_disable;
......
...@@ -570,11 +570,8 @@ static int stm32_qspi_probe(struct platform_device *pdev) ...@@ -570,11 +570,8 @@ static int stm32_qspi_probe(struct platform_device *pdev)
} }
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0)
if (irq != -EPROBE_DEFER)
dev_err(dev, "IRQ error missing or invalid\n");
return irq; return irq;
}
ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0, ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0,
dev_name(dev), qspi); dev_name(dev), qspi);
......
...@@ -428,7 +428,6 @@ static int sun4i_spi_probe(struct platform_device *pdev) ...@@ -428,7 +428,6 @@ static int sun4i_spi_probe(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
struct sun4i_spi *sspi; struct sun4i_spi *sspi;
struct resource *res;
int ret = 0, irq; int ret = 0, irq;
master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi)); master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi));
...@@ -440,8 +439,7 @@ static int sun4i_spi_probe(struct platform_device *pdev) ...@@ -440,8 +439,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master); sspi = spi_master_get_devdata(master);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); sspi->base_addr = devm_platform_ioremap_resource(pdev, 0);
sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sspi->base_addr)) { if (IS_ERR(sspi->base_addr)) {
ret = PTR_ERR(sspi->base_addr); ret = PTR_ERR(sspi->base_addr);
goto err_free_master; goto err_free_master;
...@@ -449,7 +447,6 @@ static int sun4i_spi_probe(struct platform_device *pdev) ...@@ -449,7 +447,6 @@ static int sun4i_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "No spi IRQ specified\n");
ret = -ENXIO; ret = -ENXIO;
goto err_free_master; goto err_free_master;
} }
......
...@@ -435,7 +435,6 @@ static int sun6i_spi_probe(struct platform_device *pdev) ...@@ -435,7 +435,6 @@ static int sun6i_spi_probe(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
struct sun6i_spi *sspi; struct sun6i_spi *sspi;
struct resource *res;
int ret = 0, irq; int ret = 0, irq;
master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi)); master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
...@@ -447,8 +446,7 @@ static int sun6i_spi_probe(struct platform_device *pdev) ...@@ -447,8 +446,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master); sspi = spi_master_get_devdata(master);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); sspi->base_addr = devm_platform_ioremap_resource(pdev, 0);
sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sspi->base_addr)) { if (IS_ERR(sspi->base_addr)) {
ret = PTR_ERR(sspi->base_addr); ret = PTR_ERR(sspi->base_addr);
goto err_free_master; goto err_free_master;
...@@ -456,7 +454,6 @@ static int sun6i_spi_probe(struct platform_device *pdev) ...@@ -456,7 +454,6 @@ static int sun6i_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "No spi IRQ specified\n");
ret = -ENXIO; ret = -ENXIO;
goto err_free_master; goto err_free_master;
} }
......
...@@ -670,7 +670,6 @@ static int synquacer_spi_probe(struct platform_device *pdev) ...@@ -670,7 +670,6 @@ static int synquacer_spi_probe(struct platform_device *pdev)
rx_irq = platform_get_irq(pdev, 0); rx_irq = platform_get_irq(pdev, 0);
if (rx_irq <= 0) { if (rx_irq <= 0) {
dev_err(&pdev->dev, "get rx_irq failed (%d)\n", rx_irq);
ret = rx_irq; ret = rx_irq;
goto put_spi; goto put_spi;
} }
...@@ -685,7 +684,6 @@ static int synquacer_spi_probe(struct platform_device *pdev) ...@@ -685,7 +684,6 @@ static int synquacer_spi_probe(struct platform_device *pdev)
tx_irq = platform_get_irq(pdev, 1); tx_irq = platform_get_irq(pdev, 1);
if (tx_irq <= 0) { if (tx_irq <= 0) {
dev_err(&pdev->dev, "get tx_irq failed (%d)\n", tx_irq);
ret = tx_irq; ret = tx_irq;
goto put_spi; goto put_spi;
} }
......
...@@ -419,7 +419,6 @@ static int tegra_sflash_probe(struct platform_device *pdev) ...@@ -419,7 +419,6 @@ static int tegra_sflash_probe(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
struct tegra_sflash_data *tsd; struct tegra_sflash_data *tsd;
struct resource *r;
int ret; int ret;
const struct of_device_id *match; const struct of_device_id *match;
...@@ -451,8 +450,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) ...@@ -451,8 +450,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
&master->max_speed_hz)) &master->max_speed_hz))
master->max_speed_hz = 25000000; /* 25MHz */ master->max_speed_hz = 25000000; /* 25MHz */
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); tsd->base = devm_platform_ioremap_resource(pdev, 0);
tsd->base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(tsd->base)) { if (IS_ERR(tsd->base)) {
ret = PTR_ERR(tsd->base); ret = PTR_ERR(tsd->base);
goto exit_free_master; goto exit_free_master;
......
...@@ -717,7 +717,6 @@ static int ti_qspi_probe(struct platform_device *pdev) ...@@ -717,7 +717,6 @@ static int ti_qspi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n");
ret = irq; ret = irq;
goto free_master; goto free_master;
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#define SSI_TIMEOUT_MS 2000 #define SSI_TIMEOUT_MS 2000
#define SSI_POLL_TIMEOUT_US 200
#define SSI_MAX_CLK_DIVIDER 254 #define SSI_MAX_CLK_DIVIDER 254
#define SSI_MIN_CLK_DIVIDER 4 #define SSI_MIN_CLK_DIVIDER 4
...@@ -214,6 +216,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi, ...@@ -214,6 +216,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi,
if (!priv->is_save_param || priv->mode != spi->mode) { if (!priv->is_save_param || priv->mode != spi->mode) {
uniphier_spi_set_mode(spi); uniphier_spi_set_mode(spi);
priv->mode = spi->mode; priv->mode = spi->mode;
priv->is_save_param = false;
} }
if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) { if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) {
...@@ -226,8 +229,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi, ...@@ -226,8 +229,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi,
priv->speed_hz = t->speed_hz; priv->speed_hz = t->speed_hz;
} }
if (!priv->is_save_param) priv->is_save_param = true;
priv->is_save_param = true;
/* reset FIFOs */ /* reset FIFOs */
val = SSI_FC_TXFFL | SSI_FC_RXFFL; val = SSI_FC_TXFFL | SSI_FC_RXFFL;
...@@ -290,21 +292,23 @@ static void uniphier_spi_recv(struct uniphier_spi_priv *priv) ...@@ -290,21 +292,23 @@ static void uniphier_spi_recv(struct uniphier_spi_priv *priv)
static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv) static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
{ {
unsigned int tx_count; unsigned int fifo_threshold, fill_bytes;
u32 val; u32 val;
tx_count = DIV_ROUND_UP(priv->tx_bytes, fifo_threshold = DIV_ROUND_UP(priv->rx_bytes,
bytes_per_word(priv->bits_per_word)); bytes_per_word(priv->bits_per_word));
tx_count = min(tx_count, SSI_FIFO_DEPTH); fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
fill_bytes = fifo_threshold - (priv->rx_bytes - priv->tx_bytes);
/* set fifo threshold */ /* set fifo threshold */
val = readl(priv->base + SSI_FC); val = readl(priv->base + SSI_FC);
val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK); val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK);
val |= FIELD_PREP(SSI_FC_TXFTH_MASK, tx_count); val |= FIELD_PREP(SSI_FC_TXFTH_MASK, fifo_threshold);
val |= FIELD_PREP(SSI_FC_RXFTH_MASK, tx_count); val |= FIELD_PREP(SSI_FC_RXFTH_MASK, fifo_threshold);
writel(val, priv->base + SSI_FC); writel(val, priv->base + SSI_FC);
while (tx_count--) while (fill_bytes--)
uniphier_spi_send(priv); uniphier_spi_send(priv);
} }
...@@ -323,20 +327,14 @@ static void uniphier_spi_set_cs(struct spi_device *spi, bool enable) ...@@ -323,20 +327,14 @@ static void uniphier_spi_set_cs(struct spi_device *spi, bool enable)
writel(val, priv->base + SSI_FPS); writel(val, priv->base + SSI_FPS);
} }
static int uniphier_spi_transfer_one(struct spi_master *master, static int uniphier_spi_transfer_one_irq(struct spi_master *master,
struct spi_device *spi, struct spi_device *spi,
struct spi_transfer *t) struct spi_transfer *t)
{ {
struct uniphier_spi_priv *priv = spi_master_get_devdata(master); struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
struct device *dev = master->dev.parent; struct device *dev = master->dev.parent;
unsigned long time_left; unsigned long time_left;
/* Terminate and return success for 0 byte length transfer */
if (!t->len)
return 0;
uniphier_spi_setup_transfer(spi, t);
reinit_completion(&priv->xfer_done); reinit_completion(&priv->xfer_done);
uniphier_spi_fill_tx_fifo(priv); uniphier_spi_fill_tx_fifo(priv);
...@@ -356,6 +354,59 @@ static int uniphier_spi_transfer_one(struct spi_master *master, ...@@ -356,6 +354,59 @@ static int uniphier_spi_transfer_one(struct spi_master *master,
return priv->error; return priv->error;
} }
static int uniphier_spi_transfer_one_poll(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *t)
{
struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
int loop = SSI_POLL_TIMEOUT_US * 10;
while (priv->tx_bytes) {
uniphier_spi_fill_tx_fifo(priv);
while ((priv->rx_bytes - priv->tx_bytes) > 0) {
while (!(readl(priv->base + SSI_SR) & SSI_SR_RNE)
&& loop--)
ndelay(100);
if (loop == -1)
goto irq_transfer;
uniphier_spi_recv(priv);
}
}
return 0;
irq_transfer:
return uniphier_spi_transfer_one_irq(master, spi, t);
}
static int uniphier_spi_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *t)
{
struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
unsigned long threshold;
/* Terminate and return success for 0 byte length transfer */
if (!t->len)
return 0;