Linux GPIO subsystem development
 help / color / mirror / Atom feed
* [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards
@ 2026-11-15 10:23 Jisheng Zhang
  2026-11-15 10:23 ` [PATCH v2 01/13] arm64: kconfig: let ARCH_BERLIN cover Synaptics arm64 SoCs Jisheng Zhang
                   ` (12 more replies)
  0 siblings, 13 replies; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Add initial support for the Synaptics SL261X SoCs and corresponding
RDK boards.

The SL261X SoCs include five pin-to-pin compatible SoCs: SL2611, SL2613,
SL2615, SL2617, and SL2619.

Only reset, pinctrl, clk/pll, uart, gpio, i2c, spi, i3c are included in
this series. The support for Ethernet, USB, SDHCI, CAN, DMAC, XSPI will
be submitted after this series is merged.

since v1:
 - rebase on latest rcN
 - drop some patches which have been merged
 - let the "gbl" node export pinctrl/reset/clk devices with
   MFD_CELL_NAME()
 - use <linux/platform_device.h> instead of <linux/mod_devicetable.h>
 - adopt some coding suggestions from Uwe
 - Use 0 and 1 to select normal and strong pull-up on 10-bit pads 
 - collect Acked-by tag

Jisheng Zhang (13):
  arm64: kconfig: let ARCH_BERLIN cover Synaptics arm64 SoCs
  pinctrl: berlin: use u16 instead of u8 for the offset
  pinctrl: berlin: enable module build support
  pinctrl: berlin: add optional pinconf support
  dt-bindings: soc: synaptics: add SL2610 system controllers
  soc: synaptics: add SL2610 system controller support
  reset: add Synaptics SL2610 reset controller support
  pinctrl: berlin: add Synaptics SL2610 pin controller support
  clk: berlin: add Synaptics clock controller helpers
  clk: berlin: add Synaptics SL2610 clocks and PLLs
  dt-bindings: arm: berlin: add Synaptics SL2610 SoCs and RDK boards
  arm64: dts: synaptics: add SL2610 family SoCs
  arm64: dts: synaptics: add SL2610 family RDK boards

 .../bindings/arm/marvell,berlin.yaml          |  20 +
 .../soc/synaptics/syna,sl2610-soc-syscon.yaml | 178 ++++
 MAINTAINERS                                   |   8 +
 arch/arm64/Kconfig.platforms                  |   4 +-
 arch/arm64/boot/dts/synaptics/Makefile        |   5 +
 arch/arm64/boot/dts/synaptics/sl2611-rdk.dts  |  16 +
 arch/arm64/boot/dts/synaptics/sl2611.dtsi     | 457 +++++++++++
 arch/arm64/boot/dts/synaptics/sl2613-rdk.dts  |  16 +
 arch/arm64/boot/dts/synaptics/sl2613.dtsi     |  12 +
 arch/arm64/boot/dts/synaptics/sl2615-rdk.dts  |  16 +
 arch/arm64/boot/dts/synaptics/sl2615.dtsi     |  46 ++
 arch/arm64/boot/dts/synaptics/sl2617-rdk.dts  |  16 +
 arch/arm64/boot/dts/synaptics/sl2617.dtsi     |  46 ++
 arch/arm64/boot/dts/synaptics/sl2619-rdk.dts  |  16 +
 arch/arm64/boot/dts/synaptics/sl2619.dtsi     |  44 +
 .../boot/dts/synaptics/sl261x-rdk-common.dtsi | 135 ++++
 drivers/clk/Kconfig                           |   1 +
 drivers/clk/berlin/Kconfig                    |  34 +
 drivers/clk/berlin/Makefile                   |   4 +
 drivers/clk/berlin/clk-sl2610.c               | 360 +++++++++
 drivers/clk/berlin/sl-clk.c                   | 279 +++++++
 drivers/clk/berlin/sl-clk.h                   |  31 +
 drivers/clk/berlin/sl-sysmgr-clk.c            | 241 ++++++
 drivers/clk/berlin/sl-sysmgr-clk.h            |  44 +
 drivers/clk/berlin/sl2610-pll.c               | 145 ++++
 drivers/clk/berlin/sl2610-pll.h               |  14 +
 drivers/pinctrl/berlin/Kconfig                |  16 +
 drivers/pinctrl/berlin/Makefile               |   1 +
 drivers/pinctrl/berlin/berlin.c               | 259 +++++-
 drivers/pinctrl/berlin/berlin.h               |  17 +-
 drivers/pinctrl/berlin/pinctrl-sl2610.c       | 759 ++++++++++++++++++
 drivers/reset/Kconfig                         |  13 +
 drivers/reset/Makefile                        |   1 +
 drivers/reset/reset-sl2610.c                  | 224 ++++++
 drivers/soc/Kconfig                           |   1 +
 drivers/soc/Makefile                          |   1 +
 drivers/soc/synaptics/Kconfig                 |  14 +
 drivers/soc/synaptics/Makefile                |   2 +
 drivers/soc/synaptics/sl2610-syscon.c         |  84 ++
 include/dt-bindings/clock/syna,sl2610.h       | 131 +++
 include/dt-bindings/reset/syna,sl2610-reset.h |  80 ++
 41 files changed, 3771 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/soc/synaptics/syna,sl2610-soc-syscon.yaml
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2611-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2611.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2613-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2613.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2615-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2615.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2617-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2617.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2619-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2619.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl261x-rdk-common.dtsi
 create mode 100644 drivers/clk/berlin/Kconfig
 create mode 100644 drivers/clk/berlin/clk-sl2610.c
 create mode 100644 drivers/clk/berlin/sl-clk.c
 create mode 100644 drivers/clk/berlin/sl-clk.h
 create mode 100644 drivers/clk/berlin/sl-sysmgr-clk.c
 create mode 100644 drivers/clk/berlin/sl-sysmgr-clk.h
 create mode 100644 drivers/clk/berlin/sl2610-pll.c
 create mode 100644 drivers/clk/berlin/sl2610-pll.h
 create mode 100644 drivers/pinctrl/berlin/pinctrl-sl2610.c
 create mode 100644 drivers/reset/reset-sl2610.c
 create mode 100644 drivers/soc/synaptics/Kconfig
 create mode 100644 drivers/soc/synaptics/Makefile
 create mode 100644 drivers/soc/synaptics/sl2610-syscon.c
 create mode 100644 include/dt-bindings/clock/syna,sl2610.h
 create mode 100644 include/dt-bindings/reset/syna,sl2610-reset.h

-- 
2.55.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 01/13] arm64: kconfig: let ARCH_BERLIN cover Synaptics arm64 SoCs
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 10:23 ` [PATCH v2 02/13] pinctrl: berlin: use u16 instead of u8 for the offset Jisheng Zhang
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Extend ARCH_BERLIN to cover Synaptics arm64 SoCs.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 arch/arm64/Kconfig.platforms | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 49dcd7be82ce..b830161fe68b 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -108,13 +108,13 @@ config ARCH_BRCMSTB
 endif
 
 config ARCH_BERLIN
-	bool "Marvell Berlin SoC Family"
+	bool "Synaptics/Marvell Berlin SoC Family"
 	select DW_APB_ICTL
 	select DW_APB_TIMER_OF
 	select GPIOLIB
 	select PINCTRL
 	help
-	  This enables support for Marvell Berlin SoC Family
+	  This enables support for Synaptics SoCs or Marvell Berlin SoC Family
 
 config ARCH_BITMAIN
 	bool "Bitmain SoC Platforms"
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 02/13] pinctrl: berlin: use u16 instead of u8 for the offset
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
  2026-11-15 10:23 ` [PATCH v2 01/13] arm64: kconfig: let ARCH_BERLIN cover Synaptics arm64 SoCs Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 10:23 ` [PATCH v2 03/13] pinctrl: berlin: enable module build support Jisheng Zhang
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

The u8 may not be enough for newer Synaptics SoCs.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/pinctrl/berlin/berlin.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/berlin/berlin.h b/drivers/pinctrl/berlin/berlin.h
index 231aab61d415..7e7096842eda 100644
--- a/drivers/pinctrl/berlin/berlin.h
+++ b/drivers/pinctrl/berlin/berlin.h
@@ -17,7 +17,7 @@ struct berlin_desc_function {
 
 struct berlin_desc_group {
 	const char			*name;
-	u8				offset;
+	u16				offset;
 	u8				bit_width;
 	u8				lsb;
 	struct berlin_desc_function	*functions;
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 03/13] pinctrl: berlin: enable module build support
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
  2026-11-15 10:23 ` [PATCH v2 01/13] arm64: kconfig: let ARCH_BERLIN cover Synaptics arm64 SoCs Jisheng Zhang
  2026-11-15 10:23 ` [PATCH v2 02/13] pinctrl: berlin: use u16 instead of u8 for the offset Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 10:58   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 04/13] pinctrl: berlin: add optional pinconf support Jisheng Zhang
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

For Android GKI + vendor_dlkm deployments, where vendor-specific
drivers must be kept separate from the GKI vmlinux and loaded as
modules from the vendor partition, we need to enable module build
support for berlin pinctrl drivers.

To acchive this goal:

1.Use devm_* APIs to alloc memory, so that we don't need to care free when
unloading.

2.Export two symbols which will be used by SoC pinctrl drivers.

3.Add MODULE_LICENSE and MODULE_DESCRIPTION

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/pinctrl/berlin/berlin.c | 27 ++++++++++++++-------------
 drivers/pinctrl/berlin/berlin.h | 15 +++++++++++++++
 2 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c
index 8a612ce2d1d3..a0ae75b1d705 100644
--- a/drivers/pinctrl/berlin/berlin.c
+++ b/drivers/pinctrl/berlin/berlin.c
@@ -215,7 +215,8 @@ static int berlin_pinctrl_build_state(struct platform_device *pdev)
 	}
 
 	/* we will reallocate later */
-	pctrl->functions = kzalloc_objs(*pctrl->functions, max_functions);
+	pctrl->functions = devm_kcalloc(&pdev->dev, max_functions,
+					sizeof(*pctrl->functions), GFP_KERNEL);
 	if (!pctrl->functions)
 		return -ENOMEM;
 
@@ -230,13 +231,11 @@ static int berlin_pinctrl_build_state(struct platform_device *pdev)
 		}
 	}
 
-	new_functions = krealloc(pctrl->functions,
-				    pctrl->nfunctions * sizeof(*pctrl->functions),
-				    GFP_KERNEL);
-	if (!new_functions) {
-		kfree(pctrl->functions);
+	new_functions = devm_krealloc(&pdev->dev, pctrl->functions,
+				      pctrl->nfunctions * sizeof(*pctrl->functions),
+				      GFP_KERNEL);
+	if (!new_functions)
 		return -ENOMEM;
-	}
 
 	pctrl->functions = new_functions;
 	/* map functions to theirs groups */
@@ -257,20 +256,17 @@ static int berlin_pinctrl_build_state(struct platform_device *pdev)
 				function++;
 			}
 
-			if (!found) {
-				kfree(pctrl->functions);
+			if (!found)
 				return -EINVAL;
-			}
 
 			if (!function->groups) {
 				function->groups =
 					devm_kzalloc_objs(&pdev->dev,
 							  *function->groups,
 							  function->ngroups);
-				if (!function->groups) {
-					kfree(pctrl->functions);
+
+				if (!function->groups)
 					return -ENOMEM;
-				}
 			}
 
 			groups = (const char **)function->groups;
@@ -326,6 +322,7 @@ int berlin_pinctrl_probe_regmap(struct platform_device *pdev,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(berlin_pinctrl_probe_regmap);
 
 int berlin_pinctrl_probe(struct platform_device *pdev,
 			 const struct berlin_pinctrl_desc *desc)
@@ -340,3 +337,7 @@ int berlin_pinctrl_probe(struct platform_device *pdev,
 
 	return berlin_pinctrl_probe_regmap(pdev, desc, regmap);
 }
+EXPORT_SYMBOL_GPL(berlin_pinctrl_probe);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("pinctrl library for Synaptics SoCs");
diff --git a/drivers/pinctrl/berlin/berlin.h b/drivers/pinctrl/berlin/berlin.h
index 7e7096842eda..8ff70d682593 100644
--- a/drivers/pinctrl/berlin/berlin.h
+++ b/drivers/pinctrl/berlin/berlin.h
@@ -20,6 +20,8 @@ struct berlin_desc_group {
 	u16				offset;
 	u8				bit_width;
 	u8				lsb;
+	u16				conf_offset;
+	u8				conf_bits;
 	struct berlin_desc_function	*functions;
 };
 
@@ -28,6 +30,19 @@ struct berlin_pinctrl_desc {
 	unsigned			ngroups;
 };
 
+#define BERLIN_PINCTRLCONF_GROUP(_name, _offset, _width, _lsb,		\
+		_conf_offset, _conf_bits, ...)				\
+	{								\
+		.name = _name,						\
+		.offset = _offset,					\
+		.bit_width = _width,					\
+		.lsb = _lsb,						\
+		.conf_offset = _conf_offset,				\
+		.conf_bits = _conf_bits,				\
+		.functions = (struct berlin_desc_function[]){		\
+			__VA_ARGS__, { } },				\
+	}
+
 #define BERLIN_PINCTRL_GROUP(_name, _offset, _width, _lsb, ...)		\
 	{								\
 		.name = _name,						\
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 04/13] pinctrl: berlin: add optional pinconf support
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (2 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 03/13] pinctrl: berlin: enable module build support Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 11:01   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 05/13] dt-bindings: soc: synaptics: add SL2610 system controllers Jisheng Zhang
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Add pin configuration support for newer Synaptics SoCs.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/pinctrl/berlin/Kconfig  |   1 +
 drivers/pinctrl/berlin/berlin.c | 234 +++++++++++++++++++++++++++++++-
 2 files changed, 230 insertions(+), 5 deletions(-)

diff --git a/drivers/pinctrl/berlin/Kconfig b/drivers/pinctrl/berlin/Kconfig
index 9b1644d1d4ea..abb1c912b9ba 100644
--- a/drivers/pinctrl/berlin/Kconfig
+++ b/drivers/pinctrl/berlin/Kconfig
@@ -3,6 +3,7 @@ if (ARCH_BERLIN || COMPILE_TEST)
 
 config PINCTRL_BERLIN
 	bool
+	select GENERIC_PINCONF
 	select PINMUX
 	select REGMAP_MMIO
 
diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c
index a0ae75b1d705..0edf9d5a2a7b 100644
--- a/drivers/pinctrl/berlin/berlin.c
+++ b/drivers/pinctrl/berlin/berlin.c
@@ -7,12 +7,15 @@
  * Antoine Ténart <antoine.tenart@free-electrons.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/io.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/platform_device.h>
@@ -20,9 +23,24 @@
 #include <linux/slab.h>
 
 #include "../core.h"
+#include "../pinconf.h"
 #include "../pinctrl-utils.h"
 #include "berlin.h"
 
+#define PINCFG_DS_10BIT		GENMASK(3, 0)
+#define PINCFG_IE_10BIT		BIT(4)
+#define PINCFG_PE_10BIT		BIT(5)
+#define PINCFG_PS_10BIT		BIT(6)
+#define PINCFG_SL_10BIT		BIT(7)
+#define PINCFG_SPU_10BIT	BIT(8)
+#define PINCFG_ST_10BIT		BIT(9)
+#define PINCFG_DS_8BIT		GENMASK(2, 0)
+#define PINCFG_IE_8BIT		BIT(3)
+#define PINCFG_PD_8BIT		BIT(4)
+#define PINCFG_PU_8BIT		BIT(5)
+#define PINCFG_SL_8BIT		BIT(6)
+#define PINCFG_ST_8BIT		BIT(7)
+
 struct berlin_pinctrl {
 	struct regmap *regmap;
 	struct device *dev;
@@ -56,6 +74,8 @@ static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
 	struct property *prop;
 	const char *function_name, *group_name;
 	unsigned reserved_maps = 0;
+	unsigned long *configs = NULL;
+	unsigned int num_configs = 0;
 	int ret, ngroups;
 
 	*map = NULL;
@@ -75,11 +95,19 @@ static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
 		return -EINVAL;
 	}
 
+	ret = pinconf_generic_parse_dt_config(node, pctrl_dev, &configs,
+					      &num_configs);
+	if (ret < 0) {
+		dev_err(pctrl->dev, "%s: could not parse node property\n",
+			node->name);
+		return ret;
+	}
+
 	ret = pinctrl_utils_reserve_map(pctrl_dev, map, &reserved_maps,
-					num_maps, ngroups);
+					num_maps, ngroups * (num_configs + 1));
 	if (ret) {
 		dev_err(pctrl->dev, "can't reserve map: %d\n", ret);
-		return ret;
+		goto exit;
 	}
 
 	of_property_for_each_string(node, "groups", prop, group_name) {
@@ -88,11 +116,22 @@ static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
 						function_name);
 		if (ret) {
 			dev_err(pctrl->dev, "can't add map: %d\n", ret);
-			return ret;
+			goto exit;
+		}
+
+		if (num_configs) {
+			ret = pinctrl_utils_add_map_configs(pctrl_dev, map,
+					&reserved_maps, num_maps, group_name,
+					configs, num_configs,
+					PIN_MAP_TYPE_CONFIGS_GROUP);
+			if (ret < 0)
+				goto exit;
 		}
 	}
 
-	return 0;
+exit:
+	kfree(configs);
+	return ret;
 }
 
 static const struct pinctrl_ops berlin_pinctrl_ops = {
@@ -177,6 +216,190 @@ static const struct pinmux_ops berlin_pinmux_ops = {
 	.set_mux		= &berlin_pinmux_set,
 };
 
+static int berlin_pinconf_group_get(struct pinctrl_dev *pctrl_dev,
+				    unsigned int group, unsigned long *configs)
+{
+	enum pin_config_param param = pinconf_to_config_param(*configs);
+	struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+	const struct berlin_desc_group *group_desc = pctrl->desc->groups + group;
+	bool enabled;
+	u32 val;
+	int ret;
+	u8 conf_bits = group_desc->conf_bits;
+
+	if (!conf_bits)
+		return -EOPNOTSUPP;
+
+	ret = regmap_read(pctrl->regmap, group_desc->conf_offset, &val);
+	if (ret)
+		return ret;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		if (conf_bits == 10)
+			enabled = !(val & PINCFG_PE_10BIT);
+		else
+			enabled = !(val & (PINCFG_PD_8BIT | PINCFG_PU_8BIT));
+		val = 0;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (conf_bits == 10)
+			enabled = (val & (PINCFG_PE_10BIT | PINCFG_PS_10BIT)) == PINCFG_PE_10BIT;
+		else
+			enabled = val & PINCFG_PD_8BIT;
+		val = enabled ? 1 : 0;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (conf_bits == 10) {
+			enabled = (val & (PINCFG_PE_10BIT | PINCFG_PS_10BIT)) ==
+				  (PINCFG_PE_10BIT | PINCFG_PS_10BIT);
+			val = !!(val & PINCFG_SPU_10BIT);
+		} else {
+			enabled = val & PINCFG_PU_8BIT;
+			val = enabled ? 1 : 0;
+		}
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		enabled = true;
+		if (conf_bits == 10)
+			val = FIELD_GET(PINCFG_DS_10BIT, val);
+		else
+			val = FIELD_GET(PINCFG_DS_8BIT, val);
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		if (conf_bits == 10)
+			enabled = val & PINCFG_IE_10BIT;
+		else
+			enabled = val & PINCFG_IE_8BIT;
+		val = enabled ? 1 : 0;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		if (conf_bits == 10)
+			enabled = val & PINCFG_ST_10BIT;
+		else
+			enabled = val & PINCFG_ST_8BIT;
+		val = enabled ? 1 : 0;
+		break;
+	case PIN_CONFIG_SLEW_RATE:
+		if (conf_bits == 10)
+			enabled = val & PINCFG_SL_10BIT;
+		else
+			enabled = val & PINCFG_SL_8BIT;
+		val = enabled ? 1 : 0;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	*configs = pinconf_to_config_packed(param, val);
+	return enabled ? 0 : -EINVAL;
+}
+
+static int berlin_pinconf_group_set(struct pinctrl_dev *pctrl_dev,
+				    unsigned int group, unsigned long *configs,
+				    unsigned int nconfigs)
+{
+	struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+	const struct berlin_desc_group *group_desc = pctrl->desc->groups + group;
+	u8 conf_bits = group_desc->conf_bits;
+	u32 mask = 0, val = 0;
+	int i;
+
+	if (!conf_bits)
+		return -EOPNOTSUPP;
+
+	for (i = 0; i < nconfigs; i++) {
+		enum pin_config_param param =
+					pinconf_to_config_param(configs[i]);
+		u32 arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+		case PIN_CONFIG_BIAS_PULL_UP:
+			if (param != PIN_CONFIG_BIAS_DISABLE && arg > 1)
+				return -EINVAL;
+
+			if (conf_bits == 10) {
+				mask |= PINCFG_PE_10BIT | PINCFG_PS_10BIT |
+					PINCFG_SPU_10BIT;
+				val &= ~(PINCFG_PE_10BIT | PINCFG_PS_10BIT |
+					 PINCFG_SPU_10BIT);
+				if (param == PIN_CONFIG_BIAS_PULL_UP) {
+					val |= PINCFG_PE_10BIT | PINCFG_PS_10BIT;
+					if (arg)
+						val |= PINCFG_SPU_10BIT;
+				} else if (param == PIN_CONFIG_BIAS_PULL_DOWN && arg) {
+					val |= PINCFG_PE_10BIT;
+				}
+			} else {
+				mask |= PINCFG_PU_8BIT | PINCFG_PD_8BIT;
+				val &= ~(PINCFG_PU_8BIT | PINCFG_PD_8BIT);
+				if (param != PIN_CONFIG_BIAS_DISABLE && arg)
+					val |= param == PIN_CONFIG_BIAS_PULL_UP ?
+						PINCFG_PU_8BIT : PINCFG_PD_8BIT;
+			}
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			if (conf_bits == 10) {
+				if (arg > FIELD_MAX(PINCFG_DS_10BIT))
+					return -EINVAL;
+				mask |= PINCFG_DS_10BIT;
+				val |= FIELD_PREP(PINCFG_DS_10BIT, arg);
+			} else {
+				if (arg > FIELD_MAX(PINCFG_DS_8BIT))
+					return -EINVAL;
+				mask |= PINCFG_DS_8BIT;
+				val |= FIELD_PREP(PINCFG_DS_8BIT, arg);
+			}
+			break;
+		case PIN_CONFIG_INPUT_ENABLE:
+			if (conf_bits == 10) {
+				mask |= PINCFG_IE_10BIT;
+				if (arg)
+					val |= PINCFG_IE_10BIT;
+			} else {
+				mask |= PINCFG_IE_8BIT;
+				if (arg)
+					val |= PINCFG_IE_8BIT;
+			}
+			break;
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			if (conf_bits == 10) {
+				mask |= PINCFG_ST_10BIT;
+				if (arg)
+					val |= PINCFG_ST_10BIT;
+			} else {
+				mask |= PINCFG_ST_8BIT;
+				if (arg)
+					val |= PINCFG_ST_8BIT;
+			}
+			break;
+		case PIN_CONFIG_SLEW_RATE:
+			if (conf_bits == 10) {
+				mask |= PINCFG_SL_10BIT;
+				if (arg)
+					val |= PINCFG_SL_10BIT;
+			} else {
+				mask |= PINCFG_SL_8BIT;
+				if (arg)
+					val |= PINCFG_SL_8BIT;
+			}
+			break;
+		default:
+			return -EOPNOTSUPP;
+		}
+	}
+
+	return regmap_update_bits(pctrl->regmap, group_desc->conf_offset, mask, val);
+}
+
+static const struct pinconf_ops berlin_confops = {
+	.is_generic = true,
+	.pin_config_group_get = berlin_pinconf_group_get,
+	.pin_config_group_set = berlin_pinconf_group_set,
+};
+
 static int berlin_pinctrl_add_function(struct berlin_pinctrl *pctrl,
 				       const char *name)
 {
@@ -286,6 +509,7 @@ static const struct pinctrl_desc berlin_pctrl_desc = {
 	.name		= "berlin-pinctrl",
 	.pctlops	= &berlin_pinctrl_ops,
 	.pmxops		= &berlin_pinmux_ops,
+	.confops	= &berlin_confops,
 	.owner		= THIS_MODULE,
 };
 
@@ -339,5 +563,5 @@ int berlin_pinctrl_probe(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(berlin_pinctrl_probe);
 
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("pinctrl library for Synaptics SoCs");
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 05/13] dt-bindings: soc: synaptics: add SL2610 system controllers
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (3 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 04/13] pinctrl: berlin: add optional pinconf support Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 10:58   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 06/13] soc: synaptics: add SL2610 system controller support Jisheng Zhang
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Describe the SoC, MCU, AVIO and CPU system control blocks, including their
clock inputs, clock and reset providers, and pin configuration subnodes.
The clock and reset providers share each register block node.

Add the clock and reset identifiers used by consumers of these blocks.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 .../soc/synaptics/syna,sl2610-soc-syscon.yaml | 178 ++++++++++++++++++
 MAINTAINERS                                   |   3 +
 include/dt-bindings/clock/syna,sl2610.h       | 131 +++++++++++++
 include/dt-bindings/reset/syna,sl2610-reset.h |  80 ++++++++
 4 files changed, 392 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/synaptics/syna,sl2610-soc-syscon.yaml
 create mode 100644 include/dt-bindings/clock/syna,sl2610.h
 create mode 100644 include/dt-bindings/reset/syna,sl2610-reset.h

diff --git a/Documentation/devicetree/bindings/soc/synaptics/syna,sl2610-soc-syscon.yaml b/Documentation/devicetree/bindings/soc/synaptics/syna,sl2610-soc-syscon.yaml
new file mode 100644
index 000000000000..cdf947cb3e0f
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/synaptics/syna,sl2610-soc-syscon.yaml
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/synaptics/syna,sl2610-soc-syscon.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synaptics SL2610 system control registers
+
+maintainers:
+  - Jisheng Zhang <jszhang@kernel.org>
+
+description: |
+  The SL2610 family has separate SoC, MCU, AVIO, and CPU system control
+  register blocks. The SoC and MCU blocks provide clocks, resets, and pin
+  control. The CPU block provides clocks. The AVIO block contains audio PLLs.
+
+  Clock and reset specifiers refer directly to the system control node.
+  Pin group configurations are direct children of the SoC or MCU node.
+  There are no separate clock, reset, or pin controller child nodes.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - syna,sl2610-soc-syscon
+          - syna,sl2610-mcu-syscon
+          - syna,sl2610-avio-syscon
+          - syna,sl2610-cpu-syscon
+      - const: syscon
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: External reference clock input.
+
+  '#clock-cells':
+    const: 1
+
+  '#reset-cells':
+    const: 1
+
+  syna,gbl-syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: Phandle to the SoC system control registers for CPU PLL bypass.
+
+patternProperties:
+  '-(pmux|pins)$':
+    type: object
+    description: Pin group mux and electrical configuration.
+    allOf:
+      - $ref: /schemas/pinctrl/pinmux-node.yaml#
+      - $ref: /schemas/pinctrl/pincfg-node.yaml#
+    properties:
+      groups:
+        $ref: /schemas/types.yaml#/definitions/string-array
+      function:
+        $ref: /schemas/types.yaml#/definitions/string
+      bias-pull-up:
+        description: |
+          Enable pull-up bias and select its strength. A value of 0 selects
+          normal pull-up and 1 selects strong pull-up. The boolean form is
+          equivalent to 1 and selects strong pull-up. Use bias-disable to
+          disable pull bias. Values are mode selectors, not resistance in Ohms.
+        oneOf:
+          - type: boolean
+          - $ref: /schemas/types.yaml#/definitions/uint32
+            enum: [0, 1]
+      bias-pull-down:
+        description: |
+          Enable the default pull-down with a boolean or 1, or disable it with 0.
+          Pull resistance is not selectable.
+        oneOf:
+          - type: boolean
+          - $ref: /schemas/types.yaml#/definitions/uint32
+            enum: [0, 1]
+    required:
+      - groups
+      - function
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - syna,sl2610-soc-syscon
+              - syna,sl2610-mcu-syscon
+    then:
+      required:
+        - '#clock-cells'
+        - '#reset-cells'
+    else:
+      properties:
+        '#reset-cells': false
+      patternProperties:
+        '-(pmux|pins)$': false
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: syna,sl2610-cpu-syscon
+    then:
+      required:
+        - '#clock-cells'
+        - syna,gbl-syscon
+    else:
+      properties:
+        syna,gbl-syscon: false
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: syna,sl2610-avio-syscon
+    then:
+      properties:
+        '#clock-cells': false
+
+additionalProperties: false
+
+examples:
+  - |
+    soc_syscon: syscon@f7e10000 {
+        compatible = "syna,sl2610-soc-syscon", "syscon";
+        reg = <0xf7e10000 0x10000>;
+        clocks = <&osc>;
+        #clock-cells = <1>;
+        #reset-cells = <1>;
+
+        i2c2-pmux {
+            groups = "GPIO23", "GPIO24";
+            function = "tw2";
+            bias-pull-up = <0>;
+        };
+
+        i2c3-pmux {
+            groups = "GPIO27", "GPIO28";
+            function = "tw3";
+            bias-pull-up;
+        };
+    };
+
+    syscon@e5025000 {
+        compatible = "syna,sl2610-mcu-syscon", "syscon";
+        reg = <0xe5025000 0x1000>;
+        clocks = <&osc>;
+        #clock-cells = <1>;
+        #reset-cells = <1>;
+
+        i2c0-pmux {
+            groups = "SM_GPIO12", "SM_GPIO13";
+            function = "tw0";
+        };
+    };
+
+    syscon@f7e30000 {
+        compatible = "syna,sl2610-cpu-syscon", "syscon";
+        reg = <0xf7e30000 0x4000>;
+        clocks = <&osc>;
+        #clock-cells = <1>;
+        syna,gbl-syscon = <&soc_syscon>;
+    };
+
+    syscon@f7490000 {
+        compatible = "syna,sl2610-avio-syscon", "syscon";
+        reg = <0xf7490000 0x4000>;
+        clocks = <&osc>;
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 222b7fc2c3aa..e7c061ae5a87 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3808,9 +3808,12 @@ M:	Jisheng Zhang <jszhang@kernel.org>
 M:	Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
+F:	Documentation/devicetree/bindings/soc/synaptics/
 F:	arch/arm/boot/dts/synaptics/
 F:	arch/arm/mach-berlin/
 F:	arch/arm64/boot/dts/synaptics/
+F:	include/dt-bindings/clock/syna,sl2610.h
+F:	include/dt-bindings/reset/syna,sl2610-reset.h
 
 ARM/TEGRA HDMI CEC SUBSYSTEM SUPPORT
 M:	Hans Verkuil <hverkuil@kernel.org>
diff --git a/include/dt-bindings/clock/syna,sl2610.h b/include/dt-bindings/clock/syna,sl2610.h
new file mode 100644
index 000000000000..c563a2b5ed06
--- /dev/null
+++ b/include/dt-bindings/clock/syna,sl2610.h
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Synaptics SL2610 clock tree IDs
+ *
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+/* SoC domain */
+
+/* GBL common clks */
+#define CLK_CPUFASTREF		0
+#define CLK_MEMFASTREF		1
+#define CLK_CFG			2
+#define CLK_SYS			3
+#define CLK_PERIFSYS		4
+#define CLK_APBCORE		5
+#define CLK_APBSER		6
+#define CLK_ATB			7
+#define CLK_HPC			8
+#define CLK_EMMC		9
+#define CLK_SD0			10
+#define CLK_SD1			11
+#define CLK_GETHRGMII		12
+#define CLK_GETHRGMII1		13
+#define CLK_GE0_PTP_REF		14
+#define CLK_GE1_PTP_REF		15
+#define CLK_USB2TEST		16
+#define CLK_USB2TEST480MG0	17
+#define CLK_USB2TEST480MG1	18
+#define CLK_USB2TEST480MG2	19
+#define CLK_USB2TEST100MG0	20
+#define CLK_USB2TEST100MG1	21
+#define CLK_USB2TEST100MG2	22
+#define CLK_USB2TEST100MG3	23
+#define CLK_PERIFTEST125MG0	24
+#define CLK_PERIFTEST200MG0	25
+#define CLK_PERIFTEST200MG1	26
+#define CLK_GPU			27
+#define CLK_NPU			28
+#define CLK_AVIOSYS		29
+#define CLK_AIOSYS		30
+#define CLK_AVIO_LCDC2SCAN	31
+#define CLK_AVIO_IPI		32
+#define CLK_AVIO_P		33
+#define CLK_AVIO_DPHYRXTXESC	34
+#define CLK_AVIOFPLL		35
+#define CLK_AVIO_RX_SCANBYTE	36
+#define CLK_AVIO_RX_SCANTEST	37
+
+/* GBL gate clks */
+#define CLK_USB0CORE		38
+#define CLK_SDIOSYS		39
+#define CLK_EMMCSYS		40
+#define CLK_GPUAXI		41
+#define CLK_GETHRGMIISYS	42
+#define CLK_SDIO1SYS		43
+#define CLK_USB1CORE		44
+#define CLK_GETHRGMII1SYS	45
+#define CLK_USB0PHYREF		46
+#define CLK_USB1PHYREF		47
+#define CLK_APBUART0		48
+#define CLK_APBUART1		49
+#define CLK_APBUART2		50
+#define CLK_APBUART3		51
+#define CLK_APBI2C0		52
+#define CLK_APBI2C1		53
+#define CLK_APBSPI0		54
+#define CLK_APBSPI1		55
+#define CLK_APBSPI2		56
+#define CLK_APBSPI3		57
+#define CLK_APBGPIO		58
+#define CLK_APBTIMERS		59
+#define CLK_APBSYSCNT		60
+#define CLK_APBWDT		61
+#define CLK_APBDMA		62
+#define SL2610_CLK_MAX		63
+
+/* cpuss */
+#define CLK_CPU0		0
+#define CLK_CPU1		1
+#define CLK_DSU			2
+#define SL2610_CPU_CLK_MAX	3
+
+
+/* sysmgr domain */
+
+#define CLK_CFG_UART0		0
+#define CLK_SER_UART0		1
+#define CLK_CFG_UART1		2
+#define CLK_CFG_UART2		3
+#define CLK_CFG_UART3		4
+#define CLK_CFG_GPIO		5
+#define CLK_CFG_I2CM0		6
+#define CLK_CFG_I2CM1		7
+#define CLK_CFG_SPIM		8
+#define CLK_CFG_SPIS		9
+#define CLK_CFG_I3C		10
+#define CLK_CFG_XSPI		11
+#define CLK_AXI_XSPI		12
+#define CLK_CFG_PVT		13
+#define CLK_CFG_ADC		14
+#define CLK_CFG_PWM		15
+#define CLK_BUS_CAN0		16
+#define CLK_BUS_CAN1		17
+#define CLK_CFG_PDM		18
+
+#define CLK_SER_UART1		19
+#define CLK_SER_UART2		20
+#define CLK_SER_UART3		21
+#define CLK_DEB_GPIO		22
+#define CLK_SER_I2CM0		23
+#define CLK_SER_I2CM1		24
+#define CLK_SER_SPIM		25
+#define CLK_SER_SPIS		26
+#define CLK_SER_I3C		27
+#define CLK_SER_XSPI		28
+#define CLK_HS_PVT		29
+#define CLK_CORE_ADC		30
+#define CLK_SER_PWM		31
+#define CLK_SER_CAN0		32
+#define CLK_SER_CAN1		33
+#define CLK_SER_PDM		34
+#define CLK_REF_CALIB		35
+
+#define CLK_MCU_REF		36
+#define CLK_MCU_PLL		37
+#define CLK_MCU_IO_PLL		38
+#define CLK_MCU_APB		39
+#define CLK_MCU_AXI		40
diff --git a/include/dt-bindings/reset/syna,sl2610-reset.h b/include/dt-bindings/reset/syna,sl2610-reset.h
new file mode 100644
index 000000000000..909d63147692
--- /dev/null
+++ b/include/dt-bindings/reset/syna,sl2610-reset.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (C) 2026 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#ifndef _DT_BINDINGS_SL2610_RESET_H
+#define _DT_BINDINGS_SL2610_RESET_H
+
+/* ACPU subsystem */
+#define RST_SOC_SDIO0		0
+#define RST_SOC_USB0		1
+#define RST_SOC_EMMC		2
+#define RST_SOC_GETH0		3
+#define RST_SOC_SDIO1		4
+#define RST_SOC_USB1		5
+#define RST_SOC_GETH1		6
+#define RST_SOC_USB0PHY		7
+#define RST_SOC_USB0CORE	8
+#define RST_SOC_USB0MAHB	9
+#define RST_SOC_USB1PHY		10
+#define RST_SOC_USB1CORE	11
+#define RST_SOC_USB1MAHB	12
+#define RST_SOC_UART0		13
+#define RST_SOC_UART1		14
+#define RST_SOC_UART2		15
+#define RST_SOC_UART3		16
+#define RST_SOC_I2C0		17
+#define RST_SOC_I2C1		18
+#define RST_SOC_SPI0		19
+#define RST_SOC_SPI1		20
+#define RST_SOC_SPI2		21
+#define RST_SOC_SPI3		22
+#define RST_SOC_APBTIMERS	23
+#define RST_SOC_APBSYSCNT	24
+#define RST_SOC_APBWDT		25
+#define RST_SOC_APBGPIO		26
+#define RST_SOC_APBDMA		27
+#define RST_SOC_GPUCORE		28
+#define RST_SOC_NPUCORE		29
+#define RST_SOC_AVIOAIOG	30
+#define RST_SOC_AVIOVPPG	31
+#define RST_SOC_AVIOVIPG	32
+
+/* system subsystem */
+#define RST_SM_ADCCORE		0
+#define RST_SM_ADCPRST		1
+#define RST_SM_CAN0PRST		2
+#define RST_SM_CAN0SRST		3
+#define RST_SM_CAN1PRST		4
+#define RST_SM_CAN1SRST		5
+#define RST_SM_GPIOPRST		6
+#define RST_SM_GPIOSRST		7
+#define RST_SM_I2CM0PRST	8
+#define RST_SM_I2CM0SRST	9
+#define RST_SM_I2CM1PRST	10
+#define RST_SM_I2CM1SRST	11
+#define RST_SM_I3CPRST		12
+#define RST_SM_I3CSRST		13
+#define RST_SM_PDMPRST		14
+#define RST_SM_PDMSRST		15
+#define RST_SM_PVTHSRST		16
+#define RST_SM_PVTPRST		17
+#define RST_SM_PWMPERIRST	18
+#define RST_SM_PWMPRST		19
+#define RST_SM_SPIMPRST		20
+#define RST_SM_SPIMSRST		21
+#define RST_SM_SPISPRST		22
+#define RST_SM_SPISSRST		23
+#define RST_SM_UART0PRST	24
+#define RST_SM_UART0SRST	25
+#define RST_SM_UART1PRST	26
+#define RST_SM_UART1SRST	27
+#define RST_SM_UART2PRST	28
+#define RST_SM_UART2SRST	29
+#define RST_SM_UART3PRST	30
+#define RST_SM_UART3SRST	31
+
+#endif /* _DT_BINDINGS_SL2610_RESET_H */
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 06/13] soc: synaptics: add SL2610 system controller support
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (4 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 05/13] dt-bindings: soc: synaptics: add SL2610 system controllers Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 10:56   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 07/13] reset: add Synaptics SL2610 reset " Jisheng Zhang
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Create the clock, reset and pin controller platform devices implemented
by each SL2610 system control block. Select the appropriate MFD cells
from per-block compatible data while keeping register access available
through the shared syscon.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 MAINTAINERS                           |  1 +
 drivers/soc/Kconfig                   |  1 +
 drivers/soc/Makefile                  |  1 +
 drivers/soc/synaptics/Kconfig         | 14 +++++
 drivers/soc/synaptics/Makefile        |  2 +
 drivers/soc/synaptics/sl2610-syscon.c | 84 +++++++++++++++++++++++++++
 6 files changed, 103 insertions(+)
 create mode 100644 drivers/soc/synaptics/Kconfig
 create mode 100644 drivers/soc/synaptics/Makefile
 create mode 100644 drivers/soc/synaptics/sl2610-syscon.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e7c061ae5a87..eae1493485ee 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3812,6 +3812,7 @@ F:	Documentation/devicetree/bindings/soc/synaptics/
 F:	arch/arm/boot/dts/synaptics/
 F:	arch/arm/mach-berlin/
 F:	arch/arm64/boot/dts/synaptics/
+F:	drivers/soc/synaptics/
 F:	include/dt-bindings/clock/syna,sl2610.h
 F:	include/dt-bindings/reset/syna,sl2610-reset.h
 
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 483cbdcae153..5fe7348cddab 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -27,6 +27,7 @@ source "drivers/soc/sophgo/Kconfig"
 source "drivers/soc/st/Kconfig"
 source "drivers/soc/starfive/Kconfig"
 source "drivers/soc/sunxi/Kconfig"
+source "drivers/soc/synaptics/Kconfig"
 source "drivers/soc/tegra/Kconfig"
 source "drivers/soc/ti/Kconfig"
 source "drivers/soc/ux500/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5a3efd68355c..3e51563b914c 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -33,6 +33,7 @@ obj-y				+= sophgo/
 obj-y				+= st/
 obj-y				+= starfive/
 obj-y				+= sunxi/
+obj-y				+= synaptics/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-y				+= ti/
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
diff --git a/drivers/soc/synaptics/Kconfig b/drivers/soc/synaptics/Kconfig
new file mode 100644
index 000000000000..9f0324a1a3b7
--- /dev/null
+++ b/drivers/soc/synaptics/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config SOC_SL2610_SYSCON
+	tristate "Synaptics SL2610 system controller"
+	depends on ARCH_BERLIN || COMPILE_TEST
+	depends on OF && HAS_IOMEM
+	select MFD_CORE
+	select MFD_SYSCON
+	help
+	  Support the global and control register blocks on Synaptics SL2610
+	  SoCs. This creates devices for the clock, reset and pin controllers
+	  provided by each register block.
+
+	  Say Y here to enable access to these functions on SL2610 systems.
diff --git a/drivers/soc/synaptics/Makefile b/drivers/soc/synaptics/Makefile
new file mode 100644
index 000000000000..13710fc58903
--- /dev/null
+++ b/drivers/soc/synaptics/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SOC_SL2610_SYSCON) += sl2610-syscon.o
diff --git a/drivers/soc/synaptics/sl2610-syscon.c b/drivers/soc/synaptics/sl2610-syscon.c
new file mode 100644
index 000000000000..c6fc2955ac0d
--- /dev/null
+++ b/drivers/soc/synaptics/sl2610-syscon.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Synaptics Incorporated
+ */
+
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+struct sl2610_syscon_data {
+	const struct mfd_cell *cells;
+	unsigned int num_cells;
+};
+
+static const struct mfd_cell sl2610_soc_cells[] = {
+	MFD_CELL_NAME("sl2610-soc-clk"),
+	MFD_CELL_NAME("sl2610-soc-reset"),
+	MFD_CELL_NAME("sl2610-soc-pinctrl"),
+};
+
+static const struct mfd_cell sl2610_mcu_cells[] = {
+	MFD_CELL_NAME("sl2610-mcu-clk"),
+	MFD_CELL_NAME("sl2610-mcu-reset"),
+	MFD_CELL_NAME("sl2610-mcu-pinctrl"),
+};
+
+static const struct mfd_cell sl2610_avio_cells[] = {
+	MFD_CELL_NAME("sl2610-avio-clk"),
+};
+
+static const struct mfd_cell sl2610_cpu_cells[] = {
+	MFD_CELL_NAME("sl2610-cpu-clk"),
+};
+
+static const struct sl2610_syscon_data sl2610_soc_data = {
+	.cells = sl2610_soc_cells,
+	.num_cells = ARRAY_SIZE(sl2610_soc_cells),
+};
+
+static const struct sl2610_syscon_data sl2610_mcu_data = {
+	.cells = sl2610_mcu_cells,
+	.num_cells = ARRAY_SIZE(sl2610_mcu_cells),
+};
+
+static const struct sl2610_syscon_data sl2610_avio_data = {
+	.cells = sl2610_avio_cells,
+	.num_cells = ARRAY_SIZE(sl2610_avio_cells),
+};
+
+static const struct sl2610_syscon_data sl2610_cpu_data = {
+	.cells = sl2610_cpu_cells,
+	.num_cells = ARRAY_SIZE(sl2610_cpu_cells),
+};
+
+static int sl2610_syscon_probe(struct platform_device *pdev)
+{
+	const struct sl2610_syscon_data *data = device_get_match_data(&pdev->dev);
+
+	return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+				    data->cells, data->num_cells, NULL, 0, NULL);
+}
+
+static const struct of_device_id sl2610_syscon_of_match[] = {
+	{ .compatible = "syna,sl2610-soc-syscon", .data = &sl2610_soc_data },
+	{ .compatible = "syna,sl2610-mcu-syscon", .data = &sl2610_mcu_data },
+	{ .compatible = "syna,sl2610-avio-syscon", .data = &sl2610_avio_data },
+	{ .compatible = "syna,sl2610-cpu-syscon", .data = &sl2610_cpu_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sl2610_syscon_of_match);
+
+static struct platform_driver sl2610_syscon_driver = {
+	.probe = sl2610_syscon_probe,
+	.driver = {
+		.name = "sl2610-syscon",
+		.of_match_table = sl2610_syscon_of_match,
+	},
+};
+module_platform_driver(sl2610_syscon_driver);
+
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_DESCRIPTION("Synaptics SL2610 system controller");
+MODULE_LICENSE("GPL");
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 07/13] reset: add Synaptics SL2610 reset controller support
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (5 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 06/13] soc: synaptics: add SL2610 system controller support Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 11:12   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 08/13] pinctrl: berlin: add Synaptics SL2610 pin " Jisheng Zhang
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Support the SoC and MCU reset controls exposed by the SL2610 system
controllers. Match the MFD-created platform devices, use the parent
syscon regmap and register each reset provider against the parent DT node.

Handle both pulse resets and sticky resets with assert/deassert controls.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 MAINTAINERS                  |   1 +
 drivers/reset/Kconfig        |  13 ++
 drivers/reset/Makefile       |   1 +
 drivers/reset/reset-sl2610.c | 224 +++++++++++++++++++++++++++++++++++
 4 files changed, 239 insertions(+)
 create mode 100644 drivers/reset/reset-sl2610.c

diff --git a/MAINTAINERS b/MAINTAINERS
index eae1493485ee..1bd3b2f39865 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3812,6 +3812,7 @@ F:	Documentation/devicetree/bindings/soc/synaptics/
 F:	arch/arm/boot/dts/synaptics/
 F:	arch/arm/mach-berlin/
 F:	arch/arm64/boot/dts/synaptics/
+F:	drivers/reset/reset-sl2610.c
 F:	drivers/soc/synaptics/
 F:	include/dt-bindings/clock/syna,sl2610.h
 F:	include/dt-bindings/reset/syna,sl2610-reset.h
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index eda9c698a95f..98e973a8798c 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -358,6 +358,19 @@ config RESET_SUNXI
 	help
 	  This enables the reset driver for Allwinner SoCs.
 
+config RESET_SL2610
+	tristate "Synaptics SL2610 Reset Driver"
+	depends on ARCH_BERLIN || COMPILE_TEST
+	depends on OF && HAS_IOMEM
+	select SOC_SL2610_SYSCON
+	help
+	  Support the reset controllers in the SoC and MCU system control
+	  blocks of Synaptics SL2610 SoCs. Both pulse and sticky reset lines
+	  are supported.
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called reset-sl2610.
+
 config RESET_TENSTORRENT_ATLANTIS
 	tristate "Tenstorrent atlantis reset driver"
 	depends on ARCH_TENSTORRENT || COMPILE_TEST
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 489fafd6bbe3..d28276a4f2ea 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
 obj-$(CONFIG_RESET_SKY1) += reset-sky1.o
 obj-$(CONFIG_RESET_SKY1_AUDSS) += reset-sky1-audss.o
+obj-$(CONFIG_RESET_SL2610) += reset-sl2610.o
 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
diff --git a/drivers/reset/reset-sl2610.c b/drivers/reset/reset-sl2610.c
new file mode 100644
index 000000000000..1ca58d5a3e71
--- /dev/null
+++ b/drivers/reset/reset-sl2610.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 Synaptics Incorporated
+ *
+ * Synaptics SL2610 reset driver
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <dt-bindings/reset/syna,sl2610-reset.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/* SL2610 ACPU subsystem */
+#define SL2610_GBL_PERIFRESET			0x350
+#define SL2610_GBL_PERIFSTICKYRESET		0x360
+#define SL2610_GBL_APBPERIFRESET		0x370
+#define SL2610_GBL_TOPSTICKYRESET		0x378
+#define SL2610_GBL_AVIOSTICKYRESET		0x37c
+
+/* SL2610 system subsystem */
+#define SL2610_SMGBL_STICKYRST0			0x400
+
+#define to_sl2610_reset_priv(p)	container_of((p), struct sl2610_reset_priv, rcdev)
+
+#define SL2610_RESET(id, reg, bit, sticky)[id] = { reg, BIT(bit), sticky }
+
+struct sl2610_reset_cfg {
+	u32 reg;
+	u32 bit;
+	bool sticky;
+};
+
+struct sl2610_reset_data {
+	const struct sl2610_reset_cfg *cfgs;
+	size_t num;
+};
+
+struct sl2610_reset_priv {
+	struct regmap *regmap;
+	const struct sl2610_reset_cfg *cfgs;
+	struct reset_controller_dev rcdev;
+};
+
+static const struct sl2610_reset_cfg sl2610_reset_cfgs[] = {
+	SL2610_RESET(RST_SOC_SDIO0, SL2610_GBL_PERIFRESET, 2, false),
+	SL2610_RESET(RST_SOC_USB0, SL2610_GBL_PERIFRESET, 4, false),
+	SL2610_RESET(RST_SOC_EMMC, SL2610_GBL_PERIFRESET, 5, false),
+	SL2610_RESET(RST_SOC_GETH0, SL2610_GBL_PERIFRESET, 6, false),
+	SL2610_RESET(RST_SOC_SDIO1, SL2610_GBL_PERIFRESET, 7, false),
+	SL2610_RESET(RST_SOC_USB1, SL2610_GBL_PERIFRESET, 8, false),
+	SL2610_RESET(RST_SOC_GETH1, SL2610_GBL_PERIFRESET, 9, false),
+	SL2610_RESET(RST_SOC_USB0PHY, SL2610_GBL_PERIFSTICKYRESET, 0, true),
+	SL2610_RESET(RST_SOC_USB0CORE, SL2610_GBL_PERIFSTICKYRESET, 1, true),
+	SL2610_RESET(RST_SOC_USB0MAHB, SL2610_GBL_PERIFSTICKYRESET, 2, true),
+	SL2610_RESET(RST_SOC_USB1PHY, SL2610_GBL_PERIFSTICKYRESET, 3, true),
+	SL2610_RESET(RST_SOC_USB1CORE, SL2610_GBL_PERIFSTICKYRESET, 4, true),
+	SL2610_RESET(RST_SOC_USB1MAHB, SL2610_GBL_PERIFSTICKYRESET, 5, true),
+	SL2610_RESET(RST_SOC_UART0, SL2610_GBL_APBPERIFRESET, 0, false),
+	SL2610_RESET(RST_SOC_UART1, SL2610_GBL_APBPERIFRESET, 1, false),
+	SL2610_RESET(RST_SOC_UART2, SL2610_GBL_APBPERIFRESET, 2, false),
+	SL2610_RESET(RST_SOC_UART3, SL2610_GBL_APBPERIFRESET, 3, false),
+	SL2610_RESET(RST_SOC_I2C0, SL2610_GBL_APBPERIFRESET, 4, false),
+	SL2610_RESET(RST_SOC_I2C1, SL2610_GBL_APBPERIFRESET, 5, false),
+	SL2610_RESET(RST_SOC_SPI0, SL2610_GBL_APBPERIFRESET, 6, false),
+	SL2610_RESET(RST_SOC_SPI1, SL2610_GBL_APBPERIFRESET, 7, false),
+	SL2610_RESET(RST_SOC_SPI2, SL2610_GBL_APBPERIFRESET, 8, false),
+	SL2610_RESET(RST_SOC_SPI3, SL2610_GBL_APBPERIFRESET, 9, false),
+	SL2610_RESET(RST_SOC_APBTIMERS, SL2610_GBL_APBPERIFRESET, 10, false),
+	SL2610_RESET(RST_SOC_APBSYSCNT, SL2610_GBL_APBPERIFRESET, 11, false),
+	SL2610_RESET(RST_SOC_APBWDT, SL2610_GBL_APBPERIFRESET, 12, false),
+	SL2610_RESET(RST_SOC_APBGPIO, SL2610_GBL_APBPERIFRESET, 13, false),
+	SL2610_RESET(RST_SOC_APBDMA, SL2610_GBL_APBPERIFRESET, 14, false),
+	SL2610_RESET(RST_SOC_GPUCORE, SL2610_GBL_TOPSTICKYRESET, 0, true),
+	SL2610_RESET(RST_SOC_NPUCORE, SL2610_GBL_TOPSTICKYRESET, 1, true),
+	SL2610_RESET(RST_SOC_AVIOAIOG, SL2610_GBL_AVIOSTICKYRESET, 0, true),
+	SL2610_RESET(RST_SOC_AVIOVPPG, SL2610_GBL_AVIOSTICKYRESET, 1, true),
+	SL2610_RESET(RST_SOC_AVIOVIPG, SL2610_GBL_AVIOSTICKYRESET, 2, true),
+};
+
+static const struct sl2610_reset_cfg sl2610_system_reset_cfgs[] = {
+	SL2610_RESET(RST_SM_ADCCORE, SL2610_SMGBL_STICKYRST0, 0, true),
+	SL2610_RESET(RST_SM_ADCPRST, SL2610_SMGBL_STICKYRST0, 1, true),
+	SL2610_RESET(RST_SM_CAN0PRST, SL2610_SMGBL_STICKYRST0, 2, true),
+	SL2610_RESET(RST_SM_CAN0SRST, SL2610_SMGBL_STICKYRST0, 3, true),
+	SL2610_RESET(RST_SM_CAN1PRST, SL2610_SMGBL_STICKYRST0, 4, true),
+	SL2610_RESET(RST_SM_CAN1SRST, SL2610_SMGBL_STICKYRST0, 5, true),
+	SL2610_RESET(RST_SM_GPIOPRST, SL2610_SMGBL_STICKYRST0, 6, true),
+	SL2610_RESET(RST_SM_GPIOSRST, SL2610_SMGBL_STICKYRST0, 7, true),
+	SL2610_RESET(RST_SM_I2CM0PRST, SL2610_SMGBL_STICKYRST0, 8, true),
+	SL2610_RESET(RST_SM_I2CM0SRST, SL2610_SMGBL_STICKYRST0, 9, true),
+	SL2610_RESET(RST_SM_I2CM1PRST, SL2610_SMGBL_STICKYRST0, 10, true),
+	SL2610_RESET(RST_SM_I2CM1SRST, SL2610_SMGBL_STICKYRST0, 11, true),
+	SL2610_RESET(RST_SM_I3CPRST, SL2610_SMGBL_STICKYRST0, 12, true),
+	SL2610_RESET(RST_SM_I3CSRST, SL2610_SMGBL_STICKYRST0, 13, true),
+	SL2610_RESET(RST_SM_PDMPRST, SL2610_SMGBL_STICKYRST0, 14, true),
+	SL2610_RESET(RST_SM_PDMSRST, SL2610_SMGBL_STICKYRST0, 15, true),
+	SL2610_RESET(RST_SM_PVTHSRST, SL2610_SMGBL_STICKYRST0, 16, true),
+	SL2610_RESET(RST_SM_PVTPRST, SL2610_SMGBL_STICKYRST0, 17, true),
+	SL2610_RESET(RST_SM_PWMPERIRST, SL2610_SMGBL_STICKYRST0, 18, true),
+	SL2610_RESET(RST_SM_PWMPRST, SL2610_SMGBL_STICKYRST0, 19, true),
+	SL2610_RESET(RST_SM_SPIMPRST, SL2610_SMGBL_STICKYRST0, 20, true),
+	SL2610_RESET(RST_SM_SPIMSRST, SL2610_SMGBL_STICKYRST0, 21, true),
+	SL2610_RESET(RST_SM_SPISPRST, SL2610_SMGBL_STICKYRST0, 22, true),
+	SL2610_RESET(RST_SM_SPISSRST, SL2610_SMGBL_STICKYRST0, 23, true),
+	SL2610_RESET(RST_SM_UART0PRST, SL2610_SMGBL_STICKYRST0, 24, true),
+	SL2610_RESET(RST_SM_UART0SRST, SL2610_SMGBL_STICKYRST0, 25, true),
+	SL2610_RESET(RST_SM_UART1PRST, SL2610_SMGBL_STICKYRST0, 26, true),
+	SL2610_RESET(RST_SM_UART1SRST, SL2610_SMGBL_STICKYRST0, 27, true),
+	SL2610_RESET(RST_SM_UART2PRST, SL2610_SMGBL_STICKYRST0, 28, true),
+	SL2610_RESET(RST_SM_UART2SRST, SL2610_SMGBL_STICKYRST0, 29, true),
+	SL2610_RESET(RST_SM_UART3PRST, SL2610_SMGBL_STICKYRST0, 30, true),
+	SL2610_RESET(RST_SM_UART3SRST, SL2610_SMGBL_STICKYRST0, 31, true),
+};
+
+static const struct sl2610_reset_data sl2610_reset_data = {
+	.cfgs = sl2610_reset_cfgs,
+	.num = ARRAY_SIZE(sl2610_reset_cfgs),
+};
+
+static const struct sl2610_reset_data sl2610_system_reset_data = {
+	.cfgs = sl2610_system_reset_cfgs,
+	.num = ARRAY_SIZE(sl2610_system_reset_cfgs),
+};
+
+static int sl2610_reset_assert(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	struct sl2610_reset_priv *priv = to_sl2610_reset_priv(rcdev);
+	const struct sl2610_reset_cfg *cfg = &priv->cfgs[id];
+
+	if (!cfg->sticky)
+		return -EINVAL;
+
+	return regmap_clear_bits(priv->regmap, cfg->reg, cfg->bit);
+}
+
+static int sl2610_reset_deassert(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	struct sl2610_reset_priv *priv = to_sl2610_reset_priv(rcdev);
+	const struct sl2610_reset_cfg *cfg = &priv->cfgs[id];
+
+	if (!cfg->sticky)
+		return -EINVAL;
+
+	return regmap_set_bits(priv->regmap, cfg->reg, cfg->bit);
+}
+
+static int sl2610_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct sl2610_reset_priv *priv = to_sl2610_reset_priv(rcdev);
+	const struct sl2610_reset_cfg *cfg = &priv->cfgs[id];
+
+	if (cfg->sticky) {
+		regmap_clear_bits(priv->regmap, cfg->reg, cfg->bit);
+		usleep_range(10, 15);
+		return regmap_set_bits(priv->regmap, cfg->reg, cfg->bit);
+	}
+
+	return regmap_set_bits(priv->regmap, cfg->reg, cfg->bit);
+}
+
+static const struct reset_control_ops sl2610_reset_ops = {
+	.reset	= sl2610_reset_reset,
+	.assert = sl2610_reset_assert,
+	.deassert = sl2610_reset_deassert,
+};
+
+static int sl2610_reset_probe(struct platform_device *pdev)
+{
+	struct device_node *parent_np = pdev->dev.parent->of_node;
+	struct sl2610_reset_priv *priv;
+	const struct sl2610_reset_data *data =
+		(void *)platform_get_device_id(pdev)->driver_data;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regmap = syscon_node_to_regmap(parent_np);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	priv->rcdev.owner = THIS_MODULE;
+	priv->rcdev.ops = &sl2610_reset_ops;
+	priv->rcdev.dev = &pdev->dev;
+	priv->rcdev.of_node = parent_np;
+	priv->rcdev.of_reset_n_cells = 1;
+	priv->rcdev.nr_resets = data->num;
+	priv->cfgs = data->cfgs;
+
+	return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
+}
+
+static const struct platform_device_id sl2610_reset_ids[] = {
+	{ "sl2610-soc-reset", (kernel_ulong_t)&sl2610_reset_data },
+	{ "sl2610-mcu-reset", (kernel_ulong_t)&sl2610_system_reset_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sl2610_reset_ids);
+
+static struct platform_driver sl2610_reset_driver = {
+	.probe = sl2610_reset_probe,
+	.id_table = sl2610_reset_ids,
+	.driver = {
+		.name = "sl2610-reset",
+	},
+};
+module_platform_driver(sl2610_reset_driver);
+
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_DESCRIPTION("Synaptics SL2610 reset controller");
+MODULE_LICENSE("GPL");
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 08/13] pinctrl: berlin: add Synaptics SL2610 pin controller support
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (6 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 07/13] reset: add Synaptics SL2610 reset " Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 10:57   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 09/13] clk: berlin: add Synaptics clock controller helpers Jisheng Zhang
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Add the SoC and MCU pin groups and mux functions for SL2610, together
with their pad configuration register descriptions. Bind to the platform
devices created by the system controller and associate pin configurations
with the parent syscon DT node.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 MAINTAINERS                             |   1 +
 drivers/pinctrl/berlin/Kconfig          |  15 +
 drivers/pinctrl/berlin/Makefile         |   1 +
 drivers/pinctrl/berlin/pinctrl-sl2610.c | 759 ++++++++++++++++++++++++
 4 files changed, 776 insertions(+)
 create mode 100644 drivers/pinctrl/berlin/pinctrl-sl2610.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1bd3b2f39865..b5bc76062771 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3812,6 +3812,7 @@ F:	Documentation/devicetree/bindings/soc/synaptics/
 F:	arch/arm/boot/dts/synaptics/
 F:	arch/arm/mach-berlin/
 F:	arch/arm64/boot/dts/synaptics/
+F:	drivers/pinctrl/berlin/pinctrl-sl2610.c
 F:	drivers/reset/reset-sl2610.c
 F:	drivers/soc/synaptics/
 F:	include/dt-bindings/clock/syna,sl2610.h
diff --git a/drivers/pinctrl/berlin/Kconfig b/drivers/pinctrl/berlin/Kconfig
index abb1c912b9ba..79541a4a81aa 100644
--- a/drivers/pinctrl/berlin/Kconfig
+++ b/drivers/pinctrl/berlin/Kconfig
@@ -32,4 +32,19 @@ config PINCTRL_BERLIN_BG4CT
 	depends on OF
 	select PINCTRL_BERLIN
 
+config PINCTRL_SL2610
+	tristate "Synaptics SL2610 pin controller driver"
+	depends on OF && HAS_IOMEM
+	select SOC_SL2610_SYSCON
+	select GENERIC_PINCONF
+	select PINCONF
+	select PINCTRL_BERLIN
+	help
+	  Support the SoC and MCU pin controllers on Synaptics SL2610 SoCs.
+	  These provide pin multiplexing and electrical pad configuration
+	  through their parent system control blocks.
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called pinctrl-sl2610.
+
 endif
diff --git a/drivers/pinctrl/berlin/Makefile b/drivers/pinctrl/berlin/Makefile
index 7b4aa5444a4a..448965293e6a 100644
--- a/drivers/pinctrl/berlin/Makefile
+++ b/drivers/pinctrl/berlin/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_PINCTRL_BERLIN_BG2CD)	+= berlin-bg2cd.o
 obj-$(CONFIG_PINCTRL_BERLIN_BG2Q)	+= berlin-bg2q.o
 obj-$(CONFIG_PINCTRL_BERLIN_BG4CT)	+= berlin-bg4ct.o
 obj-$(CONFIG_PINCTRL_AS370)		+= pinctrl-as370.o
+obj-$(CONFIG_PINCTRL_SL2610)		+= pinctrl-sl2610.o
diff --git a/drivers/pinctrl/berlin/pinctrl-sl2610.c b/drivers/pinctrl/berlin/pinctrl-sl2610.c
new file mode 100644
index 000000000000..0a3dc146c2c0
--- /dev/null
+++ b/drivers/pinctrl/berlin/pinctrl-sl2610.c
@@ -0,0 +1,759 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Synaptics SL2610 pinctrl driver
+ *
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+
+#include "berlin.h"
+
+static const struct berlin_desc_group sl2610_soc_pinctrl_groups[] = {
+	BERLIN_PINCTRLCONF_GROUP("GPIO23", 0x8000, 0x3, 0x00,
+			0x8800, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO23 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "tw2"), /* SCL */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rgmii"), /* MDC */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row0"),
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi3"), /* SS2n */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col3"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* OUT4 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO24", 0x8000, 0x3, 0x03,
+			0x8804, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO24 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "tw2"), /* SDA */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rgmii"), /* MDIO */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row1"),
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi3"), /* SS3n */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col2"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* OUT5 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO25", 0x8000, 0x3, 0x06,
+			0x8808, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO25 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "uart5"), /* RXD */
+			BERLIN_PINCTRL_FUNCTION(0x2, "gpio_trig1"),
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row2"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "sm_uart1"), /* RXD */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col1"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* OUT6 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO26", 0x8000, 0x3, 0x09,
+			0x880c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO26 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "uart5"), /* TXD */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rgmii"), /* PTP_PPS_O */
+			BERLIN_PINCTRL_FUNCTION(0x4, "sm_uart1"), /* TXD */
+			BERLIN_PINCTRL_FUNCTION(0x5, "usb2"), /* VBUS */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* OUT7 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO27", 0x8000, 0x3, 0x0c,
+			0x8810, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO27 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "tw3"), /* SCL */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart4"), /* TXD */
+			BERLIN_PINCTRL_FUNCTION(0x4, "sm_uart1")), /* RTSn */
+	BERLIN_PINCTRLCONF_GROUP("GPIO28", 0x8000, 0x3, 0x0f,
+			0x8814, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO28 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "tw3"), /* SDA */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart4"), /* RXD */
+			BERLIN_PINCTRL_FUNCTION(0x4, "sm_uart1")), /* CTSn */
+	BERLIN_PINCTRLCONF_GROUP("GPIO29", 0x8000, 0x3, 0x12,
+			0x8818, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO29 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart4"), /* DE */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row4"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "sm_uart1"), /* RXD */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col4"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SDI */
+	BERLIN_PINCTRLCONF_GROUP("GPIO30", 0x8000, 0x3, 0x15,
+			0x881c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO30 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart4"), /* REn */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row5"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "sm_uart1"), /* TXD */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col5"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SCLK */
+	BERLIN_PINCTRLCONF_GROUP("GPIO31", 0x8000, 0x3, 0x18,
+			0x8820, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO31 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rgmii"), /* MDC */
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi5"), /* SS3n */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi3"), /* SS2n */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SS2n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO32", 0x8000, 0x3, 0x1b,
+			0x8824, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO32 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rgmii"), /* MDIO */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi3"), /* SS3n */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SS3n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO33", 0x8004, 0x3, 0x00,
+			0x8828, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO33 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* TD0 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii1"), /* TXD0 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "can0"), /* TX */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi3"), /* SS1n */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SS1n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO34", 0x8004, 0x3, 0x03,
+			0x882c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO34 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* TD1 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii1"), /* TXD1 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "can0")), /* RX */
+	BERLIN_PINCTRLCONF_GROUP("GPIO35", 0x8004, 0x3, 0x06,
+			0x8830, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO35 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* TD2 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii2"), /* TXD0 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col7"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart5"), /* RXD */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SS0n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO36", 0x8004, 0x3, 0x09,
+			0x8834, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO36 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* TD3 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii2"), /* TXD1 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart5"), /* TXD */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SDO */
+	BERLIN_PINCTRLCONF_GROUP("GPIO37", 0x8004, 0x3, 0x0c,
+			0x8838, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO37 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* RD0 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii1"), /* RXD0 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "can1"), /* TX */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi5")), /* SDI */
+	BERLIN_PINCTRLCONF_GROUP("GPIO38", 0x8004, 0x3, 0x0f,
+			0x883c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO38 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* RD1 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii1"), /* RXD1 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "can1"), /* RX */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi5")), /* SDO */
+	BERLIN_PINCTRLCONF_GROUP("GPIO39", 0x8004, 0x3, 0x12,
+			0x8840, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO39 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* RD2 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii2"), /* RXD0 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row6"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart6"), /* RXD */
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi5"), /* SS1n*/
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4")), /* SS3n  */
+	BERLIN_PINCTRLCONF_GROUP("GPIO40", 0x8004, 0x3, 0x15,
+			0x8844, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO40 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* RD3 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii2"), /* RXD1 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row7"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart6"), /* TXD */
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi5"), /* SS2n */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4")), /* SS2n  */
+	BERLIN_PINCTRLCONF_GROUP("GPIO41", 0x8004, 0x3, 0x18,
+			0x8848, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO41 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* RXC */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii1"), /* CRSDV */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi5")), /* SCLK */
+	BERLIN_PINCTRLCONF_GROUP("GPIO42", 0x8004, 0x3, 0x1b,
+			0x884c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO42 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* TXC */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii2"), /* CRSDV */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row8"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart7"), /* RXD */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4")), /* SCLK */
+	BERLIN_PINCTRLCONF_GROUP("GPIO43", 0x8008, 0x3, 0x00,
+			0x8850, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO43 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* TXCTL */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii1"), /* TXEN */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4")), /* SS0n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO44", 0x8008, 0x3, 0x03,
+			0x8854, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO44 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* RXCTL */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii2"), /* TXEN */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row9"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart7"), /* TXD */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4")), /* SDI */
+	BERLIN_PINCTRLCONF_GROUP("GPIO45", 0x8008, 0x3, 0x06,
+			0x8858, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO45 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii1"), /* CLKOUT */
+			BERLIN_PINCTRL_FUNCTION(0x2, "rmii1")), /* REFCLK */
+	BERLIN_PINCTRLCONF_GROUP("GPIO46", 0x8008, 0x3, 0x09,
+			0x885c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO46 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "sdio1"), /* CDn */
+			BERLIN_PINCTRL_FUNCTION(0x2, "sdio2"), /* CDn */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col0"),
+			BERLIN_PINCTRL_FUNCTION(0x5, "sm_uart1"), /* RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_row9"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "dsi")), /* TE */
+	BERLIN_PINCTRLCONF_GROUP("GPIO47", 0x8008, 0x3, 0x0c,
+			0x8860, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO47 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "sdio1"), /* WP */
+			BERLIN_PINCTRL_FUNCTION(0x2, "sdio2"), /* WP */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col1"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "rmii2"), /* REFCLK */
+			BERLIN_PINCTRL_FUNCTION(0x5, "sm_uart1"), /* CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_row8")),
+	BERLIN_PINCTRLCONF_GROUP("GPIO48", 0x8008, 0x3, 0x0f,
+			0x8864, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO48 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* TD0 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi5"), /* SS0n */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4"), /* SS2n */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SS3n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO49", 0x8008, 0x3, 0x12,
+			0x8868, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO49 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* TD1 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi5"), /* SDO */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4"), /* SS3n */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SS2n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO50", 0x8008, 0x3, 0x15,
+			0x886c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO50 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* TD2 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi5"), /* SCLK */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SS1n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO51", 0x8008, 0x3, 0x18,
+			0x8870, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO51 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* TD3 */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SS0n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO52", 0x8008, 0x3, 0x1b,
+			0x8874, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO52 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RD0 */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4"), /* SS2n */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SDO */
+	BERLIN_PINCTRLCONF_GROUP("GPIO53", 0x800c, 0x3, 0x00,
+			0x8878, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO53 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RD1 */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spi4"), /* SS3n */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SCLK */
+	BERLIN_PINCTRLCONF_GROUP("GPIO54", 0x800c, 0x3, 0x03,
+			0x87c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO54 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RD2 */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SDI */
+	BERLIN_PINCTRLCONF_GROUP("GPIO55", 0x800c, 0x3, 0x06,
+			0x8880, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO55 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RD3 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "spi5"), /* SDI */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SS1n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO56", 0x800c, 0x3, 0x09,
+			0x8884, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO56 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RXC */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SS0n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO57", 0x800c, 0x3, 0x0c,
+			0x8888, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO57 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* TXC */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SDO */
+	BERLIN_PINCTRLCONF_GROUP("GPIO58", 0x800c, 0x3, 0x0f,
+			0x888c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO58 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* TXCTL */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SCLK */
+	BERLIN_PINCTRLCONF_GROUP("GPIO59", 0x800c, 0x3, 0x12,
+			0x8890, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO59 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RXCTL */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SDI */
+	BERLIN_PINCTRLCONF_GROUP("GPIO0", 0x800c, 0x3, 0x15,
+			0x8894, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO0 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* LRCK */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SS0n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO1", 0x800c, 0x3, 0x18,
+			0x8898, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO1 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* BCLK */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SCLK */
+	BERLIN_PINCTRLCONF_GROUP("GPIO2", 0x800c, 0x3, 0x1b,
+			0x889c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO2*/
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* DO */
+			BERLIN_PINCTRL_FUNCTION(0x4, "spdif"), /* O */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SDO */
+	BERLIN_PINCTRLCONF_GROUP("GPIO3", 0x8010, 0x3, 0x00,
+			0x88a0, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO3 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* MCLK */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SS1n */
+	BERLIN_PINCTRLCONF_GROUP("GPIO4", 0x8010, 0x3, 0x03,
+			0x88a4, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO4 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* DI */
+			BERLIN_PINCTRL_FUNCTION(0x4, "spdif"), /* I */
+			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SDI */
+	BERLIN_PINCTRLCONF_GROUP("GPIO5", 0x8010, 0x3, 0x06,
+			0x88a8, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO5 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* LRCK */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* PIXCLK */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row0"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "spdif"), /* I */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col7")),
+	BERLIN_PINCTRLCONF_GROUP("GPIO6", 0x8010, 0x3, 0x09,
+			0x88ac, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO6 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* BCLK */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* HSYNC */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row1"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "spdif"), /* O */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col6")),
+	BERLIN_PINCTRLCONF_GROUP("GPIO7", 0x8010, 0x3, 0x0c,
+			0x88b0, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO7 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* DO */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row2"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "spdif"), /* O */
+			BERLIN_PINCTRL_FUNCTION(0x5, "sm_pdm"), /* CLKIO */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col5")),
+	BERLIN_PINCTRLCONF_GROUP("GPIO8", 0x8010, 0x3, 0x0f,
+			0x88b4, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO8 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* DI */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* VSYNC */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row3"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "spdif"), /* I */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_col4")),
+	BERLIN_PINCTRLCONF_GROUP("GPIO9", 0x8010, 0x3, 0x12,
+			0x88b8, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO9 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* DATA0 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "pdm")), /* DI1 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO10", 0x8010, 0x3, 0x15,
+			0x88bc, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO10 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* DATA1 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "pdm"), /* DI2 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "dsi")), /* TE */
+	BERLIN_PINCTRLCONF_GROUP("GPIO11", 0x8010, 0x3, 0x18,
+			0x88c0, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO11 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s2"), /* MCLK */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* DATA2 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "sm_pdm"), /* CLKIO */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* CLK */
+	BERLIN_PINCTRLCONF_GROUP("GPIO12", 0x8010, 0x3, 0x1b,
+			0x88c4, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO12 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s3"), /* LRCK */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* DATA3 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sdio2"), /* WP */
+			BERLIN_PINCTRL_FUNCTION(0x4, "sdio1"), /* WP */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* OUT0 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO13", 0x8014, 0x3, 0x00,
+			0x88c8, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO13 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s3"), /* BCLK */
+			BERLIN_PINCTRL_FUNCTION(0x2, "pdm"), /* DI1 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "rgmii"), /* PTP_PPS_O */
+			BERLIN_PINCTRL_FUNCTION(0x4, "usb2"), /* VBUS */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* OUT1 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO14", 0x8014, 0x3, 0x03,
+			0x88cc, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO14 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s3"), /* DO */
+			BERLIN_PINCTRL_FUNCTION(0x4, "pdm"), /* DI3 */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spdif"), /* O */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* OUT2 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO15", 0x8014, 0x3, 0x06,
+			0x88d0, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO15 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "i2s3"), /* DI */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* DATA4 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "sm_pdm"), /* DI0 */
+			BERLIN_PINCTRL_FUNCTION(0x6, "spdif"), /* I */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* OUT3 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO16", 0x8014, 0x3, 0x09,
+			0x88d4, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO16 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SS0n */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sdio2")), /* DAT3 */
+	BERLIN_PINCTRLCONF_GROUP("GPIO17", 0x8014, 0x3, 0x0c,
+			0x88d8, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO17 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SS1n */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* DATA5 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sdio2"), /* DAT2 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "dsi")), /* TE */
+	BERLIN_PINCTRLCONF_GROUP("GPIO18", 0x8014, 0x3, 0x0f,
+			0x88dc, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO18 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SS2n */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* DATA6 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sdio2"), /* DAT1 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "pdm"), /* DI2 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "can1")), /* RX */
+	BERLIN_PINCTRLCONF_GROUP("GPIO19", 0x8014, 0x3, 0x12,
+			0x88e0, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO19 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SS3n */
+			BERLIN_PINCTRL_FUNCTION(0x2, "cam"), /* DATA7 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sdio2"), /* DAT0 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "pdm"), /* DI3 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "can1")), /* TX */
+	BERLIN_PINCTRLCONF_GROUP("GPIO20", 0x8014, 0x3, 0x15,
+			0x88e4, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO20 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SDO */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sdio2")), /* CMD */
+	BERLIN_PINCTRLCONF_GROUP("GPIO21", 0x8014, 0x3, 0x18,
+			0x88e8, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO21 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SCLK */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sdio2"), /* CLK */
+			BERLIN_PINCTRL_FUNCTION(0x5, "clkout")),
+	BERLIN_PINCTRLCONF_GROUP("GPIO22", 0x8014, 0x3, 0x1b,
+			0x88ec, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO22 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi2"), /* SDI */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sdio2"), /* CDn */
+			BERLIN_PINCTRL_FUNCTION(0x4, "sdio1")), /* CDn */
+};
+
+static const struct berlin_desc_group sl2610_sysmgr_pinctrl_groups[] = {
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO31", 0xb00, 0x3, 0x00,
+			0xc00, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO31*/
+			BERLIN_PINCTRL_FUNCTION(0x1, "pwm"), /* SM PWM0*/
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart1"), /* SM UART1 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row7"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "pdm"), /* SM PDM DI0 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "uart0"), /* SM UART0 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x6, "can1")), /* SM CAN1 RX */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO32", 0xb00, 0x3, 0x03,
+			0xc04, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO32 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "pwm"), /* SM PWM1 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart1"), /* SM UART1 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col0"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "pdm"), /* SM PDM CLKIO */
+			BERLIN_PINCTRL_FUNCTION(0x5, "uart0"), /* SM UART0 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x6, "can1")), /* SM CAN1 TX */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO33", 0xb00, 0x3, 0x06,
+			0xc08, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO33 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "pwm"), /* SM PWM2 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "uart2"), /* SM UART2 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart3"), /* SM UART3 RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x5, "key_row5"),
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart3_de")), /* SM UART3 DE */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO34", 0xb00, 0x3, 0x09,
+			0xc0c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO34 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "pwm"), /* SM PWM3 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "uart2"), /* SM UART2 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart3"), /* SM UART3 CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x5, "key_row4"),
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart3_ren")), /* SM UART3 REn */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO35", 0xb00, 0x3, 0x0c,
+			0xc10, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO35 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "pwm"), /* SM PWM4 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart1"), /* SM UART1 RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x3, "uart3"), /* SM UART3 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart2"), /* SM UART2 RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x5, "key_row3"),
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart0")), /* SM UART0 RTSn */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO36", 0xb00, 0x3, 0x0f,
+			0xc14, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO36 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "pwm"), /* SM PWM5 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart1"), /* SM UART1 CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x3, "uart3"), /* SM UART3 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart2"), /* SM UART2 CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x5, "key_row2"),
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart0")), /* SM UART0 CTSn */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO37", 0xb00, 0x3, 0x12,
+			0xc18, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO37 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "pwm"), /* SM PWM6 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "tw0"), /* SM TW0 SCL */
+			BERLIN_PINCTRL_FUNCTION(0x4, "key_row6"),
+			BERLIN_PINCTRL_FUNCTION(0x5, "pdm")), /* SM PDM CLKIO */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO38", 0xb00, 0x3, 0x15,
+			0xc1c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO38 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "pwm"), /* SM PWM7 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "tw0"), /* SM TW0 SDA */
+			BERLIN_PINCTRL_FUNCTION(0x5, "pdm")), /* SM PDM DI0 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO3", 0xb00, 0x3, 0x18,
+			0xc20, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO3 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi1"), /* SM SPI1 SS0n */
+			BERLIN_PINCTRL_FUNCTION(0x2, "tw1"), /* SM TW1 SCL */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm"), /* SM PWM8 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "i3c")), /* SM I3C MS SCL */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO4", 0xb00, 0x3, 0x1b,
+			0xc24, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO4 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi1"), /* SM SPI1 SS1n */
+			BERLIN_PINCTRL_FUNCTION(0x2, "tw1"), /* SM TW1 SDA */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm"), /* SM PWM0 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "i3c")), /* SM I3C MS SDA */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO5", 0xb04, 0x3, 0x00,
+			0xc28, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO5 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi1"), /* SM SPI1 SS2n */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm")), /* SM PWM1 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO6", 0xb04, 0x3, 0x03,
+			0xc2c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO6 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi1"), /* SM SPI1 SS3n */
+			BERLIN_PINCTRL_FUNCTION(0x2, "spi1s"), /* SM SPI1S SSn */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm")), /* SM PWM2 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO9", 0xb04, 0x3, 0x06,
+			0xc30, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO9 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi1"), /* SM SPI1 SDO */
+			BERLIN_PINCTRL_FUNCTION(0x2, "spi1s"), /* SM SPI1S SDO */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm")), /* SM PWM3 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO10", 0xb04, 0x3, 0x09,
+			0xc34, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO10 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi1"), /* SM SPI1 SCLK */
+			BERLIN_PINCTRL_FUNCTION(0x2, "spi1s"), /* SM SPI1S SCLK */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm")), /* SM PWM4 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO11", 0xb04, 0x3, 0x0c,
+			0xc38, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO11 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "spi1"), /* SM SPI1 SDI */
+			BERLIN_PINCTRL_FUNCTION(0x2, "spi1s"), /* SM SPI1S SDI */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm")), /* SM PWM5 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO30", 0xb04, 0x3, 0x0f,
+			0xc44, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO30 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi"), /* SM XSPI DATA7 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col6"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "sm_clkout")),
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO29", 0xb04, 0x3, 0x12,
+			0xc48, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO29 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi"), /* SM XSPI DATA6 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart3"), /* SM UART3 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col5"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart2"), /* SM UART2 CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x5, "uart0"), /* SM UART0 CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_row2"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "uart1")), /* SM UART1 CTSn */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO28", 0xb04, 0x3, 0x15,
+			0xc4c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO28 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi"), /* SM XSPI DATA5 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart3"), /* SM UART3 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col4"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart2"), /* SM UART2 RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x5, "uart0"), /* SM UART0 RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_row3"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "uart1")), /* SM UART1 RTSn */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO27", 0xb04, 0x3, 0x18,
+			0xc50, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO27 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi"), /* SM XSPI DATA4 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart2"), /* SM UART2 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col3"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart3"), /* SM UART3 CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x5, "uart3_ren"), /* SM UART3 REn */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_row4")),
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO26", 0xb04, 0x3, 0x1b,
+			0xc54, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO26 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi"), /* SM XSPI CS1n */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart2"), /* SM UART2 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col2"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "uart3"), /* SM UART3 RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x5, "uart3_de"), /* SM UART3 DE */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_row5"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "sm_clkout")),
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO25", 0xb08, 0x3, 0x00,
+			0xc58, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO25 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi"), /* SM XSPI DQS */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_row6")),
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO24", 0xb08, 0x3, 0x03,
+			0xc5c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO24 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi")), /* SM XSPI CLKn */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO23", 0xb08, 0x3, 0x06,
+			0xc60, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO23 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi")), /* SM XSPI CLK */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO22", 0xb08, 0x3, 0x09,
+			0xc64, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO22 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi")), /* SM XSPI DATA3 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO21", 0xb08, 0x3, 0x0c,
+			0xc68, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO21 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi")), /* SM XSPI DATA2 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO20", 0xb08, 0x3, 0x0f,
+			0xc6c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO20 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi")), /* SM XSPI DATA1 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO19", 0xb08, 0x3, 0x12,
+			0xc70, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO19 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi")), /* SM XSPI DATA0 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO18", 0xb08, 0x3, 0x15,
+			0xc74, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO18 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "xspi")), /* SM XSPI CS0n*/
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO17", 0xb08, 0x3, 0x18,
+			0xc78, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO17 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "uart1"), /* SM UART1 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x2, "can0"), /* SM CAN0 TX */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm"), /* SM PWM8 */
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart0")), /* SM UART0 TXD */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO15", 0xb08, 0x3, 0x1b,
+			0xc7c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO15 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "tw1"), /* SM TW1 SDA */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart0"), /* SM UART0 RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm"), /* SM PWM11 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "can0"), /* SM CAN0 TX */
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart1"), /* SM UART1 RTSn */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* DBG OUT */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO14", 0xb0c, 0x3, 0x00,
+			0xc80, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO14 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "tw1"), /* SM TW1 SCL */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart0"), /* SM UART0 CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm"), /* SM PWM10 */
+			BERLIN_PINCTRL_FUNCTION(0x4, "can0"), /* SM CAN0 RX */
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart1"), /* SM UART1 CTSn */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* DBG OUT */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO16", 0xb0c, 0x3, 0x03,
+			0xc84, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO16 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "uart1"), /* SM UART1 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x2, "can0"), /* SM CAN0 RX */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm")), /* SM PWM7 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO13", 0xb0c, 0x3, 0x06,
+			0xc88, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO13 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "tw0"), /* SM TW0 SDA */
+			BERLIN_PINCTRL_FUNCTION(0x2, "i3c"), /* SM I3C MS SDA */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sm_clkout"),
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* DBG out */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO12", 0xb0c, 0x3, 0x09,
+			0xc8c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO12 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "tw0"), /* SM TW0 SCL */
+			BERLIN_PINCTRL_FUNCTION(0x2, "i3c"), /* SM I3C MS SCL */
+			BERLIN_PINCTRL_FUNCTION(0x3, "pwm"), /* SM PWM6 */
+			BERLIN_PINCTRL_FUNCTION(0x7, "dbg")), /* DBG CLK */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO8", 0xb0c, 0x3, 0x0c,
+			0xc90, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO8 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "uart0"), /* SM UART0 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x2, "can0"), /* SM CAN0 TX */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sm_clkout"),
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart1")), /* SM UART0 TXD */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO7", 0xb0c, 0x3, 0x0f,
+			0xc94, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* SM GPIO7 */
+			BERLIN_PINCTRL_FUNCTION(0x1, "uart0"), /* SM UART0 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x2, "can0"), /* SM CAN0 RX */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_row6"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "gpio_trig"), /* TRIG2 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "pwm"), /* SM PWM9 */
+			BERLIN_PINCTRL_FUNCTION(0x6, "uart1")), /* SM UART0 RXD */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO2", 0xb0c, 0x3, 0x12,
+			0xc98, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "jtag"), /* TDO */
+			BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* SM GPIO2 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "pdm"), /* SM PDM CLKIO */
+			BERLIN_PINCTRL_FUNCTION(0x3, "i2s2"), /* MCLK */
+			BERLIN_PINCTRL_FUNCTION(0x6, "pwm")), /* SM PWM11 */
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO1", 0xb0c, 0x3, 0x15,
+			0xc9c, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "jtag"), /* TDI */
+			BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* SM GPIO1 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart0"), /* SM UART0 RXD */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col1"),
+			BERLIN_PINCTRL_FUNCTION(0x4, "gpio_trig"), /* TRIG0 */
+			BERLIN_PINCTRL_FUNCTION(0x5, "pwm"), /* SM PWM9 */
+			BERLIN_PINCTRL_FUNCTION(0x6, "key_row7")),
+	BERLIN_PINCTRLCONF_GROUP("SM_GPIO0", 0xb0c, 0x3, 0x18,
+			0xca0, 10,
+			BERLIN_PINCTRL_FUNCTION(0x0, "jtag"), /* TMS */
+			BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* SM GPIO0 */
+			BERLIN_PINCTRL_FUNCTION(0x2, "uart0"), /* SM UART0 TXD */
+			BERLIN_PINCTRL_FUNCTION(0x3, "key_col0"),
+			BERLIN_PINCTRL_FUNCTION(0x5, "pdm"), /* SM PDM DI0 */
+			BERLIN_PINCTRL_FUNCTION(0x6, "pwm")), /* SM PWM10 */
+};
+
+static const struct berlin_pinctrl_desc sl2610_soc_pinctrl_data = {
+	.groups = sl2610_soc_pinctrl_groups,
+	.ngroups = ARRAY_SIZE(sl2610_soc_pinctrl_groups),
+};
+
+static const struct berlin_pinctrl_desc sl2610_sysmgr_pinctrl_data = {
+	.groups = sl2610_sysmgr_pinctrl_groups,
+	.ngroups = ARRAY_SIZE(sl2610_sysmgr_pinctrl_groups),
+};
+
+static const struct platform_device_id sl2610_pinctrl_ids[] = {
+	{ "sl2610-soc-pinctrl", (kernel_ulong_t)&sl2610_soc_pinctrl_data },
+	{ "sl2610-mcu-pinctrl", (kernel_ulong_t)&sl2610_sysmgr_pinctrl_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sl2610_pinctrl_ids);
+
+static void sl2610_pinctrl_clear_node(void *data)
+{
+	device_set_node(data, NULL);
+}
+
+static int sl2610_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct berlin_pinctrl_desc *desc =
+		(void *)platform_get_device_id(pdev)->driver_data;
+	struct regmap *regmap;
+	int ret;
+
+	regmap = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(regmap))
+		return dev_err_probe(dev, PTR_ERR(regmap), "Failed to get syscon regmap\n");
+
+	device_set_node(dev, dev_fwnode(dev->parent));
+	ret = devm_add_action_or_reset(dev, sl2610_pinctrl_clear_node, dev);
+	if (ret)
+		return ret;
+
+	return berlin_pinctrl_probe_regmap(pdev, desc, regmap);
+}
+
+static struct platform_driver sl2610_pinctrl_driver = {
+	.probe = sl2610_pinctrl_probe,
+	.id_table = sl2610_pinctrl_ids,
+	.driver = {
+		.name = "sl2610-pinctrl",
+	},
+};
+module_platform_driver(sl2610_pinctrl_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_DESCRIPTION("pinctrl driver for Synaptics SL2610 SoC");
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 09/13] clk: berlin: add Synaptics clock controller helpers
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (7 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 08/13] pinctrl: berlin: add Synaptics SL2610 pin " Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 11:05   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 10/13] clk: berlin: add Synaptics SL2610 clocks and PLLs Jisheng Zhang
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Add the configurable divider and gate clock implementation shared by
Synaptics system controllers. Provide the MCU system manager helper for
registering its fixed clocks, gates and peripheral dividers.

Keep clock resources managed by the MFD clock device and obtain the
register range and provider node from its parent.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 MAINTAINERS                        |   1 +
 drivers/clk/Kconfig                |   1 +
 drivers/clk/berlin/Kconfig         |   7 +
 drivers/clk/berlin/Makefile        |   2 +
 drivers/clk/berlin/sl-clk.c        | 279 +++++++++++++++++++++++++++++
 drivers/clk/berlin/sl-clk.h        |  31 ++++
 drivers/clk/berlin/sl-sysmgr-clk.c | 241 +++++++++++++++++++++++++
 drivers/clk/berlin/sl-sysmgr-clk.h |  44 +++++
 8 files changed, 606 insertions(+)
 create mode 100644 drivers/clk/berlin/Kconfig
 create mode 100644 drivers/clk/berlin/sl-clk.c
 create mode 100644 drivers/clk/berlin/sl-clk.h
 create mode 100644 drivers/clk/berlin/sl-sysmgr-clk.c
 create mode 100644 drivers/clk/berlin/sl-sysmgr-clk.h

diff --git a/MAINTAINERS b/MAINTAINERS
index b5bc76062771..f3067f71d54c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3812,6 +3812,7 @@ F:	Documentation/devicetree/bindings/soc/synaptics/
 F:	arch/arm/boot/dts/synaptics/
 F:	arch/arm/mach-berlin/
 F:	arch/arm64/boot/dts/synaptics/
+F:	drivers/clk/berlin/sl-*
 F:	drivers/pinctrl/berlin/pinctrl-sl2610.c
 F:	drivers/reset/reset-sl2610.c
 F:	drivers/soc/synaptics/
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 37a8e35d4178..906fabfe0d33 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -514,6 +514,7 @@ source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/anlogic/Kconfig"
 source "drivers/clk/aspeed/Kconfig"
 source "drivers/clk/bcm/Kconfig"
+source "drivers/clk/berlin/Kconfig"
 source "drivers/clk/cix/Kconfig"
 source "drivers/clk/davinci/Kconfig"
 source "drivers/clk/eswin/Kconfig"
diff --git a/drivers/clk/berlin/Kconfig b/drivers/clk/berlin/Kconfig
new file mode 100644
index 000000000000..8f71d4c7a478
--- /dev/null
+++ b/drivers/clk/berlin/Kconfig
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config SL_COMMON_CLK
+	bool
+
+config SL_SYSMGR_CLK
+	bool
diff --git a/drivers/clk/berlin/Makefile b/drivers/clk/berlin/Makefile
index 3733733a4806..5dbd0fd264ad 100644
--- a/drivers/clk/berlin/Makefile
+++ b/drivers/clk/berlin/Makefile
@@ -3,3 +3,5 @@ obj-y += berlin2-avpll.o berlin2-pll.o berlin2-div.o
 obj-$(CONFIG_MACH_BERLIN_BG2)	+= bg2.o
 obj-$(CONFIG_MACH_BERLIN_BG2CD)	+= bg2.o
 obj-$(CONFIG_MACH_BERLIN_BG2Q)	+= bg2q.o
+obj-$(CONFIG_SL_COMMON_CLK)	+= sl-clk.o
+obj-$(CONFIG_SL_SYSMGR_CLK)	+= sl-sysmgr-clk.o
diff --git a/drivers/clk/berlin/sl-clk.c b/drivers/clk/berlin/sl-clk.c
new file mode 100644
index 000000000000..e212320a0637
--- /dev/null
+++ b/drivers/clk/berlin/sl-clk.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Synaptics Incorporated
+ * Copyright (c) 2015 Marvell Technology Group Ltd.
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "sl-clk.h"
+
+#define SL_CLK_EN		BIT(0)
+#define SL_CLK_PLL_SEL		GENMASK(3, 1)
+#define SL_CLK_PLL_SWITCH	BIT(4)
+#define SL_CLK_DIV_SWITCH	BIT(5)
+#define SL_CLK_DIV3_SWITCH	BIT(6)
+#define SL_CLK_DIV_SEL		GENMASK(9, 7)
+#define SL_MAX_PARENTS	6
+
+struct sl_clk {
+	struct clk_hw hw;
+	void __iomem *reg;
+	spinlock_t *lock;
+	struct device *dev;
+};
+
+#define to_sl_clk(_hw) container_of(_hw, struct sl_clk, hw)
+
+static const unsigned int sl_clk_values[] = { 1, 2, 3, 4, 6, 8, 12 };
+
+static unsigned int sl_clk_value(u32 val)
+{
+	static const u8 div_table[] = { 0, 2, 4, 6, 8, 12, 0, 0 };
+
+	if (val & SL_CLK_DIV3_SWITCH)
+		return 3;
+	if (!(val & SL_CLK_DIV_SWITCH))
+		return 1;
+
+	return div_table[FIELD_GET(SL_CLK_DIV_SEL, val)];
+}
+
+static unsigned long sl_clk_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct sl_clk *clk = to_sl_clk(hw);
+	unsigned int divisor = sl_clk_value(readl_relaxed(clk->reg));
+
+	if (WARN_ON_ONCE(!divisor))
+		return 0;
+
+	return parent_rate / divisor;
+}
+
+static unsigned int sl_clk_best(unsigned long parent_rate,
+				unsigned long rate)
+{
+	unsigned long best_diff = ULONG_MAX;
+	unsigned int best = 1, i;
+
+	for (i = 0; i < ARRAY_SIZE(sl_clk_values); i++) {
+		unsigned long candidate = parent_rate / sl_clk_values[i];
+		unsigned long diff = candidate > rate ? candidate - rate :
+							     rate - candidate;
+
+		if (diff < best_diff) {
+			best_diff = diff;
+			best = sl_clk_values[i];
+		}
+	}
+
+	return best;
+}
+
+static int sl_clk_determine_rate(struct clk_hw *hw,
+				 struct clk_rate_request *req)
+{
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+
+	if (!parent)
+		return -EINVAL;
+
+	req->best_parent_hw = parent;
+	req->best_parent_rate = clk_hw_get_rate(parent);
+	req->rate = req->best_parent_rate /
+		    sl_clk_best(req->best_parent_rate, req->rate);
+
+	return 0;
+}
+
+static int sl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	struct sl_clk *clk = to_sl_clk(hw);
+	unsigned int divisor, select;
+	unsigned long flags;
+	u32 val;
+
+	divisor = sl_clk_best(parent_rate, rate);
+	if (parent_rate / divisor != rate)
+		return -EINVAL;
+
+	spin_lock_irqsave(clk->lock, flags);
+	val = readl_relaxed(clk->reg);
+	val &= ~(SL_CLK_DIV3_SWITCH | SL_CLK_DIV_SWITCH |
+		 SL_CLK_DIV_SEL);
+	if (divisor == 3) {
+		val |= SL_CLK_DIV3_SWITCH;
+	} else if (divisor != 1) {
+		switch (divisor) {
+		case 2:
+			select = 1;
+			break;
+		case 4:
+			select = 2;
+			break;
+		case 6:
+			select = 3;
+			break;
+		case 8:
+			select = 4;
+			break;
+		case 12:
+			select = 5;
+			break;
+		default:
+			spin_unlock_irqrestore(clk->lock, flags);
+			return -EINVAL;
+		}
+		val |= SL_CLK_DIV_SWITCH |
+			FIELD_PREP(SL_CLK_DIV_SEL, select);
+	}
+	writel_relaxed(val, clk->reg);
+	spin_unlock_irqrestore(clk->lock, flags);
+
+	return 0;
+}
+
+static u8 sl_clk_get_parent(struct clk_hw *hw)
+{
+	struct sl_clk *clk = to_sl_clk(hw);
+	u32 val = readl_relaxed(clk->reg);
+	u8 selector;
+	unsigned int index;
+
+	if (!(val & SL_CLK_PLL_SWITCH))
+		return 0;
+
+	selector = FIELD_GET(SL_CLK_PLL_SEL, val);
+	index = selector + 1;
+	if (index < clk_hw_get_num_parents(hw))
+		return index;
+
+	dev_warn(clk->dev, "%s: unsupported parent selector %u\n",
+		 clk_hw_get_name(hw), selector);
+	return 0;
+}
+
+static int sl_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sl_clk *clk = to_sl_clk(hw);
+	unsigned long flags;
+	u32 val;
+
+	if (index >= clk_hw_get_num_parents(hw) || index >= SL_MAX_PARENTS)
+		return -EINVAL;
+
+	spin_lock_irqsave(clk->lock, flags);
+	val = readl_relaxed(clk->reg);
+	if (!index) {
+		val &= ~SL_CLK_PLL_SWITCH;
+	} else {
+		val &= ~SL_CLK_PLL_SEL;
+		val |= SL_CLK_PLL_SWITCH |
+			FIELD_PREP(SL_CLK_PLL_SEL, index - 1);
+	}
+	writel_relaxed(val, clk->reg);
+	spin_unlock_irqrestore(clk->lock, flags);
+
+	return 0;
+}
+
+static int sl_clk_enable(struct clk_hw *hw)
+{
+	struct sl_clk *clk = to_sl_clk(hw);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(clk->lock, flags);
+	val = readl_relaxed(clk->reg);
+	writel_relaxed(val | SL_CLK_EN, clk->reg);
+	spin_unlock_irqrestore(clk->lock, flags);
+
+	return 0;
+}
+
+static void sl_clk_disable(struct clk_hw *hw)
+{
+	struct sl_clk *clk = to_sl_clk(hw);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(clk->lock, flags);
+	val = readl_relaxed(clk->reg);
+	writel_relaxed(val & ~SL_CLK_EN, clk->reg);
+	spin_unlock_irqrestore(clk->lock, flags);
+}
+
+static int sl_clk_is_enabled(struct clk_hw *hw)
+{
+	struct sl_clk *clk = to_sl_clk(hw);
+
+	return !!(readl_relaxed(clk->reg) & SL_CLK_EN);
+}
+
+static const struct clk_ops sl_clk_ops = {
+	.get_parent = sl_clk_get_parent,
+	.set_parent = sl_clk_set_parent,
+	.recalc_rate = sl_clk_recalc_rate,
+	.determine_rate = sl_clk_determine_rate,
+	.set_rate = sl_clk_set_rate,
+	.enable = sl_clk_enable,
+	.disable = sl_clk_disable,
+	.is_enabled = sl_clk_is_enabled,
+};
+
+struct clk_hw *sl_clk_register(struct device *dev, void __iomem *reg,
+			       const char *name, const char * const *parent_names,
+			       unsigned int num_parents, unsigned long flags,
+			       spinlock_t *lock)
+{
+	struct clk_init_data init = {};
+	struct sl_clk *clk;
+	unsigned int i;
+	int ret;
+
+	if (!dev || !reg || !name || !parent_names || !num_parents ||
+	    num_parents > SL_MAX_PARENTS || !lock)
+		return ERR_PTR(-EINVAL);
+
+	for (i = 0; i < num_parents; i++)
+		if (!parent_names[i])
+			return ERR_PTR(-EINVAL);
+
+	clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return ERR_PTR(-ENOMEM);
+
+	clk->dev = dev;
+	clk->reg = reg;
+	clk->lock = lock;
+
+	init.name = name;
+	init.ops = &sl_clk_ops;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+	init.flags = flags;
+	clk->hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &clk->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &clk->hw;
+}
+EXPORT_SYMBOL_GPL(sl_clk_register);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Synaptics SL261x clock divider support");
diff --git a/drivers/clk/berlin/sl-clk.h b/drivers/clk/berlin/sl-clk.h
new file mode 100644
index 000000000000..7489b26a5e8d
--- /dev/null
+++ b/drivers/clk/berlin/sl-clk.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SL_CLK_H
+#define __SL_CLK_H
+
+#include <linux/compiler_types.h>
+#include <linux/spinlock_types.h>
+
+struct clk_hw;
+struct device;
+
+struct sl_clk_desc {
+	const char	*name;
+	u32		id;
+	u32		offset;
+	unsigned long	flags;
+};
+
+struct sl_gateclk_desc {
+	const char	*name;
+	const char	*parent_name;
+	u32		id;
+	u8		bit_idx;
+	unsigned long	flags;
+};
+
+struct clk_hw *sl_clk_register(struct device *dev, void __iomem *reg,
+			       const char *name, const char * const *parent_names,
+			       unsigned int num_parents, unsigned long flags,
+			       spinlock_t *lock);
+
+#endif /* __SL_CLK_H */
diff --git a/drivers/clk/berlin/sl-sysmgr-clk.c b/drivers/clk/berlin/sl-sysmgr-clk.c
new file mode 100644
index 000000000000..f3cf921fc3c1
--- /dev/null
+++ b/drivers/clk/berlin/sl-sysmgr-clk.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+
+#include "sl-sysmgr-clk.h"
+
+#define CLK_EN		BIT(0)
+#define DIV_CHNG_EN	BIT(1)
+
+struct sl_sysmgr_gateclk {
+	struct clk_hw hw;
+	void __iomem *base;
+	u8 bit_idx;
+};
+
+struct sl_sysmgr_clk {
+	struct clk_hw hw;
+	void __iomem *base;
+	u8 div_bits;
+};
+
+struct sl_sysmgr_clk_priv {
+	struct sl_sysmgr_gateclk *gclks;
+	struct sl_sysmgr_clk *clks;
+};
+
+static DEFINE_SPINLOCK(sl_sysmgr_gateclk_lock);
+
+#define to_sl_sysmgr_gateclk(hw)	container_of(hw, struct sl_sysmgr_gateclk, hw)
+#define to_sl_sysmgr_clk(hw)		container_of(hw, struct sl_sysmgr_clk, hw)
+
+static int sl_sysmgr_gateclk_enable(struct clk_hw *hw)
+{
+	u32 val;
+	struct sl_sysmgr_gateclk *clk = to_sl_sysmgr_gateclk(hw);
+
+	guard(spinlock)(&sl_sysmgr_gateclk_lock);
+
+	val = readl_relaxed(clk->base);
+	if (!(val & BIT(clk->bit_idx))) {
+		val |= BIT(clk->bit_idx);
+		writel_relaxed(val, clk->base);
+	}
+
+	return 0;
+}
+
+static int sl_sysmgr_gateclk_is_enabled(struct clk_hw *hw)
+{
+	u32 val;
+	struct sl_sysmgr_gateclk *clk = to_sl_sysmgr_gateclk(hw);
+
+	guard(spinlock)(&sl_sysmgr_gateclk_lock);
+
+	val = readl_relaxed(clk->base);
+	val &= BIT(clk->bit_idx);
+
+	return val ? 1 : 0;
+}
+
+static const struct clk_ops sl_sysmgr_gateclk_ops = {
+	.enable		= sl_sysmgr_gateclk_enable,
+	.is_enabled	= sl_sysmgr_gateclk_is_enabled,
+};
+
+static int
+sl_sysmgr_gateclk_register(struct device *dev, struct sl_sysmgr_gateclk *gclk,
+			   const char *name, const char *parent_names,
+			   u8 bit_idx, void __iomem *base)
+{
+	struct clk_init_data init;
+
+	init.name = name;
+	init.ops = &sl_sysmgr_gateclk_ops;
+	init.parent_names = &parent_names;
+	init.num_parents = 1;
+	init.flags = 0;
+
+	gclk->bit_idx = bit_idx;
+	gclk->base = base;
+	gclk->hw.init = &init;
+
+	return devm_clk_hw_register(dev, &gclk->hw);
+}
+
+static unsigned long
+sl_sysmgr_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	u32 val, div;
+	struct sl_sysmgr_clk *clk = to_sl_sysmgr_clk(hw);
+
+	val = readl_relaxed(clk->base);
+	div = (val >> 2) & ((1 << clk->div_bits) - 1);
+	++div;
+
+	return parent_rate / div;
+}
+
+static int sl_sysmgr_clk_enable(struct clk_hw *hw)
+{
+	u32 val;
+	struct sl_sysmgr_clk *clk = to_sl_sysmgr_clk(hw);
+
+	val = readl_relaxed(clk->base);
+	if (!(val & CLK_EN)) {
+		val |= CLK_EN;
+		writel_relaxed(val, clk->base);
+	}
+
+	return 0;
+}
+
+static int sl_sysmgr_clk_is_enabled(struct clk_hw *hw)
+{
+	u32 val;
+	struct sl_sysmgr_clk *clk = to_sl_sysmgr_clk(hw);
+
+	val = readl_relaxed(clk->base);
+	val &= CLK_EN;
+
+	return val ? 1 : 0;
+}
+
+static const struct clk_ops sl_sysmgr_clk_ops = {
+	.recalc_rate	= sl_sysmgr_clk_recalc_rate,
+	.enable		= sl_sysmgr_clk_enable,
+	.is_enabled	= sl_sysmgr_clk_is_enabled,
+};
+
+static int
+sl_sysmgr_clk_register(struct device *dev, struct sl_sysmgr_clk *sclk,
+		       const char *name, const char *parent_names,
+		       u8 div_bits, void __iomem *base)
+{
+	struct clk_init_data init;
+
+	init.name = name;
+	init.ops = &sl_sysmgr_clk_ops;
+	init.parent_names = &parent_names;
+	init.num_parents = 1;
+	init.flags = 0;
+
+	sclk->div_bits = div_bits;
+	sclk->base = base;
+	sclk->hw.init = &init;
+
+	return devm_clk_hw_register(dev, &sclk->hw);
+}
+
+int sl_sysmgr_clk_setup(struct platform_device *pdev,
+			const struct sl_sysmgr_fixedclk_desc *fdescs,
+			int fclk_n,
+			const struct sl_sysmgr_gateclk_desc *gdescs,
+			int gclk_n,
+			u32 gclk_offset,
+			const struct sl_sysmgr_clk_desc *descs,
+			int clk_n)
+{
+	struct device_node *parent_np = pdev->dev.parent->of_node;
+	int i, ret, num = fclk_n + gclk_n + clk_n;
+	struct clk_hw_onecell_data *clk_data;
+	struct sl_sysmgr_clk_priv *priv;
+	struct clk_hw *clk_hw;
+	void __iomem *base;
+	u32 id;
+
+	clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, num), GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+	clk_data->num = num;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->gclks = devm_kcalloc(&pdev->dev, gclk_n, sizeof(*priv->gclks), GFP_KERNEL);
+	if (!priv->gclks)
+		return -ENOMEM;
+
+	priv->clks = devm_kcalloc(&pdev->dev, clk_n, sizeof(*priv->clks), GFP_KERNEL);
+	if (!priv->clks)
+		return -ENOMEM;
+
+	base = devm_of_iomap(&pdev->dev, parent_np, 0, NULL);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	for (i = 0; i < fclk_n; i++) {
+		clk_hw = devm_clk_hw_register_fixed_rate(&pdev->dev, fdescs[i].name,
+							 NULL, 0,
+							 fdescs[i].rate);
+		if (IS_ERR(clk_hw))
+			return PTR_ERR(clk_hw);
+
+		id = fdescs[i].id;
+		clk_data->hws[id] = clk_hw;
+	}
+
+	for (i = 0; i < gclk_n; i++) {
+		ret = sl_sysmgr_gateclk_register(&pdev->dev, &priv->gclks[i],
+						 gdescs[i].name, gdescs[i].parent_name,
+						 gdescs[i].bit_idx, base + gclk_offset);
+		if (ret)
+			return ret;
+
+		id = gdescs[i].id;
+		clk_data->hws[id] = &priv->gclks[i].hw;
+	}
+
+	for (i = 0; i < clk_n; i++) {
+		ret = sl_sysmgr_clk_register(&pdev->dev, &priv->clks[i],
+					     descs[i].name, descs[i].parent_name,
+					     descs[i].div_bits, base + descs[i].offset);
+		if (ret)
+			return ret;
+
+		id = descs[i].id;
+		clk_data->hws[id] = &priv->clks[i].hw;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, clk_data);
+}
+EXPORT_SYMBOL_GPL(sl_sysmgr_clk_setup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_DESCRIPTION("SysMgr domain clk driver for Synaptics SL SoCs");
diff --git a/drivers/clk/berlin/sl-sysmgr-clk.h b/drivers/clk/berlin/sl-sysmgr-clk.h
new file mode 100644
index 000000000000..5ccf388bcccb
--- /dev/null
+++ b/drivers/clk/berlin/sl-sysmgr-clk.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2026 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ *
+ */
+
+#ifndef __SL_SYSMGR_CLK_H
+#define __SL_SYSMGR_CLK_H
+
+struct sl_sysmgr_clk_desc {
+	const char	*name;
+	const char	*parent_name;
+	u32		id;
+	u32		offset;
+	u8		div_bits;
+	unsigned long	flags;
+};
+
+struct sl_sysmgr_gateclk_desc {
+	const char	*name;
+	const char	*parent_name;
+	u32		id;
+	u8		bit_idx;
+	unsigned long	flags;
+};
+
+struct sl_sysmgr_fixedclk_desc {
+	const char	*name;
+	u32		id;
+	unsigned long	rate;
+};
+
+int sl_sysmgr_clk_setup(struct platform_device *pdev,
+			const struct sl_sysmgr_fixedclk_desc *fdescs,
+			int fclk_n,
+			const struct sl_sysmgr_gateclk_desc *gdescs,
+			int gclk_n,
+			u32 gclk_offset,
+			const struct sl_sysmgr_clk_desc *descs,
+			int clk_n);
+
+#endif
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 10/13] clk: berlin: add Synaptics SL2610 clocks and PLLs
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (8 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 09/13] clk: berlin: add Synaptics clock controller helpers Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 11:04   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 11/13] dt-bindings: arm: berlin: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Support the SL2610 SoC, CPU, AVIO and MCU clocks. Register the PLL
outputs and the divider, gate and fixed-factor clocks used by the CPU
and peripherals.

Match MFD platform devices and register clock providers on their parent
system controller nodes.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 MAINTAINERS                     |   1 +
 drivers/clk/berlin/Kconfig      |  27 +++
 drivers/clk/berlin/Makefile     |   2 +
 drivers/clk/berlin/clk-sl2610.c | 360 ++++++++++++++++++++++++++++++++
 drivers/clk/berlin/sl2610-pll.c | 145 +++++++++++++
 drivers/clk/berlin/sl2610-pll.h |  14 ++
 6 files changed, 549 insertions(+)
 create mode 100644 drivers/clk/berlin/clk-sl2610.c
 create mode 100644 drivers/clk/berlin/sl2610-pll.c
 create mode 100644 drivers/clk/berlin/sl2610-pll.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f3067f71d54c..430758242906 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3812,6 +3812,7 @@ F:	Documentation/devicetree/bindings/soc/synaptics/
 F:	arch/arm/boot/dts/synaptics/
 F:	arch/arm/mach-berlin/
 F:	arch/arm64/boot/dts/synaptics/
+F:	drivers/clk/berlin/*sl2610*
 F:	drivers/clk/berlin/sl-*
 F:	drivers/pinctrl/berlin/pinctrl-sl2610.c
 F:	drivers/reset/reset-sl2610.c
diff --git a/drivers/clk/berlin/Kconfig b/drivers/clk/berlin/Kconfig
index 8f71d4c7a478..be7e47e0ff52 100644
--- a/drivers/clk/berlin/Kconfig
+++ b/drivers/clk/berlin/Kconfig
@@ -5,3 +5,30 @@ config SL_COMMON_CLK
 
 config SL_SYSMGR_CLK
 	bool
+
+config SL2610_PLL
+	tristate "Synaptics SL2610 PLL Driver"
+	depends on ARCH_BERLIN || COMPILE_TEST
+	default n
+	help
+	  Support the integer and fractional PLL outputs used by the SoC,
+	  CPU and audio clock controllers on Synaptics SL2610 SoCs.
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called sl2610-pll.
+
+config SL2610_CLK
+	tristate "Synaptics SL2610 Clock Driver"
+	depends on ARCH_BERLIN || COMPILE_TEST
+	depends on OF && HAS_IOMEM
+	select SL2610_PLL
+	select SL_COMMON_CLK
+	select SL_SYSMGR_CLK
+	select SOC_SL2610_SYSCON
+	help
+	  This driver provides support for clock controller on Synaptics SL2610
+	  SoC. The clock controller generates and supplies clocks to various
+	  peripherals within the SoC.
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called clk-sl2610.
diff --git a/drivers/clk/berlin/Makefile b/drivers/clk/berlin/Makefile
index 5dbd0fd264ad..ec87dbed7dd4 100644
--- a/drivers/clk/berlin/Makefile
+++ b/drivers/clk/berlin/Makefile
@@ -5,3 +5,5 @@ obj-$(CONFIG_MACH_BERLIN_BG2CD)	+= bg2.o
 obj-$(CONFIG_MACH_BERLIN_BG2Q)	+= bg2q.o
 obj-$(CONFIG_SL_COMMON_CLK)	+= sl-clk.o
 obj-$(CONFIG_SL_SYSMGR_CLK)	+= sl-sysmgr-clk.o
+obj-$(CONFIG_SL2610_PLL)	+= sl2610-pll.o
+obj-$(CONFIG_SL2610_CLK)	+= clk-sl2610.o
diff --git a/drivers/clk/berlin/clk-sl2610.c b/drivers/clk/berlin/clk-sl2610.c
new file mode 100644
index 000000000000..b51d3523028d
--- /dev/null
+++ b/drivers/clk/berlin/clk-sl2610.c
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+
+#include <dt-bindings/clock/syna,sl2610.h>
+
+#include "sl2610-pll.h"
+#include "sl-clk.h"
+#include "sl-sysmgr-clk.h"
+
+#define REG_CLKENABLE		0x0420
+
+#define CLK_GATE_CTRL0		0x0600
+
+#define SYSPLL0_OFFSET		0x0200
+#define SYSPLL1_OFFSET		0x0220
+#define CPUPLL_OFFSET		0x2000
+#define APLL0_OFFSET		0x0008
+#define APLL1_OFFSET		0x0030
+
+static DEFINE_SPINLOCK(gate_lock);
+static DEFINE_SPINLOCK(lock);
+
+enum {
+	SYSPLL0_OUT, SYSPLL0_OUTF,
+	SYSPLL1_OUT, SYSPLL1_OUTF,
+	CPUPLL_OUT, CPUPLL_OUTF,
+	APLL0_OUT, APLL0_OUTF,
+	APLL1_OUT, APLL1_OUTF,
+};
+
+static const char * const clk_names[] = {
+	[SYSPLL0_OUT]		= "syspll0_out",
+	[SYSPLL0_OUTF]		= "syspll0_outf",
+	[SYSPLL1_OUT]		= "syspll1_out",
+	[SYSPLL1_OUTF]		= "syspll1_outf",
+	[CPUPLL_OUT]		= "cpupll_out",
+	[CPUPLL_OUTF]		= "cpupll_outf",
+	[APLL0_OUT]		= "apll0_out",
+	[APLL0_OUTF]		= "apll0_outf",
+	[APLL1_OUT]		= "apll1_out",
+	[APLL1_OUTF]		= "apll1_outf",
+};
+
+static const struct sl_gateclk_desc sl2610_gates[] = {
+	{ "usb0coreclk",	"perifsysclk",	CLK_USB0CORE,		0 },
+	{ "sdiosysclk",		"perifsysclk",	CLK_SDIOSYS,		1 },
+	{ "emmcsysclk",		"perifsysclk",	CLK_EMMCSYS,		2 },
+	{ "gpuaxiclk",		"hpcclk",	CLK_GPUAXI,		3 },
+	{ "gethrgmiisysclk",	"perifsysclk",	CLK_GETHRGMIISYS,	4 },
+	{ "sdio1sysclk",	"perifsysclk",	CLK_SDIO1SYS,		5 },
+	{ "usb1coreclk",	"perifsysclk",	CLK_USB1CORE,		6 },
+	{ "gethrgmii1sysclk",	"perifsysclk",	CLK_GETHRGMII1SYS,	7 },
+	{ "usb0phyrefclk",	"perifsysclk",	CLK_USB0PHYREF,		8 },
+	{ "usb1phyrefclk",	"perifsysclk",	CLK_USB1PHYREF,		9 },
+	{ "apbuart0clk",	"apbcoreclk",	CLK_APBUART0,		10 },
+	{ "apbuart1clk",	"apbcoreclk",	CLK_APBUART1,		11 },
+	{ "apbuart2clk",	"apbcoreclk",	CLK_APBUART2,		12 },
+	{ "apbuart3lck",	"apbcoreclk",	CLK_APBUART3,		13 },
+	{ "apbi2c0clk",		"apbcoreclk",	CLK_APBI2C0,		14 },
+	{ "apbi2c1lck",		"apbcoreclk",	CLK_APBI2C1,		15 },
+	{ "apbspi0clk",		"apbcoreclk",	CLK_APBSPI0,		16 },
+	{ "apbspi1clk",		"apbcoreclk",	CLK_APBSPI1,		17 },
+	{ "apbspi2clk",		"apbcoreclk",	CLK_APBSPI2,		18 },
+	{ "apbspi3clk",		"apbcoreclk",	CLK_APBSPI3,		19 },
+	{ "apbgpioclk",		"apbcoreclk",	CLK_APBGPIO,		20 },
+	{ "apbtimersclk",	"apbcoreclk",	CLK_APBTIMERS,		21 },
+	{ "apbsyscntclk",	"apbcoreclk",	CLK_APBSYSCNT,		22 },
+	{ "apbwdtclk",		"apbcoreclk",	CLK_APBWDT,		23 },
+	{ "apbdmaclk",		"apbcoreclk",	CLK_APBDMA,		24 },
+};
+
+static const struct sl_clk_desc sl2610_descs[] = {
+	{ "cpufastrefclk",	CLK_CPUFASTREF,		0x440, CLK_IS_CRITICAL },
+	{ "memfastrefclk",	CLK_MEMFASTREF,		0x444, CLK_IS_CRITICAL },
+	{ "cfgclk",		CLK_CFG,		0x448, CLK_IS_CRITICAL },
+	{ "sysclk",		CLK_SYS,		0x44c, CLK_IS_CRITICAL },
+	{ "perifsysclk",	CLK_PERIFSYS,		0x450, CLK_IS_CRITICAL },
+	{ "apbcoreclk",		CLK_APBCORE,		0x454, CLK_IS_CRITICAL },
+	{ "apbserclk",		CLK_APBSER,		0x458, CLK_IS_CRITICAL },
+	{ "atbclk",		CLK_ATB,		0x45c },
+	{ "hpcclk",		CLK_HPC,		0x460, CLK_IS_CRITICAL },
+	{ "emmcclk",		CLK_EMMC,		0x464 },
+	{ "sd0clk",		CLK_SD0,		0x468 },
+	{ "sd1clk",		CLK_SD1,		0x46c },
+	{ "gethrgmiiclk",	CLK_GETHRGMII,		0x470 },
+	{ "gethrgmii1clk",	CLK_GETHRGMII1,		0x474 },
+	{ "ge0_ptp_refclk",	CLK_GE0_PTP_REF,	0x478 },
+	{ "ge1_ptp_refclk",	CLK_GE1_PTP_REF,	0x47c },
+	{ "usb2testclk",	CLK_USB2TEST,		0x480 },
+	{ "usb2test480mg0clk",	CLK_USB2TEST480MG0,	0x484 },
+	{ "usb2test480mg1clk",	CLK_USB2TEST480MG1,	0x488 },
+	{ "usb2test480mg2clk",	CLK_USB2TEST480MG2,	0x48c },
+	{ "usb2test100mg0clk",	CLK_USB2TEST100MG0,	0x490 },
+	{ "usb2test100mg1clk",	CLK_USB2TEST100MG1,	0x494 },
+	{ "usb2test100mg2clk",	CLK_USB2TEST100MG2,	0x498 },
+	{ "usb2test100mg3clk",	CLK_USB2TEST100MG3,	0x49c },
+	{ "periftest125mg0clk",	CLK_PERIFTEST125MG0,	0x4a0 },
+	{ "periftest200mg0clk",	CLK_PERIFTEST200MG0,	0x4a4 },
+	{ "periftest200mg1clk",	CLK_PERIFTEST200MG1,	0x4a8 },
+	{ "gpuclk",		CLK_GPU,		0x4ac },
+	{ "npuclk",		CLK_NPU,		0x4b0 },
+	{ "aviosysclk",		CLK_AVIOSYS,		0x4b4, CLK_IS_CRITICAL },
+	{ "aiosysclk",		CLK_AIOSYS,		0x4b8, CLK_IS_CRITICAL },
+	{ "avio_lcdc2scanclk",	CLK_AVIO_LCDC2SCAN,	0x4bc },
+	{ "avio_ipiclk",	CLK_AVIO_IPI,		0x4c0 },
+	{ "avio_pclk",		CLK_AVIO_P,		0x4c4 },
+	{ "avio_dphyrxtxescclk", CLK_AVIO_DPHYRXTXESC,	0x4c8 },
+	{ "aviofpllclk",	CLK_AVIOFPLL,		0x4cc },
+	{ "avio_rx_scanbyteclk", CLK_AVIO_RX_SCANBYTE,	0x4d0 },
+	{ "avio_rx_scantestclk", CLK_AVIO_RX_SCANTEST,	0x4d4 },
+};
+
+static const char * const default_parent_names[] = {
+	"syspll0_out",
+	"apll0_out",
+	"syspll0_outf",
+	"apll0_outf",
+	"syspll1_out",
+	"syspll1_outf",
+};
+
+static const char * const ge_ptp_refclk_parent_names[] = {
+	"osc",
+	"apll0_outf",
+	"syspll1_out",
+	"syspll0_out",
+	"clk_mcu_axi",
+};
+
+static int sl2610_soc_clk_setup(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *parent_np = dev->parent->of_node;
+	struct clk_hw_onecell_data *clk_data;
+	const char * const *parent_names;
+	int num_parents;
+	void __iomem *base;
+	struct clk_hw **hws;
+	int n, ret;
+	u32 id;
+
+	base = devm_of_iomap(dev, parent_np, 0, NULL);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, SL2610_CLK_MAX), GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+	clk_data->num = SL2610_CLK_MAX;
+	hws = clk_data->hws;
+
+	/* sysplls */
+	ret = sl2610_pll_register(dev, base + SYSPLL0_OFFSET,
+				  clk_names[SYSPLL0_OUT], clk_names[SYSPLL0_OUTF]);
+	if (ret)
+		return ret;
+	ret = sl2610_pll_register(dev, base + SYSPLL1_OFFSET,
+				  clk_names[SYSPLL1_OUT], clk_names[SYSPLL1_OUTF]);
+	if (ret)
+		return ret;
+
+	/* normal clocks */
+	for (n = 0; n < ARRAY_SIZE(sl2610_descs); n++) {
+		const struct sl_clk_desc *cd = &sl2610_descs[n];
+
+		id = cd->id;
+		if (id == CLK_GE0_PTP_REF || id == CLK_GE1_PTP_REF) {
+			parent_names = ge_ptp_refclk_parent_names;
+			num_parents = ARRAY_SIZE(ge_ptp_refclk_parent_names);
+		} else {
+			parent_names = default_parent_names;
+			num_parents = ARRAY_SIZE(default_parent_names);
+		}
+		hws[id] = sl_clk_register(dev, base + cd->offset, cd->name,
+					  parent_names, num_parents, cd->flags, &lock);
+		if (IS_ERR(hws[id]))
+			return PTR_ERR(hws[id]);
+	}
+
+	/* gate clocks */
+	for (n = 0; n < ARRAY_SIZE(sl2610_gates); n++) {
+		const struct sl_gateclk_desc *gd = &sl2610_gates[n];
+
+		id = gd->id;
+		hws[id] = devm_clk_hw_register_gate(dev, gd->name, gd->parent_name,
+						    gd->flags, base + REG_CLKENABLE,
+						    gd->bit_idx, 0, &gate_lock);
+		if (IS_ERR(hws[id]))
+			return PTR_ERR(hws[id]);
+	}
+
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+}
+
+static int sl2610_cpu_clk_setup(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *parent_np = dev->parent->of_node;
+	struct clk_hw_onecell_data *clk_data;
+	struct clk_hw **hws;
+	void __iomem *base;
+	int ret;
+
+	base = devm_of_iomap(dev, parent_np, 0, NULL);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, SL2610_CPU_CLK_MAX), GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+	clk_data->num = SL2610_CPU_CLK_MAX;
+	hws = clk_data->hws;
+
+	/* cpupll */
+	ret = sl2610_pll_register(dev, base + CPUPLL_OFFSET,
+				  clk_names[CPUPLL_OUT], clk_names[CPUPLL_OUTF]);
+	if (ret)
+		return ret;
+
+	/* TODO: support cpupll bypass */
+	hws[CLK_CPU0] =
+		devm_clk_hw_register_fixed_factor(dev, "cpu0", clk_names[CPUPLL_OUTF], 0, 1, 1);
+	if (IS_ERR(hws[CLK_CPU0]))
+		return PTR_ERR(hws[CLK_CPU0]);
+	hws[CLK_CPU1] =
+		devm_clk_hw_register_fixed_factor(dev, "cpu1", clk_names[CPUPLL_OUTF], 0, 1, 1);
+	if (IS_ERR(hws[CLK_CPU1]))
+		return PTR_ERR(hws[CLK_CPU1]);
+	hws[CLK_DSU] =
+		devm_clk_hw_register_fixed_factor(dev, "dsu", clk_names[CPUPLL_OUT], 0, 1, 1);
+	if (IS_ERR(hws[CLK_DSU]))
+		return PTR_ERR(hws[CLK_DSU]);
+
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+}
+
+static int sl2610_aio_clk_setup(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *parent_np = dev->parent->of_node;
+	void __iomem *base;
+	int ret;
+
+	base = devm_of_iomap(dev, parent_np, 0, NULL);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	/* aplls */
+	ret = sl2610_pll_register(dev, base + APLL0_OFFSET,
+				  clk_names[APLL0_OUT], clk_names[APLL0_OUTF]);
+	if (ret)
+		return ret;
+	ret = sl2610_pll_register(dev, base + APLL1_OFFSET,
+				  clk_names[APLL1_OUT], clk_names[APLL1_OUTF]);
+	if (ret)
+		return ret;
+
+	/* TODO aio clks */
+
+	return 0;
+}
+
+static const struct sl_sysmgr_fixedclk_desc sl2610_sysmgr_fixeds[] = {
+	{ "clk_mcu_ref",	CLK_MCU_REF,	25000000 },
+	{ "clk_mcu_pll",	CLK_MCU_PLL,	400000000 },
+	{ "clk_mcu_io_pll",	CLK_MCU_IO_PLL,	300000000 },
+	{ "clk_mcu_apb",	CLK_MCU_APB,	100000000 },
+	{ "clk_mcu_axi",	CLK_MCU_AXI,	200000000 },
+};
+
+static const struct sl_sysmgr_gateclk_desc sl2610_sysmgr_gates[] = {
+	{ "clk_cfg_uart0",	"clk_mcu_apb",	CLK_CFG_UART0,	0 },
+	{ "clk_ser_uart0",	"clk_mcu_ref",	CLK_SER_UART0,	1 },
+	{ "clk_cfg_uart1",	"clk_mcu_apb",	CLK_CFG_UART1,	2 },
+	{ "clk_cfg_uart2",	"clk_mcu_apb",	CLK_CFG_UART2,	3 },
+	{ "clk_cfg_uart3",	"clk_mcu_apb",	CLK_CFG_UART3,	4 },
+	{ "clk_cfg_gpio",	"clk_mcu_apb",	CLK_CFG_GPIO,	5 },
+	{ "clk_cfg_i2cm0",	"clk_mcu_apb",	CLK_CFG_I2CM0,	6 },
+	{ "clk_cfg_i2cm1",	"clk_mcu_apb",	CLK_CFG_I2CM1,	7 },
+	{ "clk_cfg_spim",	"clk_mcu_apb",	CLK_CFG_SPIM,	8 },
+	{ "clk_cfg_spis",	"clk_mcu_apb",	CLK_CFG_SPIS,	9 },
+	{ "clk_cfg_i3c",	"clk_mcu_apb",	CLK_CFG_I3C,	10 },
+	{ "clk_cfg_xspi",	"clk_mcu_apb",	CLK_CFG_XSPI,	11 },
+	{ "clk_axi_xspi",	"clk_mcu_axi",	CLK_AXI_XSPI,	12 },
+	{ "clk_cfg_pvt",	"clk_mcu_apb",	CLK_CFG_PVT,	13 },
+	{ "clk_cfg_adc",	"clk_mcu_apb",	CLK_CFG_ADC,	14 },
+	{ "clk_cfg_pwm",	"clk_mcu_apb",	CLK_CFG_PWM,	15 },
+	{ "clk_bus_can0",	"clk_mcu_axi",	CLK_BUS_CAN0,	16 },
+	{ "clk_bus_can1",	"clk_mcu_axi",	CLK_BUS_CAN1,	17 },
+	{ "clk_cfg_pdm",	"clk_mcu_apb",	CLK_CFG_PDM,	18 },
+};
+
+static const struct sl_sysmgr_clk_desc sl2610_sysmgr_clks[] = {
+	{ "clk_ser_uart1",	"clk_mcu_pll",	CLK_SER_UART1,	0x604,	4 },
+	{ "clk_ser_uart2",	"clk_mcu_pll",	CLK_SER_UART2,	0x608,	4 },
+	{ "clk_ser_uart3",	"clk_mcu_pll",	CLK_SER_UART3,	0x60c,	4 },
+	{ "clk_deb_gpio",	"clk_mcu_pll",	CLK_DEB_GPIO,	0x610,	4 },
+	{ "clk_ser_i2cm0",	"clk_mcu_pll",	CLK_SER_I2CM0,	0x614,	4 },
+	{ "clk_ser_i2cm1",	"clk_mcu_pll",	CLK_SER_I2CM1,	0x618,	4 },
+	{ "clk_ser_spim",	"clk_mcu_pll",	CLK_SER_SPIM,	0x61c,	4 },
+	{ "clk_ser_spis",	"clk_mcu_pll",	CLK_SER_SPIS,	0x620,	4 },
+	{ "clk_ser_i3c",	"clk_mcu_pll",	CLK_SER_I3C,	0x624,	4 },
+	{ "clk_ser_xspi",	"clk_mcu_io_pll", CLK_SER_XSPI,	0x628,	4 },
+	{ "clk_hs_pvt",		"clk_mcu_pll",	CLK_HS_PVT,	0x62c,	4 },
+	{ "clk_core_adc",	"clk_mcu_pll",	CLK_CORE_ADC,	0x630,	8 },
+	{ "clk_ser_pwm",	"clk_mcu_pll",	CLK_SER_PWM,	0x634,	4 },
+	{ "clk_ser_can0",	"clk_mcu_pll",	CLK_SER_CAN0,	0x638,	4 },
+	{ "clk_ser_can1",	"clk_mcu_pll",	CLK_SER_CAN1,	0x63c,	4 },
+	{ "clk_ser_pdm",	"clk_mcu_pll",	CLK_SER_PDM,	0x640,	8 },
+	{ "clk_ref_calib",	"clk_mcu_pll",	CLK_REF_CALIB,	0x644,	8 },
+};
+
+static int sl2610_sysmgr_clk_setup(struct platform_device *pdev)
+{
+	return sl_sysmgr_clk_setup(pdev, sl2610_sysmgr_fixeds, ARRAY_SIZE(sl2610_sysmgr_fixeds),
+				   sl2610_sysmgr_gates, ARRAY_SIZE(sl2610_sysmgr_gates),
+				   CLK_GATE_CTRL0,
+				   sl2610_sysmgr_clks, ARRAY_SIZE(sl2610_sysmgr_clks));
+}
+
+static const struct platform_device_id sl2610_clks_ids[] = {
+	{ "sl2610-soc-clk", (kernel_ulong_t)sl2610_soc_clk_setup },
+	{ "sl2610-cpu-clk", (kernel_ulong_t)sl2610_cpu_clk_setup },
+	{ "sl2610-avio-clk", (kernel_ulong_t)sl2610_aio_clk_setup },
+	{ "sl2610-mcu-clk", (kernel_ulong_t)sl2610_sysmgr_clk_setup },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sl2610_clks_ids);
+
+static int sl2610_clks_probe(struct platform_device *pdev)
+{
+	int (*clk_setup)(struct platform_device *pdev);
+
+	clk_setup = (void *)platform_get_device_id(pdev)->driver_data;
+
+	return clk_setup(pdev);
+}
+
+static struct platform_driver sl2610_clks_driver = {
+	.probe = sl2610_clks_probe,
+	.id_table = sl2610_clks_ids,
+	.driver = {
+		.name = "sl2610-clk",
+	},
+};
+module_platform_driver(sl2610_clks_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_DESCRIPTION("Synaptics SL2610 clock driver");
diff --git a/drivers/clk/berlin/sl2610-pll.c b/drivers/clk/berlin/sl2610-pll.c
new file mode 100644
index 000000000000..62c5d2d19c36
--- /dev/null
+++ b/drivers/clk/berlin/sl2610-pll.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2021 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_clk.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "sl2610-pll.h"
+
+#define FRAC_BITS		24
+
+#define CTRLC			0x08
+#define DIVR_MASK		GENMASK(8, 0)
+#define CTRLD			0x0c
+#define DIVF_MASK		GENMASK(8, 0)
+#define CTRLE			0x10
+#define DIVFF_MASK		GENMASK(23, 0)
+#define CTRLF			0x14
+#define DIVQ_MASK		GENMASK(4, 0)
+#define CTRLG			0x18
+#define DIVQF_MASK		GENMASK(2, 0)
+
+#define SL2610_APLL
+struct sl2610_pll {
+	void __iomem *ctrl;
+	struct clk_hw pllout;
+	struct clk_hw plloutf;
+};
+
+#define to_pllout(_hw) container_of(_hw, struct sl2610_pll, pllout)
+#define to_plloutf(_hw) container_of(_hw, struct sl2610_pll, plloutf)
+
+static unsigned long sl2610_pll_recalc_rate(struct sl2610_pll *pll,
+					    unsigned long parent_rate, bool fractional_output)
+{
+	u32 dm, dn, frac, dp;
+	u64 rate;
+
+	dm = (readl_relaxed(pll->ctrl + CTRLC) & DIVR_MASK) + 1;
+	dn = (readl_relaxed(pll->ctrl + CTRLD) & DIVF_MASK) + 1;
+	frac = readl_relaxed(pll->ctrl + CTRLE) & DIVFF_MASK;
+
+	if (fractional_output)
+		dp = (readl_relaxed(pll->ctrl + CTRLG) & DIVQF_MASK) + 1;
+	else
+		dp = ((readl_relaxed(pll->ctrl + CTRLF) & DIVQ_MASK) + 1) * 2;
+
+	rate = (u64)parent_rate * dn;
+	rate += ((u64)parent_rate * frac + BIT_ULL(FRAC_BITS - 1)) >> FRAC_BITS;
+	rate = DIV_ROUND_CLOSEST_ULL(rate * 4, dm * dp);
+
+	return rate;
+}
+
+static unsigned long sl2610_pllout_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	return sl2610_pll_recalc_rate(to_pllout(hw), parent_rate, false);
+}
+
+static unsigned long sl2610_plloutf_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	return sl2610_pll_recalc_rate(to_plloutf(hw), parent_rate, true);
+}
+
+static const struct clk_ops sl2610_pllout_ops = {
+	.recalc_rate = sl2610_pllout_recalc_rate,
+};
+
+static const struct clk_ops sl2610_plloutf_ops = {
+	.recalc_rate = sl2610_plloutf_recalc_rate,
+};
+
+static void sl2610_pll_put_clk(void *data)
+{
+	clk_put(data);
+}
+
+int sl2610_pll_register(struct device *dev, void __iomem *ctrl,
+			const char *out, const char *outf)
+{
+	struct device_node *np = dev->parent->of_node;
+	struct clk_parent_data parent = {};
+	struct clk_init_data init = {};
+	struct sl2610_pll *pll;
+	struct clk *input;
+	int ret;
+
+	if (!dev || !ctrl || !out || !outf)
+		return -EINVAL;
+
+	input = of_clk_get(np, 0);
+	if (IS_ERR(input))
+		return dev_err_probe(dev, PTR_ERR(input),
+				     "failed to get PLL reference clock\n");
+	parent.hw = __clk_get_hw(input);
+	ret = devm_add_action_or_reset(dev, sl2610_pll_put_clk, input);
+	if (ret)
+		return ret;
+
+	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return -ENOMEM;
+	pll->ctrl = ctrl;
+
+	init.name = out;
+	init.ops = &sl2610_pllout_ops;
+	init.parent_data = &parent;
+	init.num_parents = 1;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	pll->pllout.init = &init;
+
+	ret = devm_clk_hw_register(dev, &pll->pllout);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to register pllout\n");
+
+	init.name = outf;
+	init.ops = &sl2610_plloutf_ops;
+	pll->plloutf.init = &init;
+
+	ret = devm_clk_hw_register(dev, &pll->plloutf);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to register plloutf\n");
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sl2610_pll_register);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Synaptics SL2610 PLL clock driver");
diff --git a/drivers/clk/berlin/sl2610-pll.h b/drivers/clk/berlin/sl2610-pll.h
new file mode 100644
index 000000000000..b61a93b28610
--- /dev/null
+++ b/drivers/clk/berlin/sl2610-pll.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SL2610_PLL_H
+#define __SL2610_PLL_H
+
+#include <linux/io.h>
+
+struct clk_hw_onecell_data;
+struct device;
+struct device_node;
+
+int sl2610_pll_register(struct device *dev, void __iomem *ctrl,
+			const char *out, const char *outf);
+
+#endif /* __SL2610_PLL_H */
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 11/13] dt-bindings: arm: berlin: add Synaptics SL2610 SoCs and RDK boards
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (9 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 10/13] clk: berlin: add Synaptics SL2610 clocks and PLLs Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 10:23 ` [PATCH v2 12/13] arm64: dts: synaptics: add SL2610 family SoCs Jisheng Zhang
  2026-11-15 10:23 ` [PATCH v2 13/13] arm64: dts: synaptics: add SL2610 family RDK boards Jisheng Zhang
  12 siblings, 0 replies; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Add devicetree binding for the Synaptics SL2610 SoCs and corresponding
RDK boards.

The SL2610 family includes five pin-to-pin compatible SoCs: SL2611,
SL2613, SL2615, SL2617, and SL2619.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../bindings/arm/marvell,berlin.yaml          | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/marvell,berlin.yaml b/Documentation/devicetree/bindings/arm/marvell,berlin.yaml
index 4e8442980dcb..30d94059e2f2 100644
--- a/Documentation/devicetree/bindings/arm/marvell,berlin.yaml
+++ b/Documentation/devicetree/bindings/arm/marvell,berlin.yaml
@@ -41,5 +41,25 @@ properties:
               - marvell,berlin4ct-stb
           - const: marvell,berlin4ct
           - const: marvell,berlin
+      - items:
+          - enum:
+              - syna,sl2611-rdk
+          - const: syna,sl2611
+      - items:
+          - enum:
+              - syna,sl2613-rdk
+          - const: syna,sl2613
+      - items:
+          - enum:
+              - syna,sl2615-rdk
+          - const: syna,sl2615
+      - items:
+          - enum:
+              - syna,sl2617-rdk
+          - const: syna,sl2617
+      - items:
+          - enum:
+              - syna,sl2619-rdk
+          - const: syna,sl2619
 
 additionalProperties: true
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 12/13] arm64: dts: synaptics: add SL2610 family SoCs
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (10 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 11/13] dt-bindings: arm: berlin: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 11:13   ` sashiko-bot
  2026-11-15 10:23 ` [PATCH v2 13/13] arm64: dts: synaptics: add SL2610 family RDK boards Jisheng Zhang
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Describe the CPUs, interrupt controller, system controllers and supported
serial, I2C, I3C, SPI and GPIO peripherals for the SL2610 family.

Use the SL2610 peripheral compatibles already documented in the upstream
bindings and share clock, reset and pin configuration providers through
the system controller nodes.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 arch/arm64/boot/dts/synaptics/sl2611.dtsi | 457 ++++++++++++++++++++++
 arch/arm64/boot/dts/synaptics/sl2613.dtsi |  12 +
 arch/arm64/boot/dts/synaptics/sl2615.dtsi |  46 +++
 arch/arm64/boot/dts/synaptics/sl2617.dtsi |  46 +++
 arch/arm64/boot/dts/synaptics/sl2619.dtsi |  44 +++
 5 files changed, 605 insertions(+)
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2611.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2613.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2615.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2617.dtsi
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2619.dtsi

diff --git a/arch/arm64/boot/dts/synaptics/sl2611.dtsi b/arch/arm64/boot/dts/synaptics/sl2611.dtsi
new file mode 100644
index 000000000000..663fe6034ba0
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2611.dtsi
@@ -0,0 +1,457 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2024 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <dt-bindings/clock/syna,sl2610.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/syna,sl2610-reset.h>
+
+/ {
+	compatible = "syna,sl2611";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	optee {
+		compatible = "linaro,optee-tz";
+		method = "smc";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x0>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0>;
+			i-cache-size = <32768>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <128>;
+			d-cache-size = <32768>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>;
+			next-level-cache = <&L2_0>;
+
+			L2_0: l2-cache {
+				compatible = "cache";
+				cache-size = <65536>;
+				cache-line-size = <64>;
+				cache-sets = <256>;
+				cache-level = <2>;
+				cache-unified;
+				next-level-cache = <&L3>;
+			};
+		};
+
+		L3: l3-cache0 {
+			compatible = "cache";
+			cache-level = <3>;
+			cache-unified;
+			cache-size = <262144>;
+			cache-line-size = <64>;
+			cache-sets = <256>;
+		};
+
+		idle-states {
+			entry-method = "psci";
+			CPU_SLEEP_0: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				local-timer-stop;
+				arm,psci-suspend-param = <0x0010000>;
+				entry-latency-us = <75>;
+				exit-latency-us = <155>;
+				min-residency-us = <50000>;
+			};
+		};
+	};
+
+	osc: osc {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a55-pmu";
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0xffffffff>;
+
+		sm-bus {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			dma-ranges = <0xa0000000 0x00000000 0x10000000>;
+
+			sm_clk: sm_pinctrl: sm_rst: sm_chip: syscon@e5025000 {
+				compatible = "syna,sl2610-mcu-syscon", "syscon";
+				reg = <0xe5025000 0x1000>;
+				#clock-cells = <1>;
+				#reset-cells = <1>;
+				clocks = <&osc>;
+			};
+
+			sm_uart0: serial@e5030000 {
+				compatible = "syna,sl2610-uart", "snps,dw-apb-uart";
+				reg = <0xe5030000 0x100>;
+				interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&sm_clk CLK_SER_UART0>, <&sm_clk CLK_CFG_UART0>;
+				clock-names = "baudclk", "apb_pclk";
+				reg-shift = <2>;
+				status = "disabled";
+			};
+
+			sm_uart1: serial@e5031000 {
+				compatible = "syna,sl2610-uart", "snps,dw-apb-uart";
+				reg = <0xe5031000 0x100>;
+				interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&sm_clk CLK_SER_UART1>, <&sm_clk CLK_CFG_UART1>;
+				clock-names = "baudclk", "apb_pclk";
+				reg-shift = <2>;
+				status = "disabled";
+			};
+
+			sm_uart2: serial@e5032000 {
+				compatible = "syna,sl2610-uart", "snps,dw-apb-uart";
+				reg = <0xe5032000 0x100>;
+				interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&sm_clk CLK_SER_UART2>, <&sm_clk CLK_CFG_UART2>;
+				clock-names = "baudclk", "apb_pclk";
+				reg-shift = <2>;
+				status = "disabled";
+			};
+
+			sm_uart3: serial@e5033000 {
+				compatible = "syna,sl2610-uart", "snps,dw-apb-uart";
+				reg = <0xe5033000 0x100>;
+				interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&sm_clk CLK_SER_UART3>, <&sm_clk CLK_CFG_UART3>;
+				clock-names = "baudclk", "apb_pclk";
+				reg-shift = <2>;
+				status = "disabled";
+			};
+
+			sm_spi1: spi@e5034000 {
+				compatible = "syna,sl2610-spi", "snps,dw-apb-ssi";
+				reg = <0xe5034000 0x100>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				num-cs = <4>;
+				clocks = <&sm_clk CLK_SER_SPIM>, <&sm_clk CLK_CFG_SPIM>;
+				clock-names = "ssi_clk", "pclk";
+				interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			sm_i2c0: i2c@e5035000 {
+				compatible = "syna,sl2610-i2c", "snps,designware-i2c";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0xe5035000 0x100>;
+				clocks = <&sm_clk CLK_SER_I2CM0>, <&sm_clk CLK_CFG_I2CM0>;
+				clock-names = "ref", "pclk";
+				i2c-sda-falling-time-ns = <510>;
+				i2c-scl-falling-time-ns = <510>;
+				interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			sm_i2c1: i2c@e5036000 {
+				compatible = "syna,sl2610-i2c", "snps,designware-i2c";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0xe5036000 0x100>;
+				clocks = <&sm_clk CLK_SER_I2CM1>, <&sm_clk CLK_CFG_I2CM1>;
+				clock-names = "ref", "pclk";
+				i2c-sda-falling-time-ns = <510>;
+				i2c-scl-falling-time-ns = <510>;
+				interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			sm_i3c0: i3c@e5037000 {
+				compatible = "syna,sl2610-i3c", "snps,dw-i3c-master-1.00a";
+				#address-cells = <3>;
+				#size-cells = <0>;
+				reg = <0xe5037000 0x1000>;
+				interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>;
+				resets = <&sm_rst RST_SM_I3CSRST>, <&sm_rst RST_SM_I3CPRST>;
+				clocks = <&sm_clk CLK_SER_I3C>, <&sm_clk CLK_CFG_I3C>;
+				clock-names = "core", "apb";
+				status = "disabled";
+			};
+
+			sm_gpio0: gpio@e5038000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0xe5038000 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&sm_clk CLK_CFG_GPIO>, <&sm_clk CLK_DEB_GPIO>;
+				clock-names = "bus", "db";
+
+				portc: gpio-port@0 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					ngpios = <16>;
+					reg = <0>;
+				};
+			};
+
+			sm_gpio1: gpio@e5039000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0xe5039000 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&sm_clk CLK_CFG_GPIO>, <&sm_clk CLK_DEB_GPIO>;
+				clock-names = "bus", "db";
+
+				portd: gpio-port@0 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					ngpios = <8>;
+					reg = <0>;
+				};
+			};
+
+			sm_gpio2: gpio@e503a000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0xe503a000 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&sm_clk CLK_CFG_GPIO>, <&sm_clk CLK_DEB_GPIO>;
+				clock-names = "bus", "db";
+
+				porte: gpio-port@0 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					ngpios = <8>;
+					reg = <0>;
+				};
+			};
+
+			sm_gpio3: gpio@e503b000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0xe503b000 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&sm_clk CLK_CFG_GPIO>, <&sm_clk CLK_DEB_GPIO>;
+				clock-names = "bus", "db";
+
+				portf: gpio-port@0 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					ngpios = <8>;
+					reg = <0>;
+				};
+			};
+		};
+
+		aioclk: aviogbl: syscon@f7490000 {
+			compatible = "syna,sl2610-avio-syscon", "syscon";
+			reg = <0xf7490000 0x4000>;
+			clocks = <&osc>;
+		};
+
+		clk: pinctrl: rst: chip: syscon@f7e10000 {
+			compatible = "syna,sl2610-soc-syscon", "syscon";
+			reg = <0xf7e10000 0x10000>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			clocks = <&osc>;
+		};
+
+		cpuclk: cpu_wrap: syscon@f7e30000 {
+			compatible = "syna,sl2610-cpu-syscon", "syscon";
+			reg = <0xf7e30000 0x4000>;
+			#clock-cells = <1>;
+			clocks = <&osc>;
+			syna,gbl-syscon = <&chip>;
+		};
+
+		gic: interrupt-controller@f7e59000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			interrupt-controller;
+			reg = <0xf7e59000 0x1000>,
+			      <0xf7e5a000 0x2000>,
+			      <0xf7e5c000 0x2000>,
+			      <0xf7e5e000 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		};
+
+		soc_uart0: serial@f7f00000 {
+			compatible = "syna,sl2610-uart", "snps,dw-apb-uart";
+			reg = <0xf7f00000 0x100>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk CLK_APBUART0>;
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		soc_uart1: serial@f7f01000 {
+			compatible = "syna,sl2610-uart", "snps,dw-apb-uart";
+			reg = <0xf7f01000 0x100>;
+			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk CLK_APBUART1>;
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		soc_uart2: serial@f7f02000 {
+			compatible = "syna,sl2610-uart", "snps,dw-apb-uart";
+			reg = <0xf7f02000 0x100>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk CLK_APBUART2>;
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		soc_uart3: serial@f7f03000 {
+			compatible = "syna,sl2610-uart", "snps,dw-apb-uart";
+			reg = <0xf7f03000 0x100>;
+			interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk CLK_APBUART3>;
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		soc_spi0: spi@f7f04000 {
+			compatible = "syna,sl2610-spi", "snps,dw-apb-ssi";
+			reg = <0xf7f04000 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			num-cs = <4>;
+			clocks = <&clk CLK_APBSPI0>;
+			interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		soc_i2c0: i2c@f7f05000 {
+			compatible = "syna,sl2610-i2c", "snps,designware-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xf7f05000 0x100>;
+			clocks = <&clk CLK_APBI2C0>;
+			i2c-sda-hold-time-ns = <449>;
+			i2c-sda-falling-time-ns = <425>;
+			i2c-scl-falling-time-ns = <205>;
+			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		soc_i2c1: i2c@f7f06000 {
+			compatible = "syna,sl2610-i2c", "snps,designware-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xf7f06000 0x100>;
+			clocks = <&clk CLK_APBI2C1>;
+			i2c-sda-hold-time-ns = <449>;
+			i2c-sda-falling-time-ns = <425>;
+			i2c-scl-falling-time-ns = <205>;
+			interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		soc_gpio0: gpio@f7f07000 {
+			compatible = "snps,dw-apb-gpio";
+			reg = <0xf7f07000 0x400>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&clk CLK_APBGPIO>;
+			clock-names = "bus";
+
+			porta: gpio-port@0 {
+				compatible = "snps,dw-apb-gpio-port";
+				gpio-controller;
+				#gpio-cells = <2>;
+				ngpios = <32>;
+				reg = <0>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+			};
+		};
+
+		soc_spi1: spi@f7f0b000 {
+			compatible = "syna,sl2610-spi", "snps,dw-apb-ssi";
+			reg = <0xf7f0b000 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			num-cs = <4>;
+			clocks = <&clk CLK_APBSPI1>;
+			interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		soc_spi2: spi@f7f0c000 {
+			compatible = "syna,sl2610-spi", "snps,dw-apb-ssi";
+			reg = <0xf7f0c000 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			num-cs = <4>;
+			clocks = <&clk CLK_APBSPI2>;
+			interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		soc_spi3: spi@f7f0d000 {
+			compatible = "syna,sl2610-spi", "snps,dw-apb-ssi";
+			reg = <0xf7f0d000 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			num-cs = <4>;
+			clocks = <&clk CLK_APBSPI3>;
+			interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		soc_gpio1: gpio@f7f0e000 {
+			compatible = "snps,dw-apb-gpio";
+			reg = <0xf7f0e000 0x400>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&clk CLK_APBGPIO>;
+			clock-names = "bus";
+
+			portb: gpio-port@0 {
+				compatible = "snps,dw-apb-gpio-port";
+				gpio-controller;
+				#gpio-cells = <2>;
+				ngpios = <32>;
+				reg = <0>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl2613.dtsi b/arch/arm64/boot/dts/synaptics/sl2613.dtsi
new file mode 100644
index 000000000000..379809901677
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2613.dtsi
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include "sl2611.dtsi"
+
+/ {
+	compatible = "syna,sl2613";
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl2615.dtsi b/arch/arm64/boot/dts/synaptics/sl2615.dtsi
new file mode 100644
index 000000000000..11b1fe316aa6
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2615.dtsi
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include "sl2613.dtsi"
+
+/ {
+	compatible = "syna,sl2615";
+
+	cpus {
+		cpu1: cpu@100 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x100>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0>;
+			i-cache-size = <32768>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <128>;
+			d-cache-size = <32768>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>;
+			next-level-cache = <&L2_1>;
+
+			L2_1: l2-cache {
+				compatible = "cache";
+				cache-size = <65536>;
+				cache-line-size = <64>;
+				cache-sets = <256>;
+				cache-level = <2>;
+				cache-unified;
+				next-level-cache = <&L3>;
+			};
+		};
+	};
+
+	pmu {
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>,
+				     <&cpu1>;
+	};
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl2617.dtsi b/arch/arm64/boot/dts/synaptics/sl2617.dtsi
new file mode 100644
index 000000000000..a0de686d1fae
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2617.dtsi
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include "sl2613.dtsi"
+
+/ {
+	compatible = "syna,sl2617";
+
+	cpus {
+		cpu1: cpu@100 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x100>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0>;
+			i-cache-size = <32768>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <128>;
+			d-cache-size = <32768>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>;
+			next-level-cache = <&L2_1>;
+
+			L2_1: l2-cache {
+				compatible = "cache";
+				cache-size = <65536>;
+				cache-line-size = <64>;
+				cache-sets = <256>;
+				cache-level = <2>;
+				cache-unified;
+				next-level-cache = <&L3>;
+			};
+		};
+	};
+
+	pmu {
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>,
+				     <&cpu1>;
+	};
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl2619.dtsi b/arch/arm64/boot/dts/synaptics/sl2619.dtsi
new file mode 100644
index 000000000000..96bd58bbed3e
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2619.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include "sl2613.dtsi"
+
+/ {
+	cpus {
+		cpu1: cpu@100 {
+			compatible = "arm,cortex-a55";
+			device_type = "cpu";
+			reg = <0x100>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0>;
+			i-cache-size = <32768>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <128>;
+			d-cache-size = <32768>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>;
+			next-level-cache = <&L2_1>;
+
+			L2_1: l2-cache {
+				compatible = "cache";
+				cache-size = <65536>;
+				cache-line-size = <64>;
+				cache-sets = <256>;
+				cache-level = <2>;
+				cache-unified;
+				next-level-cache = <&L3>;
+			};
+		};
+	};
+
+	pmu {
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>,
+				     <&cpu1>;
+	};
+};
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 13/13] arm64: dts: synaptics: add SL2610 family RDK boards
  2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
                   ` (11 preceding siblings ...)
  2026-11-15 10:23 ` [PATCH v2 12/13] arm64: dts: synaptics: add SL2610 family SoCs Jisheng Zhang
@ 2026-11-15 10:23 ` Jisheng Zhang
  2026-11-15 11:05   ` sashiko-bot
  12 siblings, 1 reply; 24+ messages in thread
From: Jisheng Zhang @ 2026-11-15 10:23 UTC (permalink / raw)
  To: Rob Herring, Conor Dooley, Krzysztof Kozlowski, Catalin Marinas,
	Will Deacon, Mark Rutland, Sebastian Hesselbarth, Stephen Boyd,
	Brian Masney, Jerome Brunet, Linus Walleij, Philipp Zabel
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-clk, linux-gpio

Add device trees for the SL2611, SL2613, SL2615, SL2617 and SL2619
reference development kits. Share their common console, memory, pin
configuration and regulator descriptions and enable the populated
peripherals.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 arch/arm64/boot/dts/synaptics/Makefile        |   5 +
 arch/arm64/boot/dts/synaptics/sl2611-rdk.dts  |  16 +++
 arch/arm64/boot/dts/synaptics/sl2613-rdk.dts  |  16 +++
 arch/arm64/boot/dts/synaptics/sl2615-rdk.dts  |  16 +++
 arch/arm64/boot/dts/synaptics/sl2617-rdk.dts  |  16 +++
 arch/arm64/boot/dts/synaptics/sl2619-rdk.dts  |  16 +++
 .../boot/dts/synaptics/sl261x-rdk-common.dtsi | 135 ++++++++++++++++++
 7 files changed, 220 insertions(+)
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2611-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2613-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2615-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2617-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl2619-rdk.dts
 create mode 100644 arch/arm64/boot/dts/synaptics/sl261x-rdk-common.dtsi

diff --git a/arch/arm64/boot/dts/synaptics/Makefile b/arch/arm64/boot/dts/synaptics/Makefile
index de71ddda6835..810d0d08c2de 100644
--- a/arch/arm64/boot/dts/synaptics/Makefile
+++ b/arch/arm64/boot/dts/synaptics/Makefile
@@ -2,3 +2,8 @@
 # Berlin SoC Family
 dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-dmp.dtb
 dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-stb.dtb
+dtb-$(CONFIG_ARCH_BERLIN) += sl2611-rdk.dtb
+dtb-$(CONFIG_ARCH_BERLIN) += sl2613-rdk.dtb
+dtb-$(CONFIG_ARCH_BERLIN) += sl2615-rdk.dtb
+dtb-$(CONFIG_ARCH_BERLIN) += sl2617-rdk.dtb
+dtb-$(CONFIG_ARCH_BERLIN) += sl2619-rdk.dtb
diff --git a/arch/arm64/boot/dts/synaptics/sl2611-rdk.dts b/arch/arm64/boot/dts/synaptics/sl2611-rdk.dts
new file mode 100644
index 000000000000..585872307834
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2611-rdk.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "sl2611.dtsi"
+#include "sl261x-rdk-common.dtsi"
+
+/ {
+	model = "Synaptics SL2611 RDK";
+	compatible = "syna,sl2611-rdk", "syna,sl2611";
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl2613-rdk.dts b/arch/arm64/boot/dts/synaptics/sl2613-rdk.dts
new file mode 100644
index 000000000000..de75c9fab6a2
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2613-rdk.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "sl2613.dtsi"
+#include "sl261x-rdk-common.dtsi"
+
+/ {
+	model = "Synaptics SL2613 RDK";
+	compatible = "syna,sl2613-rdk", "syna,sl2613";
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl2615-rdk.dts b/arch/arm64/boot/dts/synaptics/sl2615-rdk.dts
new file mode 100644
index 000000000000..ae03638a3a53
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2615-rdk.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "sl2615.dtsi"
+#include "sl261x-rdk-common.dtsi"
+
+/ {
+	model = "Synaptics SL2615 RDK";
+	compatible = "syna,sl2615-rdk", "syna,sl2615";
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl2617-rdk.dts b/arch/arm64/boot/dts/synaptics/sl2617-rdk.dts
new file mode 100644
index 000000000000..ba4ea21ac505
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2617-rdk.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "sl2617.dtsi"
+#include "sl261x-rdk-common.dtsi"
+
+/ {
+	model = "Synaptics SL2617 RDK";
+	compatible = "syna,sl2617-rdk", "syna,sl2617";
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl2619-rdk.dts b/arch/arm64/boot/dts/synaptics/sl2619-rdk.dts
new file mode 100644
index 000000000000..58901ac2a050
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl2619-rdk.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "sl2619.dtsi"
+#include "sl261x-rdk-common.dtsi"
+
+/ {
+	model = "Synaptics SL2619 RDK";
+	compatible = "syna,sl2619-rdk", "syna,sl2619";
+};
diff --git a/arch/arm64/boot/dts/synaptics/sl261x-rdk-common.dtsi b/arch/arm64/boot/dts/synaptics/sl261x-rdk-common.dtsi
new file mode 100644
index 000000000000..78a9b28fdf99
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/sl261x-rdk-common.dtsi
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 Synaptics Incorporated
+ *
+ * Author: Jisheng Zhang <jszhang@kernel.org>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+
+/ {
+	aliases {
+		serial0 = &sm_uart0;
+		serial1 = &sm_uart1;
+		serial2 = &sm_uart2;
+		serial3 = &sm_uart3;
+		serial4 = &soc_uart0;
+		serial5 = &soc_uart1;
+		serial6 = &soc_uart2;
+		serial7 = &soc_uart3;
+		i2c0 = &sm_i2c0;
+		i2c1 = &sm_i2c1;
+		i2c2 = &soc_i2c0;
+		i2c3 = &soc_i2c1;
+		spi1 = &sm_spi1;
+		spi2 = &soc_spi0;
+		spi3 = &soc_spi1;
+		spi4 = &soc_spi2;
+		spi5 = &soc_spi3;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vcore>;
+		};
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+		bootargs = "earlycon";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x00000000 0x0 0x80000000>;
+	};
+};
+
+&osc {
+	clock-frequency = <25000000>;
+};
+
+&pinctrl {
+	soc_i2c0_pmux: soc_i2c0-pmux {
+		groups = "GPIO23", "GPIO24";
+		function = "tw2";
+		drive-strength = <7>;
+	};
+};
+
+&sm_pinctrl {
+	sm_i2c0_pmux: i2c0-pmux {
+		groups = "SM_GPIO12", "SM_GPIO13";
+		function = "tw0";
+		drive-strength = <7>;
+	};
+
+	sm_i2c1_pmux: i2c1-pmux {
+		groups = "SM_GPIO3", "SM_GPIO4";
+		function = "tw1";
+		drive-strength = <7>;
+	};
+
+	vcore_gpio_pmux: vcore-gpio-pmux {
+		groups = "SM_GPIO5";
+		function = "gpio";
+	};
+};
+
+&sm_uart0 {
+	status = "okay";
+};
+
+&sm_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&sm_i2c0_pmux>;
+	clock-frequency = <100000>;
+
+	expander0: gpio@43 {
+		compatible = "fcs,fxl6408";
+		reg = <0x43>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	expander1: gpio@44 {
+		compatible = "fcs,fxl6408";
+		reg = <0x44>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&sm_i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&sm_i2c1_pmux>;
+	clock-frequency = <100000>;
+
+	vcore: regulator@60 {
+		compatible = "silergy,sy8827n";
+		reg = <0x60>;
+		regulator-name = "vcore";
+		regulator-min-microvolt = <700000>;
+		regulator-max-microvolt = <987500>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-active-discharge = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&vcore_gpio_pmux>;
+		enable-gpios = <&portc 5 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&soc_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&soc_i2c0_pmux>;
+	clock-frequency = <100000>;
+};
+
+&sm_uart1 {
+	status = "okay";
+};
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 06/13] soc: synaptics: add SL2610 system controller support
  2026-11-15 10:23 ` [PATCH v2 06/13] soc: synaptics: add SL2610 system controller support Jisheng Zhang
@ 2026-11-15 10:56   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 10:56 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Low] soc: synaptics: new MFD driver sl2610-syscon placed outside
  drivers/mfd
- [Low] soc: synaptics: MFD used for single-function AVIO and CPU clock
  blocks
- [Low] soc: synaptics: mfd_cell arrays passed via match data in
  sl2610_syscon_probe()
--

commit 13fffaa081530baa348dec7822fd2e447d70af16
Author: Jisheng Zhang <jszhang@kernel.org>

soc: synaptics: add SL2610 system controller support

This commit adds a driver for the Synaptics SL2610 system control blocks to
register their clock, reset, and pin controller child devices via MFD.

> diff --git a/drivers/soc/synaptics/Kconfig b/drivers/soc/synaptics/Kconfig
> new file mode 100644
> index 0000000000000..9f0324a1a3b7a
> --- /dev/null
> +++ b/drivers/soc/synaptics/Kconfig
> @@ -0,0 +1,14 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +config SOC_SL2610_SYSCON
> +	tristate "Synaptics SL2610 system controller"
> +	depends on ARCH_BERLIN || COMPILE_TEST
> +	depends on OF && HAS_IOMEM
> +	select MFD_CORE
> +	select MFD_SYSCON

[Severity: Low]
Should this driver live under drivers/mfd/ instead of drivers/soc/synaptics/?

sl2610-syscon.c does not implement any SoC bus or SoC-specific service and
only calls devm_mfd_add_devices() to instantiate MFD child devices.  New core
MFD drivers and new calls to devm_mfd_add_devices() belong in drivers/mfd/.

> diff --git a/drivers/soc/synaptics/sl2610-syscon.c b/drivers/soc/synaptics/sl2610-syscon.c
> new file mode 100644
> index 0000000000000..c6fc2955ac0de
> --- /dev/null
> +++ b/drivers/soc/synaptics/sl2610-syscon.c
> @@ -0,0 +1,84 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Synaptics Incorporated
> + */
> +
> +#include <linux/mfd/core.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +struct sl2610_syscon_data {
> +	const struct mfd_cell *cells;
> +	unsigned int num_cells;
> +};
> +
> +static const struct mfd_cell sl2610_soc_cells[] = {
> +	MFD_CELL_NAME("sl2610-soc-clk"),
> +	MFD_CELL_NAME("sl2610-soc-reset"),
> +	MFD_CELL_NAME("sl2610-soc-pinctrl"),
> +};
> +
> +static const struct mfd_cell sl2610_mcu_cells[] = {
> +	MFD_CELL_NAME("sl2610-mcu-clk"),
> +	MFD_CELL_NAME("sl2610-mcu-reset"),
> +	MFD_CELL_NAME("sl2610-mcu-pinctrl"),
> +};
> +
> +static const struct mfd_cell sl2610_avio_cells[] = {
> +	MFD_CELL_NAME("sl2610-avio-clk"),
> +};
> +
> +static const struct mfd_cell sl2610_cpu_cells[] = {
> +	MFD_CELL_NAME("sl2610-cpu-clk"),
> +};

[Severity: Low]
Why use MFD for the single-function AVIO and CPU clock blocks?

sl2610_avio_cells and sl2610_cpu_cells each register only a single clock
child device, and per the syna,sl2610-soc-syscon binding neither block
provides reset or pinctrl functions.  MFD is intended for devices that
register multiple children across different subsystems, whereas the clock
driver can bind directly to syna,sl2610-avio-syscon and
syna,sl2610-cpu-syscon while keeping shared regmap access through the
generic syscon compatible.

> +
> +static const struct sl2610_syscon_data sl2610_soc_data = {
> +	.cells = sl2610_soc_cells,
> +	.num_cells = ARRAY_SIZE(sl2610_soc_cells),
> +};
> +
> +static const struct sl2610_syscon_data sl2610_mcu_data = {
> +	.cells = sl2610_mcu_cells,
> +	.num_cells = ARRAY_SIZE(sl2610_mcu_cells),
> +};
> +
> +static const struct sl2610_syscon_data sl2610_avio_data = {
> +	.cells = sl2610_avio_cells,
> +	.num_cells = ARRAY_SIZE(sl2610_avio_cells),
> +};
> +
> +static const struct sl2610_syscon_data sl2610_cpu_data = {
> +	.cells = sl2610_cpu_cells,
> +	.num_cells = ARRAY_SIZE(sl2610_cpu_cells),
> +};
> +
> +static int sl2610_syscon_probe(struct platform_device *pdev)
> +{
> +	const struct sl2610_syscon_data *data = device_get_match_data(&pdev->dev);
> +
> +	return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
> +				    data->cells, data->num_cells, NULL, 0, NULL);
> +}
> +
> +static const struct of_device_id sl2610_syscon_of_match[] = {
> +	{ .compatible = "syna,sl2610-soc-syscon", .data = &sl2610_soc_data },
> +	{ .compatible = "syna,sl2610-mcu-syscon", .data = &sl2610_mcu_data },
> +	{ .compatible = "syna,sl2610-avio-syscon", .data = &sl2610_avio_data },
> +	{ .compatible = "syna,sl2610-cpu-syscon", .data = &sl2610_cpu_data },
> +	{ }
> +};

[Severity: Low]
This isn't a bug in normal DT probing, but MFD drivers should not pass
mfd_cell arrays through the .data field of of_device_id tables.  In addition,
if the driver is bound without an OF match (such as via sysfs
driver_override), device_get_match_data() returns NULL and
sl2610_syscon_probe() dereferences a NULL data pointer.

Could sl2610_syscon_of_match store an enum or integer ID in .data and select
the static const mfd_cell array with a switch statement (and a default error
return) in sl2610_syscon_probe()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=6

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 08/13] pinctrl: berlin: add Synaptics SL2610 pin controller support
  2026-11-15 10:23 ` [PATCH v2 08/13] pinctrl: berlin: add Synaptics SL2610 pin " Jisheng Zhang
@ 2026-11-15 10:57   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 10:57 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] pinctrl: berlin: wrong pad config offset 0x87c for GPIO54 on
  SL2610
--

commit b2ae5372019c8928361d53ac7a361789c010c9c3
Author: Jisheng Zhang <jszhang@kernel.org>

pinctrl: berlin: add Synaptics SL2610 pin controller support

This commit adds the pin controller driver for Synaptics SL2610 SoCs,
defining the SoC and MCU pin groups, mux functions, and pad configuration
register offsets.

> diff --git a/drivers/pinctrl/berlin/pinctrl-sl2610.c b/drivers/pinctrl/berlin/pinctrl-sl2610.c
> new file mode 100644
> index 0000000000000..0a3dc146c2c01
> --- /dev/null
> +++ b/drivers/pinctrl/berlin/pinctrl-sl2610.c
> @@ -0,0 +1,759 @@

[ ... ]

> +static const struct berlin_desc_group sl2610_soc_pinctrl_groups[] = {

[ ... ]

> +	BERLIN_PINCTRLCONF_GROUP("GPIO53", 0x800c, 0x3, 0x00,
> +			0x8878, 10,
> +			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO53 */
> +			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RD1 */
> +			BERLIN_PINCTRL_FUNCTION(0x6, "spi4"), /* SS3n */
> +			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SCLK */
> +	BERLIN_PINCTRLCONF_GROUP("GPIO54", 0x800c, 0x3, 0x03,
> +			0x87c, 10,
> +			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO54 */
> +			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RD2 */
> +			BERLIN_PINCTRL_FUNCTION(0x7, "spi3")), /* SDI */
> +	BERLIN_PINCTRLCONF_GROUP("GPIO55", 0x800c, 0x3, 0x06,
> +			0x8880, 10,
> +			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO55 */
> +			BERLIN_PINCTRL_FUNCTION(0x1, "rgmii2"), /* RD3 */
> +			BERLIN_PINCTRL_FUNCTION(0x5, "spi5"), /* SDI */
> +			BERLIN_PINCTRL_FUNCTION(0x7, "spi4")), /* SS1n */

[Severity: Medium]
Should the pad configuration offset for GPIO54 be 0x887c instead of 0x87c?
All other entries in sl2610_soc_pinctrl_groups place conf_offset at 4-byte
intervals in the 0x8800..0x88ec range, so configuring pad parameters for
GPIO54 will read and modify offset 0x87c in the parent syscon regmap while
leaving GPIO54's pad unconfigured.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=8

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 05/13] dt-bindings: soc: synaptics: add SL2610 system controllers
  2026-11-15 10:23 ` [PATCH v2 05/13] dt-bindings: soc: synaptics: add SL2610 system controllers Jisheng Zhang
@ 2026-11-15 10:58   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 10:58 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Low] dt-bindings: soc: synaptics: split dissimilar SL2610 syscon
  blocks into separate schemas
--

commit bc8ce74277532ebd4eaa1fb7ce6d4be07d8dfe52
Author: Jisheng Zhang <jszhang@kernel.org>

dt-bindings: soc: synaptics: add SL2610 system controllers

This commit adds a Device Tree binding schema and clock/reset header
definitions for the Synaptics SL2610 SoC, MCU, AVIO, and CPU system
control register blocks.

> diff --git a/Documentation/devicetree/bindings/soc/synaptics/syna,sl2610-soc-syscon.yaml b/Documentation/devicetree/bindings/soc/synaptics/syna,sl2610-soc-syscon.yaml
> new file mode 100644
> index 0000000000000..cdf947cb3e0f6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/synaptics/syna,sl2610-soc-syscon.yaml
> @@ -0,0 +1,178 @@

[ ... ]

> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +          - syna,sl2610-soc-syscon
> +          - syna,sl2610-mcu-syscon
> +          - syna,sl2610-avio-syscon
> +          - syna,sl2610-cpu-syscon
> +      - const: syscon

[ ... ]

> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - syna,sl2610-soc-syscon
> +              - syna,sl2610-mcu-syscon
> +    then:
> +      required:
> +        - '#clock-cells'
> +        - '#reset-cells'
> +    else:
> +      properties:
> +        '#reset-cells': false
> +      patternProperties:
> +        '-(pmux|pins)$': false
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: syna,sl2610-cpu-syscon
> +    then:
> +      required:
> +        - '#clock-cells'
> +        - syna,gbl-syscon
> +    else:
> +      properties:
> +        syna,gbl-syscon: false
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: syna,sl2610-avio-syscon
> +    then:
> +      properties:
> +        '#clock-cells': false

[Severity: Low]
Should these dissimilar system controller blocks be split into separate
binding schemas instead of combining them with three per-compatible
if-then-else blocks in allOf?

Only the SoC and MCU blocks provide resets and pin mux subnodes, only the
CPU block uses syna,gbl-syscon, and the AVIO block exposes none of these
providers.  Splitting the schema by block role would avoid toggling most
properties and patternProperties per compatible.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=5

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 03/13] pinctrl: berlin: enable module build support
  2026-11-15 10:23 ` [PATCH v2 03/13] pinctrl: berlin: enable module build support Jisheng Zhang
@ 2026-11-15 10:58   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 10:58 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] pinctrl: berlin: PINCTRL_BERLIN remains bool and built via
  obj-y
--

commit 74a8c9f28b8b05de9543f2486bac3805aa5dc526
Author: Jisheng Zhang <jszhang@kernel.org>

pinctrl: berlin: enable module build support

This commit converts allocations in the Berlin pinctrl core to devm APIs,
exports the probe helpers, and adds module metadata to support building the
driver as a module.

> diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c
> index 8a612ce2d1d36..a0ae75b1d705d 100644
> --- a/drivers/pinctrl/berlin/berlin.c
> +++ b/drivers/pinctrl/berlin/berlin.c

[ ... ]

> @@ -340,3 +337,7 @@ int berlin_pinctrl_probe(struct platform_device *pdev,
>  
>  	return berlin_pinctrl_probe_regmap(pdev, desc, regmap);
>  }
> +EXPORT_SYMBOL_GPL(berlin_pinctrl_probe);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("pinctrl library for Synaptics SoCs");

[Severity: Medium]
Can berlin.c actually be built as a loadable module when
drivers/pinctrl/berlin/Kconfig still defines the symbol as bool and
drivers/pinctrl/berlin/Makefile builds berlin.o with obj-y?

drivers/pinctrl/berlin/Kconfig:
	config PINCTRL_BERLIN
		bool

drivers/pinctrl/berlin/Makefile:
	obj-y					+= berlin.o

Even when a downstream SoC pinctrl driver is configured as a module,
selecting this symbol forces berlin.o into vmlinux instead of building a
loadable module for vendor_dlkm.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=3

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 04/13] pinctrl: berlin: add optional pinconf support
  2026-11-15 10:23 ` [PATCH v2 04/13] pinctrl: berlin: add optional pinconf support Jisheng Zhang
@ 2026-11-15 11:01   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 11:01 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [Medium] pinctrl: berlin: memory leak on error in
  berlin_pinctrl_dt_node_to_map()
- [Medium] pinctrl: berlin: wrong errno -EOPNOTSUPP in
  berlin_pinconf_group_get()
- [Low] pinctrl: berlin: map over-allocation in
  berlin_pinctrl_dt_node_to_map()
- [Low] pinctrl: berlin: berlin_pinconf_group_get() fails when slew rate
  is 0
--

commit 8d9a060e7649872ae247085353d00ffa248ae051
Author: Jisheng Zhang <jszhang@kernel.org>

pinctrl: berlin: add optional pinconf support

This commit adds generic pin configuration support (bias, drive strength,
input enable, Schmitt trigger, and slew rate) to the Berlin pinctrl driver
for 8-bit and 10-bit group configuration registers.

> diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c
> index a0ae75b1d705d..0edf9d5a2a7b7 100644
> --- a/drivers/pinctrl/berlin/berlin.c
> +++ b/drivers/pinctrl/berlin/berlin.c
[ ... ]
> @@ -75,11 +95,19 @@ static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
>  		return -EINVAL;
>  	}
>  
> +	ret = pinconf_generic_parse_dt_config(node, pctrl_dev, &configs,
> +					      &num_configs);
> +	if (ret < 0) {
> +		dev_err(pctrl->dev, "%s: could not parse node property\n",
> +			node->name);
> +		return ret;
> +	}
> +
>  	ret = pinctrl_utils_reserve_map(pctrl_dev, map, &reserved_maps,
> -					num_maps, ngroups);
> +					num_maps, ngroups * (num_configs + 1));

[Severity: Low]
Does this over-allocate *map when num_configs > 1?
pinctrl_utils_add_map_configs() packs all num_configs entries for a group
into a single PIN_MAP_TYPE_CONFIGS_GROUP map slot, so each group uses at
most two map entries (ngroups * (!!num_configs + 1) in total), leaving
ngroups * (num_configs - 1) reserved entries unused.

>  	if (ret) {
>  		dev_err(pctrl->dev, "can't reserve map: %d\n", ret);
> -		return ret;
> +		goto exit;
>  	}
>  
>  	of_property_for_each_string(node, "groups", prop, group_name) {
> @@ -88,11 +116,22 @@ static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
>  						function_name);
>  		if (ret) {
>  			dev_err(pctrl->dev, "can't add map: %d\n", ret);
> -			return ret;
> +			goto exit;
> +		}
> +
> +		if (num_configs) {
> +			ret = pinctrl_utils_add_map_configs(pctrl_dev, map,
> +					&reserved_maps, num_maps, group_name,
> +					configs, num_configs,
> +					PIN_MAP_TYPE_CONFIGS_GROUP);
> +			if (ret < 0)
> +				goto exit;
>  		}
>  	}
>  
> -	return 0;
> +exit:
> +	kfree(configs);
> +	return ret;
>  }

[Severity: Medium]
Does the error path leak *map and any per-group config arrays already
duplicated by pinctrl_utils_add_map_configs()?

When ops->dt_node_to_map() returns a negative error code, the caller
dt_to_map_one_config() in drivers/pinctrl/devicetree.c returns immediately
without freeing the partially constructed map.  If
pinctrl_utils_add_map_mux() or pinctrl_utils_add_map_configs() fails in the
loop after pinctrl_utils_reserve_map() allocated *map, jumping to exit only
frees the temporary configs array and leaks *map along with any configs
duplicated for earlier groups.  Calling pinctrl_utils_free_map(pctrl_dev,
*map, *num_maps) when ret < 0 would clean these up.

> @@ -177,6 +216,190 @@ static const struct pinmux_ops berlin_pinmux_ops = {
>  	.set_mux		= &berlin_pinmux_set,
>  };
>  
> +static int berlin_pinconf_group_get(struct pinctrl_dev *pctrl_dev,
> +				    unsigned int group, unsigned long *configs)
> +{
> +	enum pin_config_param param = pinconf_to_config_param(*configs);
> +	struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
> +	const struct berlin_desc_group *group_desc = pctrl->desc->groups + group;
> +	bool enabled;
> +	u32 val;
> +	int ret;
> +	u8 conf_bits = group_desc->conf_bits;
> +
> +	if (!conf_bits)
> +		return -EOPNOTSUPP;
[ ... ]
> +	case PIN_CONFIG_SLEW_RATE:
> +		if (conf_bits == 10)
> +			enabled = val & PINCFG_SL_10BIT;
> +		else
> +			enabled = val & PINCFG_SL_8BIT;
> +		val = enabled ? 1 : 0;
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	*configs = pinconf_to_config_packed(param, val);
> +	return enabled ? 0 : -EINVAL;
> +}

[Severity: Low]
Does querying PIN_CONFIG_SLEW_RATE fail with -EINVAL whenever the slew rate
bit is 0?

berlin_pinconf_group_set() accepts 0 as a valid slew-rate argument to clear
PINCFG_SL_10BIT or PINCFG_SL_8BIT, but berlin_pinconf_group_get() sets
enabled from that bit and returns -EINVAL when enabled is false, so a slew
rate of 0 cannot be read back (for example via debugfs pinconf-groups).
Setting enabled = true as in the PIN_CONFIG_DRIVE_STRENGTH case would allow
both 0 and 1 to be reported.

> +
> +static int berlin_pinconf_group_set(struct pinctrl_dev *pctrl_dev,
> +				    unsigned int group, unsigned long *configs,
> +				    unsigned int nconfigs)
> +{
> +	struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
> +	const struct berlin_desc_group *group_desc = pctrl->desc->groups + group;
> +	u8 conf_bits = group_desc->conf_bits;
> +	u32 mask = 0, val = 0;
> +	int i;
> +
> +	if (!conf_bits)
> +		return -EOPNOTSUPP;
[ ... ]
> +		default:
> +			return -EOPNOTSUPP;
> +		}
> +	}

[Severity: Medium]
Should berlin_pinconf_group_get() and berlin_pinconf_group_set() return
-ENOTSUPP instead of -EOPNOTSUPP when !conf_bits or when param is not
supported?

With .is_generic = true, reading debugfs pinconf-groups calls
pinconf_generic_dump_one(), which queries every generic parameter in
conf_items[] and only treats -EINVAL and -ENOTSUPP as legal responses:

drivers/pinctrl/pinconf-generic.c:pinconf_generic_dump_one() {
	...
		ret = pin_config_group_get(dev_name(pctldev->dev),
					   pindesc->name, &config);
		/* These are legal errors */
		if (ret == -EINVAL || ret == -ENOTSUPP)
			continue;
		if (ret) {
			seq_printf(s, "ERROR READING CONFIG SETTING %d ", i);
			continue;
		}
	...
}

Returning -EOPNOTSUPP causes debugfs pinconf-groups to print "ERROR READING
CONFIG SETTING" for every unsupported parameter and for any group with
conf_bits == 0.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=4

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 10/13] clk: berlin: add Synaptics SL2610 clocks and PLLs
  2026-11-15 10:23 ` [PATCH v2 10/13] clk: berlin: add Synaptics SL2610 clocks and PLLs Jisheng Zhang
@ 2026-11-15 11:04   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 11:04 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [Medium] clk: berlin: dereference of dev before NULL check in
  sl2610_pll_register()
- [Medium] clk: berlin: irq lock inversion on sl_sysmgr_gateclk_lock via
  sl2610_sysmgr_clk_setup()
- [Low] clk: berlin: fix apbuart3clk and apbi2c1clk typos in
  sl2610_gates
- [Low] clk: berlin: missing OF and HAS_IOMEM dependencies on SL2610_PLL
- [Low] clk: berlin: unused SL2610_APLL macro and struct forward
  declarations
--

commit 9456f61cc7fffcd42790e27e9671ad341c8cf8cd
Author: Jisheng Zhang <jszhang@kernel.org>

clk: berlin: add Synaptics SL2610 clocks and PLLs

This commit adds clock and PLL drivers for the Synaptics SL2610 SoC,
registering the SoC, CPU, AVIO, and MCU clocks.

> diff --git a/drivers/clk/berlin/Kconfig b/drivers/clk/berlin/Kconfig
> index 8f71d4c7a478b..be7e47e0ff523 100644
> --- a/drivers/clk/berlin/Kconfig
> +++ b/drivers/clk/berlin/Kconfig
> @@ -5,3 +5,30 @@ config SL_COMMON_CLK
>  
>  config SL_SYSMGR_CLK
>  	bool
> +
> +config SL2610_PLL
> +	tristate "Synaptics SL2610 PLL Driver"
> +	depends on ARCH_BERLIN || COMPILE_TEST
> +	default n
> +	help
> +	  Support the integer and fractional PLL outputs used by the SoC,
> +	  CPU and audio clock controllers on Synaptics SL2610 SoCs.
> +
> +	  To compile this driver as a module, choose M here. The module will
> +	  be called sl2610-pll.
> +
> +config SL2610_CLK
> +	tristate "Synaptics SL2610 Clock Driver"
> +	depends on ARCH_BERLIN || COMPILE_TEST
> +	depends on OF && HAS_IOMEM

[Severity: Low]
Should SL2610_PLL also depend on OF && HAS_IOMEM like SL2610_CLK?
sl2610-pll.c calls readl_relaxed() and of_clk_get().

Also, both symbols allow COMPILE_TEST when ARCH_BERLIN=n, but
drivers/clk/Makefile only descends into berlin/ for CONFIG_ARCH_BERLIN, so
neither driver is built under COMPILE_TEST=y with ARCH_BERLIN=n.

> diff --git a/drivers/clk/berlin/clk-sl2610.c b/drivers/clk/berlin/clk-sl2610.c
> new file mode 100644
> index 0000000000000..b51d3523028de
> --- /dev/null
> +++ b/drivers/clk/berlin/clk-sl2610.c

[ ... ]

> +static const struct sl_gateclk_desc sl2610_gates[] = {
> +	{ "usb0coreclk",	"perifsysclk",	CLK_USB0CORE,		0 },
> +	{ "sdiosysclk",		"perifsysclk",	CLK_SDIOSYS,		1 },
> +	{ "emmcsysclk",		"perifsysclk",	CLK_EMMCSYS,		2 },
> +	{ "gpuaxiclk",		"hpcclk",	CLK_GPUAXI,		3 },
> +	{ "gethrgmiisysclk",	"perifsysclk",	CLK_GETHRGMIISYS,	4 },
> +	{ "sdio1sysclk",	"perifsysclk",	CLK_SDIO1SYS,		5 },
> +	{ "usb1coreclk",	"perifsysclk",	CLK_USB1CORE,		6 },
> +	{ "gethrgmii1sysclk",	"perifsysclk",	CLK_GETHRGMII1SYS,	7 },
> +	{ "usb0phyrefclk",	"perifsysclk",	CLK_USB0PHYREF,		8 },
> +	{ "usb1phyrefclk",	"perifsysclk",	CLK_USB1PHYREF,		9 },
> +	{ "apbuart0clk",	"apbcoreclk",	CLK_APBUART0,		10 },
> +	{ "apbuart1clk",	"apbcoreclk",	CLK_APBUART1,		11 },
> +	{ "apbuart2clk",	"apbcoreclk",	CLK_APBUART2,		12 },
> +	{ "apbuart3lck",	"apbcoreclk",	CLK_APBUART3,		13 },
> +	{ "apbi2c0clk",		"apbcoreclk",	CLK_APBI2C0,		14 },
> +	{ "apbi2c1lck",		"apbcoreclk",	CLK_APBI2C1,		15 },

[Severity: Low]
Are "apbuart3lck" and "apbi2c1lck" typos for "apbuart3clk" and
"apbi2c1clk"?  Every other entry in sl2610_gates[] ends with "clk", so
these two clocks are registered under misspelled names in clk_summary and
any lookup by name.

[ ... ]

> +static int sl2610_sysmgr_clk_setup(struct platform_device *pdev)
> +{
> +	return sl_sysmgr_clk_setup(pdev, sl2610_sysmgr_fixeds, ARRAY_SIZE(sl2610_sysmgr_fixeds),
> +				   sl2610_sysmgr_gates, ARRAY_SIZE(sl2610_sysmgr_gates),
> +				   CLK_GATE_CTRL0,
> +				   sl2610_sysmgr_clks, ARRAY_SIZE(sl2610_sysmgr_clks));
> +}

[Severity: Medium]
Can registering the MCU gate clocks via sl_sysmgr_clk_setup() cause an IRQ
lock inversion or deadlock on sl_sysmgr_gateclk_lock?

In commit "clk: berlin: add Synaptics clock controller helpers",
sl_sysmgr_gateclk_enable() and sl_sysmgr_gateclk_is_enabled() acquire
sl_sysmgr_gateclk_lock with guard(spinlock) instead of
guard(spinlock_irqsave):

drivers/clk/berlin/sl-sysmgr-clk.c:sl_sysmgr_gateclk_is_enabled() {
	struct sl_sysmgr_gateclk *gclk = to_sl_sysmgr_gateclk(hw);
	u32 reg;

	guard(spinlock)(&sl_sysmgr_gateclk_lock);
	reg = readl_relaxed(gclk->reg);
    ...
}

clk_enable() holds the CCF enable_lock with interrupts disabled (and may
run in hardirq context) before calling .enable, whereas
clk_summary_show_one() and clk_hw_is_enabled() call .is_enabled from
process context without enable_lock and with interrupts enabled:

CPU0                              CPU1
----                              ----
clk_enable()
  clk_enable_lock()
    spin_lock_irqsave(&enable_lock)
                                  clk_summary_show_one()
                                    clk_core_is_enabled()
                                      sl_sysmgr_gateclk_is_enabled()
                                        spin_lock(&sl_sysmgr_gateclk_lock)
  sl_sysmgr_gateclk_enable()
    spin_lock(&sl_sysmgr_gateclk_lock)
                                        <hardirq>
                                          clk_enable()
                                            clk_enable_lock()
                                              spin_lock_irqsave(&enable_lock)

 *** DEADLOCK ***

A single-CPU deadlock also occurs if the interrupt on the same CPU calls
clk_enable() on an MCU gate clock while sl_sysmgr_gateclk_is_enabled()
holds sl_sysmgr_gateclk_lock.  Using guard(spinlock_irqsave) (or reading
gclk->reg locklessly in sl_sysmgr_gateclk_is_enabled() as sl_clk_is_enabled()
does) avoids this.

> diff --git a/drivers/clk/berlin/sl2610-pll.c b/drivers/clk/berlin/sl2610-pll.c
> new file mode 100644
> index 0000000000000..62c5d2d19c362
> --- /dev/null
> +++ b/drivers/clk/berlin/sl2610-pll.c

[ ... ]

> +#define CTRLG			0x18
> +#define DIVQF_MASK		GENMASK(2, 0)
> +
> +#define SL2610_APLL
> +struct sl2610_pll {
> +	void __iomem *ctrl;
> +	struct clk_hw pllout;
> +	struct clk_hw plloutf;
> +};

[ ... ]

> +int sl2610_pll_register(struct device *dev, void __iomem *ctrl,
> +			const char *out, const char *outf)
> +{
> +	struct device_node *np = dev->parent->of_node;
> +	struct clk_parent_data parent = {};
> +	struct clk_init_data init = {};
> +	struct sl2610_pll *pll;
> +	struct clk *input;
> +	int ret;
> +
> +	if (!dev || !ctrl || !out || !outf)
> +		return -EINVAL;

[Severity: Medium]
Does sl2610_pll_register() dereference dev and dev->parent before the !dev
check?  If dev or dev->parent is NULL, initializing np at the top of the
function causes a NULL pointer dereference instead of returning -EINVAL.
sl2610_soc_clk_setup(), sl2610_cpu_clk_setup(), and sl2610_aio_clk_setup()
in drivers/clk/berlin/clk-sl2610.c also dereference dev->parent->of_node
without checking dev->parent.

> diff --git a/drivers/clk/berlin/sl2610-pll.h b/drivers/clk/berlin/sl2610-pll.h
> new file mode 100644
> index 0000000000000..b61a93b28610d
> --- /dev/null
> +++ b/drivers/clk/berlin/sl2610-pll.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __SL2610_PLL_H
> +#define __SL2610_PLL_H
> +
> +#include <linux/io.h>
> +
> +struct clk_hw_onecell_data;
> +struct device;
> +struct device_node;

[Severity: Low]
This isn't a bug, but struct clk_hw_onecell_data and struct device_node in
sl2610-pll.h and the empty SL2610_APLL macro in sl2610-pll.c are unused and
can be dropped.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=10

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 09/13] clk: berlin: add Synaptics clock controller helpers
  2026-11-15 10:23 ` [PATCH v2 09/13] clk: berlin: add Synaptics clock controller helpers Jisheng Zhang
@ 2026-11-15 11:05   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 11:05 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [High] clk: berlin: non-irqsave spinlock in sl_sysmgr_gateclk_ops
- [Medium] clk: berlin: uninitialized clk_init_data in sl-sysmgr-clk.c
- [Medium] clk: berlin: sl_sysmgr_clk_setup() ignores descriptor flags
- [Medium] clk: berlin: missing .disable callbacks and duplicated gate
  clock in sl-sysmgr-clk
- [Low] clk: berlin: non-self-contained header sl-sysmgr-clk.h and
  unused macros
--

commit a40ea8003017371f6f9b098c53eae5c758e872e4
Author: Jisheng Zhang <jszhang@kernel.org>

clk: berlin: add Synaptics clock controller helpers

This commit adds configurable divider and gate clock helpers for Synaptics
system controllers along with an MCU system manager clock setup helper.

> diff --git a/drivers/clk/berlin/sl-sysmgr-clk.c b/drivers/clk/berlin/sl-sysmgr-clk.c
> new file mode 100644
> index 0000000000000..f3cf921fc3c1a
> --- /dev/null
> +++ b/drivers/clk/berlin/sl-sysmgr-clk.c
> @@ -0,0 +1,241 @@

[ ... ]

> +#include <linux/platform_device.h>
> +#include <linux/version.h>
> +
> +#include "sl-sysmgr-clk.h"
> +
> +#define CLK_EN		BIT(0)
> +#define DIV_CHNG_EN	BIT(1)

[ ... ]

> +static int sl_sysmgr_gateclk_enable(struct clk_hw *hw)
> +{
> +	u32 val;
> +	struct sl_sysmgr_gateclk *clk = to_sl_sysmgr_gateclk(hw);
> +
> +	guard(spinlock)(&sl_sysmgr_gateclk_lock);
> +
> +	val = readl_relaxed(clk->base);
> +	if (!(val & BIT(clk->bit_idx))) {
> +		val |= BIT(clk->bit_idx);
> +		writel_relaxed(val, clk->base);
> +	}
> +
> +	return 0;
> +}
> +
> +static int sl_sysmgr_gateclk_is_enabled(struct clk_hw *hw)
> +{
> +	u32 val;
> +	struct sl_sysmgr_gateclk *clk = to_sl_sysmgr_gateclk(hw);
> +
> +	guard(spinlock)(&sl_sysmgr_gateclk_lock);
> +
> +	val = readl_relaxed(clk->base);
> +	val &= BIT(clk->bit_idx);
> +
> +	return val ? 1 : 0;
> +}

[Severity: High]
Can taking sl_sysmgr_gateclk_lock with guard(spinlock) instead of
spinlock_irqsave deadlock?

clk_core_is_enabled() calls .is_enabled from process context without
holding enable_lock and with local interrupts enabled (for example via
clk_summary_show_one() or __clk_is_enabled()), while clk_enable() can be
called from hardirq context:

clk_summary_show_one()
  ...
    sl_sysmgr_gateclk_is_enabled()
      spin_lock(&sl_sysmgr_gateclk_lock)
      <hardirq>
        clk_enable()
          ...
            sl_sysmgr_gateclk_enable()
              spin_lock(&sl_sysmgr_gateclk_lock)  <-- spins forever

sl_sysmgr_gateclk_enable() needs guard(spinlock_irqsave), while
sl_sysmgr_gateclk_is_enabled() only performs a single readl_relaxed() and
does not need the lock.

> +static const struct clk_ops sl_sysmgr_gateclk_ops = {
> +	.enable		= sl_sysmgr_gateclk_enable,
> +	.is_enabled	= sl_sysmgr_gateclk_is_enabled,
> +};
> +
> +static int
> +sl_sysmgr_gateclk_register(struct device *dev, struct sl_sysmgr_gateclk *gclk,
> +			   const char *name, const char *parent_names,
> +			   u8 bit_idx, void __iomem *base)
> +{
> +	struct clk_init_data init;
> +
> +	init.name = name;
> +	init.ops = &sl_sysmgr_gateclk_ops;
> +	init.parent_names = &parent_names;
> +	init.num_parents = 1;
> +	init.flags = 0;

[ ... ]

> +static const struct clk_ops sl_sysmgr_clk_ops = {
> +	.recalc_rate	= sl_sysmgr_clk_recalc_rate,
> +	.enable		= sl_sysmgr_clk_enable,
> +	.is_enabled	= sl_sysmgr_clk_is_enabled,
> +};

[Severity: Medium]
Should sl_sysmgr_gateclk_ops and sl_sysmgr_clk_ops implement .disable
callbacks?

Without .disable, consumer calls to clk_disable() and late boot's
clk_disable_unused() cannot gate these clocks in hardware, and
clk_is_enabled_when_prepared() treats them as enabled by .prepare even
though .prepare is not implemented.  In addition, struct sl_sysmgr_gateclk
and struct sl_sysmgr_gateclk_desc duplicate devm_clk_hw_register_gate()
and struct sl_gateclk_desc in drivers/clk/berlin/sl-clk.h.

> +static int
> +sl_sysmgr_clk_register(struct device *dev, struct sl_sysmgr_clk *sclk,
> +		       const char *name, const char *parent_names,
> +		       u8 div_bits, void __iomem *base)
> +{
> +	struct clk_init_data init;
> +
> +	init.name = name;
> +	init.ops = &sl_sysmgr_clk_ops;
> +	init.parent_names = &parent_names;
> +	init.num_parents = 1;
> +	init.flags = 0;

[Severity: Medium]
Does leaving struct clk_init_data init uninitialized on the stack in
sl_sysmgr_gateclk_register() and sl_sysmgr_clk_register() pass garbage
init.parent_data and init.parent_hws pointers into devm_clk_hw_register()?

clk_core_populate_parent_map() reads init->parent_hws and
init->parent_data unconditionally when registering the clock.

[ ... ]

> +	for (i = 0; i < gclk_n; i++) {
> +		ret = sl_sysmgr_gateclk_register(&pdev->dev, &priv->gclks[i],
> +						 gdescs[i].name, gdescs[i].parent_name,
> +						 gdescs[i].bit_idx, base + gclk_offset);
> +		if (ret)
> +			return ret;
> +
> +		id = gdescs[i].id;
> +		clk_data->hws[id] = &priv->gclks[i].hw;
> +	}
> +
> +	for (i = 0; i < clk_n; i++) {
> +		ret = sl_sysmgr_clk_register(&pdev->dev, &priv->clks[i],
> +					     descs[i].name, descs[i].parent_name,
> +					     descs[i].div_bits, base + descs[i].offset);
> +		if (ret)
> +			return ret;

[Severity: Medium]
Does sl_sysmgr_clk_setup() drop the flags field from gdescs[i] and
descs[i]?

struct sl_sysmgr_gateclk_desc and struct sl_sysmgr_clk_desc both define an
unsigned long flags member, but sl_sysmgr_clk_setup() never passes them to
sl_sysmgr_gateclk_register() or sl_sysmgr_clk_register(), which hardcode
init.flags = 0 and ignore flags such as CLK_IS_CRITICAL or
CLK_IGNORE_UNUSED.

[ ... ]

> diff --git a/drivers/clk/berlin/sl-sysmgr-clk.h b/drivers/clk/berlin/sl-sysmgr-clk.h
> new file mode 100644
> index 0000000000000..5ccf388bcccbd
> --- /dev/null
> +++ b/drivers/clk/berlin/sl-sysmgr-clk.h
> @@ -0,0 +1,44 @@

[ ... ]

> +#ifndef __SL_SYSMGR_CLK_H
> +#define __SL_SYSMGR_CLK_H
> +
> +struct sl_sysmgr_clk_desc {
> +	const char	*name;
> +	const char	*parent_name;
> +	u32		id;
> +	u32		offset;
> +	u8		div_bits;
> +	unsigned long	flags;
> +};

[ ... ]

> +int sl_sysmgr_clk_setup(struct platform_device *pdev,
> +			const struct sl_sysmgr_fixedclk_desc *fdescs,
> +			int fclk_n,
> +			const struct sl_sysmgr_gateclk_desc *gdescs,
> +			int gclk_n,
> +			u32 gclk_offset,
> +			const struct sl_sysmgr_clk_desc *descs,
> +			int clk_n);
> +
> +#endif

[Severity: Low]
Does sl-sysmgr-clk.h need #include <linux/types.h> and a forward
declaration of struct platform_device so it is self-contained when
included before other headers?  Also, <linux/version.h> and DIV_CHNG_EN in
sl-sysmgr-clk.c are unused, and sl-clk.h uses u32 and u8 without directly
including <linux/types.h>.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=9

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 13/13] arm64: dts: synaptics: add SL2610 family RDK boards
  2026-11-15 10:23 ` [PATCH v2 13/13] arm64: dts: synaptics: add SL2610 family RDK boards Jisheng Zhang
@ 2026-11-15 11:05   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 11:05 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Low] arm64: dts: synaptics: deprecated cpu0-supply used in
  sl261x-rdk-common.dtsi
- [Low] arm64: dts: synaptics: underscore in soc_i2c0-pmux node name
- [Low] arm64: dts: synaptics: unused linux-event-codes.h include in
  sl261x-rdk-common.dtsi
--

commit f1ba81aeb15547b6a1942dc7df6778c88410e949
Author: Jisheng Zhang <jszhang@kernel.org>

arm64: dts: synaptics: add SL2610 family RDK boards

This commit adds device tree files for the Synaptics SL2611, SL2613,
SL2615, SL2617, and SL2619 reference development kits along with a shared
common dtsi.

> diff --git a/arch/arm64/boot/dts/synaptics/sl261x-rdk-common.dtsi b/arch/arm64/boot/dts/synaptics/sl261x-rdk-common.dtsi
> new file mode 100644
> index 0000000000000..78a9b28fdf99e
> --- /dev/null
> +++ b/arch/arm64/boot/dts/synaptics/sl261x-rdk-common.dtsi
> @@ -0,0 +1,135 @@
> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +/*
> + * Copyright (C) 2025 Synaptics Incorporated
> + *
> + * Author: Jisheng Zhang <jszhang@kernel.org>
> + */
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/linux-event-codes.h>

[Severity: Low]
Is the dt-bindings/input/linux-event-codes.h include needed here? Neither
sl261x-rdk-common.dtsi nor the board dts files that include it define any
input nodes or reference event code macros.

[ ... ]

> +	cpus {
> +		cpu@0 {
> +			cpu0-supply = <&vcore>;
> +		};
> +	};

[Severity: Low]
Should cpu@0 use cpu-supply instead of cpu0-supply?
Documentation/devicetree/bindings/arm/cpus.yaml marks cpu0-supply as
deprecated in favor of cpu-supply, and the dual-core SL2615, SL2617, and
SL2619 variants also define cpu1: cpu@100.

[ ... ]

> +&pinctrl {
> +	soc_i2c0_pmux: soc_i2c0-pmux {
> +		groups = "GPIO23", "GPIO24";
> +		function = "tw2";
> +		drive-strength = <7>;
> +	};
> +};

[Severity: Low]
Should the node name soc_i2c0-pmux use a hyphen instead of an underscore
(for example, soc-i2c0-pmux)? Using an underscore in a devicetree node
name triggers a dtc node_name_chars_strict warning when building with W=2.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=13

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 07/13] reset: add Synaptics SL2610 reset controller support
  2026-11-15 10:23 ` [PATCH v2 07/13] reset: add Synaptics SL2610 reset " Jisheng Zhang
@ 2026-11-15 11:12   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 11:12 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] reset: sl2610: wrong errno in sl2610_reset_assert() and
  deassert()
--

commit fd9868407ed20a422bf28d62579da17aa23dc9fc
Author: Jisheng Zhang <jszhang@kernel.org>

reset: add Synaptics SL2610 reset controller support

This commit adds a reset controller driver for the SoC and MCU system
control blocks on Synaptics SL2610 SoCs, supporting both pulse and sticky
reset lines.

> diff --git a/drivers/reset/reset-sl2610.c b/drivers/reset/reset-sl2610.c
> new file mode 100644
> index 0000000000000..1ca58d5a3e713
> --- /dev/null
> +++ b/drivers/reset/reset-sl2610.c
[ ... ]
> +static int sl2610_reset_assert(struct reset_controller_dev *rcdev,
> +			       unsigned long id)
> +{
> +	struct sl2610_reset_priv *priv = to_sl2610_reset_priv(rcdev);
> +	const struct sl2610_reset_cfg *cfg = &priv->cfgs[id];
> +
> +	if (!cfg->sticky)
> +		return -EINVAL;
> +
> +	return regmap_clear_bits(priv->regmap, cfg->reg, cfg->bit);
> +}
> +
> +static int sl2610_reset_deassert(struct reset_controller_dev *rcdev,
> +				 unsigned long id)
> +{
> +	struct sl2610_reset_priv *priv = to_sl2610_reset_priv(rcdev);
> +	const struct sl2610_reset_cfg *cfg = &priv->cfgs[id];
> +
> +	if (!cfg->sticky)
> +		return -EINVAL;
> +
> +	return regmap_set_bits(priv->regmap, cfg->reg, cfg->bit);
> +}

[Severity: Medium]
Should sl2610_reset_assert() and sl2610_reset_deassert() return -ENOTSUPP
(or 0 in sl2610_reset_deassert()) instead of -EINVAL when !cfg->sticky?

In drivers/reset/core.c, reset_control_deassert() treats self-deasserting
pulse reset lines as deasserted by default when .deassert() is not
implemented, and documents that .deassert() should return -ENOTSUPP when
deassertion cannot be guaranteed:

drivers/reset/core.c:reset_control_deassert() {
	...
	/*
	 * If the reset controller does not implement .deassert(), we assume
	 * that it handles self-deasserting reset lines via .reset(). In that
	 * case, the reset lines are deasserted by default. If that is not the
	 * case, the reset controller driver should implement .deassert() and
	 * return -ENOTSUPP.
	 */
	if (!rcdev->ops->deassert)
		return 0;
	...
}

Because this controller implements .assert() and .deassert() for its
sticky lines, returning -EINVAL for the 22 pulse reset lines in
sl2610_reset_cfgs[] causes consumer drivers that call
reset_control_deassert() during probe (such as 8250_dw) to fail probe, and
prevents consumers such as stmmac_dvr_probe() from checking for -ENOTSUPP
on reset_control_assert() and falling back to reset_control_reset().

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=7

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 12/13] arm64: dts: synaptics: add SL2610 family SoCs
  2026-11-15 10:23 ` [PATCH v2 12/13] arm64: dts: synaptics: add SL2610 family SoCs Jisheng Zhang
@ 2026-11-15 11:13   ` sashiko-bot
  0 siblings, 0 replies; 24+ messages in thread
From: sashiko-bot @ 2026-11-15 11:13 UTC (permalink / raw)
  To: Jisheng Zhang; +Cc: devicetree, linux-clk, linux-gpio, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Low] arm64: dts: synaptics: missing root compatible property in
  sl2619.dtsi
- [Low] arm64: dts: synaptics: duplicated cpu1 and pmu nodes in
  sl2617/sl2619.dtsi
- [Low] arm64: dts: synaptics: optee node placed under root instead of
  /firmware
--

commit 9dec2dc5b8adc9799e77b0f1baf814fa359dd8c4
Author: Jisheng Zhang <jszhang@kernel.org>

arm64: dts: synaptics: add SL2610 family SoCs

This commit adds devicetree files for the Synaptics SL2610 family SoCs
(SL2611, SL2613, SL2615, SL2617, and SL2619), describing CPUs, GIC,
system controllers, and serial, I2C, I3C, SPI, and GPIO peripherals.

> diff --git a/arch/arm64/boot/dts/synaptics/sl2611.dtsi b/arch/arm64/boot/dts/synaptics/sl2611.dtsi
> new file mode 100644
> index 0000000000000..663fe6034ba05
> --- /dev/null
> +++ b/arch/arm64/boot/dts/synaptics/sl2611.dtsi
> @@ -0,0 +1,457 @@
> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +/*
> + * Copyright (C) 2024 Synaptics Incorporated
> + *
> + * Author: Jisheng Zhang <jszhang@kernel.org>
> + */
> +
> +#include <dt-bindings/clock/syna,sl2610.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/reset/syna,sl2610-reset.h>
> +
> +/ {
> +	compatible = "syna,sl2611";
> +	interrupt-parent = <&gic>;
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +
> +	psci {
> +		compatible = "arm,psci-1.0";
> +		method = "smc";
> +	};
> +
> +	optee {
> +		compatible = "linaro,optee-tz";
> +		method = "smc";
> +	};

[Severity: Low]
Should the optee node be placed under a /firmware container node?

Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.yaml
places optee under /firmware, which of_platform_default_populate_init()
looks up directly via of_find_node_by_path("/firmware") before populating
the rest of the tree.

[ ... ]

> diff --git a/arch/arm64/boot/dts/synaptics/sl2617.dtsi b/arch/arm64/boot/dts/synaptics/sl2617.dtsi
> new file mode 100644
> index 0000000000000..a0de686d1fae5
> --- /dev/null
> +++ b/arch/arm64/boot/dts/synaptics/sl2617.dtsi
> @@ -0,0 +1,46 @@
> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +/*
> + * Copyright (C) 2025 Synaptics Incorporated
> + *
> + * Author: Jisheng Zhang <jszhang@kernel.org>
> + */
> +
> +#include "sl2613.dtsi"
> +
> +/ {
> +	compatible = "syna,sl2617";
> +
> +	cpus {
> +		cpu1: cpu@100 {

[Severity: Low]
This isn't a bug, but sl2617.dtsi and sl2619.dtsi duplicate the entire
cpu1 and pmu definitions from sl2615.dtsi.  Could they include
sl2615.dtsi and override the root compatible property, the same way
sl2613.dtsi includes sl2611.dtsi?

[ ... ]

> diff --git a/arch/arm64/boot/dts/synaptics/sl2619.dtsi b/arch/arm64/boot/dts/synaptics/sl2619.dtsi
> new file mode 100644
> index 0000000000000..96bd58bbed3e1
> --- /dev/null
> +++ b/arch/arm64/boot/dts/synaptics/sl2619.dtsi
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +/*
> + * Copyright (C) 2025 Synaptics Incorporated
> + *
> + * Author: Jisheng Zhang <jszhang@kernel.org>
> + */
> +
> +#include "sl2613.dtsi"
> +
> +/ {
> +	cpus {

[Severity: Low]
Is the root node missing compatible = "syna,sl2619"; here?

Unlike sl2615.dtsi and sl2617.dtsi, sl2619.dtsi does not override the
root compatible property and inherits compatible = "syna,sl2613"; from
sl2613.dtsi.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261115102401.3520-1-jszhang@kernel.org?part=12

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2026-11-15 11:13 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-15 10:23 [PATCH v2 00/13] arm64: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
2026-11-15 10:23 ` [PATCH v2 01/13] arm64: kconfig: let ARCH_BERLIN cover Synaptics arm64 SoCs Jisheng Zhang
2026-11-15 10:23 ` [PATCH v2 02/13] pinctrl: berlin: use u16 instead of u8 for the offset Jisheng Zhang
2026-11-15 10:23 ` [PATCH v2 03/13] pinctrl: berlin: enable module build support Jisheng Zhang
2026-11-15 10:58   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 04/13] pinctrl: berlin: add optional pinconf support Jisheng Zhang
2026-11-15 11:01   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 05/13] dt-bindings: soc: synaptics: add SL2610 system controllers Jisheng Zhang
2026-11-15 10:58   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 06/13] soc: synaptics: add SL2610 system controller support Jisheng Zhang
2026-11-15 10:56   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 07/13] reset: add Synaptics SL2610 reset " Jisheng Zhang
2026-11-15 11:12   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 08/13] pinctrl: berlin: add Synaptics SL2610 pin " Jisheng Zhang
2026-11-15 10:57   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 09/13] clk: berlin: add Synaptics clock controller helpers Jisheng Zhang
2026-11-15 11:05   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 10/13] clk: berlin: add Synaptics SL2610 clocks and PLLs Jisheng Zhang
2026-11-15 11:04   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 11/13] dt-bindings: arm: berlin: add Synaptics SL2610 SoCs and RDK boards Jisheng Zhang
2026-11-15 10:23 ` [PATCH v2 12/13] arm64: dts: synaptics: add SL2610 family SoCs Jisheng Zhang
2026-11-15 11:13   ` sashiko-bot
2026-11-15 10:23 ` [PATCH v2 13/13] arm64: dts: synaptics: add SL2610 family RDK boards Jisheng Zhang
2026-11-15 11:05   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox