All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephan Gerhold <stephan.gerhold@linaro.org>
To: Linus Walleij <linusw@kernel.org>
Cc: u-boot@lists.u-boot-project.org, Tom Rini <trini@konsulko.com>,
	Stefan Hansson <newbyte@postmarketos.org>
Subject: Re: [PATCH v5 01/13] pinctrl: Add compact Nomadik pin controller
Date: Mon, 24 Aug 2026 15:17:17 +0200	[thread overview]
Message-ID: <aoxEXcQ9dDZ4MDkf@linaro.org> (raw)
In-Reply-To: <20260823-ux500-external-sdcard-v5-1-07ca794e2b94@kernel.org>

On Sun, Aug 23, 2026 at 10:39:20PM +0200, Linus Walleij wrote:
> Add the minimal pin control support needed to consume default states from
> the upstream DB8500 device trees. Resolve the nine Nomadik GPIO banks
> through nomadik-gpio-chips and apply the mux, direction, value, pull and
> low-EMI settings directly to their registers.
> 
> Only the DB8500 binding and default-state configuration needed by
> U-Boot are supported. There is no GPIO ownership or sleep-state
> handling.
> 
> Signed-off-by: Linus Walleij <linusw@kernel.org>

Reviewed-by: Stephan Gerhold <stephan.gerhold@linaro.org>

Thanks!

> ---
>  MAINTAINERS                       |   1 +
>  arch/arm/Kconfig                  |   2 +
>  drivers/pinctrl/Kconfig           |   7 ++
>  drivers/pinctrl/Makefile          |   1 +
>  drivers/pinctrl/pinctrl-nomadik.c | 230 ++++++++++++++++++++++++++++++++++++++
>  5 files changed, 241 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index eb48eea55c5a..a5d6b5be29dc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -787,6 +787,7 @@ S:	Maintained
>  F:	arch/arm/dts/ste-*
>  F:	arch/arm/mach-u8500/
>  F:	drivers/gpio/nmk_gpio.c
> +F:	drivers/pinctrl/pinctrl-nomadik.c
>  F:	drivers/phy/phy-ab8500-usb.c
>  F:	drivers/power/pmic/ab8500.c
>  F:	drivers/timer/nomadik-mtu-timer.c
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 1b474a346bf2..5b02ff18bd0e 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1278,6 +1278,8 @@ config ARCH_U8500
>  	imply DM_RTC
>  	imply NOMADIK_GPIO
>  	imply NOMADIK_MTU_TIMER
> +	imply PINCTRL
> +	imply PINCTRL_NOMADIK
>  	imply PHY
>  	imply PL01X_SERIAL
>  	imply PMIC_AB8500
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index fd30aaeeaa89..04785a927fec 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -75,6 +75,13 @@ config PINCONF_RECURSIVE
>  	  configuration; you can save memory footprint when this feature is
>  	  no needed.
>  
> +config PINCTRL_NOMADIK
> +	bool "Nomadik pin control driver"
> +	depends on PINCTRL_FULL
> +	help
> +	  Enable pin multiplexing and configuration support for the Nomadik
> +	  GPIO blocks in the ST-Ericsson DB8500.
> +
>  config SPL_PINCTRL
>  	bool "Support pin controllers in SPL"
>  	depends on SPL && SPL_DM
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 91149796bb5f..23219626e392 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_PINCTRL_K210)		+= pinctrl-k210.o
>  obj-$(CONFIG_PINCTRL_MESON)		+= meson/
>  obj-$(CONFIG_PINCTRL_MSCC)		+= mscc/
>  obj-$(CONFIG_PINCTRL_MTK)		+= mediatek/
> +obj-$(CONFIG_PINCTRL_NOMADIK)		+= pinctrl-nomadik.o
>  obj-$(CONFIG_PINCTRL_PIC32)		+= pinctrl_pic32.o
>  obj-$(CONFIG_PINCTRL_QCOM)		+= qcom/
>  obj-$(CONFIG_PINCTRL_QE)		+= pinctrl-qe-io.o
> diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
> new file mode 100644
> index 000000000000..12d032226608
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-nomadik.c
> @@ -0,0 +1,230 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (C) 2026 Linus Walleij <linusw@kernel.org> */
> +
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <dt-bindings/pinctrl/nomadik.h>
> +#include <vsprintf.h>
> +#include <asm/io.h>
> +
> +#define NMK_GPIO_BANKS		9
> +#define NMK_GPIO_PER_BANK	32
> +
> +struct nmk_gpio_regs {
> +	u32 dat;
> +	u32 dats;
> +	u32 datc;
> +	u32 pdis;
> +	u32 dir;
> +	u32 dirs;
> +	u32 dirc;
> +	u32 slpm;
> +	u32 afsla;
> +	u32 afslb;
> +	u32 lowemi;
> +};
> +
> +struct nmk_pinctrl_priv {
> +	struct nmk_gpio_regs *bank[NMK_GPIO_BANKS];
> +};
> +
> +enum nmk_alt {
> +	NMK_ALT_GPIO,
> +	NMK_ALT_A,
> +	NMK_ALT_B,
> +	NMK_ALT_C,
> +};
> +
> +static int nmk_pinctrl_parse_pin(const char *name, unsigned int *pin)
> +{
> +	char *end;
> +
> +	if (strncmp(name, "GPIO", 4))
> +		return -EINVAL;
> +
> +	*pin = dectoul(name + 4, &end);
> +	if (end == name + 4 || *end != '_' ||
> +	    *pin >= NMK_GPIO_BANKS * NMK_GPIO_PER_BANK)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static struct nmk_gpio_regs *
> +nmk_pinctrl_bank(struct udevice *dev, unsigned int pin)
> +{
> +	struct nmk_pinctrl_priv *priv = dev_get_priv(dev);
> +
> +	return priv->bank[pin / NMK_GPIO_PER_BANK];
> +}
> +
> +static void nmk_pinctrl_set_mux(struct udevice *dev, unsigned int pin,
> +				unsigned int alt)
> +{
> +	struct nmk_gpio_regs *regs = nmk_pinctrl_bank(dev, pin);
> +	u32 mask = BIT(pin % NMK_GPIO_PER_BANK);
> +	u32 val;
> +
> +	val = readl(&regs->afsla);
> +	if (alt & NMK_ALT_A)
> +		val |= mask;
> +	else
> +		val &= ~mask;
> +	writel(val, &regs->afsla);
> +
> +	val = readl(&regs->afslb);
> +	if (alt & NMK_ALT_B)
> +		val |= mask;
> +	else
> +		val &= ~mask;
> +	writel(val, &regs->afslb);
> +}
> +
> +static int nmk_pinctrl_set_config(struct udevice *dev, ofnode node,
> +				  unsigned int pin)
> +{
> +	struct nmk_gpio_regs *regs = nmk_pinctrl_bank(dev, pin);
> +	u32 mask = BIT(pin % NMK_GPIO_PER_BANK);
> +	u32 val;
> +
> +	if (!ofnode_read_u32(node, "ste,input", &val)) {
> +		writel(mask, &regs->dirc);
> +		if (val == INPUT_NOPULL) {
> +			setbits_le32(&regs->pdis, mask);
> +		} else {
> +			clrbits_le32(&regs->pdis, mask);
> +			if (val == INPUT_PULLUP)
> +				writel(mask, &regs->dats);
> +			else if (val == INPUT_PULLDOWN)
> +				writel(mask, &regs->datc);
> +			else
> +				return -EINVAL;
> +		}
> +	}
> +
> +	if (!ofnode_read_u32(node, "ste,output", &val)) {
> +		if (val == OUTPUT_HIGH)
> +			writel(mask, &regs->dats);
> +		else if (val == OUTPUT_LOW)
> +			writel(mask, &regs->datc);
> +		else
> +			return -EINVAL;
> +		writel(mask, &regs->dirs);
> +	}
> +
> +	if (!ofnode_read_u32(node, "ste,lowemi", &val)) {
> +		if (val)
> +			setbits_le32(&regs->lowemi, mask);
> +		else
> +			clrbits_le32(&regs->lowemi, mask);
> +	}
> +
> +	return 0;
> +}
> +
> +static int nmk_pinctrl_get_alt(ofnode node, unsigned int *alt)
> +{
> +	const char *group;
> +
> +	if (ofnode_read_string_index(node, "groups", 0, &group))
> +		return -EINVAL;
> +
> +	if (strstr(group, "_a_"))
> +		*alt = NMK_ALT_A;
> +	else if (strstr(group, "_b_"))
> +		*alt = NMK_ALT_B;
> +	else if (strstr(group, "_c_"))
> +		*alt = NMK_ALT_C;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int nmk_pinctrl_set_state(struct udevice *dev, struct udevice *config)
> +{
> +	unsigned int alt = NMK_ALT_GPIO;
> +	ofnode node;
> +	int count;
> +	int ret;
> +	int i;
> +
> +	dev_for_each_subnode(node, config) {
> +		if (ofnode_read_string(node, "function")) {
> +			ret = nmk_pinctrl_get_alt(node, &alt);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
> +	dev_for_each_subnode(node, config) {
> +		ofnode cfg;
> +
> +		count = ofnode_read_string_count(node, "pins");
> +		if (count < 0)
> +			continue;
> +
> +		cfg = ofnode_parse_phandle(node, "ste,config", 0);
> +		if (!ofnode_valid(cfg))
> +			cfg = node;
> +
> +		for (i = 0; i < count; i++) {
> +			const char *name;
> +			unsigned int pin;
> +
> +			ret = ofnode_read_string_index(node, "pins", i, &name);
> +			if (ret)
> +				return ret;
> +			ret = nmk_pinctrl_parse_pin(name, &pin);
> +			if (ret)
> +				return ret;
> +			ret = nmk_pinctrl_set_config(dev, cfg, pin);
> +			if (ret)
> +				return ret;
> +			nmk_pinctrl_set_mux(dev, pin, alt);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int nmk_pinctrl_probe(struct udevice *dev)
> +{
> +	struct nmk_pinctrl_priv *priv = dev_get_priv(dev);
> +	struct ofnode_phandle_args args;
> +	fdt_addr_t addr;
> +	int ret;
> +	int i;
> +
> +	for (i = 0; i < NMK_GPIO_BANKS; i++) {
> +		ret = dev_read_phandle_with_args(dev, "nomadik-gpio-chips",
> +						 NULL, 0, i, &args);
> +		if (ret)
> +			return ret;
> +
> +		addr = ofnode_get_addr(args.node);
> +		if (addr == FDT_ADDR_T_NONE)
> +			return -EINVAL;
> +		priv->bank[i] = (struct nmk_gpio_regs *)addr;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct pinctrl_ops nmk_pinctrl_ops = {
> +	.set_state = nmk_pinctrl_set_state,
> +};
> +
> +static const struct udevice_id nmk_pinctrl_ids[] = {
> +	{ .compatible = "stericsson,db8500-pinctrl" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pinctrl_nomadik) = {
> +	.name = "pinctrl_nomadik",
> +	.id = UCLASS_PINCTRL,
> +	.of_match = nmk_pinctrl_ids,
> +	.probe = nmk_pinctrl_probe,
> +	.priv_auto = sizeof(struct nmk_pinctrl_priv),
> +	.ops = &nmk_pinctrl_ops,
> +};
> 
> -- 
> 2.55.0
> 

  reply	other threads:[~2026-08-24 13:17 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-23 20:39 [PATCH v5 00/13] arm: u8500: Enable upstream DT based SD card boot Linus Walleij
2026-08-23 20:39 ` [PATCH v5 01/13] pinctrl: Add compact Nomadik pin controller Linus Walleij
2026-08-24 13:17   ` Stephan Gerhold [this message]
2026-08-23 20:39 ` [PATCH v5 02/13] mmc: arm_pl180: Configure Ux500 signal direction Linus Walleij
2026-08-23 20:39 ` [PATCH v5 03/13] mmc: arm_pl180: Gate idle card clocks Linus Walleij
2026-08-24 13:25   ` Stephan Gerhold
2026-08-24 19:50     ` Linus Walleij
2026-08-23 20:39 ` [PATCH v5 04/13] power: regulator: Add driver voltage clamp callback Linus Walleij
2026-08-23 20:39 ` [PATCH v5 05/13] mmc: arm_pl180: Set initial supply voltages Linus Walleij
2026-08-23 20:39 ` [PATCH v5 06/13] mmc: arm_pl180: Power down card supplies at OS handoff Linus Walleij
2026-08-24 13:30   ` Stephan Gerhold
2026-08-24 20:01     ` Linus Walleij
2026-08-25  7:43       ` Stephan Gerhold
2026-08-23 20:39 ` [PATCH v5 07/13] power: regulator: Add AB8500 AUX3 support Linus Walleij
2026-08-24 13:45   ` Stephan Gerhold
2026-08-24 20:04     ` Linus Walleij
2026-08-23 20:39 ` [PATCH v5 08/13] arm: u8500: Enable SD card regulators Linus Walleij
2026-08-23 20:39 ` [PATCH v5 09/13] configs: stemmy: Boot EFI from external SD card Linus Walleij
2026-08-24 13:46   ` Stephan Gerhold
2026-08-23 20:39 ` [PATCH v5 10/13] arm: u8500: Switch Stemmy to upstream Janice device tree Linus Walleij
2026-08-24 13:55   ` Stephan Gerhold
2026-08-24 20:21     ` Linus Walleij
2026-08-23 20:39 ` [PATCH v5 11/13] ARM: dts: ux500: Make panel regulators have unique names Linus Walleij
2026-08-23 20:39 ` [PATCH v5 12/13] ARM: dts: ux500: Harmonize GPIO key names Linus Walleij
2026-08-23 20:39 ` [PATCH v5 13/13] arm: u8500: Package Stemmy device trees in FIT Linus Walleij
2026-08-24 13:59   ` Stephan Gerhold

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=aoxEXcQ9dDZ4MDkf@linaro.org \
    --to=stephan.gerhold@linaro.org \
    --cc=linusw@kernel.org \
    --cc=newbyte@postmarketos.org \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.u-boot-project.org \
    /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.