All of lore.kernel.org
 help / color / mirror / Atom feed
From: Clark Wang <xiaoning.wang@nxp.com>
To: "broonie@kernel.org" <broonie@kernel.org>
Cc: "linux-spi@vger.kernel.org" <linux-spi@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Clark Wang <xiaoning.wang@nxp.com>
Subject: [PATCH 7/8] spi: lpspi: Add cs-gpio support
Date: Mon, 7 Jan 2019 07:47:47 +0000	[thread overview]
Message-ID: <20190107074639.6336-8-xiaoning.wang@nxp.com> (raw)
In-Reply-To: <20190107074639.6336-1-xiaoning.wang@nxp.com>

Add cs-gpio feature for LPSPI.
The cs line will be controlled in fsl_lpspi_transfe_one_msg() function.

Still support using the mode without cs-gpio. It depends on if attribute
cs-gpio has been configured in dts file.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
 drivers/spi/spi-fsl-lpspi.c | 89 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 69635cde0e22..83e15366b739 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -9,6 +9,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -16,7 +17,9 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/spi-imx.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
@@ -28,6 +31,10 @@
 
 #define FSL_LPSPI_RPM_TIMEOUT 50 /* 50ms */
 
+#define LPSPI_CS_ACTIVE		1
+#define LPSPI_CS_INACTIVE	0
+#define LPSPI_CS_DELAY		100
+
 /* i.MX7ULP LPSPI registers */
 #define IMX7ULP_VERID	0x0
 #define IMX7ULP_PARAM	0x4
@@ -91,6 +98,7 @@ struct fsl_lpspi_data {
 	struct clk *clk_ipg;
 	struct clk *clk_per;
 	bool is_slave;
+	bool hascsgpio;
 
 	void *rx_buf;
 	const void *tx_buf;
@@ -106,6 +114,8 @@ struct fsl_lpspi_data {
 	struct completion xfer_done;
 
 	bool slave_aborted;
+
+	int chipselect[4];
 };
 
 static const struct of_device_id fsl_lpspi_dt_ids[] = {
@@ -178,6 +188,20 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller)
 	return 0;
 }
 
+static void fsl_lpspi_chipselect(struct spi_device *spi, bool enable)
+{
+	struct fsl_lpspi_data *fsl_lpspi =
+				spi_controller_get_devdata(spi->controller);
+	int gpio = fsl_lpspi->chipselect[spi->chip_select];
+
+	enable = (!!(spi->mode & SPI_CS_HIGH) == enable);
+
+	if (!gpio_is_valid(gpio))
+		return;
+
+	gpio_set_value_cansleep(gpio, enable);
+}
+
 static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
 {
 	u8 txfifo_cnt;
@@ -422,6 +446,25 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller,
 	return 0;
 }
 
+static int fsl_lpspi_setup(struct spi_device *spi)
+{
+	struct fsl_lpspi_data *fsl_lpspi =
+				spi_controller_get_devdata(spi->controller);
+	int gpio = fsl_lpspi->chipselect[spi->chip_select];
+
+	dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__,
+		 spi->mode, spi->bits_per_word, spi->max_speed_hz);
+
+	if (gpio_is_valid(gpio)) {
+		gpio_direction_output(gpio,
+				fsl_lpspi->config.mode & SPI_CS_HIGH ? 0 : 1);
+	}
+
+	fsl_lpspi_chipselect(spi, LPSPI_CS_INACTIVE);
+
+	return 0;
+}
+
 static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
 				      struct spi_message *msg)
 {
@@ -430,8 +473,12 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
 	struct spi_device *spi = msg->spi;
 	struct spi_transfer *xfer;
 	bool is_first_xfer = true;
+	bool keep_cs = false;
 	int ret = 0;
 
+	if (fsl_lpspi->hascsgpio)
+		fsl_lpspi_chipselect(spi, LPSPI_CS_ACTIVE);
+
 	msg->status = 0;
 	msg->actual_length = 0;
 
@@ -448,10 +495,24 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
 		if (ret < 0)
 			goto complete;
 
+		if (fsl_lpspi->hascsgpio && xfer->cs_change) {
+			if (list_is_last(&xfer->transfer_list,
+					 &msg->transfers)) {
+				keep_cs = true;
+			} else {
+				fsl_lpspi_chipselect(spi, LPSPI_CS_INACTIVE);
+				udelay(10);
+				fsl_lpspi_chipselect(spi, LPSPI_CS_ACTIVE);
+			}
+		}
+
 		msg->actual_length += xfer->len;
 	}
 
 complete:
+	if (fsl_lpspi->hascsgpio && !keep_cs)
+		fsl_lpspi_chipselect(spi, LPSPI_CS_INACTIVE);
+
 	msg->status = ret;
 	spi_finalize_current_message(controller);
 
@@ -531,10 +592,13 @@ static int fsl_lpspi_init_rpm(struct fsl_lpspi_data *fsl_lpspi)
 
 static int fsl_lpspi_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
 	struct fsl_lpspi_data *fsl_lpspi;
 	struct spi_controller *controller;
+	struct spi_imx_master *lpspi_platform_info =
+		dev_get_platdata(&pdev->dev);
 	struct resource *res;
-	int ret, irq;
+	int i, ret, irq;
 	u32 temp;
 
 	if (of_property_read_bool((&pdev->dev)->of_node, "spi-slave"))
@@ -558,6 +622,29 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
 	fsl_lpspi->is_slave = of_property_read_bool((&pdev->dev)->of_node,
 						    "spi-slave");
 
+	fsl_lpspi->hascsgpio = false;
+	if (!fsl_lpspi->is_slave) {
+		for (i = 0; i < controller->num_chipselect; i++) {
+			int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
+
+			if (!gpio_is_valid(cs_gpio) && lpspi_platform_info)
+				cs_gpio = lpspi_platform_info->chipselect[i];
+
+			fsl_lpspi->chipselect[i] = cs_gpio;
+			if (!gpio_is_valid(cs_gpio))
+				continue;
+
+			ret = devm_gpio_request(&pdev->dev,
+					fsl_lpspi->chipselect[i], DRIVER_NAME);
+			if (ret) {
+				dev_err(&pdev->dev, "can't get cs gpios\n");
+				goto out_controller_put;
+			}
+			controller->setup = fsl_lpspi_setup;
+			fsl_lpspi->hascsgpio = true;
+		}
+	}
+
 	controller->transfer_one_message = fsl_lpspi_transfer_one_msg;
 	controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware;
 	controller->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware;
-- 
2.17.1


  parent reply	other threads:[~2019-01-07  7:48 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-07  7:47 [PATCH 0/8] spi: lpspi: Fix bugs and Add some functions support Clark Wang
2019-01-07  7:47 ` Clark Wang
2019-01-07  7:47 ` [PATCH 1/8] spi: lpspi: Add i.MX8 boards support for lpspi Clark Wang
2019-01-07 15:15   ` Mark Brown
2019-01-07  7:47 ` [PATCH 2/8] spi: lpspi: enable runtime pm " Clark Wang
2019-01-07 15:16   ` Mark Brown
2019-01-07  7:47 ` [PATCH 3/8] spi: lpspi: Improve the stability of lpspi data transmission Clark Wang
2019-01-07  7:47 ` [PATCH 4/8] spi: lpspi: Fix wrong transmission when don't use CONT Clark Wang
2019-01-07 18:59   ` Applied "spi: lpspi: Fix wrong transmission when don't use CONT" to the spi tree Mark Brown
2019-01-07 18:59     ` Mark Brown
2019-01-07  7:47 ` [PATCH 5/8] spi: lpspi: Fix CLK pin becomes low before one transfer Clark Wang
2019-01-07  7:47 ` [PATCH 6/8] spi: lpspi: add the error info of transfer speed setting Clark Wang
2019-01-09 12:43   ` Mark Brown
2019-01-07  7:47 ` Clark Wang [this message]
2019-01-09 12:33   ` [PATCH 7/8] spi: lpspi: Add cs-gpio support Mark Brown
2019-01-07  7:47 ` [PATCH 8/8] spi: lpspi: add dma mode support Clark Wang
2019-01-07 15:22   ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190107074639.6336-8-xiaoning.wang@nxp.com \
    --to=xiaoning.wang@nxp.com \
    --cc=broonie@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-spi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.