All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] devicetree: add a binding for GPIOs going though a level shifter
@ 2014-11-24 14:01 Alban Bedel
  2014-11-24 14:01 ` [PATCH 2/2] gpio: add a driver for GPIOs going through " Alban Bedel
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Alban Bedel @ 2014-11-24 14:01 UTC (permalink / raw)
  To: linux-gpio
  Cc: linux-kernel, devicetree, Alban Bedel, Grant Likely,
	Alexandre Courbot, Linus Walleij, Kumar Gala, Ian Campbell,
	Mark Rutland, Pawel Moll, Rob Herring

Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
---
 .../devicetree/bindings/gpio/gpio-level-shifter.txt       | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt

diff --git a/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt b/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt
new file mode 100644
index 0000000..e108c43
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt
@@ -0,0 +1,15 @@
+GPIO level shifter
+
+This binding allow supporting GPIOs going though a level shifter.
+
+Required properties:
+- compatible : should be "gpio-level-shifter"
+- data-gpios : list of the data GPIO phandles
+- #gpio-cells : should be 2
+- gpio-controller : marks the device node as a GPIO controller
+
+Optional properties:
+- enable-gpio : phandle of the GPIO that control the level shifter enable pin
+- direction-gpio : phandle of the GPIO that control the level shifter direction
+- vcca-supply : phandle of the regulator for side A of the level shifter
+- vccb-supply : phandle of the regulator for side B of the level shifter
-- 
2.1.3


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

* [PATCH 2/2] gpio: add a driver for GPIOs going through a level shifter
  2014-11-24 14:01 [PATCH 1/2] devicetree: add a binding for GPIOs going though a level shifter Alban Bedel
@ 2014-11-24 14:01 ` Alban Bedel
  2014-11-28 13:37   ` Linus Walleij
  2014-11-24 21:01 ` [PATCH 1/2] devicetree: add a binding for GPIOs going though " Rob Herring
  2014-11-28 13:39 ` Linus Walleij
  2 siblings, 1 reply; 5+ messages in thread
From: Alban Bedel @ 2014-11-24 14:01 UTC (permalink / raw)
  To: linux-gpio
  Cc: linux-kernel, devicetree, Alban Bedel, Grant Likely,
	Alexandre Courbot, Linus Walleij, Kumar Gala, Ian Campbell,
	Mark Rutland, Pawel Moll, Rob Herring

This driver support setting the level shifter direction and/or enable
as needed.

Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
---
 drivers/gpio/Kconfig              |   6 +
 drivers/gpio/Makefile             |   1 +
 drivers/gpio/gpio-level-shifter.c | 248 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 255 insertions(+)
 create mode 100644 drivers/gpio/gpio-level-shifter.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 0959ca9..bb00cc5 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -181,6 +181,12 @@ config GPIO_F7188X
 	  To compile this driver as a module, choose M here: the module will
 	  be called f7188x-gpio.
 
+config GPIO_LEVEL_SHIFTER
+	tristate "Level shifter GPIO support"
+	help
+	  This enables support for GPIOs that are going through a simple level
+	  shifter.
+
 config GPIO_MOXART
 	bool "MOXART GPIO support"
 	depends on ARCH_MOXART
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index e5d346c..e9adc12 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
 obj-$(CONFIG_GPIO_KEMPLD)	+= gpio-kempld.o
 obj-$(CONFIG_ARCH_KS8695)	+= gpio-ks8695.o
 obj-$(CONFIG_GPIO_INTEL_MID)	+= gpio-intel-mid.o
+obj-$(CONFIG_GPIO_LEVEL_SHIFTER)+= gpio-level-shifter.o
 obj-$(CONFIG_GPIO_LP3943)	+= gpio-lp3943.o
 obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o
 obj-$(CONFIG_GPIO_LYNXPOINT)	+= gpio-lynxpoint.o
diff --git a/drivers/gpio/gpio-level-shifter.c b/drivers/gpio/gpio-level-shifter.c
new file mode 100644
index 0000000..1760048
--- /dev/null
+++ b/drivers/gpio/gpio-level-shifter.c
@@ -0,0 +1,248 @@
+/*
+ * Driver for GPIOs that are going through a level shifter.
+ *
+ * Copyright (C) 2014 - Alban Bedel
+ *
+ * Author: Alban Bedel <alban.bedel@avionic-design.de>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#define MAX_DATA_GPIO 32
+
+enum level_shifter_direction {
+	DIRECTION_NONE,
+	DIRECTION_INPUT,
+	DIRECTION_OUTPUT
+};
+
+struct level_shifter_gpio {
+	struct gpio_chip gc;
+
+	spinlock_t lock;
+	int num_requested;
+
+	struct gpio_desc *data_gpio[MAX_DATA_GPIO];
+	struct gpio_desc *enable_gpio;
+	struct gpio_desc *direction_gpio;
+	enum level_shifter_direction direction;
+
+	struct regulator *vcc_a;
+	struct regulator *vcc_b;
+};
+
+#define to_level_shifter_gpio(c) \
+	container_of(c, struct level_shifter_gpio, gc)
+
+int level_shifter_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct level_shifter_gpio *ls = to_level_shifter_gpio(chip);
+
+	spin_lock(&ls->lock);
+
+	if (ls->num_requested == 0 && ls->enable_gpio)
+		gpiod_set_value(ls->enable_gpio, 1);
+
+	ls->num_requested++;
+
+	spin_unlock(&ls->lock);
+
+	return 0;
+}
+
+void level_shifter_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct level_shifter_gpio *ls = to_level_shifter_gpio(chip);
+
+	spin_lock(&ls->lock);
+
+	ls->num_requested--;
+
+	if (ls->num_requested == 0) {
+		if (ls->enable_gpio)
+			gpiod_set_value(ls->enable_gpio, 0);
+		if (ls->direction_gpio)
+			ls->direction = DIRECTION_NONE;
+	}
+
+	spin_unlock(&ls->lock);
+}
+
+static void level_shifter_gpio_set(
+	struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct level_shifter_gpio *ls = to_level_shifter_gpio(chip);
+
+	gpiod_set_value(ls->data_gpio[offset], value);
+}
+
+static int level_shifter_gpio_direction_output(
+	struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct level_shifter_gpio *ls = to_level_shifter_gpio(chip);
+	int err;
+
+	spin_lock(&ls->lock);
+
+	/* Set the direction GPIO if needed */
+	if (ls->direction_gpio) {
+		/* We can't change the direction once set */
+		if (ls->direction == DIRECTION_INPUT) {
+			spin_unlock(&ls->lock);
+			return -EINVAL;
+		}
+		gpiod_set_value(ls->direction_gpio, 1);
+	}
+
+	err = gpiod_direction_output(ls->data_gpio[offset], value);
+
+	/* Save the direction if there was no error */
+	if (!err && ls->direction_gpio)
+		ls->direction = DIRECTION_OUTPUT;
+
+	spin_unlock(&ls->lock);
+
+	return err;
+}
+
+static int level_shifter_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct level_shifter_gpio *ls = to_level_shifter_gpio(chip);
+
+	return gpiod_get_value(ls->data_gpio[offset]);
+}
+
+static int level_shifter_gpio_direction_input(
+	struct gpio_chip *chip, unsigned offset)
+{
+	struct level_shifter_gpio *ls = to_level_shifter_gpio(chip);
+	int err;
+
+	spin_lock(&ls->lock);
+
+	/* Set the direction GPIO if needed */
+	if (ls->direction_gpio) {
+		/* We can't change the direction once set */
+		if (ls->direction == DIRECTION_OUTPUT) {
+			spin_unlock(&ls->lock);
+			return -EINVAL;
+		}
+		gpiod_set_value(ls->direction_gpio, 1);
+	}
+
+	err = gpiod_direction_input(ls->data_gpio[offset]);
+
+	/* Save the direction if there was no error */
+	if (!err && ls->direction_gpio)
+		ls->direction = DIRECTION_INPUT;
+
+	spin_unlock(&ls->lock);
+
+	return err;
+}
+
+static int level_shifter_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct level_shifter_gpio *ls;
+	struct gpio_desc *gpiod;
+	int err, i;
+
+	ls = devm_kzalloc(&pdev->dev, sizeof(*ls), GFP_KERNEL);
+	if (!ls)
+		return -ENOMEM;
+
+	spin_lock_init(&ls->lock);
+
+	if (np)
+		ls->gc.label = np->name;
+	else
+		ls->gc.label = "level-shifter-gpio";
+
+	ls->gc.of_node = pdev->dev.of_node;
+	ls->gc.base = -1;
+	ls->gc.request = level_shifter_gpio_request;
+	ls->gc.free = level_shifter_gpio_free;
+	ls->gc.set = level_shifter_gpio_set;
+	ls->gc.direction_output = level_shifter_gpio_direction_output;
+	ls->gc.get = level_shifter_gpio_get;
+	ls->gc.direction_input = level_shifter_gpio_direction_input;
+
+	for (i = 0; i < MAX_DATA_GPIO; i++) {
+		gpiod = devm_gpiod_get_index_optional(
+			&pdev->dev, "data", i, GPIOD_IN);
+		if (!gpiod)
+			continue;
+		if (IS_ERR(gpiod))
+			return PTR_ERR(gpiod);
+
+		ls->data_gpio[ls->gc.ngpio++] = gpiod;
+	}
+
+	ls->enable_gpio = devm_gpiod_get_optional(
+		&pdev->dev, "enable", GPIOD_OUT_LOW);
+	if (IS_ERR(ls->enable_gpio))
+		return PTR_ERR(ls->enable_gpio);
+
+	ls->direction_gpio = devm_gpiod_get_optional(
+		&pdev->dev, "direction", GPIOD_OUT_LOW);
+	if (IS_ERR(ls->direction_gpio))
+		return PTR_ERR(ls->direction_gpio);
+
+	ls->vcc_a = devm_regulator_get_optional(&pdev->dev, "vcca");
+	if (IS_ERR(ls->vcc_a) && PTR_ERR(ls->vcc_a) != -ENODEV)
+		return PTR_ERR(ls->vcc_a);
+	if (!IS_ERR(ls->vcc_a)) {
+		err = regulator_enable(ls->vcc_a);
+		if (err)
+			return err;
+	}
+
+	ls->vcc_b = devm_regulator_get_optional(&pdev->dev, "vccb");
+	if (IS_ERR(ls->vcc_b) && PTR_ERR(ls->vcc_b) != -ENODEV)
+		return PTR_ERR(ls->vcc_b);
+	if (!IS_ERR(ls->vcc_b)) {
+		err = regulator_enable(ls->vcc_b);
+		if (err)
+			return err;
+	}
+
+	err = gpiochip_add(&ls->gc);
+	if (err) {
+		if (!IS_ERR(ls->vcc_a))
+			regulator_disable(ls->vcc_a);
+		if (!IS_ERR(ls->vcc_b))
+			regulator_disable(ls->vcc_b);
+	}
+	return err;
+}
+
+static const struct of_device_id level_shifter_gpio_of_match[] = {
+	{ .compatible = "gpio-level-shifter"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, level_shifter_gpio_of_match);
+
+static struct platform_driver level_shifter_gpio_driver = {
+	.driver = {
+		.name = "level-shifter-gpio",
+		.owner = THIS_MODULE,
+		.of_match_table = level_shifter_gpio_of_match,
+	},
+	.probe = level_shifter_gpio_probe,
+};
+module_platform_driver(level_shifter_gpio_driver);
+
+MODULE_AUTHOR("Alban Bedel <alban.bedel@avionic-design.de>");
+MODULE_DESCRIPTION("Driver for GPIO going thru a level shifter");
+MODULE_LICENSE("GPL v2");
-- 
2.1.3

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

* Re: [PATCH 1/2] devicetree: add a binding for GPIOs going though a level shifter
  2014-11-24 14:01 [PATCH 1/2] devicetree: add a binding for GPIOs going though a level shifter Alban Bedel
  2014-11-24 14:01 ` [PATCH 2/2] gpio: add a driver for GPIOs going through " Alban Bedel
@ 2014-11-24 21:01 ` Rob Herring
  2014-11-28 13:39 ` Linus Walleij
  2 siblings, 0 replies; 5+ messages in thread
From: Rob Herring @ 2014-11-24 21:01 UTC (permalink / raw)
  To: Alban Bedel
  Cc: linux-gpio, linux-kernel, devicetree, Grant Likely,
	Alexandre Courbot, Linus Walleij, Kumar Gala, Ian Campbell,
	Mark Rutland, Pawel Moll, Rob Herring

On Mon, Nov 24, 2014 at 8:01 AM, Alban Bedel
<alban.bedel@avionic-design.de> wrote:
> Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
> ---
>  .../devicetree/bindings/gpio/gpio-level-shifter.txt       | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt
>
> diff --git a/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt b/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt
> new file mode 100644
> index 0000000..e108c43
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt
> @@ -0,0 +1,15 @@
> +GPIO level shifter
> +
> +This binding allow supporting GPIOs going though a level shifter.
> +
> +Required properties:
> +- compatible : should be "gpio-level-shifter"
> +- data-gpios : list of the data GPIO phandles
> +- #gpio-cells : should be 2
> +- gpio-controller : marks the device node as a GPIO controller
> +
> +Optional properties:
> +- enable-gpio : phandle of the GPIO that control the level shifter enable pin
> +- direction-gpio : phandle of the GPIO that control the level shifter direction

What if you had 2 level shifters with a common enable, but with
different directions? We'd have to support an ORing of the enable
state. That's largely a gpio subsystem problem I guess.

Otherwise, this looks pretty good to me:

Acked-by: Rob Herring <robh@kernel.org>

Rob

> +- vcca-supply : phandle of the regulator for side A of the level shifter
> +- vccb-supply : phandle of the regulator for side B of the level shifter
> --
> 2.1.3
>

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

* Re: [PATCH 2/2] gpio: add a driver for GPIOs going through a level shifter
  2014-11-24 14:01 ` [PATCH 2/2] gpio: add a driver for GPIOs going through " Alban Bedel
@ 2014-11-28 13:37   ` Linus Walleij
  0 siblings, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2014-11-28 13:37 UTC (permalink / raw)
  To: Alban Bedel
  Cc: linux-gpio, linux-kernel, devicetree, Grant Likely,
	Alexandre Courbot, Kumar Gala, Ian Campbell, Mark Rutland,
	Pawel Moll, Rob Herring

On Mon, Nov 24, 2014 at 3:01 PM, Alban Bedel
<alban.bedel@avionic-design.de> wrote:

> This driver support setting the level shifter direction and/or enable
> as needed.
>
> Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>

Very interesting patch!

I have some worries. What if the backing GPIO chip supports interrupts
on GPIO lines, and consumers do gpiod_get() from this level
shifter front-end, followed by gpio_to_irq()? Then the line will
not be converted to an IRQ properly.

In the device tree case I guess you can refer to the backing
GPIO chip with the interrupt property, but then you have to
coordinate setting the line as input both on this front-end and
on the back-end. Now the drivers won't properly enforce that.

So it would be much nicer if the level shifter front-end would
also propagate irqchip stuff to the back-end. I don't know if that
will be easy.

The second problem is that of handling a level shifter backed
by more than one GPIO chip, as mentioned by Rob for the other
patch. It's better if we store the backing GPIO chip on a per-line
basis. Make struct level_shifter_gpio contain a list of lines and
for each line have another struct that contain per-line data
like the gpiod for that line (so you can find the gpio_chip and
have it unique if need be).

Then I wonder if all level shifters are such that you set the direction
for all lines going in/out of it, or if there are level shifters where this
is controlled on a per-line basis.

Patch MAINTAINERS so that you are indicated as maintainer
of this driver.

Would you consider also maintaining
drivers/gpio/gpio-adnp.c?

> +config GPIO_LEVEL_SHIFTER
> +       tristate "Level shifter GPIO support"

depends on OF_GPIO or select OF_GPIO?
select REGULATOR?

(...)
> +#include <linux/module.h>
> +#include <linux/spinlock.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/regulator/consumer.h>

Thanks for using descriptors solely.

> +#define MAX_DATA_GPIO 32

Why? Use a list with dynamic allocation instead of such
arbitrary restrictions.

> +enum level_shifter_direction {
> +       DIRECTION_NONE,
> +       DIRECTION_INPUT,
> +       DIRECTION_OUTPUT
> +};
> +
> +struct level_shifter_gpio {
> +       struct gpio_chip gc;
> +
> +       spinlock_t lock;
> +       int num_requested;
> +
> +       struct gpio_desc *data_gpio[MAX_DATA_GPIO];
> +       struct gpio_desc *enable_gpio;
> +       struct gpio_desc *direction_gpio;
> +       enum level_shifter_direction direction;
> +
> +       struct regulator *vcc_a;
> +       struct regulator *vcc_b;

Is VCC_A and VCC_B really the right terminology?

I see this in some datasheets but the pinout seems top be
VCC and VDD, which one is it? Needs crystal clear documentation
anyways.

> +};

Add kerneldoc to this struct.

> +#define to_level_shifter_gpio(c) \
> +       container_of(c, struct level_shifter_gpio, gc)
> +
> +int level_shifter_gpio_request(struct gpio_chip *chip, unsigned offset)
> +{
> +       struct level_shifter_gpio *ls = to_level_shifter_gpio(chip);
> +
> +       spin_lock(&ls->lock);

Since the backend may be slow (e.g. on an I2C bus)
it is not wise to use a spinlock here.

Exactly what is it protecting really? I think you can just
remove it.

> +       if (ls->num_requested == 0 && ls->enable_gpio)
> +               gpiod_set_value(ls->enable_gpio, 1);
> +
> +       ls->num_requested++;

Instead of your own refence counting, use struct kref for
whatever it is you need to keep track of. It will handle
callbacks when references reach 0 etc.

<linux/kref.h> grep kernel for examples.

(...)
> +void level_shifter_gpio_free(struct gpio_chip *chip, unsigned offset)
> +{
> +       struct level_shifter_gpio *ls = to_level_shifter_gpio(chip);
> +
> +       spin_lock(&ls->lock);
> +
> +       ls->num_requested--;
> +
> +       if (ls->num_requested == 0) {
> +               if (ls->enable_gpio)
> +                       gpiod_set_value(ls->enable_gpio, 0);
> +               if (ls->direction_gpio)
> +                       ls->direction = DIRECTION_NONE;

Is that really true? Isn't it just keeping what it used to be?

DIRECTION_DONT_CARE seems more appropriate if you
use it like this.

(...)
> +static int level_shifter_gpio_probe(struct platform_device *pdev)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       struct level_shifter_gpio *ls;
> +       struct gpio_desc *gpiod;
> +       int err, i;
> +
> +       ls = devm_kzalloc(&pdev->dev, sizeof(*ls), GFP_KERNEL);
> +       if (!ls)
> +               return -ENOMEM;
> +
> +       spin_lock_init(&ls->lock);
> +
> +       if (np)
> +               ls->gc.label = np->name;
> +       else
> +               ls->gc.label = "level-shifter-gpio";
> +
> +       ls->gc.of_node = pdev->dev.of_node;
> +       ls->gc.base = -1;
> +       ls->gc.request = level_shifter_gpio_request;
> +       ls->gc.free = level_shifter_gpio_free;
> +       ls->gc.set = level_shifter_gpio_set;
> +       ls->gc.direction_output = level_shifter_gpio_direction_output;
> +       ls->gc.get = level_shifter_gpio_get;
> +       ls->gc.direction_input = level_shifter_gpio_direction_input;
> +
> +       for (i = 0; i < MAX_DATA_GPIO; i++) {
> +               gpiod = devm_gpiod_get_index_optional(
> +                       &pdev->dev, "data", i, GPIOD_IN);

Instead just keep getting indexes until we get
a -ENOENT and add dynamically to a gpiod list.

 +       ls->vcc_a = devm_regulator_get_optional(&pdev->dev, "vcca");
> +       if (IS_ERR(ls->vcc_a) && PTR_ERR(ls->vcc_a) != -ENODEV)
> +               return PTR_ERR(ls->vcc_a);
> +       if (!IS_ERR(ls->vcc_a)) {
> +               err = regulator_enable(ls->vcc_a);
> +               if (err)
> +                       return err;
> +       }
> +
> +       ls->vcc_b = devm_regulator_get_optional(&pdev->dev, "vccb");
> +       if (IS_ERR(ls->vcc_b) && PTR_ERR(ls->vcc_b) != -ENODEV)
> +               return PTR_ERR(ls->vcc_b);
> +       if (!IS_ERR(ls->vcc_b)) {
> +               err = regulator_enable(ls->vcc_b);
> +               if (err)
> +                       return err;
> +       }

Why are the regulators enabled even if the level shifter is not
in use?

Should these regulator_enable() calls be done at the same
place as the other enablement, when a GPIO is requested
and num_requested goes from 0->1?

Yours,
Linus Walleij

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

* Re: [PATCH 1/2] devicetree: add a binding for GPIOs going though a level shifter
  2014-11-24 14:01 [PATCH 1/2] devicetree: add a binding for GPIOs going though a level shifter Alban Bedel
  2014-11-24 14:01 ` [PATCH 2/2] gpio: add a driver for GPIOs going through " Alban Bedel
  2014-11-24 21:01 ` [PATCH 1/2] devicetree: add a binding for GPIOs going though " Rob Herring
@ 2014-11-28 13:39 ` Linus Walleij
  2 siblings, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2014-11-28 13:39 UTC (permalink / raw)
  To: Alban Bedel
  Cc: linux-gpio, linux-kernel, devicetree, Grant Likely,
	Alexandre Courbot, Kumar Gala, Ian Campbell, Mark Rutland,
	Pawel Moll, Rob Herring

On Mon, Nov 24, 2014 at 3:01 PM, Alban Bedel
<alban.bedel@avionic-design.de> wrote:

> Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
> ---
>  .../devicetree/bindings/gpio/gpio-level-shifter.txt       | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt
>
> diff --git a/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt b/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt
> new file mode 100644
> index 0000000..e108c43
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/gpio-level-shifter.txt
> @@ -0,0 +1,15 @@
> +GPIO level shifter
> +
> +This binding allow supporting GPIOs going though a level shifter.
> +
> +Required properties:
> +- compatible : should be "gpio-level-shifter"
> +- data-gpios : list of the data GPIO phandles
> +- #gpio-cells : should be 2
> +- gpio-controller : marks the device node as a GPIO controller
> +
> +Optional properties:
> +- enable-gpio : phandle of the GPIO that control the level shifter enable pin
> +- direction-gpio : phandle of the GPIO that control the level shifter direction
> +- vcca-supply : phandle of the regulator for side A of the level shifter
> +- vccb-supply : phandle of the regulator for side B of the level shifter

It must be clear which side is facing the parent GPIO controller,
A or B.

It must be clear which one of these two should be used if the level shifter
has ony VCC.

And isn't the proper terminology VCC+VDD?

An example must be provided.

Yours,
Linus Walleij

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

end of thread, other threads:[~2014-11-28 13:39 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-24 14:01 [PATCH 1/2] devicetree: add a binding for GPIOs going though a level shifter Alban Bedel
2014-11-24 14:01 ` [PATCH 2/2] gpio: add a driver for GPIOs going through " Alban Bedel
2014-11-28 13:37   ` Linus Walleij
2014-11-24 21:01 ` [PATCH 1/2] devicetree: add a binding for GPIOs going though " Rob Herring
2014-11-28 13:39 ` Linus Walleij

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.