All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick Delaunay <patrick.delaunay@st.com>
To: u-boot@lists.denx.de
Subject: [PATCH v3 21/21] test: pinmux: add pincontrol-gpio for pin configuration
Date: Mon, 13 Jan 2020 11:35:15 +0100	[thread overview]
Message-ID: <20200113103515.20879-22-patrick.delaunay@st.com> (raw)
In-Reply-To: <20200113103515.20879-1-patrick.delaunay@st.com>

Add a simple pincontrol associated to the sandbox gpio driver,
that allows to check pin configuration with the command pinmux.

The pinmux test is also updated to test behavior with 2 pincontrols.

Example to check LED pin configuration:

=> pinmux list
| Device                        | Driver                        | Parent
| pinctrl-gpio                  | sandbox_pinctrl_gpio          | root_driver
| pinctrl                       | sandbox_pinctrl               | root_driver

=> pinmux dev pinctrl-gpio

=> pinmux status

a0        : gpio input .
a1        : gpio input .
a2        : gpio input .
a3        : gpio input .
a4        : gpio input .
a5        : gpio output .
a6        : gpio output .
...

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
---

Changes in v3: None
Changes in v2:
- Adapt sandbox_pinctrl_gpio driver with the saved dir_flags in
  sandbox gpio driver
- rebase on v2020.01-rc3

 arch/sandbox/dts/test.dts    |  48 +++++----
 drivers/gpio/sandbox.c       | 195 +++++++++++++++++++++++++++++++++++
 test/py/tests/test_pinmux.py |  10 ++
 3 files changed, 231 insertions(+), 22 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 8ab22c0c81..b69f0da871 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -288,28 +288,32 @@
 		};
 	};
 
-	gpio_a: base-gpios {
-		compatible = "sandbox,gpio";
-		gpio-controller;
-		#gpio-cells = <1>;
-		gpio-bank-name = "a";
-		sandbox,gpio-count = <20>;
-	};
-
-	gpio_b: extra-gpios {
-		compatible = "sandbox,gpio";
-		gpio-controller;
-		#gpio-cells = <5>;
-		gpio-bank-name = "b";
-		sandbox,gpio-count = <10>;
-	};
-
-	gpio_c: extra2-gpios {
-		compatible = "sandbox,gpio";
-		gpio-controller;
-		#gpio-cells = <2>;
-		gpio-bank-name = "c";
-		sandbox,gpio-count = <10>;
+	pinctrl-gpio {
+		compatible = "sandbox,pinctrl-gpio";
+
+		gpio_a: base-gpios {
+			compatible = "sandbox,gpio";
+			gpio-controller;
+			#gpio-cells = <1>;
+			gpio-bank-name = "a";
+			sandbox,gpio-count = <20>;
+		};
+
+		gpio_b: extra-gpios {
+			compatible = "sandbox,gpio";
+			gpio-controller;
+			#gpio-cells = <5>;
+			gpio-bank-name = "b";
+			sandbox,gpio-count = <10>;
+		};
+
+		gpio_c: pinmux-gpios {
+			compatible = "sandbox,gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank-name = "c";
+			sandbox,gpio-count = <10>;
+		};
 	};
 
 	i2c at 0 {
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index a9c470ee5e..bf6287f029 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -251,3 +251,198 @@ U_BOOT_DRIVER(gpio_sandbox) = {
 	.remove	= gpio_sandbox_remove,
 	.ops	= &gpio_sandbox_ops,
 };
+
+/* pincontrol: used only to check GPIO pin configuration (pinmux command) */
+
+struct sb_pinctrl_priv {
+	int pinctrl_ngpios;
+	struct list_head gpio_dev;
+};
+
+struct sb_gpio_bank {
+	struct udevice *gpio_dev;
+	struct list_head list;
+};
+
+static int sb_populate_gpio_dev_list(struct udevice *dev)
+{
+	struct sb_pinctrl_priv *priv = dev_get_priv(dev);
+	struct udevice *gpio_dev;
+	struct udevice *child;
+	struct sb_gpio_bank *gpio_bank;
+	int ret;
+
+	/*
+	 * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
+	 * a list with all gpio device reference which belongs to the
+	 * current pin-controller. This list is used to find pin_name and
+	 * pin muxing
+	 */
+	list_for_each_entry(child, &dev->child_head, sibling_node) {
+		ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
+						&gpio_dev);
+		if (ret < 0)
+			continue;
+
+		gpio_bank = malloc(sizeof(*gpio_bank));
+		if (!gpio_bank) {
+			dev_err(dev, "Not enough memory\n");
+			return -ENOMEM;
+		}
+
+		gpio_bank->gpio_dev = gpio_dev;
+		list_add_tail(&gpio_bank->list, &priv->gpio_dev);
+	}
+
+	return 0;
+}
+
+static int sb_pinctrl_get_pins_count(struct udevice *dev)
+{
+	struct sb_pinctrl_priv *priv = dev_get_priv(dev);
+	struct gpio_dev_priv *uc_priv;
+	struct sb_gpio_bank *gpio_bank;
+
+	/*
+	 * if get_pins_count has already been executed once on this
+	 * pin-controller, no need to run it again
+	 */
+	if (priv->pinctrl_ngpios)
+		return priv->pinctrl_ngpios;
+
+	if (list_empty(&priv->gpio_dev))
+		sb_populate_gpio_dev_list(dev);
+	/*
+	 * walk through all banks to retrieve the pin-controller
+	 * pins number
+	 */
+	list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
+		uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
+
+		priv->pinctrl_ngpios += uc_priv->gpio_count;
+	}
+
+	return priv->pinctrl_ngpios;
+}
+
+static struct udevice *sb_pinctrl_get_gpio_dev(struct udevice *dev,
+					       unsigned int selector,
+					       unsigned int *idx)
+{
+	struct sb_pinctrl_priv *priv = dev_get_priv(dev);
+	struct sb_gpio_bank *gpio_bank;
+	struct gpio_dev_priv *uc_priv;
+	int pin_count = 0;
+
+	if (list_empty(&priv->gpio_dev))
+		sb_populate_gpio_dev_list(dev);
+
+	/* look up for the bank which owns the requested pin */
+	list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
+		uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
+
+		if (selector < (pin_count + uc_priv->gpio_count)) {
+			/*
+			 * we found the bank, convert pin selector to
+			 * gpio bank index
+			 */
+			*idx = selector - pin_count;
+
+			return gpio_bank->gpio_dev;
+		}
+		pin_count += uc_priv->gpio_count;
+	}
+
+	return NULL;
+}
+
+static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
+					   unsigned int selector)
+{
+	struct gpio_dev_priv *uc_priv;
+	struct udevice *gpio_dev;
+	unsigned int gpio_idx;
+	static char pin_name[PINNAME_SIZE];
+
+	/* look up for the bank which owns the requested pin */
+	gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
+	if (!gpio_dev) {
+		snprintf(pin_name, PINNAME_SIZE, "Error");
+	} else {
+		uc_priv = dev_get_uclass_priv(gpio_dev);
+
+		snprintf(pin_name, PINNAME_SIZE, "%s%d",
+			 uc_priv->bank_name,
+			 gpio_idx);
+	}
+
+	return pin_name;
+}
+
+static char *get_dir_flags_string(ulong flags)
+{
+	if (flags & GPIOD_OPEN_DRAIN)
+		return "drive-open-drain";
+	if (flags & GPIOD_OPEN_SOURCE)
+		return "drive-open-source";
+	if (flags & GPIOD_PULL_UP)
+		return "bias-pull-up";
+	if (flags & GPIOD_PULL_DOWN)
+		return "bias-pull-down";
+	return ".";
+}
+
+static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
+				     unsigned int selector,
+				     char *buf, int size)
+{
+	struct udevice *gpio_dev;
+	unsigned int gpio_idx;
+	ulong dir_flags;
+	int function;
+
+	/* look up for the bank which owns the requested pin */
+	gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
+	if (!gpio_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);
+
+		snprintf(buf, size, "gpio %s %s",
+			 function == GPIOF_OUTPUT ? "output" : "input",
+			 get_dir_flags_string(dir_flags));
+	}
+
+	return 0;
+}
+
+static int sandbox_pinctrl_probe(struct udevice *dev)
+{
+	struct sb_pinctrl_priv *priv = dev_get_priv(dev);
+
+	INIT_LIST_HEAD(&priv->gpio_dev);
+
+	return 0;
+}
+
+static struct pinctrl_ops sandbox_pinctrl_gpio_ops = {
+	.get_pin_name		= sb_pinctrl_get_pin_name,
+	.get_pins_count		= sb_pinctrl_get_pins_count,
+	.get_pin_muxing		= sb_pinctrl_get_pin_muxing,
+};
+
+static const struct udevice_id sandbox_pinctrl_gpio_match[] = {
+	{ .compatible = "sandbox,pinctrl-gpio" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
+	.name = "sandbox_pinctrl_gpio",
+	.id = UCLASS_PINCTRL,
+	.of_match = sandbox_pinctrl_gpio_match,
+	.ops = &sandbox_pinctrl_gpio_ops,
+	.bind = dm_scan_fdt_dev,
+	.probe = sandbox_pinctrl_probe,
+	.priv_auto_alloc_size	= sizeof(struct sb_pinctrl_priv),
+};
diff --git a/test/py/tests/test_pinmux.py b/test/py/tests/test_pinmux.py
index 5ca0b4b630..4e6df992a4 100644
--- a/test/py/tests/test_pinmux.py
+++ b/test/py/tests/test_pinmux.py
@@ -22,6 +22,12 @@ def test_pinmux_usage_2(u_boot_console):
 def test_pinmux_status_all(u_boot_console):
     """Test that 'pinmux status -a' displays pin's muxing."""
     output = u_boot_console.run_command('pinmux status -a')
+
+    assert ('pinctrl-gpio:' in output)
+    assert ('a5        : gpio output .' in output)
+    assert ('a6        : gpio output .' in output)
+
+    assert ('pinctrl:' in output)
     assert ('SCL       : I2C SCL.' in output)
     assert ('SDA       : I2C SDA.' in output)
     assert ('TX        : Uart TX.' in output)
@@ -63,6 +69,10 @@ def test_pinmux_status(u_boot_console):
     """Test that 'pinmux status' displays selected pincontroller's pin
     muxing descriptions."""
     output = u_boot_console.run_command('pinmux status')
+
+    assert (not 'pinctrl-gpio:' in output)
+    assert (not 'pinctrl:' in output)
+
     assert ('SCL       : I2C SCL.' in output)
     assert ('SDA       : I2C SDA.' in output)
     assert ('TX        : Uart TX.' in output)
-- 
2.17.1

  parent reply	other threads:[~2020-01-13 10:35 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-13 10:34 [PATCH v3 00/21] dm: add support of new binding in gpio and pincontrol Patrick Delaunay
2020-01-13 10:34 ` [PATCH v3 01/21] dm: pinctrl: convert pinctrl-single to livetree Patrick Delaunay
2020-04-17 21:05   ` Tom Rini
2020-04-22 16:27     ` Tom Rini
2020-04-22 17:29       ` Lokesh Vutla
2020-01-13 10:34 ` [PATCH v3 02/21] dm: core: add ofnode and dev function to iterate on node property Patrick Delaunay
2020-01-30  2:17   ` Simon Glass
2020-04-17 21:05   ` Tom Rini
2020-01-13 10:34 ` [PATCH v3 03/21] dm: pinctrl: migrate pinctrl-generic to livetree Patrick Delaunay
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:34 ` [PATCH v3 04/21] dt-bindings: gpio: document the new pull-up/pull-down flags Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:34 ` [PATCH v3 05/21] gpio: remove GPIOD_REQUESTED Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 06/21] gpio: remove the open_drain API and ops Patrick Delaunay
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 07/21] gpio: add gpio descriptor initialization helper Patrick Delaunay
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 08/21] gpio: add function _gpio_get_value Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 09/21] gpio: add function _dm_gpio_set_dir_flags Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 10/21] gpio: add function check_dir_flags Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 11/21] gpio: add helper GPIOD_FLAGS_OUTPUT Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 12/21] gpio: update dir_flags management Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 13/21] gpio: add support of new GPIO direction flag Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:06   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 14/21] gpio: add ops to get dir flags Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:07   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 15/21] gpio: add ops to set " Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:07   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 16/21] dt-bindings: gpio: alignment with kernel v5.3 Patrick Delaunay
2020-01-30  2:18   ` Simon Glass
2020-04-17 21:07   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 17/21] pinctrl: sandbox: Add mux information in get_pin_muxing Patrick Delaunay
2020-04-17 21:07   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 18/21] test: dm: update test for pins configuration in pinctrl node Patrick Delaunay
2020-04-17 21:07   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 19/21] gpio: sandbox: cleanup binding support Patrick Delaunay
2020-04-17 21:07   ` Tom Rini
2020-01-13 10:35 ` [PATCH v3 20/21] test: dm: update test for pins configuration in gpio Patrick Delaunay
2020-04-17 21:07   ` Tom Rini
2020-01-13 10:35 ` Patrick Delaunay [this message]
2020-04-17 21:07   ` [PATCH v3 21/21] test: pinmux: add pincontrol-gpio for pin configuration Tom Rini
2020-03-27 19:21 ` [PATCH v3 00/21] dm: add support of new binding in gpio and pincontrol Tom Rini
2020-03-27 19:44   ` Simon Glass
2020-03-28 20:04     ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200113103515.20879-22-patrick.delaunay@st.com \
    --to=patrick.delaunay@st.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.