Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] soc: ti: Add TDA54 SCM configuration syscon support
@ 2026-10-27  8:36 Moteen Shah
  2026-10-27  8:36 ` [PATCH v2 1/3] dt-bindings: soc: ti: Document the ti,tda54-mcu-scm-conf binding Moteen Shah
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Moteen Shah @ 2026-10-27  8:36 UTC (permalink / raw)
  To: conor+dt, robh, krzk+dt, nm, ssantosh
  Cc: u-kumar1, gehariprasath, m-shah, vigneshr, afd, a-limaye,
	y-abhilashchandra, johan, kees, jm, devicetree, linux-kernel,
	linux-arm-kernel

This series adds support for the TDA54 SCM configuration region in the MCU
domain. The region is shared by several peripherals, so it is exposed as a
syscon regmap for other drivers to look up by phandle.

Patch 1 adds the device tree binding for ti,tda54-mcu-scm-conf.

Patch 2 splits the SoC decode and registration logic out of
k3_chipinfo_probe() into k3_socinfo_register() and exports it. The helper
lets other drivers register SoC information after reading the JTAG ID through
their own access path, and uses devm cleanup for registered SoC devices and
their attributes.

Patch 3 adds the TDA54 SCM configuration driver. It provides proxy-aware
register access with SCM unlock and claim handling, publishes the regmap
through syscon, and registers TDA54 SoC information through the helper from
patch 2. The option defaults to m on ARCH_K3.

Changelog:
Link to V1: https://lore.kernel.org/all/20261019080736.944127-1-m-shah@ti.com/

Changes in v2:
- No changes to the device tree binding patch.
- Use devm-managed allocation for the SoC attributes and revision string in
  k3-socinfo, and simplify the cleanup of the registered SoC device.
- Enable fast_io for the TDA54 SCM configuration regmap.

Moteen Shah (3):
  dt-bindings: soc: ti: Document the ti,tda54-mcu-scm-conf binding
  soc: ti: k3-socinfo: Export SoC registration helper
  soc: ti: Add TDA54 SCM configuration syscon support

 .../soc/ti/ti,tda54-mcu-scm-conf.yaml         |  78 +++++++
 drivers/soc/ti/Kconfig                        |  16 ++
 drivers/soc/ti/Makefile                       |   1 +
 drivers/soc/ti/k3-socinfo.c                   | 121 ++++++----
 drivers/soc/ti/tda54-mcu-sysconf.c            | 217 ++++++++++++++++++
 include/linux/soc/ti/k3-socinfo.h             |  11 +
 6 files changed, 402 insertions(+), 42 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml
 create mode 100644 drivers/soc/ti/tda54-mcu-sysconf.c
 create mode 100644 include/linux/soc/ti/k3-socinfo.h

-- 
2.34.1



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

* [PATCH v2 1/3] dt-bindings: soc: ti: Document the ti,tda54-mcu-scm-conf binding
  2026-10-27  8:36 [PATCH v2 0/3] soc: ti: Add TDA54 SCM configuration syscon support Moteen Shah
@ 2026-10-27  8:36 ` Moteen Shah
  2026-10-28 12:24   ` Krzysztof Kozlowski
  2026-10-27  8:36 ` [PATCH v2 2/3] soc: ti: k3-socinfo: Export SoC registration helper Moteen Shah
  2026-10-27  8:37 ` [PATCH v2 3/3] soc: ti: Add TDA54 SCM configuration syscon support Moteen Shah
  2 siblings, 1 reply; 5+ messages in thread
From: Moteen Shah @ 2026-10-27  8:36 UTC (permalink / raw)
  To: conor+dt, robh, krzk+dt, nm, ssantosh
  Cc: u-kumar1, gehariprasath, m-shah, vigneshr, afd, a-limaye,
	y-abhilashchandra, johan, kees, jm, devicetree, linux-kernel,
	linux-arm-kernel

TDA54's MCU domain exposes a shared scm_conf syscon region that other
peripherals, including chipid, access into rather than owning a
dedicated register window. Rather than a bare fallback entry in the
generic syscon compatible list, give it a dedicated binding
describing the region and the proxy/claim/lock arbitration scheme
that gates write access to a subset of its registers.

Some of the claimable registers are gate clock controls, so also
document the required "#clock-cells" property that lets the node be
referenced directly as a clock provider for those gates. The clock
specifier selects the ePWM time-base gate by instance number.

Co-developed-by: Aniket Limaye <a-limaye@ti.com>
Signed-off-by: Aniket Limaye <a-limaye@ti.com>
Signed-off-by: Moteen Shah <m-shah@ti.com>
---
 .../soc/ti/ti,tda54-mcu-scm-conf.yaml         | 78 +++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml

diff --git a/Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml b/Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml
new file mode 100644
index 0000000000000..111cbb739b5f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/ti/ti,tda54-mcu-scm-conf.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TDA54 SoC MCU Domain System Control Module Configuration registers
+
+maintainers:
+  - Aniket Limaye <a-limaye@ti.com>
+  - Moteen Shah <m-shah@ti.com>
+
+description: |
+  The TDA54 SoC's MCU domain exposes a System Control Module configuration
+  register region (scm_conf) containing miscellaneous control and status
+  registers for MCU domain peripherals, including the JTAGID/device
+  identification registers, boot configuration and status registers, and
+  device feature registers.
+
+  A subset of these registers is write-protected by a proxy/claim scheme:
+  each register is mirrored across 8 proxy regions, and a host must unlock
+  via LOCK_KICK. Any proxy other than proxy-0 must also claim a register
+  through its CLAIM register before writing through that proxy. Proxy-0 is
+  the default access proxy: its claim bits are tied low, so it needs no
+  claim and can write any register that is not claimed by another proxy.
+  For example: Proxy0's CLAIM0 register sits at offset 0x3100, while the
+  same register mirrored at ProxyN sits at N * 0x4000 + 0x3100.
+
+  Each of the 8 proxy regions also has its own fault status and
+  interrupt registers, but a fault can only be handled through proxy-0.
+  Hence, interrupt/fault handling is not described by this binding.
+
+  Some of the claimable registers are gate clock controls (e.g. the
+  ehrpwm_tbclk gates). This node is the clock provider for those gates;
+  writes to them are still routed through the proxy claim scheme described
+  above.
+
+properties:
+  compatible:
+    const: ti,tda54-mcu-scm-conf
+
+  reg:
+    maxItems: 1
+
+  ti,proxy-id:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 7
+    description:
+      Proxy region (0-7) through which this node's clients access
+      claimable registers and their fault status registers.
+
+  "#clock-cells":
+    const: 1
+    description:
+      The cell selects the ePWM time-base clock gate. Values 0 to 12 select
+      ehrpwm_tbclk0 to ehrpwm_tbclk12, i.e. the gate for ePWM instance N is
+      specifier N.
+
+required:
+  - compatible
+  - reg
+  - ti,proxy-id
+  - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+
+  - |
+    scm_conf1: syscon@5e800000 {
+        compatible = "ti,tda54-mcu-scm-conf";
+        reg = <0x5e800000 0x20000>;
+        ti,proxy-id = <0>;
+        #clock-cells = <1>;
+    };
+
+...
-- 
2.34.1



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

* [PATCH v2 2/3] soc: ti: k3-socinfo: Export SoC registration helper
  2026-10-27  8:36 [PATCH v2 0/3] soc: ti: Add TDA54 SCM configuration syscon support Moteen Shah
  2026-10-27  8:36 ` [PATCH v2 1/3] dt-bindings: soc: ti: Document the ti,tda54-mcu-scm-conf binding Moteen Shah
@ 2026-10-27  8:36 ` Moteen Shah
  2026-10-27  8:37 ` [PATCH v2 3/3] soc: ti: Add TDA54 SCM configuration syscon support Moteen Shah
  2 siblings, 0 replies; 5+ messages in thread
From: Moteen Shah @ 2026-10-27  8:36 UTC (permalink / raw)
  To: conor+dt, robh, krzk+dt, nm, ssantosh
  Cc: u-kumar1, gehariprasath, m-shah, vigneshr, afd, a-limaye,
	y-abhilashchandra, johan, kees, jm, devicetree, linux-kernel,
	linux-arm-kernel

The k3-socinfo driver reads the JTAG ID through a dedicated MMIO region and
then decodes it and registers the SoC device.

Newer TI SoCs like TDA54 use a different path for accessing the JTAG ID
register, but the decoding of the JTAG ID into the SoC information remains
the same.

Split the decode and registration part out of k3_chipinfo_probe() into
k3_socinfo_register() and export it, so that other drivers can register the
SoC device once they have read the JTAG ID through their own access path.

Since the helper can now be called from modular drivers, it must not leak
the SoC device when the caller goes away. Tie the registration to the
calling device with a devm action, which unregisters the SoC device on
unbind. The SoC attributes and revision string are allocated with devm too,
so they are freed on unbind as well. Callers need no unregister counterpart
and the helper keeps returning an int.

Signed-off-by: Moteen Shah <m-shah@ti.com>
---
 drivers/soc/ti/k3-socinfo.c       | 119 +++++++++++++++++++-----------
 include/linux/soc/ti/k3-socinfo.h |  11 +++
 2 files changed, 88 insertions(+), 42 deletions(-)
 create mode 100644 include/linux/soc/ti/k3-socinfo.h

diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c
index 48dbef3acceb4..e81d27e03c9d9 100644
--- a/drivers/soc/ti/k3-socinfo.c
+++ b/drivers/soc/ti/k3-socinfo.c
@@ -5,6 +5,8 @@
  * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
  */
 
+#include <linux/device.h>
+#include <linux/export.h>
 #include <linux/mfd/syscon.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/of.h>
@@ -12,6 +14,7 @@
 #include <linux/regmap.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/soc/ti/k3-socinfo.h>
 #include <linux/string.h>
 #include <linux/sys_soc.h>
 
@@ -115,14 +118,14 @@ k3_chipinfo_variant_to_sr(struct device *dev, unsigned int partno,
 	case JTAG_ID_PARTNO_J721E:
 		if (variant >= ARRAY_SIZE(j721e_rev_string_map))
 			goto err_unknown_variant;
-		soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s",
-						   j721e_rev_string_map[variant]);
+		soc_dev_attr->revision = devm_kasprintf(dev, GFP_KERNEL, "SR%s",
+							j721e_rev_string_map[variant]);
 		break;
 	case JTAG_ID_PARTNO_AM62LX:
 		if (variant >= ARRAY_SIZE(am62lx_rev_string_map))
 			goto err_unknown_variant;
-		soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s",
-						   am62lx_rev_string_map[variant]);
+		soc_dev_attr->revision = devm_kasprintf(dev, GFP_KERNEL, "SR%s",
+							am62lx_rev_string_map[variant]);
 		break;
 	case JTAG_ID_PARTNO_AM62PX:
 		/* Check GP_SW1 for silicon revision */
@@ -134,13 +137,13 @@ k3_chipinfo_variant_to_sr(struct device *dev, unsigned int partno,
 				 gpsw_variant);
 			gpsw_variant = 0;
 		}
-		soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s",
-						   am62p_gpsw_rev_string_map[gpsw_variant]);
+		soc_dev_attr->revision = devm_kasprintf(dev, GFP_KERNEL, "SR%s",
+							am62p_gpsw_rev_string_map[gpsw_variant]);
 		break;
 	default:
 		variant++;
-		soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0",
-						   variant);
+		soc_dev_attr->revision = devm_kasprintf(dev, GFP_KERNEL, "SR%x.0",
+							variant);
 	}
 
 	if (!soc_dev_attr->revision)
@@ -152,38 +155,39 @@ k3_chipinfo_variant_to_sr(struct device *dev, unsigned int partno,
 	return -ENODEV;
 }
 
-static const struct regmap_config k3_chipinfo_regmap_cfg = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 4,
+struct k3_socinfo {
+	struct soc_device *soc_dev;
 };
 
-static int k3_chipinfo_probe(struct platform_device *pdev)
+static void k3_socinfo_unregister(void *data)
+{
+	struct k3_socinfo *info = data;
+
+	soc_device_unregister(info->soc_dev);
+}
+
+/**
+ * k3_socinfo_register() - Decode a JTAG ID and register the SoC device
+ * @dev: device on whose behalf the SoC device is registered
+ * @jtag_id: raw JTAG ID register value read by the caller
+ *
+ * The registration is managed by @dev: the SoC device is unregistered and its
+ * attributes are released automatically when @dev is unbound, so callers need
+ * no matching unregister call.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int k3_socinfo_register(struct device *dev, u32 jtag_id)
 {
-	struct device_node *node = pdev->dev.of_node;
+	struct device_node *node;
+	struct k3_socinfo *info;
 	struct soc_device_attribute *soc_dev_attr;
-	struct device *dev = &pdev->dev;
 	struct soc_device *soc_dev;
-	struct regmap *regmap;
-	void __iomem *base;
 	u32 partno_id;
 	u32 variant;
-	u32 jtag_id;
 	u32 mfg;
 	int ret;
 
-	base = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	regmap = devm_regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg);
-	if (IS_ERR(regmap))
-		return PTR_ERR(regmap);
-
-	ret = regmap_read(regmap, CTRLMMR_WKUP_JTAGID_REG, &jtag_id);
-	if (ret < 0)
-		return ret;
-
 	mfg = (jtag_id & CTRLMMR_WKUP_JTAGID_MFG_MASK) >>
 	       CTRLMMR_WKUP_JTAGID_MFG_SHIFT;
 
@@ -198,20 +202,24 @@ static int k3_chipinfo_probe(struct platform_device *pdev)
 	partno_id = (jtag_id & CTRLMMR_WKUP_JTAGID_PARTNO_MASK) >>
 		 CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT;
 
-	soc_dev_attr = kzalloc_obj(*soc_dev_attr);
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL);
 	if (!soc_dev_attr)
 		return -ENOMEM;
 
 	ret = k3_chipinfo_partno_to_names(partno_id, soc_dev_attr);
 	if (ret) {
 		dev_err(dev, "Unknown SoC JTAGID[0x%08X]: %d\n", jtag_id, ret);
-		goto err;
+		return ret;
 	}
 
 	ret = k3_chipinfo_variant_to_sr(dev, partno_id, variant, soc_dev_attr);
 	if (ret) {
 		dev_err(dev, "Unknown SoC SR[0x%08X]: %d\n", jtag_id, ret);
-		goto err;
+		return ret;
 	}
 
 	node = of_find_node_by_path("/");
@@ -219,22 +227,49 @@ static int k3_chipinfo_probe(struct platform_device *pdev)
 	of_node_put(node);
 
 	soc_dev = soc_device_register(soc_dev_attr);
-	if (IS_ERR(soc_dev)) {
-		ret = PTR_ERR(soc_dev);
-		goto err_free_rev;
-	}
+	if (IS_ERR(soc_dev))
+		return PTR_ERR(soc_dev);
+
+	info->soc_dev = soc_dev;
+	ret = devm_add_action_or_reset(dev, k3_socinfo_unregister, info);
+	if (ret)
+		return ret;
 
 	dev_info(dev, "Family:%s rev:%s JTAGID[0x%08x] Detected\n",
 		 soc_dev_attr->family,
 		 soc_dev_attr->revision, jtag_id);
 
 	return 0;
+}
+EXPORT_SYMBOL_GPL(k3_socinfo_register);
+
+static const struct regmap_config k3_chipinfo_regmap_cfg = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int k3_chipinfo_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct regmap *regmap;
+	void __iomem *base;
+	u32 jtag_id;
+	int ret;
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	regmap = devm_regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	ret = regmap_read(regmap, CTRLMMR_WKUP_JTAGID_REG, &jtag_id);
+	if (ret < 0)
+		return ret;
 
-err_free_rev:
-	kfree(soc_dev_attr->revision);
-err:
-	kfree(soc_dev_attr);
-	return ret;
+	return k3_socinfo_register(dev, jtag_id);
 }
 
 static const struct of_device_id k3_chipinfo_of_match[] = {
diff --git a/include/linux/soc/ti/k3-socinfo.h b/include/linux/soc/ti/k3-socinfo.h
new file mode 100644
index 0000000000000..487e69d0069d1
--- /dev/null
+++ b/include/linux/soc/ti/k3-socinfo.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_SOC_TI_K3_SOCINFO_H__
+#define __LINUX_SOC_TI_K3_SOCINFO_H__
+
+#include <linux/types.h>
+
+struct device;
+
+int k3_socinfo_register(struct device *dev, u32 jtag_id);
+
+#endif /* __LINUX_SOC_TI_K3_SOCINFO_H__ */
-- 
2.34.1



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

* [PATCH v2 3/3] soc: ti: Add TDA54 SCM configuration syscon support
  2026-10-27  8:36 [PATCH v2 0/3] soc: ti: Add TDA54 SCM configuration syscon support Moteen Shah
  2026-10-27  8:36 ` [PATCH v2 1/3] dt-bindings: soc: ti: Document the ti,tda54-mcu-scm-conf binding Moteen Shah
  2026-10-27  8:36 ` [PATCH v2 2/3] soc: ti: k3-socinfo: Export SoC registration helper Moteen Shah
@ 2026-10-27  8:37 ` Moteen Shah
  2 siblings, 0 replies; 5+ messages in thread
From: Moteen Shah @ 2026-10-27  8:37 UTC (permalink / raw)
  To: conor+dt, robh, krzk+dt, nm, ssantosh
  Cc: u-kumar1, gehariprasath, m-shah, vigneshr, afd, a-limaye,
	y-abhilashchandra, johan, kees, jm, devicetree, linux-kernel,
	linux-arm-kernel

Add the TDA54 SCM configuration driver providing access to the SCM register
space through regmap/syscon.

The driver handles proxy-based register access and SCM unlock/claim
handling, and registers TDA54 SoC information using the common K3 SoC
info helper exported by k3-socinfo, for which the TDA54 part number is
added to the SoC ID table.

Default the option to m on ARCH_K3, so that the driver gets built for TDA54
boards without requiring a defconfig change.

Signed-off-by: Moteen Shah <m-shah@ti.com>
---
 drivers/soc/ti/Kconfig             |  16 +++
 drivers/soc/ti/Makefile            |   1 +
 drivers/soc/ti/k3-socinfo.c        |   2 +
 drivers/soc/ti/tda54-mcu-sysconf.c | 217 +++++++++++++++++++++++++++++
 4 files changed, 236 insertions(+)
 create mode 100644 drivers/soc/ti/tda54-mcu-sysconf.c

diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index 163aadd589d3a..ea5da6722da29 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -82,6 +82,22 @@ config TI_PRUSS
 	  processors on various TI SoCs. It's safe to say N here if you're
 	  not interested in the PRU or if you are unsure.
 
+config TI_TDA54_MCU_SYSCONF
+	tristate "TI TDA54 SCM configuration controller"
+	depends on ARCH_K3 || COMPILE_TEST
+	depends on OF
+	default m if ARCH_K3
+	select MFD_SYSCON
+	select TI_K3_SOCINFO
+	help
+	  Support the SCM configuration controller found on TI TDA54.
+	  The controller provides a syscon regmap and is also the
+	  hardware access path used to obtain and register K3 SoC
+	  identification information.
+
+	  This driver can be built as a module, in which case the module
+	  will be called tda54-mcu-sysconf.
+
 endif # SOC_TI
 
 config TI_SCI_INTA_MSI_DOMAIN
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile
index cb800a745e66d..33f4ddca32ed6 100644
--- a/drivers/soc/ti/Makefile
+++ b/drivers/soc/ti/Makefile
@@ -11,4 +11,5 @@ obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN)	+= ti_sci_inta_msi.o
 obj-$(CONFIG_TI_K3_RINGACC)		+= k3-ringacc.o
 obj-$(CONFIG_TI_K3_SOCINFO)		+= k3-socinfo.o
 obj-$(CONFIG_TI_PRUSS)			+= pruss.o
+obj-$(CONFIG_TI_TDA54_MCU_SYSCONF)	+= tda54-mcu-sysconf.o
 obj-$(CONFIG_POWER_AVS_OMAP)		+= smartreflex.o
diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c
index e81d27e03c9d9..51493c7e10b9f 100644
--- a/drivers/soc/ti/k3-socinfo.c
+++ b/drivers/soc/ti/k3-socinfo.c
@@ -50,6 +50,7 @@
 #define JTAG_ID_PARTNO_AM62PX		0xBB9D
 #define JTAG_ID_PARTNO_J722S		0xBBA0
 #define JTAG_ID_PARTNO_AM62LX		0xBBA7
+#define JTAG_ID_PARTNO_TDA54		0xBBC1
 
 static const struct k3_soc_id {
 	unsigned int id;
@@ -66,6 +67,7 @@ static const struct k3_soc_id {
 	{ JTAG_ID_PARTNO_AM62PX, "AM62PX" },
 	{ JTAG_ID_PARTNO_J722S, "J722S" },
 	{ JTAG_ID_PARTNO_AM62LX, "AM62LX" },
+	{ JTAG_ID_PARTNO_TDA54, "TDA54" },
 };
 
 static const char * const j721e_rev_string_map[] = {
diff --git a/drivers/soc/ti/tda54-mcu-sysconf.c b/drivers/soc/ti/tda54-mcu-sysconf.c
new file mode 100644
index 0000000000000..3ef82e737d095
--- /dev/null
+++ b/drivers/soc/ti/tda54-mcu-sysconf.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TDA54 SCM Configuration syscon driver
+ *
+ * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/
+ */
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/soc/ti/k3-socinfo.h>
+#include <linux/types.h>
+
+/* Size of a single proxy window into the scm_conf register space */
+#define TDA54_SCM_CONF_PROXY_STRIDE		0x4000
+
+#define TDA54_JTAG_ID_REG_OFFSET		0x14
+
+#define TDA54_SCM_CONF_LOCK_KICK0_UNLOCK_VAL	0x68EF3490
+#define TDA54_SCM_CONF_LOCK_KICK1_UNLOCK_VAL	0xD172BC5A
+
+/*
+ * Claim registers start at 0x3100. Claim register i holds the claim bit
+ * for each of the 32 registers in the (i * TDA54_SCM_CONF_CLAIM_BLOCK_SIZE)
+ * .. (i * TDA54_SCM_CONF_CLAIM_BLOCK_SIZE + 0x7c) block, one bit per
+ * register, i.e. bit b of claim register i corresponds to the register at
+ * offset i * TDA54_SCM_CONF_CLAIM_BLOCK_SIZE + b * 4.
+ */
+#define TDA54_SCM_CONF_CLAIM_REG_STRIDE		0x4
+#define TDA54_SCM_CONF_CLAIM_REGS_PER_WORD	32
+#define TDA54_SCM_CONF_CLAIM_BLOCK_SIZE		\
+	(TDA54_SCM_CONF_CLAIM_REGS_PER_WORD * 0x4)
+
+/* Per-SoC register offset data (platform data) */
+struct tda54_scm_conf_data {
+	u32 lock_offset;
+	u32 claim_offset;
+	u32 claim_status_offset;
+};
+
+static const struct tda54_scm_conf_data tda54_scm_conf_data = {
+	.lock_offset		= 0x3008,
+	.claim_offset		= 0x3100,
+	.claim_status_offset	= 0x3300,
+};
+
+struct tda54_scm_conf {
+	void __iomem *base;
+	u32 proxy;
+	const struct tda54_scm_conf_data *pdata;
+};
+
+/*
+ * Make @reg writable through this proxy.
+ *
+ * Proxy 0 is the default access proxy for all unclaimed registers. Its claim
+ * bits are tied low, so it cannot claim anything and needs no claim to write;
+ * it can write @reg unless another proxy has claimed it, which is reported by
+ * the claim status.
+ *
+ * Any other proxy has to claim @reg first. Registers claimed by a proxy can no
+ * longer be written through any other proxy's address, until that proxy
+ * releases the claim. The claim status is set once any proxy owns @reg, so
+ * read the claim register back to check that the claim is held by this proxy.
+ */
+static int tda54_scm_conf_claim(struct tda54_scm_conf *scm, unsigned int reg)
+{
+	unsigned int block = reg / TDA54_SCM_CONF_CLAIM_BLOCK_SIZE;
+	unsigned int bit = (reg % TDA54_SCM_CONF_CLAIM_BLOCK_SIZE) /
+			   TDA54_SCM_CONF_CLAIM_REG_STRIDE;
+	unsigned int claim_reg = scm->pdata->claim_offset +
+				 block * TDA54_SCM_CONF_CLAIM_REG_STRIDE;
+	unsigned int status_reg = scm->pdata->claim_status_offset +
+				  block * TDA54_SCM_CONF_CLAIM_REG_STRIDE;
+	u32 val;
+
+	if (!scm->proxy) {
+		if (readl(scm->base + status_reg) & BIT(bit))
+			return -EBUSY;
+
+		return 0;
+	}
+
+	val = readl(scm->base + claim_reg);
+	val |= BIT(bit);
+	writel(val, scm->base + claim_reg);
+
+	if (!(readl(scm->base + claim_reg) & BIT(bit)))
+		return -EBUSY;
+
+	return 0;
+}
+
+static int tda54_scm_conf_reg_read(void *context, unsigned int reg,
+				   unsigned int *val)
+{
+	struct tda54_scm_conf *scm = context;
+
+	*val = readl(scm->base + reg);
+
+	return 0;
+}
+
+static int tda54_scm_conf_reg_write(void *context, unsigned int reg,
+				    unsigned int val)
+{
+	struct tda54_scm_conf *scm = context;
+	int ret;
+
+	ret = tda54_scm_conf_claim(scm, reg);
+	if (ret)
+		return ret;
+
+	writel(val, scm->base + reg);
+
+	return 0;
+}
+
+static const struct regmap_config tda54_scm_conf_regmap_cfg = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.fast_io = true,
+	.reg_read = tda54_scm_conf_reg_read,
+	.reg_write = tda54_scm_conf_reg_write,
+};
+
+static int tda54_scm_conf_register_socinfo(struct device *dev,
+					   struct regmap *regmap)
+{
+	u32 jtag_id;
+	int ret;
+
+	ret = regmap_read(regmap, TDA54_JTAG_ID_REG_OFFSET, &jtag_id);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to read JTAG ID\n");
+
+	return k3_socinfo_register(dev, jtag_id);
+}
+
+static int tda54_scm_conf_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tda54_scm_conf *scm;
+	struct regmap *regmap;
+	void __iomem *base;
+	int ret;
+
+	scm = devm_kzalloc(dev, sizeof(*scm), GFP_KERNEL);
+	if (!scm)
+		return -ENOMEM;
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	if (of_property_read_u32(dev->of_node, "ti,proxy-id", &scm->proxy))
+		return dev_err_probe(dev, -ENODATA, "missing ti,proxy-id property\n");
+
+	if (scm->proxy >= 8)
+		return dev_err_probe(dev, -EINVAL,
+				     "ti,proxy-id must be between 0 and 7\n");
+
+	scm->base = base + scm->proxy * TDA54_SCM_CONF_PROXY_STRIDE;
+
+	/* Get register offsets from driver data (matched by compatible) */
+	scm->pdata = of_device_get_match_data(dev);
+
+	regmap = devm_regmap_init(dev, NULL, scm, &tda54_scm_conf_regmap_cfg);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	writel(TDA54_SCM_CONF_LOCK_KICK0_UNLOCK_VAL, scm->base + scm->pdata->lock_offset);
+	writel(TDA54_SCM_CONF_LOCK_KICK1_UNLOCK_VAL, scm->base + scm->pdata->lock_offset + 4);
+
+	/*
+	 * There is no way to unregister a syscon regmap, so publish it only
+	 * once nothing else in probe can fail.
+	 */
+	ret = of_syscon_register_regmap(dev->of_node, regmap);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to register syscon regmap\n");
+
+	/*
+	 * SoC identification is informational, so a failure here must not fail
+	 * the probe. It is registered last and released through devres.
+	 */
+	ret = tda54_scm_conf_register_socinfo(dev, regmap);
+	if (ret)
+		dev_warn(dev, "SoC info not registered: %d\n", ret);
+
+	return 0;
+}
+
+static const struct of_device_id tda54_scm_conf_of_match[] = {
+	{ .compatible = "ti,tda54-mcu-scm-conf", .data = &tda54_scm_conf_data },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, tda54_scm_conf_of_match);
+
+static struct platform_driver tda54_scm_conf_driver = {
+	.probe = tda54_scm_conf_probe,
+	.driver = {
+		.name = "k3-tda54-scm-conf",
+		.of_match_table = tda54_scm_conf_of_match,
+		.suppress_bind_attrs = true,
+	},
+};
+
+module_platform_driver(tda54_scm_conf_driver);
+
+MODULE_AUTHOR("Moteen Shah <m-shah@ti.com>");
+MODULE_DESCRIPTION("TDA54 SCM Configuration syscon driver");
+MODULE_LICENSE("GPL");
-- 
2.34.1



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

* Re: [PATCH v2 1/3] dt-bindings: soc: ti: Document the ti,tda54-mcu-scm-conf binding
  2026-10-27  8:36 ` [PATCH v2 1/3] dt-bindings: soc: ti: Document the ti,tda54-mcu-scm-conf binding Moteen Shah
@ 2026-10-28 12:24   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 5+ messages in thread
From: Krzysztof Kozlowski @ 2026-10-28 12:24 UTC (permalink / raw)
  To: Moteen Shah
  Cc: conor+dt, robh, krzk+dt, nm, ssantosh, u-kumar1, gehariprasath,
	vigneshr, afd, a-limaye, y-abhilashchandra, johan, kees, jm,
	devicetree, linux-kernel, linux-arm-kernel

On Tue, Oct 27, 2026 at 02:06:58PM +0530, Moteen Shah wrote:
> TDA54's MCU domain exposes a shared scm_conf syscon region that other
> peripherals, including chipid, access into rather than owning a
> dedicated register window. Rather than a bare fallback entry in the
> generic syscon compatible list, give it a dedicated binding
> describing the region and the proxy/claim/lock arbitration scheme
> that gates write access to a subset of its registers.
> 

A nit, subject: drop second/last, redundant "binding". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v7.1-rc7/source/Documentation/devicetree/bindings/submitting-patches.rst#L23

> Some of the claimable registers are gate clock controls, so also
> document the required "#clock-cells" property that lets the node be
> referenced directly as a clock provider for those gates. The clock
> specifier selects the ePWM time-base gate by instance number.
> 
> Co-developed-by: Aniket Limaye <a-limaye@ti.com>
> Signed-off-by: Aniket Limaye <a-limaye@ti.com>
> Signed-off-by: Moteen Shah <m-shah@ti.com>
> ---
>  .../soc/ti/ti,tda54-mcu-scm-conf.yaml         | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml
> 
> diff --git a/Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml b/Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml
> new file mode 100644
> index 0000000000000..111cbb739b5f1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/ti/ti,tda54-mcu-scm-conf.yaml
> @@ -0,0 +1,78 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/ti/ti,tda54-mcu-scm-conf.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Texas Instruments TDA54 SoC MCU Domain System Control Module Configuration registers
> +
> +maintainers:
> +  - Aniket Limaye <a-limaye@ti.com>
> +  - Moteen Shah <m-shah@ti.com>
> +
> +description: |
> +  The TDA54 SoC's MCU domain exposes a System Control Module configuration
> +  register region (scm_conf) containing miscellaneous control and status
> +  registers for MCU domain peripherals, including the JTAGID/device
> +  identification registers, boot configuration and status registers, and
> +  device feature registers.
> +
> +  A subset of these registers is write-protected by a proxy/claim scheme:
> +  each register is mirrored across 8 proxy regions, and a host must unlock
> +  via LOCK_KICK. Any proxy other than proxy-0 must also claim a register
> +  through its CLAIM register before writing through that proxy. Proxy-0 is
> +  the default access proxy: its claim bits are tied low, so it needs no
> +  claim and can write any register that is not claimed by another proxy.
> +  For example: Proxy0's CLAIM0 register sits at offset 0x3100, while the
> +  same register mirrored at ProxyN sits at N * 0x4000 + 0x3100.
> +
> +  Each of the 8 proxy regions also has its own fault status and
> +  interrupt registers, but a fault can only be handled through proxy-0.
> +  Hence, interrupt/fault handling is not described by this binding.
> +
> +  Some of the claimable registers are gate clock controls (e.g. the
> +  ehrpwm_tbclk gates). This node is the clock provider for those gates;
> +  writes to them are still routed through the proxy claim scheme described
> +  above.
> +
> +properties:
> +  compatible:
> +    const: ti,tda54-mcu-scm-conf
> +
> +  reg:
> +    maxItems: 1
> +
> +  ti,proxy-id:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 7
> +    description:
> +      Proxy region (0-7) through which this node's clients access
> +      claimable registers and their fault status registers.

I don't get the need of this property. You have a one, specific device, so
why the proxy id would vary per board?

It also looks like re-implementing access controllers.

Best regards,
Krzysztof



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

end of thread, other threads:[~2026-10-28 12:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-27  8:36 [PATCH v2 0/3] soc: ti: Add TDA54 SCM configuration syscon support Moteen Shah
2026-10-27  8:36 ` [PATCH v2 1/3] dt-bindings: soc: ti: Document the ti,tda54-mcu-scm-conf binding Moteen Shah
2026-10-28 12:24   ` Krzysztof Kozlowski
2026-10-27  8:36 ` [PATCH v2 2/3] soc: ti: k3-socinfo: Export SoC registration helper Moteen Shah
2026-10-27  8:37 ` [PATCH v2 3/3] soc: ti: Add TDA54 SCM configuration syscon support Moteen Shah

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