linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] spi: lpspi: Add cs-gpio support
@ 2018-12-04  6:24 Clark Wang
  2018-12-11 14:26 ` Mark Brown
  0 siblings, 1 reply; 3+ messages in thread
From: Clark Wang @ 2018-12-04  6:24 UTC (permalink / raw)
  To: broonie; +Cc: linux-spi, linux-kernel, Clark Wang

Add cs-gpio feature for LPSPI. Use fsl_lpspi_prepare_message() and
fsl_lpspi_unprepare_message() to enable and control cs line.
These two functions will be only called at the beginning and the ending
of a message transfer.

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 | 79 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index a7d01b79827b..c6fe3f94de19 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
@@ -104,6 +111,8 @@ struct fsl_lpspi_data {
 	struct completion xfer_done;
 
 	bool slave_aborted;
+
+	int chipselect[0];
 };
 
 static const struct of_device_id fsl_lpspi_dt_ids[] = {
@@ -176,6 +185,48 @@ 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 int fsl_lpspi_prepare_message(struct spi_controller *controller,
+						struct spi_message *msg)
+{
+	struct fsl_lpspi_data *fsl_lpspi =
+				spi_controller_get_devdata(controller);
+	struct spi_device *spi = msg->spi;
+	int gpio = fsl_lpspi->chipselect[spi->chip_select];
+
+	if (gpio_is_valid(gpio)) {
+		gpio_direction_output(gpio,
+				fsl_lpspi->config.mode & SPI_CS_HIGH ? 0 : 1);
+	}
+
+	fsl_lpspi_chipselect(spi, LPSPI_CS_ACTIVE);
+
+	return 0;
+}
+
+static int fsl_lpspi_unprepare_message(struct spi_controller *controller,
+						struct spi_message *msg)
+{
+	struct spi_device *spi = msg->spi;
+
+	fsl_lpspi_chipselect(spi, LPSPI_CS_INACTIVE);
+
+	return 0;
+}
+
 static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
 {
 	u8 txfifo_cnt;
@@ -512,10 +563,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"))
@@ -539,6 +593,29 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
 	fsl_lpspi->is_slave = of_property_read_bool((&pdev->dev)->of_node,
 						    "spi-slave");
 
+	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->prepare_message = fsl_lpspi_prepare_message;
+		controller->unprepare_message = fsl_lpspi_unprepare_message;
+	}
+
 	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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] spi: lpspi: Add cs-gpio support
  2018-12-04  6:24 [PATCH] spi: lpspi: Add cs-gpio support Clark Wang
@ 2018-12-11 14:26 ` Mark Brown
  2018-12-12  2:12   ` Clark Wang
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Brown @ 2018-12-11 14:26 UTC (permalink / raw)
  To: Clark Wang; +Cc: linux-spi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 709 bytes --]

On Tue, Dec 04, 2018 at 06:24:59AM +0000, Clark Wang wrote:

> Add cs-gpio feature for LPSPI. Use fsl_lpspi_prepare_message() and
> fsl_lpspi_unprepare_message() to enable and control cs line.
> These two functions will be only called at the beginning and the ending
> of a message transfer.

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

Why is this not using the core support for GPIO chip selects?  Note that
you can't just implement chip select in the prepare and unprepare,
drivers can toggle chip select within a message so the code should be
looking at the individual transfers to see if cs_change is set and
acting accordingly.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [PATCH] spi: lpspi: Add cs-gpio support
  2018-12-11 14:26 ` Mark Brown
@ 2018-12-12  2:12   ` Clark Wang
  0 siblings, 0 replies; 3+ messages in thread
From: Clark Wang @ 2018-12-12  2:12 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi, linux-kernel


> -----Original Message-----
> From: Mark Brown <broonie@kernel.org>
> Sent: Tuesday, December 11, 2018 22:26
> To: Clark Wang <xiaoning.wang@nxp.com>
> Cc: linux-spi@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH] spi: lpspi: Add cs-gpio support
> 
> On Tue, Dec 04, 2018 at 06:24:59AM +0000, Clark Wang wrote:
> 
> > Add cs-gpio feature for LPSPI. Use fsl_lpspi_prepare_message() and
> > fsl_lpspi_unprepare_message() to enable and control cs line.
> > These two functions will be only called at the beginning and the
> > ending of a message transfer.
> 
> > Still support using the mode without cs-gpio. It depends on if
> > attribute cs-gpio has been configured in dts file.
> 
> Why is this not using the core support for GPIO chip selects?  Note that you
> can't just implement chip select in the prepare and unprepare, drivers can
> toggle chip select within a message so the code should be looking at the
> individual transfers to see if cs_change is set and acting accordingly.

Ok, I will try to use the core support for GPIO chip selects.

Regards,
Clark Wang

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-12-12  2:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-04  6:24 [PATCH] spi: lpspi: Add cs-gpio support Clark Wang
2018-12-11 14:26 ` Mark Brown
2018-12-12  2:12   ` Clark Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).