aboutsummaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch209
1 files changed, 209 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch
new file mode 100644
index 0000000..af15bae
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch
@@ -0,0 +1,209 @@
+From 383d0d23b9292dab56a2fdf5f6fecf898be6d142 Mon Sep 17 00:00:00 2001
+From: Hisashi Nakamura <hisashi.nakamura.ak@renesas.com>
+Date: Mon, 28 Jul 2014 14:47:56 +0900
+Subject: [PATCH 4/7] spi: sh-msiof: Add slave mode support
+
+Add slave mode support to the MSIOF driver, in both PIO and DMA mode.
+
+For now this only supports the transmission of messages with a size
+that is known in advance.
+
+Signed-off-by: Hisashi Nakamura <hisashi.nakamura.ak@renesas.com>
+Signed-off-by: Hiromitsu Yamasaki <hiromitsu.yamasaki.ym@renesas.com>
+[geert: Timeout handling cleanup, spi core integration, cancellation,
+ rewording]
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Acked-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/spi/sh-msiof.txt | 2 +
+ drivers/spi/spi-sh-msiof.c | 79 ++++++++++++++------
+ 2 files changed, 60 insertions(+), 21 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt
+index c2b6251..74ee3cd 100644
+--- a/Documentation/devicetree/bindings/spi/sh-msiof.txt
++++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt
+@@ -33,6 +33,8 @@ Optional properties:
+ specifiers, one for transmission, and one for
+ reception.
+ - dma-names : Must contain a list of two DMA names, "tx" and "rx".
++- spi-slave : Empty property indicating the SPI controller is used
++ in slave mode.
+ - renesas,dtdl : delay sync signal (setup) in transmit mode.
+ Must contain one of the following values:
+ 0 (no bit delay)
+diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
+index 3281dc7..3b87024 100644
+--- a/drivers/spi/spi-sh-msiof.c
++++ b/drivers/spi/spi-sh-msiof.c
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 2016-2017 Renesas Electronics Corporation
+ * Copyright (c) 2009 Magnus Damm
+- * Copyright (C) 2014 Glider bvba
++ * Copyright (C) 2014-2017 Glider bvba
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -35,7 +35,6 @@
+
+ #include <asm/unaligned.h>
+
+-
+ struct sh_msiof_chipdata {
+ u16 tx_fifo_size;
+ u16 rx_fifo_size;
+@@ -62,6 +61,7 @@ struct sh_msiof_spi_priv {
+ void *rx_dma_page;
+ dma_addr_t tx_dma_addr;
+ dma_addr_t rx_dma_addr;
++ bool slave_aborted;
+ unsigned int quirks;
+ };
+
+@@ -712,6 +712,33 @@ static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf)
+ return ret;
+ }
+
++static int sh_msiof_slave_abort(struct spi_master *master)
++{
++ struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
++
++ p->slave_aborted = true;
++ complete(&p->done);
++ return 0;
++}
++
++static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p)
++{
++ if (spi_controller_is_slave(p->master)) {
++ if (wait_for_completion_interruptible(&p->done) ||
++ p->slave_aborted) {
++ dev_dbg(&p->pdev->dev, "interrupted\n");
++ return -EINTR;
++ }
++ } else {
++ if (!wait_for_completion_timeout(&p->done, HZ)) {
++ dev_err(&p->pdev->dev, "timeout\n");
++ return -ETIMEDOUT;
++ }
++ }
++
++ return 0;
++}
++
+ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
+ void (*tx_fifo)(struct sh_msiof_spi_priv *,
+ const void *, int, int),
+@@ -747,6 +774,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
+ tx_fifo(p, tx_buf, words, fifo_shift);
+
+ reinit_completion(&p->done);
++ p->slave_aborted = false;
+
+ ret = sh_msiof_spi_start(p, rx_buf);
+ if (ret) {
+@@ -867,6 +895,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
+ reinit_completion(&p->done);
+ reinit_completion(&p->done_dma_tx);
+ reinit_completion(&p->done_dma_rx);
++ p->slave_aborted = false;
+
+ /* Now start DMA */
+ if (rx)
+@@ -1205,8 +1234,14 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
+ if (!info)
+ return NULL;
+
++ if (of_property_read_bool(np, "slave"))
++ info->mode = SPI_MSIOF_SLAVE;
++ else
++ info->mode = SPI_MSIOF_MASTER;
++
+ /* Parse the MSIOF properties */
+- of_property_read_u32(np, "num-cs", &num_cs);
++ if (info->mode == SPI_MSIOF_MASTER)
++ of_property_read_u32(np, "num-cs", &num_cs);
+ of_property_read_u32(np, "renesas,tx-fifo-size",
+ &info->tx_fifo_override);
+ of_property_read_u32(np, "renesas,rx-fifo-size",
+@@ -1214,10 +1249,6 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
+ of_property_read_u32(np, "renesas,dtdl", &info->dtdl);
+ of_property_read_u32(np, "renesas,syncdl", &info->syncdl);
+
+- if (of_property_read_bool(np, "slave"))
+- info->mode = SPI_MSIOF_SLAVE;
+- else
+- info->mode = SPI_MSIOF_MASTER;
+
+ info->num_chipselect = num_cs;
+
+@@ -1368,6 +1399,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
+ struct spi_master *master;
+ const struct sh_msiof_chipdata *chipdata;
+ const struct of_device_id *of_id;
++ struct sh_msiof_spi_info *info;
+ struct sh_msiof_spi_priv *p;
+ struct clk *ref_clk;
+ u32 clk_rate = 0;
+@@ -1375,32 +1407,36 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
+ int ret;
+ const struct soc_device_attribute *attr;
+
+- master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
+- if (master == NULL) {
+- dev_err(&pdev->dev, "failed to allocate spi master\n");
+- return -ENOMEM;
+- }
+-
+- p = spi_master_get_devdata(master);
+-
+- platform_set_drvdata(pdev, p);
+- p->master = master;
+-
+ of_id = of_match_device(sh_msiof_match, &pdev->dev);
+ if (of_id) {
+ chipdata = of_id->data;
+- p->info = sh_msiof_spi_parse_dt(&pdev->dev);
++ info = sh_msiof_spi_parse_dt(&pdev->dev);
+ } else {
+ chipdata = (const void *)pdev->id_entry->driver_data;
+- p->info = dev_get_platdata(&pdev->dev);
++ info = dev_get_platdata(&pdev->dev);
+ }
+
+- if (!p->info) {
++ if (!info) {
+ dev_err(&pdev->dev, "failed to obtain device info\n");
+ ret = -ENXIO;
+ goto err1;
+ }
+
++ if (info->mode == SPI_MSIOF_SLAVE)
++ master = spi_alloc_slave(&pdev->dev,
++ sizeof(struct sh_msiof_spi_priv));
++ else
++ master = spi_alloc_master(&pdev->dev,
++ sizeof(struct sh_msiof_spi_priv));
++ if (master == NULL)
++ return -ENOMEM;
++
++ p = spi_master_get_devdata(master);
++
++ platform_set_drvdata(pdev, p);
++ p->master = master;
++ p->info = info;
++
+ attr = soc_device_match(rcar_quirks_match);
+ if (attr)
+ p->quirks = (uintptr_t)attr->data;
+@@ -1458,6 +1494,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
+ master->num_chipselect = p->info->num_chipselect;
+ master->setup = sh_msiof_spi_setup;
+ master->prepare_message = sh_msiof_prepare_message;
++ master->slave_abort = sh_msiof_slave_abort;
+ master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
+ master->auto_runtime_pm = true;
+ master->transfer_one = sh_msiof_transfer_one;
+--
+1.7.10.4