From nobody Mon Feb 9 07:07:48 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 26FC7238C2A; Thu, 23 Oct 2025 17:16:01 +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=1761239762; cv=none; b=c+H9oLGLCxIzG96d/TGcxUuO7cIPpYb+k2CoLz/2SZDVBEi2W2lmutE82UXB3cvdoEDxYkCpEKCTmW0ZoPEgrC8/XMB4KNiJRltO2D/mxs93Xb1arHFkoryZiHxdAHcZpUy51tIZAcY4mSW0v0O1V6BBy9rz/v4lYAu55eySPLg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761239762; c=relaxed/simple; bh=USKbnz/WWtmRAu/WsgpdJwkstKtmlsjlsNtL8jTy6Fw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z2W2rqX+9OEOkLTic/8sixAQv4EVrSLI9mg7U3mG03wWUhbbT/VMqmRgUlVGMfIcnJnwDFfb8xrn6qHIsriprqFrO0RmwLKkidgcvSuxTA+AdTi8GCXv438jDhG75BgUaHkNZ7++2ZjYP7yC1yC7MRRlfcUqlkZEhkllWBl7FOY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bHP8BhKp; 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="bHP8BhKp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C5A6AC4CEE7; Thu, 23 Oct 2025 17:15:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761239761; bh=USKbnz/WWtmRAu/WsgpdJwkstKtmlsjlsNtL8jTy6Fw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bHP8BhKpIKTpQRytdcJX2VF1LdlaWvIbhTdU2/cxonQdXN+Kmal8uhfnFv6Je41xe jvxD3vXR0E44tITvWAg6mdnldKDwjJqH9JL2prtfAf84cZwk2nl0DXNZozYrs3+Y53 NPyCcQ43QkqvWIdQLo2KXhV6F19W8FH96IuGRuhKZK92VduM1h//LVfycwNAqjBPuV 1qoBNJtplqux90zHeJcUdf1r7y43rebp0h/JWzQvwp/E9fKJCAhY1YWkJSSmmbJqwf A0QQeUEPWebbZF9wjrtqh41gb1Mq80wXq756zYEeoyD8mA0j1pcYn7/Yk/SbVc6YdM 9joTOw4Q1SyLw== From: Conor Dooley To: linus.walleij@linaro.org Cc: conor@kernel.org, Conor Dooley , Rob Herring , Krzysztof Kozlowski , linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, Valentina.FernandezAlanis@microchip.com Subject: [PATCH v4 4/5] pinctrl: add polarfire soc iomux0 pinmux driver Date: Thu, 23 Oct 2025 18:15:00 +0100 Message-ID: <20251023-challenge-facecloth-339abdf3513f@spud> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251023-stopwatch-cough-47d5497be5aa@spud> References: <20251023-stopwatch-cough-47d5497be5aa@spud> 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=11389; i=conor.dooley@microchip.com; h=from:subject:message-id; bh=FspkpCwBeD2MbueZeRJsfAuxKRuAcH0xEJ18CVdNA/o=; b=owGbwMvMwCVWscWwfUFT0iXG02pJDBm/kibWKOScMVgl+6BUTqnT+n5PYkTWr3CdZGPLrx0bj p2ymBbaUcrCIMbFICumyJJ4u69Fav0flx3OPW9h5rAygQxh4OIUgInY+jMyvHk+y/XsIk8Z2xjL vfy2/EFNXyJ3bjhs+pM1+3/b22MPFRgZ3t1KvN97yi/uhbuhvp141lTWCQEXdzMvk3mXmPrPttS bFwA= 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 On Polarfire SoC, iomux0 is responsible for routing functions to either Multiprocessor Subsystem (MSS) IOs or to the FPGA fabric, where they can either interface with custom RTL or be routed to the FPGA fabric's IOs. Add a driver for it. Signed-off-by: Conor Dooley --- drivers/pinctrl/Kconfig | 8 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-mpfs-iomux0.c | 278 ++++++++++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-mpfs-iomux0.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e83fda9bf308..4ec2bb7f67cf 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -505,6 +505,14 @@ config PINCTRL_PISTACHIO help This support pinctrl and GPIO driver for IMG Pistachio SoC. =20 +config PINCTRL_POLARFIRE_SOC + bool "Polarfire SoC pinctrl driver" + depends on ARCH_MICROCHIP || COMPILE_TEST + select GENERIC_PINCONF + default y + help + This selects the pinctrl driver for Microchip Polarfire SoC. + config PINCTRL_RK805 tristate "Pinctrl and GPIO driver for RK805 PMIC" depends on MFD_RK8XX diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f33976a6c91b..ea4e890766e1 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_PINCTRL_PEF2256) +=3D pinctrl-pef2256.o obj-$(CONFIG_PINCTRL_PIC32) +=3D pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PIC64GX) +=3D pinctrl-pic64gx-gpio2.o obj-$(CONFIG_PINCTRL_PISTACHIO) +=3D pinctrl-pistachio.o +obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) +=3D pinctrl-mpfs-iomux0.o obj-$(CONFIG_PINCTRL_RK805) +=3D pinctrl-rk805.o obj-$(CONFIG_PINCTRL_ROCKCHIP) +=3D pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_RP1) +=3D pinctrl-rp1.o diff --git a/drivers/pinctrl/pinctrl-mpfs-iomux0.c b/drivers/pinctrl/pinctr= l-mpfs-iomux0.c new file mode 100644 index 000000000000..49d9fcec0a16 --- /dev/null +++ b/drivers/pinctrl/pinctrl-mpfs-iomux0.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "core.h" +#include "pinctrl-utils.h" +#include "pinconf.h" +#include "pinmux.h" + +#define MPFS_IOMUX0_REG 0x200 + +struct mpfs_iomux0_pinctrl { + struct pinctrl_dev *pctrl; + struct device *dev; + struct regmap *regmap; + struct pinctrl_desc desc; +}; + +struct mpfs_iomux0_pin_group { + const char *name; + const unsigned int *pins; + u32 mask; + u32 setting; +}; + +struct mpfs_iomux0_function { + const char *name; + const char * const *groups; +}; + +static const struct pinctrl_pin_desc mpfs_iomux0_pins[] =3D { + PINCTRL_PIN(0, "spi0"), + PINCTRL_PIN(1, "spi1"), + PINCTRL_PIN(2, "i2c0"), + PINCTRL_PIN(3, "i2c1"), + PINCTRL_PIN(4, "can0"), + PINCTRL_PIN(5, "can1"), + PINCTRL_PIN(6, "qspi"), + PINCTRL_PIN(7, "uart0"), + PINCTRL_PIN(8, "uart1"), + PINCTRL_PIN(9, "uart2"), + PINCTRL_PIN(10, "uart3"), + PINCTRL_PIN(11, "uart4"), + PINCTRL_PIN(12, "mdio0"), + PINCTRL_PIN(13, "mdio1"), +}; + +static const unsigned int mpfs_iomux0_spi0_pins[] =3D { 0 }; +static const unsigned int mpfs_iomux0_spi1_pins[] =3D { 1 }; +static const unsigned int mpfs_iomux0_i2c0_pins[] =3D { 2 }; +static const unsigned int mpfs_iomux0_i2c1_pins[] =3D { 3 }; +static const unsigned int mpfs_iomux0_can0_pins[] =3D { 4 }; +static const unsigned int mpfs_iomux0_can1_pins[] =3D { 5 }; +static const unsigned int mpfs_iomux0_qspi_pins[] =3D { 6 }; +static const unsigned int mpfs_iomux0_uart0_pins[] =3D { 7 }; +static const unsigned int mpfs_iomux0_uart1_pins[] =3D { 8 }; +static const unsigned int mpfs_iomux0_uart2_pins[] =3D { 9 }; +static const unsigned int mpfs_iomux0_uart3_pins[] =3D { 10 }; +static const unsigned int mpfs_iomux0_uart4_pins[] =3D { 11 }; +static const unsigned int mpfs_iomux0_mdio0_pins[] =3D { 12 }; +static const unsigned int mpfs_iomux0_mdio1_pins[] =3D { 13 }; + +#define MPFS_IOMUX0_GROUP(_name) { \ + .name =3D #_name "_mssio", \ + .pins =3D mpfs_iomux0_##_name##_pins, \ + .mask =3D BIT(mpfs_iomux0_##_name##_pins[0]), \ + .setting =3D 0x0, \ +}, { \ + .name =3D #_name "_fabric", \ + .pins =3D mpfs_iomux0_##_name##_pins, \ + .mask =3D BIT(mpfs_iomux0_##_name##_pins[0]), \ + .setting =3D BIT(mpfs_iomux0_##_name##_pins[0]), \ +} + +static const struct mpfs_iomux0_pin_group mpfs_iomux0_pin_groups[] =3D { + MPFS_IOMUX0_GROUP(spi0), + MPFS_IOMUX0_GROUP(spi1), + MPFS_IOMUX0_GROUP(i2c0), + MPFS_IOMUX0_GROUP(i2c1), + MPFS_IOMUX0_GROUP(can0), + MPFS_IOMUX0_GROUP(can1), + MPFS_IOMUX0_GROUP(qspi), + MPFS_IOMUX0_GROUP(uart0), + MPFS_IOMUX0_GROUP(uart1), + MPFS_IOMUX0_GROUP(uart2), + MPFS_IOMUX0_GROUP(uart3), + MPFS_IOMUX0_GROUP(uart4), + MPFS_IOMUX0_GROUP(mdio0), + MPFS_IOMUX0_GROUP(mdio1), +}; + +static const char * const mpfs_iomux0_spi0_groups[] =3D { "spi0_mssio", "s= pi0_fabric" }; +static const char * const mpfs_iomux0_spi1_groups[] =3D { "spi1_mssio", "s= pi1_fabric" }; +static const char * const mpfs_iomux0_i2c0_groups[] =3D { "i2c0_mssio", "i= 2c0_fabric" }; +static const char * const mpfs_iomux0_i2c1_groups[] =3D { "i2c1_mssio", "i= 2c1_fabric" }; +static const char * const mpfs_iomux0_can0_groups[] =3D { "can0_mssio", "c= an0_fabric" }; +static const char * const mpfs_iomux0_can1_groups[] =3D { "can1_mssio", "c= an1_fabric" }; +static const char * const mpfs_iomux0_qspi_groups[] =3D { "qspi_mssio", "q= spi_fabric" }; +static const char * const mpfs_iomux0_uart0_groups[] =3D { "uart0_mssio", = "uart0_fabric" }; +static const char * const mpfs_iomux0_uart1_groups[] =3D { "uart1_mssio", = "uart1_fabric" }; +static const char * const mpfs_iomux0_uart2_groups[] =3D { "uart2_mssio", = "uart2_fabric" }; +static const char * const mpfs_iomux0_uart3_groups[] =3D { "uart3_mssio", = "uart3_fabric" }; +static const char * const mpfs_iomux0_uart4_groups[] =3D { "uart4_mssio", = "uart4_fabric" }; +static const char * const mpfs_iomux0_mdio0_groups[] =3D { "mdio0_mssio", = "mdio0_fabric" }; +static const char * const mpfs_iomux0_mdio1_groups[] =3D { "mdio1_mssio", = "mdio1_fabric" }; + +#define MPFS_IOMUX0_FUNCTION(_name) { \ + .name =3D #_name, \ + .groups =3D mpfs_iomux0_##_name##_groups, \ +} + +static const struct mpfs_iomux0_function mpfs_iomux0_functions[] =3D { + MPFS_IOMUX0_FUNCTION(spi0), + MPFS_IOMUX0_FUNCTION(spi1), + MPFS_IOMUX0_FUNCTION(i2c0), + MPFS_IOMUX0_FUNCTION(i2c1), + MPFS_IOMUX0_FUNCTION(can0), + MPFS_IOMUX0_FUNCTION(can1), + MPFS_IOMUX0_FUNCTION(qspi), + MPFS_IOMUX0_FUNCTION(uart0), + MPFS_IOMUX0_FUNCTION(uart1), + MPFS_IOMUX0_FUNCTION(uart2), + MPFS_IOMUX0_FUNCTION(uart3), + MPFS_IOMUX0_FUNCTION(uart4), + MPFS_IOMUX0_FUNCTION(mdio0), + MPFS_IOMUX0_FUNCTION(mdio1), +}; + +static void mpfs_iomux0_pin_dbg_show(struct pinctrl_dev *pctrl_dev, struct= seq_file *seq, + unsigned int pin) +{ + struct mpfs_iomux0_pinctrl *pctrl =3D pinctrl_dev_get_drvdata(pctrl_dev); + u32 val; + + seq_printf(seq, "reg: %x, pin: %u ", MPFS_IOMUX0_REG, pin); + + regmap_read(pctrl->regmap, MPFS_IOMUX0_REG, &val); + val =3D (val & BIT(pin)) >> pin; + + seq_printf(seq, "val: %x\n", val); +} + +static int mpfs_iomux0_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(mpfs_iomux0_pin_groups); +} + +static const char *mpfs_iomux0_group_name(struct pinctrl_dev *pctldev, uns= igned int selector) +{ + return mpfs_iomux0_pin_groups[selector].name; +} + +static int mpfs_iomux0_group_pins(struct pinctrl_dev *pctldev, unsigned in= t selector, + const unsigned int **pins, unsigned int *num_pins) +{ + *pins =3D mpfs_iomux0_pin_groups[selector].pins; + *num_pins =3D 1; + + return 0; +} + +static const struct pinctrl_ops mpfs_iomux0_pinctrl_ops =3D { + .get_groups_count =3D mpfs_iomux0_groups_count, + .get_group_name =3D mpfs_iomux0_group_name, + .get_group_pins =3D mpfs_iomux0_group_pins, + .dt_node_to_map =3D pinconf_generic_dt_node_to_map_all, + .dt_free_map =3D pinctrl_utils_free_map, + .pin_dbg_show =3D mpfs_iomux0_pin_dbg_show, +}; + +static int mpfs_iomux0_pinmux_set_mux(struct pinctrl_dev *pctrl_dev, unsig= ned int fsel, + unsigned int gsel) +{ + struct mpfs_iomux0_pinctrl *pctrl =3D pinctrl_dev_get_drvdata(pctrl_dev); + struct device *dev =3D pctrl->dev; + const struct mpfs_iomux0_pin_group *group; + const struct mpfs_iomux0_function *function; + + group =3D &mpfs_iomux0_pin_groups[gsel]; + function =3D &mpfs_iomux0_functions[fsel]; + + dev_dbg(dev, "Setting func %s mask %x setting %x\n", + function->name, group->mask, group->setting); + regmap_assign_bits(pctrl->regmap, MPFS_IOMUX0_REG, group->mask, group->se= tting); + + return 0; +} + +static int mpfs_iomux0_pinmux_get_funcs_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(mpfs_iomux0_functions); +} + +static const char *mpfs_iomux0_pinmux_get_func_name(struct pinctrl_dev *pc= tldev, + unsigned int selector) +{ + return mpfs_iomux0_functions[selector].name; +} + +static int mpfs_iomux0_pinmux_get_groups(struct pinctrl_dev *pctldev, unsi= gned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + *groups =3D mpfs_iomux0_functions[selector].groups; + *num_groups =3D 2; + + return 0; +} + +static const struct pinmux_ops mpfs_iomux0_pinmux_ops =3D { + .get_functions_count =3D mpfs_iomux0_pinmux_get_funcs_count, + .get_function_name =3D mpfs_iomux0_pinmux_get_func_name, + .get_function_groups =3D mpfs_iomux0_pinmux_get_groups, + .set_mux =3D mpfs_iomux0_pinmux_set_mux, +}; + +static int mpfs_iomux0_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct mpfs_iomux0_pinctrl *pctrl; + + pctrl =3D devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + + pctrl->regmap =3D device_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(pctrl->regmap)) + dev_err_probe(dev, PTR_ERR(pctrl->regmap), "Failed to find syscon regmap= \n"); + + pctrl->desc.name =3D dev_name(dev); + pctrl->desc.pins =3D mpfs_iomux0_pins; + pctrl->desc.npins =3D ARRAY_SIZE(mpfs_iomux0_pins); + pctrl->desc.pctlops =3D &mpfs_iomux0_pinctrl_ops; + pctrl->desc.pmxops =3D &mpfs_iomux0_pinmux_ops; + pctrl->desc.owner =3D THIS_MODULE; + + pctrl->dev =3D dev; + + platform_set_drvdata(pdev, pctrl); + + pctrl->pctrl =3D devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); + if (IS_ERR(pctrl->pctrl)) + return PTR_ERR(pctrl->pctrl); + + return 0; +} + +static const struct of_device_id mpfs_iomux0_of_match[] =3D { + { .compatible =3D "microchip,mpfs-pinctrl-iomux0" }, + { } +}; +MODULE_DEVICE_TABLE(of, mpfs_iomux0_of_match); + +static struct platform_driver mpfs_iomux0_driver =3D { + .driver =3D { + .name =3D "mpfs-pinctrl-iomux0", + .of_match_table =3D mpfs_iomux0_of_match, + }, + .probe =3D mpfs_iomux0_probe, +}; +module_platform_driver(mpfs_iomux0_driver); + +MODULE_AUTHOR("Conor Dooley "); +MODULE_DESCRIPTION("Polarfire SoC iomux0 pinctrl driver"); +MODULE_LICENSE("GPL"); --=20 2.51.0