dm: gpio: Add of-platdata support
authorSimon Glass <sjg@chromium.org>
Sat, 7 Aug 2021 13:24:12 +0000 (07:24 -0600)
committerSimon Glass <sjg@chromium.org>
Sat, 25 Sep 2021 15:46:15 +0000 (09:46 -0600)
Add support for accessing GPIOs using of-plata. This uses the same
mechanism as for clocks, but allows use of the xlate() method so that
the driver can interpret the parameters.

Update the condition for GPIO_HOG so that it is not built into SPL,
since it needs SPL_OF_REAL which is not enabled in sandbox_spl.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/sandbox/dts/sandbox.dtsi
configs/sandbox_noinst_defconfig
configs/sandbox_spl_defconfig
drivers/gpio/Makefile
drivers/gpio/gpio-uclass.c
drivers/gpio/sandbox.c
drivers/gpio/sandbox_test.c [new file with mode: 0644]
include/asm-generic/gpio.h
test/dm/of_platdata.c

index 1fc9c9b..66b813f 100644 (file)
@@ -66,7 +66,7 @@
        };
 
        gpio_b: gpios@1 {
-               u-boot,dm-pre-proper;
+               u-boot,dm-spl;
                gpio-controller;
                compatible = "sandbox,gpio";
                #gpio-cells = <2>;
                sandbox,gpio-count = <10>;
        };
 
+       gpio-test {
+               u-boot,dm-spl;
+               compatible = "sandbox,gpio-test";
+               test-gpios = <&gpio_b 3 0>;
+       };
+
        hexagon {
                compatible = "demo-simple";
                colour = "white";
index 6469260..b358456 100644 (file)
@@ -1,4 +1,5 @@
 CONFIG_SYS_TEXT_BASE=0x200000
+CONFIG_SPL_GPIO=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=1
@@ -122,6 +123,7 @@ CONFIG_SANDBOX_GPIO=y
 CONFIG_I2C_CROS_EC_TUNNEL=y
 CONFIG_I2C_CROS_EC_LDO=y
 CONFIG_DM_I2C_GPIO=y
+# CONFIG_SPL_DM_I2C_GPIO is not set
 CONFIG_SYS_I2C_SANDBOX=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
index 3e9877c..73cf5dd 100644 (file)
@@ -1,4 +1,5 @@
 CONFIG_SYS_TEXT_BASE=0x200000
+CONFIG_SPL_GPIO=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=1
@@ -124,6 +125,7 @@ CONFIG_SANDBOX_GPIO=y
 CONFIG_I2C_CROS_EC_TUNNEL=y
 CONFIG_I2C_CROS_EC_LDO=y
 CONFIG_DM_I2C_GPIO=y
+# CONFIG_SPL_DM_I2C_GPIO is not set
 CONFIG_SYS_I2C_SANDBOX=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
index 58f4704..1891748 100644 (file)
@@ -33,7 +33,7 @@ obj-$(CONFIG_ROCKCHIP_GPIO)   += rk_gpio.o
 obj-$(CONFIG_RCAR_GPIO)                += gpio-rcar.o
 obj-$(CONFIG_RZA1_GPIO)                += gpio-rza1.o
 obj-$(CONFIG_S5P)              += s5p_gpio.o
-obj-$(CONFIG_SANDBOX_GPIO)     += sandbox.o
+obj-$(CONFIG_SANDBOX_GPIO)     += sandbox.o sandbox_test.o
 obj-$(CONFIG_TEGRA_GPIO)       += tegra_gpio.o
 obj-$(CONFIG_TEGRA186_GPIO)    += tegra186_gpio.o
 obj-$(CONFIG_DA8XX_GPIO)       += da8xx_gpio.o
@@ -62,7 +62,7 @@ obj-$(CONFIG_OCTEON_GPIO)     += octeon_gpio.o
 obj-$(CONFIG_MVEBU_GPIO)       += mvebu_gpio.o
 obj-$(CONFIG_MSM_GPIO)         += msm_gpio.o
 obj-$(CONFIG_$(SPL_)PCF8575_GPIO)      += pcf8575_gpio.o
-obj-$(CONFIG_PM8916_GPIO)      += pm8916_gpio.o
+obj-$(CONFIG_$(SPL_TPL_)PM8916_GPIO)   += pm8916_gpio.o
 obj-$(CONFIG_MT7620_GPIO)      += mt7620_gpio.o
 obj-$(CONFIG_MT7621_GPIO)      += mt7621_gpio.o
 obj-$(CONFIG_MSCC_SGPIO)       += mscc_sgpio.o
index e0d3ae6..bb2f232 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <log.h>
 #include <dm/devres.h>
 #include <dm/device_compat.h>
@@ -231,7 +232,7 @@ static int gpio_find_and_xlate(struct gpio_desc *desc,
                return gpio_xlate_offs_flags(desc->dev, desc, args);
 }
 
-#if defined(CONFIG_GPIO_HOG)
+#if CONFIG_IS_ENABLED(GPIO_HOG)
 
 struct gpio_hog_priv {
        struct gpio_desc gpiod;
@@ -1226,6 +1227,27 @@ int gpio_get_list_count(struct udevice *dev, const char *list_name)
 }
 #endif /* OF_PLATDATA */
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+int gpio_request_by_phandle(struct udevice *dev,
+                           const struct phandle_2_arg *cells,
+                           struct gpio_desc *desc, int flags)
+{
+       struct ofnode_phandle_args args;
+       struct udevice *gpio_dev;
+       const int index = 0;
+       int ret;
+
+       ret = device_get_by_ofplat_idx(cells->idx, &gpio_dev);
+       if (ret)
+               return ret;
+       args.args[0] = cells->arg[0];
+       args.args[1] = cells->arg[1];
+
+       return gpio_request_tail(ret, NULL, &args, NULL, index, desc, flags,
+                                index > 0, gpio_dev);
+}
+#endif
+
 int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
 {
        /* For now, we don't do any checking of dev */
@@ -1430,7 +1452,7 @@ static int gpio_post_bind(struct udevice *dev)
        }
 #endif
 
-       if (IS_ENABLED(CONFIG_GPIO_HOG)) {
+       if (CONFIG_IS_ENABLED(OF_REAL) && IS_ENABLED(CONFIG_GPIO_HOG)) {
                dev_for_each_subnode(node, dev) {
                        if (ofnode_read_bool(node, "gpio-hog")) {
                                const char *name = ofnode_get_name(node);
index d008fdd..106b2a7 100644 (file)
@@ -323,11 +323,13 @@ static const struct dm_gpio_ops gpio_sandbox_ops = {
 
 static int sandbox_gpio_of_to_plat(struct udevice *dev)
 {
-       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+       if (CONFIG_IS_ENABLED(OF_REAL)) {
+               struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 
-       uc_priv->gpio_count = dev_read_u32_default(dev, "sandbox,gpio-count",
-                                                  0);
-       uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
+               uc_priv->gpio_count =
+                       dev_read_u32_default(dev, "sandbox,gpio-count", 0);
+               uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
+       }
 
        return 0;
 }
@@ -371,6 +373,8 @@ U_BOOT_DRIVER(sandbox_gpio) = {
 
 DM_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias)
 
+#if CONFIG_IS_ENABLED(PINCTRL)
+
 /* pincontrol: used only to check GPIO pin configuration (pinmux command) */
 
 struct sb_pinctrl_priv {
@@ -579,3 +583,5 @@ U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
        .priv_auto      = sizeof(struct sb_pinctrl_priv),
        ACPI_OPS_PTR(&pinctrl_sandbox_acpi_ops)
 };
+
+#endif /* PINCTRL */
diff --git a/drivers/gpio/sandbox_test.c b/drivers/gpio/sandbox_test.c
new file mode 100644 (file)
index 0000000..c76e199
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sandbox driver for testing GPIOs with of-platdata
+ *
+ * Copyright 2021 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm-generic/gpio.h>
+
+static const struct udevice_id sandbox_gpio_test_ids[] = {
+       { .compatible = "sandbox,gpio-test" },
+       { }
+};
+
+U_BOOT_DRIVER(sandbox_gpio_test) = {
+       .name = "sandbox_gpio_test",
+       .id = UCLASS_MISC,
+       .of_match = sandbox_gpio_test_ids,
+};
index e33cde7..6de13d9 100644 (file)
@@ -608,6 +608,11 @@ int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
  */
 int dm_gpio_request(struct gpio_desc *desc, const char *label);
 
+struct phandle_2_arg;
+int gpio_request_by_phandle(struct udevice *dev,
+                           const struct phandle_2_arg *cells,
+                           struct gpio_desc *desc, int flags);
+
 /**
  * gpio_get_list_count() - Returns the number of GPIOs in a list
  *
index 0829890..ec41087 100644 (file)
@@ -8,6 +8,7 @@
 #include <dm/test.h>
 #include <test/test.h>
 #include <test/ut.h>
+#include <asm-generic/gpio.h>
 #include <asm/global_data.h>
 
 /* Test that we can find a device using of-platdata */
@@ -259,3 +260,22 @@ static int dm_test_of_plat_irq(struct unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_of_plat_irq, UT_TESTF_SCAN_PDATA);
+
+/* Test GPIOs with of-platdata */
+static int dm_test_of_plat_gpio(struct unit_test_state *uts)
+{
+       struct dtd_sandbox_gpio_test *plat;
+       struct udevice *dev;
+       struct gpio_desc desc;
+
+       ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_gpio_test",
+                                             &dev));
+       plat = dev_get_plat(dev);
+
+       ut_assertok(gpio_request_by_phandle(dev, &plat->test_gpios[0], &desc,
+                                           GPIOD_IS_OUT));
+       ut_asserteq_str("sandbox_gpio", desc.dev->name);
+
+       return 0;
+}
+DM_TEST(dm_test_of_plat_gpio, UT_TESTF_SCAN_PDATA);