summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-16 09:35:24 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-16 09:35:24 -0800
commit46a1daac56b3bf1bdbd8b37e6db811f015bc1f4b (patch)
tree5143225e474619cd153c28dc9e68ff8e41b91c47 /drivers
parent6086f349a30232f3119ec647356cd191087b1333 (diff)
parent9c5a40f2922a5a6d6b42e7b3d4c8e253918c07a1 (diff)
Merge tag 'pinctrl-v7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij: "Core changes: - Drop the unused devm_pinctrl_unregister() function - Move pretended generic pin control functionality out of the core and into the Amlogic AM4 driver. We have something better coming (hopefully) New hardware support: - Spacemit K3 (RISC-V) pin control support - Atmel AT91 PIO4 (ARM32) SAMA7D65 pin control support - Exynos9610 (ARM64) pin control support - Qualcomm Mahua TLMM (ARM64) pin control support - Microchip Polarfire MSSIO (RISC-V) pin control support - Ocelot LAN9645XF (multiplatform) pin control support Improvements: - Using a few more guards for locking - Various nonurgent fixes and tweaks" * tag 'pinctrl-v7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (73 commits) pinctrl: generic: move function to amlogic-am4 driver pinctrl: intel: Align Copyright note with corporate guidelines pinctrl: mediatek: remove unused drv_offset field pinctrl: canaan: k230: Fix NULL pointer dereference when parsing devicetree pinctrl: single: fix refcount leak in pcs_add_gpio_func() pinctrl: meson: amlogic-a4: Fix device node reference leak in bank helpers pinctrl: qcom: sm8250-lpass-lpi: Fix i2s2_data_groups definition pinctrl: core: Remove duplicate error messages pinctrl: core: Simplify devm_pinctrl_*() pinctrl: core: Remove unused devm_pinctrl_unregister() dt-bindings: pinctrl: spacemit: fix drive-strength check warning pinctrl: fix kismet issues with GENERIC_PINCTRL pinctrl: tangier: Join tng_pinctrl_probe() into its wrapper pinctrl: tangier: Remove duplicate error messages pinctrl: lynxpoint: Remove duplicate error messages pinctrl: cherryview: Remove duplicate error messages pinctrl: baytrail: Remove duplicate error messages pinctrl: intel: Remove duplicate error messages pinctrl: equilibrium: Fix device node reference leak in pinbank_init() dt-bindings: pinctrl: pinctrl-microchip-sgpio: add LAN969x ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/base.h9
-rw-r--r--drivers/base/pinctrl.c2
-rw-r--r--drivers/pinctrl/Kconfig26
-rw-r--r--drivers/pinctrl/Makefile4
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c4
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c7
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c5
-rw-r--r--drivers/pinctrl/core.c93
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx-scmi.c20
-rw-r--r--drivers/pinctrl/intel/Kconfig22
-rw-r--r--drivers/pinctrl/intel/pinctrl-alderlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c45
-rw-r--r--drivers/pinctrl/intel/pinctrl-broxton.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-cannonlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-cedarfork.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c4
-rw-r--r--drivers/pinctrl/intel/pinctrl-denverton.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-elkhartlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-emmitsburg.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-icelake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel-platform.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c4
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.h2
-rw-r--r--drivers/pinctrl/intel/pinctrl-jasperlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-lakefield.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-lewisburg.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-lynxpoint.c31
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-meteorlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-meteorpoint.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-moorefield.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-sunrisepoint.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-tangier.c23
-rw-r--r--drivers/pinctrl/intel/pinctrl-tangier.h2
-rw-r--r--drivers/pinctrl/intel/pinctrl-tigerlake.c2
-rw-r--r--drivers/pinctrl/mediatek/mtk-eint.c29
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7981.c2
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7986.c4
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7988.c2
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt8365.c1
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.h1
-rw-r--r--drivers/pinctrl/meson/Kconfig22
-rw-r--r--drivers/pinctrl/meson/pinctrl-amlogic-a4.c83
-rw-r--r--drivers/pinctrl/microchip/Kconfig18
-rw-r--r--drivers/pinctrl/microchip/Makefile5
-rw-r--r--drivers/pinctrl/microchip/pinctrl-mpfs-iomux0.c (renamed from drivers/pinctrl/pinctrl-mpfs-iomux0.c)8
-rw-r--r--drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c737
-rw-r--r--drivers/pinctrl/microchip/pinctrl-pic64gx-gpio2.c (renamed from drivers/pinctrl/pinctrl-pic64gx-gpio2.c)2
-rw-r--r--drivers/pinctrl/pinconf-generic.c69
-rw-r--r--drivers/pinctrl/pinconf.h16
-rw-r--r--drivers/pinctrl/pinctrl-amd.c2
-rw-r--r--drivers/pinctrl/pinctrl-apple-gpio.c18
-rw-r--r--drivers/pinctrl/pinctrl-at91-pio4.c9
-rw-r--r--drivers/pinctrl/pinctrl-aw9523.c53
-rw-r--r--drivers/pinctrl/pinctrl-equilibrium.c1
-rw-r--r--drivers/pinctrl/pinctrl-generic.c189
-rw-r--r--drivers/pinctrl/pinctrl-k230.c7
-rw-r--r--drivers/pinctrl/pinctrl-microchip-sgpio.c6
-rw-r--r--drivers/pinctrl/pinctrl-ocelot.c184
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c19
-rw-r--r--drivers/pinctrl/pinctrl-scmi.c3
-rw-r--r--drivers/pinctrl/pinctrl-single.c2
-rw-r--r--drivers/pinctrl/pinctrl-st.c1
-rw-r--r--drivers/pinctrl/pinctrl-tb10x.c17
-rw-r--r--drivers/pinctrl/qcom/pinctrl-glymur.c46
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/renesas/Kconfig2
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzt2h.c248
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos-arm64.c117
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c2
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h1
-rw-r--r--drivers/pinctrl/sophgo/pinctrl-cv18xx.h4
-rw-r--r--drivers/pinctrl/sophgo/pinctrl-sg2042.h6
-rw-r--r--drivers/pinctrl/spacemit/Kconfig4
-rw-r--r--drivers/pinctrl/spacemit/pinctrl-k1.c642
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c3
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra-xusb.c30
77 files changed, 2490 insertions, 466 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 8c2175820da9..79d031d2d845 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -302,3 +302,12 @@ static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
void software_node_notify(struct device *dev);
void software_node_notify_remove(struct device *dev);
+
+#ifdef CONFIG_PINCTRL
+int pinctrl_bind_pins(struct device *dev);
+#else
+static inline int pinctrl_bind_pins(struct device *dev)
+{
+ return 0;
+}
+#endif /* CONFIG_PINCTRL */
diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c
index c22864458511..6e250272c843 100644
--- a/drivers/base/pinctrl.c
+++ b/drivers/base/pinctrl.c
@@ -14,6 +14,8 @@
#include <linux/pinctrl/consumer.h>
#include <linux/slab.h>
+#include "base.h"
+
/**
* pinctrl_bind_pins() - called by the device core before probe
* @dev: the device that is just about to probe
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 7b9f792acb0e..afecd9407f53 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -25,6 +25,12 @@ config GENERIC_PINCONF
bool
select PINCONF
+config GENERIC_PINCTRL
+ bool
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+
config DEBUG_PINCTRL
bool "Debug PINCTRL calls"
depends on DEBUG_KERNEL
@@ -486,16 +492,6 @@ config PINCTRL_PIC32MZDA
def_bool y if PIC32MZDA
select PINCTRL_PIC32
-config PINCTRL_PIC64GX
- bool "pic64gx gpio2 pinctrl driver"
- depends on ARCH_MICROCHIP || COMPILE_TEST
- depends on OF
- select GENERIC_PINCONF
- select REGMAP_MMIO
- default y
- help
- This selects the pinctrl driver for gpio2 on pic64gx.
-
config PINCTRL_PISTACHIO
bool "IMG Pistachio SoC pinctrl driver"
depends on OF && (MIPS || COMPILE_TEST)
@@ -507,15 +503,6 @@ config PINCTRL_PISTACHIO
help
This support pinctrl and GPIO driver for IMG Pistachio SoC.
-config PINCTRL_POLARFIRE_SOC
- bool "Polarfire SoC pinctrl driver"
- depends on ARCH_MICROCHIP || COMPILE_TEST
- depends on OF
- 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
@@ -710,6 +697,7 @@ source "drivers/pinctrl/freescale/Kconfig"
source "drivers/pinctrl/intel/Kconfig"
source "drivers/pinctrl/mediatek/Kconfig"
source "drivers/pinctrl/meson/Kconfig"
+source "drivers/pinctrl/microchip/Kconfig"
source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/nomadik/Kconfig"
source "drivers/pinctrl/nuvoton/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index be5200c23e60..f7d5d5f76d0c 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -7,6 +7,7 @@ obj-y += core.o pinctrl-utils.o
obj-$(CONFIG_PINMUX) += pinmux.o
obj-$(CONFIG_PINCONF) += pinconf.o
obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
+obj-$(CONFIG_GENERIC_PINCTRL) += pinctrl-generic.o
obj-$(CONFIG_OF) += devicetree.o
obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o
@@ -48,9 +49,7 @@ obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o
obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o
obj-$(CONFIG_PINCTRL_PEF2256) += pinctrl-pef2256.o
obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
-obj-$(CONFIG_PINCTRL_PIC64GX) += pinctrl-pic64gx-gpio2.o
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
-obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-iomux0.o
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_RP1) += pinctrl-rp1.o
@@ -76,6 +75,7 @@ obj-y += freescale/
obj-$(CONFIG_X86) += intel/
obj-y += mediatek/
obj-$(CONFIG_PINCTRL_MESON) += meson/
+obj-y += microchip/
obj-y += mvebu/
obj-y += nomadik/
obj-y += nuvoton/
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
index cb295856dda1..f9d8fb1ab1ec 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
@@ -6,14 +6,12 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/string.h>
#include <linux/types.h>
#include "../core.h"
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
index 792089628362..50979787db5c 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
@@ -7,14 +7,13 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
-#include <linux/mutex.h>
+#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/string.h>
#include <linux/types.h>
#include "../core.h"
@@ -2654,9 +2653,7 @@ static struct regmap *aspeed_g5_acquire_regmap(struct aspeed_pinmux_data *ctx,
np = of_parse_phandle(ctx->dev->of_node,
"aspeed,external-nodes", 1);
if (np) {
- if (!of_device_is_compatible(np->parent, "aspeed,ast2400-lpc-v2") &&
- !of_device_is_compatible(np->parent, "aspeed,ast2500-lpc-v2") &&
- !of_device_is_compatible(np->parent, "aspeed,ast2600-lpc-v2"))
+ if (!of_device_is_compatible(np->parent, "aspeed,ast2500-lpc-v2"))
return ERR_PTR(-ENODEV);
map = syscon_node_to_regmap(np->parent);
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
index b0c7e4f6df9c..8cf61aab81b1 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
@@ -4,13 +4,10 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
-#include <linux/string.h>
#include <linux/types.h>
#include "../core.h"
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 83254a95ef17..342bda2a1bd6 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1383,9 +1383,9 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
}
EXPORT_SYMBOL_GPL(pinctrl_select_state);
-static void devm_pinctrl_release(struct device *dev, void *res)
+static void devm_pinctrl_release(void *p)
{
- pinctrl_put(*(struct pinctrl **)res);
+ pinctrl_put(p);
}
/**
@@ -1397,31 +1397,21 @@ static void devm_pinctrl_release(struct device *dev, void *res)
*/
struct pinctrl *devm_pinctrl_get(struct device *dev)
{
- struct pinctrl **ptr, *p;
-
- ptr = devres_alloc(devm_pinctrl_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
+ struct pinctrl *p;
+ int ret;
p = pinctrl_get(dev);
- if (!IS_ERR(p)) {
- *ptr = p;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
+ if (IS_ERR(p))
+ return p;
+
+ ret = devm_add_action_or_reset(dev, devm_pinctrl_release, p);
+ if (ret)
+ return ERR_PTR(ret);
return p;
}
EXPORT_SYMBOL_GPL(devm_pinctrl_get);
-static int devm_pinctrl_match(struct device *dev, void *res, void *data)
-{
- struct pinctrl **p = res;
-
- return *p == data;
-}
-
/**
* devm_pinctrl_put() - Resource managed pinctrl_put()
* @p: the pinctrl handle to release
@@ -1432,8 +1422,7 @@ static int devm_pinctrl_match(struct device *dev, void *res, void *data)
*/
void devm_pinctrl_put(struct pinctrl *p)
{
- WARN_ON(devres_release(p->dev, devm_pinctrl_release,
- devm_pinctrl_match, p));
+ devm_release_action(p->dev, devm_pinctrl_release, p);
}
EXPORT_SYMBOL_GPL(devm_pinctrl_put);
@@ -2198,10 +2187,8 @@ int pinctrl_enable(struct pinctrl_dev *pctldev)
int error;
error = pinctrl_claim_hogs(pctldev);
- if (error) {
- dev_err(pctldev->dev, "could not claim hogs: %i\n", error);
+ if (error)
return error;
- }
mutex_lock(&pinctrldev_list_mutex);
list_add_tail(&pctldev->node, &pinctrldev_list);
@@ -2316,23 +2303,11 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
}
EXPORT_SYMBOL_GPL(pinctrl_unregister);
-static void devm_pinctrl_dev_release(struct device *dev, void *res)
+static void devm_pinctrl_dev_release(void *pctldev)
{
- struct pinctrl_dev *pctldev = *(struct pinctrl_dev **)res;
-
pinctrl_unregister(pctldev);
}
-static int devm_pinctrl_dev_match(struct device *dev, void *res, void *data)
-{
- struct pctldev **r = res;
-
- if (WARN_ON(!r || !*r))
- return 0;
-
- return *r == data;
-}
-
/**
* devm_pinctrl_register() - Resource managed version of pinctrl_register().
* @dev: parent device for this pin controller
@@ -2348,20 +2323,16 @@ struct pinctrl_dev *devm_pinctrl_register(struct device *dev,
const struct pinctrl_desc *pctldesc,
void *driver_data)
{
- struct pinctrl_dev **ptr, *pctldev;
-
- ptr = devres_alloc(devm_pinctrl_dev_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
+ struct pinctrl_dev *pctldev;
+ int ret;
pctldev = pinctrl_register(pctldesc, dev, driver_data);
- if (IS_ERR(pctldev)) {
- devres_free(ptr);
+ if (IS_ERR(pctldev))
return pctldev;
- }
- *ptr = pctldev;
- devres_add(dev, ptr);
+ ret = devm_add_action_or_reset(dev, devm_pinctrl_dev_release, pctldev);
+ if (ret)
+ return ERR_PTR(ret);
return pctldev;
}
@@ -2383,38 +2354,16 @@ int devm_pinctrl_register_and_init(struct device *dev,
void *driver_data,
struct pinctrl_dev **pctldev)
{
- struct pinctrl_dev **ptr;
int error;
- ptr = devres_alloc(devm_pinctrl_dev_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return -ENOMEM;
-
error = pinctrl_register_and_init(pctldesc, dev, driver_data, pctldev);
- if (error) {
- devres_free(ptr);
+ if (error)
return error;
- }
-
- *ptr = *pctldev;
- devres_add(dev, ptr);
- return 0;
+ return devm_add_action_or_reset(dev, devm_pinctrl_dev_release, *pctldev);
}
EXPORT_SYMBOL_GPL(devm_pinctrl_register_and_init);
-/**
- * devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister().
- * @dev: device for which resource was allocated
- * @pctldev: the pinctrl device to unregister.
- */
-void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev)
-{
- WARN_ON(devres_release(dev, devm_pinctrl_dev_release,
- devm_pinctrl_dev_match, pctldev));
-}
-EXPORT_SYMBOL_GPL(devm_pinctrl_unregister);
-
static int __init pinctrl_init(void)
{
pr_debug("initialized pinctrl subsystem\n");
diff --git a/drivers/pinctrl/freescale/pinctrl-imx-scmi.c b/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
index 4e8ab919b334..dab2fabdf456 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx-scmi.c
@@ -38,11 +38,12 @@ struct scmi_pinctrl_imx {
};
/* SCMI pin control types, aligned with SCMI firmware */
-#define IMX_SCMI_NUM_CFG 4
+#define IMX_SCMI_NUM_CFG 5
#define IMX_SCMI_PIN_MUX 192
#define IMX_SCMI_PIN_CONFIG 193
#define IMX_SCMI_PIN_DAISY_ID 194
#define IMX_SCMI_PIN_DAISY_CFG 195
+#define IMX_SCMI_PIN_EXT 196
#define IMX_SCMI_NO_PAD_CTL BIT(31)
#define IMX_SCMI_PAD_SION BIT(30)
@@ -50,8 +51,9 @@ struct scmi_pinctrl_imx {
#define IMX_SCMI_PIN_SIZE 24
-#define IMX95_DAISY_OFF 0x408
#define IMX94_DAISY_OFF 0x608
+#define IMX95_DAISY_OFF 0x408
+#define IMX952_DAISY_OFF 0x460
static int pinctrl_scmi_imx_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
@@ -73,6 +75,8 @@ static int pinctrl_scmi_imx_dt_node_to_map(struct pinctrl_dev *pctldev,
daisy_off = IMX95_DAISY_OFF;
} else if (of_machine_is_compatible("fsl,imx94")) {
daisy_off = IMX94_DAISY_OFF;
+ } else if (of_machine_is_compatible("fsl,imx952")) {
+ daisy_off = IMX952_DAISY_OFF;
} else {
dev_err(pctldev->dev, "platform not support scmi pinctrl\n");
return -EINVAL;
@@ -118,7 +122,14 @@ static int pinctrl_scmi_imx_dt_node_to_map(struct pinctrl_dev *pctldev,
pin_id = mux_reg / 4;
- cfg[j++] = pinconf_to_config_packed(IMX_SCMI_PIN_MUX, mux_val);
+ cfg[j++] = pinconf_to_config_packed(IMX_SCMI_PIN_MUX, (mux_val & 0xFF));
+
+ if (mux_val & 0xFF00) {
+ int ext_val = (mux_val & 0xFF00) >> 8;
+
+ cfg[j++] = pinconf_to_config_packed(IMX_SCMI_PIN_EXT, ext_val);
+ } else
+ ncfg--;
if (!conf_reg || (conf_val & IMX_SCMI_NO_PAD_CTL))
ncfg--;
@@ -291,8 +302,9 @@ scmi_pinctrl_imx_get_pins(struct scmi_pinctrl_imx *pmx, struct pinctrl_desc *des
}
static const char * const scmi_pinctrl_imx_allowlist[] = {
- "fsl,imx95",
"fsl,imx94",
+ "fsl,imx95",
+ "fsl,imx952",
NULL
};
diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig
index 248c2e558ff3..04c3a5b581f3 100644
--- a/drivers/pinctrl/intel/Kconfig
+++ b/drivers/pinctrl/intel/Kconfig
@@ -45,6 +45,7 @@ config PINCTRL_INTEL_PLATFORM
of Intel PCH pins and using them as GPIOs. Currently the following
Intel SoCs / platforms require this to be functional:
- Lunar Lake
+ - Nova Lake
- Panther Lake
config PINCTRL_ALDERLAKE
@@ -52,7 +53,10 @@ config PINCTRL_ALDERLAKE
select PINCTRL_INTEL
help
This pinctrl driver provides an interface that allows configuring
- of Intel Alder Lake PCH pins and using them as GPIOs.
+ PCH pins of the following platforms and using them as GPIOs:
+ - Alder Lake HX, N, and S
+ - Raptor Lake HX, E, and S
+ - Twin Lake
config PINCTRL_BROXTON
tristate "Intel Broxton pinctrl and GPIO driver"
@@ -136,15 +140,17 @@ config PINCTRL_METEORLAKE
select PINCTRL_INTEL
help
This pinctrl driver provides an interface that allows configuring
- of Intel Meteor Lake pins and using them as GPIOs.
+ SoC pins of the following platforms and using them as GPIOs:
+ - Arrow Lake (all variants)
+ - Meteor Lake (all variants)
config PINCTRL_METEORPOINT
tristate "Intel Meteor Point pinctrl and GPIO driver"
select PINCTRL_INTEL
help
- Meteor Point is the PCH of Intel Meteor Lake. This pinctrl driver
- provides an interface that allows configuring of PCH pins and
- using them as GPIOs.
+ This pinctrl driver provides an interface that allows configuring
+ PCH pins of the following platforms and using them as GPIOs:
+ - Arrow Lake HX and S
config PINCTRL_SUNRISEPOINT
tristate "Intel Sunrisepoint pinctrl and GPIO driver"
@@ -159,7 +165,11 @@ config PINCTRL_TIGERLAKE
select PINCTRL_INTEL
help
This pinctrl driver provides an interface that allows configuring
- of Intel Tiger Lake PCH pins and using them as GPIOs.
+ PCH pins of the following platforms and using them as GPIOs:
+ - Alder Lake H, P, PS, and U
+ - Raptor Lake H, P, PS, PX, and U
+ - Rocket Lake S
+ - Tiger Lake (all variants)
source "drivers/pinctrl/intel/Kconfig.tng"
endmenu
diff --git a/drivers/pinctrl/intel/pinctrl-alderlake.c b/drivers/pinctrl/intel/pinctrl-alderlake.c
index 7bf1d5c285a0..dcb541976f2f 100644
--- a/drivers/pinctrl/intel/pinctrl-alderlake.c
+++ b/drivers/pinctrl/intel/pinctrl-alderlake.c
@@ -2,7 +2,7 @@
/*
* Intel Alder Lake PCH pinctrl/GPIO driver
*
- * Copyright (C) 2020, 2022 Intel Corporation
+ * Copyright (C) 2020-2022 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index b3a5222a175f..b733ec31ad9d 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -2,7 +2,7 @@
/*
* Pinctrl GPIO driver for Intel Baytrail
*
- * Copyright (c) 2012-2013, Intel Corporation
+ * Copyright (C) 2012-2013 Intel Corporation
* Author: Mathias Nyman <mathias.nyman@linux.intel.com>
*/
@@ -101,10 +101,12 @@ struct intel_pad_context {
u32 val;
};
-#define COMMUNITY(p, n, map) \
+#define BYT_COMMUNITY(p, n, g, map) \
{ \
.pin_base = (p), \
.npins = (n), \
+ .gpps = (g), \
+ .ngpps = ARRAY_SIZE(g), \
.pad_map = (map),\
}
@@ -360,8 +362,15 @@ static const struct intel_function byt_score_functions[] = {
FUNCTION("gpio", byt_score_gpio_groups),
};
+static const struct intel_padgroup byt_score_gpps[] = {
+ INTEL_GPP(0, 0, 31, 0),
+ INTEL_GPP(1, 32, 63, 32),
+ INTEL_GPP(2, 64, 95, 64),
+ INTEL_GPP(3, 96, 101, 96),
+};
+
static const struct intel_community byt_score_communities[] = {
- COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map),
+ BYT_COMMUNITY(0, 102, byt_score_gpps, byt_score_pins_map),
};
static const struct intel_pinctrl_soc_data byt_score_soc_data = {
@@ -483,8 +492,13 @@ static const struct intel_function byt_sus_functions[] = {
FUNCTION("pmu_clk", byt_sus_pmu_clk_groups),
};
+static const struct intel_padgroup byt_sus_gpps[] = {
+ INTEL_GPP(0, 0, 31, 0),
+ INTEL_GPP(1, 32, 43, 32),
+};
+
static const struct intel_community byt_sus_communities[] = {
- COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map),
+ BYT_COMMUNITY(0, 44, byt_sus_gpps, byt_sus_pins_map),
};
static const struct intel_pinctrl_soc_data byt_sus_soc_data = {
@@ -536,8 +550,12 @@ static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
3, 6, 10, 13, 2, 5, 9, 7,
};
+static const struct intel_padgroup byt_ncore_gpps[] = {
+ INTEL_GPP(0, 0, 27, 0),
+};
+
static const struct intel_community byt_ncore_communities[] = {
- COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map),
+ BYT_COMMUNITY(0, 28, byt_ncore_gpps, byt_ncore_pins_map),
};
static const struct intel_pinctrl_soc_data byt_ncore_soc_data = {
@@ -1490,19 +1508,6 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
return 0;
}
-static int byt_gpio_add_pin_ranges(struct gpio_chip *chip)
-{
- struct intel_pinctrl *vg = gpiochip_get_data(chip);
- struct device *dev = vg->dev;
- int ret;
-
- ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc->npins);
- if (ret)
- return dev_err_probe(dev, ret, "failed to add GPIO pin range\n");
-
- return 0;
-}
-
static int byt_gpio_probe(struct intel_pinctrl *vg)
{
struct platform_device *pdev = to_platform_device(vg->dev);
@@ -1515,7 +1520,7 @@ static int byt_gpio_probe(struct intel_pinctrl *vg)
gc->label = dev_name(vg->dev);
gc->base = -1;
gc->can_sleep = false;
- gc->add_pin_ranges = byt_gpio_add_pin_ranges;
+ gc->add_pin_ranges = intel_gpio_add_pin_ranges;
gc->parent = vg->dev;
gc->ngpio = vg->soc->npins;
@@ -1611,7 +1616,7 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
vg->pctldev = devm_pinctrl_register(dev, &vg->pctldesc, vg);
if (IS_ERR(vg->pctldev))
- return dev_err_probe(dev, PTR_ERR(vg->pctldev), "failed to register pinctrl\n");
+ return PTR_ERR(vg->pctldev);
ret = byt_gpio_probe(vg);
if (ret)
diff --git a/drivers/pinctrl/intel/pinctrl-broxton.c b/drivers/pinctrl/intel/pinctrl-broxton.c
index 140b29956340..3d3c1706928a 100644
--- a/drivers/pinctrl/intel/pinctrl-broxton.c
+++ b/drivers/pinctrl/intel/pinctrl-broxton.c
@@ -2,7 +2,7 @@
/*
* Intel Broxton SoC pinctrl/GPIO driver
*
- * Copyright (C) 2015, 2016 Intel Corporation
+ * Copyright (C) 2015-2016 Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-cannonlake.c b/drivers/pinctrl/intel/pinctrl-cannonlake.c
index a3ffd19fd5be..baa7c9a62ff9 100644
--- a/drivers/pinctrl/intel/pinctrl-cannonlake.c
+++ b/drivers/pinctrl/intel/pinctrl-cannonlake.c
@@ -2,7 +2,7 @@
/*
* Intel Cannon Lake PCH pinctrl/GPIO driver
*
- * Copyright (C) 2017, Intel Corporation
+ * Copyright (C) 2017 Intel Corporation
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-cedarfork.c b/drivers/pinctrl/intel/pinctrl-cedarfork.c
index 2916f7d90090..578e1ee57acf 100644
--- a/drivers/pinctrl/intel/pinctrl-cedarfork.c
+++ b/drivers/pinctrl/intel/pinctrl-cedarfork.c
@@ -2,7 +2,7 @@
/*
* Intel Cedar Fork PCH pinctrl/GPIO driver
*
- * Copyright (C) 2017, Intel Corporation
+ * Copyright (C) 2017 Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 8bd0c8512f78..a33eca5eafc4 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -2,7 +2,7 @@
/*
* Cherryview/Braswell pinctrl driver
*
- * Copyright (C) 2014, 2020 Intel Corporation
+ * Copyright (C) 2014-2020 Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*
* This driver is based on the original Cherryview GPIO driver by
@@ -1644,7 +1644,7 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl);
if (IS_ERR(pctrl->pctldev))
- return dev_err_probe(dev, PTR_ERR(pctrl->pctldev), "failed to register pinctrl\n");
+ return PTR_ERR(pctrl->pctldev);
ret = chv_gpio_probe(pctrl, irq);
if (ret)
diff --git a/drivers/pinctrl/intel/pinctrl-denverton.c b/drivers/pinctrl/intel/pinctrl-denverton.c
index f492f73ba246..4a1d346fb30c 100644
--- a/drivers/pinctrl/intel/pinctrl-denverton.c
+++ b/drivers/pinctrl/intel/pinctrl-denverton.c
@@ -2,7 +2,7 @@
/*
* Intel Denverton SoC pinctrl/GPIO driver
*
- * Copyright (C) 2017, Intel Corporation
+ * Copyright (C) 2017 Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-elkhartlake.c b/drivers/pinctrl/intel/pinctrl-elkhartlake.c
index 0e8742f31cd4..8a24ef12141d 100644
--- a/drivers/pinctrl/intel/pinctrl-elkhartlake.c
+++ b/drivers/pinctrl/intel/pinctrl-elkhartlake.c
@@ -2,7 +2,7 @@
/*
* Intel Elkhart Lake PCH pinctrl/GPIO driver
*
- * Copyright (C) 2019, Intel Corporation
+ * Copyright (C) 2019 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-emmitsburg.c b/drivers/pinctrl/intel/pinctrl-emmitsburg.c
index ba06a9ec239a..3b63b6dd2560 100644
--- a/drivers/pinctrl/intel/pinctrl-emmitsburg.c
+++ b/drivers/pinctrl/intel/pinctrl-emmitsburg.c
@@ -2,7 +2,7 @@
/*
* Intel Emmitsburg PCH pinctrl/GPIO driver
*
- * Copyright (C) 2020, Intel Corporation
+ * Copyright (C) 2020 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-icelake.c b/drivers/pinctrl/intel/pinctrl-icelake.c
index 1516fe7b4e4a..daabc5288cbb 100644
--- a/drivers/pinctrl/intel/pinctrl-icelake.c
+++ b/drivers/pinctrl/intel/pinctrl-icelake.c
@@ -2,7 +2,7 @@
/*
* Intel Ice Lake PCH pinctrl/GPIO driver
*
- * Copyright (C) 2018, 2022 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-intel-platform.c b/drivers/pinctrl/intel/pinctrl-intel-platform.c
index dd5dbede0f59..61dd579e3f97 100644
--- a/drivers/pinctrl/intel/pinctrl-intel-platform.c
+++ b/drivers/pinctrl/intel/pinctrl-intel-platform.c
@@ -2,7 +2,7 @@
/*
* Intel PCH pinctrl/GPIO driver
*
- * Copyright (C) 2021-2023, Intel Corporation
+ * Copyright (C) 2021-2023 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index cf9db8ac0f42..9d32bb8bc13a 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -2,7 +2,7 @@
/*
* Intel pinctrl/GPIO core driver.
*
- * Copyright (C) 2015, Intel Corporation
+ * Copyright (C) 2015 Intel Corporation
* Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
@@ -1673,7 +1673,7 @@ int intel_pinctrl_probe(struct platform_device *pdev,
pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl);
if (IS_ERR(pctrl->pctldev))
- return dev_err_probe(dev, PTR_ERR(pctrl->pctldev), "failed to register pinctrl\n");
+ return PTR_ERR(pctrl->pctldev);
ret = intel_gpio_probe(pctrl, irq);
if (ret)
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
index c1520797f895..2f37109d5860 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.h
+++ b/drivers/pinctrl/intel/pinctrl-intel.h
@@ -2,7 +2,7 @@
/*
* Core pinctrl/GPIO driver for Intel GPIO controllers
*
- * Copyright (C) 2015, Intel Corporation
+ * Copyright (C) 2015 Intel Corporation
* Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-jasperlake.c b/drivers/pinctrl/intel/pinctrl-jasperlake.c
index c6e1836c69a7..a8f65c3dbb1c 100644
--- a/drivers/pinctrl/intel/pinctrl-jasperlake.c
+++ b/drivers/pinctrl/intel/pinctrl-jasperlake.c
@@ -2,7 +2,7 @@
/*
* Intel Jasper Lake PCH pinctrl/GPIO driver
*
- * Copyright (C) 2020, Intel Corporation
+ * Copyright (C) 2020 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-lakefield.c b/drivers/pinctrl/intel/pinctrl-lakefield.c
index bfb8b565d15c..39872c352ac2 100644
--- a/drivers/pinctrl/intel/pinctrl-lakefield.c
+++ b/drivers/pinctrl/intel/pinctrl-lakefield.c
@@ -2,7 +2,7 @@
/*
* Intel Lakefield PCH pinctrl/GPIO driver
*
- * Copyright (C) 2020, Intel Corporation
+ * Copyright (C) 2020 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-lewisburg.c b/drivers/pinctrl/intel/pinctrl-lewisburg.c
index 9fe651370f32..ebbc94047b6f 100644
--- a/drivers/pinctrl/intel/pinctrl-lewisburg.c
+++ b/drivers/pinctrl/intel/pinctrl-lewisburg.c
@@ -2,7 +2,7 @@
/*
* Intel Lewisburg pinctrl/GPIO driver
*
- * Copyright (C) 2017, Intel Corporation
+ * Copyright (C) 2017 Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c
index 1565eefdd4bf..299ee4f22bdc 100644
--- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c
+++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c
@@ -2,7 +2,7 @@
/*
* Intel Lynxpoint PCH pinctrl/GPIO driver
*
- * Copyright (c) 2012, 2019, Intel Corporation
+ * Copyright (C) 2012-2019 Intel Corporation
* Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
* Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
@@ -29,10 +29,12 @@
#include "pinctrl-intel.h"
-#define COMMUNITY(p, n) \
+#define LPTLP_COMMUNITY(p, n, g) \
{ \
.pin_base = (p), \
.npins = (n), \
+ .gpps = (g), \
+ .ngpps = ARRAY_SIZE(g), \
}
static const struct pinctrl_pin_desc lptlp_pins[] = {
@@ -133,8 +135,14 @@ static const struct pinctrl_pin_desc lptlp_pins[] = {
PINCTRL_PIN(94, "GP94_UART0_CTSB"),
};
+static const struct intel_padgroup lptlp_gpps[] = {
+ INTEL_GPP(0, 0, 31, 0),
+ INTEL_GPP(1, 32, 63, 32),
+ INTEL_GPP(2, 64, 94, 64),
+};
+
static const struct intel_community lptlp_communities[] = {
- COMMUNITY(0, 95),
+ LPTLP_COMMUNITY(0, 95, lptlp_gpps),
};
static const struct intel_pinctrl_soc_data lptlp_soc_data = {
@@ -692,19 +700,6 @@ static int lp_gpio_irq_init_hw(struct gpio_chip *chip)
return 0;
}
-static int lp_gpio_add_pin_ranges(struct gpio_chip *chip)
-{
- struct intel_pinctrl *lg = gpiochip_get_data(chip);
- struct device *dev = lg->dev;
- int ret;
-
- ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, lg->soc->npins);
- if (ret)
- return dev_err_probe(dev, ret, "failed to add GPIO pin range\n");
-
- return 0;
-}
-
static int lp_gpio_probe(struct platform_device *pdev)
{
const struct intel_pinctrl_soc_data *soc;
@@ -740,7 +735,7 @@ static int lp_gpio_probe(struct platform_device *pdev)
lg->pctldev = devm_pinctrl_register(dev, &lg->pctldesc, lg);
if (IS_ERR(lg->pctldev))
- return dev_err_probe(dev, PTR_ERR(lg->pctldev), "failed to register pinctrl\n");
+ return PTR_ERR(lg->pctldev);
platform_set_drvdata(pdev, lg);
@@ -777,7 +772,7 @@ static int lp_gpio_probe(struct platform_device *pdev)
gc->base = -1;
gc->ngpio = LP_NUM_GPIO;
gc->can_sleep = false;
- gc->add_pin_ranges = lp_gpio_add_pin_ranges;
+ gc->add_pin_ranges = intel_gpio_add_pin_ranges;
gc->parent = dev;
/* set up interrupts */
diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c
index 2f4d73dda41d..83b4d1862545 100644
--- a/drivers/pinctrl/intel/pinctrl-merrifield.c
+++ b/drivers/pinctrl/intel/pinctrl-merrifield.c
@@ -2,7 +2,7 @@
/*
* Intel Merrifield SoC pinctrl driver
*
- * Copyright (C) 2016, Intel Corporation
+ * Copyright (C) 2016 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-meteorlake.c b/drivers/pinctrl/intel/pinctrl-meteorlake.c
index b7395947569a..3f5070a339bf 100644
--- a/drivers/pinctrl/intel/pinctrl-meteorlake.c
+++ b/drivers/pinctrl/intel/pinctrl-meteorlake.c
@@ -2,7 +2,7 @@
/*
* Intel Meteor Lake PCH pinctrl/GPIO driver
*
- * Copyright (C) 2022, Intel Corporation
+ * Copyright (C) 2022 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-meteorpoint.c b/drivers/pinctrl/intel/pinctrl-meteorpoint.c
index b7858c2b2c5c..bff7be1f137d 100644
--- a/drivers/pinctrl/intel/pinctrl-meteorpoint.c
+++ b/drivers/pinctrl/intel/pinctrl-meteorpoint.c
@@ -2,7 +2,7 @@
/*
* Intel Meteor Point PCH pinctrl/GPIO driver
*
- * Copyright (C) 2022-2023, Intel Corporation
+ * Copyright (C) 2022-2023 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-moorefield.c b/drivers/pinctrl/intel/pinctrl-moorefield.c
index 6a79207e6b2a..30f9a4481827 100644
--- a/drivers/pinctrl/intel/pinctrl-moorefield.c
+++ b/drivers/pinctrl/intel/pinctrl-moorefield.c
@@ -2,7 +2,7 @@
/*
* Intel Moorefield SoC pinctrl driver
*
- * Copyright (C) 2022, Intel Corporation
+ * Copyright (C) 2022 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
index b51befde9e8b..308651091d9c 100644
--- a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
+++ b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
@@ -2,7 +2,7 @@
/*
* Intel Sunrisepoint PCH pinctrl/GPIO driver
*
- * Copyright (C) 2015, Intel Corporation
+ * Copyright (C) 2015 Intel Corporation
* Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/intel/pinctrl-tangier.c b/drivers/pinctrl/intel/pinctrl-tangier.c
index 5f0b7334a489..5fc13d369dd8 100644
--- a/drivers/pinctrl/intel/pinctrl-tangier.c
+++ b/drivers/pinctrl/intel/pinctrl-tangier.c
@@ -2,7 +2,7 @@
/*
* Intel Tangier pinctrl driver
*
- * Copyright (C) 2016, 2023 Intel Corporation
+ * Copyright (C) 2016-2023 Intel Corporation
*
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Raag Jadav <raag.jadav@intel.com>
@@ -518,15 +518,19 @@ static const struct pinctrl_desc tng_pinctrl_desc = {
.owner = THIS_MODULE,
};
-static int tng_pinctrl_probe(struct platform_device *pdev,
- const struct tng_pinctrl *data)
+int devm_tng_pinctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ const struct tng_pinctrl *data;
struct tng_family *families;
struct tng_pinctrl *tp;
void __iomem *regs;
unsigned int i;
+ data = device_get_match_data(dev);
+ if (!data)
+ return -ENODATA;
+
tp = devm_kmemdup(dev, data, sizeof(*data), GFP_KERNEL);
if (!tp)
return -ENOMEM;
@@ -562,21 +566,10 @@ static int tng_pinctrl_probe(struct platform_device *pdev,
tp->pctldev = devm_pinctrl_register(dev, &tp->pctldesc, tp);
if (IS_ERR(tp->pctldev))
- return dev_err_probe(dev, PTR_ERR(tp->pctldev), "failed to register pinctrl\n");
+ return PTR_ERR(tp->pctldev);
return 0;
}
-
-int devm_tng_pinctrl_probe(struct platform_device *pdev)
-{
- const struct tng_pinctrl *data;
-
- data = device_get_match_data(&pdev->dev);
- if (!data)
- return -ENODATA;
-
- return tng_pinctrl_probe(pdev, data);
-}
EXPORT_SYMBOL_NS_GPL(devm_tng_pinctrl_probe, "PINCTRL_TANGIER");
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
diff --git a/drivers/pinctrl/intel/pinctrl-tangier.h b/drivers/pinctrl/intel/pinctrl-tangier.h
index 955cc967c0bc..6af8eeeae943 100644
--- a/drivers/pinctrl/intel/pinctrl-tangier.h
+++ b/drivers/pinctrl/intel/pinctrl-tangier.h
@@ -2,7 +2,7 @@
/*
* Intel Tangier pinctrl functions
*
- * Copyright (C) 2016, 2023 Intel Corporation
+ * Copyright (C) 2016-2023 Intel Corporation
*
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Raag Jadav <raag.jadav@intel.com>
diff --git a/drivers/pinctrl/intel/pinctrl-tigerlake.c b/drivers/pinctrl/intel/pinctrl-tigerlake.c
index c0887596d113..ae231f7fba49 100644
--- a/drivers/pinctrl/intel/pinctrl-tigerlake.c
+++ b/drivers/pinctrl/intel/pinctrl-tigerlake.c
@@ -2,7 +2,7 @@
/*
* Intel Tiger Lake PCH pinctrl/GPIO driver
*
- * Copyright (C) 2019 - 2020, Intel Corporation
+ * Copyright (C) 2019-2020 Intel Corporation
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
index c8c5097c11c4..2a3c04eedc5f 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.c
+++ b/drivers/pinctrl/mediatek/mtk-eint.c
@@ -544,24 +544,32 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)
}
}
- eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL);
+ eint->pin_list = devm_kcalloc(eint->dev, eint->nbase,
+ sizeof(*eint->pin_list), GFP_KERNEL);
if (!eint->pin_list)
goto err_pin_list;
- eint->wake_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
+ eint->wake_mask = devm_kcalloc(eint->dev, eint->nbase,
+ sizeof(*eint->wake_mask), GFP_KERNEL);
if (!eint->wake_mask)
goto err_wake_mask;
- eint->cur_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
+ eint->cur_mask = devm_kcalloc(eint->dev, eint->nbase,
+ sizeof(*eint->cur_mask), GFP_KERNEL);
if (!eint->cur_mask)
goto err_cur_mask;
for (i = 0; i < eint->nbase; i++) {
- eint->pin_list[i] = devm_kzalloc(eint->dev, eint->base_pin_num[i] * sizeof(u16),
+ eint->pin_list[i] = devm_kzalloc(eint->dev,
+ eint->base_pin_num[i] * sizeof(**eint->pin_list),
GFP_KERNEL);
port = DIV_ROUND_UP(eint->base_pin_num[i], 32);
- eint->wake_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
- eint->cur_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
+ eint->wake_mask[i] = devm_kzalloc(eint->dev,
+ port * sizeof(**eint->wake_mask),
+ GFP_KERNEL);
+ eint->cur_mask[i] = devm_kzalloc(eint->dev,
+ port * sizeof(**eint->cur_mask),
+ GFP_KERNEL);
if (!eint->pin_list[i] || !eint->wake_mask[i] || !eint->cur_mask[i])
goto err_eint;
}
@@ -597,12 +605,9 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)
err_eint:
for (i = 0; i < eint->nbase; i++) {
- if (eint->cur_mask[i])
- devm_kfree(eint->dev, eint->cur_mask[i]);
- if (eint->wake_mask[i])
- devm_kfree(eint->dev, eint->wake_mask[i]);
- if (eint->pin_list[i])
- devm_kfree(eint->dev, eint->pin_list[i]);
+ devm_kfree(eint->dev, eint->cur_mask[i]);
+ devm_kfree(eint->dev, eint->wake_mask[i]);
+ devm_kfree(eint->dev, eint->pin_list[i]);
}
devm_kfree(eint->dev, eint->cur_mask);
err_cur_mask:
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7981.c b/drivers/pinctrl/mediatek/pinctrl-mt7981.c
index 6216c2e057f6..22c8f2480346 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c
@@ -1019,7 +1019,7 @@ static struct mtk_pin_soc mt7981_data = {
.nfuncs = ARRAY_SIZE(mt7981_functions),
.eint_hw = &mt7981_eint_hw,
.gpio_m = 0,
- .ies_present = false,
+ .ies_present = true,
.base_names = mt7981_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7986.c b/drivers/pinctrl/mediatek/pinctrl-mt7986.c
index 2a762ade9c35..5dda4b7467fd 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c
@@ -919,7 +919,7 @@ static struct mtk_pin_soc mt7986a_data = {
.nfuncs = ARRAY_SIZE(mt7986_functions),
.eint_hw = &mt7986a_eint_hw,
.gpio_m = 0,
- .ies_present = false,
+ .ies_present = true,
.base_names = mt7986_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set,
@@ -945,7 +945,7 @@ static struct mtk_pin_soc mt7986b_data = {
.nfuncs = ARRAY_SIZE(mt7986_functions),
.eint_hw = &mt7986b_eint_hw,
.gpio_m = 0,
- .ies_present = false,
+ .ies_present = true,
.base_names = mt7986_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/drivers/pinctrl/mediatek/pinctrl-mt7988.c
index 9569e8c0cec1..fd3a7ff0a04d 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7988.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7988.c
@@ -1505,7 +1505,7 @@ static const struct mtk_pin_soc mt7988_data = {
.nfuncs = ARRAY_SIZE(mt7988_functions),
.eint_hw = &mt7988_eint_hw,
.gpio_m = 0,
- .ies_present = false,
+ .ies_present = true,
.base_names = mt7988_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt7988_pinctrl_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8365.c b/drivers/pinctrl/mediatek/pinctrl-mt8365.c
index e3e0d66cfbbf..c20b9e2e02dd 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8365.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8365.c
@@ -456,7 +456,6 @@ static const struct mtk_pinctrl_devdata mt8365_pinctrl_data = {
.smt_offset = 0x0470,
.pullen_offset = 0x0860,
.pullsel_offset = 0x0900,
- .drv_offset = 0x0710,
.type1_start = 145,
.type1_end = 145,
.port_shf = 4,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
index 11afa12a96cb..3b96f3dd338d 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
@@ -263,7 +263,6 @@ struct mtk_pinctrl_devdata {
unsigned int smt_offset;
unsigned int pullen_offset;
unsigned int pullsel_offset;
- unsigned int drv_offset;
unsigned int dout_offset;
unsigned int din_offset;
unsigned int pinmux_offset;
diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
index 0315e224bce6..ce6aeec2fc79 100644
--- a/drivers/pinctrl/meson/Kconfig
+++ b/drivers/pinctrl/meson/Kconfig
@@ -15,25 +15,25 @@ if PINCTRL_MESON
config PINCTRL_MESON8
bool "Meson 8 SoC pinctrl driver"
- depends on ARM
+ depends on ARM || COMPILE_TEST
select PINCTRL_MESON8_PMX
default ARCH_MESON
config PINCTRL_MESON8B
bool "Meson 8b SoC pinctrl driver"
- depends on ARM
+ depends on ARM || COMPILE_TEST
select PINCTRL_MESON8_PMX
default ARCH_MESON
config PINCTRL_MESON_GXBB
tristate "Meson gxbb SoC pinctrl driver"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
select PINCTRL_MESON8_PMX
default ARCH_MESON
config PINCTRL_MESON_GXL
tristate "Meson gxl SoC pinctrl driver"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
select PINCTRL_MESON8_PMX
default ARCH_MESON
@@ -42,7 +42,7 @@ config PINCTRL_MESON8_PMX
config PINCTRL_MESON_AXG
tristate "Meson axg Soc pinctrl driver"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
select PINCTRL_MESON_AXG_PMX
default ARCH_MESON
@@ -51,25 +51,25 @@ config PINCTRL_MESON_AXG_PMX
config PINCTRL_MESON_G12A
tristate "Meson g12a Soc pinctrl driver"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
select PINCTRL_MESON_AXG_PMX
default ARCH_MESON
config PINCTRL_MESON_A1
tristate "Meson a1 Soc pinctrl driver"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
select PINCTRL_MESON_AXG_PMX
default ARCH_MESON
config PINCTRL_MESON_S4
tristate "Meson s4 Soc pinctrl driver"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
select PINCTRL_MESON_AXG_PMX
default ARCH_MESON
config PINCTRL_AMLOGIC_A4
bool "AMLOGIC pincontrol"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
default ARCH_MESON
help
This is the driver for the pin controller found on Amlogic SoCs.
@@ -80,13 +80,13 @@ config PINCTRL_AMLOGIC_A4
config PINCTRL_AMLOGIC_C3
tristate "Amlogic C3 SoC pinctrl driver"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
select PINCTRL_MESON_AXG_PMX
default ARCH_MESON
config PINCTRL_AMLOGIC_T7
tristate "Amlogic T7 SoC pinctrl driver"
- depends on ARM64
+ depends on ARM64 || COMPILE_TEST
select PINCTRL_MESON_AXG_PMX
default ARCH_MESON
diff --git a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
index d9e3a8d5932a..dfa32b11555c 100644
--- a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
+++ b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
@@ -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,
};
@@ -725,8 +794,9 @@ static u32 aml_bank_pins(struct device_node *np)
if (of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
0, &of_args))
return 0;
- else
- return of_args.args[2];
+
+ of_node_put(of_args.np);
+ return of_args.args[2];
}
static int aml_bank_number(struct device_node *np)
@@ -736,8 +806,9 @@ static int aml_bank_number(struct device_node *np)
if (of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
0, &of_args))
return -EINVAL;
- else
- return of_args.args[1] >> 8;
+
+ of_node_put(of_args.np);
+ return of_args.args[1] >> 8;
}
static unsigned int aml_count_pins(struct device_node *np)
@@ -893,7 +964,7 @@ static const struct gpio_chip aml_gpio_template = {
.direction_input = aml_gpio_direction_input,
.direction_output = aml_gpio_direction_output,
.get_direction = aml_gpio_get_direction,
- .can_sleep = false,
+ .can_sleep = true,
};
static void init_bank_register_bit(struct aml_pinctrl *info,
diff --git a/drivers/pinctrl/microchip/Kconfig b/drivers/pinctrl/microchip/Kconfig
new file mode 100644
index 000000000000..aba55f686f45
--- /dev/null
+++ b/drivers/pinctrl/microchip/Kconfig
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config PINCTRL_PIC64GX
+ bool "pic64gx gpio2 pinctrl driver"
+ depends on ARCH_MICROCHIP || COMPILE_TEST
+ depends on OF
+ select GENERIC_PINCONF
+ select REGMAP_MMIO
+ help
+ This selects the pinctrl driver for gpio2 on pic64gx.
+
+config PINCTRL_POLARFIRE_SOC
+ bool "Polarfire SoC pinctrl drivers"
+ depends on ARCH_MICROCHIP || COMPILE_TEST
+ depends on OF
+ select GENERIC_PINCTRL
+ help
+ This selects the pinctrl drivers for Microchip Polarfire SoC.
diff --git a/drivers/pinctrl/microchip/Makefile b/drivers/pinctrl/microchip/Makefile
new file mode 100644
index 000000000000..ab0575cd2ed1
--- /dev/null
+++ b/drivers/pinctrl/microchip/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_PINCTRL_PIC64GX) += pinctrl-pic64gx-gpio2.o
+obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-iomux0.o
+obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-mssio.o
diff --git a/drivers/pinctrl/pinctrl-mpfs-iomux0.c b/drivers/pinctrl/microchip/pinctrl-mpfs-iomux0.c
index cf5b2e4e8f5b..1b060a038920 100644
--- a/drivers/pinctrl/pinctrl-mpfs-iomux0.c
+++ b/drivers/pinctrl/microchip/pinctrl-mpfs-iomux0.c
@@ -15,10 +15,10 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
-#include "core.h"
-#include "pinctrl-utils.h"
-#include "pinconf.h"
-#include "pinmux.h"
+#include "../core.h"
+#include "../pinctrl-utils.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
#define MPFS_IOMUX0_REG 0x200
diff --git a/drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c b/drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c
new file mode 100644
index 000000000000..3d5ffd6cb14b
--- /dev/null
+++ b/drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c
@@ -0,0 +1,737 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/seq_file.h>
+
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+
+#define MPFS_PINCTRL_PAD_MUX_MASK GENMASK(3, 0)
+
+#define MPFS_PINCTRL_IOCFG_MASK GENMASK(14, 0)
+#define MPFS_PINCTRL_IBUFMD_MASK GENMASK(2, 0)
+#define MPFS_PINCTRL_DRV_MASK GENMASK(6, 3)
+#define MPFS_PINCTRL_CLAMP BIT(7)
+#define MPFS_PINCTRL_ENHYST BIT(8)
+#define MPFS_PINCTRL_LOCKDN BIT(9)
+#define MPFS_PINCTRL_WPD BIT(10)
+#define MPFS_PINCTRL_WPU BIT(11)
+#define MPFS_PINCTRL_PULL_MASK GENMASK(11, 10)
+#define MPFS_PINCTRL_LP_PERSIST_EN BIT(12)
+#define MPFS_PINCTRL_LP_BYPASS_EN BIT(13)
+
+#define MPFS_PINCTRL_MSSIO_BANK2_CFG_CR 0x1c4
+#define MPFS_PINCTRL_MSSIO_BANK4_CFG_CR 0x1c8
+#define MPFS_PINCTRL_BANK_VOLTAGE_MASK GENMASK(19, 16)
+
+#define MPFS_PINCTRL_IOCFG01_REG 0x234
+
+#define MPFS_PINCTRL_INTER_BANK_GAP 0x4
+
+#define MPFS_PINCTRL_BANK2_START 14
+
+#define MPFS_PINCTRL_LOCKDOWN (PIN_CONFIG_END + 1)
+#define MPFS_PINCTRL_CLAMP_DIODE (PIN_CONFIG_END + 2)
+#define MPFS_PINCTRL_IBUFMD (PIN_CONFIG_END + 3)
+
+struct mpfs_pinctrl_mux_config {
+ u8 pin;
+ u8 function;
+};
+
+struct mpfs_pinctrl {
+ struct pinctrl_dev *pctrl;
+ struct device *dev;
+ struct regmap *regmap;
+ struct regmap *sysreg_regmap;
+ struct mutex mutex;
+ struct pinctrl_desc desc;
+};
+
+struct mpfs_pinctrl_drive_strength {
+ u8 ma;
+ u8 val;
+};
+
+struct mpfs_pinctrl_bank_voltage {
+ u32 uv;
+ u8 val;
+};
+
+static struct mpfs_pinctrl_drive_strength mpfs_pinctrl_drive_strengths[8] = {
+ { .ma = 2, .val = 2 },
+ { .ma = 4, .val = 3 },
+ { .ma = 6, .val = 4 },
+ { .ma = 8, .val = 5 },
+ { .ma = 10, .val = 6 },
+ { .ma = 12, .val = 7 },
+ { .ma = 16, .val = 10 },
+ { .ma = 20, .val = 12 },
+};
+static struct mpfs_pinctrl_bank_voltage mpfs_pinctrl_bank_voltages[8] = {
+ { .uv = 1200000, .val = 0 },
+ { .uv = 1500000, .val = 2 },
+ { .uv = 1800000, .val = 4 },
+ { .uv = 2500000, .val = 6 },
+ { .uv = 3300000, .val = 8 },
+ { .uv = 0, .val = 0x3f }, // pin unused
+};
+
+static int mpfs_pinctrl_get_drive_strength_ma(u32 drive_strength)
+{
+ size_t num = ARRAY_SIZE(mpfs_pinctrl_drive_strengths);
+
+ for (int i = 0; i < num; i++)
+ if (drive_strength == mpfs_pinctrl_drive_strengths[i].val)
+ return mpfs_pinctrl_drive_strengths[i].ma;
+
+ return -EINVAL;
+}
+
+static int mpfs_pinctrl_get_drive_strength_val(u32 drive_strength_ma)
+{
+ size_t num = ARRAY_SIZE(mpfs_pinctrl_drive_strengths);
+
+ if (!drive_strength_ma)
+ return -EINVAL;
+
+ for (int i = 0; i < num; i++)
+ if (drive_strength_ma <= mpfs_pinctrl_drive_strengths[i].ma)
+ return mpfs_pinctrl_drive_strengths[i].val;
+
+ return mpfs_pinctrl_drive_strengths[num - 1].val;
+}
+
+static int mpfs_pinctrl_get_bank_voltage_uv(u32 bank_voltage)
+{
+ size_t num = ARRAY_SIZE(mpfs_pinctrl_bank_voltages);
+
+ for (int i = 0; i < num; i++)
+ if (bank_voltage == mpfs_pinctrl_bank_voltages[i].val)
+ return mpfs_pinctrl_bank_voltages[i].uv;
+
+ return -EINVAL;
+}
+
+static int mpfs_pinctrl_get_bank_voltage_val(u32 bank_voltage_uv)
+{
+ size_t num = ARRAY_SIZE(mpfs_pinctrl_bank_voltages);
+
+ for (int i = 0; i < num; i++)
+ if (bank_voltage_uv <= mpfs_pinctrl_bank_voltages[i].uv)
+ return mpfs_pinctrl_bank_voltages[i].val;
+
+ return -EINVAL;
+}
+
+static u32 mpfs_pinctrl_pin_to_bank_voltage(struct mpfs_pinctrl *pctrl, unsigned int pin)
+{
+ u32 bank_voltage, val;
+
+ if (pin < MPFS_PINCTRL_BANK2_START)
+ regmap_read(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK4_CFG_CR, &val);
+ else
+ regmap_read(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK2_CFG_CR, &val);
+
+ bank_voltage = FIELD_GET(MPFS_PINCTRL_BANK_VOLTAGE_MASK, val);
+
+ return mpfs_pinctrl_get_bank_voltage_uv(bank_voltage);
+}
+
+static void mpfs_pinctrl_set_bank_voltage(struct mpfs_pinctrl *pctrl, unsigned int pin,
+ u32 bank_voltage)
+{
+ u32 val = FIELD_PREP(MPFS_PINCTRL_BANK_VOLTAGE_MASK, bank_voltage);
+
+ if (pin < MPFS_PINCTRL_BANK2_START)
+ regmap_assign_bits(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK4_CFG_CR,
+ MPFS_PINCTRL_BANK_VOLTAGE_MASK, val);
+ else
+ regmap_assign_bits(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK2_CFG_CR,
+ MPFS_PINCTRL_BANK_VOLTAGE_MASK, val);
+}
+
+static char *mpfs_pinctrl_function_names[] = {
+ "sd",
+ "emmc",
+ "qspi",
+ "spi",
+ "usb",
+ "uart",
+ "i2c",
+ "can",
+ "mdio",
+ "misc",
+ "reserved",
+ "gpio",
+ "fabric test",
+ "tied-low",
+ "tied-high",
+ "tristate"
+};
+
+static int mpfs_pinctrl_function_map(const char *function)
+{
+ size_t num = ARRAY_SIZE(mpfs_pinctrl_function_names);
+
+ for (int i = 0; i < num; i++)
+ if (!strcmp(function, mpfs_pinctrl_function_names[i]))
+ return i;
+
+ return -EINVAL;
+}
+
+static const struct pinconf_generic_params mpfs_pinctrl_custom_bindings[] = {
+ { "microchip,clamp-diode", MPFS_PINCTRL_CLAMP_DIODE, 1 },
+ { "microchip,ibufmd", MPFS_PINCTRL_IBUFMD, 0x0 },
+};
+
+static int mpfs_pinctrl_pin_to_iomux_offset(unsigned int pin)
+{
+ int offset;
+
+ switch (pin) {
+ case 0 ... 7:
+ offset = pin * 4;
+ break;
+ case 8 ... 13:
+ offset = (pin - 8) * 4;
+ break;
+ case 14 ... 21:
+ offset = (pin - 14) * 4;
+ break;
+ case 22 ... 29:
+ offset = (pin - 22) * 4;
+ break;
+ case 30 ... 37:
+ offset = (pin - 30) * 4;
+ break;
+ default:
+ offset = -EINVAL;
+ }
+
+ return offset;
+}
+
+static int mpfs_pinctrl_pin_to_iomux_reg(unsigned int pin)
+{
+ int reg;
+
+ switch (pin) {
+ case 0 ... 7:
+ reg = 0x204;
+ break;
+ case 8 ... 13:
+ reg = 0x208;
+ break;
+ case 14 ... 21:
+ reg = 0x20c;
+ break;
+ case 22 ... 29:
+ reg = 0x210;
+ break;
+ case 30 ... 37:
+ reg = 0x214;
+ break;
+ default:
+ reg = -EINVAL;
+ }
+
+ return reg;
+}
+
+static int mpfs_pinctrl_pin_to_iocfg_reg(unsigned int pin)
+{
+ u32 reg = MPFS_PINCTRL_IOCFG01_REG;
+
+ if (pin >= MPFS_PINCTRL_BANK2_START)
+ reg += MPFS_PINCTRL_INTER_BANK_GAP;
+
+ // 2 pins per 32-bit register
+ reg += (pin / 2) * 0x4;
+
+ return reg;
+}
+
+static int mpfs_pinctrl_pin_to_iocfg_offset(unsigned int pin)
+{
+ return 16 * (pin % 2);
+}
+
+static void mpfs_pinctrl_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq,
+ unsigned int pin)
+{
+ struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ u32 func;
+ int reg, offset;
+
+ reg = mpfs_pinctrl_pin_to_iomux_reg(pin);
+ offset = mpfs_pinctrl_pin_to_iomux_offset(pin);
+
+ seq_printf(seq, "reg: %x, offset: %u ", reg, offset);
+ seq_printf(seq, "pin: %u ", pin);
+
+ if (reg < 0 || offset < 0)
+ return;
+
+ regmap_read(pctrl->regmap, reg, &func);
+ func = (func >> offset) & MPFS_PINCTRL_PAD_MUX_MASK;
+ seq_printf(seq, "func: %s (%x)\n", mpfs_pinctrl_function_names[func], func);
+}
+
+static const struct pinctrl_ops mpfs_pinctrl_ops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .pin_dbg_show = mpfs_pinctrl_dbg_show,
+ .dt_node_to_map = pinctrl_generic_pins_function_dt_node_to_map,
+ .dt_free_map = pinctrl_utils_free_map,
+};
+
+static int mpfs_pinctrl_set_pin_func(struct mpfs_pinctrl *pctrl, u8 pin, u8 function)
+{
+ struct device *dev = pctrl->dev;
+ int reg, offset;
+ u32 func, mask;
+
+ reg = mpfs_pinctrl_pin_to_iomux_reg(pin);
+ offset = mpfs_pinctrl_pin_to_iomux_offset(pin);
+
+ func = function << offset;
+ mask = MPFS_PINCTRL_PAD_MUX_MASK << offset;
+
+ dev_dbg(dev, "Setting pin %u. reg: %x offset %u func %x\n", pin, reg, offset, func);
+
+ if (reg < 0 || offset < 0)
+ return -EINVAL;
+
+ regmap_update_bits(pctrl->regmap, reg, mask, func);
+
+ return 0;
+}
+
+static int mpfs_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev, unsigned int fsel,
+ unsigned int gsel)
+{
+ struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ const struct group_desc *group;
+ const char **functions;
+
+ group = pinctrl_generic_get_group(pctrl_dev, gsel);
+ if (!group)
+ return -EINVAL;
+
+ functions = group->data;
+
+ for (int i = 0; i < group->grp.npins; i++) {
+ int function;
+
+ function = mpfs_pinctrl_function_map(functions[i]);
+ if (function < 0) {
+ dev_err(pctrl->dev, "invalid function %s\n", functions[i]);
+ return function;
+ }
+
+ mpfs_pinctrl_set_pin_func(pctrl, group->grp.pins[i], function);
+ }
+
+ return 0;
+}
+
+static const struct pinmux_ops mpfs_pinctrl_pinmux_ops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = mpfs_pinctrl_set_mux,
+};
+
+static int mpfs_pinctrl_pinconf_get(struct pinctrl_dev *pctrl_dev, unsigned int pin,
+ unsigned long *config)
+{
+ struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ int param = pinconf_to_config_param(*config);
+ int reg = mpfs_pinctrl_pin_to_iocfg_reg(pin);
+ int val;
+ u32 arg;
+ u8 str;
+
+ regmap_read(pctrl->regmap, reg, &val);
+
+ val = val >> mpfs_pinctrl_pin_to_iocfg_offset(pin);
+ val = val & MPFS_PINCTRL_IOCFG_MASK;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ if (!(val & MPFS_PINCTRL_WPD))
+ return -EINVAL;
+
+ if (!(val & MPFS_PINCTRL_WPU))
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (!(val & MPFS_PINCTRL_WPD))
+ return -EINVAL;
+
+ if (val & MPFS_PINCTRL_WPU)
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (!(val & MPFS_PINCTRL_WPU))
+ return -EINVAL;
+
+ if (val & MPFS_PINCTRL_WPD)
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ if (val & MPFS_PINCTRL_PULL_MASK)
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ str = FIELD_GET(MPFS_PINCTRL_DRV_MASK, val);
+ if (!str)
+ return -EINVAL;
+
+ arg = mpfs_pinctrl_get_drive_strength_ma(str);
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (!FIELD_GET(MPFS_PINCTRL_ENHYST, val))
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case PIN_CONFIG_PERSIST_STATE:
+ if (!FIELD_GET(MPFS_PINCTRL_LP_PERSIST_EN, val))
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case PIN_CONFIG_MODE_LOW_POWER:
+ if (!FIELD_GET(MPFS_PINCTRL_LP_BYPASS_EN, val))
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ arg = mpfs_pinctrl_pin_to_bank_voltage(pctrl, pin);
+ break;
+ case MPFS_PINCTRL_CLAMP_DIODE:
+ if (!FIELD_GET(MPFS_PINCTRL_CLAMP, val))
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case MPFS_PINCTRL_LOCKDOWN:
+ /*
+ * Lockdown is a read-only configuration, it'll get set if the
+ * tamper unit triggers global lockdown and lockdown has been
+ * set in the MSS Configurator for the bank a pin belongs to.
+ */
+ if (!FIELD_GET(MPFS_PINCTRL_LOCKDN, val))
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ case MPFS_PINCTRL_IBUFMD:
+ arg = FIELD_GET(MPFS_PINCTRL_IBUFMD_MASK, val);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int mpfs_pinctrl_pinconf_generate_config(struct mpfs_pinctrl *pctrl, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs,
+ u32 *value, u32 *bank_voltage)
+{
+ u32 val = 0;
+
+ for (int i = 0; i < num_configs; i++) {
+ int param, tmp;
+ u32 arg;
+
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ val |= MPFS_PINCTRL_PULL_MASK;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ val &= ~MPFS_PINCTRL_PULL_MASK;
+ val |= MPFS_PINCTRL_WPD;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ val &= ~MPFS_PINCTRL_PULL_MASK;
+ val |= MPFS_PINCTRL_WPU;
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ val &= ~MPFS_PINCTRL_PULL_MASK;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ tmp = mpfs_pinctrl_get_drive_strength_val(arg);
+ if (tmp < 0)
+ return tmp;
+
+ val |= FIELD_PREP(MPFS_PINCTRL_DRV_MASK, tmp);
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (!arg)
+ break;
+ val |= MPFS_PINCTRL_ENHYST;
+ break;
+ case PIN_CONFIG_PERSIST_STATE:
+ val |= MPFS_PINCTRL_LP_PERSIST_EN;
+ break;
+ case PIN_CONFIG_MODE_LOW_POWER:
+ if (arg)
+ val |= MPFS_PINCTRL_LP_BYPASS_EN;
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ tmp = mpfs_pinctrl_get_bank_voltage_val(arg);
+ if (tmp < 0)
+ return tmp;
+
+ *bank_voltage = tmp;
+ break;
+ case MPFS_PINCTRL_CLAMP_DIODE:
+ val |= MPFS_PINCTRL_CLAMP;
+ break;
+ case MPFS_PINCTRL_IBUFMD:
+ val |= FIELD_PREP(MPFS_PINCTRL_IBUFMD_MASK, arg);
+ break;
+ default:
+ dev_err(pctrl->dev, "config %u not supported\n", param);
+ return -ENOTSUPP;
+ }
+ }
+
+ *value = val;
+ return 0;
+}
+
+static int mpfs_pinctrl_pin_set_config(struct mpfs_pinctrl *pctrl, unsigned int pin, u32 config)
+{
+ int reg = mpfs_pinctrl_pin_to_iocfg_reg(pin);
+ int offset = mpfs_pinctrl_pin_to_iocfg_offset(pin);
+ u32 val, mask;
+
+ mask = MPFS_PINCTRL_IOCFG_MASK << offset;
+ val = config << offset;
+
+ regmap_update_bits(pctrl->regmap, reg, mask, val);
+
+ return 0;
+}
+
+static int mpfs_pinctrl_pinconf_set(struct pinctrl_dev *pctrl_dev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ u32 val, bank_voltage = 0;
+ int ret;
+
+ ret = mpfs_pinctrl_pinconf_generate_config(pctrl, pin, configs, num_configs, &val,
+ &bank_voltage);
+ if (ret)
+ return ret;
+
+ ret = mpfs_pinctrl_pin_set_config(pctrl, pin, val);
+ if (ret)
+ return ret;
+
+ if (bank_voltage)
+ mpfs_pinctrl_set_bank_voltage(pctrl, pin, bank_voltage);
+
+ return 0;
+}
+
+static int mpfs_pinctrl_pinconf_group_set(struct pinctrl_dev *pctrl_dev, unsigned int gsel,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ const struct group_desc *group;
+ unsigned int pin;
+ u32 val, bank_voltage = 0;
+ int ret;
+
+ group = pinctrl_generic_get_group(pctrl_dev, gsel);
+ if (!group)
+ return -EINVAL;
+
+ /*
+ * Assume that the first pin in a group is representative, as the mss
+ * configurator doesn't allow splitting a function between two banks.
+ */
+ pin = group->grp.pins[0];
+
+ ret = mpfs_pinctrl_pinconf_generate_config(pctrl, pin, configs, num_configs, &val,
+ &bank_voltage);
+ if (ret)
+ return ret;
+
+ for (int i = 0; i < group->grp.npins; i++)
+ mpfs_pinctrl_pin_set_config(pctrl, group->grp.pins[i], val);
+
+ if (bank_voltage)
+ mpfs_pinctrl_set_bank_voltage(pctrl, group->grp.pins[0], bank_voltage);
+
+ return 0;
+}
+
+static void mpfs_pinctrl_pinconf_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq,
+ unsigned int pin)
+{
+ struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ u32 val;
+ int reg, offset;
+
+ reg = mpfs_pinctrl_pin_to_iocfg_reg(pin);
+ offset = mpfs_pinctrl_pin_to_iocfg_offset(pin);
+
+ seq_printf(seq, "pin: %u ", pin);
+ seq_printf(seq, "reg: %x offset: %u ", reg, offset);
+
+ if (reg < 0 || offset < 0)
+ return;
+
+ regmap_read(pctrl->regmap, reg, &val);
+ val = (val & (MPFS_PINCTRL_IOCFG_MASK << offset)) >> offset;
+ seq_printf(seq, "val: %x\n", val);
+}
+
+static const struct pinconf_ops mpfs_pinctrl_pinconf_ops = {
+ .pin_config_get = mpfs_pinctrl_pinconf_get,
+ .pin_config_set = mpfs_pinctrl_pinconf_set,
+ .pin_config_group_set = mpfs_pinctrl_pinconf_group_set,
+ .pin_config_dbg_show = mpfs_pinctrl_pinconf_dbg_show,
+ .is_generic = true,
+};
+
+static const struct pinctrl_pin_desc mpfs_pinctrl_pins[] = {
+ PINCTRL_PIN(0, "bank 4 0"),
+ PINCTRL_PIN(1, "bank 4 1"),
+ PINCTRL_PIN(2, "bank 4 2"),
+ PINCTRL_PIN(3, "bank 4 3"),
+ PINCTRL_PIN(4, "bank 4 4"),
+ PINCTRL_PIN(5, "bank 4 5"),
+ PINCTRL_PIN(6, "bank 4 6"),
+ PINCTRL_PIN(7, "bank 4 7"),
+ PINCTRL_PIN(8, "bank 4 8"),
+ PINCTRL_PIN(9, "bank 4 9"),
+ PINCTRL_PIN(10, "bank 4 10"),
+ PINCTRL_PIN(11, "bank 4 11"),
+ PINCTRL_PIN(12, "bank 4 12"),
+ PINCTRL_PIN(13, "bank 4 13"),
+
+ PINCTRL_PIN(14, "bank 2 0"),
+ PINCTRL_PIN(15, "bank 2 1"),
+ PINCTRL_PIN(16, "bank 2 2"),
+ PINCTRL_PIN(17, "bank 2 3"),
+ PINCTRL_PIN(18, "bank 2 4"),
+ PINCTRL_PIN(19, "bank 2 5"),
+ PINCTRL_PIN(20, "bank 2 6"),
+ PINCTRL_PIN(21, "bank 2 7"),
+ PINCTRL_PIN(22, "bank 2 8"),
+ PINCTRL_PIN(23, "bank 2 9"),
+ PINCTRL_PIN(24, "bank 2 10"),
+ PINCTRL_PIN(25, "bank 2 11"),
+ PINCTRL_PIN(26, "bank 2 12"),
+ PINCTRL_PIN(27, "bank 2 13"),
+ PINCTRL_PIN(28, "bank 2 14"),
+ PINCTRL_PIN(29, "bank 2 15"),
+ PINCTRL_PIN(30, "bank 2 16"),
+ PINCTRL_PIN(31, "bank 2 17"),
+ PINCTRL_PIN(32, "bank 2 18"),
+ PINCTRL_PIN(33, "bank 2 19"),
+ PINCTRL_PIN(34, "bank 2 20"),
+ PINCTRL_PIN(35, "bank 2 21"),
+ PINCTRL_PIN(36, "bank 2 22"),
+ PINCTRL_PIN(37, "bank 2 23"),
+};
+
+static int mpfs_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mpfs_pinctrl *pctrl;
+ int ret;
+
+ pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
+ if (!pctrl)
+ return -ENOMEM;
+
+ pctrl->regmap = 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->sysreg_regmap = syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb");
+ if (IS_ERR(pctrl->sysreg_regmap))
+ return PTR_ERR(pctrl->sysreg_regmap);
+
+ pctrl->desc.name = dev_name(dev);
+ pctrl->desc.pins = mpfs_pinctrl_pins;
+ pctrl->desc.npins = ARRAY_SIZE(mpfs_pinctrl_pins);
+ pctrl->desc.pctlops = &mpfs_pinctrl_ops;
+ pctrl->desc.pmxops = &mpfs_pinctrl_pinmux_ops;
+ pctrl->desc.confops = &mpfs_pinctrl_pinconf_ops;
+ pctrl->desc.owner = THIS_MODULE;
+ pctrl->desc.num_custom_params = ARRAY_SIZE(mpfs_pinctrl_custom_bindings);
+ pctrl->desc.custom_params = mpfs_pinctrl_custom_bindings;
+
+ pctrl->dev = dev;
+
+ ret = devm_mutex_init(dev, &pctrl->mutex);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, pctrl);
+
+ pctrl->pctrl = 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_pinctrl_of_match[] = {
+ { .compatible = "microchip,mpfs-pinctrl-mssio" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mpfs_pinctrl_of_match);
+
+static struct platform_driver mpfs_pinctrl_driver = {
+ .driver = {
+ .name = "mpfs-pinctrl",
+ .of_match_table = mpfs_pinctrl_of_match,
+ },
+ .probe = mpfs_pinctrl_probe,
+};
+module_platform_driver(mpfs_pinctrl_driver);
+
+MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
+MODULE_DESCRIPTION("Polarfire SoC mssio pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-pic64gx-gpio2.c b/drivers/pinctrl/microchip/pinctrl-pic64gx-gpio2.c
index f322bb5e6181..a0b3e839cf3b 100644
--- a/drivers/pinctrl/pinctrl-pic64gx-gpio2.c
+++ b/drivers/pinctrl/microchip/pinctrl-pic64gx-gpio2.c
@@ -14,7 +14,7 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
-#include "pinctrl-utils.h"
+#include "../pinctrl-utils.h"
#define PIC64GX_PINMUX_REG 0x0
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 366775841c63..94b1d057197c 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -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,
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index e1ae71610526..2880adef476e 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -160,3 +160,19 @@ pinconf_generic_parse_dt_pinmux(struct device_node *np, struct device *dev,
return -ENOTSUPP;
}
#endif
+
+#if defined(CONFIG_GENERIC_PINCTRL) && defined (CONFIG_OF)
+int pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **maps,
+ unsigned int *num_maps);
+#else
+static inline int
+pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **maps,
+ unsigned int *num_maps)
+{
+ return -ENOTSUPP;
+}
+#endif
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 2dac5c71eb00..2af94ef56434 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -21,11 +21,9 @@
#include <linux/gpio/driver.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
-#include <linux/mutex.h>
#include <linux/acpi.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
-#include <linux/list.h>
#include <linux/bitops.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
diff --git a/drivers/pinctrl/pinctrl-apple-gpio.c b/drivers/pinctrl/pinctrl-apple-gpio.c
index e1a7bc8cf765..2bd5013b19ac 100644
--- a/drivers/pinctrl/pinctrl-apple-gpio.c
+++ b/drivers/pinctrl/pinctrl-apple-gpio.c
@@ -102,9 +102,9 @@ static u32 apple_gpio_get_reg(struct apple_gpio_pinctrl *pctl,
static int apple_gpio_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *node,
struct pinctrl_map **map,
- unsigned *num_maps)
+ unsigned int *num_maps)
{
- unsigned reserved_maps;
+ unsigned int reserved_maps;
struct apple_gpio_pinctrl *pctl;
u32 pinfunc, pin, func;
int num_pins, i, ret;
@@ -170,8 +170,15 @@ static const struct pinctrl_ops apple_gpio_pinctrl_ops = {
/* Pin multiplexer functions */
-static int apple_gpio_pinmux_set(struct pinctrl_dev *pctldev, unsigned func,
- unsigned group)
+static bool apple_gpio_pinmux_func_is_gpio(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ /* Function selector 0 is always the GPIO mode */
+ return (selector == 0);
+}
+
+static int apple_gpio_pinmux_set(struct pinctrl_dev *pctldev, unsigned int func,
+ unsigned int group)
{
struct apple_gpio_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
@@ -186,6 +193,7 @@ static const struct pinmux_ops apple_gpio_pinmux_ops = {
.get_functions_count = pinmux_generic_get_function_count,
.get_function_name = pinmux_generic_get_function_name,
.get_function_groups = pinmux_generic_get_function_groups,
+ .function_is_gpio = apple_gpio_pinmux_func_is_gpio,
.set_mux = apple_gpio_pinmux_set,
.strict = true,
};
@@ -202,7 +210,7 @@ static int apple_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
return GPIO_LINE_DIRECTION_IN;
}
-static int apple_gpio_get(struct gpio_chip *chip, unsigned offset)
+static int apple_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct apple_gpio_pinctrl *pctl = gpiochip_get_data(chip);
unsigned int reg = apple_gpio_get_reg(pctl, offset);
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index ec5351fc282e..41cbb46ac589 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -1053,6 +1053,12 @@ static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
.last_bank_count = ATMEL_PIO_NPINS_PER_BANK,
};
+static const struct atmel_pioctrl_data microchip_sama7d65_pioctrl_data = {
+ .nbanks = 5,
+ .last_bank_count = 14, /* sama7d65 has only PE0 to PE13 */
+ .slew_rate_support = 1,
+};
+
static const struct atmel_pioctrl_data microchip_sama7g5_pioctrl_data = {
.nbanks = 5,
.last_bank_count = 8, /* sama7g5 has only PE0 to PE7 */
@@ -1064,6 +1070,9 @@ static const struct of_device_id atmel_pctrl_of_match[] = {
.compatible = "atmel,sama5d2-pinctrl",
.data = &atmel_sama5d2_pioctrl_data,
}, {
+ .compatible = "microchip,sama7d65-pinctrl",
+ .data = &microchip_sama7d65_pioctrl_data,
+ }, {
.compatible = "microchip,sama7g5-pinctrl",
.data = &microchip_sama7g5_pioctrl_data,
}, {
diff --git a/drivers/pinctrl/pinctrl-aw9523.c b/drivers/pinctrl/pinctrl-aw9523.c
index 479553a79216..02a24ac87ea4 100644
--- a/drivers/pinctrl/pinctrl-aw9523.c
+++ b/drivers/pinctrl/pinctrl-aw9523.c
@@ -291,14 +291,14 @@ static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned int mask, val;
int i, rc;
- mutex_lock(&awi->i2c_lock);
+ guard(mutex)(&awi->i2c_lock);
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]);
rc = aw9523_pcfg_param_to_reg(param, pin, &reg);
if (rc)
- goto end;
+ return rc;
switch (param) {
case PIN_CONFIG_LEVEL:
@@ -307,7 +307,7 @@ static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
AW9523_REG_CONF_STATE(pin),
BIT(regbit), 0);
if (rc)
- goto end;
+ return rc;
/* Then, fall through to config output level */
fallthrough;
@@ -323,10 +323,9 @@ static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
/* Open-Drain is supported only on port 0 */
- if (pin >= AW9523_PINS_PER_PORT) {
- rc = -ENOTSUPP;
- goto end;
- }
+ if (pin >= AW9523_PINS_PER_PORT)
+ return -ENOTSUPP;
+
mask = AW9523_GCR_GPOMD_MASK;
val = 0;
break;
@@ -341,17 +340,15 @@ static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
val = AW9523_GCR_GPOMD_MASK;
break;
default:
- rc = -ENOTSUPP;
- goto end;
+ return -ENOTSUPP;
}
rc = regmap_update_bits(awi->regmap, reg, mask, val);
if (rc)
- goto end;
+ return rc;
}
-end:
- mutex_unlock(&awi->i2c_lock);
- return rc;
+
+ return 0;
}
static const struct pinconf_ops aw9523_pinconf_ops = {
@@ -599,14 +596,14 @@ static int aw9523_gpio_get_multiple(struct gpio_chip *chip,
u8 m, state = 0;
int ret;
- mutex_lock(&awi->i2c_lock);
+ guard(mutex)(&awi->i2c_lock);
/* Port 0 (gpio 0-7) */
m = *mask;
if (m) {
ret = _aw9523_gpio_get_multiple(awi, 0, &state, m);
if (ret)
- goto out;
+ return ret;
}
*bits = state;
@@ -616,13 +613,12 @@ static int aw9523_gpio_get_multiple(struct gpio_chip *chip,
ret = _aw9523_gpio_get_multiple(awi, AW9523_PINS_PER_PORT,
&state, m);
if (ret)
- goto out;
+ return ret;
*bits |= (state << 8);
}
-out:
- mutex_unlock(&awi->i2c_lock);
- return ret;
+
+ return 0;
}
static int aw9523_gpio_set_multiple(struct gpio_chip *chip,
@@ -632,30 +628,28 @@ static int aw9523_gpio_set_multiple(struct gpio_chip *chip,
struct aw9523 *awi = gpiochip_get_data(chip);
u8 mask_lo, mask_hi, bits_lo, bits_hi;
unsigned int reg;
- int ret = 0;
+ int ret;
mask_lo = *mask;
mask_hi = *mask >> 8;
bits_lo = *bits;
bits_hi = *bits >> 8;
- mutex_lock(&awi->i2c_lock);
+ guard(mutex)(&awi->i2c_lock);
if (mask_hi) {
reg = AW9523_REG_OUT_STATE(AW9523_PINS_PER_PORT);
ret = regmap_write_bits(awi->regmap, reg, mask_hi, bits_hi);
if (ret)
- goto out;
+ return ret;
}
if (mask_lo) {
reg = AW9523_REG_OUT_STATE(0);
ret = regmap_write_bits(awi->regmap, reg, mask_lo, bits_lo);
if (ret)
- goto out;
+ return ret;
}
-out:
- mutex_unlock(&awi->i2c_lock);
- return ret;
+ return 0;
}
static int aw9523_gpio_set(struct gpio_chip *chip, unsigned int offset,
@@ -695,16 +689,15 @@ static int aw9523_direction_output(struct gpio_chip *chip,
u8 regbit = offset % AW9523_PINS_PER_PORT;
int ret;
- mutex_lock(&awi->i2c_lock);
+ guard(mutex)(&awi->i2c_lock);
ret = regmap_update_bits(awi->regmap, AW9523_REG_OUT_STATE(offset),
BIT(regbit), value ? BIT(regbit) : 0);
if (ret)
- goto end;
+ return ret;
ret = regmap_update_bits(awi->regmap, AW9523_REG_CONF_STATE(offset),
BIT(regbit), 0);
-end:
- mutex_unlock(&awi->i2c_lock);
+
return ret;
}
diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c
index 2d04829b29c9..48b55c5bf8d4 100644
--- a/drivers/pinctrl/pinctrl-equilibrium.c
+++ b/drivers/pinctrl/pinctrl-equilibrium.c
@@ -846,6 +846,7 @@ static int pinbank_init(struct device_node *np,
bank->pin_base = spec.args[1];
bank->nr_pins = spec.args[2];
+ of_node_put(spec.np);
bank->aval_pinmap = readl(bank->membase + REG_AVAIL);
bank->id = id;
diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
new file mode 100644
index 000000000000..efb39c6a6703
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-generic.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#define pr_fmt(fmt) "generic pinconfig core: " fmt
+
+#include <linux/array_size.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinctrl-utils.h"
+#include "pinmux.h"
+
+static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *parent,
+ struct device_node *np,
+ struct pinctrl_map **maps,
+ unsigned int *num_maps,
+ unsigned int *num_reserved_maps,
+ const char **group_names,
+ unsigned int ngroups)
+{
+ struct device *dev = pctldev->dev;
+ const char **functions;
+ const char *group_name;
+ unsigned long *configs;
+ unsigned int num_configs, pin, *pins;
+ int npins, ret, reserve = 1;
+
+ npins = of_property_count_u32_elems(np, "pins");
+
+ if (npins < 1) {
+ dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n",
+ parent, np, npins);
+ return npins;
+ }
+
+ group_name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", parent, np);
+ if (!group_name)
+ return -ENOMEM;
+
+ group_names[ngroups] = group_name;
+
+ pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+ if (!pins)
+ return -ENOMEM;
+
+ functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL);
+ if (!functions)
+ return -ENOMEM;
+
+ for (int i = 0; i < npins; i++) {
+ ret = of_property_read_u32_index(np, "pins", i, &pin);
+ if (ret)
+ return ret;
+
+ pins[i] = pin;
+
+ ret = of_property_read_string(np, "function", &functions[i]);
+ if (ret)
+ return ret;
+ }
+
+ ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve);
+ if (ret)
+ return ret;
+
+ ret = pinctrl_utils_add_map_mux(pctldev, maps, num_reserved_maps, num_maps, group_name,
+ parent->name);
+ if (ret < 0)
+ return ret;
+
+ ret = pinctrl_generic_add_group(pctldev, group_name, pins, npins, functions);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to add group %s: %d\n",
+ group_name, ret);
+
+ ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to parse pin config of group %s\n",
+ group_name);
+
+ if (num_configs == 0)
+ return 0;
+
+ ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve);
+ if (ret)
+ return ret;
+
+ ret = pinctrl_utils_add_map_configs(pctldev, maps, num_reserved_maps, num_maps, group_name,
+ configs,
+ num_configs, PIN_MAP_TYPE_CONFIGS_GROUP);
+ kfree(configs);
+ if (ret)
+ return ret;
+
+ return 0;
+};
+
+/*
+ * For platforms that do not define groups or functions in the driver, but
+ * instead use the devicetree to describe them. This function will, unlike
+ * pinconf_generic_dt_node_to_map() etc which rely on driver defined groups
+ * and functions, create them in addition to parsing pinconf properties and
+ * adding mappings.
+ */
+int pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **maps,
+ unsigned int *num_maps)
+{
+ struct device *dev = pctldev->dev;
+ struct device_node *child_np;
+ const char **group_names;
+ unsigned int num_reserved_maps = 0;
+ int ngroups = 0;
+ int ret;
+
+ *maps = NULL;
+ *num_maps = 0;
+
+ /*
+ * Check if this is actually the pins node, or a parent containing
+ * multiple pins nodes.
+ */
+ if (!of_property_present(np, "pins"))
+ goto parent;
+
+ group_names = devm_kcalloc(dev, 1, sizeof(*group_names), GFP_KERNEL);
+ if (!group_names)
+ return -ENOMEM;
+
+ ret = pinctrl_generic_pins_function_dt_subnode_to_map(pctldev, np, np,
+ maps, num_maps,
+ &num_reserved_maps,
+ group_names,
+ ngroups);
+ if (ret) {
+ pinctrl_utils_free_map(pctldev, *maps, *num_maps);
+ return dev_err_probe(dev, ret, "error figuring out mappings for %s\n", np->name);
+ }
+
+ ret = pinmux_generic_add_function(pctldev, np->name, group_names, 1, NULL);
+ if (ret < 0) {
+ pinctrl_utils_free_map(pctldev, *maps, *num_maps);
+ return dev_err_probe(dev, ret, "error adding function %s\n", np->name);
+ }
+
+ return 0;
+
+parent:
+ for_each_available_child_of_node(np, child_np)
+ ngroups += 1;
+
+ group_names = devm_kcalloc(dev, ngroups, sizeof(*group_names), GFP_KERNEL);
+ if (!group_names)
+ return -ENOMEM;
+
+ ngroups = 0;
+ for_each_available_child_of_node_scoped(np, child_np) {
+ ret = pinctrl_generic_pins_function_dt_subnode_to_map(pctldev, np, child_np,
+ maps, num_maps,
+ &num_reserved_maps,
+ group_names,
+ ngroups);
+ if (ret) {
+ pinctrl_utils_free_map(pctldev, *maps, *num_maps);
+ return dev_err_probe(dev, ret, "error figuring out mappings for %s\n",
+ np->name);
+ }
+
+ ngroups++;
+ }
+
+ ret = pinmux_generic_add_function(pctldev, np->name, group_names, ngroups, NULL);
+ if (ret < 0) {
+ pinctrl_utils_free_map(pctldev, *maps, *num_maps);
+ return dev_err_probe(dev, ret, "error adding function %s\n", np->name);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pinctrl_generic_pins_function_dt_node_to_map);
diff --git a/drivers/pinctrl/pinctrl-k230.c b/drivers/pinctrl/pinctrl-k230.c
index d716f23d837f..20f7c0f70eb7 100644
--- a/drivers/pinctrl/pinctrl-k230.c
+++ b/drivers/pinctrl/pinctrl-k230.c
@@ -65,6 +65,7 @@ struct k230_pmx_func {
};
struct k230_pinctrl {
+ struct device *dev;
struct pinctrl_desc pctl;
struct pinctrl_dev *pctl_dev;
struct regmap *regmap_base;
@@ -470,7 +471,7 @@ static int k230_pinctrl_parse_groups(struct device_node *np,
struct k230_pinctrl *info,
unsigned int index)
{
- struct device *dev = info->pctl_dev->dev;
+ struct device *dev = info->dev;
const __be32 *list;
int size, i, ret;
@@ -511,7 +512,7 @@ static int k230_pinctrl_parse_functions(struct device_node *np,
struct k230_pinctrl *info,
unsigned int index)
{
- struct device *dev = info->pctl_dev->dev;
+ struct device *dev = info->dev;
struct k230_pmx_func *func;
struct k230_pin_group *grp;
static unsigned int idx, i;
@@ -596,6 +597,8 @@ static int k230_pinctrl_probe(struct platform_device *pdev)
if (!info)
return -ENOMEM;
+ info->dev = dev;
+
pctl = &info->pctl;
pctl->name = "k230-pinctrl";
diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c
index b6363f3cdce9..7a6cb5f502b0 100644
--- a/drivers/pinctrl/pinctrl-microchip-sgpio.c
+++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c
@@ -264,19 +264,17 @@ static int sgpio_single_shot(struct sgpio_priv *priv)
* setting.
* After the manual burst, reenable the auto repeat mode again.
*/
- mutex_lock(&priv->poll_lock);
+ guard(mutex)(&priv->poll_lock);
ret = regmap_update_bits(priv->regs, addr, single_shot | auto_repeat,
single_shot);
if (ret)
- goto out;
+ return ret;
ret = regmap_read_poll_timeout(priv->regs, addr, ctrl,
!(ctrl & single_shot), 100, 60000);
/* reenable auto repeat mode even if there was an error */
ret2 = regmap_update_bits(priv->regs, addr, auto_repeat, auto_repeat);
-out:
- mutex_unlock(&priv->poll_lock);
return ret ?: ret2;
}
diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c
index 70da3f37567a..6ea9544ddd06 100644
--- a/drivers/pinctrl/pinctrl-ocelot.c
+++ b/drivers/pinctrl/pinctrl-ocelot.c
@@ -97,6 +97,8 @@ enum {
FUNC_FC_SHRD20,
FUNC_FUSA,
FUNC_GPIO,
+ FUNC_I2C,
+ FUNC_I2C_Sa,
FUNC_IB_TRG_a,
FUNC_IB_TRG_b,
FUNC_IB_TRG_c,
@@ -112,9 +114,11 @@ enum {
FUNC_IRQ1,
FUNC_IRQ1_IN,
FUNC_IRQ1_OUT,
+ FUNC_IRQ2,
FUNC_IRQ3,
FUNC_IRQ4,
FUNC_EXT_IRQ,
+ FUNC_MACLED,
FUNC_MIIM,
FUNC_MIIM_a,
FUNC_MIIM_b,
@@ -126,6 +130,7 @@ enum {
FUNC_OB_TRG_a,
FUNC_OB_TRG_b,
FUNC_PHY_LED,
+ FUNC_PHY_DBG,
FUNC_PCI_WAKE,
FUNC_MD,
FUNC_PCIE_PERST,
@@ -156,10 +161,12 @@ enum {
FUNC_SG0,
FUNC_SG1,
FUNC_SG2,
+ FUNC_SPI,
FUNC_SGPIO_a,
FUNC_SGPIO_b,
FUNC_SI,
FUNC_SI2,
+ FUNC_SI_Sa,
FUNC_SYNCE,
FUNC_TACHO,
FUNC_TACHO_a,
@@ -188,6 +195,7 @@ enum {
FUNC_EMMC_SD,
FUNC_REF_CLK,
FUNC_RCVRD_CLK,
+ FUNC_RGMII,
FUNC_MAX
};
@@ -237,6 +245,8 @@ static const char *const ocelot_function_names[] = {
[FUNC_FC_SHRD20] = "fc_shrd20",
[FUNC_FUSA] = "fusa",
[FUNC_GPIO] = "gpio",
+ [FUNC_I2C] = "i2c",
+ [FUNC_I2C_Sa] = "i2c_slave_a",
[FUNC_IB_TRG_a] = "ib_trig_a",
[FUNC_IB_TRG_b] = "ib_trig_b",
[FUNC_IB_TRG_c] = "ib_trig_c",
@@ -252,9 +262,11 @@ static const char *const ocelot_function_names[] = {
[FUNC_IRQ1] = "irq1",
[FUNC_IRQ1_IN] = "irq1_in",
[FUNC_IRQ1_OUT] = "irq1_out",
+ [FUNC_IRQ2] = "irq2",
[FUNC_IRQ3] = "irq3",
[FUNC_IRQ4] = "irq4",
[FUNC_EXT_IRQ] = "ext_irq",
+ [FUNC_MACLED] = "mac_led",
[FUNC_MIIM] = "miim",
[FUNC_MIIM_a] = "miim_a",
[FUNC_MIIM_b] = "miim_b",
@@ -263,6 +275,7 @@ static const char *const ocelot_function_names[] = {
[FUNC_MIIM_Sb] = "miim_slave_b",
[FUNC_MIIM_IRQ] = "miim_irq",
[FUNC_PHY_LED] = "phy_led",
+ [FUNC_PHY_DBG] = "phy_dbg",
[FUNC_PCI_WAKE] = "pci_wake",
[FUNC_PCIE_PERST] = "pcie_perst",
[FUNC_MD] = "md",
@@ -300,6 +313,8 @@ static const char *const ocelot_function_names[] = {
[FUNC_SGPIO_b] = "sgpio_b",
[FUNC_SI] = "si",
[FUNC_SI2] = "si2",
+ [FUNC_SI_Sa] = "si_slave_a",
+ [FUNC_SPI] = "spi",
[FUNC_SYNCE] = "synce",
[FUNC_TACHO] = "tacho",
[FUNC_TACHO_a] = "tacho_a",
@@ -328,6 +343,7 @@ static const char *const ocelot_function_names[] = {
[FUNC_EMMC_SD] = "emmc_sd",
[FUNC_REF_CLK] = "ref_clk",
[FUNC_RCVRD_CLK] = "rcvrd_clk",
+ [FUNC_RGMII] = "rgmii",
};
struct ocelot_pmx_func {
@@ -358,12 +374,14 @@ struct ocelot_pinctrl {
const struct ocelot_pincfg_data *pincfg_data;
struct ocelot_pmx_func func[FUNC_MAX];
u8 stride;
+ u8 altm_stride;
struct workqueue_struct *wq;
};
struct ocelot_match_data {
struct pinctrl_desc desc;
struct ocelot_pincfg_data pincfg_data;
+ unsigned int n_alt_modes;
};
struct ocelot_irq_work {
@@ -1321,6 +1339,132 @@ static const struct pinctrl_pin_desc lan969x_pins[] = {
LAN969X_PIN(66),
};
+#define LAN9645X_P(p, f0, f1, f2, f3, f4, f5, f6, f7) \
+static struct ocelot_pin_caps lan9645x_pin_##p = { \
+ .pin = p, \
+ .functions = { \
+ FUNC_##f0, FUNC_##f1, FUNC_##f2, \
+ FUNC_##f3 \
+ }, \
+ .a_functions = { \
+ FUNC_##f4, FUNC_##f5, FUNC_##f6, \
+ FUNC_##f7 \
+ }, \
+}
+
+/* Pin FUNC0 FUNC1 FUNC2 FUNC3 FUNC4 FUNC5 FUNC6 FUNC7 */
+LAN9645X_P(0, GPIO, SPI, SI_Sa, I2C_Sa, MIIM_Sa, UART, MIIM, PHY_DBG);
+LAN9645X_P(1, GPIO, SPI, SI_Sa, I2C_Sa, MIIM_Sa, UART, MIIM, PHY_DBG);
+LAN9645X_P(2, GPIO, SPI, SI_Sa, I2C, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(3, GPIO, SPI, SI_Sa, I2C, MIIM_Sa, NONE, NONE, PHY_DBG);
+LAN9645X_P(4, GPIO, RGMII, TWI_SCL_M, I2C, NONE, NONE, SI_Sa, PHY_DBG);
+LAN9645X_P(5, GPIO, RGMII, TWI_SCL_M, I2C, NONE, NONE, SI_Sa, PHY_DBG);
+LAN9645X_P(6, GPIO, RGMII, TWI_SCL_M, NONE, NONE, NONE, SI_Sa, PHY_DBG);
+LAN9645X_P(7, GPIO, RGMII, TWI_SCL_M, SFP, SGPIO_a, MIIM, SI_Sa, PHY_DBG);
+LAN9645X_P(8, GPIO, RGMII, TWI_SCL_M, SFP, SGPIO_a, MIIM, NONE, PHY_DBG);
+LAN9645X_P(9, GPIO, RGMII, TWI_SCL_M, RECO_CLK, SGPIO_a, IRQ1, UART, PHY_DBG);
+LAN9645X_P(10, GPIO, RGMII, TWI_SCL_M, RECO_CLK, SGPIO_a, IRQ2, UART, PHY_DBG);
+LAN9645X_P(11, GPIO, RGMII, TWI_SCL_M, MIIM, NONE, IRQ3, NONE, PHY_DBG);
+LAN9645X_P(12, GPIO, RGMII, TWI_SCL_M, MIIM, PTP0, NONE, NONE, PHY_DBG);
+LAN9645X_P(13, GPIO, RGMII, TWI_SCL_M, CLKMON, PTP1, MACLED, NONE, PHY_DBG);
+LAN9645X_P(14, GPIO, RGMII, TWI_SCL_M, CLKMON, PTP2, MACLED, NONE, PHY_DBG);
+LAN9645X_P(15, GPIO, RGMII, TWI_SCL_M, CLKMON, PTP3, NONE, NONE, PHY_DBG);
+LAN9645X_P(16, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(17, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(18, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(19, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(20, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(21, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(22, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(23, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(24, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(25, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(26, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(27, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG);
+LAN9645X_P(28, GPIO, RECO_CLK, MIIM, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(29, GPIO, RECO_CLK, MIIM, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(30, GPIO, PTP0, I2C, UART, NONE, NONE, NONE, R);
+LAN9645X_P(31, GPIO, PTP1, TWI_SCL_M, UART, NONE, NONE, NONE, R);
+LAN9645X_P(32, GPIO, PTP2, TWI_SCL_M, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(33, GPIO, PTP3, IRQ0, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(34, GPIO, RECO_CLK, PHY_LED, PHY_LED, NONE, NONE, NONE, R);
+LAN9645X_P(35, GPIO, RECO_CLK, PHY_LED, PHY_LED, NONE, MACLED, NONE, R);
+LAN9645X_P(36, GPIO, PTP0, PHY_LED, PHY_LED, NONE, MACLED, NONE, R);
+LAN9645X_P(37, GPIO, PTP1, PHY_LED, PHY_LED, NONE, MACLED, NONE, R);
+LAN9645X_P(38, GPIO, NONE, PHY_LED, PHY_LED, NONE, MACLED, NONE, R);
+LAN9645X_P(39, GPIO, UART, PHY_LED, NONE, NONE, MACLED, NONE, R);
+LAN9645X_P(40, GPIO, SPI, PHY_LED, SGPIO_a, NONE, MACLED, NONE, R);
+LAN9645X_P(41, GPIO, SPI, PHY_LED, SGPIO_a, IRQ1, MACLED, NONE, R);
+LAN9645X_P(42, GPIO, SPI, PHY_LED, SGPIO_a, IRQ2, MACLED, SFP, R);
+LAN9645X_P(43, GPIO, SPI, PHY_LED, SGPIO_a, IRQ3, MACLED, SFP, R);
+LAN9645X_P(44, GPIO, MIIM, I2C, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(45, GPIO, MIIM, I2C, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(46, GPIO, NONE, PHY_LED, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(47, GPIO, NONE, PHY_LED, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(48, GPIO, MIIM_Sa, PHY_LED, NONE, NONE, NONE, NONE, R);
+LAN9645X_P(49, GPIO, MIIM_Sa, PHY_LED, I2C_Sa, NONE, NONE, NONE, R);
+LAN9645X_P(50, GPIO, MIIM_Sa, PHY_LED, I2C_Sa, NONE, NONE, NONE, R);
+
+#define LAN9645X_PIN(n) { \
+ .number = n, \
+ .name = "GPIO_"#n, \
+ .drv_data = &lan9645x_pin_##n \
+}
+
+static const struct pinctrl_pin_desc lan9645x_pins[] = {
+ LAN9645X_PIN(0),
+ LAN9645X_PIN(1),
+ LAN9645X_PIN(2),
+ LAN9645X_PIN(3),
+ LAN9645X_PIN(4),
+ LAN9645X_PIN(5),
+ LAN9645X_PIN(6),
+ LAN9645X_PIN(7),
+ LAN9645X_PIN(8),
+ LAN9645X_PIN(9),
+ LAN9645X_PIN(10),
+ LAN9645X_PIN(11),
+ LAN9645X_PIN(12),
+ LAN9645X_PIN(13),
+ LAN9645X_PIN(14),
+ LAN9645X_PIN(15),
+ LAN9645X_PIN(16),
+ LAN9645X_PIN(17),
+ LAN9645X_PIN(18),
+ LAN9645X_PIN(19),
+ LAN9645X_PIN(20),
+ LAN9645X_PIN(21),
+ LAN9645X_PIN(22),
+ LAN9645X_PIN(23),
+ LAN9645X_PIN(24),
+ LAN9645X_PIN(25),
+ LAN9645X_PIN(26),
+ LAN9645X_PIN(27),
+ LAN9645X_PIN(28),
+ LAN9645X_PIN(29),
+ LAN9645X_PIN(30),
+ LAN9645X_PIN(31),
+ LAN9645X_PIN(32),
+ LAN9645X_PIN(33),
+ LAN9645X_PIN(34),
+ LAN9645X_PIN(35),
+ LAN9645X_PIN(36),
+ LAN9645X_PIN(37),
+ LAN9645X_PIN(38),
+ LAN9645X_PIN(39),
+ LAN9645X_PIN(40),
+ LAN9645X_PIN(41),
+ LAN9645X_PIN(42),
+ LAN9645X_PIN(43),
+ LAN9645X_PIN(44),
+ LAN9645X_PIN(45),
+ LAN9645X_PIN(46),
+ LAN9645X_PIN(47),
+ LAN9645X_PIN(48),
+ LAN9645X_PIN(49),
+ LAN9645X_PIN(50),
+};
+
static int ocelot_get_functions_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(ocelot_function_names);
@@ -1362,7 +1506,7 @@ static int ocelot_pin_function_idx(struct ocelot_pinctrl *info,
return -1;
}
-#define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + ((info)->stride * ((p) / 32))))
+#define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + ((info)->altm_stride * ((p) / 32))))
static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int selector, unsigned int group)
@@ -1469,6 +1613,13 @@ static int lan966x_gpio_request_enable(struct pinctrl_dev *pctldev,
return 0;
}
+static int lan9645x_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ return 0;
+}
+
static const struct pinmux_ops ocelot_pmx_ops = {
.get_functions_count = ocelot_get_functions_count,
.get_function_name = ocelot_get_function_name,
@@ -1487,6 +1638,15 @@ static const struct pinmux_ops lan966x_pmx_ops = {
.gpio_request_enable = lan966x_gpio_request_enable,
};
+static const struct pinmux_ops lan9645x_pmx_ops = {
+ .get_functions_count = ocelot_get_functions_count,
+ .get_function_name = ocelot_get_function_name,
+ .get_function_groups = ocelot_get_function_groups,
+ .set_mux = lan966x_pinmux_set_mux,
+ .gpio_set_direction = ocelot_gpio_set_direction,
+ .gpio_request_enable = lan9645x_gpio_request_enable,
+};
+
static int ocelot_pctl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
@@ -1884,6 +2044,24 @@ static const struct ocelot_match_data lan969x_desc = {
},
};
+static struct ocelot_match_data lan9645xf_desc = {
+ .desc = {
+ .name = "lan9645xf-pinctrl",
+ .pins = lan9645x_pins,
+ .npins = ARRAY_SIZE(lan9645x_pins),
+ .pctlops = &ocelot_pctl_ops,
+ .pmxops = &lan9645x_pmx_ops,
+ .confops = &ocelot_confops,
+ .owner = THIS_MODULE,
+ },
+ .pincfg_data = {
+ .pd_bit = BIT(3),
+ .pu_bit = BIT(2),
+ .drive_bits = GENMASK(1, 0),
+ },
+ .n_alt_modes = 7,
+};
+
static int ocelot_create_group_func_map(struct device *dev,
struct ocelot_pinctrl *info)
{
@@ -2218,6 +2396,7 @@ static const struct of_device_id ocelot_pinctrl_of_match[] = {
{ .compatible = "microchip,sparx5-pinctrl", .data = &sparx5_desc },
{ .compatible = "microchip,lan966x-pinctrl", .data = &lan966x_desc },
{ .compatible = "microchip,lan9691-pinctrl", .data = &lan969x_desc },
+ { .compatible = "microchip,lan96455f-pinctrl", .data = &lan9645xf_desc },
{},
};
MODULE_DEVICE_TABLE(of, ocelot_pinctrl_of_match);
@@ -2294,6 +2473,9 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
reset_control_reset(reset);
info->stride = 1 + (info->desc->npins - 1) / 32;
+ info->altm_stride = info->stride;
+ if (data->n_alt_modes)
+ info->altm_stride = fls(data->n_alt_modes);
regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4;
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 2fc67aeafdb3..816823403e97 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -3639,17 +3639,16 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
* The lock makes sure that either gpio-probe has completed
* or the gpio driver hasn't probed yet.
*/
- mutex_lock(&bank->deferred_lock);
- if (!gpio || !gpio->direction_output) {
- rc = rockchip_pinconf_defer_pin(bank, pin - bank->pin_base, param,
- arg);
- mutex_unlock(&bank->deferred_lock);
- if (rc)
- return rc;
-
- break;
+ scoped_guard(mutex, &bank->deferred_lock) {
+ if (!gpio || !gpio->direction_output) {
+ rc = rockchip_pinconf_defer_pin(bank,
+ pin - bank->pin_base,
+ param, arg);
+ if (rc)
+ return rc;
+ break;
+ }
}
- mutex_unlock(&bank->deferred_lock);
}
switch (param) {
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index af3ac031e362..d5fb8649cd9a 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -504,8 +504,9 @@ static int pinctrl_scmi_get_pins(struct scmi_pinctrl *pmx,
}
static const char * const scmi_pinctrl_blocklist[] = {
- "fsl,imx95",
"fsl,imx94",
+ "fsl,imx95",
+ "fsl,imx952",
NULL
};
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 998f23d6c317..d85e6c1f6321 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1359,6 +1359,7 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
}
range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL);
if (!range) {
+ of_node_put(gpiospec.np);
ret = -ENOMEM;
break;
}
@@ -1368,6 +1369,7 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
mutex_lock(&pcs->mutex);
list_add_tail(&range->node, &pcs->gpiofuncs);
mutex_unlock(&pcs->mutex);
+ of_node_put(gpiospec.np);
}
return ret;
}
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index d3cea3437d7f..8ce88e591f47 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -987,6 +987,7 @@ static int st_pinconf_get(struct pinctrl_dev *pctldev,
static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
+ __must_hold(&pctldev->mutex)
{
struct st_pio_control *pc;
unsigned long config;
diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c
index 129fa51d13b1..3f581404a9b9 100644
--- a/drivers/pinctrl/pinctrl-tb10x.c
+++ b/drivers/pinctrl/pinctrl-tb10x.c
@@ -607,7 +607,7 @@ static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl,
int muxmode = -1;
int i;
- mutex_lock(&state->mutex);
+ guard(mutex)(&state->mutex);
/*
* Figure out to which port the requested GPIO belongs and how to
@@ -642,7 +642,6 @@ static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl,
* Error: The requested pin is already
* used for something else.
*/
- mutex_unlock(&state->mutex);
return -EBUSY;
}
break;
@@ -667,8 +666,6 @@ static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl,
if (muxport >= 0)
tb10x_pinctrl_set_config(state, muxport, muxmode);
- mutex_unlock(&state->mutex);
-
return 0;
}
@@ -695,34 +692,28 @@ static int tb10x_pctl_set_mux(struct pinctrl_dev *pctl,
if (grp->port < 0)
return 0;
- mutex_lock(&state->mutex);
+ guard(mutex)(&state->mutex);
/*
* Check if the requested function is compatible with previously
* requested functions.
*/
if (state->ports[grp->port].count
- && (state->ports[grp->port].mode != grp->mode)) {
- mutex_unlock(&state->mutex);
+ && (state->ports[grp->port].mode != grp->mode))
return -EBUSY;
- }
/*
* Check if the requested function is compatible with previously
* requested GPIOs.
*/
for (i = 0; i < grp->pincnt; i++)
- if (test_bit(grp->pins[i], state->gpios)) {
- mutex_unlock(&state->mutex);
+ if (test_bit(grp->pins[i], state->gpios))
return -EBUSY;
- }
tb10x_pinctrl_set_config(state, grp->port, grp->mode);
state->ports[grp->port].count++;
- mutex_unlock(&state->mutex);
-
return 0;
}
diff --git a/drivers/pinctrl/qcom/pinctrl-glymur.c b/drivers/pinctrl/qcom/pinctrl-glymur.c
index 335005084b6b..44f9745325b7 100644
--- a/drivers/pinctrl/qcom/pinctrl-glymur.c
+++ b/drivers/pinctrl/qcom/pinctrl-glymur.c
@@ -1729,6 +1729,26 @@ static const struct msm_gpio_wakeirq_map glymur_pdc_map[] = {
{ 232, 206 }, { 234, 172 }, { 235, 173 }, { 242, 158 }, { 244, 156 },
};
+static const struct msm_gpio_wakeirq_map mahua_pdc_map[] = {
+ { 0, 116 }, { 2, 114 }, { 3, 115 }, { 4, 175 }, { 5, 176 },
+ { 7, 111 }, { 11, 129 }, { 13, 130 }, { 15, 112 }, { 19, 113 },
+ { 23, 187 }, { 27, 188 }, { 28, 121 }, { 29, 122 }, { 30, 136 },
+ { 31, 203 }, { 32, 189 }, { 34, 174 }, { 35, 190 }, { 36, 191 },
+ { 39, 124 }, { 43, 192 }, { 47, 193 }, { 51, 123 }, { 53, 133 },
+ { 55, 125 }, { 59, 131 }, { 64, 134 }, { 65, 150 }, { 66, 186 },
+ { 67, 132 }, { 68, 195 }, { 71, 135 }, { 75, 196 }, { 79, 197 },
+ { 83, 198 }, { 84, 181 }, { 85, 199 }, { 87, 200 }, { 91, 201 },
+ { 92, 182 }, { 93, 183 }, { 94, 184 }, { 95, 185 }, { 98, 202 },
+ { 105, 157 }, { 113, 128 }, { 121, 117 }, { 123, 118 }, { 125, 119 },
+ { 129, 120 }, { 131, 126 }, { 132, 160 }, { 133, 194 }, { 134, 127 },
+ { 141, 137 }, { 144, 138 }, { 145, 139 }, { 147, 140 }, { 148, 141 },
+ { 150, 146 }, { 151, 147 }, { 153, 148 }, { 154, 144 }, { 155, 159 },
+ { 156, 149 }, { 157, 151 }, { 163, 142 }, { 172, 143 }, { 181, 145 },
+ { 193, 161 }, { 196, 152 }, { 203, 177 }, { 208, 178 }, { 215, 162 },
+ { 217, 153 }, { 220, 154 }, { 221, 155 }, { 228, 179 }, { 230, 180 },
+ { 232, 206 }, { 234, 172 }, { 235, 173 }, { 242, 158 }, { 244, 156 },
+};
+
static const struct msm_pinctrl_soc_data glymur_tlmm = {
.pins = glymur_pins,
.npins = ARRAY_SIZE(glymur_pins),
@@ -1742,14 +1762,34 @@ static const struct msm_pinctrl_soc_data glymur_tlmm = {
.egpio_func = 11,
};
+static const struct msm_pinctrl_soc_data mahua_tlmm = {
+ .pins = glymur_pins,
+ .npins = ARRAY_SIZE(glymur_pins),
+ .functions = glymur_functions,
+ .nfunctions = ARRAY_SIZE(glymur_functions),
+ .groups = glymur_groups,
+ .ngroups = ARRAY_SIZE(glymur_groups),
+ .ngpios = 251,
+ .wakeirq_map = mahua_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(mahua_pdc_map),
+ .egpio_func = 11,
+};
+
static const struct of_device_id glymur_tlmm_of_match[] = {
- { .compatible = "qcom,glymur-tlmm", },
- { }
+ { .compatible = "qcom,glymur-tlmm", .data = &glymur_tlmm },
+ { .compatible = "qcom,mahua-tlmm", .data = &mahua_tlmm },
+ { },
};
static int glymur_tlmm_probe(struct platform_device *pdev)
{
- return msm_pinctrl_probe(pdev, &glymur_tlmm);
+ const struct msm_pinctrl_soc_data *data;
+
+ data = of_device_get_match_data(&pdev->dev);
+ if (!data)
+ return -ENODEV;
+
+ return msm_pinctrl_probe(pdev, data);
}
static struct platform_driver glymur_tlmm_driver = {
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c
index 64494a86490e..c27452eece3e 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c
@@ -73,7 +73,7 @@ static const char * const i2s1_ws_groups[] = { "gpio7" };
static const char * const i2s1_data_groups[] = { "gpio8", "gpio9" };
static const char * const wsa_swr_clk_groups[] = { "gpio10" };
static const char * const wsa_swr_data_groups[] = { "gpio11" };
-static const char * const i2s2_data_groups[] = { "gpio12", "gpio12" };
+static const char * const i2s2_data_groups[] = { "gpio12", "gpio13" };
static const struct lpi_pingroup sm8250_groups[] = {
LPI_PINGROUP(0, 0, swr_tx_clk, qua_mi2s_sclk, _, _),
diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig
index 8cbd79a13414..d979e25e5088 100644
--- a/drivers/pinctrl/renesas/Kconfig
+++ b/drivers/pinctrl/renesas/Kconfig
@@ -308,9 +308,11 @@ config PINCTRL_RZT2H
bool "pin control support for RZ/N2H and RZ/T2H" if COMPILE_TEST
depends on 64BIT && OF
select GPIOLIB
+ select GPIOLIB_IRQCHIP
select GENERIC_PINCTRL_GROUPS
select GENERIC_PINMUX_FUNCTIONS
select GENERIC_PINCONF
+ select IRQ_DOMAIN_HIERARCHY
help
This selects GPIO and pinctrl driver for Renesas RZ/T2H
platforms.
diff --git a/drivers/pinctrl/renesas/pinctrl-rzt2h.c b/drivers/pinctrl/renesas/pinctrl-rzt2h.c
index 4826ff91cd90..9949108a35bb 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzt2h.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzt2h.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/spinlock.h>
@@ -51,6 +52,7 @@
#define PFC_MASK GENMASK_ULL(5, 0)
#define PFC_PIN_MASK(pin) (PFC_MASK << ((pin) * 8))
+#define PFC_FUNC_INTERRUPT 0
/*
* Use 16 lower bits [15:0] for pin identifier
@@ -64,6 +66,9 @@
#define RZT2H_MAX_SAFETY_PORTS 12
+#define RZT2H_INTERRUPTS_START 16
+#define RZT2H_INTERRUPTS_NUM 17
+
struct rzt2h_pinctrl_data {
unsigned int n_port_pins;
const u8 *port_pin_configs;
@@ -79,9 +84,11 @@ struct rzt2h_pinctrl {
struct device *dev;
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range gpio_range;
+ DECLARE_BITMAP(used_irqs, RZT2H_INTERRUPTS_NUM);
spinlock_t lock; /* lock read/write registers */
struct mutex mutex; /* serialize adding groups and functions */
bool safety_port_enabled;
+ atomic_t wakeup_path;
};
#define RZT2H_GET_BASE(pctrl, port) \
@@ -119,6 +126,19 @@ static int rzt2h_validate_pin(struct rzt2h_pinctrl *pctrl, unsigned int offset)
return (pincfg & BIT(pin)) ? 0 : -EINVAL;
}
+static void rzt2h_pinctrl_set_gpio_en(struct rzt2h_pinctrl *pctrl,
+ u8 port, u8 pin, bool en)
+{
+ u8 reg = rzt2h_pinctrl_readb(pctrl, port, PMC(port));
+
+ if (en)
+ reg &= ~BIT(pin);
+ else
+ reg |= BIT(pin);
+
+ rzt2h_pinctrl_writeb(pctrl, port, reg, PMC(port));
+}
+
static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl,
u8 port, u8 pin, u8 func)
{
@@ -133,8 +153,7 @@ static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl,
rzt2h_pinctrl_writew(pctrl, port, reg16, PM(port));
/* Temporarily switch to GPIO mode with PMC register */
- reg16 = rzt2h_pinctrl_readb(pctrl, port, PMC(port));
- rzt2h_pinctrl_writeb(pctrl, port, reg16 & ~BIT(pin), PMC(port));
+ rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, true);
/* Select Pin function mode with PFC register */
reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port));
@@ -142,8 +161,7 @@ static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl,
rzt2h_pinctrl_writeq(pctrl, port, reg64 | ((u64)func << (pin * 8)), PFC(port));
/* Switch to Peripheral pin function with PMC register */
- reg16 = rzt2h_pinctrl_readb(pctrl, port, PMC(port));
- rzt2h_pinctrl_writeb(pctrl, port, reg16 | BIT(pin), PMC(port));
+ rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, false);
}
static int rzt2h_pinctrl_set_mux(struct pinctrl_dev *pctldev,
@@ -447,7 +465,6 @@ static int rzt2h_gpio_request(struct gpio_chip *chip, unsigned int offset)
u8 port = RZT2H_PIN_ID_TO_PORT(offset);
u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
int ret;
- u8 reg;
ret = rzt2h_validate_pin(pctrl, offset);
if (ret)
@@ -460,9 +477,7 @@ static int rzt2h_gpio_request(struct gpio_chip *chip, unsigned int offset)
guard(spinlock_irqsave)(&pctrl->lock);
/* Select GPIO mode in PMC Register */
- reg = rzt2h_pinctrl_readb(pctrl, port, PMC(port));
- reg &= ~BIT(bit);
- rzt2h_pinctrl_writeb(pctrl, port, reg, PMC(port));
+ rzt2h_pinctrl_set_gpio_en(pctrl, port, bit, true);
return 0;
}
@@ -486,6 +501,7 @@ static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip);
u8 port = RZT2H_PIN_ID_TO_PORT(offset);
u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
+ u64 reg64;
u16 reg;
int ret;
@@ -493,8 +509,25 @@ static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
if (ret)
return ret;
- if (rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit))
+ guard(spinlock_irqsave)(&pctrl->lock);
+
+ if (rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit)) {
+ /*
+ * When a GPIO is being requested as an IRQ, the pinctrl
+ * framework expects to be able to read the GPIO's direction.
+ * IRQ function is separate from GPIO, and enabling it takes the
+ * pin out of GPIO mode.
+ * At this point, .child_to_parent_hwirq() has already been
+ * called to enable the IRQ function.
+ * Default to input direction for IRQ function.
+ */
+ reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port));
+ reg64 = (reg64 >> (bit * 8)) & PFC_MASK;
+ if (reg64 == PFC_FUNC_INTERRUPT)
+ return GPIO_LINE_DIRECTION_IN;
+
return -EINVAL;
+ }
reg = rzt2h_pinctrl_readw(pctrl, port, PM(port));
reg = (reg >> (bit * 2)) & PM_MASK;
@@ -617,14 +650,185 @@ static const char * const rzt2h_gpio_names[] = {
"P35_0", "P35_1", "P35_2", "P35_3", "P35_4", "P35_5", "P35_6", "P35_7",
};
+/*
+ * Interrupts 0-15 are for INTCPUn, which are not exposed externally.
+ * Interrupts 16-31 are for IRQn. SEI is 32.
+ * This table matches the information found in User Manual's Section
+ * 17.5, Multiplexed Pin Configurations, Tables 17.5 to 17.40, on the
+ * Interrupt rows.
+ * RZ/N2H has the same GPIO to IRQ mapping, except for the pins which
+ * are not present.
+ */
+static const u8 rzt2h_gpio_irq_map[] = {
+ 32, 16, 17, 18, 19, 0, 20, 21,
+ 22, 0, 0, 0, 0, 0, 0, 0,
+ 23, 24, 25, 26, 27, 0, 0, 0,
+ 0, 0, 28, 29, 30, 31, 0, 0,
+ 0, 0, 0, 0, 0, 32, 16, 17,
+ 18, 19, 20, 21, 22, 0, 0, 0,
+ 0, 0, 24, 25, 26, 27, 0, 28,
+ 29, 30, 31, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 24, 32, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 20, 23, 17, 18, 19, 0, 16, 25,
+ 29, 20, 21, 22, 23, 0, 0, 0,
+ 0, 0, 0, 0, 17, 0, 0, 18,
+ 0, 0, 19, 0, 0, 20, 0, 30,
+ 21, 0, 0, 22, 0, 0, 24, 25,
+ 0, 0, 0, 0, 0, 16, 17, 0,
+ 18, 0, 0, 26, 27, 0, 0, 0,
+ 28, 29, 30, 31, 0, 0, 0, 0,
+ 23, 31, 32, 16, 17, 18, 19, 20,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 27, 0, 0, 21, 22, 23, 24, 25,
+ 26, 0, 0, 0, 0, 0, 0, 0,
+ 27, 28, 29, 30, 31, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 28, 32, 16,
+ 17, 18, 19, 0, 0, 0, 0, 20,
+ 21, 22, 23, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 24, 25, 0, 0,
+ 0, 0, 26, 27, 0, 0, 0, 30,
+ 0, 29, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 28, 29, 30, 31, 0,
+ 0, 0, 0, 0, 0, 0, 0, 30,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void rzt2h_gpio_irq_disable(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ unsigned int hwirq = irqd_to_hwirq(d);
+
+ irq_chip_disable_parent(d);
+ gpiochip_disable_irq(gc, hwirq);
+}
+
+static void rzt2h_gpio_irq_enable(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ unsigned int hwirq = irqd_to_hwirq(d);
+
+ gpiochip_enable_irq(gc, hwirq);
+ irq_chip_enable_parent(d);
+}
+
+static int rzt2h_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rzt2h_pinctrl *pctrl = container_of(gc, struct rzt2h_pinctrl, gpio_chip);
+ int ret;
+
+ ret = irq_chip_set_wake_parent(d, on);
+ if (ret)
+ return ret;
+
+ /*
+ * If any of the IRQs are in use, put the entire pin controller on the
+ * device wakeup path.
+ */
+ if (on)
+ atomic_inc(&pctrl->wakeup_path);
+ else
+ atomic_dec(&pctrl->wakeup_path);
+
+ return 0;
+}
+
+static const struct irq_chip rzt2h_gpio_irqchip = {
+ .name = "rzt2h-gpio",
+ .irq_disable = rzt2h_gpio_irq_disable,
+ .irq_enable = rzt2h_gpio_irq_enable,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_set_type = irq_chip_set_type_parent,
+ .irq_set_wake = rzt2h_gpio_irq_set_wake,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static int rzt2h_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
+ unsigned int child,
+ unsigned int child_type,
+ unsigned int *parent,
+ unsigned int *parent_type)
+{
+ struct rzt2h_pinctrl *pctrl = gpiochip_get_data(gc);
+ u8 port = RZT2H_PIN_ID_TO_PORT(child);
+ u8 pin = RZT2H_PIN_ID_TO_PIN(child);
+ u8 parent_irq;
+
+ parent_irq = rzt2h_gpio_irq_map[child];
+ if (parent_irq < RZT2H_INTERRUPTS_START)
+ return -EINVAL;
+
+ if (test_and_set_bit(parent_irq - RZT2H_INTERRUPTS_START,
+ pctrl->used_irqs))
+ return -EBUSY;
+
+ rzt2h_pinctrl_set_pfc_mode(pctrl, port, pin, PFC_FUNC_INTERRUPT);
+
+ *parent = parent_irq;
+ *parent_type = child_type;
+
+ return 0;
+}
+
+static void rzt2h_gpio_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rzt2h_pinctrl *pctrl = container_of(gc, struct rzt2h_pinctrl, gpio_chip);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u8 port = RZT2H_PIN_ID_TO_PORT(hwirq);
+ u8 pin = RZT2H_PIN_ID_TO_PIN(hwirq);
+
+ if (test_and_clear_bit(hwirq - RZT2H_INTERRUPTS_START, pctrl->used_irqs))
+ rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, false);
+
+ irq_domain_free_irqs_common(domain, virq, nr_irqs);
+}
+
+static void rzt2h_gpio_init_irq_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct rzt2h_pinctrl *pctrl = gpiochip_get_data(gc);
+ unsigned int offset;
+
+ for (offset = 0; offset < ngpios; offset++) {
+ if (!rzt2h_gpio_irq_map[offset] || rzt2h_validate_pin(pctrl, offset))
+ clear_bit(offset, valid_mask);
+ }
+}
+
static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl)
{
struct pinctrl_gpio_range *range = &pctrl->gpio_range;
struct gpio_chip *chip = &pctrl->gpio_chip;
+ struct device_node *np = pctrl->dev->of_node;
+ struct irq_domain *parent_domain;
struct device *dev = pctrl->dev;
struct of_phandle_args of_args;
+ struct device_node *parent_np;
+ struct gpio_irq_chip *girq;
int ret;
+ parent_np = of_irq_find_parent(np);
+ if (!parent_np)
+ return -ENXIO;
+
+ parent_domain = irq_find_host(parent_np);
+ of_node_put(parent_np);
+ if (!parent_domain)
+ return -EPROBE_DEFER;
+
ret = of_parse_phandle_with_fixed_args(dev->of_node, "gpio-ranges", 3, 0, &of_args);
if (ret)
return dev_err_probe(dev, ret, "Unable to parse gpio-ranges\n");
@@ -648,6 +852,17 @@ static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl)
chip->set = rzt2h_gpio_set;
chip->label = dev_name(dev);
+ if (of_property_present(np, "interrupt-controller")) {
+ girq = &chip->irq;
+ gpio_irq_chip_set_chip(girq, &rzt2h_gpio_irqchip);
+ girq->fwnode = dev_fwnode(pctrl->dev);
+ girq->parent_domain = parent_domain;
+ girq->child_to_parent_hwirq = rzt2h_gpio_child_to_parent_hwirq;
+ girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell;
+ girq->child_irq_domain_ops.free = rzt2h_gpio_irq_domain_free;
+ girq->init_valid_mask = rzt2h_gpio_init_irq_valid_mask;
+ }
+
range->id = 0;
range->pin_base = 0;
range->base = 0;
@@ -792,10 +1007,25 @@ static const struct of_device_id rzt2h_pinctrl_of_table[] = {
{ /* sentinel */ }
};
+static int rzt2h_pinctrl_suspend_noirq(struct device *dev)
+{
+ struct rzt2h_pinctrl *pctrl = dev_get_drvdata(dev);
+
+ if (atomic_read(&pctrl->wakeup_path))
+ device_set_wakeup_path(dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops rzt2h_pinctrl_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(rzt2h_pinctrl_suspend_noirq, NULL)
+};
+
static struct platform_driver rzt2h_pinctrl_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(rzt2h_pinctrl_of_table),
+ .pm = pm_sleep_ptr(&rzt2h_pinctrl_pm_ops),
.suppress_bind_attrs = true,
},
.probe = rzt2h_pinctrl_probe,
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 627dca504d7a..fe9f92cb037e 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -1770,6 +1770,123 @@ const struct samsung_pinctrl_of_match_data exynos8895_of_data __initconst = {
.num_ctrl = ARRAY_SIZE(exynos8895_pin_ctrl),
};
+/* pin banks of exynos9610 pin-controller 0 (ALIVE) */
+static const struct samsung_pin_bank_data exynos9610_pin_banks0[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTN(6, 0x000, "etc0"),
+ GS101_PIN_BANK_EINTW(8, 0x020, "gpa0", 0x00, 0x00),
+ GS101_PIN_BANK_EINTW(8, 0x040, "gpa1", 0x04, 0x08),
+ GS101_PIN_BANK_EINTW(8, 0x060, "gpa2", 0x08, 0x0c),
+ EXYNOS850_PIN_BANK_EINTN(5, 0x080, "gpq0"),
+};
+
+/* pin banks of exynos9610 pin-controller 1 (CMGP) */
+static const struct samsung_pin_bank_data exynos9610_pin_banks1[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTW(1, 0x000, "gpm0", 0x00),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x020, "gpm1", 0x04),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x040, "gpm2", 0x08),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x060, "gpm3", 0x0C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x080, "gpm4", 0x10),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0A0, "gpm5", 0x14),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0C0, "gpm6", 0x18),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0E0, "gpm7", 0x1C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x100, "gpm8", 0x20),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x120, "gpm9", 0x24),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x140, "gpm10", 0x28),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x160, "gpm11", 0x2C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x180, "gpm12", 0x30),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1A0, "gpm13", 0x34),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1C0, "gpm14", 0x38),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1E0, "gpm15", 0x3C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x200, "gpm16", 0x40),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x220, "gpm17", 0x44),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x240, "gpm18", 0x48),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x260, "gpm19", 0x4C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x280, "gpm20", 0x50),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x2A0, "gpm21", 0x54),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x2C0, "gpm22", 0x58),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x2E0, "gpm23", 0x5C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x300, "gpm24", 0x60),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x320, "gpm25", 0x64),
+};
+
+/* pin banks of exynos9610 pin-controller 2 (DISPAUD) */
+static const struct samsung_pin_bank_data exynos9610_pin_banks2[] __initconst = {
+ GS101_PIN_BANK_EINTG(5, 0x000, "gpb0", 0x00, 0x00),
+ GS101_PIN_BANK_EINTG(4, 0x020, "gpb1", 0x04, 0x08),
+ GS101_PIN_BANK_EINTG(5, 0x040, "gpb2", 0x08, 0x0c),
+};
+
+/* pin banks of exynos9610 pin-controller 3 (FSYS) */
+static const struct samsung_pin_bank_data exynos9610_pin_banks3[] __initconst = {
+ GS101_PIN_BANK_EINTG(4, 0x000, "gpf0", 0x00, 0x00),
+ GS101_PIN_BANK_EINTG(8, 0x020, "gpf1", 0x04, 0x04),
+ GS101_PIN_BANK_EINTG(6, 0x040, "gpf2", 0x08, 0x0c),
+};
+
+/* pin banks of exynos9610 pin-controller 4 (TOP) */
+static const struct samsung_pin_bank_data exynos9610_pin_banks4[] __initconst = {
+ GS101_PIN_BANK_EINTG(8, 0x000, "gpp0", 0x00, 0x00),
+ GS101_PIN_BANK_EINTG(6, 0x020, "gpp1", 0x04, 0x08),
+ GS101_PIN_BANK_EINTG(8, 0x040, "gpp2", 0x08, 0x10),
+ GS101_PIN_BANK_EINTG(8, 0x060, "gpc0", 0x0C, 0x18),
+ GS101_PIN_BANK_EINTG(8, 0x080, "gpc1", 0x10, 0x20),
+ GS101_PIN_BANK_EINTG(5, 0x0A0, "gpc2", 0x14, 0x28),
+ GS101_PIN_BANK_EINTG(8, 0x0C0, "gpg0", 0x18, 0x30),
+ GS101_PIN_BANK_EINTG(8, 0x0E0, "gpg1", 0x1C, 0x38),
+ GS101_PIN_BANK_EINTG(8, 0x100, "gpg2", 0x20, 0x40),
+ GS101_PIN_BANK_EINTG(6, 0x120, "gpg3", 0x24, 0x48),
+ GS101_PIN_BANK_EINTG(3, 0x140, "gpg4", 0x28, 0x50),
+};
+
+/* pin banks of exynos9610 pin-controller 5 (SHUB) */
+static const struct samsung_pin_bank_data exynos9610_pin_banks5[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTG(4, 0x000, "gph0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(3, 0x020, "gph1", 0x04),
+};
+
+static const struct samsung_pin_ctrl exynos9610_pin_ctrl[] __initconst = {
+ {
+ /* pin-controller instance 0 ALIVE data */
+ .pin_banks = exynos9610_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos9610_pin_banks0),
+ .eint_wkup_init = exynos_eint_wkup_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 1 CMGP data */
+ .pin_banks = exynos9610_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos9610_pin_banks1),
+ .eint_wkup_init = exynos_eint_wkup_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 2 DISPAUD data */
+ .pin_banks = exynos9610_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos9610_pin_banks2),
+ }, {
+ /* pin-controller instance 3 FSYS data */
+ .pin_banks = exynos9610_pin_banks3,
+ .nr_banks = ARRAY_SIZE(exynos9610_pin_banks3),
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 4 TOP data */
+ .pin_banks = exynos9610_pin_banks4,
+ .nr_banks = ARRAY_SIZE(exynos9610_pin_banks4),
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 5 SHUB data */
+ .pin_banks = exynos9610_pin_banks5,
+ .nr_banks = ARRAY_SIZE(exynos9610_pin_banks5),
+ },
+};
+
+const struct samsung_pinctrl_of_match_data exynos9610_of_data __initconst = {
+ .ctrl = exynos9610_pin_ctrl,
+ .num_ctrl = ARRAY_SIZE(exynos9610_pin_ctrl),
+};
+
/*
* Pinctrl driver data for Tesla FSD SoC. FSD SoC includes three
* gpio/pin-mux/pinconfig controllers.
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index e374effba25a..5ac6f6b02327 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1504,6 +1504,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
.data = &exynos8890_of_data },
{ .compatible = "samsung,exynos8895-pinctrl",
.data = &exynos8895_of_data },
+ { .compatible = "samsung,exynos9610-pinctrl",
+ .data = &exynos9610_of_data },
{ .compatible = "samsung,exynos9810-pinctrl",
.data = &exynos9810_of_data },
{ .compatible = "samsung,exynos990-pinctrl",
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index 0f7b2ea98158..937600430a6e 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -398,6 +398,7 @@ extern const struct samsung_pinctrl_of_match_data exynos7885_of_data;
extern const struct samsung_pinctrl_of_match_data exynos850_of_data;
extern const struct samsung_pinctrl_of_match_data exynos8890_of_data;
extern const struct samsung_pinctrl_of_match_data exynos8895_of_data;
+extern const struct samsung_pinctrl_of_match_data exynos9610_of_data;
extern const struct samsung_pinctrl_of_match_data exynos9810_of_data;
extern const struct samsung_pinctrl_of_match_data exynos990_of_data;
extern const struct samsung_pinctrl_of_match_data exynosautov9_of_data;
diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.h b/drivers/pinctrl/sophgo/pinctrl-cv18xx.h
index 759c0e604acf..973ab9a38fcf 100644
--- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.h
+++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.h
@@ -6,11 +6,7 @@
#ifndef _PINCTRL_SOPHGO_CV18XX_H
#define _PINCTRL_SOPHGO_CV18XX_H
-#include <linux/bits.h>
#include <linux/bitfield.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h>
diff --git a/drivers/pinctrl/sophgo/pinctrl-sg2042.h b/drivers/pinctrl/sophgo/pinctrl-sg2042.h
index d481973fcf97..1a2b00dde1fa 100644
--- a/drivers/pinctrl/sophgo/pinctrl-sg2042.h
+++ b/drivers/pinctrl/sophgo/pinctrl-sg2042.h
@@ -6,12 +6,6 @@
#ifndef _PINCTRL_SOPHGO_SG2042_H
#define _PINCTRL_SOPHGO_SG2042_H
-#include <linux/bits.h>
-#include <linux/bitfield.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h>
diff --git a/drivers/pinctrl/spacemit/Kconfig b/drivers/pinctrl/spacemit/Kconfig
index d6f6017fd097..c021d51033d1 100644
--- a/drivers/pinctrl/spacemit/Kconfig
+++ b/drivers/pinctrl/spacemit/Kconfig
@@ -4,7 +4,7 @@
#
config PINCTRL_SPACEMIT_K1
- bool "SpacemiT K1 SoC Pinctrl driver"
+ bool "SpacemiT K1/K3 SoC Pinctrl driver"
depends on ARCH_SPACEMIT || COMPILE_TEST
depends on OF
default ARCH_SPACEMIT
@@ -12,7 +12,7 @@ config PINCTRL_SPACEMIT_K1
select GENERIC_PINMUX_FUNCTIONS
select GENERIC_PINCONF
help
- Say Y to select the pinctrl driver for K1 SoC.
+ Say Y to select the pinctrl driver for K1/K3 SoC.
This pin controller allows selecting the mux function for
each pin. This driver can also be built as a module called
pinctrl-k1.
diff --git a/drivers/pinctrl/spacemit/pinctrl-k1.c b/drivers/pinctrl/spacemit/pinctrl-k1.c
index 33af9b5791c1..71390402aaa6 100644
--- a/drivers/pinctrl/spacemit/pinctrl-k1.c
+++ b/drivers/pinctrl/spacemit/pinctrl-k1.c
@@ -7,8 +7,10 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/mutex.h>
@@ -24,11 +26,12 @@
#include "pinctrl-k1.h"
/*
- * +---------+----------+-----------+--------+--------+----------+--------+
- * | pull | drive | schmitter | slew | edge | strong | mux |
- * | up/down | strength | trigger | rate | detect | pull | mode |
- * +---------+----------+-----------+--------+--------+----------+--------+
- * 3 bits 3 bits 2 bits 1 bit 3 bits 1 bit 3 bits
+ * | pull | drive | schmitter | slew | edge | strong | mux |
+ * SoC | up/down | strength | trigger | rate | detect | pull | mode |
+ *-----+---------+----------+-----------+-------+--------+--------+--------+
+ * K1 | 3 bits | 3 bits | 2 bits | 1 bit | 3 bits | 1 bit | 3 bits |
+ *-----+---------+----------+-----------+-------+--------+--------+--------+
+ * K3 | 3 bits | 4 bits | 1 bits | 1 bit | 3 bits | 1 bit | 3 bits |
*/
#define PAD_MUX GENMASK(2, 0)
@@ -38,12 +41,50 @@
#define PAD_EDGE_CLEAR BIT(6)
#define PAD_SLEW_RATE GENMASK(12, 11)
#define PAD_SLEW_RATE_EN BIT(7)
-#define PAD_SCHMITT GENMASK(9, 8)
-#define PAD_DRIVE GENMASK(12, 10)
+#define PAD_SCHMITT_K1 GENMASK(9, 8)
+#define PAD_DRIVE_K1 GENMASK(12, 10)
+#define PAD_SCHMITT_K3 BIT(8)
+#define PAD_DRIVE_K3 GENMASK(12, 9)
#define PAD_PULLDOWN BIT(13)
#define PAD_PULLUP BIT(14)
#define PAD_PULL_EN BIT(15)
+#define IO_PWR_DOMAIN_OFFSET 0x800
+
+#define IO_PWR_DOMAIN_GPIO2_Kx 0x0c
+#define IO_PWR_DOMAIN_MMC_Kx 0x1c
+
+#define IO_PWR_DOMAIN_GPIO3_K1 0x10
+#define IO_PWR_DOMAIN_QSPI_K1 0x20
+
+#define IO_PWR_DOMAIN_GPIO1_K3 0x04
+#define IO_PWR_DOMAIN_GPIO5_K3 0x10
+#define IO_PWR_DOMAIN_GPIO4_K3 0x20
+#define IO_PWR_DOMAIN_QSPI_K3 0x2c
+
+#define IO_PWR_DOMAIN_V18EN BIT(2)
+
+#define APBC_ASFAR 0x50
+#define APBC_ASSAR 0x54
+
+#define APBC_ASFAR_AKEY 0xbaba
+#define APBC_ASSAR_AKEY 0xeb10
+
+struct spacemit_pin_drv_strength {
+ u8 val;
+ u32 mA;
+};
+
+struct spacemit_pinctrl_dconf {
+ u64 schmitt_mask;
+ u64 drive_mask;
+
+ struct spacemit_pin_drv_strength *ds_1v8_tbl;
+ size_t ds_1v8_tbl_num;
+ struct spacemit_pin_drv_strength *ds_3v3_tbl;
+ size_t ds_3v3_tbl_num;
+};
+
struct spacemit_pin {
u16 pin;
u16 flags;
@@ -60,12 +101,17 @@ struct spacemit_pinctrl {
raw_spinlock_t lock;
void __iomem *regs;
+
+ struct regmap *regmap_apbc;
};
struct spacemit_pinctrl_data {
const struct pinctrl_pin_desc *pins;
const struct spacemit_pin *data;
u16 npins;
+ unsigned int (*pin_to_offset)(unsigned int pin);
+ unsigned int (*pin_to_io_pd_offset)(unsigned int pin);
+ const struct spacemit_pinctrl_dconf *dconf;
};
struct spacemit_pin_mux_config {
@@ -73,13 +119,8 @@ struct spacemit_pin_mux_config {
u32 config;
};
-struct spacemit_pin_drv_strength {
- u8 val;
- u32 mA;
-};
-
/* map pin id to pinctrl register offset, refer MFPR definition */
-static unsigned int spacemit_pin_to_offset(unsigned int pin)
+static unsigned int spacemit_k1_pin_to_offset(unsigned int pin)
{
unsigned int offset = 0;
@@ -124,10 +165,67 @@ static unsigned int spacemit_pin_to_offset(unsigned int pin)
return offset << 2;
}
+static unsigned int spacemit_k3_pin_to_offset(unsigned int pin)
+{
+ unsigned int offset = pin > 130 ? (pin + 2) : pin;
+
+ return offset << 2;
+}
+
+static unsigned int spacemit_k1_pin_to_io_pd_offset(unsigned int pin)
+{
+ unsigned int offset = 0;
+
+ switch (pin) {
+ case 47 ... 52:
+ offset = IO_PWR_DOMAIN_GPIO3_K1;
+ break;
+ case 75 ... 80:
+ offset = IO_PWR_DOMAIN_GPIO2_Kx;
+ break;
+ case 98 ... 103:
+ offset = IO_PWR_DOMAIN_QSPI_K1;
+ break;
+ case 104 ... 109:
+ offset = IO_PWR_DOMAIN_MMC_Kx;
+ break;
+ }
+
+ return offset;
+}
+
+static unsigned int spacemit_k3_pin_to_io_pd_offset(unsigned int pin)
+{
+ unsigned int offset = 0;
+
+ switch (pin) {
+ case 0 ... 20:
+ offset = IO_PWR_DOMAIN_GPIO1_K3;
+ break;
+ case 21 ... 41:
+ offset = IO_PWR_DOMAIN_GPIO2_Kx;
+ break;
+ case 76 ... 98:
+ offset = IO_PWR_DOMAIN_GPIO4_K3;
+ break;
+ case 99 ... 127:
+ offset = IO_PWR_DOMAIN_GPIO5_K3;
+ break;
+ case 132 ... 137:
+ offset = IO_PWR_DOMAIN_MMC_Kx;
+ break;
+ case 138 ... 144:
+ offset = IO_PWR_DOMAIN_QSPI_K3;
+ break;
+ }
+
+ return offset;
+}
+
static inline void __iomem *spacemit_pin_to_reg(struct spacemit_pinctrl *pctrl,
unsigned int pin)
{
- return pctrl->regs + spacemit_pin_to_offset(pin);
+ return pctrl->regs + pctrl->data->pin_to_offset(pin);
}
static u16 spacemit_dt_get_pin(u32 value)
@@ -177,7 +275,7 @@ static void spacemit_pctrl_dbg_show(struct pinctrl_dev *pctldev,
void __iomem *reg;
u32 value;
- seq_printf(seq, "offset: 0x%04x ", spacemit_pin_to_offset(pin));
+ seq_printf(seq, "offset: 0x%04x ", pctrl->data->pin_to_offset(pin));
seq_printf(seq, "type: %s ", io_type_desc[type]);
reg = spacemit_pin_to_reg(pctrl, pin);
@@ -185,23 +283,70 @@ static void spacemit_pctrl_dbg_show(struct pinctrl_dev *pctldev,
seq_printf(seq, "mux: %ld reg: 0x%04x", (value & PAD_MUX), value);
}
-/* use IO high level output current as the table */
-static struct spacemit_pin_drv_strength spacemit_ds_1v8_tbl[4] = {
- { 0, 11 },
- { 2, 21 },
- { 4, 32 },
- { 6, 42 },
+static const struct spacemit_pinctrl_dconf k1_drive_conf = {
+ .drive_mask = PAD_DRIVE_K1,
+ .schmitt_mask = PAD_SCHMITT_K1,
+ .ds_1v8_tbl = (struct spacemit_pin_drv_strength[]) {
+ { 0, 11 },
+ { 2, 21 },
+ { 4, 32 },
+ { 6, 42 },
+ },
+ .ds_1v8_tbl_num = 4,
+ .ds_3v3_tbl = (struct spacemit_pin_drv_strength[]) {
+ { 0, 7 },
+ { 2, 10 },
+ { 4, 13 },
+ { 6, 16 },
+ { 1, 19 },
+ { 3, 23 },
+ { 5, 26 },
+ { 7, 29 },
+ },
+ .ds_3v3_tbl_num = 8,
};
-static struct spacemit_pin_drv_strength spacemit_ds_3v3_tbl[8] = {
- { 0, 7 },
- { 2, 10 },
- { 4, 13 },
- { 6, 16 },
- { 1, 19 },
- { 3, 23 },
- { 5, 26 },
- { 7, 29 },
+static const struct spacemit_pinctrl_dconf k3_drive_conf = {
+ .drive_mask = PAD_DRIVE_K3,
+ .schmitt_mask = PAD_SCHMITT_K3,
+ .ds_1v8_tbl = (struct spacemit_pin_drv_strength[]) {
+ { 0, 2 },
+ { 1, 4 },
+ { 2, 6 },
+ { 3, 7 },
+ { 4, 9 },
+ { 5, 11 },
+ { 6, 13 },
+ { 7, 14 },
+ { 8, 21 },
+ { 9, 23 },
+ { 10, 25 },
+ { 11, 26 },
+ { 12, 28 },
+ { 13, 30 },
+ { 14, 31 },
+ { 15, 33 },
+ },
+ .ds_1v8_tbl_num = 16,
+ .ds_3v3_tbl = (struct spacemit_pin_drv_strength[]) {
+ { 0, 3 },
+ { 1, 5 },
+ { 2, 7 },
+ { 3, 9 },
+ { 4, 11 },
+ { 5, 13 },
+ { 6, 15 },
+ { 7, 17 },
+ { 8, 25 },
+ { 9, 27 },
+ { 10, 29 },
+ { 11, 31 },
+ { 12, 33 },
+ { 13, 35 },
+ { 14, 37 },
+ { 15, 38 },
+ },
+ .ds_3v3_tbl_num = 16,
};
static inline u8 spacemit_get_ds_value(struct spacemit_pin_drv_strength *tbl,
@@ -229,16 +374,17 @@ static inline u32 spacemit_get_ds_mA(struct spacemit_pin_drv_strength *tbl,
}
static inline u8 spacemit_get_driver_strength(enum spacemit_pin_io_type type,
+ const struct spacemit_pinctrl_dconf *dconf,
u32 mA)
{
switch (type) {
case IO_TYPE_1V8:
- return spacemit_get_ds_value(spacemit_ds_1v8_tbl,
- ARRAY_SIZE(spacemit_ds_1v8_tbl),
+ return spacemit_get_ds_value(dconf->ds_1v8_tbl,
+ dconf->ds_1v8_tbl_num,
mA);
case IO_TYPE_3V3:
- return spacemit_get_ds_value(spacemit_ds_3v3_tbl,
- ARRAY_SIZE(spacemit_ds_3v3_tbl),
+ return spacemit_get_ds_value(dconf->ds_3v3_tbl,
+ dconf->ds_3v3_tbl_num,
mA);
default:
return 0;
@@ -246,16 +392,17 @@ static inline u8 spacemit_get_driver_strength(enum spacemit_pin_io_type type,
}
static inline u32 spacemit_get_drive_strength_mA(enum spacemit_pin_io_type type,
+ const struct spacemit_pinctrl_dconf *dconf,
u32 value)
{
switch (type) {
case IO_TYPE_1V8:
- return spacemit_get_ds_mA(spacemit_ds_1v8_tbl,
- ARRAY_SIZE(spacemit_ds_1v8_tbl),
- value & 0x6);
+ return spacemit_get_ds_mA(dconf->ds_1v8_tbl,
+ dconf->ds_1v8_tbl_num,
+ value);
case IO_TYPE_3V3:
- return spacemit_get_ds_mA(spacemit_ds_3v3_tbl,
- ARRAY_SIZE(spacemit_ds_3v3_tbl),
+ return spacemit_get_ds_mA(dconf->ds_3v3_tbl,
+ dconf->ds_3v3_tbl_num,
value);
default:
return 0;
@@ -294,6 +441,42 @@ static int spacemit_pctrl_check_power(struct pinctrl_dev *pctldev,
return 0;
}
+static void spacemit_set_io_pwr_domain(struct spacemit_pinctrl *pctrl,
+ const struct spacemit_pin *spin,
+ const enum spacemit_pin_io_type type)
+{
+ u32 offset, val = 0;
+
+ if (!pctrl->regmap_apbc)
+ return;
+
+ offset = pctrl->data->pin_to_io_pd_offset(spin->pin);
+
+ /* Other bits are reserved so don't need to save them */
+ if (type == IO_TYPE_1V8)
+ val = IO_PWR_DOMAIN_V18EN;
+
+ /*
+ * IO power domain registers are protected and cannot be accessed
+ * directly. Before performing any read or write to the IO power
+ * domain registers, an explicit unlock sequence must be issued
+ * via the AIB Secure Access Register (ASAR).
+ *
+ * The unlock sequence allows exactly one subsequent access to the
+ * IO power domain registers. After that access completes, the ASAR
+ * keys are automatically cleared, and the registers become locked
+ * again.
+ *
+ * This mechanism ensures that IO power domain configuration is
+ * performed intentionally, as incorrect voltage settings may
+ * result in functional failures or hardware damage.
+ */
+ regmap_write(pctrl->regmap_apbc, APBC_ASFAR, APBC_ASFAR_AKEY);
+ regmap_write(pctrl->regmap_apbc, APBC_ASSAR, APBC_ASSAR_AKEY);
+
+ writel_relaxed(val, pctrl->regs + IO_PWR_DOMAIN_OFFSET + offset);
+}
+
static int spacemit_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **maps,
@@ -501,7 +684,9 @@ static int spacemit_pinconf_get(struct pinctrl_dev *pctldev,
#define ENABLE_DRV_STRENGTH BIT(1)
#define ENABLE_SLEW_RATE BIT(2)
-static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin,
+static int spacemit_pinconf_generate_config(struct spacemit_pinctrl *pctrl,
+ const struct spacemit_pin *spin,
+ const struct spacemit_pinctrl_dconf *dconf,
unsigned long *configs,
unsigned int num_configs,
u32 *value)
@@ -539,8 +724,8 @@ static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin,
drv_strength = arg;
break;
case PIN_CONFIG_INPUT_SCHMITT:
- v &= ~PAD_SCHMITT;
- v |= FIELD_PREP(PAD_SCHMITT, arg);
+ v &= ~dconf->schmitt_mask;
+ v |= (arg << __ffs(dconf->schmitt_mask)) & dconf->schmitt_mask;
break;
case PIN_CONFIG_POWER_SOURCE:
voltage = arg;
@@ -574,12 +759,13 @@ static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin,
default:
return -EINVAL;
}
+ spacemit_set_io_pwr_domain(pctrl, spin, type);
}
- val = spacemit_get_driver_strength(type, drv_strength);
+ val = spacemit_get_driver_strength(type, dconf, drv_strength);
- v &= ~PAD_DRIVE;
- v |= FIELD_PREP(PAD_DRIVE, val);
+ v &= ~dconf->drive_mask;
+ v |= (val << __ffs(dconf->drive_mask)) & dconf->drive_mask;
}
if (flag & ENABLE_SLEW_RATE) {
@@ -629,7 +815,8 @@ static int spacemit_pinconf_set(struct pinctrl_dev *pctldev,
const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
u32 value;
- if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value))
+ if (spacemit_pinconf_generate_config(pctrl, spin, pctrl->data->dconf,
+ configs, num_configs, &value))
return -EINVAL;
return spacemit_pin_set_config(pctrl, pin, value);
@@ -651,7 +838,8 @@ static int spacemit_pinconf_group_set(struct pinctrl_dev *pctldev,
return -EINVAL;
spin = spacemit_get_pin(pctrl, group->grp.pins[0]);
- if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value))
+ if (spacemit_pinconf_generate_config(pctrl, spin, pctrl->data->dconf,
+ configs, num_configs, &value))
return -EINVAL;
for (i = 0; i < group->grp.npins; i++)
@@ -685,6 +873,7 @@ static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *seq, unsigned int pin)
{
struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct spacemit_pinctrl_dconf *dconf = pctrl->data->dconf;
const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
enum spacemit_pin_io_type type = spacemit_to_pin_io_type(spin);
void __iomem *reg = spacemit_pin_to_reg(pctrl, pin);
@@ -695,17 +884,17 @@ static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev,
seq_printf(seq, ", io type (%s)", io_type_desc[type]);
- tmp = FIELD_GET(PAD_DRIVE, value);
+ tmp = (value & dconf->drive_mask) >> __ffs(dconf->drive_mask);
if (type == IO_TYPE_1V8 || type == IO_TYPE_3V3) {
- mA = spacemit_get_drive_strength_mA(type, tmp);
+ mA = spacemit_get_drive_strength_mA(type, dconf, tmp);
seq_printf(seq, ", drive strength (%d mA)", mA);
}
/* drive strength depend on power source, so show all values */
if (type == IO_TYPE_EXTERNAL)
seq_printf(seq, ", drive strength (%d or %d mA)",
- spacemit_get_drive_strength_mA(IO_TYPE_1V8, tmp),
- spacemit_get_drive_strength_mA(IO_TYPE_3V3, tmp));
+ spacemit_get_drive_strength_mA(IO_TYPE_1V8, dconf, tmp),
+ spacemit_get_drive_strength_mA(IO_TYPE_3V3, dconf, tmp));
seq_printf(seq, ", register (0x%04x)", value);
}
@@ -720,6 +909,7 @@ static const struct pinconf_ops spacemit_pinconf_ops = {
static int spacemit_pinctrl_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct spacemit_pinctrl *pctrl;
struct clk *func_clk, *bus_clk;
@@ -741,6 +931,12 @@ static int spacemit_pinctrl_probe(struct platform_device *pdev)
if (IS_ERR(pctrl->regs))
return PTR_ERR(pctrl->regs);
+ pctrl->regmap_apbc = syscon_regmap_lookup_by_phandle(np, "spacemit,apbc");
+ if (IS_ERR(pctrl->regmap_apbc)) {
+ dev_warn(dev, "no syscon found, disable power voltage switch functionality\n");
+ pctrl->regmap_apbc = NULL;
+ }
+
func_clk = devm_clk_get_enabled(dev, "func");
if (IS_ERR(func_clk))
return dev_err_probe(dev, PTR_ERR(func_clk), "failed to get func clock\n");
@@ -1042,10 +1238,352 @@ static const struct spacemit_pinctrl_data k1_pinctrl_data = {
.pins = k1_pin_desc,
.data = k1_pin_data,
.npins = ARRAY_SIZE(k1_pin_desc),
+ .pin_to_offset = spacemit_k1_pin_to_offset,
+ .pin_to_io_pd_offset = spacemit_k1_pin_to_io_pd_offset,
+ .dconf = &k1_drive_conf,
+};
+
+static const struct pinctrl_pin_desc k3_pin_desc[] = {
+ PINCTRL_PIN(0, "GPIO_00"),
+ PINCTRL_PIN(1, "GPIO_01"),
+ PINCTRL_PIN(2, "GPIO_02"),
+ PINCTRL_PIN(3, "GPIO_03"),
+ PINCTRL_PIN(4, "GPIO_04"),
+ PINCTRL_PIN(5, "GPIO_05"),
+ PINCTRL_PIN(6, "GPIO_06"),
+ PINCTRL_PIN(7, "GPIO_07"),
+ PINCTRL_PIN(8, "GPIO_08"),
+ PINCTRL_PIN(9, "GPIO_09"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "PWR_SCL"),
+ PINCTRL_PIN(129, "PWR_SDA"),
+ PINCTRL_PIN(130, "VCXO_EN"),
+ PINCTRL_PIN(131, "PMIC_INT_N"),
+ PINCTRL_PIN(132, "MMC1_DAT3"),
+ PINCTRL_PIN(133, "MMC1_DAT2"),
+ PINCTRL_PIN(134, "MMC1_DAT1"),
+ PINCTRL_PIN(135, "MMC1_DAT0"),
+ PINCTRL_PIN(136, "MMC1_CMD"),
+ PINCTRL_PIN(137, "MMC1_CLK"),
+ PINCTRL_PIN(138, "QSPI_DAT0"),
+ PINCTRL_PIN(139, "QSPI_DAT1"),
+ PINCTRL_PIN(140, "QSPI_DAT2"),
+ PINCTRL_PIN(141, "QSPI_DAT3"),
+ PINCTRL_PIN(142, "QSPI_CS0"),
+ PINCTRL_PIN(143, "QSPI_CS1"),
+ PINCTRL_PIN(144, "QSPI_CLK"),
+ PINCTRL_PIN(145, "PRI_TDI"),
+ PINCTRL_PIN(146, "PRI_TMS"),
+ PINCTRL_PIN(147, "PRI_TCK"),
+ PINCTRL_PIN(148, "PRI_TDO"),
+ PINCTRL_PIN(149, "PWR_SSP_SCLK"),
+ PINCTRL_PIN(150, "PWR_SSP_FRM"),
+ PINCTRL_PIN(151, "PWR_SSP_TXD"),
+ PINCTRL_PIN(152, "PWR_SSP_RXD"),
+};
+
+static const struct spacemit_pin k3_pin_data[ARRAY_SIZE(k3_pin_desc)] = {
+ /* GPIO1 bank */
+ K1_FUNC_PIN(0, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(1, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(2, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(3, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(4, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(5, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(6, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(7, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(8, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(9, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(10, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(11, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(12, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(13, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(14, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(15, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(16, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(17, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(18, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(19, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(20, 0, IO_TYPE_EXTERNAL),
+
+ /* GPIO2 bank */
+ K1_FUNC_PIN(21, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(22, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(23, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(24, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(25, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(26, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(27, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(28, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(29, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(30, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(31, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(32, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(33, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(34, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(35, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(36, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(37, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(38, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(39, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(40, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(41, 0, IO_TYPE_EXTERNAL),
+
+ /* GPIO3 bank */
+ K1_FUNC_PIN(42, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(43, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(44, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(45, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(46, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(47, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(48, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(49, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(50, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(51, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(52, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(53, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(54, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(55, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(56, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(57, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(58, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(59, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(60, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(61, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(62, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(63, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(64, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(65, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(66, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(67, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(68, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(69, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(70, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(71, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(72, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(73, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(74, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(75, 0, IO_TYPE_1V8),
+
+ /* GPIO4 bank */
+ K1_FUNC_PIN(76, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(77, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(78, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(79, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(80, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(81, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(82, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(83, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(84, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(85, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(86, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(87, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(88, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(89, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(90, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(91, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(92, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(93, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(94, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(95, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(96, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(97, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(98, 0, IO_TYPE_EXTERNAL),
+
+ /* GPIO5 bank */
+ K1_FUNC_PIN(99, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(100, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(101, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(102, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(103, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(104, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(105, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(106, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(107, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(108, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(109, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(110, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(111, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(112, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(113, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(114, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(115, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(116, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(117, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(118, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(119, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(120, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(121, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(122, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(123, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(124, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(125, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(126, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(127, 0, IO_TYPE_EXTERNAL),
+
+ /* PMIC */
+ K1_FUNC_PIN(128, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(129, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(130, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(131, 0, IO_TYPE_1V8),
+
+ /* SD/MMC1 */
+ K1_FUNC_PIN(132, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(133, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(134, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(135, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(136, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(137, 1, IO_TYPE_EXTERNAL),
+
+ /* QSPI */
+ K1_FUNC_PIN(138, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(139, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(140, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(141, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(142, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(143, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(144, 1, IO_TYPE_EXTERNAL),
+
+ /* PMIC */
+ K1_FUNC_PIN(145, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(146, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(147, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(148, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(149, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(150, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(151, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(152, 1, IO_TYPE_1V8),
+};
+
+static const struct spacemit_pinctrl_data k3_pinctrl_data = {
+ .pins = k3_pin_desc,
+ .data = k3_pin_data,
+ .npins = ARRAY_SIZE(k3_pin_desc),
+ .pin_to_offset = spacemit_k3_pin_to_offset,
+ .pin_to_io_pd_offset = spacemit_k3_pin_to_io_pd_offset,
+ .dconf = &k3_drive_conf,
};
static const struct of_device_id k1_pinctrl_ids[] = {
{ .compatible = "spacemit,k1-pinctrl", .data = &k1_pinctrl_data },
+ { .compatible = "spacemit,k3-pinctrl", .data = &k3_pinctrl_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, k1_pinctrl_ids);
@@ -1061,5 +1599,5 @@ static struct platform_driver k1_pinctrl_driver = {
builtin_platform_driver(k1_pinctrl_driver);
MODULE_AUTHOR("Yixun Lan <dlan@gentoo.org>");
-MODULE_DESCRIPTION("Pinctrl driver for the SpacemiT K1 SoC");
+MODULE_DESCRIPTION("Pinctrl driver for the SpacemiT K1/K3 SoC");
MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c
index 9b67063a0b0b..44f84e4c29bf 100644
--- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c
@@ -7,14 +7,11 @@
*/
#include <linux/bits.h>
-#include <linux/clk.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/mutex.h>
#include <linux/platform_device.h>
-#include <linux/reset.h>
#include <linux/spinlock.h>
#include <linux/pinctrl/pinctrl.h>
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c
index 49c5edeba87f..c6a51bb21215 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c
@@ -474,14 +474,14 @@ static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
#endif
};
-static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
+static void tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
{
u32 value;
- mutex_lock(&padctl->lock);
+ guard(mutex)(&padctl->lock);
if (padctl->enable++ > 0)
- goto out;
+ return;
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
@@ -498,23 +498,19 @@ static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
-
-out:
- mutex_unlock(&padctl->lock);
- return 0;
}
-static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
+static void tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
{
u32 value;
- mutex_lock(&padctl->lock);
+ guard(mutex)(&padctl->lock);
if (WARN_ON(padctl->enable == 0))
- goto out;
+ return;
if (--padctl->enable > 0)
- goto out;
+ return;
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
@@ -531,24 +527,24 @@ static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
-
-out:
- mutex_unlock(&padctl->lock);
- return 0;
}
static int tegra_xusb_phy_init(struct phy *phy)
{
struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
- return tegra_xusb_padctl_enable(padctl);
+ tegra_xusb_padctl_enable(padctl);
+
+ return 0;
}
static int tegra_xusb_phy_exit(struct phy *phy)
{
struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
- return tegra_xusb_padctl_disable(padctl);
+ tegra_xusb_padctl_disable(padctl);
+
+ return 0;
}
static int pcie_phy_power_on(struct phy *phy)