From nobody Sat Feb 7 17:48:50 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 071473D1CB0; Tue, 3 Feb 2026 16:17:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770135454; cv=none; b=hDhwW9QMhMnAMQZu/kfIZTd0Xi/jc1SakRHqRT0w5LNCTxzl7eJ+9L9bUPFlfXbgGT06yylPHoXu50p0UPGE7W2lhCA8yiX9ly3N9mq5e9eSjXLoJu07ikw+8YsVSTCLa5KwpWdQlPZ5080M8PP5669mn+yHn+me4rToAyt63Iw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770135454; c=relaxed/simple; bh=t0pahqHxkD8WOqNTV7Gd8i8Krv2yBRmUEy3BYV6hbWc=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=egnh33WRkFUmOMPStt1KJeMfzbtLyQDOxfMYC1NcnxSTbk9sJdKzARjsgD3N2Cx2Cu5ujvv+XnaY/MdQLN85zKaPRE3QoHQ4Zol7F1dNq14VARb+k0fwNmR3FuwRpi2Fh/s1dcHNV93BaufF5+49pEPQIH2689iq88ExECisqNI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nW3HSxwN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nW3HSxwN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8122AC19421; Tue, 3 Feb 2026 16:17:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770135453; bh=t0pahqHxkD8WOqNTV7Gd8i8Krv2yBRmUEy3BYV6hbWc=; h=From:To:Cc:Subject:Date:From; b=nW3HSxwNgImm+htCdGGb1KrWsi4WDyKQRZZVJ98XJJU0SkcoUKt9u4MYOBh089ig+ sD4vR65N+gXWMqaQTmMsZc8IKVG6QDN8aC2Gtyb4w1gg+1l8KliDwMbthLNPmu/0Ms 4NYAvLPgpQS6Aagb9RqoVhefNN1gkJWReWAG24Xasn4yvjUF1WWxIz8N4RGkciyjx0 xwMgHQ5EHR0rbh7WMFHC1/TNTNDmWf3sqh1F8BQMlryijIZBvaZc5XPE+rTwLP2rvx ACJdN/RT9qP3e+zeAJg8M0iL1JwL1osMuU54hLcwi+BQivoNEj/fy0XUfzTyQUh7GO 5vnK83p6XgACQ== From: Conor Dooley To: linusw@kernel.org Cc: conor@kernel.org, Conor Dooley , Xianwei Zhao , Neil Armstrong , Kevin Hilman , Jerome Brunet , Martin Blumenstingl , linux-amlogic@lists.infradead.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [RFC] pinctrl: pinconf-generic: move ..dt_node_to_map_pinmux() to amlogic-am4 driver Date: Tue, 3 Feb 2026 16:17:07 +0000 Message-ID: <20260203-craftsman-battered-3491ff68f462@spud> X-Mailer: git-send-email 2.51.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=9541; i=conor.dooley@microchip.com; h=from:subject:message-id; bh=fPiT2UToPxliK4qfPSkNC22QUXGjpLo8+s/WAHJ1Tts=; b=owGbwMvMwCVWscWwfUFT0iXG02pJDJlN8o36yaICMmvvXBZz3tdtsqFAZcHaqZKPXr3c++kN2 9SjwcebO0pZGMS4GGTFFFkSb/e1SK3/47LDuectzBxWJpAhDFycAjAR5mpGhjcqDxfMyZgluO/G 2pVFuY8/Ov28uzA38ncpg6bHeh5hz9cM/519biecsWqeV/5OtPo1+4qVN26qNvZ96817GzpJ/3/ We24A X-Developer-Key: i=conor.dooley@microchip.com; a=openpgp; fpr=F9ECA03CF54F12CD01F1655722E2C55B37CF380C Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Conor Dooley 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 =3D ; | config-item1; | }; | }; | label: cfg { | group1 { | pinmux =3D ; | config-item2; | }; | group2 { | pinmux =3D ; | 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 =3D ; | }; | }; | }; 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 =3D ; | }; | }; 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 Acked-by: Andy Shevchenko --- CC: Xianwei Zhao CC: Linus Walleij CC: Neil Armstrong CC: Kevin Hilman CC: Jerome Brunet CC: Martin Blumenstingl CC: linux-amlogic@lists.infradead.org CC: linux-gpio@vger.kernel.org CC: linux-arm-kernel@lists.infradead.org CC: linux-kernel@vger.kernel.org drivers/pinctrl/meson/pinctrl-amlogic-a4.c | 71 +++++++++++++++++++++- drivers/pinctrl/pinconf-generic.c | 69 --------------------- include/linux/pinctrl/pinconf-generic.h | 5 -- 3 files changed, 70 insertions(+), 75 deletions(-) diff --git a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c b/drivers/pinctrl/m= eson/pinctrl-amlogic-a4.c index d9e3a8d5932a..67c96e4661f5 100644 --- a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c +++ b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c @@ -24,6 +24,7 @@ #include =20 #include "../core.h" +#include "../pinctrl-utils.h" #include "../pinconf.h" =20 #define gpio_chip_to_bank(chip) \ @@ -672,11 +673,79 @@ static void aml_pin_dbg_show(struct pinctrl_dev *pcde= v, struct seq_file *s, seq_printf(s, " %s", dev_name(pcdev->dev)); } =20 +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 =3D pctldev->dev; + struct device_node *pnode; + unsigned long *configs =3D NULL; + unsigned int num_configs =3D 0; + struct property *prop; + unsigned int reserved_maps; + int reserve; + int ret; + + prop =3D of_find_property(np, "pinmux", NULL); + if (!prop) { + dev_info(dev, "Missing pinmux property\n"); + return -ENOENT; + } + + pnode =3D of_get_parent(np); + if (!pnode) { + dev_info(dev, "Missing function node\n"); + return -EINVAL; + } + + reserved_maps =3D 0; + *map =3D NULL; + *num_maps =3D 0; + + ret =3D 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 =3D 1; + if (num_configs) + reserve++; + + ret =3D pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, + num_maps, reserve); + if (ret < 0) + goto exit; + + ret =3D pinctrl_utils_add_map_mux(pctldev, map, + &reserved_maps, num_maps, np->name, + pnode->name); + if (ret < 0) + goto exit; + + if (num_configs) { + ret =3D 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 =3D { .get_groups_count =3D aml_get_groups_count, .get_group_name =3D aml_get_group_name, .get_group_pins =3D aml_get_group_pins, - .dt_node_to_map =3D pinconf_generic_dt_node_to_map_pinmux, + .dt_node_to_map =3D aml_dt_node_to_map_pinmux, .dt_free_map =3D pinconf_generic_dt_free_map, .pin_dbg_show =3D aml_pin_dbg_show, }; diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-ge= neric.c index d182ec84e2df..30475da0fd10 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -424,75 +424,6 @@ int pinconf_generic_parse_dt_config(struct device_node= *np, } EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_config); =20 -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 =3D pctldev->dev; - struct device_node *pnode; - unsigned long *configs =3D NULL; - unsigned int num_configs =3D 0; - struct property *prop; - unsigned int reserved_maps; - int reserve; - int ret; - - prop =3D of_find_property(np, "pinmux", NULL); - if (!prop) { - dev_info(dev, "Missing pinmux property\n"); - return -ENOENT; - } - - pnode =3D of_get_parent(np); - if (!pnode) { - dev_info(dev, "Missing function node\n"); - return -EINVAL; - } - - reserved_maps =3D 0; - *map =3D NULL; - *num_maps =3D 0; - - ret =3D 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 =3D 1; - if (num_configs) - reserve++; - - ret =3D pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, - num_maps, reserve); - if (ret < 0) - goto exit; - - ret =3D pinctrl_utils_add_map_mux(pctldev, map, - &reserved_maps, num_maps, np->name, - pnode->name); - if (ret < 0) - goto exit; - - if (num_configs) { - ret =3D 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, diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctr= l/pinconf-generic.h index 1be4032071c2..89277808ea61 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -250,9 +250,4 @@ static inline int pinconf_generic_dt_node_to_map_all(st= ruct 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 */ --=20 2.51.0