]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
pinctrl: generic: move function to amlogic-am4 driver
authorConor Dooley <conor.dooley@microchip.com>
Tue, 3 Feb 2026 16:17:07 +0000 (16:17 +0000)
committerLinus Walleij <linusw@kernel.org>
Fri, 6 Feb 2026 11:07:14 +0000 (12:07 +0100)
pinconf_generic_dt_node_to_map_pinmux() is not actually a generic
function, and really belongs in the amlogic-am4 driver. There are three
reasons why.

First, and least, of the reasons is that this function behaves
differently to the other dt_node_to_map functions in a way that is not
obvious from a first glance. This difference stems for the devicetree
properties that the function is intended for use with, and how they are
typically used. The other generic dt_node_to_map functions support
platforms where the pins, groups and functions are described statically
in the driver and require a function that will produce a mapping from dt
nodes to these pre-established descriptions. No other code in the driver
is require to be executed at runtime.
pinconf_generic_dt_node_to_map_pinmux() on the other hand is intended for
use with the pinmux property, where groups and functions are determined
entirely from the devicetree. As a result, there are no statically
defined groups and functions in the driver for this function to perform
a mapping to. Other drivers that use the pinmux property (e.g. the k1)
their dt_node_to_map function creates the groups and functions as the
devicetree is parsed. Instead of that,
pinconf_generic_dt_node_to_map_pinmux() requires that the devicetree is
parsed twice, once by it and once at probe, so that the driver
dynamically creates the groups and functions before the dt_node_to_map
callback is executed. I don't believe this double parsing requirement is
how developers would expect this to work and is not necessary given
there are drivers that do not have this behaviour.

Secondly and thirdly, the function bakes in some assumptions that only
really match the amlogic platform about how the devicetree is constructed.
These, to me, are problematic for something that claims to be generic.

The other dt_node_to_map implementations accept a being called for
either a node containing pin configuration properties or a node
containing child nodes that each contain the configuration properties.
IOW, they support the following two devicetree configurations:

| cfg {
|  label: group {
|  pinmux = <asjhdasjhlajskd>;
|  config-item1;
|  };
| };

| label: cfg {
|  group1 {
|  pinmux = <dsjhlfka>;
|  config-item2;
|  };
|  group2 {
|  pinmux = <lsdjhaf>;
|  config-item1;
|  };
| };

pinconf_generic_dt_node_to_map_pinmux() only supports the latter.

The other assumption about devicetree configuration that the function
makes is that the labeled node's parent is a "function node". The amlogic
driver uses these "function nodes" to create the functions at probe
time, and pinconf_generic_dt_node_to_map_pinmux() finds the parent of
the node it is operating on's name as part of the mapping. IOW, it
requires that the devicetree look like:

| pinctrl@bla {
|
|  func-foo {
|  label: group-default {
|  pinmuxes = <lskdf>;
|  };
|  };
| };

and couldn't be used if the nodes containing the pinmux and
configuration properties are children of the pinctrl node itself:

| pinctrl@bla {
|
|  label: group-default {
|  pinmuxes = <lskdf>;
|  };
| };

These final two reasons are mainly why I believe this is not suitable as
a generic function, and should be moved into the driver that is the sole
user and originator of the "generic" function.

Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Acked-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
drivers/pinctrl/meson/pinctrl-amlogic-a4.c
drivers/pinctrl/pinconf-generic.c
include/linux/pinctrl/pinconf-generic.h

index 40542edd557e0b6a19623accfc91b6a50c7b891c..dfa32b11555cdc5c55506db2297ce05c422ae7a9 100644 (file)
@@ -24,6 +24,7 @@
 #include <dt-bindings/pinctrl/amlogic,pinctrl.h>
 
 #include "../core.h"
+#include "../pinctrl-utils.h"
 #include "../pinconf.h"
 
 #define gpio_chip_to_bank(chip) \
@@ -672,11 +673,79 @@ static void aml_pin_dbg_show(struct pinctrl_dev *pcdev, struct seq_file *s,
        seq_printf(s, " %s", dev_name(pcdev->dev));
 }
 
+static int aml_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev,
+                                    struct device_node *np,
+                                    struct pinctrl_map **map,
+                                    unsigned int *num_maps)
+{
+       struct device *dev = pctldev->dev;
+       struct device_node *pnode;
+       unsigned long *configs = NULL;
+       unsigned int num_configs = 0;
+       struct property *prop;
+       unsigned int reserved_maps;
+       int reserve;
+       int ret;
+
+       prop = of_find_property(np, "pinmux", NULL);
+       if (!prop) {
+               dev_info(dev, "Missing pinmux property\n");
+               return -ENOENT;
+       }
+
+       pnode = of_get_parent(np);
+       if (!pnode) {
+               dev_info(dev, "Missing function node\n");
+               return -EINVAL;
+       }
+
+       reserved_maps = 0;
+       *map = NULL;
+       *num_maps = 0;
+
+       ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
+                                             &num_configs);
+       if (ret < 0) {
+               dev_err(dev, "%pOF: could not parse node property\n", np);
+               return ret;
+       }
+
+       reserve = 1;
+       if (num_configs)
+               reserve++;
+
+       ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps,
+                                       num_maps, reserve);
+       if (ret < 0)
+               goto exit;
+
+       ret = pinctrl_utils_add_map_mux(pctldev, map,
+                                       &reserved_maps, num_maps, np->name,
+                                       pnode->name);
+       if (ret < 0)
+               goto exit;
+
+       if (num_configs) {
+               ret = pinctrl_utils_add_map_configs(pctldev, map, &reserved_maps,
+                                                   num_maps, np->name, configs,
+                                                   num_configs, PIN_MAP_TYPE_CONFIGS_GROUP);
+               if (ret < 0)
+                       goto exit;
+       }
+
+exit:
+       kfree(configs);
+       if (ret)
+               pinctrl_utils_free_map(pctldev, *map, *num_maps);
+
+       return ret;
+}
+
 static const struct pinctrl_ops aml_pctrl_ops = {
        .get_groups_count       = aml_get_groups_count,
        .get_group_name         = aml_get_group_name,
        .get_group_pins         = aml_get_group_pins,
-       .dt_node_to_map         = pinconf_generic_dt_node_to_map_pinmux,
+       .dt_node_to_map         = aml_dt_node_to_map_pinmux,
        .dt_free_map            = pinconf_generic_dt_free_map,
        .pin_dbg_show           = aml_pin_dbg_show,
 };
index 366775841c639966ad345f0c20c9d761741a16b8..94b1d057197c60efa56639258f7cf8cd266e2042 100644 (file)
@@ -385,75 +385,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_config);
 
-int pinconf_generic_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev,
-                                         struct device_node *np,
-                                         struct pinctrl_map **map,
-                                         unsigned int *num_maps)
-{
-       struct device *dev = pctldev->dev;
-       struct device_node *pnode;
-       unsigned long *configs = NULL;
-       unsigned int num_configs = 0;
-       struct property *prop;
-       unsigned int reserved_maps;
-       int reserve;
-       int ret;
-
-       prop = of_find_property(np, "pinmux", NULL);
-       if (!prop) {
-               dev_info(dev, "Missing pinmux property\n");
-               return -ENOENT;
-       }
-
-       pnode = of_get_parent(np);
-       if (!pnode) {
-               dev_info(dev, "Missing function node\n");
-               return -EINVAL;
-       }
-
-       reserved_maps = 0;
-       *map = NULL;
-       *num_maps = 0;
-
-       ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
-                                             &num_configs);
-       if (ret < 0) {
-               dev_err(dev, "%pOF: could not parse node property\n", np);
-               return ret;
-       }
-
-       reserve = 1;
-       if (num_configs)
-               reserve++;
-
-       ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps,
-                                       num_maps, reserve);
-       if (ret < 0)
-               goto exit;
-
-       ret = pinctrl_utils_add_map_mux(pctldev, map,
-                                       &reserved_maps, num_maps, np->name,
-                                       pnode->name);
-       if (ret < 0)
-               goto exit;
-
-       if (num_configs) {
-               ret = pinctrl_utils_add_map_configs(pctldev, map, &reserved_maps,
-                                                   num_maps, np->name, configs,
-                                                   num_configs, PIN_MAP_TYPE_CONFIGS_GROUP);
-               if (ret < 0)
-                       goto exit;
-       }
-
-exit:
-       kfree(configs);
-       if (ret)
-               pinctrl_utils_free_map(pctldev, *map, *num_maps);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map_pinmux);
-
 int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
                struct device_node *np, struct pinctrl_map **map,
                unsigned int *reserved_maps, unsigned int *num_maps,
index 1be4032071c23b6da9d891ce30b2a6b0d091c40c..89277808ea614134b9d886767484f8bea3319884 100644 (file)
@@ -250,9 +250,4 @@ static inline int pinconf_generic_dt_node_to_map_all(struct pinctrl_dev *pctldev
        return pinconf_generic_dt_node_to_map(pctldev, np_config, map, num_maps,
                        PIN_MAP_TYPE_INVALID);
 }
-
-int pinconf_generic_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev,
-                                         struct device_node *np,
-                                         struct pinctrl_map **map,
-                                         unsigned int *num_maps);
 #endif /* __LINUX_PINCTRL_PINCONF_GENERIC_H */