* [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* 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
* [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* 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
* [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* 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
* [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* 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
* [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* 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
* [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* 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
* [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* 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
* [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* 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
* [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* 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
* [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 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