Skip to contentSkip to conversation

gpio: 74x164: Use module_spi_driver boiler plate function

PATCH Superseded Maxime Ripard 5 participants 34 messages Sep 5, 2012 – Sep 7, 2012

Subsystems (4)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/8 gpio: 74x164: Use module_spi_driver boiler plate function

---
 drivers/gpio/gpio-74x164.c |   13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)
drivers/gpio/gpio-74x164.c +1 -12
index a31ad6f..2975036 100644
@@ -159,18 +159,7 @@ static struct spi_driver gen_74x164_driver = {
 	.probe		= gen_74x164_probe,
 	.remove		= __devexit_p(gen_74x164_remove),
 };
-
-static int __init gen_74x164_init(void)
-{
-	return spi_register_driver(&gen_74x164_driver);
-}
-subsys_initcall(gen_74x164_init);
-
-static void __exit gen_74x164_exit(void)
-{
-	spi_unregister_driver(&gen_74x164_driver);
-}
-module_exit(gen_74x164_exit);
+module_spi_driver(gen_74x164_driver);
 
 MODULE_AUTHOR("Gabor Juhos <[email protected]>");
 MODULE_AUTHOR("Miguel Gaio <[email protected]>");
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH 2/8 gpio: 74x164: Use devm_kzalloc

---
 drivers/gpio/gpio-74x164.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/gpio/gpio-74x164.c +3 -5
index 2975036..604b998 100644
@@ -90,7 +90,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 	if (ret < 0)
 		return ret;
 
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	chip = devm_kzalloc(&spi->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
@@ -125,7 +125,6 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 exit_destroy:
 	dev_set_drvdata(&spi->dev, NULL);
 	mutex_destroy(&chip->lock);
-	kfree(chip);
 	return ret;
 }
 
@@ -141,10 +140,9 @@ static int __devexit gen_74x164_remove(struct spi_device *spi)
 	dev_set_drvdata(&spi->dev, NULL);
 
 	ret = gpiochip_remove(&chip->gpio_chip);
-	if (!ret) {
+	if (!ret)
 		mutex_destroy(&chip->lock);
-		kfree(chip);
-	} else
+	else
 		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
 				ret);
 
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH 2/8 gpio: 74x164: Use devm_kzalloc

Quoted 1 line · On Wednesday 05 September 2012 10:40:51 Maxime Ripard wrote:

drivers/gpio/gpio-74x164.c static int __devinit gen_74x164_probe(struct spi_device

Quoted 9 lines
---
 drivers/gpio/gpio-74x164.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/gpio/gpio-74x164.c +0 -0
index 2975036..604b998 100644
@@ -90,7 +90,7 @@ static int __devinit gen_74x164_probe(struct spi_device 

*spi)

drivers/gpio/gpio-74x164.c static int __devinit gen_74x164_probe(struct spi_device

Quoted 9 lines
drivers/gpio/gpio-74x164.c +1 -1
 	if (ret < 0)
 		return ret;
 
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	chip = devm_kzalloc(&spi->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
@@ -125,7 +125,6 @@ static int __devinit gen_74x164_probe(struct spi_device 

*spi)

drivers/gpio/gpio-74x164.c static int __devexit gen_74x164_remove(struct

Quoted 8 lines
drivers/gpio/gpio-74x164.c +0 -1
 exit_destroy:
 	dev_set_drvdata(&spi->dev, NULL);
 	mutex_destroy(&chip->lock);
-	kfree(chip);
 	return ret;
 }
 
@@ -141,10 +140,9 @@ static int __devexit gen_74x164_remove(struct 

spi_device *spi)

Quoted 20 lines
drivers/gpio/gpio-74x164.c +2 -3
 	dev_set_drvdata(&spi->dev, NULL);
 
 	ret = gpiochip_remove(&chip->gpio_chip);
-	if (!ret) {
+	if (!ret)
 		mutex_destroy(&chip->lock);
-		kfree(chip);
-	} else
+	else
 		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
 				ret);
 
Signature · 7 lines
1.7.9.5


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#6 lore raw

PATCH 3/8 gpio: 74x164: Remove platform data and use dynamic gpio number assignment

In reply to Maxime Ripard
---
 drivers/gpio/gpio-74x164.c |   10 +---------
 include/linux/spi/74x164.h |    9 ---------
 2 files changed, 1 insertion(+), 18 deletions(-)
 delete mode 100644 include/linux/spi/74x164.h
drivers/gpio/gpio-74x164.c +1 -9
index 604b998..24cfe4c 100644
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/74x164.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -72,15 +71,8 @@ static int gen_74x164_direction_output(struct gpio_chip *gc,
 static int __devinit gen_74x164_probe(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
-	struct gen_74x164_chip_platform_data *pdata;
 	int ret;
 
-	pdata = spi->dev.platform_data;
-	if (!pdata || !pdata->base) {
-		dev_dbg(&spi->dev, "incorrect or missing platform data\n");
-		return -EINVAL;
-	}
-
 	/*
 	 * bits_per_word cannot be configured in platform data
 	 */
@@ -104,7 +96,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 	chip->gpio_chip.direction_output = gen_74x164_direction_output;
 	chip->gpio_chip.get = gen_74x164_get_value;
 	chip->gpio_chip.set = gen_74x164_set_value;
-	chip->gpio_chip.base = pdata->base;
+	chip->gpio_chip.base = -1;
 	chip->gpio_chip.ngpio = 8;
 	chip->gpio_chip.can_sleep = 1;
 	chip->gpio_chip.dev = &spi->dev;
include/linux/spi/74x164.h deleted +0 -9
deleted file mode 100644
index 0aa6acc..0000000
@@ -1,9 +0,0 @@
-#ifndef LINUX_SPI_74X164_H
-#define LINUX_SPI_74X164_H
-
-struct gen_74x164_chip_platform_data {
-	/* number assigned to the first GPIO */
-	unsigned	base;
-};
-
-#endif
Signature · 1 line
1.7.9.5
#7 lore raw

PATCH 3/8 gpio: 74x164: Remove platform data and use dynamic gpio number assignment

Quoted 1 line · On Wednesday 05 September 2012 10:40:52 Maxime Ripard wrote:

No, please don't do it that way, rather check if the platform_data pointer is null, and if it is, fall-back to dynamic gpio base assignment. There is a currently out of tree user of this for which it matters to be able to set a specific gpio base numbering.

drivers/gpio/gpio-74x164.c static int gen_74x164_direction_output(struct gpio_chip

Quoted 19 lines
---
 drivers/gpio/gpio-74x164.c |   10 +---------
 include/linux/spi/74x164.h |    9 ---------
 2 files changed, 1 insertion(+), 18 deletions(-)
 delete mode 100644 include/linux/spi/74x164.h
drivers/gpio/gpio-74x164.c +0 -1
index 604b998..24cfe4c 100644
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/74x164.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -72,15 +71,8 @@ static int gen_74x164_direction_output(struct gpio_chip 

*gc,

drivers/gpio/gpio-74x164.c static int __devinit gen_74x164_probe(struct spi_device

Quoted 16 lines
drivers/gpio/gpio-74x164.c +0 -7
 static int __devinit gen_74x164_probe(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
-	struct gen_74x164_chip_platform_data *pdata;
 	int ret;
 
-	pdata = spi->dev.platform_data;
-	if (!pdata || !pdata->base) {
-		dev_dbg(&spi->dev, "incorrect or missing platform data\n");
-		return -EINVAL;
-	}
-
 	/*
 	 * bits_per_word cannot be configured in platform data
 	 */
@@ -104,7 +96,7 @@ static int __devinit gen_74x164_probe(struct spi_device 

*spi)

Quoted 31 lines
drivers/gpio/gpio-74x164.c +1 -1
 	chip->gpio_chip.direction_output = gen_74x164_direction_output;
 	chip->gpio_chip.get = gen_74x164_get_value;
 	chip->gpio_chip.set = gen_74x164_set_value;
-	chip->gpio_chip.base = pdata->base;
+	chip->gpio_chip.base = -1;
 	chip->gpio_chip.ngpio = 8;
 	chip->gpio_chip.can_sleep = 1;
 	chip->gpio_chip.dev = &spi->dev;
include/linux/spi/74x164.h deleted +0 -9
deleted file mode 100644
index 0aa6acc..0000000
@@ -1,9 +0,0 @@
-#ifndef LINUX_SPI_74X164_H
-#define LINUX_SPI_74X164_H
-
-struct gen_74x164_chip_platform_data {
-	/* number assigned to the first GPIO */
-	unsigned	base;
-};
-
-#endif
Signature · 7 lines
1.7.9.5


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#8 lore raw

PATCH 3/8 gpio: 74x164: Remove platform data and use dynamic gpio number assignment

Le Wed, 05 Sep 2012 10:48:14 +0200,
Florian Fainelli <[email protected]> a ?crit :

Quoted 7 lines · On Wednesday 05 September 2012 10:40:52 Maxime Ripard wrote:
Quoted 1 line

No, please don't do it that way, rather check if the platform_data pointer is null, and if it is, fall-back to dynamic gpio base assignment. There is a currently out of tree user of this for which it matters to be able to set a specific gpio base numbering.

Do we care about out of tree users?

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#9 lore raw

PATCH 3/8 gpio: 74x164: Remove platform data and use dynamic gpio number assignment

In reply to Maxime Ripard

Le Wed, 5 Sep 2012 10:40:52 +0200,
Maxime Ripard <[email protected]> a ?crit :

Quoted 1 line

You should probably explicitly mention that the platform_data thing is removed because it has no users in-tree.

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#10 lore raw

PATCH 4/8 gpio: 74x164: Add device tree support

In reply to Maxime Ripard
---
 drivers/gpio/gpio-74x164.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/gpio/gpio-74x164.c +7 -0
index 24cfe4c..613067c 100644
@@ -141,10 +141,17 @@ static int __devexit gen_74x164_remove(struct spi_device *spi)
 	return ret;
 }
 
+static const struct of_device_id gen_74x164_dt_ids[] = {
+	{ .compatible = "fairchild,74hc595" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids);
+
 static struct spi_driver gen_74x164_driver = {
 	.driver = {
 		.name		= "74x164",
 		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(gen_74x164_dt_ids),
 	},
 	.probe		= gen_74x164_probe,
 	.remove		= __devexit_p(gen_74x164_remove),
Signature · 1 line
1.7.9.5
#11 lore raw

PATCH 4/8 gpio: 74x164: Add device tree support

Quoted 1 line · On Wednesday 05 September 2012 10:40:53 Maxime Ripard wrote:

drivers/gpio/gpio-74x164.c static int __devexit gen_74x164_remove(struct

Quoted 9 lines
---
 drivers/gpio/gpio-74x164.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/gpio/gpio-74x164.c +0 -0
index 24cfe4c..613067c 100644
@@ -141,10 +141,17 @@ static int __devexit gen_74x164_remove(struct 

spi_device *spi)

Quoted 25 lines
drivers/gpio/gpio-74x164.c +7 -0
 	return ret;
 }
 
+static const struct of_device_id gen_74x164_dt_ids[] = {
+	{ .compatible = "fairchild,74hc595" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids);
+
 static struct spi_driver gen_74x164_driver = {
 	.driver = {
 		.name		= "74x164",
 		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(gen_74x164_dt_ids),
 	},
 	.probe		= gen_74x164_probe,
 	.remove		= __devexit_p(gen_74x164_remove),
Signature · 7 lines
1.7.9.5


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#14 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

In reply to Maxime Ripard

The shift registers have an output that, when enabled, propagates the values of its internal register to the pins. Make use of this pin through the output-latch-gpio dt property.

---
 drivers/gpio/gpio-74x164.c |   32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)
drivers/gpio/gpio-74x164.c +31 -1
index 613067c..ff8d3d8 100644
@@ -13,6 +13,7 @@
 #include <linux/mutex.h>
 #include <linux/spi/spi.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
@@ -21,6 +22,7 @@ struct gen_74x164_chip {
 	struct gpio_chip	gpio_chip;
 	struct mutex		lock;
 	u8			port_config;
+	int			chip_select;
 };
 
 static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
@@ -30,8 +32,14 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
 
 static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
 {
-	return spi_write(chip->spi,
+	int ret;
+
+	gpio_set_value(chip->chip_select, 0);
+	ret = spi_write(chip->spi,
 			 &chip->port_config, sizeof(chip->port_config));
+	gpio_set_value(chip->chip_select, 1);
+
+	return ret;
 }
 
 static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
@@ -73,6 +81,11 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 	struct gen_74x164_chip *chip;
 	int ret;
 
+	if (!spi->dev.of_node) {
+		dev_err(&spi->dev, "No device tree data available.\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * bits_per_word cannot be configured in platform data
 	 */
@@ -102,6 +115,23 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 	chip->gpio_chip.dev = &spi->dev;
 	chip->gpio_chip.owner = THIS_MODULE;
 
+	chip->chip_select = of_get_named_gpio(spi->dev.of_node, "output-latch-gpio", 0);
+	if (gpio_is_valid(chip->chip_select)) {
+		int flags = GPIOF_OUT_INIT_HIGH;
+		if (of_get_property(spi->dev.of_node, "latch-active-low", NULL))
+			flags = GPIOF_OUT_INIT_LOW;
+		ret = devm_gpio_request_one(&spi->dev, chip->chip_select,
+					    flags, "output-latch");
+		if (ret) {
+			dev_err(&spi->dev,
+				"failed to request gpio %d: %d\n",
+				chip->chip_select, ret);
+			goto exit_destroy;
+		}
+	}
+
+	gpio_set_value(chip->chip_select, 1);
+
 	ret = __gen_74x164_write_config(chip);
 	if (ret) {
 		dev_err(&spi->dev, "Failed writing: %d\n", ret);
Signature · 1 line
1.7.9.5
#15 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Le Wed, 5 Sep 2012 10:40:54 +0200,
Maxime Ripard <[email protected]> a ?crit :

Quoted 5 lines

The shift registers have an output that, when enabled, propagates the values of its internal register to the pins. Make use of this pin through the output-latch-gpio dt property.

Well, thinking more about this, and reviewing the i.MX 28 datasheet a bit more thoroughly, I don't think you need this GPIO thing. It is an active-low pin that should be kept low during the entire duration of the transfer, which basically is a chip select. And in turns out that the CFA10049 board uses pins that can be controlled as chip selects directly by the SPI controller, so you should rather use this rather than introduce a specially handled GPIO. This needs testing, but I don't see why it wouldn't work.

Best regards,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#16 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Hi Thomas,

Le Wed, 5 Sep 2012 11:20:12 +0200,
Thomas Petazzoni <[email protected]> a ?crit :

Quoted 9 lines

Le Wed, 5 Sep 2012 10:40:54 +0200,
Maxime Ripard <[email protected]> a ?crit :

Quoted 5 lines

The shift registers have an output that, when enabled, propagates the values of its internal register to the pins. Make use of this pin through the output-latch-gpio dt property.

Quoted 9 lines

Well, thinking more about this, and reviewing the i.MX 28 datasheet a bit more thoroughly, I don't think you need this GPIO thing. It is an active-low pin that should be kept low during the entire duration of the transfer, which basically is a chip select. And in turns out that the CFA10049 board uses pins that can be controlled as chip selects directly by the SPI controller, so you should rather use this rather than introduce a specially handled GPIO. This needs testing, but I don't see why it wouldn't work.

are you talking of the /OE pin of the 74HC595 ?

Eric

#17 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Le Wed, 5 Sep 2012 11:46:45 +0200,
Eric B?nard <[email protected]> a ?crit :

Quoted 10 lines
Quoted 9 lines

Well, thinking more about this, and reviewing the i.MX 28 datasheet a bit more thoroughly, I don't think you need this GPIO thing. It is an active-low pin that should be kept low during the entire duration of the transfer, which basically is a chip select. And in turns out that the CFA10049 board uses pins that can be controlled as chip selects directly by the SPI controller, so you should rather use this rather than introduce a specially handled GPIO. This needs testing, but I don't see why it wouldn't work.

are you talking of the /OE pin of the 74HC595 ?

No. Our chip select lines are connected to the STCP pin. It is technically not a chip select, but a low-to-high transition on this pin triggers the apparition on the output pins of the 74HC595 of the contents of the storage register. So, doing a high-to-low transition before the SPI transfer, and then a low-to-high transition after the SPI transfer will actually do what we want. But maybe this is an abuse of the chip select concept, I don't know.

I don't think the /OE pin can be used as a chip select, because when it is high, the state of the output pins is not maintained to their previous state: the pins are turned into the high impedance state. If used as a chip select, it would mean that the value of the output pins transition from their old state to high impedance at the beginning of the transfer, and then from the high impedance to their new state at the end of the transfer. And of course, this signal is inverted compared to a normal chip select.

Note that I may be completely wrong, I'm a software guy, not a hardware one :)

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#18 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Hi,

Le Wed, 5 Sep 2012 12:09:06 +0200,
Thomas Petazzoni <[email protected]> a ?crit :

Quoted 7 lines

I don't think the /OE pin can be used as a chip select, because when it is high, the state of the output pins is not maintained to their previous state: the pins are turned into the high impedance state. If used as a chip select, it would mean that the value of the output pins transition from their old state to high impedance at the beginning of the transfer, and then from the high impedance to their new state at the end of the transfer.

OK that's exactly what I was thinking to ;-)

Quoted 1 line

And of course, this signal is inverted compared to a normal chip select.

polarity of the chip select can vary (mc13xxx-spi has an active high CS for example).

Eric

#19 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Le Wed, 5 Sep 2012 12:26:52 +0200,
Eric B?nard <[email protected]> a ?crit :

Quoted 11 lines

Le Wed, 5 Sep 2012 12:09:06 +0200,
Thomas Petazzoni <[email protected]> a ?crit :

Quoted 7 lines

I don't think the /OE pin can be used as a chip select, because when it is high, the state of the output pins is not maintained to their previous state: the pins are turned into the high impedance state. If used as a chip select, it would mean that the value of the output pins transition from their old state to high impedance at the beginning of the transfer, and then from the high impedance to their new state at the end of the transfer.

OK that's exactly what I was thinking to ;-)

Good. So, do you think it's reasonable to use the STCP as a chip-select for this device?

Quoted 4 lines
Quoted 1 line

And of course, this signal is inverted compared to a normal chip select.

polarity of the chip select can vary (mc13xxx-spi has an active high CS for example).

Sure, but I guess it depends on capabilities of the SPI controller in your SoC. I haven't seen a way of configuring the polarity of the chip selects in the i.MX28 SPI controller, but maybe I've missed it. Anyway, /OE isn't usable as a chip-select, so we don't care.

Best regards,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#20 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Le Wed, 5 Sep 2012 13:56:46 +0200,
Thomas Petazzoni <[email protected]> a ?crit :

Quoted 13 lines

Le Wed, 5 Sep 2012 12:26:52 +0200,
Eric B?nard <[email protected]> a ?crit :

Quoted 10 lines

Le Wed, 5 Sep 2012 12:09:06 +0200,
Thomas Petazzoni <[email protected]> a ?crit :

Quoted 7 lines

I don't think the /OE pin can be used as a chip select, because when it is high, the state of the output pins is not maintained to their previous state: the pins are turned into the high impedance state. If used as a chip select, it would mean that the value of the output pins transition from their old state to high impedance at the beginning of the transfer, and then from the high impedance to their new state at the end of the transfer.

Quoted 5 lines
Quoted 1 line

OK that's exactly what I was thinking to ;-)

Good. So, do you think it's reasonable to use the STCP as a chip-select for this device?

in your case maybe but that really depends on how the chip is wired to the CPU so I'm not sure that can be a generic choice.

Quoted 10 lines
Quoted 4 lines
Quoted 1 line

And of course, this signal is inverted compared to a normal chip select.

polarity of the chip select can vary (mc13xxx-spi has an active high CS for example).

Sure, but I guess it depends on capabilities of the SPI controller in your SoC. I haven't seen a way of configuring the polarity of the chip selects in the i.MX28 SPI controller, but maybe I've missed it. Anyway, /OE isn't usable as a chip-select, so we don't care.

that's a reason why the chip select can be a simple gpio (even if it's wired on a SPI chip select capable pin)

Eric

#21 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Le Wed, 5 Sep 2012 14:22:44 +0200,
Eric B?nard <[email protected]> a ?crit :

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

OK that's exactly what I was thinking to ;-)

Good. So, do you think it's reasonable to use the STCP as a chip-select for this device?

in your case maybe but that really depends on how the chip is wired to the CPU so I'm not sure that can be a generic choice.

I'm not sure to see how this chip could be wired differently to the CPU. The CPU must do a low-to-high transition on STCP to get the values out from the internal register.

So, in other words, we don't know how to choose between:

*) Keep the current solution Maxime has implemented, where we have a
specific latch GPIO property in the Device Tree for this 74HC595, and the 74HC595 driver is responsible for toggling this GPIO when needed.

*) Use the internal SPI controller logic to control this pin as a
chip-select, and therefore get rid of Maxime's code with the specific latch GPIO property in the Device Tree.

Thoughts?

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#22 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Le Wed, 5 Sep 2012 14:29:52 +0200,
Thomas Petazzoni <[email protected]> a ?crit :

Quoted 17 lines

Le Wed, 5 Sep 2012 14:22:44 +0200,
Eric B?nard <[email protected]> a ?crit :

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

OK that's exactly what I was thinking to ;-)

Good. So, do you think it's reasonable to use the STCP as a chip-select for this device?

in your case maybe but that really depends on how the chip is wired to the CPU so I'm not sure that can be a generic choice.

I'm not sure to see how this chip could be wired differently to the CPU. The CPU must do a low-to-high transition on STCP to get the values out from the internal register.

So, in other words, we don't know how to choose between:

Quoted 9 lines

*) Keep the current solution Maxime has implemented, where we have a
specific latch GPIO property in the Device Tree for this 74HC595, and the 74HC595 driver is responsible for toggling this GPIO when needed.

*) Use the internal SPI controller logic to control this pin as a
chip-select, and therefore get rid of Maxime's code with the specific latch GPIO property in the Device Tree.

daisy chaining won't work in the second case (I may be wrong but IIRC the chip select will toggle at each spi_write) unless you configure the spi controller to send a 8x(number of 74HC595) bits word :

 	gpio_set_value(chip->chip_select, 0);
	for (i = chip->registers - 1; i >= 0; i--) {
		ret = spi_write(chip->spi,
				chip->buffer + i, sizeof(u8));
		if (ret)
			return ret;
	}

gpio_set_value(chip->chip_select, 1);

Eric

#23 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Le 05/09/2012 14:54, Eric B?nard a ?crit :

Quoted 41 lines

Le Wed, 5 Sep 2012 14:29:52 +0200,
Thomas Petazzoni <[email protected]> a ?crit :

Quoted 17 lines

Le Wed, 5 Sep 2012 14:22:44 +0200,
Eric B?nard <[email protected]> a ?crit :

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

OK that's exactly what I was thinking to ;-)

Good. So, do you think it's reasonable to use the STCP as a chip-select for this device?

in your case maybe but that really depends on how the chip is wired to the CPU so I'm not sure that can be a generic choice.

I'm not sure to see how this chip could be wired differently to the CPU. The CPU must do a low-to-high transition on STCP to get the values out from the internal register.

So, in other words, we don't know how to choose between:

Quoted 9 lines

*) Keep the current solution Maxime has implemented, where we have a
specific latch GPIO property in the Device Tree for this 74HC595, and the 74HC595 driver is responsible for toggling this GPIO when needed.

*) Use the internal SPI controller logic to control this pin as a
chip-select, and therefore get rid of Maxime's code with the specific latch GPIO property in the Device Tree.

daisy chaining won't work in the second case (I may be wrong but IIRC the chip select will toggle at each spi_write) unless you configure the spi controller to send a 8x(number of 74HC595) bits word :

 	gpio_set_value(chip->chip_select, 0);
	for (i = chip->registers - 1; i >= 0; i--) {
		ret = spi_write(chip->spi,
				chip->buffer + i, sizeof(u8));
		if (ret)
			return ret;
	}
Quoted 1 line

gpio_set_value(chip->chip_select, 1);

And what about using the spi_message structure and one single spi_sync instead of several spi_write ? Would that work in our case ?

Signature · 4 lines
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#24 lore raw

PATCH 5/8 gpio: 74x164: Add output pin support

Le Wed, 05 Sep 2012 15:02:09 +0200,
Maxime Ripard <[email protected]> a ?crit :

Quoted 3 lines

And what about using the spi_message structure and one single spi_sync instead of several spi_write ? Would that work in our case ?

if you are sure that the controler will keep the chip select low during the whole transfer that should work (that means on some spi controllers you will have to configure the chip select as a plain gpio depending on the number of buffer you chain).

Eric

#25 lore raw

PATCH 6/8 gpio: 74x164: Add support for daisy-chaining

In reply to Maxime Ripard

These types of shift registers can be daisy-chained, each new value sent while the output pin is kept low will make the previous value shift to the next register in the chain.

This patch add support for chained shift registers, through the registers-number dt property.

---
 drivers/gpio/gpio-74x164.c |   42 +++++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 9 deletions(-)
drivers/gpio/gpio-74x164.c +33 -9
index ff8d3d8..79b3e10 100644
@@ -19,9 +19,10 @@
 
 struct gen_74x164_chip {
 	struct spi_device	*spi;
+	u8			*buffer;
 	struct gpio_chip	gpio_chip;
 	struct mutex		lock;
-	u8			port_config;
+	u32			registers;
 	int			chip_select;
 };
 
@@ -32,23 +33,31 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
 
 static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
 {
-	int ret;
+	int i, ret;
 
 	gpio_set_value(chip->chip_select, 0);
-	ret = spi_write(chip->spi,
-			 &chip->port_config, sizeof(chip->port_config));
+
+	for (i = chip->registers - 1; i >= 0; i--) {
+		ret = spi_write(chip->spi,
+				chip->buffer + i, sizeof(u8));
+		if (ret)
+			return ret;
+	}
+
 	gpio_set_value(chip->chip_select, 1);
 
-	return ret;
+	return 0;
 }
 
 static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
 {
 	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+	u8 bank = offset / 8;
+	u8 pin = offset % 8;
 	int ret;
 
 	mutex_lock(&chip->lock);
-	ret = (chip->port_config >> offset) & 0x1;
+	ret = (*(chip->buffer + bank) >> pin) & 0x1;
 	mutex_unlock(&chip->lock);
 
 	return ret;
@@ -58,12 +67,14 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
 		unsigned offset, int val)
 {
 	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+	u8 bank = offset / 8;
+	u8 pin = offset % 8;
 
 	mutex_lock(&chip->lock);
 	if (val)
-		chip->port_config |= (1 << offset);
+		*(chip->buffer + bank) |= (1 << pin);
 	else
-		chip->port_config &= ~(1 << offset);
+		*(chip->buffer + bank) &= ~(1 << pin);
 
 	__gen_74x164_write_config(chip);
 	mutex_unlock(&chip->lock);
@@ -110,7 +121,20 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 	chip->gpio_chip.get = gen_74x164_get_value;
 	chip->gpio_chip.set = gen_74x164_set_value;
 	chip->gpio_chip.base = -1;
-	chip->gpio_chip.ngpio = 8;
+
+	if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) {
+		dev_err(&spi->dev, "Missing registers-number property in the DT.\n");
+		ret = -EINVAL;
+		goto exit_destroy;
+	}
+
+	chip->gpio_chip.ngpio = 8 * chip->registers;
+	chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
+	if (!chip->buffer) {
+		ret = -ENOMEM;
+		goto exit_destroy;
+	}
+
 	chip->gpio_chip.can_sleep = 1;
 	chip->gpio_chip.dev = &spi->dev;
 	chip->gpio_chip.owner = THIS_MODULE;
Signature · 1 line
1.7.9.5
#26 lore raw

PATCH 6/8 gpio: 74x164: Add support for daisy-chaining

Le Wed, 5 Sep 2012 10:40:55 +0200,
Maxime Ripard <[email protected]> a ?crit :

drivers/gpio/gpio-74x164.c static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) · line 45

Quoted 6 lines
drivers/gpio/gpio-74x164.c +6 -0
+	for (i = chip->registers - 1; i >= 0; i--) {
+		ret = spi_write(chip->spi,
+				chip->buffer + i, sizeof(u8));
+		if (ret)
+			return ret;
+	}

I think you should have a comment on top of this loop to explain why this loop is done in the reverse direction. Of course, I personally know why, but the reviewers/readers may not.

drivers/gpio/gpio-74x164.c static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) · line 60

Quoted 10 lines

static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) {

drivers/gpio/gpio-74x164.c +3 -1
 	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+	u8 bank = offset / 8;
+	u8 pin = offset % 8;
 	int ret;
 
 	mutex_lock(&chip->lock);
-	ret = (chip->port_config >> offset) & 0x1;
+	ret = (*(chip->buffer + bank) >> pin) & 0x1;
	ret = (chip->buffer[bank] >> pin) & 0x1;

drivers/gpio/gpio-74x164.c static void gen_74x164_set_value(struct gpio_chip *gc, · line 75

Quoted 9 lines

{

drivers/gpio/gpio-74x164.c +3 -1
 	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+	u8 bank = offset / 8;
+	u8 pin = offset % 8;
 
 	mutex_lock(&chip->lock);
 	if (val)
-		chip->port_config |= (1 << offset);
+		*(chip->buffer + bank) |= (1 << pin);
		chip->buffer[bank] |= (1 << pin)

drivers/gpio/gpio-74x164.c static void gen_74x164_set_value(struct gpio_chip *gc, · line 77

Quoted 3 lines
drivers/gpio/gpio-74x164.c +1 -1
 	else
-		chip->port_config &= ~(1 << offset);
+		*(chip->buffer + bank) &= ~(1 << pin);
		chip->buffer[bank] &= ~(1 << pin)

drivers/gpio/gpio-74x164.c static int __devinit gen_74x164_probe(struct spi_device *spi) · line 129

Quoted 5 lines
drivers/gpio/gpio-74x164.c +5 -0
+	if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) {
+		dev_err(&spi->dev, "Missing registers-number property in the DT.\n");
+		ret = -EINVAL;
+		goto exit_destroy;
+	}

I'm wondering whether this shouldn't be named daisy-chain-length or something like that, but I'm not sure.

drivers/gpio/gpio-74x164.c static int __devinit gen_74x164_probe(struct spi_device *spi) · line 131

Quoted 1 line
drivers/gpio/gpio-74x164.c +1 -0
+	chip->gpio_chip.ngpio = 8 * chip->registers;

Maybe make "8" a #define so that it becomes self-explanatory what this 8 is?

Best regards,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#27 lore raw

PATCH 7/8 gpio: 74x164: dts: Add documentation for the dt binding

In reply to Maxime Ripard
---
 .../devicetree/bindings/gpio/gpio-74x164.txt       |   26 ++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-74x164.txt
Documentation/devicetree/bindings/gpio/gpio-74x164.txt new file +26 -0
new file mode 100644
index 0000000..e2a40a5
@@ -0,0 +1,26 @@
+* Generic 8-bits shift register GPIO driver
+
+Required properties:
+- compatible : Should be "fairchild,74hc595"
+- reg : chip select number
+- gpio-controller : Marks the device node as a gpio controller.
+- #gpio-cells : Should be two.  The first cell is the pin number and
+  the second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
+- register-number: Number of daisy-chained shift registers
+- output-latch-gpio: GPIO connected to the output pin of the registers
+
+Optional properties:
+- latch-active-low: If the output pin is active low
+
+Example:
+
+gpio5: gpio5 at 0 {
+	compatible = "fairchild,74hc595";
+	gpio-controller;
+	#gpio-cells = <2>;
+	registers-number = <4>;
+	output-latch-gpio = <&gpio0 26 0>;
+	spi-max-frequency = <100000>;
+};
Signature · 1 line
1.7.9.5
#28 lore raw

PATCH 8/8 ARM: dts: cfa10049: Add the 74HC595 gpio expanders

In reply to Maxime Ripard
---
 arch/arm/boot/dts/imx28-cfa10049.dts |   20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
arch/arm/boot/dts/imx28-cfa10049.dts +20 -0
index 1f7fa50..820153a 100644
@@ -39,6 +39,26 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&spi3_pins_cfa10049>;
 				status = "okay";
+
+				gpio5: gpio5 at 0 {
+					compatible = "fairchild,74hc595";
+					gpio-controller;
+					#gpio-cells = <2>;
+					reg = <0>;
+					registers-number = <4>;
+					output-latch-gpio = <&gpio0 26 0>;
+					spi-max-frequency = <100000>;
+				};
+
+				gpio6: gpio6 at 1 {
+					compatible = "fairchild,74hc595";
+					gpio-controller;
+					#gpio-cells = <2>;
+					reg = <1>;
+					registers-number = <2>;
+					output-latch-gpio = <&gpio0 17 0>;
+					spi-max-frequency = <100000>;
+				};
 			};
 		};
 
Signature · 1 line
1.7.9.5
#29 lore raw

PATCH 1/8 gpio: 74x164: Use module_spi_driver boiler plate function

In reply to Maxime Ripard
Quoted 1 line · On Wednesday 05 September 2012 10:40:50 Maxime Ripard wrote:
Quoted 36 lines
---
 drivers/gpio/gpio-74x164.c |   13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)
drivers/gpio/gpio-74x164.c +1 -12
index a31ad6f..2975036 100644
@@ -159,18 +159,7 @@ static struct spi_driver gen_74x164_driver = {
 	.probe		= gen_74x164_probe,
 	.remove		= __devexit_p(gen_74x164_remove),
 };
-
-static int __init gen_74x164_init(void)
-{
-	return spi_register_driver(&gen_74x164_driver);
-}
-subsys_initcall(gen_74x164_init);
-
-static void __exit gen_74x164_exit(void)
-{
-	spi_unregister_driver(&gen_74x164_driver);
-}
-module_exit(gen_74x164_exit);
+module_spi_driver(gen_74x164_driver);
 
 MODULE_AUTHOR("Gabor Juhos <[email protected]>");
 MODULE_AUTHOR("Miguel Gaio <[email protected]>");
Signature · 7 lines
1.7.9.5


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#30 lore raw

PATCH 1/8 gpio: 74x164: Use module_spi_driver boiler plate function

In reply to Maxime Ripard

Le Wed, 5 Sep 2012 10:40:50 +0200,
Maxime Ripard <[email protected]> a ?crit :

Quoted 1 line
Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#32 lore raw

PATCH 1/8 gpio: 74x164: Use module_spi_driver boiler plate function

Hi Linus,

Le 06/09/2012 09:21, Linus Walleij a ?crit :

Quoted 8 lines
Quoted 4 lines · Maxime Ripard
---
 drivers/gpio/gpio-74x164.c |   13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)
Quoted 4 lines

I guess all of these will go through your kernel tree? Tell me if you want me to apply these to my GPIO tree.

Since I don't have any kernel tree, I guess you can apply them in your tree :)

Signature · 4 lines
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#33 lore raw

PATCH 1/8 gpio: 74x164: Use module_spi_driver boiler plate function

Quoted 10 lines · Maxime Ripard

Hi Linus,
Le 06/09/2012 09:21, Linus Walleij a ?crit :

Quoted 5 lines

I guess all of these will go through your kernel tree? Tell me if you want me to apply these to my GPIO tree.

Since I don't have any kernel tree, I guess you can apply them in your tree :)

I was more thinking if the Free Electrons people were doing composite pull requests to ARM SoC. Oh well, nevermind, I'll take them.

Applied!

Linus Walleij