All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peng Fan <van.freenix@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/2] dm: spi: soft_spi: support linux way and bug fix
Date: Mon, 21 Mar 2016 16:29:37 +0800	[thread overview]
Message-ID: <1458548978-8741-1-git-send-email-van.freenix@gmail.com> (raw)

1. Support compatible string "spi-gpio" which is used by Linux
   Linux use different bindings, so use UBOOT_COMPAT and
   LINUX_COMPAT to differentiate them.
2. Bug fix
   When doing xfer, should use device->parent, but not device
   When doing bit xfer, should use "!!(tmpdout & 0x80)", but not
   "(tmpdout & 0x80)"
3. Introduce SPI_MASTER_NO_RX and SPI_MASTER_NO_TX to handle
   no rx or no tx case.
4. Tested on i.MX6 UltraLite board with 74LV595 spi-gpio chip.

Signed-off-by: Peng Fan <van.freenix@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Jagan Teki <jteki@openedev.com>
Cc: Stefano Babic <sbabic@denx.de>
---
 drivers/spi/soft_spi.c | 75 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 57 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
index aa4abcc..9a2b5f2 100644
--- a/drivers/spi/soft_spi.c
+++ b/drivers/spi/soft_spi.c
@@ -26,15 +26,23 @@ struct soft_spi_platdata {
 	struct gpio_desc mosi;
 	struct gpio_desc miso;
 	int spi_delay_us;
+	int flags;
 };
 
+#define SPI_MASTER_NO_RX        BIT(0)
+#define SPI_MASTER_NO_TX        BIT(1)
+
+#define UBOOT_COMPAT BIT(0)
+#define LINUX_COMPAT BIT(1)
+
 struct soft_spi_priv {
 	unsigned int mode;
 };
 
 static int soft_spi_scl(struct udevice *dev, int bit)
 {
-	struct soft_spi_platdata *plat = dev->platdata;
+	struct udevice *bus = dev_get_parent(dev);
+	struct soft_spi_platdata *plat = dev_get_platdata(bus);
 
 	dm_gpio_set_value(&plat->sclk, bit);
 
@@ -43,7 +51,8 @@ static int soft_spi_scl(struct udevice *dev, int bit)
 
 static int soft_spi_sda(struct udevice *dev, int bit)
 {
-	struct soft_spi_platdata *plat = dev->platdata;
+	struct udevice *bus = dev_get_parent(dev);
+	struct soft_spi_platdata *plat = dev_get_platdata(bus);
 
 	dm_gpio_set_value(&plat->mosi, bit);
 
@@ -52,7 +61,8 @@ static int soft_spi_sda(struct udevice *dev, int bit)
 
 static int soft_spi_cs_activate(struct udevice *dev)
 {
-	struct soft_spi_platdata *plat = dev->platdata;
+	struct udevice *bus = dev_get_parent(dev);
+	struct soft_spi_platdata *plat = dev_get_platdata(bus);
 
 	dm_gpio_set_value(&plat->cs, 0);
 	dm_gpio_set_value(&plat->sclk, 0);
@@ -63,7 +73,8 @@ static int soft_spi_cs_activate(struct udevice *dev)
 
 static int soft_spi_cs_deactivate(struct udevice *dev)
 {
-	struct soft_spi_platdata *plat = dev->platdata;
+	struct udevice *bus = dev_get_parent(dev);
+	struct soft_spi_platdata *plat = dev_get_platdata(bus);
 
 	dm_gpio_set_value(&plat->cs, 0);
 
@@ -100,8 +111,9 @@ static int soft_spi_release_bus(struct udevice *dev)
 static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen,
 			 const void *dout, void *din, unsigned long flags)
 {
-	struct soft_spi_priv *priv = dev_get_priv(dev);
-	struct soft_spi_platdata *plat = dev->platdata;
+	struct udevice *bus = dev_get_parent(dev);
+	struct soft_spi_priv *priv = dev_get_priv(bus);
+	struct soft_spi_platdata *plat = dev_get_platdata(bus);
 	uchar		tmpdin  = 0;
 	uchar		tmpdout = 0;
 	const u8	*txd = dout;
@@ -134,14 +146,16 @@ static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
 		if (!cpha)
 			soft_spi_scl(dev, 0);
-		soft_spi_sda(dev, tmpdout & 0x80);
+		if ((plat->flags & SPI_MASTER_NO_TX) == 0)
+			soft_spi_sda(dev, !!(tmpdout & 0x80));
 		udelay(plat->spi_delay_us);
 		if (cpha)
 			soft_spi_scl(dev, 0);
 		else
 			soft_spi_scl(dev, 1);
 		tmpdin	<<= 1;
-		tmpdin	|= dm_gpio_get_value(&plat->miso);
+		if ((plat->flags & SPI_MASTER_NO_RX) == 0)
+			tmpdin	|= dm_gpio_get_value(&plat->miso);
 		tmpdout	<<= 1;
 		udelay(plat->spi_delay_us);
 		if (cpha)
@@ -202,25 +216,50 @@ static int soft_spi_probe(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parent_priv(dev);
 	struct soft_spi_platdata *plat = dev->platdata;
+	ulong driver_data = dev_get_driver_data(dev);
 	int cs_flags, clk_flags;
+	int ret;
 
 	cs_flags = (slave->mode & SPI_CS_HIGH) ? 0 : GPIOD_ACTIVE_LOW;
 	clk_flags = (slave->mode & SPI_CPOL) ? GPIOD_ACTIVE_LOW : 0;
-	if (gpio_request_by_name(dev, "cs-gpio", 0, &plat->cs,
-				 GPIOD_IS_OUT | cs_flags) ||
-	    gpio_request_by_name(dev, "sclk-gpio", 0, &plat->sclk,
-				 GPIOD_IS_OUT | clk_flags) ||
-	    gpio_request_by_name(dev, "mosi-gpio", 0, &plat->mosi,
-				 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE) ||
-	    gpio_request_by_name(dev, "miso-gpio", 0, &plat->miso,
-				 GPIOD_IS_IN))
-		return -EINVAL;
+	if (driver_data & UBOOT_COMPAT) {
+		if (gpio_request_by_name(dev, "cs-gpio", 0, &plat->cs,
+					 GPIOD_IS_OUT | cs_flags) ||
+		    gpio_request_by_name(dev, "sclk-gpio", 0, &plat->sclk,
+					 GPIOD_IS_OUT | clk_flags) ||
+		    gpio_request_by_name(dev, "mosi-gpio", 0, &plat->mosi,
+					 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE) ||
+		    gpio_request_by_name(dev, "miso-gpio", 0, &plat->miso,
+					 GPIOD_IS_IN))
+			return -EINVAL;
+	} else if (driver_data & LINUX_COMPAT) {
+		if (gpio_request_by_name(dev, "cs-gpios", 0, &plat->cs,
+					 GPIOD_IS_OUT | cs_flags) ||
+		    gpio_request_by_name(dev, "gpio-sck", 0, &plat->sclk,
+					 GPIOD_IS_OUT | clk_flags))
+			return -EINVAL;
+
+		ret = gpio_request_by_name(dev, "gpio-mosi", 0, &plat->mosi,
+					   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+		if (ret)
+			plat->flags |= SPI_MASTER_NO_TX;
+
+		ret = gpio_request_by_name(dev, "gpio-miso", 0, &plat->miso,
+					   GPIOD_IS_IN);
+		if (ret)
+			plat->flags |= SPI_MASTER_NO_RX;
+
+		if ((plat->flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX)) ==
+		    (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX))
+			return -EINVAL;
+	}
 
 	return 0;
 }
 
 static const struct udevice_id soft_spi_ids[] = {
-	{ .compatible = "u-boot,soft-spi" },
+	{ .compatible = "u-boot,soft-spi", .data = UBOOT_COMPAT },
+	{ .compatible = "spi-gpio", .data = LINUX_COMPAT },
 	{ }
 };
 
-- 
2.6.2

             reply	other threads:[~2016-03-21  8:29 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-21  8:29 Peng Fan [this message]
2016-03-21  8:29 ` [U-Boot] [PATCH 2/2] dm: gpio: introduce 74x164 driver Peng Fan
2016-04-09 18:33   ` Simon Glass
2016-04-11  5:44     ` Peng Fan
2016-04-09 18:33 ` [U-Boot] [PATCH 1/2] dm: spi: soft_spi: support linux way and bug fix Simon Glass
2016-04-11  5:45   ` Peng Fan

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=1458548978-8741-1-git-send-email-van.freenix@gmail.com \
    --to=van.freenix@gmail.com \
    --cc=u-boot@lists.denx.de \
    /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.