All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] gpio: Update and simplify the uclass API
@ 2021-01-15 14:04 Simon Glass
  2021-01-15 14:04 ` [PATCH 01/15] gpio: Disable functions not used with of-platdata Simon Glass
                   ` (14 more replies)
  0 siblings, 15 replies; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

At present the GPIO uclass mirrors what was in U-Boot before driver model.
It works well in most cases but is becoming cumbersome with things like
pull-up/down and drive strength. In those cases it is easier for the
driver to deal with all the flags at one, rather than piece by piece.

In fact the current API does not officially have a method for adjusting
anything other than the direction flags. While set_dir_flags() and
get_dir_flags() do in fact support changing other flags, this is not
documented.

Secondly, set_dir_flags actually ORs the current flags with the new ones
so it is not possible to clear flags. It seems better to use a clr/set
interface (bit clear followed by OR) to provide more flexibility.

Finally, direction_input() and direction_output() are really just the same
thing as set_dir_flags(), with a different name. We currently use the
latter if available, failing back to the former. But it makes sense to
deprecate the old methods.

This series makes the above changes. Existing drivers are mostly left
alone, since they should continue to operate as is. The sandbox driver is
updated to add the required new tests and the x86 driver is switched over
to the new API.

The STM32 driver should be checked to make sure the open source/open drain
features still work as intended.


Simon Glass (15):
  gpio: Disable functions not used with of-platdata
  dm: gpio: Rename set_dir_flags() method to update_flags()
  dm: gpio: Rename get_dir_flags() method to get_flags()
  gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags()
  gpio: Drop dm_gpio_set_dir()
  gpio: sandbox: Rename GPIO dir_flags to flags
  gpio: sandbox: Use a separate flag for the value
  gpio: sandbox: Fully separate pin value from output value
  gpio: sandbox: Make sandbox_gpio_set_flags() set all flags
  dm: gpio: Add a way to update flags
  gpio: Replace direction_input() and direction_output()
  gpio: Use an 'ops' variable everywhere
  gpio: x86: Drop the deprecated methods in intel_gpio
  gpio: sandbox: Track whether a GPIO is driven
  gpio: Add a way to read 3-way strapping pins

 arch/sandbox/include/asm/gpio.h           |  17 +-
 arch/x86/include/asm/intel_pinctrl_defs.h |   5 +
 drivers/gpio/gpio-uclass.c                | 228 ++++++++++++++-----
 drivers/gpio/intel_gpio.c                 |  72 +++---
 drivers/gpio/sandbox.c                    | 137 ++++++++----
 drivers/gpio/stm32_gpio.c                 |  14 +-
 drivers/pinctrl/pinctrl-stmfx.c           |  14 +-
 include/asm-generic/gpio.h                | 130 +++++++++--
 test/dm/gpio.c                            | 261 +++++++++++++++++++---
 9 files changed, 663 insertions(+), 215 deletions(-)

-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 01/15] gpio: Disable functions not used with of-platdata
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-18 21:17   ` Pratyush Yadav
  2021-01-21  8:59   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags() Simon Glass
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

These functions use devicetree and cannot wprl with of-platdata, which has
no runtime devicetree.

If they are used, the current linker error is confusing, since it talks
about missing functions in the bowels of driver model.

Avoid compiling these functions at all with of-platdata, so that a
straightforward link error points to the problem.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/gpio-uclass.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index bad6b71e0c3..e84b68db772 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -1023,6 +1023,7 @@ err:
 	return ret;
 }
 
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
 				       int index, struct gpio_desc *desc,
 				       int flags, bool add_index)
@@ -1109,6 +1110,7 @@ int gpio_get_list_count(struct udevice *dev, const char *list_name)
 
 	return ret;
 }
+#endif /* OF_PLATDATA */
 
 int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
 {
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags()
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
  2021-01-15 14:04 ` [PATCH 01/15] gpio: Disable functions not used with of-platdata Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-18 21:39   ` Pratyush Yadav
  2021-01-21  9:01   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 03/15] dm: gpio: Rename get_dir_flags() method to get_flags() Simon Glass
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

The current method is a misnomer since it is also used (e.g. by stm32) to
update pull settings and open source/open drain.

Rename it and expand the documentation to cover a few more details.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/gpio-uclass.c      | 16 ++++++++--------
 drivers/gpio/sandbox.c          |  6 +++---
 drivers/gpio/stm32_gpio.c       |  6 +++---
 drivers/pinctrl/pinctrl-stmfx.c |  6 +++---
 include/asm-generic/gpio.h      | 30 ++++++++++++++++++++++++------
 test/dm/gpio.c                  |  8 ++++----
 6 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index e84b68db772..0862a28bf86 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -619,7 +619,7 @@ static int check_dir_flags(ulong flags)
 	return 0;
 }
 
-static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
 {
 	struct udevice *dev = desc->dev;
 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
@@ -637,9 +637,9 @@ static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 		return ret;
 	}
 
-	/* GPIOD_ are directly managed by driver in set_dir_flags*/
-	if (ops->set_dir_flags) {
-		ret = ops->set_dir_flags(dev, desc->offset, flags);
+	/* GPIOD_ are directly managed by driver in update_flags */
+	if (ops->update_flags) {
+		ret = ops->update_flags(dev, desc->offset, flags);
 	} else {
 		if (flags & GPIOD_IS_OUT) {
 			ret = ops->direction_output(dev, desc->offset,
@@ -666,7 +666,7 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 
 	/* combine the requested flags (for IN/OUT) and the descriptor flags */
 	flags |= desc->flags;
-	ret = _dm_gpio_set_dir_flags(desc, flags);
+	ret = _dm_gpio_update_flags(desc, flags);
 
 	return ret;
 }
@@ -679,7 +679,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
 	if (ret)
 		return ret;
 
-	return _dm_gpio_set_dir_flags(desc, desc->flags);
+	return _dm_gpio_update_flags(desc, desc->flags);
 }
 
 int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags)
@@ -1307,8 +1307,8 @@ static int gpio_post_bind(struct udevice *dev)
 			ops->get_function += gd->reloc_off;
 		if (ops->xlate)
 			ops->xlate += gd->reloc_off;
-		if (ops->set_dir_flags)
-			ops->set_dir_flags += gd->reloc_off;
+		if (ops->update_flags)
+			ops->update_flags += gd->reloc_off;
 		if (ops->get_dir_flags)
 			ops->get_dir_flags += gd->reloc_off;
 
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index dc8d506e8d4..029908dc9f9 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -177,8 +177,8 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
 	return 0;
 }
 
-static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-				 ulong flags)
+static int sb_gpio_update_flags(struct udevice *dev, unsigned int offset,
+				ulong flags)
 {
 	ulong *dir_flags;
 
@@ -272,7 +272,7 @@ static const struct dm_gpio_ops gpio_sandbox_ops = {
 	.set_value		= sb_gpio_set_value,
 	.get_function		= sb_gpio_get_function,
 	.xlate			= sb_gpio_xlate,
-	.set_dir_flags		= sb_gpio_set_dir_flags,
+	.update_flags		= sb_gpio_update_flags,
 	.get_dir_flags		= sb_gpio_get_dir_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
 	.get_acpi		= sb_gpio_get_acpi,
diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
index 79d55e812db..daae6ddb93f 100644
--- a/drivers/gpio/stm32_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -189,8 +189,8 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset)
 	return GPIOF_FUNC;
 }
 
-static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-				    ulong flags)
+static int stm32_gpio_update_flags(struct udevice *dev, unsigned int offset,
+				   ulong flags)
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
@@ -268,7 +268,7 @@ static const struct dm_gpio_ops gpio_stm32_ops = {
 	.get_value		= stm32_gpio_get_value,
 	.set_value		= stm32_gpio_set_value,
 	.get_function		= stm32_gpio_get_function,
-	.set_dir_flags		= stm32_gpio_set_dir_flags,
+	.update_flags		= stm32_gpio_update_flags,
 	.get_dir_flags		= stm32_gpio_get_dir_flags,
 };
 
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index 7cf08dbddd1..084d5cef7aa 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -163,8 +163,8 @@ static int stmfx_gpio_direction_output(struct udevice *dev,
 	return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1);
 }
 
-static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-				    ulong flags)
+static int stmfx_gpio_update_flags(struct udevice *dev, unsigned int offset,
+				   ulong flags)
 {
 	int ret = -ENOTSUPP;
 
@@ -266,7 +266,7 @@ static const struct dm_gpio_ops stmfx_gpio_ops = {
 	.get_function = stmfx_gpio_get_function,
 	.direction_input = stmfx_gpio_direction_input,
 	.direction_output = stmfx_gpio_direction_output,
-	.set_dir_flags = stmfx_gpio_set_dir_flags,
+	.update_flags = stmfx_gpio_update_flags,
 	.get_dir_flags = stmfx_gpio_get_dir_flags,
 };
 
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 82294cbdc57..4626e7d92ae 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -301,20 +301,38 @@ struct dm_gpio_ops {
 		     struct ofnode_phandle_args *args);
 
 	/**
-	 * set_dir_flags() - Set GPIO dir flags
+	 * update_flags() - Adjust GPIO flags
 	 *
 	 * This function should set up the GPIO configuration according to the
-	 * information provide by the direction flags bitfield.
+	 * information provide by @flags.
+	 *
+	 * If any flags cannot be set (e.g. the driver or hardware does not
+	 * support them or this particular GPIO does not have the requested
+	 * feature), the driver should perform what changes it can. The uclass
+	 * can read the current flags back with a call to get_dir_flags() if
+	 * desired.
+	 *
+	 * The uclass checks that flags do not obviously conflict (e.g. input
+	 * and output). If the driver finds other conflicts it should return
+	 * -ERECALLCONFLICT
+	 *
+	 * Note that GPIOD_ACTIVE_LOW should be ignored, since the uclass
+	 * adjusts for it automatically. For example, for an output GPIO,
+	 * GPIOD_ACTIVE_LOW causes GPIOD_IS_OUT_ACTIVE to be inverted by the
+	 * uclass, so the driver always sees the value that should be set at the
+	 * pin (1=high, 0=low).
 	 *
 	 * This method is optional.
 	 *
 	 * @dev:	GPIO device
 	 * @offset:	GPIO offset within that device
-	 * @flags:	GPIO configuration to use
-	 * @return 0 if OK, -ve on error
+	 * @flags:	New flags value (GPIOD_...)
+	 *
+	 * @return 0 if OK, -ERECALLCONFLICT if flags conflict in some
+	 *	non-obvious way and were not applied, other -ve on error
 	 */
-	int (*set_dir_flags)(struct udevice *dev, unsigned int offset,
-			     ulong flags);
+	int (*update_flags)(struct udevice *dev, unsigned int offset,
+			    ulong flags);
 
 	/**
 	 * get_dir_flags() - Get GPIO dir flags
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index d7b85e74ce5..a08c3590d71 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -81,12 +81,12 @@ static int dm_test_gpio(struct unit_test_state *uts)
 	/* Make it an open drain output, and reset it */
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
 		    sandbox_gpio_get_dir_flags(dev, offset));
-	ut_assertok(ops->set_dir_flags(dev, offset,
-				       GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
+	ut_assertok(ops->update_flags(dev, offset,
+				      GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
 		    sandbox_gpio_get_dir_flags(dev, offset));
-	ut_assertok(ops->set_dir_flags(dev, offset,
-				       GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
+	ut_assertok(ops->update_flags(dev, offset,
+				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
 		    sandbox_gpio_get_dir_flags(dev, offset));
 
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 03/15] dm: gpio: Rename get_dir_flags() method to get_flags()
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
  2021-01-15 14:04 ` [PATCH 01/15] gpio: Disable functions not used with of-platdata Simon Glass
  2021-01-15 14:04 ` [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags() Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-18 21:54   ` Pratyush Yadav
  2021-01-21  9:02   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 04/15] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags() Simon Glass
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

It is more useful to be able to read all the flags, not just the direction
ones. In fact this is what the STM32 driver does. Update the method name
to reflect this.

Tweak the docs a little and use 'flagsp' as the return argument, as is
common in driver model, to indicate it returns a value.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/gpio-uclass.c      | 30 +++++++++++++++---------------
 drivers/gpio/sandbox.c          |  8 ++++----
 drivers/gpio/stm32_gpio.c       |  8 ++++----
 drivers/pinctrl/pinctrl-stmfx.c |  8 ++++----
 include/asm-generic/gpio.h      | 13 +++++++------
 5 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 0862a28bf86..83d3cf0a6b3 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -682,39 +682,39 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
 	return _dm_gpio_update_flags(desc, desc->flags);
 }
 
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags)
+int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flagsp)
 {
 	struct udevice *dev = desc->dev;
 	int ret, value;
 	struct dm_gpio_ops *ops = gpio_get_ops(dev);
-	ulong dir_flags;
+	ulong flags;
 
-	ret = check_reserved(desc, "get_dir_flags");
+	ret = check_reserved(desc, "get_flags");
 	if (ret)
 		return ret;
 
 	/* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */
-	if (ops->get_dir_flags) {
-		ret = ops->get_dir_flags(dev, desc->offset, &dir_flags);
+	if (ops->get_flags) {
+		ret = ops->get_flags(dev, desc->offset, &flags);
 		if (ret)
 			return ret;
 
 		/* GPIOD_ACTIVE_LOW is saved in desc->flags */
-		value = dir_flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
+		value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
 		if (desc->flags & GPIOD_ACTIVE_LOW)
 			value = !value;
-		dir_flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
-		dir_flags |= (desc->flags & GPIOD_ACTIVE_LOW);
+		flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
+		flags |= (desc->flags & GPIOD_ACTIVE_LOW);
 		if (value)
-			dir_flags |= GPIOD_IS_OUT_ACTIVE;
+			flags |= GPIOD_IS_OUT_ACTIVE;
 	} else {
-		dir_flags = desc->flags;
+		flags = desc->flags;
 		/* only GPIOD_IS_OUT_ACTIVE is provided by uclass */
-		dir_flags &= ~GPIOD_IS_OUT_ACTIVE;
+		flags &= ~GPIOD_IS_OUT_ACTIVE;
 		if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc))
-			dir_flags |= GPIOD_IS_OUT_ACTIVE;
+			flags |= GPIOD_IS_OUT_ACTIVE;
 	}
-	*flags = dir_flags;
+	*flagsp = flags;
 
 	return 0;
 }
@@ -1309,8 +1309,8 @@ static int gpio_post_bind(struct udevice *dev)
 			ops->xlate += gd->reloc_off;
 		if (ops->update_flags)
 			ops->update_flags += gd->reloc_off;
-		if (ops->get_dir_flags)
-			ops->get_dir_flags += gd->reloc_off;
+		if (ops->get_flags)
+			ops->get_flags += gd->reloc_off;
 
 		reloc_done++;
 	}
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 029908dc9f9..fd14d4e8b5f 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -199,11 +199,11 @@ static int sb_gpio_update_flags(struct udevice *dev, unsigned int offset,
 	return 0;
 }
 
-static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-				 ulong *flags)
+static int sb_gpio_get_flags(struct udevice *dev, unsigned int offset,
+			     ulong *flagsp)
 {
 	debug("%s: offset:%u\n", __func__, offset);
-	*flags = *get_gpio_dir_flags(dev, offset);
+	*flagsp = *get_gpio_dir_flags(dev, offset);
 
 	return 0;
 }
@@ -273,7 +273,7 @@ static const struct dm_gpio_ops gpio_sandbox_ops = {
 	.get_function		= sb_gpio_get_function,
 	.xlate			= sb_gpio_xlate,
 	.update_flags		= sb_gpio_update_flags,
-	.get_dir_flags		= sb_gpio_get_dir_flags,
+	.get_flags		= sb_gpio_get_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
 	.get_acpi		= sb_gpio_get_acpi,
 #endif
diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
index daae6ddb93f..06a1f28cb77 100644
--- a/drivers/gpio/stm32_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -221,8 +221,8 @@ static int stm32_gpio_update_flags(struct udevice *dev, unsigned int offset,
 	return 0;
 }
 
-static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-				    ulong *flags)
+static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset,
+				ulong *flagsp)
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
@@ -257,7 +257,7 @@ static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
 	default:
 		break;
 	}
-	*flags = dir_flags;
+	*flagsp = dir_flags;
 
 	return 0;
 }
@@ -269,7 +269,7 @@ static const struct dm_gpio_ops gpio_stm32_ops = {
 	.set_value		= stm32_gpio_set_value,
 	.get_function		= stm32_gpio_get_function,
 	.update_flags		= stm32_gpio_update_flags,
-	.get_dir_flags		= stm32_gpio_get_dir_flags,
+	.get_flags		= stm32_gpio_get_flags,
 };
 
 static int gpio_stm32_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index 084d5cef7aa..6477febbaa1 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -199,8 +199,8 @@ static int stmfx_gpio_update_flags(struct udevice *dev, unsigned int offset,
 	return ret;
 }
 
-static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-				    ulong *flags)
+static int stmfx_gpio_get_flags(struct udevice *dev, unsigned int offset,
+				ulong *flagsp)
 {
 	ulong dir_flags = 0;
 	int ret;
@@ -233,7 +233,7 @@ static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
 				dir_flags |= GPIOD_PULL_DOWN;
 		}
 	}
-	*flags = dir_flags;
+	*flagsp = dir_flags;
 
 	return 0;
 }
@@ -267,7 +267,7 @@ static const struct dm_gpio_ops stmfx_gpio_ops = {
 	.direction_input = stmfx_gpio_direction_input,
 	.direction_output = stmfx_gpio_direction_output,
 	.update_flags = stmfx_gpio_update_flags,
-	.get_dir_flags = stmfx_gpio_get_dir_flags,
+	.get_flags = stmfx_gpio_get_flags,
 };
 
 U_BOOT_DRIVER(stmfx_gpio) = {
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 4626e7d92ae..48e042dc44b 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -309,7 +309,7 @@ struct dm_gpio_ops {
 	 * If any flags cannot be set (e.g. the driver or hardware does not
 	 * support them or this particular GPIO does not have the requested
 	 * feature), the driver should perform what changes it can. The uclass
-	 * can read the current flags back with a call to get_dir_flags() if
+	 * can read the current flags back with a call to get_flags() if
 	 * desired.
 	 *
 	 * The uclass checks that flags do not obviously conflict (e.g. input
@@ -335,19 +335,20 @@ struct dm_gpio_ops {
 			    ulong flags);
 
 	/**
-	 * get_dir_flags() - Get GPIO dir flags
+	 * get_flags() - Get GPIO flags
 	 *
-	 * This function return the GPIO direction flags used.
+	 * This function return the GPIO flags used. It should read this from
+	 * the hardware directly.
 	 *
 	 * This method is optional.
 	 *
 	 * @dev:	GPIO device
 	 * @offset:	GPIO offset within that device
-	 * @flags:	place to put the used direction flags by GPIO
+	 * @flagsp:	place to put the current flags value
 	 * @return 0 if OK, -ve on error
 	 */
-	int (*get_dir_flags)(struct udevice *dev, unsigned int offset,
-			     ulong *flags);
+	int (*get_flags)(struct udevice *dev, unsigned int offset,
+			 ulong *flagsp);
 
 #if CONFIG_IS_ENABLED(ACPIGEN)
 	/**
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 04/15] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags()
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (2 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 03/15] dm: gpio: Rename get_dir_flags() method to get_flags() Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-18 21:57   ` Pratyush Yadav
  2021-01-21  9:05   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 05/15] gpio: Drop dm_gpio_set_dir() Simon Glass
                   ` (10 subsequent siblings)
  14 siblings, 2 replies; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

This function can be used to get any flags, not just direction flags.
Rename it to avoid confusion.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/gpio-uclass.c |  2 +-
 include/asm-generic/gpio.h |  4 ++--
 test/dm/gpio.c             | 12 ++++++------
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 83d3cf0a6b3..864a9003245 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -682,7 +682,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
 	return _dm_gpio_update_flags(desc, desc->flags);
 }
 
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flagsp)
+int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
 	struct udevice *dev = desc->dev;
 	int ret, value;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 48e042dc44b..5ecb73c138d 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -685,7 +685,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc);
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
 
 /**
- * dm_gpio_get_dir_flags() - Get direction flags
+ * dm_gpio_get_flags() - Get direction flags
  *
  * read the current direction flags
  *
@@ -694,7 +694,7 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
  * @flags:	place to put the used flags
  * @return 0 if OK, -ve on error, in which case desc->flags is not updated
  */
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags);
+int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flags);
 
 /**
  * gpio_get_number() - Get the global GPIO number of a GPIO
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index a08c3590d71..6b9ec88ca2b 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -397,22 +397,22 @@ static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts)
 	ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list,
 						 ARRAY_SIZE(desc_list), 0));
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[0], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[0], &flags));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[1], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[1], &flags));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[2], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[2], &flags));
 	ut_asserteq(GPIOD_IS_OUT, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[3], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[3], &flags));
 	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[4], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[4], &flags));
 	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[5], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[5], &flags));
 	ut_asserteq(GPIOD_IS_IN, flags);
 
 	ut_assertok(gpio_free_list(dev, desc_list, 6));
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 05/15] gpio: Drop dm_gpio_set_dir()
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (3 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 04/15] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags() Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21  9:06   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 06/15] gpio: sandbox: Rename GPIO dir_flags to flags Simon Glass
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

This function is not used. Drop it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/gpio-uclass.c | 11 -----------
 include/asm-generic/gpio.h | 11 -----------
 2 files changed, 22 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 864a9003245..aa0e3852122 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -671,17 +671,6 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 	return ret;
 }
 
-int dm_gpio_set_dir(struct gpio_desc *desc)
-{
-	int ret;
-
-	ret = check_reserved(desc, "set_dir");
-	if (ret)
-		return ret;
-
-	return _dm_gpio_update_flags(desc, desc->flags);
-}
-
 int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
 	struct udevice *dev = desc->dev;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 5ecb73c138d..30ff5feb160 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -659,17 +659,6 @@ int dm_gpio_get_value(const struct gpio_desc *desc);
 
 int dm_gpio_set_value(const struct gpio_desc *desc, int value);
 
-/**
- * dm_gpio_set_dir() - Set the direction for a GPIO
- *
- * This sets up the direction according to the GPIO flags: desc->flags.
- *
- * @desc:	GPIO description containing device, offset and flags,
- *		previously returned by gpio_request_by_name()
- * @return 0 if OK, -ve on error
- */
-int dm_gpio_set_dir(struct gpio_desc *desc);
-
 /**
  * dm_gpio_set_dir_flags() - Set direction using description and added flags
  *
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 06/15] gpio: sandbox: Rename GPIO dir_flags to flags
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (4 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 05/15] gpio: Drop dm_gpio_set_dir() Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21  9:14   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 07/15] gpio: sandbox: Use a separate flag for the value Simon Glass
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

Adjust the terminology in this driver to reflect that fact that all flags
are handled, not just direction flags.

Create a new access function to get the full GPIO state, not just the
direction flags. Drop the static invalid_dir_flags since we can rely on a
segfault if something is wrong.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/sandbox/include/asm/gpio.h |  8 ++--
 drivers/gpio/sandbox.c          | 65 ++++++++++++++++++---------------
 test/dm/gpio.c                  | 18 ++++-----
 3 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index df4ba4fb5f3..20d78296551 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -69,17 +69,17 @@ int sandbox_gpio_set_direction(struct udevice *dev, unsigned int offset,
  * @param offset	GPIO offset within bank
  * @return dir_flags: bitfield accesses by GPIOD_ defines
  */
-ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset);
+ulong sandbox_gpio_get_flags(struct udevice *dev, unsigned int offset);
 
 /**
  * Set the simulated flags of a GPIO (used only in sandbox test code)
  *
  * @param dev		device to use
  * @param offset	GPIO offset within bank
- * @param flags		dir_flags: bitfield accesses by GPIOD_ defines
+ * @param flags		bitfield accesses by GPIOD_ defines
  * @return -1 on error, 0 if ok
  */
-int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-			       ulong flags);
+int sandbox_gpio_set_flags(struct udevice *dev, unsigned int offset,
+			   ulong flags);
 
 #endif
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index fd14d4e8b5f..9ce5d823505 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -22,34 +22,44 @@
 
 struct gpio_state {
 	const char *label;	/* label given by requester */
-	ulong dir_flags;	/* dir_flags (GPIOD_...) */
+	ulong flags;		/* flags (GPIOD_...) */
 };
 
-/* Access routines for GPIO dir flags */
-static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
+/* Access routines for GPIO info */
+static struct gpio_state *get_gpio_state(struct udevice *dev, uint offset)
 {
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct gpio_state *state = dev_get_priv(dev);
 
 	if (offset >= uc_priv->gpio_count) {
-		static ulong invalid_dir_flags;
 		printf("sandbox_gpio: error: invalid gpio %u\n", offset);
-		return &invalid_dir_flags;
+		return NULL;
 	}
 
-	return &state[offset].dir_flags;
+	return &state[offset];
+}
+
+/* Access routines for GPIO dir flags */
+static ulong *get_gpio_flags(struct udevice *dev, unsigned int offset)
+{
+	struct gpio_state *state = get_gpio_state(dev, offset);
+
+	if (!state)
+		return NULL;
+
+	return &state->flags;
 
 }
 
 static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
 {
-	return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
+	return (*get_gpio_flags(dev, offset) & flag) != 0;
 }
 
 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
 			 int value)
 {
-	ulong *gpio = get_gpio_dir_flags(dev, offset);
+	ulong *gpio = get_gpio_flags(dev, offset);
 
 	if (value)
 		*gpio |= flag;
@@ -88,15 +98,14 @@ int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
 	return 0;
 }
 
-ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
+ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset)
 {
-	return *get_gpio_dir_flags(dev, offset);
+	return *get_gpio_flags(dev, offset);
 }
 
-int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-			       ulong flags)
+int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
 {
-	*get_gpio_dir_flags(dev, offset) = flags;
+	*get_gpio_flags(dev, offset) = flags;
 
 	return 0;
 }
@@ -177,33 +186,31 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
 	return 0;
 }
 
-static int sb_gpio_update_flags(struct udevice *dev, unsigned int offset,
-				ulong flags)
+static int sb_gpio_update_flags(struct udevice *dev, uint offset, ulong newf)
 {
-	ulong *dir_flags;
+	ulong *flags;
 
-	debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
+	debug("%s: offset:%u, flags = %lx\n", __func__, offset, newf);
 
-	dir_flags = get_gpio_dir_flags(dev, offset);
+	flags = get_gpio_flags(dev, offset);
 
 	/*
 	 * For testing purposes keep the output value when switching to input.
 	 * This allows us to manipulate the input value via the gpio command.
 	 */
-	if (flags & GPIOD_IS_IN)
-		*dir_flags = (flags & ~GPIOD_IS_OUT_ACTIVE) |
-			     (*dir_flags & GPIOD_IS_OUT_ACTIVE);
+	if (newf & GPIOD_IS_IN)
+		*flags = (newf & ~GPIOD_IS_OUT_ACTIVE) |
+			(*flags & GPIOD_IS_OUT_ACTIVE);
 	else
-		*dir_flags = flags;
+		*flags = newf;
 
 	return 0;
 }
 
-static int sb_gpio_get_flags(struct udevice *dev, unsigned int offset,
-			     ulong *flagsp)
+static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
 {
 	debug("%s: offset:%u\n", __func__, offset);
-	*flagsp = *get_gpio_dir_flags(dev, offset);
+	*flagsp = *get_gpio_flags(dev, offset);
 
 	return 0;
 }
@@ -456,7 +463,7 @@ static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
 	return pin_name;
 }
 
-static char *get_dir_flags_string(ulong flags)
+static char *get_flags_string(ulong flags)
 {
 	if (flags & GPIOD_OPEN_DRAIN)
 		return "drive-open-drain";
@@ -475,7 +482,7 @@ static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
 {
 	struct udevice *gpio_dev;
 	unsigned int gpio_idx;
-	ulong dir_flags;
+	ulong flags;
 	int function;
 
 	/* look up for the bank which owns the requested pin */
@@ -484,11 +491,11 @@ static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
 		snprintf(buf, size, "Error");
 	} else {
 		function = sb_gpio_get_function(gpio_dev, gpio_idx);
-		dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
+		flags = *get_gpio_flags(gpio_dev, gpio_idx);
 
 		snprintf(buf, size, "gpio %s %s",
 			 function == GPIOF_OUTPUT ? "output" : "input",
-			 get_dir_flags_string(dir_flags));
+			 get_flags_string(flags));
 	}
 
 	return 0;
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index 6b9ec88ca2b..43e868cd4ea 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -80,15 +80,15 @@ static int dm_test_gpio(struct unit_test_state *uts)
 
 	/* Make it an open drain output, and reset it */
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-		    sandbox_gpio_get_dir_flags(dev, offset));
+		    sandbox_gpio_get_flags(dev, offset));
 	ut_assertok(ops->update_flags(dev, offset,
 				      GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-		    sandbox_gpio_get_dir_flags(dev, offset));
+		    sandbox_gpio_get_flags(dev, offset));
 	ut_assertok(ops->update_flags(dev, offset,
 				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-		    sandbox_gpio_get_dir_flags(dev, offset));
+		    sandbox_gpio_get_flags(dev, offset));
 
 	/* Make it an input */
 	ut_assertok(ops->direction_input(dev, offset));
@@ -176,7 +176,7 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts)
 
 	/* GPIO 0 is (GPIO_OUT|GPIO_OPEN_DRAIN) */
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-		    sandbox_gpio_get_dir_flags(gpio_c, 0));
+		    sandbox_gpio_get_flags(gpio_c, 0));
 
 	/* Set it as output high, should become an input */
 	ut_assertok(dm_gpio_set_value(&desc_list[0], 1));
@@ -190,7 +190,7 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts)
 
 	/* GPIO 1 is (GPIO_OUT|GPIO_OPEN_SOURCE) */
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
-		    sandbox_gpio_get_dir_flags(gpio_c, 1));
+		    sandbox_gpio_get_flags(gpio_c, 1));
 
 	/* Set it as output high, should become output high */
 	ut_assertok(dm_gpio_set_value(&desc_list[1], 1));
@@ -204,7 +204,7 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts)
 
 	/* GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN) */
 	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-		    sandbox_gpio_get_dir_flags(gpio_c, 6));
+		    sandbox_gpio_get_flags(gpio_c, 6));
 
 	/* Set it as output high, should become output low */
 	ut_assertok(dm_gpio_set_value(&desc_list[6], 1));
@@ -218,7 +218,7 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts)
 
 	/* GPIO 7 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_SOURCE) */
 	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
-		    sandbox_gpio_get_dir_flags(gpio_c, 7));
+		    sandbox_gpio_get_flags(gpio_c, 7));
 
 	/* Set it as output high, should become an input */
 	ut_assertok(dm_gpio_set_value(&desc_list[7], 1));
@@ -363,12 +363,12 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts)
 	ut_assertok(gpio_free_list(dev, desc_list, 3));
 
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-		    sandbox_gpio_get_dir_flags(gpio_a, 1));
+		    sandbox_gpio_get_flags(gpio_a, 1));
 	ut_asserteq(6, gpio_request_list_by_name(dev, "test2-gpios", desc_list,
 						 ARRAY_SIZE(desc_list), 0));
 
 	/* This was set to output previously but flags resetted to 0 = INPUT */
-	ut_asserteq(0, sandbox_gpio_get_dir_flags(gpio_a, 1));
+	ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 1));
 	ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 1, NULL));
 
 	/* Active low should invert the input value */
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 07/15] gpio: sandbox: Use a separate flag for the value
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (5 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 06/15] gpio: sandbox: Rename GPIO dir_flags to flags Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21  9:33   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 08/15] gpio: sandbox: Fully separate pin value from output value Simon Glass
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

At present with the sandbox GPIO driver it is not possible to change the
value of GPIOD_IS_OUT_ACTIVE unless the GPIO is an output. This makes it
hard to test changing the flags since we need to be aware of the internal
workings of the driver.

The feature is designed to aid testing.

Split this feature out into a separate sandbox-specific flag, so that the
flags can change unimpeded. This will make it easier to allow updating the
flags in a future patch.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/sandbox/include/asm/gpio.h |  5 ++++
 drivers/gpio/sandbox.c          | 43 +++++++++++++++------------------
 2 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index 20d78296551..3f267797644 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -23,6 +23,11 @@
  */
 #include <asm-generic/gpio.h>
 
+/* Our own private GPIO flags, which musn't conflict with GPIOD_... */
+#define GPIOD_EXT_HIGH		BIT(20)	/* external source is high (else low) */
+
+#define GPIOD_SANDBOX_MASK	BIT(20)
+
 /**
  * Return the simulated value of a GPIO (used only in sandbox test code)
  *
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 9ce5d823505..52e73e2300a 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -59,12 +59,12 @@ static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
 			 int value)
 {
-	ulong *gpio = get_gpio_flags(dev, offset);
+	struct gpio_state *state = get_gpio_state(dev, offset);
 
 	if (value)
-		*gpio |= flag;
+		state->flags |= flag;
 	else
-		*gpio &= ~flag;
+		state->flags &= ~flag;
 
 	return 0;
 }
@@ -75,14 +75,19 @@ static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
 
 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
 {
+	struct gpio_state *state = get_gpio_state(dev, offset);
+
 	if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
 		debug("sandbox_gpio: get_value on output gpio %u\n", offset);
-	return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
+
+	return state->flags & GPIOD_EXT_HIGH ? true : false;
 }
 
 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
-	return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
+	set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH, value);
+
+	return 0;
 }
 
 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
@@ -93,19 +98,25 @@ int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
 int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
 {
 	set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
-	set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
+	set_gpio_flag(dev, offset, GPIOD_IS_IN, !output);
 
 	return 0;
 }
 
 ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset)
 {
-	return *get_gpio_flags(dev, offset);
+	ulong flags = *get_gpio_flags(dev, offset);
+
+	return flags & ~GPIOD_SANDBOX_MASK;
 }
 
 int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
 {
-	*get_gpio_flags(dev, offset) = flags;
+	struct gpio_state *state = get_gpio_state(dev, offset);
+
+	if (flags & GPIOD_IS_OUT_ACTIVE)
+		flags |= GPIOD_EXT_HIGH;
+	state->flags = (state->flags & GPIOD_SANDBOX_MASK) | flags;
 
 	return 0;
 }
@@ -188,23 +199,9 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
 
 static int sb_gpio_update_flags(struct udevice *dev, uint offset, ulong newf)
 {
-	ulong *flags;
-
 	debug("%s: offset:%u, flags = %lx\n", __func__, offset, newf);
 
-	flags = get_gpio_flags(dev, offset);
-
-	/*
-	 * For testing purposes keep the output value when switching to input.
-	 * This allows us to manipulate the input value via the gpio command.
-	 */
-	if (newf & GPIOD_IS_IN)
-		*flags = (newf & ~GPIOD_IS_OUT_ACTIVE) |
-			(*flags & GPIOD_IS_OUT_ACTIVE);
-	else
-		*flags = newf;
-
-	return 0;
+	return sandbox_gpio_set_flags(dev, offset, newf);
 }
 
 static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 08/15] gpio: sandbox: Fully separate pin value from output value
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (6 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 07/15] gpio: sandbox: Use a separate flag for the value Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21  9:39   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 09/15] gpio: sandbox: Make sandbox_gpio_set_flags() set all flags Simon Glass
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

At present we have the concept of a pin's external value. This is what
is used when getting the value of a pin. But we still set the
GPIOD_IS_OUT_ACTIVE flag when changing the value. This is not actually
correct, since if the pin changes from output to input, the external
value need not change. Adjust the logic for this difference.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/sandbox.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 52e73e2300a..ebc160cb849 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -85,7 +85,7 @@ int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
 
 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
-	set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH, value);
+	set_gpio_flag(dev, offset, GPIOD_EXT_HIGH, value);
 
 	return 0;
 }
@@ -137,10 +137,19 @@ static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
 static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
 				    int value)
 {
+	int ret;
+
 	debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
-	return sandbox_gpio_set_direction(dev, offset, 1) |
-		sandbox_gpio_set_value(dev, offset, value);
+	ret = sandbox_gpio_set_direction(dev, offset, 1);
+	if (ret)
+		return ret;
+	ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH,
+			    value);
+	if (ret)
+		return ret;
+
+	return 0;
 }
 
 /* read GPIO IN value of port 'offset' */
@@ -154,6 +163,8 @@ static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
 /* write GPIO OUT value to port 'offset' */
 static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
+	int ret;
+
 	debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
 	if (!sandbox_gpio_get_direction(dev, offset)) {
@@ -162,7 +173,12 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 		return -1;
 	}
 
-	return sandbox_gpio_set_value(dev, offset, value);
+	ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH,
+			    value);
+	if (ret)
+		return ret;
+
+	return 0;
 }
 
 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 09/15] gpio: sandbox: Make sandbox_gpio_set_flags() set all flags
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (7 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 08/15] gpio: sandbox: Fully separate pin value from output value Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21  9:43   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 10/15] dm: gpio: Add a way to update flags Simon Glass
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

Allow this function to see all flags, including the internal sandbox ones.
This allows the tests to fully control the behaviour of the driver.

To make this work, move the setting of GPIOD_EXT_HIGH -to where the flags
are updated via driver model, rather than the sandbox 'back door'.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/sandbox.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index ebc160cb849..11d4757abbb 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -114,9 +114,7 @@ int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
 {
 	struct gpio_state *state = get_gpio_state(dev, offset);
 
-	if (flags & GPIOD_IS_OUT_ACTIVE)
-		flags |= GPIOD_EXT_HIGH;
-	state->flags = (state->flags & GPIOD_SANDBOX_MASK) | flags;
+	state->flags = flags;
 
 	return 0;
 }
@@ -213,17 +211,26 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
 	return 0;
 }
 
-static int sb_gpio_update_flags(struct udevice *dev, uint offset, ulong newf)
+static int sb_gpio_update_flags(struct udevice *dev, uint offset, ulong flags)
 {
-	debug("%s: offset:%u, flags = %lx\n", __func__, offset, newf);
+	debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags);
+	struct gpio_state *state = get_gpio_state(dev, offset);
+
+	if (flags & GPIOD_IS_OUT) {
+		if (flags & GPIOD_IS_OUT_ACTIVE)
+			flags |= GPIOD_EXT_HIGH;
+		else
+			flags &= ~GPIOD_EXT_HIGH;
+	}
+	state->flags = flags;
 
-	return sandbox_gpio_set_flags(dev, offset, newf);
+	return 0;
 }
 
 static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
 {
 	debug("%s: offset:%u\n", __func__, offset);
-	*flagsp = *get_gpio_flags(dev, offset);
+	*flagsp = *get_gpio_flags(dev, offset) & ~GPIOD_SANDBOX_MASK;
 
 	return 0;
 }
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 10/15] dm: gpio: Add a way to update flags
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (8 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 09/15] gpio: sandbox: Make sandbox_gpio_set_flags() set all flags Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21 10:07   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 11/15] gpio: Replace direction_input() and direction_output() Simon Glass
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

It is convenient to be able to adjust some of the flags for a GPIO while
leaving others alone. Add a function for this.

Update dm_gpio_set_dir_flags() to make use of this.

Also update dm_gpio_set_value() to use this also, since this allows the
open-drain / open-source features to be implemented directly in the
driver, rather than using the uclass workaround.

Update the sandbox tests accordingly. This involves a lot of changes to
dm_test_gpio_opendrain_opensource() since we no-longer have the direciion
being reported differently depending on the open drain/open source flags.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/gpio-uclass.c |  65 ++++++++++++++-----
 include/asm-generic/gpio.h |  25 ++++++++
 test/dm/gpio.c             | 125 ++++++++++++++++++++++++++++++++-----
 3 files changed, 184 insertions(+), 31 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index aa0e3852122..05627ecdc30 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -568,6 +568,7 @@ int dm_gpio_get_value(const struct gpio_desc *desc)
 
 int dm_gpio_set_value(const struct gpio_desc *desc, int value)
 {
+	const struct dm_gpio_ops *ops;
 	int ret;
 
 	ret = check_reserved(desc, "set_value");
@@ -577,21 +578,33 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value)
 	if (desc->flags & GPIOD_ACTIVE_LOW)
 		value = !value;
 
+	/* GPIOD_ are directly managed by driver in update_flags */
+	ops = gpio_get_ops(desc->dev);
+	if (ops->update_flags) {
+		ulong flags = desc->flags;
+
+		if (value)
+			flags |= GPIOD_IS_OUT_ACTIVE;
+		else
+			flags &= ~GPIOD_IS_OUT_ACTIVE;
+		return ops->update_flags(desc->dev, desc->offset, flags);
+	}
+
 	/*
 	 * Emulate open drain by not actively driving the line high or
 	 * Emulate open source by not actively driving the line low
 	 */
 	if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
 	    (desc->flags & GPIOD_OPEN_SOURCE && !value))
-		return gpio_get_ops(desc->dev)->direction_input(desc->dev,
-								desc->offset);
+		return ops->direction_input(desc->dev, desc->offset);
 	else if (desc->flags & GPIOD_OPEN_DRAIN ||
 		 desc->flags & GPIOD_OPEN_SOURCE)
-		return gpio_get_ops(desc->dev)->direction_output(desc->dev,
-								desc->offset,
-								value);
+		return ops->direction_output(desc->dev, desc->offset, value);
+
+	ret = ops->set_value(desc->dev, desc->offset, value);
+	if (ret)
+		return ret;
 
-	gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
 	return 0;
 }
 
@@ -619,6 +632,17 @@ static int check_dir_flags(ulong flags)
 	return 0;
 }
 
+/**
+ * _dm_gpio_update_flags() - Send flags to the driver
+ *
+ * This uses the best available method to send the given flags to the driver.
+ * Note that if flags & GPIOD_ACTIVE_LOW, the driver sees the opposite value
+ * of GPIOD_IS_OUT_ACTIVE.
+ *
+ * @desc:	GPIO description
+ * @flags:	flags value to set
+ * @return 0 if OK, -ve on error
+ */
 static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
 {
 	struct udevice *dev = desc->dev;
@@ -637,6 +661,11 @@ static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
 		return ret;
 	}
 
+	/* If active low, invert the output state */
+	if ((flags & (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) ==
+		(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW))
+		flags ^= GPIOD_IS_OUT_ACTIVE;
+
 	/* GPIOD_ are directly managed by driver in update_flags */
 	if (ops->update_flags) {
 		ret = ops->update_flags(dev, desc->offset, flags);
@@ -649,26 +678,34 @@ static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
 		}
 	}
 
-	/* save the flags also in descriptor */
-	if (!ret)
-		desc->flags = flags;
-
 	return ret;
 }
 
-int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set)
 {
+	ulong flags;
 	int ret;
 
 	ret = check_reserved(desc, "set_dir_flags");
 	if (ret)
 		return ret;
 
-	/* combine the requested flags (for IN/OUT) and the descriptor flags */
-	flags |= desc->flags;
+	flags = (desc->flags & ~clr) | set;
+
 	ret = _dm_gpio_update_flags(desc, flags);
+	if (ret)
+		return ret;
 
-	return ret;
+	/* save the flags also in descriptor */
+	desc->flags = flags;
+
+	return 0;
+}
+
+int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+{
+	/* combine the requested flags (for IN/OUT) and the descriptor flags */
+	return dm_gpio_clrset_flags(desc, 0, flags);
 }
 
 int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 30ff5feb160..4a657b1bd2b 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -128,6 +128,12 @@ struct gpio_desc {
 #define GPIOD_PULL_UP		BIT(7)	/* GPIO has pull-up enabled */
 #define GPIOD_PULL_DOWN		BIT(8)	/* GPIO has pull-down enabled */
 
+/* Flags for updating the above */
+#define GPIOD_MASK_DIR		(GPIOD_IS_OUT | GPIOD_IS_IN | \
+					GPIOD_IS_OUT_ACTIVE)
+#define GPIOD_MASK_DSTYPE	(GPIOD_OPEN_DRAIN | GPIOD_OPEN_SOURCE)
+#define GPIOD_MASK_PULL		(GPIOD_PULL_UP | GPIOD_PULL_DOWN)
+
 	uint offset;		/* GPIO offset within the device */
 	/*
 	 * We could consider adding the GPIO label in here. Possibly we could
@@ -659,6 +665,25 @@ int dm_gpio_get_value(const struct gpio_desc *desc);
 
 int dm_gpio_set_value(const struct gpio_desc *desc, int value);
 
+/**
+ * dm_gpio_clrset_flags() - Update flags
+ *
+ * This updates the flags as directled. Note that desc->flags is updated by this
+ * function on success. If any changes cannot be made, best efforts are made.
+ *
+ * By use of @clr and @set any of flags can be individually updated, or left
+ * alone
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @clr:	Flags to clear (GPIOD_...)
+ * @set:	Flags to set (GPIOD_...)
+ * @return 0 if OK, -EINVAL if the flags had obvious conflicts,
+ * -ERECALLCONFLICT if there was a non-obvious hardware conflict when attempting
+ * to set the flags
+ */
+int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set);
+
 /**
  * dm_gpio_set_dir_flags() - Set direction using description and added flags
  *
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index 43e868cd4ea..eaf78e9aed8 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -178,15 +178,15 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts)
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
 		    sandbox_gpio_get_flags(gpio_c, 0));
 
-	/* Set it as output high, should become an input */
+	/* Set it as output high */
 	ut_assertok(dm_gpio_set_value(&desc_list[0], 1));
-	ut_assertok(gpio_get_status(gpio_c, 0, buf, sizeof(buf)));
-	ut_asserteq_str("c0: input: 0 [x] a-test.test3-gpios0", buf);
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | GPIOD_IS_OUT_ACTIVE,
+		    sandbox_gpio_get_flags(gpio_c, 0));
 
-	/* Set it as output low, should become output low */
+	/* Set it as output low */
 	ut_assertok(dm_gpio_set_value(&desc_list[0], 0));
-	ut_assertok(gpio_get_status(gpio_c, 0, buf, sizeof(buf)));
-	ut_asserteq_str("c0: output: 0 [x] a-test.test3-gpios0", buf);
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
+		    sandbox_gpio_get_flags(gpio_c, 0));
 
 	/* GPIO 1 is (GPIO_OUT|GPIO_OPEN_SOURCE) */
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
@@ -197,13 +197,21 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts)
 	ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf)));
 	ut_asserteq_str("c1: output: 1 [x] a-test.test3-gpios1", buf);
 
-	/* Set it as output low, should become an input */
+	/* Set it as output low */
 	ut_assertok(dm_gpio_set_value(&desc_list[1], 0));
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
+		    sandbox_gpio_get_flags(gpio_c, 1));
+
 	ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf)));
-	ut_asserteq_str("c1: input: 1 [x] a-test.test3-gpios1", buf);
+	ut_asserteq_str("c1: output: 0 [x] a-test.test3-gpios1", buf);
 
-	/* GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN) */
-	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
+	/*
+	 * GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN). Looking at it
+	 * directlt from the driver, we get GPIOD_IS_OUT_ACTIVE also, since it
+	 * is active low
+	 */
+	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN |
+		    GPIOD_IS_OUT_ACTIVE,
 		    sandbox_gpio_get_flags(gpio_c, 6));
 
 	/* Set it as output high, should become output low */
@@ -211,19 +219,21 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts)
 	ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf)));
 	ut_asserteq_str("c6: output: 0 [x] a-test.test3-gpios6", buf);
 
-	/* Set it as output low, should become an input */
+	/* Set it as output low */
 	ut_assertok(dm_gpio_set_value(&desc_list[6], 0));
-	ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf)));
-	ut_asserteq_str("c6: input: 0 [x] a-test.test3-gpios6", buf);
+	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN |
+		    GPIOD_IS_OUT_ACTIVE,
+		    sandbox_gpio_get_flags(gpio_c, 6));
 
 	/* GPIO 7 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_SOURCE) */
-	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
+	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE |
+		    GPIOD_IS_OUT_ACTIVE,
 		    sandbox_gpio_get_flags(gpio_c, 7));
 
-	/* Set it as output high, should become an input */
+	/* Set it as output high */
 	ut_assertok(dm_gpio_set_value(&desc_list[7], 1));
-	ut_assertok(gpio_get_status(gpio_c, 7, buf, sizeof(buf)));
-	ut_asserteq_str("c7: input: 0 [x] a-test.test3-gpios7", buf);
+	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
+		    sandbox_gpio_get_flags(gpio_c, 7));
 
 	/* Set it as output low, should become output high */
 	ut_assertok(dm_gpio_set_value(&desc_list[7], 0));
@@ -582,3 +592,84 @@ static int dm_test_gpio_devm(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_gpio_devm, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int dm_test_clrset_flags(struct unit_test_state *uts)
+{
+	struct gpio_desc desc;
+	struct udevice *dev;
+	ulong flags;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+	ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0));
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_OUT));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_OUT, flags);
+	ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, flags);
+	ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+	ut_asserteq(1, dm_gpio_get_value(&desc));
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_IN, flags & GPIOD_MASK_DIR);
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_PULL,
+					 GPIOD_PULL_UP));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
+
+	/* Check we cannot set both PULL_UP and PULL_DOWN */
+	ut_asserteq(-EINVAL, dm_gpio_clrset_flags(&desc, 0, GPIOD_PULL_DOWN));
+
+	return 0;
+}
+DM_TEST(dm_test_clrset_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_clrset_flags_invert(struct unit_test_state *uts)
+{
+	struct gpio_desc desc;
+	struct udevice *dev;
+	ulong flags;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+	ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc,
+					 GPIOD_IS_OUT | GPIOD_ACTIVE_LOW));
+
+	/*
+	 * From this size we see it as 0 (active low), but the sandbox driver
+	 * sees the pin value high
+	 */
+	ut_asserteq(0, dm_gpio_get_value(&desc));
+	ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	ut_assertok(dm_gpio_set_value(&desc, 1));
+	ut_asserteq(1, dm_gpio_get_value(&desc));
+	ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	/* Do the same with dm_gpio_clrset_flags() */
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0));
+	ut_asserteq(0, dm_gpio_get_value(&desc));
+	ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE));
+	ut_asserteq(1, dm_gpio_get_value(&desc));
+	ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE,
+		    flags);
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, flags);
+
+	return 0;
+}
+DM_TEST(dm_test_clrset_flags_invert, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 11/15] gpio: Replace direction_input() and direction_output()
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (9 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 10/15] dm: gpio: Add a way to update flags Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21 10:12   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 12/15] gpio: Use an 'ops' variable everywhere Simon Glass
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

The new update_flags() method is more flexible since it allows the
driver to see the full flags all at once. Use that in preference to these
two functions. Add comments to that effect.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/gpio-uclass.c | 15 ++++++---------
 include/asm-generic/gpio.h | 26 +++++++++++++++++++++++++-
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 05627ecdc30..68ed65d0899 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -512,13 +512,10 @@ int gpio_direction_input(unsigned gpio)
 	int ret;
 
 	ret = gpio_to_device(gpio, &desc);
-	if (ret)
-		return ret;
-	ret = check_reserved(&desc, "dir_input");
 	if (ret)
 		return ret;
 
-	return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset);
+	return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN);
 }
 
 /**
@@ -533,17 +530,17 @@ int gpio_direction_input(unsigned gpio)
 int gpio_direction_output(unsigned gpio, int value)
 {
 	struct gpio_desc desc;
+	ulong flags;
 	int ret;
 
 	ret = gpio_to_device(gpio, &desc);
-	if (ret)
-		return ret;
-	ret = check_reserved(&desc, "dir_output");
 	if (ret)
 		return ret;
 
-	return gpio_get_ops(desc.dev)->direction_output(desc.dev,
-							desc.offset, value);
+	flags = GPIOD_IS_OUT;
+	if (value)
+		flags |= GPIOD_IS_OUT_ACTIVE;
+	return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, flags);
 }
 
 static int _gpio_get_value(const struct gpio_desc *desc)
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 4a657b1bd2b..4628d937259 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -266,10 +266,32 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
 struct dm_gpio_ops {
 	int (*request)(struct udevice *dev, unsigned offset, const char *label);
 	int (*rfree)(struct udevice *dev, unsigned int offset);
+
+	/**
+	 * direction_input() - deprecated
+	 *
+	 * Equivalent to update_flags(...GPIOD_IS_IN)
+	 */
 	int (*direction_input)(struct udevice *dev, unsigned offset);
+
+	/**
+	 * direction_output() - deprecated
+	 *
+	 * Equivalent to update_flags(...GPIOD_IS_OUT) with GPIOD_IS_OUT_ACTIVE
+	 * also set if @value
+	 */
 	int (*direction_output)(struct udevice *dev, unsigned offset,
 				int value);
+
 	int (*get_value)(struct udevice *dev, unsigned offset);
+
+	/**
+	 * set_value() - Sets the GPIO value of an output
+	 *
+	 * If the driver provides an @update_flags() method then that is used
+	 * in preference to this, with GPIOD_IS_OUT_ACTIVE set according to
+	 * @value.
+	 */
 	int (*set_value)(struct udevice *dev, unsigned offset, int value);
 	/**
 	 * get_function() Get the GPIO function
@@ -328,7 +350,9 @@ struct dm_gpio_ops {
 	 * uclass, so the driver always sees the value that should be set at the
 	 * pin (1=high, 0=low).
 	 *
-	 * This method is optional.
+	 * This method is required and should be implemented by new drivers. At
+	 * some point, it will supersede direction_input() and
+	 * direction_output(), which wil be removed.
 	 *
 	 * @dev:	GPIO device
 	 * @offset:	GPIO offset within that device
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 12/15] gpio: Use an 'ops' variable everywhere
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (10 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 11/15] gpio: Replace direction_input() and direction_output() Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21 10:13   ` Patrick DELAUNAY
  2021-01-15 14:04 ` [PATCH 13/15] gpio: x86: Drop the deprecated methods in intel_gpio Simon Glass
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

Update this driver to use the common method of putting the driver
operations in an 'ops' variable install of calling gpio_get_ops()
repeatedly. Make it const since operations do not change.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/gpio/gpio-uclass.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 68ed65d0899..77b40263bbd 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -219,7 +219,7 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
 static int gpio_find_and_xlate(struct gpio_desc *desc,
 			       struct ofnode_phandle_args *args)
 {
-	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 
 	if (ops->xlate)
 		return ops->xlate(desc->dev, desc, args);
@@ -352,6 +352,7 @@ int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc)
 
 int dm_gpio_request(struct gpio_desc *desc, const char *label)
 {
+	const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 	struct udevice *dev = desc->dev;
 	struct gpio_dev_priv *uc_priv;
 	char *str;
@@ -363,8 +364,8 @@ int dm_gpio_request(struct gpio_desc *desc, const char *label)
 	str = strdup(label);
 	if (!str)
 		return -ENOMEM;
-	if (gpio_get_ops(dev)->request) {
-		ret = gpio_get_ops(dev)->request(dev, desc->offset, label);
+	if (ops->request) {
+		ret = ops->request(dev, desc->offset, label);
 		if (ret) {
 			free(str);
 			return ret;
@@ -441,14 +442,15 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...)
 
 int _dm_gpio_free(struct udevice *dev, uint offset)
 {
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 	struct gpio_dev_priv *uc_priv;
 	int ret;
 
 	uc_priv = dev_get_uclass_priv(dev);
 	if (!uc_priv->name[offset])
 		return -ENXIO;
-	if (gpio_get_ops(dev)->rfree) {
-		ret = gpio_get_ops(dev)->rfree(dev, offset);
+	if (ops->rfree) {
+		ret = ops->rfree(dev, offset);
 		if (ret)
 			return ret;
 	}
@@ -545,9 +547,10 @@ int gpio_direction_output(unsigned gpio, int value)
 
 static int _gpio_get_value(const struct gpio_desc *desc)
 {
+	const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 	int value;
 
-	value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
+	value = ops->get_value(desc->dev, desc->offset);
 
 	return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
 }
@@ -643,7 +646,7 @@ static int check_dir_flags(ulong flags)
 static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
 {
 	struct udevice *dev = desc->dev;
-	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	int ret = 0;
 
@@ -709,7 +712,7 @@ int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
 	struct udevice *dev = desc->dev;
 	int ret, value;
-	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 	ulong flags;
 
 	ret = check_reserved(desc, "get_flags");
@@ -807,7 +810,7 @@ static int get_function(struct udevice *dev, int offset, bool skip_unused,
 			const char **namep)
 {
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 
 	BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
 	if (!device_active(dev))
@@ -844,7 +847,7 @@ int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
 
 int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
 {
-	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 	struct gpio_dev_priv *priv;
 	char *str = buf;
 	int func;
@@ -884,7 +887,7 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
 #if CONFIG_IS_ENABLED(ACPIGEN)
 int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio)
 {
-	struct dm_gpio_ops *ops;
+	const struct dm_gpio_ops *ops;
 
 	memset(gpio, '\0', sizeof(*gpio));
 	if (!dm_gpio_is_valid(desc)) {
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 13/15] gpio: x86: Drop the deprecated methods in intel_gpio
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (11 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 12/15] gpio: Use an 'ops' variable everywhere Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-15 14:04 ` [PATCH 14/15] gpio: sandbox: Track whether a GPIO is driven Simon Glass
  2021-01-15 14:05 ` [PATCH 15/15] gpio: Add a way to read 3-way strapping pins Simon Glass
  14 siblings, 0 replies; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

We don't need to implement direction_input() and direction_output()
anymore. Drop them and use update_flags() instead.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/x86/include/asm/intel_pinctrl_defs.h |  5 ++
 drivers/gpio/intel_gpio.c                 | 72 ++++++++++++-----------
 2 files changed, 43 insertions(+), 34 deletions(-)

diff --git a/arch/x86/include/asm/intel_pinctrl_defs.h b/arch/x86/include/asm/intel_pinctrl_defs.h
index 1ea141f082f..5d83d24bae2 100644
--- a/arch/x86/include/asm/intel_pinctrl_defs.h
+++ b/arch/x86/include/asm/intel_pinctrl_defs.h
@@ -11,6 +11,11 @@
 
 /* This file is included by device trees, so avoid BIT() macros */
 
+#define GPIO_DW_SIZE(x)			(sizeof(u32) * (x))
+#define PAD_CFG_OFFSET(x, dw_num)	((x) + GPIO_DW_SIZE(dw_num))
+#define PAD_CFG0_OFFSET(x)		PAD_CFG_OFFSET(x, 0)
+#define PAD_CFG1_OFFSET(x)		PAD_CFG_OFFSET(x, 1)
+
 #define PAD_CFG0_TX_STATE_BIT		0
 #define PAD_CFG0_TX_STATE		(1 << PAD_CFG0_TX_STATE_BIT)
 #define PAD_CFG0_RX_STATE_BIT		1
diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c
index eda95485c93..d596bed2465 100644
--- a/drivers/gpio/intel_gpio.c
+++ b/drivers/gpio/intel_gpio.c
@@ -3,6 +3,8 @@
  * Copyright 2019 Google LLC
  */
 
+#define LOG_CATEGORY	UCLASS_GPIO
+
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
@@ -23,38 +25,6 @@
 #include <dm/acpi.h>
 #include <dt-bindings/gpio/x86-gpio.h>
 
-static int intel_gpio_direction_input(struct udevice *dev, uint offset)
-{
-	struct udevice *pinctrl = dev_get_parent(dev);
-	uint config_offset;
-
-	config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
-
-	pcr_clrsetbits32(pinctrl, config_offset,
-			 PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
-				  PAD_CFG0_RX_DISABLE,
-			 PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE);
-
-	return 0;
-}
-
-static int intel_gpio_direction_output(struct udevice *dev, uint offset,
-				       int value)
-{
-	struct udevice *pinctrl = dev_get_parent(dev);
-	uint config_offset;
-
-	config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
-
-	pcr_clrsetbits32(pinctrl, config_offset,
-			 PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
-				  PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE,
-			 PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE |
-				  (value ? PAD_CFG0_TX_STATE : 0));
-
-	return 0;
-}
-
 static int intel_gpio_get_value(struct udevice *dev, uint offset)
 {
 	struct udevice *pinctrl = dev_get_parent(dev);
@@ -130,6 +100,41 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc,
 	return 0;
 }
 
+static int intel_gpio_update_flags(struct udevice *dev, unsigned int offset,
+				   ulong flags)
+{
+	struct udevice *pinctrl = dev_get_parent(dev);
+	u32 bic0 = 0, bic1 = 0;
+	u32 or0, or1;
+	uint config_offset;
+
+	config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
+
+	if (flags & GPIOD_IS_OUT) {
+		bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
+			PAD_CFG0_TX_DISABLE;
+		or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE;
+	} else if (flags & GPIOD_IS_IN) {
+		bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
+			PAD_CFG0_RX_DISABLE;
+		or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE;
+	}
+	if (flags & GPIOD_PULL_UP) {
+		bic1 |= PAD_CFG1_PULL_MASK;
+		or1 |= PAD_CFG1_PULL_UP_20K;
+	} else if (flags & GPIOD_PULL_DOWN) {
+		bic1 |= PAD_CFG1_PULL_MASK;
+		or1 |= PAD_CFG1_PULL_DN_20K;
+	}
+
+	pcr_clrsetbits32(pinctrl, PAD_CFG0_OFFSET(config_offset), bic0, or0);
+	pcr_clrsetbits32(pinctrl, PAD_CFG1_OFFSET(config_offset), bic1, or1);
+	log_debug("%s: flags=%lx, offset=%x, config_offset=%x, %x/%x %x/%x\n",
+		  dev->name, flags, offset, config_offset, bic0, or0, bic1, or1);
+
+	return 0;
+}
+
 #if CONFIG_IS_ENABLED(ACPIGEN)
 static int intel_gpio_get_acpi(const struct gpio_desc *desc,
 			       struct acpi_gpio *gpio)
@@ -177,12 +182,11 @@ static int intel_gpio_of_to_plat(struct udevice *dev)
 }
 
 static const struct dm_gpio_ops gpio_intel_ops = {
-	.direction_input	= intel_gpio_direction_input,
-	.direction_output	= intel_gpio_direction_output,
 	.get_value		= intel_gpio_get_value,
 	.set_value		= intel_gpio_set_value,
 	.get_function		= intel_gpio_get_function,
 	.xlate			= intel_gpio_xlate,
+	.update_flags		= intel_gpio_update_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
 	.get_acpi		= intel_gpio_get_acpi,
 #endif
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 14/15] gpio: sandbox: Track whether a GPIO is driven
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (12 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 13/15] gpio: x86: Drop the deprecated methods in intel_gpio Simon Glass
@ 2021-01-15 14:04 ` Simon Glass
  2021-01-21 10:19   ` Patrick DELAUNAY
  2021-01-15 14:05 ` [PATCH 15/15] gpio: Add a way to read 3-way strapping pins Simon Glass
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:04 UTC (permalink / raw)
  To: u-boot

Add a new flag to keep track of whether sandbox is driving the pin, or
whether it is expecting an input signal. If it is driving, then the value
of the pin is the value being driven (0 or 1). If not driving, then we
consider the value 0, since we don't currently handle things like pull-ups
yet.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/sandbox/include/asm/gpio.h |  3 ++-
 drivers/gpio/sandbox.c          | 21 +++++++++++++++------
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index 3f267797644..edf78cb4131 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -25,8 +25,9 @@
 
 /* Our own private GPIO flags, which musn't conflict with GPIOD_... */
 #define GPIOD_EXT_HIGH		BIT(20)	/* external source is high (else low) */
+#define GPIOD_EXT_DRIVEN	BIT(21)	/* external source is driven */
 
-#define GPIOD_SANDBOX_MASK	BIT(20)
+#define GPIOD_SANDBOX_MASK	GENMASK(21, 20)
 
 /**
  * Return the simulated value of a GPIO (used only in sandbox test code)
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 11d4757abbb..b32f7ac529b 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -76,16 +76,22 @@ static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
 {
 	struct gpio_state *state = get_gpio_state(dev, offset);
+	bool val;
 
 	if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
 		debug("sandbox_gpio: get_value on output gpio %u\n", offset);
 
-	return state->flags & GPIOD_EXT_HIGH ? true : false;
+	if (state->flags & GPIOD_EXT_DRIVEN)
+		val = state->flags & GPIOD_EXT_HIGH;
+	else
+		val = false;
+
+	return val;
 }
 
 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
-	set_gpio_flag(dev, offset, GPIOD_EXT_HIGH, value);
+	set_gpio_flag(dev, offset, GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
 
 	return 0;
 }
@@ -142,8 +148,8 @@ static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
 	ret = sandbox_gpio_set_direction(dev, offset, 1);
 	if (ret)
 		return ret;
-	ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH,
-			    value);
+	ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
+			    GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
 	if (ret)
 		return ret;
 
@@ -171,8 +177,8 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 		return -1;
 	}
 
-	ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH,
-			    value);
+	ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
+			    GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
 	if (ret)
 		return ret;
 
@@ -217,10 +223,13 @@ static int sb_gpio_update_flags(struct udevice *dev, uint offset, ulong flags)
 	struct gpio_state *state = get_gpio_state(dev, offset);
 
 	if (flags & GPIOD_IS_OUT) {
+		flags |= GPIOD_EXT_DRIVEN;
 		if (flags & GPIOD_IS_OUT_ACTIVE)
 			flags |= GPIOD_EXT_HIGH;
 		else
 			flags &= ~GPIOD_EXT_HIGH;
+	} else {
+		flags |= state->flags & GPIOD_SANDBOX_MASK;
 	}
 	state->flags = flags;
 
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 15/15] gpio: Add a way to read 3-way strapping pins
  2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
                   ` (13 preceding siblings ...)
  2021-01-15 14:04 ` [PATCH 14/15] gpio: sandbox: Track whether a GPIO is driven Simon Glass
@ 2021-01-15 14:05 ` Simon Glass
  2021-01-21 10:52   ` Patrick DELAUNAY
  14 siblings, 1 reply; 34+ messages in thread
From: Simon Glass @ 2021-01-15 14:05 UTC (permalink / raw)
  To: u-boot

Using the internal vs. external pull resistors it is possible to get
27 different combinations from 3 strapping pins. Add an implementation
of this.

This involves updating the sandbox GPIO driver to model external and
(weaker) internal pull resistors. The get_value() method now takes account
of what is driving a pin:

   sandbox: GPIOD_EXT_DRIVEN - in which case GPIO_EXT_HIGH provides the
          value
   outside source - in which case GPIO_EXT_PULL_UP/DOWN indicates the
          external state and we work the final state using those flags and
          the internal GPIOD_PULL_UP/DOWN flags

Of course the outside source does not really exist in sandbox. We are just
modelling it for test purpose.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/sandbox/include/asm/gpio.h |  5 +-
 drivers/gpio/gpio-uclass.c      | 78 ++++++++++++++++++++++++++
 drivers/gpio/sandbox.c          | 13 +++--
 include/asm-generic/gpio.h      | 37 +++++++++++++
 test/dm/gpio.c                  | 98 +++++++++++++++++++++++++++++++++
 5 files changed, 226 insertions(+), 5 deletions(-)

diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index edf78cb4131..097abfb299c 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -26,8 +26,11 @@
 /* Our own private GPIO flags, which musn't conflict with GPIOD_... */
 #define GPIOD_EXT_HIGH		BIT(20)	/* external source is high (else low) */
 #define GPIOD_EXT_DRIVEN	BIT(21)	/* external source is driven */
+#define GPIOD_EXT_PULL_UP	BIT(22)	/* GPIO has external pull-up */
+#define GPIOD_EXT_PULL_DOWN	BIT(23)	/* GPIO has external pull-down */
 
-#define GPIOD_SANDBOX_MASK	GENMASK(21, 20)
+#define GPIOD_EXT_PULL		(BIT(21) | BIT(22))
+#define GPIOD_SANDBOX_MASK	GENMASK(23, 20)
 
 /**
  * Return the simulated value of a GPIO (used only in sandbox test code)
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 77b40263bbd..984c07d1dfa 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2013 Google, Inc
  */
 
+#define LOG_CATEGORY	UCLASS_GPIO
+
 #include <common.h>
 #include <dm.h>
 #include <log.h>
@@ -20,6 +22,7 @@
 #include <dm/device_compat.h>
 #include <linux/bug.h>
 #include <linux/ctype.h>
+#include <linux/delay.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -708,6 +711,21 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 	return dm_gpio_clrset_flags(desc, 0, flags);
 }
 
+int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
+			  ulong set)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		ret = dm_gpio_clrset_flags(&desc[i], clr, set);
+		if (ret)
+			return log_ret(ret);
+	}
+
+	return 0;
+}
+
 int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
 	struct udevice *dev = desc->dev;
@@ -974,6 +992,66 @@ int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count)
 	return vector;
 }
 
+int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
+				    int count)
+{
+	static const char tristate[] = "01z";
+	enum {
+		PULLUP,
+		PULLDOWN,
+
+		NUM_OPTIONS,
+	};
+	int vals[NUM_OPTIONS];
+	uint mask;
+	uint vector = 0;
+	int ret, i;
+
+	for (i = 0; i < NUM_OPTIONS; i++) {
+		uint flags = GPIOD_IS_IN;
+
+		flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
+		ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
+					    flags);
+		if (ret)
+			return log_msg_ret("pu", ret);
+
+		/* Give the lines time to settle */
+		udelay(10);
+
+		ret = dm_gpio_get_values_as_int(desc_list, count);
+		if (ret < 0)
+			return log_msg_ret("get1", ret);
+		vals[i] = ret;
+	}
+
+	log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count);
+	for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) {
+		uint pd = vals[PULLDOWN] & mask ? 1 : 0;
+		uint pu = vals[PULLUP] & mask ? 1 : 0;
+		uint digit;
+
+		/*
+		 * Get value with internal pulldown active. If this is 1 then
+		 * there is a stronger external pullup, which we call 1. If not
+		 * then call it 0.
+		 */
+		digit = pd;
+
+		/*
+		 * If the values differ then the pin is floating so we call
+		 * this a 2.
+		 */
+		if (pu != pd)
+			digit |= 2;
+		log_debug("%c ", tristate[digit]);
+		vector = 3 * vector + digit;
+	}
+	log_debug("vector=%d\n", vector);
+
+	return vector;
+}
+
 /**
  * gpio_request_tail: common work for requesting a gpio.
  *
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index b32f7ac529b..56b339f5e3c 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -19,7 +19,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/sandbox-gpio.h>
 
-
 struct gpio_state {
 	const char *label;	/* label given by requester */
 	ulong flags;		/* flags (GPIOD_...) */
@@ -81,10 +80,16 @@ int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
 	if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
 		debug("sandbox_gpio: get_value on output gpio %u\n", offset);
 
-	if (state->flags & GPIOD_EXT_DRIVEN)
+	if (state->flags & GPIOD_EXT_DRIVEN) {
 		val = state->flags & GPIOD_EXT_HIGH;
-	else
-		val = false;
+	} else {
+		if (state->flags & GPIOD_EXT_PULL_UP)
+			val = true;
+		else if (state->flags & GPIOD_EXT_PULL_DOWN)
+			val = false;
+		else
+			val = state->flags & GPIOD_PULL_UP;
+	}
 
 	return val;
 }
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 4628d937259..1cf81a3fc7a 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -505,6 +505,28 @@ int gpio_get_values_as_int(const int *gpio_list);
  */
 int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count);
 
+/**
+ * dm_gpio_get_values_as_int_base3() - Create a base-3 int from a list of GPIOs
+ *
+ * This uses pull-ups/pull-downs to figure out whether a GPIO line is externally
+ * pulled down, pulled up or floating. This allows three different strap values
+ * for each pin.
+ *
+ * With this it is possible to obtain more combinations from the same number of
+ * strapping pins, when compared to dm_gpio_get_values_as_int(). The external
+ * pull resistors should be made stronger that the internal SoC pull resistors,
+ * for this to work.
+ *
+ * With 2 pins, 6 combinations are possible, compare with 4
+ * With 3 pins, 27 are possible, compared with 8
+ *
+ * @desc_list: List of GPIOs to collect
+ * @count: Number of GPIOs
+ * @return resulting integer value, or -ve on error
+ */
+int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
+				    int count);
+
 /**
  * gpio_claim_vector() - claim a number of GPIOs for input
  *
@@ -722,6 +744,21 @@ int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set);
  */
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
 
+/**
+ * dm_gpios_clrset_flags() - Sets flags for a set of GPIOs
+ *
+ * This clears and sets flags individually for each GPIO.
+ *
+ * @desc:	List of GPIOs to update
+ * @count:	Number of GPIOs in the list
+ * @clr:	Flags to clear (GPIOD_...), e.g. GPIOD_MASK_DIR if you are
+ *		changing the direction
+ * @set:	Flags to set (GPIOD_...)
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
+			  ulong set);
+
 /**
  * dm_gpio_get_flags() - Get direction flags
  *
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index eaf78e9aed8..726c1b6c44f 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -673,3 +673,101 @@ static int dm_test_clrset_flags_invert(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_clrset_flags_invert, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int set_gpios(struct unit_test_state *uts, struct gpio_desc *desc,
+		     int count, uint value)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		const uint mask = 1 << i;
+
+		ut_assertok(sandbox_gpio_set_value(desc[i].dev, desc[i].offset,
+						   value & mask));
+	}
+
+	return 0;
+}
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_gpio_get_values_as_int(struct unit_test_state *uts)
+{
+	const int gpio_count = 3;
+	struct gpio_desc desc[gpio_count];
+	struct udevice *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+
+	ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc,
+						 gpio_count, GPIOD_IS_IN));
+	ut_assertok(set_gpios(uts, desc, gpio_count, 0));
+	ut_asserteq(0, dm_gpio_get_values_as_int(desc, gpio_count));
+
+	ut_assertok(set_gpios(uts, desc, gpio_count, 5));
+	ut_asserteq(5, dm_gpio_get_values_as_int(desc, gpio_count));
+
+	ut_assertok(set_gpios(uts, desc, gpio_count, 7));
+	ut_asserteq(7, dm_gpio_get_values_as_int(desc, gpio_count));
+
+	return 0;
+}
+DM_TEST(dm_test_gpio_get_values_as_int,
+	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_gpio_get_values_as_int_base3(struct unit_test_state *uts)
+{
+	const int gpio_count = 3;
+	struct gpio_desc desc[gpio_count];
+	struct udevice *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+
+	ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc,
+						 gpio_count, GPIOD_IS_IN));
+
+	/*
+	 * First test the sandbox GPIO driver works as expected. The external
+	 * pull resistor should be stronger than the internal one.
+	 */
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset,
+			       GPIOD_IS_IN | GPIOD_EXT_PULL_UP | GPIOD_PULL_UP);
+	ut_asserteq(1, dm_gpio_get_value(desc));
+
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_IS_IN |
+			       GPIOD_EXT_PULL_DOWN | GPIOD_PULL_UP);
+	ut_asserteq(0, dm_gpio_get_value(desc));
+
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset,
+			       GPIOD_IS_IN | GPIOD_PULL_UP);
+	ut_asserteq(1, dm_gpio_get_value(desc));
+
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_PULL_DOWN);
+	ut_asserteq(0, dm_gpio_get_value(desc));
+
+	/*
+	 * Set up pins: pull-up (1), pull-down (0) and floating (2). This should
+	 * result in digits 2 0 1, i.e. 2 * 9 + 1 * 3 = 19
+	 */
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_EXT_PULL_UP);
+	sandbox_gpio_set_flags(desc[1].dev, desc[1].offset,
+			       GPIOD_EXT_PULL_DOWN);
+	sandbox_gpio_set_flags(desc[2].dev, desc[2].offset, 0);
+	ut_asserteq(19, dm_gpio_get_values_as_int_base3(desc, gpio_count));
+
+	/*
+	 * Set up pins: floating (2), pull-up (1) and pull-down (0). This should
+	 * result in digits 0 1 2, i.e. 1 * 3 + 2 = 5
+	 */
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, 0);
+	sandbox_gpio_set_flags(desc[1].dev, desc[1].offset, GPIOD_EXT_PULL_UP);
+	sandbox_gpio_set_flags(desc[2].dev, desc[2].offset,
+			       GPIOD_EXT_PULL_DOWN);
+	ut_asserteq(5, dm_gpio_get_values_as_int_base3(desc, gpio_count));
+
+	return 0;
+}
+DM_TEST(dm_test_gpio_get_values_as_int_base3,
+	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.30.0.284.gd98b1dd5eaa7-goog

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

* [PATCH 01/15] gpio: Disable functions not used with of-platdata
  2021-01-15 14:04 ` [PATCH 01/15] gpio: Disable functions not used with of-platdata Simon Glass
@ 2021-01-18 21:17   ` Pratyush Yadav
  2021-01-21  8:59   ` Patrick DELAUNAY
  1 sibling, 0 replies; 34+ messages in thread
From: Pratyush Yadav @ 2021-01-18 21:17 UTC (permalink / raw)
  To: u-boot

On 15/01/21 07:04AM, Simon Glass wrote:
> These functions use devicetree and cannot wprl with of-platdata, which has
					    ^^^^
Your right hand's offset is off by one ;-)

> no runtime devicetree.
> 
> If they are used, the current linker error is confusing, since it talks
> about missing functions in the bowels of driver model.
> 
> Avoid compiling these functions at all with of-platdata, so that a
> straightforward link error points to the problem.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  drivers/gpio/gpio-uclass.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
> index bad6b71e0c3..e84b68db772 100644
> --- a/drivers/gpio/gpio-uclass.c
> +++ b/drivers/gpio/gpio-uclass.c
> @@ -1023,6 +1023,7 @@ err:
>  	return ret;
>  }
>  
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
>  static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
>  				       int index, struct gpio_desc *desc,
>  				       int flags, bool add_index)
> @@ -1109,6 +1110,7 @@ int gpio_get_list_count(struct udevice *dev, const char *list_name)
>  
>  	return ret;
>  }
> +#endif /* OF_PLATDATA */
>  
>  int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
>  {
> -- 
> 2.30.0.284.gd98b1dd5eaa7-goog
> 

-- 
Regards,
Pratyush Yadav
Texas Instruments India

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

* [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags()
  2021-01-15 14:04 ` [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags() Simon Glass
@ 2021-01-18 21:39   ` Pratyush Yadav
  2021-01-21  9:01   ` Patrick DELAUNAY
  1 sibling, 0 replies; 34+ messages in thread
From: Pratyush Yadav @ 2021-01-18 21:39 UTC (permalink / raw)
  To: u-boot

Hi Simon,

> Subject: [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags()

Why not call it set_flags()? Matches up nicely with get_flags() in 
03/15.

On 15/01/21 07:04AM, Simon Glass wrote:
> The current method is a misnomer since it is also used (e.g. by stm32) to
> update pull settings and open source/open drain.
> 
> Rename it and expand the documentation to cover a few more details.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  drivers/gpio/gpio-uclass.c      | 16 ++++++++--------
>  drivers/gpio/sandbox.c          |  6 +++---
>  drivers/gpio/stm32_gpio.c       |  6 +++---
>  drivers/pinctrl/pinctrl-stmfx.c |  6 +++---
>  include/asm-generic/gpio.h      | 30 ++++++++++++++++++++++++------
>  test/dm/gpio.c                  |  8 ++++----
>  6 files changed, 45 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
> index e84b68db772..0862a28bf86 100644
> --- a/drivers/gpio/gpio-uclass.c
> +++ b/drivers/gpio/gpio-uclass.c
> @@ -619,7 +619,7 @@ static int check_dir_flags(ulong flags)
>  	return 0;
>  }
>  
> -static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
> +static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
>  {
>  	struct udevice *dev = desc->dev;
>  	struct dm_gpio_ops *ops = gpio_get_ops(dev);
> @@ -637,9 +637,9 @@ static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
>  		return ret;
>  	}
>  
> -	/* GPIOD_ are directly managed by driver in set_dir_flags*/
> -	if (ops->set_dir_flags) {
> -		ret = ops->set_dir_flags(dev, desc->offset, flags);
> +	/* GPIOD_ are directly managed by driver in update_flags */
> +	if (ops->update_flags) {
> +		ret = ops->update_flags(dev, desc->offset, flags);
>  	} else {
>  		if (flags & GPIOD_IS_OUT) {
>  			ret = ops->direction_output(dev, desc->offset,
> @@ -666,7 +666,7 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
>  
>  	/* combine the requested flags (for IN/OUT) and the descriptor flags */
>  	flags |= desc->flags;
> -	ret = _dm_gpio_set_dir_flags(desc, flags);
> +	ret = _dm_gpio_update_flags(desc, flags);
>  
>  	return ret;
>  }
> @@ -679,7 +679,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
>  	if (ret)
>  		return ret;
>  
> -	return _dm_gpio_set_dir_flags(desc, desc->flags);
> +	return _dm_gpio_update_flags(desc, desc->flags);
>  }
>  
>  int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags)
> @@ -1307,8 +1307,8 @@ static int gpio_post_bind(struct udevice *dev)
>  			ops->get_function += gd->reloc_off;
>  		if (ops->xlate)
>  			ops->xlate += gd->reloc_off;
> -		if (ops->set_dir_flags)
> -			ops->set_dir_flags += gd->reloc_off;
> +		if (ops->update_flags)
> +			ops->update_flags += gd->reloc_off;
>  		if (ops->get_dir_flags)
>  			ops->get_dir_flags += gd->reloc_off;
>  
> diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
> index dc8d506e8d4..029908dc9f9 100644
> --- a/drivers/gpio/sandbox.c
> +++ b/drivers/gpio/sandbox.c
> @@ -177,8 +177,8 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
>  	return 0;
>  }
>  
> -static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
> -				 ulong flags)
> +static int sb_gpio_update_flags(struct udevice *dev, unsigned int offset,
> +				ulong flags)
>  {
>  	ulong *dir_flags;
>  
> @@ -272,7 +272,7 @@ static const struct dm_gpio_ops gpio_sandbox_ops = {
>  	.set_value		= sb_gpio_set_value,
>  	.get_function		= sb_gpio_get_function,
>  	.xlate			= sb_gpio_xlate,
> -	.set_dir_flags		= sb_gpio_set_dir_flags,
> +	.update_flags		= sb_gpio_update_flags,
>  	.get_dir_flags		= sb_gpio_get_dir_flags,
>  #if CONFIG_IS_ENABLED(ACPIGEN)
>  	.get_acpi		= sb_gpio_get_acpi,
> diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
> index 79d55e812db..daae6ddb93f 100644
> --- a/drivers/gpio/stm32_gpio.c
> +++ b/drivers/gpio/stm32_gpio.c
> @@ -189,8 +189,8 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset)
>  	return GPIOF_FUNC;
>  }
>  
> -static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
> -				    ulong flags)
> +static int stm32_gpio_update_flags(struct udevice *dev, unsigned int offset,
> +				   ulong flags)
>  {
>  	struct stm32_gpio_priv *priv = dev_get_priv(dev);
>  	struct stm32_gpio_regs *regs = priv->regs;
> @@ -268,7 +268,7 @@ static const struct dm_gpio_ops gpio_stm32_ops = {
>  	.get_value		= stm32_gpio_get_value,
>  	.set_value		= stm32_gpio_set_value,
>  	.get_function		= stm32_gpio_get_function,
> -	.set_dir_flags		= stm32_gpio_set_dir_flags,
> +	.update_flags		= stm32_gpio_update_flags,
>  	.get_dir_flags		= stm32_gpio_get_dir_flags,
>  };
>  
> diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
> index 7cf08dbddd1..084d5cef7aa 100644
> --- a/drivers/pinctrl/pinctrl-stmfx.c
> +++ b/drivers/pinctrl/pinctrl-stmfx.c
> @@ -163,8 +163,8 @@ static int stmfx_gpio_direction_output(struct udevice *dev,
>  	return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1);
>  }
>  
> -static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
> -				    ulong flags)
> +static int stmfx_gpio_update_flags(struct udevice *dev, unsigned int offset,
> +				   ulong flags)
>  {
>  	int ret = -ENOTSUPP;
>  
> @@ -266,7 +266,7 @@ static const struct dm_gpio_ops stmfx_gpio_ops = {
>  	.get_function = stmfx_gpio_get_function,
>  	.direction_input = stmfx_gpio_direction_input,
>  	.direction_output = stmfx_gpio_direction_output,
> -	.set_dir_flags = stmfx_gpio_set_dir_flags,
> +	.update_flags = stmfx_gpio_update_flags,
>  	.get_dir_flags = stmfx_gpio_get_dir_flags,
>  };
>  
> diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
> index 82294cbdc57..4626e7d92ae 100644
> --- a/include/asm-generic/gpio.h
> +++ b/include/asm-generic/gpio.h
> @@ -301,20 +301,38 @@ struct dm_gpio_ops {
>  		     struct ofnode_phandle_args *args);
>  
>  	/**
> -	 * set_dir_flags() - Set GPIO dir flags
> +	 * update_flags() - Adjust GPIO flags
>  	 *
>  	 * This function should set up the GPIO configuration according to the
> -	 * information provide by the direction flags bitfield.
> +	 * information provide by @flags.

While we're here, might as well fix the typo. s/provide/provided/

> +	 *
> +	 * If any flags cannot be set (e.g. the driver or hardware does not
> +	 * support them or this particular GPIO does not have the requested
> +	 * feature), the driver should perform what changes it can. The uclass

"the driver should perform what changes it can" is very vague. Ideally 
it should either be "driver should return an error" or "driver should 
ignore those flags and reset them to 0". This will make the behavior of 
this function very clear to both implementers and callers.

> +	 * can read the current flags back with a call to get_dir_flags() if
> +	 * desired.
> +	 *
> +	 * The uclass checks that flags do not obviously conflict (e.g. input
> +	 * and output). If the driver finds other conflicts it should return
> +	 * -ERECALLCONFLICT
> +	 *
> +	 * Note that GPIOD_ACTIVE_LOW should be ignored, since the uclass
> +	 * adjusts for it automatically. For example, for an output GPIO,
> +	 * GPIOD_ACTIVE_LOW causes GPIOD_IS_OUT_ACTIVE to be inverted by the
> +	 * uclass, so the driver always sees the value that should be set at the
> +	 * pin (1=high, 0=low).
>  	 *
>  	 * This method is optional.
>  	 *
>  	 * @dev:	GPIO device
>  	 * @offset:	GPIO offset within that device
> -	 * @flags:	GPIO configuration to use
> -	 * @return 0 if OK, -ve on error
> +	 * @flags:	New flags value (GPIOD_...)
> +	 *
> +	 * @return 0 if OK, -ERECALLCONFLICT if flags conflict in some
> +	 *	non-obvious way and were not applied, other -ve on error
>  	 */
> -	int (*set_dir_flags)(struct udevice *dev, unsigned int offset,
> -			     ulong flags);
> +	int (*update_flags)(struct udevice *dev, unsigned int offset,
> +			    ulong flags);
>  
>  	/**
>  	 * get_dir_flags() - Get GPIO dir flags
> diff --git a/test/dm/gpio.c b/test/dm/gpio.c
> index d7b85e74ce5..a08c3590d71 100644
> --- a/test/dm/gpio.c
> +++ b/test/dm/gpio.c
> @@ -81,12 +81,12 @@ static int dm_test_gpio(struct unit_test_state *uts)
>  	/* Make it an open drain output, and reset it */
>  	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
>  		    sandbox_gpio_get_dir_flags(dev, offset));
> -	ut_assertok(ops->set_dir_flags(dev, offset,
> -				       GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
> +	ut_assertok(ops->update_flags(dev, offset,
> +				      GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
>  	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
>  		    sandbox_gpio_get_dir_flags(dev, offset));
> -	ut_assertok(ops->set_dir_flags(dev, offset,
> -				       GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
> +	ut_assertok(ops->update_flags(dev, offset,
> +				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
>  	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
>  		    sandbox_gpio_get_dir_flags(dev, offset));
>  

With these fixed,

Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

-- 
Regards,
Pratyush Yadav
Texas Instruments India

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

* [PATCH 03/15] dm: gpio: Rename get_dir_flags() method to get_flags()
  2021-01-15 14:04 ` [PATCH 03/15] dm: gpio: Rename get_dir_flags() method to get_flags() Simon Glass
@ 2021-01-18 21:54   ` Pratyush Yadav
  2021-01-21  9:02   ` Patrick DELAUNAY
  1 sibling, 0 replies; 34+ messages in thread
From: Pratyush Yadav @ 2021-01-18 21:54 UTC (permalink / raw)
  To: u-boot

On 15/01/21 07:04AM, Simon Glass wrote:
> It is more useful to be able to read all the flags, not just the direction
> ones. In fact this is what the STM32 driver does. Update the method name
> to reflect this.
> 
> Tweak the docs a little and use 'flagsp' as the return argument, as is
> common in driver model, to indicate it returns a value.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  drivers/gpio/gpio-uclass.c      | 30 +++++++++++++++---------------
>  drivers/gpio/sandbox.c          |  8 ++++----
>  drivers/gpio/stm32_gpio.c       |  8 ++++----
>  drivers/pinctrl/pinctrl-stmfx.c |  8 ++++----
>  include/asm-generic/gpio.h      | 13 +++++++------
>  5 files changed, 34 insertions(+), 33 deletions(-)
> 

Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

-- 
Regards,
Pratyush Yadav
Texas Instruments India

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

* [PATCH 04/15] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags()
  2021-01-15 14:04 ` [PATCH 04/15] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags() Simon Glass
@ 2021-01-18 21:57   ` Pratyush Yadav
  2021-01-21  9:05   ` Patrick DELAUNAY
  1 sibling, 0 replies; 34+ messages in thread
From: Pratyush Yadav @ 2021-01-18 21:57 UTC (permalink / raw)
  To: u-boot

On 15/01/21 07:04AM, Simon Glass wrote:
> This function can be used to get any flags, not just direction flags.
> Rename it to avoid confusion.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  drivers/gpio/gpio-uclass.c |  2 +-
>  include/asm-generic/gpio.h |  4 ++--
>  test/dm/gpio.c             | 12 ++++++------
>  3 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
> index 83d3cf0a6b3..864a9003245 100644
> --- a/drivers/gpio/gpio-uclass.c
> +++ b/drivers/gpio/gpio-uclass.c
> @@ -682,7 +682,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
>  	return _dm_gpio_update_flags(desc, desc->flags);
>  }
>  
> -int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flagsp)
> +int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
>  {
>  	struct udevice *dev = desc->dev;
>  	int ret, value;
> diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
> index 48e042dc44b..5ecb73c138d 100644
> --- a/include/asm-generic/gpio.h
> +++ b/include/asm-generic/gpio.h
> @@ -685,7 +685,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc);
>  int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
>  
>  /**
> - * dm_gpio_get_dir_flags() - Get direction flags
> + * dm_gpio_get_flags() - Get direction flags

s/Get direction flags/Get flags/

With this fixed,

Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

-- 
Regards,
Pratyush Yadav
Texas Instruments India

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

* [PATCH 01/15] gpio: Disable functions not used with of-platdata
  2021-01-15 14:04 ` [PATCH 01/15] gpio: Disable functions not used with of-platdata Simon Glass
  2021-01-18 21:17   ` Pratyush Yadav
@ 2021-01-21  8:59   ` Patrick DELAUNAY
  1 sibling, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  8:59 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> These functions use devicetree and cannot wprl with of-platdata, which has

wprl

> no runtime devicetree.
>
> If they are used, the current linker error is confusing, since it talks
> about missing functions in the bowels of driver model.
>
> Avoid compiling these functions at all with of-platdata, so that a
> straightforward link error points to the problem.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/gpio-uclass.c | 2 ++
>   1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
> index bad6b71e0c3..e84b68db772 100644
> --- a/drivers/gpio/gpio-uclass.c
> +++ b/drivers/gpio/gpio-uclass.c
> @@ -1023,6 +1023,7 @@ err:
>   	return ret;
>   }
>   
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
>   static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
>   				       int index, struct gpio_desc *desc,
>   				       int flags, bool add_index)
> @@ -1109,6 +1110,7 @@ int gpio_get_list_count(struct udevice *dev, const char *list_name)
>   
>   	return ret;
>   }
> +#endif /* OF_PLATDATA */
>   
>   int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
>   {


Except the commit message


Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags()
  2021-01-15 14:04 ` [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags() Simon Glass
  2021-01-18 21:39   ` Pratyush Yadav
@ 2021-01-21  9:01   ` Patrick DELAUNAY
  1 sibling, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  9:01 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> The current method is a misnomer since it is also used (e.g. by stm32) to
> update pull settings and open source/open drain.
>
> Rename it and expand the documentation to cover a few more details.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/gpio-uclass.c      | 16 ++++++++--------
>   drivers/gpio/sandbox.c          |  6 +++---
>   drivers/gpio/stm32_gpio.c       |  6 +++---
>   drivers/pinctrl/pinctrl-stmfx.c |  6 +++---
>   include/asm-generic/gpio.h      | 30 ++++++++++++++++++++++++------
>   test/dm/gpio.c                  |  8 ++++----
>   6 files changed, 45 insertions(+), 27 deletions(-)
>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 03/15] dm: gpio: Rename get_dir_flags() method to get_flags()
  2021-01-15 14:04 ` [PATCH 03/15] dm: gpio: Rename get_dir_flags() method to get_flags() Simon Glass
  2021-01-18 21:54   ` Pratyush Yadav
@ 2021-01-21  9:02   ` Patrick DELAUNAY
  1 sibling, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  9:02 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> It is more useful to be able to read all the flags, not just the direction
> ones. In fact this is what the STM32 driver does. Update the method name
> to reflect this.
>
> Tweak the docs a little and use 'flagsp' as the return argument, as is
> common in driver model, to indicate it returns a value.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/gpio-uclass.c      | 30 +++++++++++++++---------------
>   drivers/gpio/sandbox.c          |  8 ++++----
>   drivers/gpio/stm32_gpio.c       |  8 ++++----
>   drivers/pinctrl/pinctrl-stmfx.c |  8 ++++----
>   include/asm-generic/gpio.h      | 13 +++++++------
>   5 files changed, 34 insertions(+), 33 deletions(-)
>

Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 04/15] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags()
  2021-01-15 14:04 ` [PATCH 04/15] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags() Simon Glass
  2021-01-18 21:57   ` Pratyush Yadav
@ 2021-01-21  9:05   ` Patrick DELAUNAY
  1 sibling, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  9:05 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> This function can be used to get any flags, not just direction flags.
> Rename it to avoid confusion.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/gpio-uclass.c |  2 +-
>   include/asm-generic/gpio.h |  4 ++--
>   test/dm/gpio.c             | 12 ++++++------
>   3 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
> index 83d3cf0a6b3..864a9003245 100644
> --- a/drivers/gpio/gpio-uclass.c
> +++ b/drivers/gpio/gpio-uclass.c
> @@ -682,7 +682,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
>   	return _dm_gpio_update_flags(desc, desc->flags);
>   }
>   
> -int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flagsp)
> +int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
>   {
>   	struct udevice *dev = desc->dev;
>   	int ret, value;
> diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
> index 48e042dc44b..5ecb73c138d 100644
> --- a/include/asm-generic/gpio.h
> +++ b/include/asm-generic/gpio.h
> @@ -685,7 +685,7 @@ int dm_gpio_set_dir(struct gpio_desc *desc);
>   int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
>   
>   /**
> - * dm_gpio_get_dir_flags() - Get direction flags
> + * dm_gpio_get_flags() - Get direction flags

Get GPIO flags

>    *
>    * read the current direction flags

read the current flags of the GPIO

>    *
> @@ -694,7 +694,7 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
>    * @flags:	place to put the used flags
>    * @return 0 if OK, -ve on error, in which case desc->flags is not updated
>    */
> -int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags);
> +int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flags);
>   
>   /**
>    * gpio_get_number() - Get the global GPIO number of a GPIO
> diff --git a/test/dm/gpio.c b/test/dm/gpio.c
> index a08c3590d71..6b9ec88ca2b 100644
> --- a/test/dm/gpio.c
> +++ b/test/dm/gpio.c
> @@ -397,22 +397,22 @@ static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts)
>   	ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list,
>   						 ARRAY_SIZE(desc_list), 0));
>   
> -	ut_assertok(dm_gpio_get_dir_flags(&desc_list[0], &flags));
> +	ut_assertok(dm_gpio_get_flags(&desc_list[0], &flags));
>   	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags);
>   
> -	ut_assertok(dm_gpio_get_dir_flags(&desc_list[1], &flags));
> +	ut_assertok(dm_gpio_get_flags(&desc_list[1], &flags));
>   	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags);
>   
> -	ut_assertok(dm_gpio_get_dir_flags(&desc_list[2], &flags));
> +	ut_assertok(dm_gpio_get_flags(&desc_list[2], &flags));
>   	ut_asserteq(GPIOD_IS_OUT, flags);
>   
> -	ut_assertok(dm_gpio_get_dir_flags(&desc_list[3], &flags));
> +	ut_assertok(dm_gpio_get_flags(&desc_list[3], &flags));
>   	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
>   
> -	ut_assertok(dm_gpio_get_dir_flags(&desc_list[4], &flags));
> +	ut_assertok(dm_gpio_get_flags(&desc_list[4], &flags));
>   	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags);
>   
> -	ut_assertok(dm_gpio_get_dir_flags(&desc_list[5], &flags));
> +	ut_assertok(dm_gpio_get_flags(&desc_list[5], &flags));
>   	ut_asserteq(GPIOD_IS_IN, flags);
>   
>   	ut_assertok(gpio_free_list(dev, desc_list, 6));


With the 2 comments


Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 05/15] gpio: Drop dm_gpio_set_dir()
  2021-01-15 14:04 ` [PATCH 05/15] gpio: Drop dm_gpio_set_dir() Simon Glass
@ 2021-01-21  9:06   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  9:06 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> This function is not used. Drop it.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/gpio-uclass.c | 11 -----------
>   include/asm-generic/gpio.h | 11 -----------
>   2 files changed, 22 deletions(-)
>

Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 06/15] gpio: sandbox: Rename GPIO dir_flags to flags
  2021-01-15 14:04 ` [PATCH 06/15] gpio: sandbox: Rename GPIO dir_flags to flags Simon Glass
@ 2021-01-21  9:14   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  9:14 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> Adjust the terminology in this driver to reflect that fact that all flags
> are handled, not just direction flags.
>
> Create a new access function to get the full GPIO state, not just the
> direction flags. Drop the static invalid_dir_flags since we can rely on a
> segfault if something is wrong.


If I remember, I add this static vairable? to avoid crash during normal 
pytest....

But it is more the case with the serie, it is better to drop it.


>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   arch/sandbox/include/asm/gpio.h |  8 ++--
>   drivers/gpio/sandbox.c          | 65 ++++++++++++++++++---------------
>   test/dm/gpio.c                  | 18 ++++-----
>   3 files changed, 49 insertions(+), 42 deletions(-)
>
> diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
> index df4ba4fb5f3..20d78296551 100644
> --- a/arch/sandbox/include/asm/gpio.h
> +++ b/arch/sandbox/include/asm/gpio.h
> @@ -69,17 +69,17 @@ int sandbox_gpio_set_direction(struct udevice *dev, unsigned int offset,
>    * @param offset	GPIO offset within bank
>    * @return dir_flags: bitfield accesses by GPIOD_ defines
>    */
> -ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset);
> +ulong sandbox_gpio_get_flags(struct udevice *dev, unsigned int offset);
>   


(...)

>   
> -/* Access routines for GPIO dir flags */
> -static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
> +/* Access routines for GPIO info */
> +static struct gpio_state *get_gpio_state(struct udevice *dev, uint offset)
>   {
>   	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>   	struct gpio_state *state = dev_get_priv(dev);
>   
>   	if (offset >= uc_priv->gpio_count) {
> -		static ulong invalid_dir_flags;
>   		printf("sandbox_gpio: error: invalid gpio %u\n", offset);
> -		return &invalid_dir_flags;
> +		return NULL;
>   	}
>   
> -	return &state[offset].dir_flags;
> +	return &state[offset];
> +}
> +
> +/* Access routines for GPIO dir flags */

/* Access routines for GPIO flags */


> +static ulong *get_gpio_flags(struct udevice *dev, unsigned int offset)
> +{
> +	struct gpio_state *state = get_gpio_state(dev, offset);
> +
> +	if (!state)
> +		return NULL;
> +
> +	return &state->flags;
>   
>   }
>   

(...)

With comment


Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 07/15] gpio: sandbox: Use a separate flag for the value
  2021-01-15 14:04 ` [PATCH 07/15] gpio: sandbox: Use a separate flag for the value Simon Glass
@ 2021-01-21  9:33   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  9:33 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> At present with the sandbox GPIO driver it is not possible to change the
> value of GPIOD_IS_OUT_ACTIVE unless the GPIO is an output. This makes it
> hard to test changing the flags since we need to be aware of the internal
> workings of the driver.
>
> The feature is designed to aid testing.
>
> Split this feature out into a separate sandbox-specific flag, so that the
> flags can change unimpeded. This will make it easier to allow updating the
> flags in a future patch.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   arch/sandbox/include/asm/gpio.h |  5 ++++
>   drivers/gpio/sandbox.c          | 43 +++++++++++++++------------------
>   2 files changed, 25 insertions(+), 23 deletions(-)
>
> diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
> index 20d78296551..3f267797644 100644
> --- a/arch/sandbox/include/asm/gpio.h
> +++ b/arch/sandbox/include/asm/gpio.h
> @@ -23,6 +23,11 @@
>    */
>   #include <asm-generic/gpio.h>
>   
> +/* Our own private GPIO flags, which musn't conflict with GPIOD_... */
> +#define GPIOD_EXT_HIGH		BIT(20)	/* external source is high (else low) */
> +
> +#define GPIOD_SANDBOX_MASK	BIT(20)
> +


This internal SANDBOX is starting at 20 to avoid possible conflict with? 
GPIOD_

It should start at BIT(32) and decreasing order to allow more possible

GPIOD for SANDOX or in include/asm/gpio.h


>   /**
>    * Return the simulated value of a GPIO (used only in sandbox test code)
>    *
> diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
> index 9ce5d823505..52e73e2300a 100644
> --- a/drivers/gpio/sandbox.c
> +++ b/drivers/gpio/sandbox.c
> @@ -59,12 +59,12 @@ static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
>   static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
>   			 int value)
>   {
> -	ulong *gpio = get_gpio_flags(dev, offset);
> +	struct gpio_state *state = get_gpio_state(dev, offset);
>   
>   	if (value)
> -		*gpio |= flag;
> +		state->flags |= flag;
>   	else
> -		*gpio &= ~flag;
> +		state->flags &= ~flag;
>   
>   	return 0;
>   }
> @@ -75,14 +75,19 @@ static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
>   
>   int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
>   {
> +	struct gpio_state *state = get_gpio_state(dev, offset);
> +
>   	if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
>   		debug("sandbox_gpio: get_value on output gpio %u\n", offset);
> -	return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
> +
> +	return state->flags & GPIOD_EXT_HIGH ? true : false;
>   }
>   
>   int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
>   {
> -	return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
> +	set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | GPIOD_EXT_HIGH, value);
> +
> +	return 0;
>   }
>   
>   int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
> @@ -93,19 +98,25 @@ int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
>   int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
>   {
>   	set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
> -	set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
> +	set_gpio_flag(dev, offset, GPIOD_IS_IN, !output);
>   
>   	return 0;
>   }
>   
>   ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset)
>   {
> -	return *get_gpio_flags(dev, offset);
> +	ulong flags = *get_gpio_flags(dev, offset);
> +
> +	return flags & ~GPIOD_SANDBOX_MASK;
>   }
>   
>   int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
>   {
> -	*get_gpio_flags(dev, offset) = flags;
> +	struct gpio_state *state = get_gpio_state(dev, offset);
> +
> +	if (flags & GPIOD_IS_OUT_ACTIVE)
> +		flags |= GPIOD_EXT_HIGH;


when you set GPIO out active, you force the EXT_HIGH for sandbox

but if the the test request LOW output it is not managed ?

I just ask if it is normal...

here the EXT_HIGH bit could be cleared with:

 ? else

      flags &= ~GPIOD_EXT_HIGH;

> +	state->flags = (state->flags & GPIOD_SANDBOX_MASK) | flags;
>   
>   	return 0;
>   }
> @@ -188,23 +199,9 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
>   
>   static int sb_gpio_update_flags(struct udevice *dev, uint offset, ulong newf)
>   {
> -	ulong *flags;
> -
>   	debug("%s: offset:%u, flags = %lx\n", __func__, offset, newf);
>   
> -	flags = get_gpio_flags(dev, offset);
> -
> -	/*
> -	 * For testing purposes keep the output value when switching to input.
> -	 * This allows us to manipulate the input value via the gpio command.
> -	 */
> -	if (newf & GPIOD_IS_IN)
> -		*flags = (newf & ~GPIOD_IS_OUT_ACTIVE) |
> -			(*flags & GPIOD_IS_OUT_ACTIVE);
> -	else
> -		*flags = newf;
> -
> -	return 0;
> +	return sandbox_gpio_set_flags(dev, offset, newf);
>   }
>   
>   static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)


Patrick

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

* [PATCH 08/15] gpio: sandbox: Fully separate pin value from output value
  2021-01-15 14:04 ` [PATCH 08/15] gpio: sandbox: Fully separate pin value from output value Simon Glass
@ 2021-01-21  9:39   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  9:39 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> At present we have the concept of a pin's external value. This is what
> is used when getting the value of a pin. But we still set the
> GPIOD_IS_OUT_ACTIVE flag when changing the value. This is not actually
> correct, since if the pin changes from output to input, the external
> value need not change. Adjust the logic for this difference.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/sandbox.c | 24 ++++++++++++++++++++----
>   1 file changed, 20 insertions(+), 4 deletions(-)
>

Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 09/15] gpio: sandbox: Make sandbox_gpio_set_flags() set all flags
  2021-01-15 14:04 ` [PATCH 09/15] gpio: sandbox: Make sandbox_gpio_set_flags() set all flags Simon Glass
@ 2021-01-21  9:43   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21  9:43 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> Allow this function to see all flags, including the internal sandbox ones.
> This allows the tests to fully control the behaviour of the driver.
>
> To make this work, move the setting of GPIOD_EXT_HIGH -to where the flags
> are updated via driver model, rather than the sandbox 'back door'.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/sandbox.c | 21 ++++++++++++++-------
>   1 file changed, 14 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
> index ebc160cb849..11d4757abbb 100644
> --- a/drivers/gpio/sandbox.c
> +++ b/drivers/gpio/sandbox.c
> @@ -114,9 +114,7 @@ int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
>   {
>   	struct gpio_state *state = get_gpio_state(dev, offset);
>   
> -	if (flags & GPIOD_IS_OUT_ACTIVE)
> -		flags |= GPIOD_EXT_HIGH;
> -	state->flags = (state->flags & GPIOD_SANDBOX_MASK) | flags;
> +	state->flags = flags;
>   
>   	return 0;
>   }
> @@ -213,17 +211,26 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
>   	return 0;
>   }
>   
> -static int sb_gpio_update_flags(struct udevice *dev, uint offset, ulong newf)
> +static int sb_gpio_update_flags(struct udevice *dev, uint offset, ulong flags)
>   {
> -	debug("%s: offset:%u, flags = %lx\n", __func__, offset, newf);
> +	debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags);
> +	struct gpio_state *state = get_gpio_state(dev, offset);
> +
> +	if (flags & GPIOD_IS_OUT) {
> +		if (flags & GPIOD_IS_OUT_ACTIVE)
> +			flags |= GPIOD_EXT_HIGH;
> +		else
> +			flags &= ~GPIOD_EXT_HIGH;
> +	}

Here GPIOD_EXT_HIGH is fully managed with GPIOD_IS_OUT_ACTIVE.

So that correct my remark on function sandbox_gpio_set_flags() in 
previous patche

[PATCH 07/15] gpio: sandbox: Use a separate flag for the value


> +	state->flags = flags;
>   
> -	return sandbox_gpio_set_flags(dev, offset, newf);
> +	return 0;
>   }
>   
>   static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
>   {
>   	debug("%s: offset:%u\n", __func__, offset);
> -	*flagsp = *get_gpio_flags(dev, offset);
> +	*flagsp = *get_gpio_flags(dev, offset) & ~GPIOD_SANDBOX_MASK;
>   
>   	return 0;
>   }


Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 10/15] dm: gpio: Add a way to update flags
  2021-01-15 14:04 ` [PATCH 10/15] dm: gpio: Add a way to update flags Simon Glass
@ 2021-01-21 10:07   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21 10:07 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> It is convenient to be able to adjust some of the flags for a GPIO while
> leaving others alone. Add a function for this.
>
> Update dm_gpio_set_dir_flags() to make use of this.
>
> Also update dm_gpio_set_value() to use this also, since this allows the
> open-drain / open-source features to be implemented directly in the
> driver, rather than using the uclass workaround.
>
> Update the sandbox tests accordingly. This involves a lot of changes to
> dm_test_gpio_opendrain_opensource() since we no-longer have the direciion
> being reported differently depending on the open drain/open source flags.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/gpio-uclass.c |  65 ++++++++++++++-----
>   include/asm-generic/gpio.h |  25 ++++++++
>   test/dm/gpio.c             | 125 ++++++++++++++++++++++++++++++++-----
>   3 files changed, 184 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
> index aa0e3852122..05627ecdc30 100644
> --- a/drivers/gpio/gpio-uclass.c
> +++ b/drivers/gpio/gpio-uclass.c
> @@ -568,6 +568,7 @@ int dm_gpio_get_value(const struct gpio_desc *desc)
>   
>   int dm_gpio_set_value(const struct gpio_desc *desc, int value)
>   {
> +	const struct dm_gpio_ops *ops;
>   	int ret;
>   
>   	ret = check_reserved(desc, "set_value");
> @@ -577,21 +578,33 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value)
>   	if (desc->flags & GPIOD_ACTIVE_LOW)
>   		value = !value;
>   
> +	/* GPIOD_ are directly managed by driver in update_flags */
> +	ops = gpio_get_ops(desc->dev);
> +	if (ops->update_flags) {
> +		ulong flags = desc->flags;
> +
> +		if (value)
> +			flags |= GPIOD_IS_OUT_ACTIVE;
> +		else
> +			flags &= ~GPIOD_IS_OUT_ACTIVE;
> +		return ops->update_flags(desc->dev, desc->offset, flags);
> +	}
> +
>   	/*
>   	 * Emulate open drain by not actively driving the line high or
>   	 * Emulate open source by not actively driving the line low
>   	 */
>   	if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
>   	    (desc->flags & GPIOD_OPEN_SOURCE && !value))
> -		return gpio_get_ops(desc->dev)->direction_input(desc->dev,
> -								desc->offset);
> +		return ops->direction_input(desc->dev, desc->offset);
>   	else if (desc->flags & GPIOD_OPEN_DRAIN ||
>   		 desc->flags & GPIOD_OPEN_SOURCE)
> -		return gpio_get_ops(desc->dev)->direction_output(desc->dev,
> -								desc->offset,
> -								value);
> +		return ops->direction_output(desc->dev, desc->offset, value);
> +
> +	ret = ops->set_value(desc->dev, desc->offset, value);
> +	if (ret)
> +		return ret;
>   
> -	gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
>   	return 0;
>   }
>   
> @@ -619,6 +632,17 @@ static int check_dir_flags(ulong flags)
>   	return 0;
>   }
>   
> +/**
> + * _dm_gpio_update_flags() - Send flags to the driver
> + *
> + * This uses the best available method to send the given flags to the driver.
> + * Note that if flags & GPIOD_ACTIVE_LOW, the driver sees the opposite value
> + * of GPIOD_IS_OUT_ACTIVE.
> + *
> + * @desc:	GPIO description
> + * @flags:	flags value to set
> + * @return 0 if OK, -ve on error
> + */
>   static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
>   {
>   	struct udevice *dev = desc->dev;
> @@ -637,6 +661,11 @@ static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
>   		return ret;
>   	}
>   
> +	/* If active low, invert the output state */
> +	if ((flags & (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) ==
> +		(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW))
> +		flags ^= GPIOD_IS_OUT_ACTIVE;
> +


This modifciation imply that GPIOD_ACTIVE_LOW must no more managed in 
ops update_flags

(as indicated previously in the serie in ops description)



>   	/* GPIOD_ are directly managed by driver in update_flags */
>   	if (ops->update_flags) {
>   		ret = ops->update_flags(dev, desc->offset, flags);
> @@ -649,26 +678,34 @@ static int _dm_gpio_update_flags(struct gpio_desc *desc, ulong flags)
>   		}
>   	}
>   
> -	/* save the flags also in descriptor */
> -	if (!ret)
> -		desc->flags = flags;
> -
>   	return ret;
>   }
>   
(...)

In current STM32 implementation, the set_dir_flags could be called with 
GPIOD_ACTIVE_LOW, so it was managed in ops set_dir_flags()

it was hndle by using the macro GPIOD_FLAGS_OUTPUT.


As after the serie the GPIOD_ACTIVE_LOW must no more mamaged in driver: 
I agree that is is more clean / simple.


But this patch need also modification in? driver using GPIOD_FLAGS_OUTPUT

drivers/gpio/stm32_gpio.c:208:??? ??? int value = GPIOD_FLAGS_OUTPUT(flags);

drivers/gpio/gpio-uclass.c:680: GPIOD_FLAGS_OUTPUT(flags));


I think GPIOD_FLAGS_OUTPUT could be remove, as it is only used in

drivers/gpio/stm32_gpio.c::stm32_gpio_update_flags()


Something as:


-------------------------- drivers/gpio/gpio-uclass.c 
--------------------------
index b240ddd3d9..45fe791431 100644
@@ -654,6 +654,7 @@ static int _dm_gpio_update_flags(struct gpio_desc 
*desc, ulong flags)
 ???? const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 ???? struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 ???? int ret = 0;
+??? int value;

 ???? ret = check_dir_flags(flags);
 ???? if (ret) {
@@ -676,8 +677,8 @@ static int _dm_gpio_update_flags(struct gpio_desc 
*desc, ulong flags)
 ???? ??? ret = ops->update_flags(dev, desc->offset, flags);
 ???? } else {
 ???? ??? if (flags & GPIOD_IS_OUT) {
-??? ??? ??? ret = ops->direction_output(dev, desc->offset,
-??? ??? ??? ??? ??? ??? ??? GPIOD_FLAGS_OUTPUT(flags));
+??? ??? ??? value = !!(flags & GPIOD_IS_OUT_ACTIVE);
+??? ??? ??? ret = ops->direction_output(dev, desc->offset, value);
 ???? ??? } else if (flags & GPIOD_IS_IN) {
 ???? ??? ??? ret = ops->direction_input(dev, desc->offset);
 ???? ??? }

-------------------------- drivers/gpio/stm32_gpio.c 
--------------------------
index da9a40ebf8..d9ad50f3c9 100644
@@ -205,12 +205,13 @@ static int stm32_gpio_update_flags(struct udevice 
*dev, unsigned int offset,
 ???? printf("%s: %s %d flags = %lx\n", __func__, dev->name, idx, flags);

 ???? if (flags & GPIOD_IS_OUT) {
-??? ??? int value = GPIOD_FLAGS_OUTPUT(flags);
+??? ??? int value = !!(flags & GPIOD_IS_OUT_ACTIVE);

 ???? ??? if (flags & GPIOD_OPEN_DRAIN)
 ???? ??? ??? stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD);
 ???? ??? else
 ???? ??? ??? stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP);
+
 ???? ??? stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
 ???? ??? writel(BSRR_BIT(idx, value), &regs->bsrr);
 ???? ??? printf("%s: %s %d moder = %x value = %d\n",
@@ -304,7 +305,7 @@ static int gpio_stm32_probe(struct udevice *dev)
 ???? ret = dev_read_phandle_with_args(dev, "gpio-ranges",
 ???? ??? ??? ??? ??? ?NULL, 3, i, &args);

-??? dev_dbg(dev, "dev_read_phandle_with_args = %d %d %d\n", ret, 
-ENOENT, dev_read_u32_default(dev, "ngpios", 0));
+??? dev_dbg(dev, "dev_read_phandle_with_args(%d) = %d %d %d\n", i, ret, 
-ENOENT, dev_read_u32_default(dev, "ngpios", 0));

 ???? if (!ret && args.args_count < 3)
 ???? ??? return -EINVAL;
@@ -322,6 +323,8 @@ static int gpio_stm32_probe(struct udevice *dev)

 ???? ??? ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3,
 ???? ??? ??? ??? ??? ??? ?++i, &args);
+??? ??? dev_dbg(dev, "dev_read_phandle_with_args(%d) = %d %d %d\n", 
i-1, ret, -ENOENT, dev_read_u32_default(dev, "ngpios", 0));
+
 ???? ??? if (!ret && args.args_count < 3)
 ???? ??? ??? return -EINVAL;
 ???? }

----------------------- drivers/pinctrl/pinctrl-stmfx.c 
-----------------------
index 6477febbaa..e2c95d8d42 100644
@@ -169,6 +169,8 @@ static int stmfx_gpio_update_flags(struct udevice 
*dev, unsigned int offset,
 ???? int ret = -ENOTSUPP;

 ???? if (flags & GPIOD_IS_OUT) {
+??? ??? int value = !!(flags & GPIOD_IS_OUT_ACTIVE);
+
 ???? ??? if (flags & GPIOD_OPEN_SOURCE)
 ???? ??? ??? return -ENOTSUPP;
 ???? ??? if (flags & GPIOD_OPEN_DRAIN)
@@ -177,8 +179,7 @@ static int stmfx_gpio_update_flags(struct udevice 
*dev, unsigned int offset,
 ???? ??? ??? ret = stmfx_conf_set_type(dev, offset, 1);
 ???? ??? if (ret)
 ???? ??? ??? return ret;
-??? ??? ret = stmfx_gpio_direction_output(dev, offset,
-??? ??? ??? ??? ??? ??? ? GPIOD_FLAGS_OUTPUT(flags));
+??? ??? ret = stmfx_gpio_direction_output(dev, offset, value);
 ???? } else if (flags & GPIOD_IS_IN) {
 ???? ??? ret = stmfx_gpio_direction_input(dev, offset);
 ???? ??? if (ret)

-------------------------- include/asm-generic/gpio.h 
--------------------------
index 1cf81a3fc7..62514db5be 100644
@@ -141,12 +141,6 @@ struct gpio_desc {
 ???? ?*/
 ?};

-/* helper to compute the value of the gpio output */
-#define GPIOD_FLAGS_OUTPUT_MASK (GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE)
-#define GPIOD_FLAGS_OUTPUT(flags) \
-??? (((((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_IS_OUT_ACTIVE) || \
-??? ? (((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_ACTIVE_LOW)))
-
 ?/**
 ? * dm_gpio_is_valid() - Check if a GPIO is valid
 ? *



Regards

Patrick

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

* [PATCH 11/15] gpio: Replace direction_input() and direction_output()
  2021-01-15 14:04 ` [PATCH 11/15] gpio: Replace direction_input() and direction_output() Simon Glass
@ 2021-01-21 10:12   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21 10:12 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> The new update_flags() method is more flexible since it allows the
> driver to see the full flags all at once. Use that in preference to these
> two functions. Add comments to that effect.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/gpio-uclass.c | 15 ++++++---------
>   include/asm-generic/gpio.h | 26 +++++++++++++++++++++++++-
>   2 files changed, 31 insertions(+), 10 deletions(-)
>


Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 12/15] gpio: Use an 'ops' variable everywhere
  2021-01-15 14:04 ` [PATCH 12/15] gpio: Use an 'ops' variable everywhere Simon Glass
@ 2021-01-21 10:13   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21 10:13 UTC (permalink / raw)
  To: u-boot

Hi,

On 1/15/21 3:04 PM, Simon Glass wrote:
> Update this driver to use the common method of putting the driver
> operations in an 'ops' variable install of calling gpio_get_ops()
> repeatedly. Make it const since operations do not change.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   drivers/gpio/gpio-uclass.c | 25 ++++++++++++++-----------
>   1 file changed, 14 insertions(+), 11 deletions(-)
>

Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 14/15] gpio: sandbox: Track whether a GPIO is driven
  2021-01-15 14:04 ` [PATCH 14/15] gpio: sandbox: Track whether a GPIO is driven Simon Glass
@ 2021-01-21 10:19   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21 10:19 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:04 PM, Simon Glass wrote:
> Add a new flag to keep track of whether sandbox is driving the pin, or
> whether it is expecting an input signal. If it is driving, then the value
> of the pin is the value being driven (0 or 1). If not driving, then we
> consider the value 0, since we don't currently handle things like pull-ups
> yet.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   arch/sandbox/include/asm/gpio.h |  3 ++-
>   drivers/gpio/sandbox.c          | 21 +++++++++++++++------
>   2 files changed, 17 insertions(+), 7 deletions(-)
>

Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>

Thanks

Patrick

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

* [PATCH 15/15] gpio: Add a way to read 3-way strapping pins
  2021-01-15 14:05 ` [PATCH 15/15] gpio: Add a way to read 3-way strapping pins Simon Glass
@ 2021-01-21 10:52   ` Patrick DELAUNAY
  0 siblings, 0 replies; 34+ messages in thread
From: Patrick DELAUNAY @ 2021-01-21 10:52 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 1/15/21 3:05 PM, Simon Glass wrote:
> Using the internal vs. external pull resistors it is possible to get
> 27 different combinations from 3 strapping pins. Add an implementation
> of this.
>
> This involves updating the sandbox GPIO driver to model external and
> (weaker) internal pull resistors. The get_value() method now takes account
> of what is driving a pin:
>
>     sandbox: GPIOD_EXT_DRIVEN - in which case GPIO_EXT_HIGH provides the
>            value
>     outside source - in which case GPIO_EXT_PULL_UP/DOWN indicates the
>            external state and we work the final state using those flags and
>            the internal GPIOD_PULL_UP/DOWN flags
>
> Of course the outside source does not really exist in sandbox. We are just
> modelling it for test purpose.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   arch/sandbox/include/asm/gpio.h |  5 +-
>   drivers/gpio/gpio-uclass.c      | 78 ++++++++++++++++++++++++++
>   drivers/gpio/sandbox.c          | 13 +++--
>   include/asm-generic/gpio.h      | 37 +++++++++++++
>   test/dm/gpio.c                  | 98 +++++++++++++++++++++++++++++++++
>   5 files changed, 226 insertions(+), 5 deletions(-)
>
> diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
> index edf78cb4131..097abfb299c 100644
> --- a/arch/sandbox/include/asm/gpio.h
> +++ b/arch/sandbox/include/asm/gpio.h
> @@ -26,8 +26,11 @@
>   /* Our own private GPIO flags, which musn't conflict with GPIOD_... */
>   #define GPIOD_EXT_HIGH		BIT(20)	/* external source is high (else low) */
>   #define GPIOD_EXT_DRIVEN	BIT(21)	/* external source is driven */
> +#define GPIOD_EXT_PULL_UP	BIT(22)	/* GPIO has external pull-up */
> +#define GPIOD_EXT_PULL_DOWN	BIT(23)	/* GPIO has external pull-down */
>   
> -#define GPIOD_SANDBOX_MASK	GENMASK(21, 20)
> +#define GPIOD_EXT_PULL		(BIT(21) | BIT(22))
> +#define GPIOD_SANDBOX_MASK	GENMASK(23, 20)
>   
>   /**
>    * Return the simulated value of a GPIO (used only in sandbox test code)
> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
> index 77b40263bbd..984c07d1dfa 100644
> --- a/drivers/gpio/gpio-uclass.c
> +++ b/drivers/gpio/gpio-uclass.c
> @@ -3,6 +3,8 @@
>    * Copyright (c) 2013 Google, Inc
>    */
>   
> +#define LOG_CATEGORY	UCLASS_GPIO
> +

define for LOG feature could be a separate patch ?

to support CONFIG_LOG with existing debug() macro

>   #include <common.h>
>   #include <dm.h>
>   #include <log.h>
> @@ -20,6 +22,7 @@
>   #include <dm/device_compat.h>
>   #include <linux/bug.h>
>   #include <linux/ctype.h>
> +#include <linux/delay.h>
>   
>   DECLARE_GLOBAL_DATA_PTR;
>   
> @@ -708,6 +711,21 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
>   	return dm_gpio_clrset_flags(desc, 0, flags);
>   }
>   
> +int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
> +			  ulong set)
> +{
> +	int ret;
> +	int i;
> +
> +	for (i = 0; i < count; i++) {
> +		ret = dm_gpio_clrset_flags(&desc[i], clr, set);
> +		if (ret)
> +			return log_ret(ret);
> +	}
> +
> +	return 0;
> +}
> +
>   int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
>   {
>   	struct udevice *dev = desc->dev;
> @@ -974,6 +992,66 @@ int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count)
>   	return vector;
>   }
>   
> +int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
> +				    int count)
> +{
> +	static const char tristate[] = "01z";
> +	enum {
> +		PULLUP,
> +		PULLDOWN,
> +
> +		NUM_OPTIONS,
> +	};
> +	int vals[NUM_OPTIONS];
> +	uint mask;
> +	uint vector = 0;
> +	int ret, i;
> +

return error if overflow for the the request count ?

when size_of(int) / 3 < count.


> +	for (i = 0; i < NUM_OPTIONS; i++) {
> +		uint flags = GPIOD_IS_IN;
> +
> +		flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
> +		ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
> +					    flags);
> +		if (ret)
> +			return log_msg_ret("pu", ret);
> +
> +		/* Give the lines time to settle */
> +		udelay(10);
> +
> +		ret = dm_gpio_get_values_as_int(desc_list, count);
> +		if (ret < 0)
> +			return log_msg_ret("get1", ret);
> +		vals[i] = ret;
> +	}
> +
> +	log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count);
> +	for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) {
> +		uint pd = vals[PULLDOWN] & mask ? 1 : 0;
> +		uint pu = vals[PULLUP] & mask ? 1 : 0;
> +		uint digit;
> +
> +		/*
> +		 * Get value with internal pulldown active. If this is 1 then
> +		 * there is a stronger external pullup, which we call 1. If not
> +		 * then call it 0.
> +		 */
> +		digit = pd;
> +
> +		/*
> +		 * If the values differ then the pin is floating so we call
> +		 * this a 2.
> +		 */
> +		if (pu != pd)
> +			digit |= 2;

/*
  * If the values differ then the pin is floating so we call
  * this a 2.
  * else Get value with internal pulldown active. If this is 1 then
  * there is a stronger external pullup, which we call 1. If not
  * then call it 0.
 ?*/
if (pu != pd)
	digit = 2;
else
	digit = pd;

I known that it is the same result (as in this case digit = pd = 0 and 
pu = 1)

but perhaps more clear that "digit |= 2;" with OR operator


> +		log_debug("%c ", tristate[digit]);
> +		vector = 3 * vector + digit;
> +	}
> +	log_debug("vector=%d\n", vector);
> +
> +	return vector;
> +}
> +
>   /**
>    * gpio_request_tail: common work for requesting a gpio.
>    *
> diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
> index b32f7ac529b..56b339f5e3c 100644
> --- a/drivers/gpio/sandbox.c
> +++ b/drivers/gpio/sandbox.c
> @@ -19,7 +19,6 @@
>   #include <dt-bindings/gpio/gpio.h>
>   #include <dt-bindings/gpio/sandbox-gpio.h>
>   
> -
>   struct gpio_state {
>   	const char *label;	/* label given by requester */
>   	ulong flags;		/* flags (GPIOD_...) */
> @@ -81,10 +80,16 @@ int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
>   	if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
>   		debug("sandbox_gpio: get_value on output gpio %u\n", offset);
>   
> -	if (state->flags & GPIOD_EXT_DRIVEN)
> +	if (state->flags & GPIOD_EXT_DRIVEN) {
>   		val = state->flags & GPIOD_EXT_HIGH;
> -	else
> -		val = false;
> +	} else {
> +		if (state->flags & GPIOD_EXT_PULL_UP)
> +			val = true;
> +		else if (state->flags & GPIOD_EXT_PULL_DOWN)
> +			val = false;
> +		else
> +			val = state->flags & GPIOD_PULL_UP;
> +	}
>   
>   	return val;
>   }
> diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
> index 4628d937259..1cf81a3fc7a 100644
> --- a/include/asm-generic/gpio.h
> +++ b/include/asm-generic/gpio.h
> @@ -505,6 +505,28 @@ int gpio_get_values_as_int(const int *gpio_list);
>    */
>   int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count);
>   
> +/**
> + * dm_gpio_get_values_as_int_base3() - Create a base-3 int from a list of GPIOs
> + *
> + * This uses pull-ups/pull-downs to figure out whether a GPIO line is externally
> + * pulled down, pulled up or floating. This allows three different strap values
> + * for each pin.

Add base 3 associated value description in function description

* 0 : external pull down

* 1 : externall pull up

* 2 : floating


> + *
> + * With this it is possible to obtain more combinations from the same number of
> + * strapping pins, when compared to dm_gpio_get_values_as_int(). The external
> + * pull resistors should be made stronger that the internal SoC pull resistors,
> + * for this to work.
> + *
> + * With 2 pins, 6 combinations are possible, compare with 4
> + * With 3 pins, 27 are possible, compared with 8
> + *
> + * @desc_list: List of GPIOs to collect
> + * @count: Number of GPIOs
> + * @return resulting integer value, or -ve on error
> + */
> +int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
> +				    int count);
> +
>   /**
>    * gpio_claim_vector() - claim a number of GPIOs for input
>    *

(...)


For information, I am testing the feature on STM32 platform.

I hope have a result before the end of the week.


Regards

Patrick

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

end of thread, other threads:[~2021-01-21 10:52 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-15 14:04 [PATCH 00/15] gpio: Update and simplify the uclass API Simon Glass
2021-01-15 14:04 ` [PATCH 01/15] gpio: Disable functions not used with of-platdata Simon Glass
2021-01-18 21:17   ` Pratyush Yadav
2021-01-21  8:59   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 02/15] dm: gpio: Rename set_dir_flags() method to update_flags() Simon Glass
2021-01-18 21:39   ` Pratyush Yadav
2021-01-21  9:01   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 03/15] dm: gpio: Rename get_dir_flags() method to get_flags() Simon Glass
2021-01-18 21:54   ` Pratyush Yadav
2021-01-21  9:02   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 04/15] gpio: Rename dm_gpio_get_dir_flags() to dm_gpio_get_flags() Simon Glass
2021-01-18 21:57   ` Pratyush Yadav
2021-01-21  9:05   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 05/15] gpio: Drop dm_gpio_set_dir() Simon Glass
2021-01-21  9:06   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 06/15] gpio: sandbox: Rename GPIO dir_flags to flags Simon Glass
2021-01-21  9:14   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 07/15] gpio: sandbox: Use a separate flag for the value Simon Glass
2021-01-21  9:33   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 08/15] gpio: sandbox: Fully separate pin value from output value Simon Glass
2021-01-21  9:39   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 09/15] gpio: sandbox: Make sandbox_gpio_set_flags() set all flags Simon Glass
2021-01-21  9:43   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 10/15] dm: gpio: Add a way to update flags Simon Glass
2021-01-21 10:07   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 11/15] gpio: Replace direction_input() and direction_output() Simon Glass
2021-01-21 10:12   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 12/15] gpio: Use an 'ops' variable everywhere Simon Glass
2021-01-21 10:13   ` Patrick DELAUNAY
2021-01-15 14:04 ` [PATCH 13/15] gpio: x86: Drop the deprecated methods in intel_gpio Simon Glass
2021-01-15 14:04 ` [PATCH 14/15] gpio: sandbox: Track whether a GPIO is driven Simon Glass
2021-01-21 10:19   ` Patrick DELAUNAY
2021-01-15 14:05 ` [PATCH 15/15] gpio: Add a way to read 3-way strapping pins Simon Glass
2021-01-21 10:52   ` Patrick DELAUNAY

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.