Merge tag 'reset-for-v6.9' of git://git.pengutronix.de/pza/linux into soc/late
authorArnd Bergmann <arnd@arndb.de>
Mon, 4 Mar 2024 16:38:27 +0000 (17:38 +0100)
committerArnd Bergmann <arnd@arndb.de>
Mon, 4 Mar 2024 16:38:27 +0000 (17:38 +0100)
Reset controller updates for v6.9

Enable support for the Sophgo SG2042 reset controller via reset-simple,
add a GPIO-based reset controller criver for shared GPIO resets, extract
an of_phandle_args_equal() helper function out of cpufreq, and use it in
reset-gpio.

Based on v6.8-rc5 because reset-gpio depends on commits in the
gpio-driver-h-stubs-for-v6.8-rc5 tag.

* tag 'reset-for-v6.9' of git://git.pengutronix.de/pza/linux:
  reset: Instantiate reset GPIO controller for shared reset-gpios
  reset: gpio: Add GPIO-based reset controller
  cpufreq: do not open-code of_phandle_args_equal()
  of: Add of_phandle_args_equal() helper
  reset: simple: add support for Sophgo SG2042
  dt-bindings: reset: sophgo: support SG2042

Link: https://lore.kernel.org/r/20240301111300.4038207-1-p.zabel@pengutronix.de
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Documentation/devicetree/bindings/reset/sophgo,sg2042-reset.yaml [new file with mode: 0644]
MAINTAINERS
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/core.c
drivers/reset/reset-gpio.c [new file with mode: 0644]
drivers/reset/reset-simple.c
include/dt-bindings/reset/sophgo,sg2042-reset.h [new file with mode: 0644]
include/linux/cpufreq.h
include/linux/of.h
include/linux/reset-controller.h

diff --git a/Documentation/devicetree/bindings/reset/sophgo,sg2042-reset.yaml b/Documentation/devicetree/bindings/reset/sophgo,sg2042-reset.yaml
new file mode 100644 (file)
index 0000000..76e1931
--- /dev/null
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/sophgo,sg2042-reset.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sophgo SG2042 SoC Reset Controller
+
+maintainers:
+  - Chen Wang <unicorn_wang@outlook.com>
+
+properties:
+  compatible:
+    const: sophgo,sg2042-reset
+
+  reg:
+    maxItems: 1
+
+  "#reset-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    rstgen: reset-controller@c00 {
+        compatible = "sophgo,sg2042-reset";
+        reg = <0xc00 0xc>;
+        #reset-cells = <1>;
+    };
index 2ecaaec6a6bf40b1cd3cccaef0f8db81c2e627b5..f124d82b02bb9ba7cdecb158c102e95d686427d6 100644 (file)
@@ -8911,6 +8911,11 @@ F:       Documentation/i2c/muxes/i2c-mux-gpio.rst
 F:     drivers/i2c/muxes/i2c-mux-gpio.c
 F:     include/linux/platform_data/i2c-mux-gpio.h
 
+GENERIC GPIO RESET DRIVER
+M:     Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+S:     Maintained
+F:     drivers/reset/reset-gpio.c
+
 GENERIC HDLC (WAN) DRIVERS
 M:     Krzysztof Halasa <khc@pm.waw.pl>
 S:     Maintained
index ccd59ddd76100a51d56beec797d00bfa8156440b..85b27c42cf65ba8c21c105a129391d8322cc00f0 100644 (file)
@@ -66,6 +66,15 @@ config RESET_BRCMSTB_RESCAL
          This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on
          BCM7216.
 
+config RESET_GPIO
+       tristate "GPIO reset controller"
+       help
+         This enables a generic reset controller for resets attached via
+         GPIOs.  Typically for OF platforms this driver expects "reset-gpios"
+         property.
+
+         If compiled as module, it will be called reset-gpio.
+
 config RESET_HSDK
        bool "Synopsys HSDK Reset Driver"
        depends on HAS_IOMEM
@@ -213,7 +222,7 @@ config RESET_SCMI
 
 config RESET_SIMPLE
        bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
-       default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
+       default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_SOPHGO || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
        depends on HAS_IOMEM
        help
          This enables a simple reset controller driver for reset lines that
@@ -228,6 +237,7 @@ config RESET_SIMPLE
           - RCC reset controller in STM32 MCUs
           - Allwinner SoCs
           - SiFive FU740 SoCs
+          - Sophgo SoCs
 
 config RESET_SOCFPGA
        bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA)
index 8270da8a4baa62a3677eaf50cbd32ffa4c9450f2..fd8b49fa46fc89a2d5f2e71ccb4e65898fab9a9b 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
 obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
 obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
 obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
+obj-$(CONFIG_RESET_GPIO) += reset-gpio.o
 obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
 obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
index 4d5a78d3c085bc76cda872cc80379b2fa6135ff2..dba74e857be621b9e0b2c5ab575219191e1bf792 100644 (file)
@@ -5,14 +5,19 @@
  * Copyright 2013 Philipp Zabel, Pengutronix
  */
 #include <linux/atomic.h>
+#include <linux/cleanup.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/kref.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
+#include <linux/idr.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/acpi.h>
+#include <linux/platform_device.h>
 #include <linux/reset.h>
 #include <linux/reset-controller.h>
 #include <linux/slab.h>
@@ -23,6 +28,11 @@ static LIST_HEAD(reset_controller_list);
 static DEFINE_MUTEX(reset_lookup_mutex);
 static LIST_HEAD(reset_lookup_list);
 
+/* Protects reset_gpio_lookup_list */
+static DEFINE_MUTEX(reset_gpio_lookup_mutex);
+static LIST_HEAD(reset_gpio_lookup_list);
+static DEFINE_IDA(reset_gpio_ida);
+
 /**
  * struct reset_control - a reset control
  * @rcdev: a pointer to the reset controller device
@@ -63,6 +73,16 @@ struct reset_control_array {
        struct reset_control *rstc[] __counted_by(num_rstcs);
 };
 
+/**
+ * struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices
+ * @of_args: phandle to the reset controller with all the args like GPIO number
+ * @list: list entry for the reset_gpio_lookup_list
+ */
+struct reset_gpio_lookup {
+       struct of_phandle_args of_args;
+       struct list_head list;
+};
+
 static const char *rcdev_name(struct reset_controller_dev *rcdev)
 {
        if (rcdev->dev)
@@ -71,6 +91,9 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev)
        if (rcdev->of_node)
                return rcdev->of_node->full_name;
 
+       if (rcdev->of_args)
+               return rcdev->of_args->np->full_name;
+
        return NULL;
 }
 
@@ -99,6 +122,9 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
  */
 int reset_controller_register(struct reset_controller_dev *rcdev)
 {
+       if (rcdev->of_node && rcdev->of_args)
+               return -EINVAL;
+
        if (!rcdev->of_xlate) {
                rcdev->of_reset_n_cells = 1;
                rcdev->of_xlate = of_reset_simple_xlate;
@@ -813,12 +839,171 @@ static void __reset_control_put_internal(struct reset_control *rstc)
        kref_put(&rstc->refcnt, __reset_control_release);
 }
 
+static int __reset_add_reset_gpio_lookup(int id, struct device_node *np,
+                                        unsigned int gpio,
+                                        unsigned int of_flags)
+{
+       const struct fwnode_handle *fwnode = of_fwnode_handle(np);
+       unsigned int lookup_flags;
+       const char *label_tmp;
+
+       /*
+        * Later we map GPIO flags between OF and Linux, however not all
+        * constants from include/dt-bindings/gpio/gpio.h and
+        * include/linux/gpio/machine.h match each other.
+        */
+       if (of_flags > GPIO_ACTIVE_LOW) {
+               pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
+                      of_flags, gpio);
+               return -EINVAL;
+       }
+
+       struct gpio_device *gdev __free(gpio_device_put) = gpio_device_find_by_fwnode(fwnode);
+       if (!gdev)
+               return -EPROBE_DEFER;
+
+       label_tmp = gpio_device_get_label(gdev);
+       if (!label_tmp)
+               return -EINVAL;
+
+       char *label __free(kfree) = kstrdup(label_tmp, GFP_KERNEL);
+       if (!label)
+               return -ENOMEM;
+
+       /* Size: one lookup entry plus sentinel */
+       struct gpiod_lookup_table *lookup __free(kfree) = kzalloc(struct_size(lookup, table, 2),
+                                                                 GFP_KERNEL);
+       if (!lookup)
+               return -ENOMEM;
+
+       lookup->dev_id = kasprintf(GFP_KERNEL, "reset-gpio.%d", id);
+       if (!lookup->dev_id)
+               return -ENOMEM;
+
+       lookup_flags = GPIO_PERSISTENT;
+       lookup_flags |= of_flags & GPIO_ACTIVE_LOW;
+       lookup->table[0] = GPIO_LOOKUP(no_free_ptr(label), gpio, "reset",
+                                      lookup_flags);
+
+       /* Not freed on success, because it is persisent subsystem data. */
+       gpiod_add_lookup_table(no_free_ptr(lookup));
+
+       return 0;
+}
+
+/*
+ * @args:      phandle to the GPIO provider with all the args like GPIO number
+ */
+static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
+{
+       struct reset_gpio_lookup *rgpio_dev;
+       struct platform_device *pdev;
+       int id, ret;
+
+       /*
+        * Currently only #gpio-cells=2 is supported with the meaning of:
+        * args[0]: GPIO number
+        * args[1]: GPIO flags
+        * TODO: Handle other cases.
+        */
+       if (args->args_count != 2)
+               return -ENOENT;
+
+       /*
+        * Registering reset-gpio device might cause immediate
+        * bind, resulting in its probe() registering new reset controller thus
+        * taking reset_list_mutex lock via reset_controller_register().
+        */
+       lockdep_assert_not_held(&reset_list_mutex);
+
+       mutex_lock(&reset_gpio_lookup_mutex);
+
+       list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) {
+               if (args->np == rgpio_dev->of_args.np) {
+                       if (of_phandle_args_equal(args, &rgpio_dev->of_args))
+                               goto out; /* Already on the list, done */
+               }
+       }
+
+       id = ida_alloc(&reset_gpio_ida, GFP_KERNEL);
+       if (id < 0) {
+               ret = id;
+               goto err_unlock;
+       }
+
+       /* Not freed on success, because it is persisent subsystem data. */
+       rgpio_dev = kzalloc(sizeof(*rgpio_dev), GFP_KERNEL);
+       if (!rgpio_dev) {
+               ret = -ENOMEM;
+               goto err_ida_free;
+       }
+
+       ret = __reset_add_reset_gpio_lookup(id, args->np, args->args[0],
+                                           args->args[1]);
+       if (ret < 0)
+               goto err_kfree;
+
+       rgpio_dev->of_args = *args;
+       /*
+        * We keep the device_node reference, but of_args.np is put at the end
+        * of __of_reset_control_get(), so get it one more time.
+        * Hold reference as long as rgpio_dev memory is valid.
+        */
+       of_node_get(rgpio_dev->of_args.np);
+       pdev = platform_device_register_data(NULL, "reset-gpio", id,
+                                            &rgpio_dev->of_args,
+                                            sizeof(rgpio_dev->of_args));
+       ret = PTR_ERR_OR_ZERO(pdev);
+       if (ret)
+               goto err_put;
+
+       list_add(&rgpio_dev->list, &reset_gpio_lookup_list);
+
+out:
+       mutex_unlock(&reset_gpio_lookup_mutex);
+
+       return 0;
+
+err_put:
+       of_node_put(rgpio_dev->of_args.np);
+err_kfree:
+       kfree(rgpio_dev);
+err_ida_free:
+       ida_free(&reset_gpio_ida, id);
+err_unlock:
+       mutex_unlock(&reset_gpio_lookup_mutex);
+
+       return ret;
+}
+
+static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args,
+                                                      bool gpio_fallback)
+{
+       struct reset_controller_dev *rcdev;
+
+       lockdep_assert_held(&reset_list_mutex);
+
+       list_for_each_entry(rcdev, &reset_controller_list, list) {
+               if (gpio_fallback) {
+                       if (rcdev->of_args && of_phandle_args_equal(args,
+                                                                   rcdev->of_args))
+                               return rcdev;
+               } else {
+                       if (args->np == rcdev->of_node)
+                               return rcdev;
+               }
+       }
+
+       return NULL;
+}
+
 struct reset_control *
 __of_reset_control_get(struct device_node *node, const char *id, int index,
                       bool shared, bool optional, bool acquired)
 {
+       bool gpio_fallback = false;
        struct reset_control *rstc;
-       struct reset_controller_dev *r, *rcdev;
+       struct reset_controller_dev *rcdev;
        struct of_phandle_args args;
        int rstc_id;
        int ret;
@@ -839,39 +1024,52 @@ __of_reset_control_get(struct device_node *node, const char *id, int index,
                                         index, &args);
        if (ret == -EINVAL)
                return ERR_PTR(ret);
-       if (ret)
-               return optional ? NULL : ERR_PTR(ret);
+       if (ret) {
+               if (!IS_ENABLED(CONFIG_RESET_GPIO))
+                       return optional ? NULL : ERR_PTR(ret);
 
-       mutex_lock(&reset_list_mutex);
-       rcdev = NULL;
-       list_for_each_entry(r, &reset_controller_list, list) {
-               if (args.np == r->of_node) {
-                       rcdev = r;
-                       break;
+               /*
+                * There can be only one reset-gpio for regular devices, so
+                * don't bother with the "reset-gpios" phandle index.
+                */
+               ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells",
+                                                0, &args);
+               if (ret)
+                       return optional ? NULL : ERR_PTR(ret);
+
+               gpio_fallback = true;
+
+               ret = __reset_add_reset_gpio_device(&args);
+               if (ret) {
+                       rstc = ERR_PTR(ret);
+                       goto out_put;
                }
        }
 
+       mutex_lock(&reset_list_mutex);
+       rcdev = __reset_find_rcdev(&args, gpio_fallback);
        if (!rcdev) {
                rstc = ERR_PTR(-EPROBE_DEFER);
-               goto out;
+               goto out_unlock;
        }
 
        if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
                rstc = ERR_PTR(-EINVAL);
-               goto out;
+               goto out_unlock;
        }
 
        rstc_id = rcdev->of_xlate(rcdev, &args);
        if (rstc_id < 0) {
                rstc = ERR_PTR(rstc_id);
-               goto out;
+               goto out_unlock;
        }
 
        /* reset_list_mutex also protects the rcdev's reset_control list */
        rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired);
 
-out:
+out_unlock:
        mutex_unlock(&reset_list_mutex);
+out_put:
        of_node_put(args.np);
 
        return rstc;
diff --git a/drivers/reset/reset-gpio.c b/drivers/reset/reset-gpio.c
new file mode 100644 (file)
index 0000000..2290b25
--- /dev/null
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/gpio/consumer.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+struct reset_gpio_priv {
+       struct reset_controller_dev rc;
+       struct gpio_desc *reset;
+};
+
+static inline struct reset_gpio_priv
+*rc_to_reset_gpio(struct reset_controller_dev *rc)
+{
+       return container_of(rc, struct reset_gpio_priv, rc);
+}
+
+static int reset_gpio_assert(struct reset_controller_dev *rc, unsigned long id)
+{
+       struct reset_gpio_priv *priv = rc_to_reset_gpio(rc);
+
+       gpiod_set_value_cansleep(priv->reset, 1);
+
+       return 0;
+}
+
+static int reset_gpio_deassert(struct reset_controller_dev *rc,
+                              unsigned long id)
+{
+       struct reset_gpio_priv *priv = rc_to_reset_gpio(rc);
+
+       gpiod_set_value_cansleep(priv->reset, 0);
+
+       return 0;
+}
+
+static int reset_gpio_status(struct reset_controller_dev *rc, unsigned long id)
+{
+       struct reset_gpio_priv *priv = rc_to_reset_gpio(rc);
+
+       return gpiod_get_value_cansleep(priv->reset);
+}
+
+static const struct reset_control_ops reset_gpio_ops = {
+       .assert = reset_gpio_assert,
+       .deassert = reset_gpio_deassert,
+       .status = reset_gpio_status,
+};
+
+static int reset_gpio_of_xlate(struct reset_controller_dev *rcdev,
+                              const struct of_phandle_args *reset_spec)
+{
+       return reset_spec->args[0];
+}
+
+static void reset_gpio_of_node_put(void *data)
+{
+       of_node_put(data);
+}
+
+static int reset_gpio_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct of_phandle_args *platdata = dev_get_platdata(dev);
+       struct reset_gpio_priv *priv;
+       int ret;
+
+       if (!platdata)
+               return -EINVAL;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, &priv->rc);
+
+       priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(priv->reset))
+               return dev_err_probe(dev, PTR_ERR(priv->reset),
+                                    "Could not get reset gpios\n");
+
+       priv->rc.ops = &reset_gpio_ops;
+       priv->rc.owner = THIS_MODULE;
+       priv->rc.dev = dev;
+       priv->rc.of_args = platdata;
+       ret = devm_add_action_or_reset(dev, reset_gpio_of_node_put,
+                                      priv->rc.of_node);
+       if (ret)
+               return ret;
+
+       /* Cells to match GPIO specifier, but it's not really used */
+       priv->rc.of_reset_n_cells = 2;
+       priv->rc.of_xlate = reset_gpio_of_xlate;
+       priv->rc.nr_resets = 1;
+
+       return devm_reset_controller_register(dev, &priv->rc);
+}
+
+static const struct platform_device_id reset_gpio_ids[] = {
+       { .name = "reset-gpio", },
+       {}
+};
+MODULE_DEVICE_TABLE(platform, reset_gpio_ids);
+
+static struct platform_driver reset_gpio_driver = {
+       .probe          = reset_gpio_probe,
+       .id_table       = reset_gpio_ids,
+       .driver = {
+               .name = "reset-gpio",
+       },
+};
+module_platform_driver(reset_gpio_driver);
+
+MODULE_AUTHOR("Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>");
+MODULE_DESCRIPTION("Generic GPIO reset driver");
+MODULE_LICENSE("GPL");
index 818cabcc9fb7527d5f1d4fe5ca9f99af85e19485..27606783983086ec7cd63852642137a6107adb8e 100644 (file)
@@ -151,6 +151,8 @@ static const struct of_device_id reset_simple_dt_ids[] = {
        { .compatible = "snps,dw-high-reset" },
        { .compatible = "snps,dw-low-reset",
                .data = &reset_simple_active_low },
+       { .compatible = "sophgo,sg2042-reset",
+               .data = &reset_simple_active_low },
        { /* sentinel */ },
 };
 
diff --git a/include/dt-bindings/reset/sophgo,sg2042-reset.h b/include/dt-bindings/reset/sophgo,sg2042-reset.h
new file mode 100644 (file)
index 0000000..9ab0980
--- /dev/null
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved.
+ */
+
+#ifndef __DT_BINDINGS_RESET_SOPHGO_SG2042_H_
+#define __DT_BINDINGS_RESET_SOPHGO_SG2042_H_
+
+#define RST_MAIN_AP                    0
+#define RST_RISCV_CPU                  1
+#define RST_RISCV_LOW_SPEED_LOGIC      2
+#define RST_RISCV_CMN                  3
+#define RST_HSDMA                      4
+#define RST_SYSDMA                     5
+#define RST_EFUSE0                     6
+#define RST_EFUSE1                     7
+#define RST_RTC                                8
+#define RST_TIMER                      9
+#define RST_WDT                                10
+#define RST_AHB_ROM0                   11
+#define RST_AHB_ROM1                   12
+#define RST_I2C0                       13
+#define RST_I2C1                       14
+#define RST_I2C2                       15
+#define RST_I2C3                       16
+#define RST_GPIO0                      17
+#define RST_GPIO1                      18
+#define RST_GPIO2                      19
+#define RST_PWM                                20
+#define RST_AXI_SRAM0                  21
+#define RST_AXI_SRAM1                  22
+#define RST_SF0                                23
+#define RST_SF1                                24
+#define RST_LPC                                25
+#define RST_ETH0                       26
+#define RST_EMMC                       27
+#define RST_SD                         28
+#define RST_UART0                      29
+#define RST_UART1                      30
+#define RST_UART2                      31
+#define RST_UART3                      32
+#define RST_SPI0                       33
+#define RST_SPI1                       34
+#define RST_DBG_I2C                    35
+#define RST_PCIE0                      36
+#define RST_PCIE1                      37
+#define RST_DDR0                       38
+#define RST_DDR1                       39
+#define RST_DDR2                       40
+#define RST_DDR3                       41
+#define RST_FAU0                       42
+#define RST_FAU1                       43
+#define RST_FAU2                       44
+#define RST_RXU0                       45
+#define RST_RXU1                       46
+#define RST_RXU2                       47
+#define RST_RXU3                       48
+#define RST_RXU4                       49
+#define RST_RXU5                       50
+#define RST_RXU6                       51
+#define RST_RXU7                       52
+#define RST_RXU8                       53
+#define RST_RXU9                       54
+#define RST_RXU10                      55
+#define RST_RXU11                      56
+#define RST_RXU12                      57
+#define RST_RXU13                      58
+#define RST_RXU14                      59
+#define RST_RXU15                      60
+#define RST_RXU16                      61
+#define RST_RXU17                      62
+#define RST_RXU18                      63
+#define RST_RXU19                      64
+#define RST_RXU20                      65
+#define RST_RXU21                      66
+#define RST_RXU22                      67
+#define RST_RXU23                      68
+#define RST_RXU24                      69
+#define RST_RXU25                      70
+#define RST_RXU26                      71
+#define RST_RXU27                      72
+#define RST_RXU28                      73
+#define RST_RXU29                      74
+#define RST_RXU30                      75
+#define RST_RXU31                      76
+
+#endif /* __DT_BINDINGS_RESET_SOPHGO_SG2042_H_ */
index afda5f24d3ddc69e8bdaf5dfc0008f350dbd49a1..3cd06dafb04ba9777d10cb8f0826b30eda962df4 100644 (file)
@@ -1149,8 +1149,7 @@ static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_
                if (ret < 0)
                        continue;
 
-               if (pargs->np == args.np && pargs->args_count == args.args_count &&
-                   !memcmp(pargs->args, args.args, sizeof(args.args[0]) * args.args_count))
+               if (of_phandle_args_equal(pargs, &args))
                        cpumask_set_cpu(cpu, cpumask);
 
                of_node_put(args.np);
index 6a9ddf20e79abdf0341f0cf6210e5991231eeab8..85bcc05b278d589e053e9ced9df3a463c2588285 100644 (file)
@@ -1065,6 +1065,22 @@ static inline int of_parse_phandle_with_optional_args(const struct device_node *
                                            0, index, out_args);
 }
 
+/**
+ * of_phandle_args_equal() - Compare two of_phandle_args
+ * @a1:                First of_phandle_args to compare
+ * @a2:                Second of_phandle_args to compare
+ *
+ * Return: True if a1 and a2 are the same (same node pointer, same phandle
+ * args), false otherwise.
+ */
+static inline bool of_phandle_args_equal(const struct of_phandle_args *a1,
+                                        const struct of_phandle_args *a2)
+{
+       return a1->np == a2->np &&
+              a1->args_count == a2->args_count &&
+              !memcmp(a1->args, a2->args, sizeof(a1->args[0]) * a1->args_count);
+}
+
 /**
  * of_property_count_u8_elems - Count the number of u8 elements in a property
  *
index 0fa4f60e11862d088d35eed5f6e0e79f3be1c9c1..357df16ede328657478eceb1ba6065f42a210ea2 100644 (file)
@@ -60,6 +60,9 @@ struct reset_control_lookup {
  * @reset_control_head: head of internal list of requested reset controls
  * @dev: corresponding driver model device struct
  * @of_node: corresponding device tree node as phandle target
+ * @of_args: for reset-gpios controllers: corresponding phandle args with
+ *           of_node and GPIO number complementing of_node; either this or
+ *           of_node should be present
  * @of_reset_n_cells: number of cells in reset line specifiers
  * @of_xlate: translation function to translate from specifier as found in the
  *            device tree to id as given to the reset control ops, defaults
@@ -73,6 +76,7 @@ struct reset_controller_dev {
        struct list_head reset_control_head;
        struct device *dev;
        struct device_node *of_node;
+       const struct of_phandle_args *of_args;
        int of_reset_n_cells;
        int (*of_xlate)(struct reset_controller_dev *rcdev,
                        const struct of_phandle_args *reset_spec);