Linux clock framework development
 help / color / mirror / Atom feed
* [PATCH 0/4] soc: toshiba: tc9564: config system controller
@ 2026-11-04  0:43 Alex Elder
  2026-11-04  0:43 ` [PATCH 1/4] dt-bindings: soc: introduce toshiba,tc9564-config-syscon.yaml Alex Elder
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Alex Elder @ 2026-11-04  0:43 UTC (permalink / raw)
  To: sboyd, bmasney+clk, jbrunet+clk, p.zabel, robh, krzk+dt, conor+dt
  Cc: daniel, mohd.anwar, lorenzo.bianconi, fabrice.gasnier,
	alexandre.torgue, marex, changhuang.liang, devicetree, linux-clk,
	linux-kernel

This series is comprised of some code that was previously sent
separately.  It now incorporates a new system controller driver
that advertises clock and reset functionality, as well as regmap
access to its address range.  This combination is being treated
as a new series.  (Details of previous versions are below.)

The Toshiba TC9564 is an SoC that attaches to a host system via PCIe.
It includes a PCIe switch with three downstream ports.  To one of
these ports an embedded PCIe endpoint is attached, and that implements
two PCI functions.  BAR 4 for both PCI functions provides access to
registers controlling blocks within the SoC.

The system controller driver adds the clock and reset devices
using the mfd_add_devices() interface.  The clocks and resets
are implemented by drivers included in this series.

					-Alex

The system controller, along with its devicetree binding are new.
My hope is that this new model addresses concerns that Krzysztof
Kozlowski has expressed in prior versions of the clock and reset
code ("fold into the parent").

The clock controller driver was last posted as version 3, and all
feedback from prior versions has been addressed.  This driver has
essentially been completely rewritten.  There are now three clock
types (PLL, fixed factor, and gate), and each defined clock has
a parent, and the is_enabled callback is implemented for the gate
clocks.

The last version of the clock driver is here:
  https://lore.kernel.org/lkml/20261012152408.3729237-1-elder@riscstar.com/

The reset controller driver was last posted as version 1.  All
feedback received on that version has been addressed, and it's
a bit simpler than before.

The last version of the reset driver is here:
  https://lore.kernel.org/lkml/20261012164354.3872326-1-elder@riscstar.com/

Alex Elder (4):
  dt-bindings: soc: introduce toshiba,tc9564-config-syscon.yaml
  soc: toshiba: tc9564: add a new syscon driver
  clk: toshiba: introduce a TC9564 SoC clock driver
  reset: toshiba: introduce a TC9564 SoC reset driver

 .../toshiba/toshiba,tc9564-config-syscon.yaml |  68 +++++
 MAINTAINERS                                   |  23 ++
 drivers/clk/Kconfig                           |  12 +
 drivers/clk/Makefile                          |   1 +
 drivers/clk/clk-tc9564.c                      | 288 ++++++++++++++++++
 drivers/reset/Kconfig                         |  12 +
 drivers/reset/Makefile                        |   1 +
 drivers/reset/reset-tc9564.c                  | 135 ++++++++
 drivers/soc/Kconfig                           |   1 +
 drivers/soc/Makefile                          |   1 +
 drivers/soc/toshiba/Kconfig                   |  12 +
 drivers/soc/toshiba/Makefile                  |   3 +
 drivers/soc/toshiba/tc9564-syscon.c           |  42 +++
 include/dt-bindings/soc/toshiba,tc9564.h      |  46 +++
 14 files changed, 645 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.yaml
 create mode 100644 drivers/clk/clk-tc9564.c
 create mode 100644 drivers/reset/reset-tc9564.c
 create mode 100644 drivers/soc/toshiba/Kconfig
 create mode 100644 drivers/soc/toshiba/Makefile
 create mode 100644 drivers/soc/toshiba/tc9564-syscon.c
 create mode 100644 include/dt-bindings/soc/toshiba,tc9564.h


base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
-- 
2.53.0


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

* [PATCH 1/4] dt-bindings: soc: introduce toshiba,tc9564-config-syscon.yaml
  2026-11-04  0:43 [PATCH 0/4] soc: toshiba: tc9564: config system controller Alex Elder
@ 2026-11-04  0:43 ` Alex Elder
  2026-11-04  0:43 ` [PATCH 2/4] soc: toshiba: tc9564: add a new syscon driver Alex Elder
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Alex Elder @ 2026-11-04  0:43 UTC (permalink / raw)
  To: sboyd, bmasney+clk, jbrunet+clk, p.zabel, robh, krzk+dt, conor+dt
  Cc: daniel, mohd.anwar, lorenzo.bianconi, fabrice.gasnier,
	alexandre.torgue, marex, changhuang.liang, devicetree, linux-clk,
	linux-kernel

Define the binding for the system controller that implements the clock
and reset controller functionality present in the Toshiba TC9564 SoC.

Co-developed-by: Daniel Thompson <daniel@riscstar.com>
Signed-off-by: Daniel Thompson <daniel@riscstar.com>
Signed-off-by: Alex Elder <elder@riscstar.com>
---
 .../toshiba/toshiba,tc9564-config-syscon.yaml | 68 +++++++++++++++++++
 MAINTAINERS                                   |  8 +++
 include/dt-bindings/soc/toshiba,tc9564.h      | 46 +++++++++++++
 3 files changed, 122 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.yaml
 create mode 100644 include/dt-bindings/soc/toshiba,tc9564.h

diff --git a/Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.yaml b/Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.yaml
new file mode 100644
index 0000000000000..5a241a9c915d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/toshiba/toshiba,tc9564-config-syscon.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Toshiba TC9564 Multifunction System Controller
+
+maintainers:
+  - Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
+  - Alex Elder <elder@riscstar.com>
+  - Daniel Thompson <daniel@riscstar.com>
+
+description:
+  The Toshiba TC9564 is an SoC accessed by a host system through the
+  upstream PCIe port on the PCIe switch it implements.  The switch
+  includes an embedded PCIe endpoint that provides access to various
+  SoC peripherals via its BARs.  These peripherals include a simple
+  controller to gate internal clocks, as well as a reset controller.
+
+  The clock controller uses registers within the same page as a reset
+  controller, so this system controller controls access to both.
+
+  A total of 21 simple gated clocks are implemented within the SoC.
+  At this time, support for enabling and disabling only a subset of
+  them is provided at this time.  Similarly, the SoC implements 13
+  resets, but currently not all of them can be controlled.
+
+properties:
+  compatible:
+    items:
+      - const: toshiba,tc9564-config-syscon
+      - const: syscon
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  "#clock-cells":
+    const: 1
+    description:
+      Clock ids are defined in <include/dt-bindings/soc/toshiba,tc9564.h>
+
+  "#reset-cells":
+    const: 1
+    description:
+      Reset ids are defined in <include/dt-bindings/soc/toshiba,tc9564.h>
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - "#clock-cells"
+  - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    syscon@0 {
+        compatible = "toshiba,tc9564-config-syscon", "syscon";
+        reg = <0x0 0x2000>;
+        clocks = <&tc9564_xo_board>;
+        #clock-cells = <1>;
+        #reset-cells = <1>;
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 93abbb315065d..2b1b29169e0e9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28339,6 +28339,14 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/misc/pci1179,0220.yaml
 F:	drivers/misc/tc9564-pci.c
 
+TOSHIBA TC9564 SYSTEM CONTROLLER DRIVER
+M:	Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
+M:	Alex Elder <elder@kernel.org>
+M:	Daniel Thompson <danielt@kernel.org>
+S:	Maintained
+F:	Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.yaml
+F:	include/dt-bindings/soc/toshiba,tc9564.h
+
 TOSHIBA WMI HOTKEYS DRIVER
 M:	Azael Avalos <coproscefalo@gmail.com>
 L:	platform-driver-x86@vger.kernel.org
diff --git a/include/dt-bindings/soc/toshiba,tc9564.h b/include/dt-bindings/soc/toshiba,tc9564.h
new file mode 100644
index 0000000000000..66bcdf837f958
--- /dev/null
+++ b/include/dt-bindings/soc/toshiba,tc9564.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+/*
+ * Copyright (C) 2026 by RISCstar Solutions Corporation.  All rights reserved.
+ */
+
+#ifndef __SOC_TOSHIBA_TC9564_H__
+#define __SOC_TOSHIBA_TC9564_H__
+
+/* Clock IDs */
+
+#define CLOCK_PLL		0
+
+#define CLOCK_62_5M		1
+#define CLOCK_125M		2
+#define CLOCK_250M		3
+#define CLOCK_312_5M		4
+
+#define CLOCK_MSIGEN		5
+
+#define CLOCK_MAC0_TX		6
+#define CLOCK_MAC0_RX		7
+#define CLOCK_MAC0_125M		8
+#define CLOCK_MAC0_312_5M	9
+#define CLOCK_MAC0_ALL		10
+
+#define CLOCK_MAC1_TX		11
+#define CLOCK_MAC1_RX		12
+#define CLOCK_MAC1_125M		13
+#define CLOCK_MAC1_312_5M	14
+#define CLOCK_MAC1_ALL		15
+#define CLOCK_MAC1_RMII		16
+
+/* Reset IDs */
+
+#define RESET_MSIGEN		0
+
+#define RESET_MAC0_MAC		1
+#define RESET_MAC0_PMA		2
+#define RESET_MAC0_XPCS		3
+
+#define RESET_MAC1_MAC		4
+#define RESET_MAC1_PMA		5
+#define RESET_MAC1_XPCS		6
+
+#endif /* __SOC_TOSHIBA_TC9564_H__*/
-- 
2.53.0


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

* [PATCH 2/4] soc: toshiba: tc9564: add a new syscon driver
  2026-11-04  0:43 [PATCH 0/4] soc: toshiba: tc9564: config system controller Alex Elder
  2026-11-04  0:43 ` [PATCH 1/4] dt-bindings: soc: introduce toshiba,tc9564-config-syscon.yaml Alex Elder
@ 2026-11-04  0:43 ` Alex Elder
  2026-11-04  0:50   ` sashiko-bot
  2026-11-04  0:43 ` [PATCH 3/4] clk: toshiba: introduce a TC9564 SoC clock driver Alex Elder
  2026-11-04  0:43 ` [PATCH 4/4] reset: toshiba: introduce a TC9564 SoC reset driver Alex Elder
  3 siblings, 1 reply; 8+ messages in thread
From: Alex Elder @ 2026-11-04  0:43 UTC (permalink / raw)
  To: sboyd, bmasney+clk, jbrunet+clk, p.zabel, robh, krzk+dt, conor+dt
  Cc: daniel, mohd.anwar, lorenzo.bianconi, fabrice.gasnier,
	alexandre.torgue, marex, changhuang.liang, devicetree, linux-clk,
	linux-kernel

Introduce a new system controller driver for devices found within the
Toshiba TC9564 SoC.  The system controller manages access to an 8 KB
region, and implements controllers for a set of clocks as well as a
set of resets.  The region also includes registers that indicate when
initialization is done for the chip's two Ethernet interfaces.

The SoC has a single 25 MHz input clock, and from that derives clocks
of various rates used by functional blocks within the chip.

Signed-off-by: Alex Elder <elder@riscstar.com>
---
 MAINTAINERS                         |  1 +
 drivers/soc/Kconfig                 |  1 +
 drivers/soc/Makefile                |  1 +
 drivers/soc/toshiba/Kconfig         | 12 +++++++++
 drivers/soc/toshiba/Makefile        |  3 +++
 drivers/soc/toshiba/tc9564-syscon.c | 42 +++++++++++++++++++++++++++++
 6 files changed, 60 insertions(+)
 create mode 100644 drivers/soc/toshiba/Kconfig
 create mode 100644 drivers/soc/toshiba/Makefile
 create mode 100644 drivers/soc/toshiba/tc9564-syscon.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 2b1b29169e0e9..c25ee6e0f1c68 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28345,6 +28345,7 @@ M:	Alex Elder <elder@kernel.org>
 M:	Daniel Thompson <danielt@kernel.org>
 S:	Maintained
 F:	Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.yaml
+F:	drivers/soc/toshiba/tc9564-syscon.c
 F:	include/dt-bindings/soc/toshiba,tc9564.h
 
 TOSHIBA WMI HOTKEYS DRIVER
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 483cbdcae1534..f655d368e0fb6 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -29,6 +29,7 @@ source "drivers/soc/starfive/Kconfig"
 source "drivers/soc/sunxi/Kconfig"
 source "drivers/soc/tegra/Kconfig"
 source "drivers/soc/ti/Kconfig"
+source "drivers/soc/toshiba/Kconfig"
 source "drivers/soc/ux500/Kconfig"
 source "drivers/soc/versatile/Kconfig"
 source "drivers/soc/vt8500/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5a3efd68355cd..150f7f4f05560 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -35,6 +35,7 @@ obj-y				+= starfive/
 obj-y				+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-y				+= ti/
+obj-y				+= toshiba/
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
 obj-y				+= versatile/
 obj-y				+= vt8500/
diff --git a/drivers/soc/toshiba/Kconfig b/drivers/soc/toshiba/Kconfig
new file mode 100644
index 0000000000000..91adcbe71905c
--- /dev/null
+++ b/drivers/soc/toshiba/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config SOC_TOSHIBA_TC9564_SYSCON
+	tristate "Toshiba TC9564 config system controller support"
+	depends on TC9564_PCI
+	depends on MFD_CORE
+	default TC9564_PCI
+	help
+	  This enables support for the config system controller for the
+	  TC9564 SoC.  It implements an MMIO regmap to manage access to
+	  two pages of I/O memory, and serves as a clock and reset
+	  controller for IP blocks within the chip.
diff --git a/drivers/soc/toshiba/Makefile b/drivers/soc/toshiba/Makefile
new file mode 100644
index 0000000000000..18dc03507b320
--- /dev/null
+++ b/drivers/soc/toshiba/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_SOC_TOSHIBA_TC9564_SYSCON)	+= tc9564-syscon.o
diff --git a/drivers/soc/toshiba/tc9564-syscon.c b/drivers/soc/toshiba/tc9564-syscon.c
new file mode 100644
index 0000000000000..0d0e2422b82d0
--- /dev/null
+++ b/drivers/soc/toshiba/tc9564-syscon.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2026 by RISCstar Solutions Corporation.  All rights reserved.
+ */
+
+#include <linux/device.h>
+#include <linux/device-id/of.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static const struct mfd_cell tc9564_config_syscon_cells[] = {
+	MFD_CELL_NAME("toshiba-tc9564-clock"),
+	MFD_CELL_NAME("toshiba-tc9564-reset"),
+};
+
+static int tc9564_config_syscon_probe(struct platform_device *pdev)
+{
+	return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+				    tc9564_config_syscon_cells,
+				    ARRAY_SIZE(tc9564_config_syscon_cells),
+				    NULL, 0, NULL);
+}
+
+static const struct of_device_id tc9564_config_syscon_match[] = {
+	{ .compatible = "toshiba,tc9564-config-syscon", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tc9564_config_syscon_match);
+
+static struct platform_driver tc9564_config_syscon_driver = {
+	.driver = {
+		.name		= KBUILD_MODNAME,
+		.of_match_table	= tc9564_config_syscon_match,
+	},
+	.probe = tc9564_config_syscon_probe,
+};
+module_platform_driver(tc9564_config_syscon_driver);
+
+MODULE_DESCRIPTION("Toshiba TC9564 config syscon driver");
+MODULE_LICENSE("GPL");
-- 
2.53.0


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

* [PATCH 3/4] clk: toshiba: introduce a TC9564 SoC clock driver
  2026-11-04  0:43 [PATCH 0/4] soc: toshiba: tc9564: config system controller Alex Elder
  2026-11-04  0:43 ` [PATCH 1/4] dt-bindings: soc: introduce toshiba,tc9564-config-syscon.yaml Alex Elder
  2026-11-04  0:43 ` [PATCH 2/4] soc: toshiba: tc9564: add a new syscon driver Alex Elder
@ 2026-11-04  0:43 ` Alex Elder
  2026-11-04  0:54   ` sashiko-bot
  2026-11-04  0:43 ` [PATCH 4/4] reset: toshiba: introduce a TC9564 SoC reset driver Alex Elder
  3 siblings, 1 reply; 8+ messages in thread
From: Alex Elder @ 2026-11-04  0:43 UTC (permalink / raw)
  To: sboyd, bmasney+clk, jbrunet+clk, p.zabel, robh, krzk+dt, conor+dt
  Cc: daniel, mohd.anwar, lorenzo.bianconi, fabrice.gasnier,
	alexandre.torgue, marex, changhuang.liang, devicetree, linux-clk,
	linux-kernel

Define a new platform driver that manages clocks implemented by the
Toshiba TC9564 SoC.  There are 21 gate clocks that can be enabled
and disabled, but currently only the clocks that are (or will soon
be) used are defined to be controllable.

Two registers manage the state of the clocks.  The registers are
accessed via a regmap supplied by a system controller.  Access to
the memory region is provided via a BAR on a PCIe endpoint function
embedded in the TC9564 SoC.

Co-developed-by: Daniel Thompson <daniel@riscstar.com>
Signed-off-by: Daniel Thompson <daniel@riscstar.com>
Signed-off-by: Alex Elder <elder@riscstar.com>
---
 MAINTAINERS              |   7 +
 drivers/clk/Kconfig      |  12 ++
 drivers/clk/Makefile     |   1 +
 drivers/clk/clk-tc9564.c | 288 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 308 insertions(+)
 create mode 100644 drivers/clk/clk-tc9564.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c25ee6e0f1c68..ee01aed56508d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28332,6 +28332,13 @@ F:	Documentation/devicetree/bindings/media/i2c/toshiba,tc358743.yaml
 F:	drivers/media/i2c/tc358743*
 F:	include/media/i2c/tc358743.h
 
+TOSHIBA TC9564 CLOCK DRIVER
+M:	Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
+M:	Alex Elder <elder@kernel.org>
+M:	Daniel Thompson <danielt@kernel.org>
+S:	Maintained
+F:	drivers/clk/clk-tc9564.c
+
 TOSHIBA TC9564 PCI DRIVER
 M:	Alex Elder <elder@kernel.org>
 M:	Daniel Thompson <danielt@kernel.org>
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 37a8e35d41783..0d186150d0c75 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -293,6 +293,18 @@ config COMMON_CLK_S2MPS11
 	  clock. These multi-function devices have two (S2MPS14) or three
 	  (S2MPS11, S5M8767) fixed-rate oscillators, clocked at 32KHz each.
 
+config COMMON_CLK_TC9564
+	tristate "Toshiba TC9564 clock support"
+	depends on SOC_TOSHIBA_TC9564_SYSCON
+	select MFD_SYSCON
+	default SOC_TOSHIBA_TC9564_SYSCON
+	help
+	  This enables support for the clock controller embedded in the
+	  Toshiba TC9564 SoC.  The state of each clock is controlled via
+	  MMIO to a region managed by a system controller; this ensures
+	  access to the region is coordinated between this and the reset
+	  and XGMAC (stmmac) drivers.
+
 config CLK_TWL
 	tristate "Clock driver for the TWL PMIC family"
 	depends on TWL4030_CORE
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 52d138d4ffc88..a11a8326d79cb 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -111,6 +111,7 @@ obj-$(CONFIG_COMMON_CLK_SI570)		+= clk-si570.o
 obj-$(CONFIG_COMMON_CLK_SP7021)		+= clk-sp7021.o
 obj-$(CONFIG_COMMON_CLK_STM32F)		+= clk-stm32f4.o
 obj-$(CONFIG_COMMON_CLK_STM32H7)	+= clk-stm32h7.o
+obj-$(CONFIG_COMMON_CLK_TC9564)		+= clk-tc9564.o
 obj-$(CONFIG_COMMON_CLK_TPS68470)      += clk-tps68470.o
 obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
 obj-$(CONFIG_CLK_TWL)			+= clk-twl.o
diff --git a/drivers/clk/clk-tc9564.c b/drivers/clk/clk-tc9564.c
new file mode 100644
index 0000000000000..8eeba85919703
--- /dev/null
+++ b/drivers/clk/clk-tc9564.c
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2026 by RISCstar Solutions Corporation.  All rights reserved.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/soc/toshiba,tc9564.h>
+
+/*
+ * The full name of every clock has a prefix "tc9564" followed by a single
+ * character ('a', 'b', etc.) that differs for each chip/device number.
+ * Each clock's "name" defines the unique portion of the clock's full name.
+ */
+#define FULL_NAME_SIZE	24	/* Enough for formatted full name */
+#define NAME_SIZE	12	/* Unique portion of the clock name */
+#define FORMAT_FULL_NAME(_full_name, _id, _name)		\
+	snprintf(_full_name, FULL_NAME_SIZE, "tc9564%c_%.*s",	\
+		'a' + (_id), NAME_SIZE, _name)
+
+/* Two registers control whether gate clocks are enabled */
+#define CLK_CTRL0_OFFSET	0x1004	/* Common and MAC0 gate clocks */
+#define CLK_CTRL1_OFFSET	0x100c	/* MAC1 gate clocks */
+
+enum clock_type { PLL, FIXED, GATE };
+
+struct tc9564_clock {
+	struct regmap *regmap;
+	struct clk_hw_onecell_data *clk_data;
+};
+
+struct gate_clock {
+	struct clk_hw hw;
+	const struct clock_init *init;
+};
+
+struct clock_init {
+	const char name[NAME_SIZE];
+	enum clock_type type;
+	union {
+		u32 mult;	/* PLL rate multiplier */
+
+		u32 div;	/* Fixed rate clock divider */
+
+		struct {	/* Gate clock */
+			u16 parent;	/* Parent clock ID, e.g. CLOCK_50M */
+			u16 offset;	/* CLK_CTRL0_OFFSET/CLK_CTRL1_OFFSET */
+			u32 mask;
+		};
+	};
+};
+
+/* There is only one PLL */
+#define PLL_INIT(_name, _mult)				\
+	[CLOCK_##_name] = {				\
+		.name = #_name,				\
+		.type = PLL,				\
+		.mult = (_mult),			\
+	}
+
+/* The PLL is the parent of all the fixed rate clocks */
+#define FIXED_INIT(_name, _div)				\
+	[CLOCK_##_name] = {				\
+		.name = #_name,				\
+		.type = FIXED,				\
+		.div = (_div),				\
+	}
+
+#define GATE_INIT0(_name, _bit, _pname)	__GATE_INIT(_name, 0, _bit, _pname)
+#define GATE_INIT1(_name, _bit, _pname)	__GATE_INIT(_name, 1, _bit, _pname)
+#define __GATE_INIT(_name, _reg, _bit, _pname)		\
+	[CLOCK_##_name] = {				\
+		.name = #_name,				\
+		.type = GATE,				\
+		.parent = CLOCK_##_pname,		\
+		.offset = CLK_CTRL ## _reg ## _OFFSET,	\
+		.mask = BIT(_bit),			\
+	}
+
+/*
+ * Clocks are initialized and registered in the order of their IDs.
+ * Parent clocks must be registered before their children.
+ */
+static const struct clock_init clock_init[] = {
+	PLL_INIT(PLL, 50),
+
+	FIXED_INIT(62_5M, 20),
+	FIXED_INIT(125M, 10),
+	FIXED_INIT(250M, 5),
+	FIXED_INIT(312_5M, 4),
+
+	GATE_INIT0(MSIGEN, 18, 62_5M),
+
+	GATE_INIT0(MAC0_TX, 7, 250M),
+	GATE_INIT0(MAC0_RX, 14, 250M),
+	GATE_INIT0(MAC0_125M, 29, 125M),
+	GATE_INIT0(MAC0_312_5M, 30, 312_5M),
+	GATE_INIT0(MAC0_ALL, 31, 250M),
+
+	GATE_INIT1(MAC1_TX, 7, 250M),
+	GATE_INIT1(MAC1_RX, 14, 250M),
+	GATE_INIT1(MAC1_125M, 29, 125M),
+	GATE_INIT1(MAC1_312_5M, 30, 312_5M),
+	GATE_INIT1(MAC1_ALL, 31, 250M),
+	GATE_INIT1(MAC1_RMII, 15, 125M),
+};
+#define CLOCK_COUNT	ARRAY_SIZE(clock_init)
+
+/* Parent is the input oscillator running at 25 MHz; PLL runs at 1250 MHz */
+static struct clk_hw *pll_register(struct device *dev,
+				   const struct clock_init *init)
+{
+	char full_name[FULL_NAME_SIZE];
+
+	FORMAT_FULL_NAME(full_name, dev->id, init->name);
+
+	return devm_clk_hw_register_fixed_factor_index(dev, full_name, 0, 0,
+						       init->mult, 1);
+}
+
+/* The PLL is the parent of all fixed clocks */
+static struct clk_hw *fixed_register(struct device *dev,
+				     const struct clock_init *init)
+{
+	struct tc9564_clock *tc9564_clock = dev_get_drvdata(dev);
+	char full_name[FULL_NAME_SIZE];
+	struct clk_hw *pll_hw;
+
+	FORMAT_FULL_NAME(full_name, dev->id, init->name);
+
+	pll_hw = tc9564_clock->clk_data->hws[CLOCK_PLL];
+
+	return devm_clk_hw_register_fixed_factor_parent_hw(dev, full_name,
+							   pll_hw, 0,
+							   1, init->div);
+}
+
+static const struct gate_clock *hw_to_gate_clock(struct clk_hw *hw)
+{
+	return container_of_const(hw, struct gate_clock, hw);
+}
+
+static void gate_clk_manage(struct clk_hw *hw, bool enable)
+{
+	struct tc9564_clock *tc9564_clock = dev_get_drvdata(clk_hw_get_dev(hw));
+	const struct gate_clock *clock = hw_to_gate_clock(hw);
+	u32 mask = clock->init->mask;
+
+	regmap_update_bits(tc9564_clock->regmap, clock->init->offset, mask,
+			   enable ? mask : 0);
+}
+
+static int gate_clk_enable(struct clk_hw *hw)
+{
+	gate_clk_manage(hw, true);
+
+	return 0;
+}
+
+static void gate_clk_disable(struct clk_hw *hw)
+{
+	gate_clk_manage(hw, false);
+}
+
+static int gate_clk_is_enabled(struct clk_hw *hw)
+{
+	struct tc9564_clock *tc9564_clock = dev_get_drvdata(clk_hw_get_dev(hw));
+	const struct gate_clock *clock = hw_to_gate_clock(hw);
+	u32 val;
+
+	regmap_read(tc9564_clock->regmap, clock->init->offset, &val);
+
+	return val & clock->init->mask ? 1 : 0;
+}
+
+static const struct clk_ops gate_clk_ops = {
+	.enable = gate_clk_enable,
+	.disable = gate_clk_disable,
+	.is_enabled = gate_clk_is_enabled,
+};
+
+static struct clk_hw *gate_register(struct device *dev,
+				    const struct clock_init *init)
+{
+	struct tc9564_clock *tc9564_clock = dev_get_drvdata(dev);
+	struct clk_init_data clk_init = { };
+	const struct clk_hw *parent_hw;
+	char full_name[FULL_NAME_SIZE];
+	struct gate_clock *clock;
+	int ret;
+
+	clock = devm_kzalloc_obj(dev, *clock);
+	if (!clock)
+		return ERR_PTR(-ENOMEM);
+
+	FORMAT_FULL_NAME(full_name, dev->id, init->name);
+
+	parent_hw = tc9564_clock->clk_data->hws[init->parent];
+
+	clk_init.name = full_name;
+	clk_init.ops = &gate_clk_ops;
+	clk_init.parent_hws = &parent_hw;
+	clk_init.num_parents = 1;
+
+	clock->hw.init = &clk_init;
+	clock->init = init;
+
+	ret = devm_clk_hw_register(dev, &clock->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &clock->hw;
+}
+
+static int tc9564_clk_probe(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data;
+	struct tc9564_clock *tc9564_clock;
+	struct device *dev = &pdev->dev;
+	struct device_node *parent_np;
+	int ret;
+
+	parent_np = dev_of_node(dev->parent);
+	if (!parent_np)
+		return dev_err_probe(dev, -EINVAL, "no devicetree node\n");
+
+	tc9564_clock = devm_kzalloc_obj(dev, *tc9564_clock);
+	if (!tc9564_clock)
+		return -ENOMEM;
+
+	/* Note: MMIO regmap (no error checking needed when used) */
+	tc9564_clock->regmap = device_node_to_regmap(parent_np);
+	if (IS_ERR(tc9564_clock->regmap))
+		return dev_err_probe(dev, PTR_ERR(tc9564_clock->regmap),
+				     "failed to get config regmap\n");
+
+	clk_data = devm_kzalloc_flex(dev, *tc9564_clock->clk_data, hws,
+				     CLOCK_COUNT);
+	if (!clk_data)
+		return -ENOMEM;
+	tc9564_clock->clk_data = clk_data;
+
+	dev_set_drvdata(dev, tc9564_clock);
+
+	/* Initialize all the clocks */
+	for (u32 i = 0; i < clk_data->num; i++) {
+		const struct clock_init *init = &clock_init[i];
+		struct clk_hw *hw;
+
+		if (init->type == PLL)
+			hw = pll_register(dev, init);
+		else if (init->type == FIXED)
+			hw = fixed_register(dev, init);
+		else
+			hw = gate_register(dev, init);
+		if (IS_ERR(hw))
+			return dev_err_probe(dev, PTR_ERR(hw),
+					     "failed to register %s\n",
+					     init->name);
+		clk_data->hws[i] = hw;
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to add provider\n");
+
+	return 0;
+}
+
+static struct platform_driver tc9564_clk_driver = {
+	.probe = tc9564_clk_probe,
+	.driver = {
+		.name = "toshiba-tc9564-clock",
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+};
+module_platform_driver(tc9564_clk_driver);
+
+MODULE_DESCRIPTION("Toshiba TC9564 Clock Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:toshiba-tc9564-clock");
-- 
2.53.0


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

* [PATCH 4/4] reset: toshiba: introduce a TC9564 SoC reset driver
  2026-11-04  0:43 [PATCH 0/4] soc: toshiba: tc9564: config system controller Alex Elder
                   ` (2 preceding siblings ...)
  2026-11-04  0:43 ` [PATCH 3/4] clk: toshiba: introduce a TC9564 SoC clock driver Alex Elder
@ 2026-11-04  0:43 ` Alex Elder
  2026-11-04  9:49   ` Philipp Zabel
  3 siblings, 1 reply; 8+ messages in thread
From: Alex Elder @ 2026-11-04  0:43 UTC (permalink / raw)
  To: sboyd, bmasney+clk, jbrunet+clk, p.zabel, robh, krzk+dt, conor+dt
  Cc: daniel, mohd.anwar, lorenzo.bianconi, fabrice.gasnier,
	alexandre.torgue, marex, changhuang.liang, devicetree, linux-clk,
	linux-kernel

Define a new platform driver that manages reset signals implemented by
the Toshiba TC9564 SoC.  There are 13 reset signals available, but
currently only the resets that are (or will soon be) used are defined
to be controllable.

Two registers manage the state of the resets.  The registers are
accessed via a regmap supplied by a system controller.  Access to
the memory region is provided via a BAR on a PCIe endpoint function
embedded in the TC9564 SoC.

Co-developed-by: Daniel Thompson <daniel@riscstar.com>
Signed-off-by: Daniel Thompson <daniel@riscstar.com>
Signed-off-by: Alex Elder <elder@riscstar.com>
---
 MAINTAINERS                  |   7 ++
 drivers/reset/Kconfig        |  12 ++++
 drivers/reset/Makefile       |   1 +
 drivers/reset/reset-tc9564.c | 135 +++++++++++++++++++++++++++++++++++
 4 files changed, 155 insertions(+)
 create mode 100644 drivers/reset/reset-tc9564.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ee01aed56508d..8389b11fe6e1a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28355,6 +28355,13 @@ F:	Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.ya
 F:	drivers/soc/toshiba/tc9564-syscon.c
 F:	include/dt-bindings/soc/toshiba,tc9564.h
 
+TOSHIBA TC9564 RESET DRIVER
+M:	Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
+M:	Alex Elder <elder@kernel.org>
+M:	Daniel Thompson <danielt@kernel.org>
+S:	Maintained
+F:	drivers/reset/reset-tc9564.c
+
 TOSHIBA WMI HOTKEYS DRIVER
 M:	Azael Avalos <coproscefalo@gmail.com>
 L:	platform-driver-x86@vger.kernel.org
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index eda9c698a95f3..8c1b08f4eebe6 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -358,6 +358,18 @@ config RESET_SUNXI
 	help
 	  This enables the reset driver for Allwinner SoCs.
 
+config RESET_TC9564
+	tristate "Toshiba TC9564 reset support"
+	depends on SOC_TOSHIBA_TC9564_SYSCON
+	select MFD_SYSCON
+	default SOC_TOSHIBA_TC9564_SYSCON
+	help
+	  This enables support for the reset controller embedded in the
+	  Toshiba TC9564 SoC.  The state of reset lines is controlled
+	  via MMIO to a region managed by a system controller; this
+	  ensures access to the region is coordinated between this and
+	  the clock and XGMAC (stmmac) drivers.
+
 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 489fafd6bbe3f..6ddded26309ef 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_RESET_SKY1_AUDSS) += reset-sky1-audss.o
 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
+obj-$(CONFIG_RESET_TC9564) += reset-tc9564.o
 obj-$(CONFIG_RESET_TENSTORRENT_ATLANTIS) += reset-tenstorrent-atlantis.o
 obj-$(CONFIG_RESET_TH1520) += reset-th1520.o
 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
diff --git a/drivers/reset/reset-tc9564.c b/drivers/reset/reset-tc9564.c
new file mode 100644
index 0000000000000..fcd58d5f1962f
--- /dev/null
+++ b/drivers/reset/reset-tc9564.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2026 by RISCstar Solutions Corporation.  All rights reserved.
+ */
+
+#include <linux/bits.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/soc/toshiba,tc9564.h>
+
+#define RST_CTRL0_OFFSET	0x1008
+#define RST_CTRL1_OFFSET	0x1010
+
+struct tc9564_reset {
+	u32 offset;			/* RST_CTRL0_OFFSET/RST_CTRL1_OFFSET */
+	u32 mask;
+};
+
+#define RESET_INIT0(_name, _bit)	__RESET_INIT(_name, 0, _bit)
+#define RESET_INIT1(_name, _bit)	__RESET_INIT(_name, 1, _bit)
+#define __RESET_INIT(_name, _reg, _bit)			\
+	[RESET_##_name] = {				\
+		.offset	= RST_CTRL ## _reg ## _OFFSET,	\
+		.mask = BIT(_bit),			\
+	}
+
+static const struct tc9564_reset tc9564_reset[] = {
+	RESET_INIT0(MSIGEN, 18),
+
+	RESET_INIT0(MAC0_MAC, 7),
+	RESET_INIT0(MAC0_PMA, 30),
+	RESET_INIT0(MAC0_XPCS, 31),
+
+	RESET_INIT1(MAC1_MAC, 7),
+	RESET_INIT1(MAC1_PMA, 30),
+	RESET_INIT1(MAC1_XPCS, 31),
+};
+#define RESET_COUNT	ARRAY_SIZE(tc9564_reset)
+
+static void reset_manage(struct reset_controller_dev *rcdev,
+			 unsigned long id, bool assert)
+{
+	const struct tc9564_reset *reset = &tc9564_reset[id];
+	struct regmap *regmap = dev_get_drvdata(rcdev->dev);
+	u32 mask = reset->mask;
+
+	regmap_update_bits(regmap, reset->offset, mask, assert ? mask : 0);
+}
+
+static int reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	reset_manage(rcdev, id, true);
+
+	return 0;
+}
+
+static int reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	reset_manage(rcdev, id, false);
+
+	return 0;
+}
+
+static int reset_status(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	const struct tc9564_reset *reset = &tc9564_reset[id];
+	struct regmap *regmap = dev_get_drvdata(rcdev->dev);
+	u32 val;
+
+	regmap_read(regmap, reset->offset, &val);
+
+	return val & reset->mask ? 1 : 0;
+}
+
+static const struct reset_control_ops reset_control_ops = {
+	.assert = reset_assert,
+	.deassert = reset_deassert,
+	.status = reset_status,
+};
+
+static int tc9564_reset_probe(struct platform_device *pdev)
+{
+	struct reset_controller_dev *rcdev;
+	struct device *dev = &pdev->dev;
+	struct device_node *parent_np;
+	struct regmap *regmap;
+	int ret;
+
+	parent_np = dev_of_node(dev->parent);
+	if (!parent_np)
+		return dev_err_probe(dev, -EINVAL, "no devicetree node\n");
+
+	/* Note: MMIO regmap (no error checking needed when used) */
+	regmap = device_node_to_regmap(parent_np);
+	if (IS_ERR(regmap))
+		return dev_err_probe(dev, PTR_ERR(regmap),
+				     "failed to get config regmap\n");
+
+	rcdev = devm_kzalloc_obj(dev, *rcdev);
+	if (!rcdev)
+		return -ENOMEM;
+
+	rcdev->ops = &reset_control_ops;
+	rcdev->owner = THIS_MODULE;
+	rcdev->dev = dev;
+	rcdev->of_node = parent_np;
+	rcdev->nr_resets = RESET_COUNT;
+
+	dev_set_drvdata(dev, regmap);
+
+	ret = devm_reset_controller_register(dev, rcdev);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to register reset controller\n");
+
+	return 0;
+}
+
+static struct platform_driver tc9564_reset_driver = {
+	.probe = tc9564_reset_probe,
+	.driver = {
+		.name = "toshiba-tc9564-reset",
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+};
+module_platform_driver(tc9564_reset_driver);
+
+MODULE_DESCRIPTION("Toshiba TC9564 Reset Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:toshiba-tc9564-reset");
-- 
2.53.0


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

* Re: [PATCH 2/4] soc: toshiba: tc9564: add a new syscon driver
  2026-11-04  0:43 ` [PATCH 2/4] soc: toshiba: tc9564: add a new syscon driver Alex Elder
@ 2026-11-04  0:50   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-11-04  0:50 UTC (permalink / raw)
  To: Alex Elder; +Cc: devicetree, linux-clk, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] soc: toshiba: SOC_TOSHIBA_TC9564_SYSCON depends on hidden MFD_CORE
- [Low] soc: toshiba: MFD driver calling devm_mfd_add_devices() outside drivers/mfd/
- [Low] soc: toshiba: Kconfig help and commit message mismatch tc9564-syscon.c
--

commit 0d303444d1af16f91e36247fd63b0cb020f8be95
Author: Alex Elder <elder@riscstar.com>

soc: toshiba: tc9564: add a new syscon driver

This commit introduces a platform driver for the Toshiba TC9564 config
system controller, registering MFD child devices for the chip's clock
and reset controllers.

> diff --git a/drivers/soc/toshiba/Kconfig b/drivers/soc/toshiba/Kconfig
> new file mode 100644
> index 0000000000000..91adcbe71905c
> --- /dev/null
> +++ b/drivers/soc/toshiba/Kconfig
> @@ -0,0 +1,12 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +config SOC_TOSHIBA_TC9564_SYSCON
> +	tristate "Toshiba TC9564 config system controller support"
> +	depends on TC9564_PCI
> +	depends on MFD_CORE
> +	default TC9564_PCI

[Severity: Medium]
Should SOC_TOSHIBA_TC9564_SYSCON use "select MFD_CORE" instead of
"depends on MFD_CORE"?

In drivers/mfd/Kconfig, MFD_CORE is a promptless helper symbol with
"default n":

    config MFD_CORE
        tristate
        select IRQ_DOMAIN
        default n

When a kernel configuration enables CONFIG_TC9564_PCI without any
unrelated MFD driver that selects MFD_CORE, the dependency on MFD_CORE
remains unmet and SOC_TOSHIBA_TC9564_SYSCON cannot be enabled.
Similarly, if TC9564_PCI is built-in (y) and only modular drivers select
MFD_CORE, SOC_TOSHIBA_TC9564_SYSCON is restricted to modular (m).

> +	help
> +	  This enables support for the config system controller for the
> +	  TC9564 SoC.  It implements an MMIO regmap to manage access to
> +	  two pages of I/O memory, and serves as a clock and reset
> +	  controller for IP blocks within the chip.

[Severity: Low]
Does this help text (and the commit message) accurately describe what
drivers/soc/toshiba/tc9564-syscon.c implements?

In tc9564_config_syscon_probe(), the driver only calls
devm_mfd_add_devices() to register the toshiba-tc9564-clock and
toshiba-tc9564-reset MFD cells; it does not set up an MMIO regmap (nor
does SOC_TOSHIBA_TC9564_SYSCON select MFD_SYSCON) or implement the clock
and reset controller providers itself. Could the help text and commit
description be updated to reflect that this driver instantiates the
clock and reset child devices?

[ ... ]

> diff --git a/drivers/soc/toshiba/tc9564-syscon.c b/drivers/soc/toshiba/tc9564-syscon.c
> new file mode 100644
> index 0000000000000..0d0e2422b82d0
> --- /dev/null
> +++ b/drivers/soc/toshiba/tc9564-syscon.c
> @@ -0,0 +1,42 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +/*
> + * Copyright (C) 2026 by RISCstar Solutions Corporation.  All rights reserved.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/device-id/of.h>
> +#include <linux/mfd/core.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +static const struct mfd_cell tc9564_config_syscon_cells[] = {
> +	MFD_CELL_NAME("toshiba-tc9564-clock"),
> +	MFD_CELL_NAME("toshiba-tc9564-reset"),
> +};
> +
> +static int tc9564_config_syscon_probe(struct platform_device *pdev)
> +{
> +	return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
> +				    tc9564_config_syscon_cells,
> +				    ARRAY_SIZE(tc9564_config_syscon_cells),
> +				    NULL, 0, NULL);
> +}

[Severity: Low]
Since tc9564_config_syscon_probe() in drivers/soc/toshiba/tc9564-syscon.c
is purely an MFD driver calling devm_mfd_add_devices() to register child
devices, should this driver be placed under drivers/mfd/ rather than
drivers/soc/toshiba/ (with an "mfd: tc9564: ..." commit subject prefix)
to follow MFD subsystem placement conventions?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261104004332.2141282-1-elder@riscstar.com?part=2

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

* Re: [PATCH 3/4] clk: toshiba: introduce a TC9564 SoC clock driver
  2026-11-04  0:43 ` [PATCH 3/4] clk: toshiba: introduce a TC9564 SoC clock driver Alex Elder
@ 2026-11-04  0:54   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-11-04  0:54 UTC (permalink / raw)
  To: Alex Elder; +Cc: devicetree, linux-clk, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] clk: tc9564: duplicate clock names across chips due to using dev->id
- [High] clk: tc9564: uninitialized clk_data->num in tc9564_clk_probe()
--

commit d0d52063b982041aca91451199195cd79995784b
Author: Alex Elder <elder@riscstar.com>

clk: toshiba: introduce a TC9564 SoC clock driver

This commit adds a platform clock driver for the Toshiba TC9564 SoC,
registering its PLL, fixed-factor, and gate clocks via a syscon regmap.

> diff --git a/drivers/clk/clk-tc9564.c b/drivers/clk/clk-tc9564.c
> new file mode 100644
> index 0000000000000..8eeba85919703
> --- /dev/null
> +++ b/drivers/clk/clk-tc9564.c
> @@ -0,0 +1,288 @@

[ ... ]

> +/*
> + * The full name of every clock has a prefix "tc9564" followed by a single
> + * character ('a', 'b', etc.) that differs for each chip/device number.
> + * Each clock's "name" defines the unique portion of the clock's full name.
> + */
> +#define FULL_NAME_SIZE	24	/* Enough for formatted full name */
> +#define NAME_SIZE	12	/* Unique portion of the clock name */
> +#define FORMAT_FULL_NAME(_full_name, _id, _name)		\
> +	snprintf(_full_name, FULL_NAME_SIZE, "tc9564%c_%.*s",	\
> +		'a' + (_id), NAME_SIZE, _name)

[ ... ]

> +/* Parent is the input oscillator running at 25 MHz; PLL runs at 1250 MHz */
> +static struct clk_hw *pll_register(struct device *dev,
> +				   const struct clock_init *init)
> +{
> +	char full_name[FULL_NAME_SIZE];
> +
> +	FORMAT_FULL_NAME(full_name, dev->id, init->name);
> +
> +	return devm_clk_hw_register_fixed_factor_index(dev, full_name, 0, 0,
> +						       init->mult, 1);
> +}
> +
> +/* The PLL is the parent of all fixed clocks */
> +static struct clk_hw *fixed_register(struct device *dev,
> +				     const struct clock_init *init)
> +{
> +	struct tc9564_clock *tc9564_clock = dev_get_drvdata(dev);
> +	char full_name[FULL_NAME_SIZE];
> +	struct clk_hw *pll_hw;
> +
> +	FORMAT_FULL_NAME(full_name, dev->id, init->name);

[ ... ]

> +static struct clk_hw *gate_register(struct device *dev,
> +				    const struct clock_init *init)
> +{
> +	struct tc9564_clock *tc9564_clock = dev_get_drvdata(dev);
> +	struct clk_init_data clk_init = { };
> +	const struct clk_hw *parent_hw;
> +	char full_name[FULL_NAME_SIZE];
> +	struct gate_clock *clock;
> +	int ret;
> +
> +	clock = devm_kzalloc_obj(dev, *clock);
> +	if (!clock)
> +		return ERR_PTR(-ENOMEM);
> +
> +	FORMAT_FULL_NAME(full_name, dev->id, init->name);

[Severity: High]
Will passing dev->id to FORMAT_FULL_NAME() in pll_register(),
fixed_register(), and gate_register() cause clock registration to fail with
-EEXIST when more than one TC9564 device is present?

The clock MFD cell is registered as a platform device in
tc9564_config_syscon_probe():

drivers/soc/toshiba/tc9564-syscon.c:tc9564_config_syscon_probe() {
	...
	return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
				    tc9564_config_syscon_cells,
				    ARRAY_SIZE(tc9564_config_syscon_cells),
				    NULL, 0, NULL);
}

For platform devices, the platform bus stores the instance ID in pdev->id
(struct platform_device::id), while dev->id (struct device::id) is never set
and remains 0 for every instance. As a result, every TC9564 device formats
its clocks with the "tc9564a_" prefix (such as "tc9564a_PLL"), so probing a
second TC9564 device collides in __clk_core_init() when registering its
clocks in the global clock namespace.

Note that pdev->id cannot be passed directly to 'a' + (_id) either, because
PLATFORM_DEVID_AUTO allocates IDs from the system-wide platform_devid_ida
shared across all auto-numbered platform devices rather than a 0-based
per-chip index.

> +
> +	parent_hw = tc9564_clock->clk_data->hws[init->parent];
> +
> +	clk_init.name = full_name;
> +	clk_init.ops = &gate_clk_ops;
> +	clk_init.parent_hws = &parent_hw;
> +	clk_init.num_parents = 1;
> +
> +	clock->hw.init = &clk_init;
> +	clock->init = init;
> +
> +	ret = devm_clk_hw_register(dev, &clock->hw);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &clock->hw;
> +}
> +
> +static int tc9564_clk_probe(struct platform_device *pdev)
> +{
> +	struct clk_hw_onecell_data *clk_data;
> +	struct tc9564_clock *tc9564_clock;
> +	struct device *dev = &pdev->dev;
> +	struct device_node *parent_np;
> +	int ret;
> +
> +	parent_np = dev_of_node(dev->parent);
> +	if (!parent_np)
> +		return dev_err_probe(dev, -EINVAL, "no devicetree node\n");
> +
> +	tc9564_clock = devm_kzalloc_obj(dev, *tc9564_clock);
> +	if (!tc9564_clock)
> +		return -ENOMEM;
> +
> +	/* Note: MMIO regmap (no error checking needed when used) */
> +	tc9564_clock->regmap = device_node_to_regmap(parent_np);
> +	if (IS_ERR(tc9564_clock->regmap))
> +		return dev_err_probe(dev, PTR_ERR(tc9564_clock->regmap),
> +				     "failed to get config regmap\n");
> +
> +	clk_data = devm_kzalloc_flex(dev, *tc9564_clock->clk_data, hws,
> +				     CLOCK_COUNT);
> +	if (!clk_data)
> +		return -ENOMEM;
> +	tc9564_clock->clk_data = clk_data;
> +
> +	dev_set_drvdata(dev, tc9564_clock);
> +
> +	/* Initialize all the clocks */
> +	for (u32 i = 0; i < clk_data->num; i++) {

[Severity: High]
Does clk_data->num remain 0 in tc9564_clk_probe() when building with
compilers that do not support __builtin_counted_by_ref?

devm_kzalloc_flex() populates the __counted_by counter via
__set_flex_counter():

include/linux/compiler_types.h:
#if __has_builtin(__builtin_counted_by_ref) && \
    !defined(CONFIG_CC_HAS_BROKEN_COUNTED_BY_REF)
#define __flex_counter(FAM)	__builtin_counted_by_ref(FAM)
#else
#define __flex_counter(FAM)	((void *)NULL)
#endif

include/linux/overflow.h:
#define __set_flex_counter(FAM, COUNT)				\
({								\
	*_Generic(__flex_counter(FAM),				\
		  void *:  &(size_t){ 0 },			\
		  default: __flex_counter(FAM)) = (COUNT);	\
})

On compilers without a working __builtin_counted_by_ref (such as GCC < 15.1
or Clang < 22.1), __set_flex_counter() writes COUNT into a temporary compound
literal and leaves clk_data->num as 0. Without an explicit
clk_data->num = CLOCK_COUNT assignment, the loop in tc9564_clk_probe()
registers zero clocks and of_clk_hw_onecell_get() rejects all clock lookups
with -EINVAL.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261104004332.2141282-1-elder@riscstar.com?part=3

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

* Re: [PATCH 4/4] reset: toshiba: introduce a TC9564 SoC reset driver
  2026-11-04  0:43 ` [PATCH 4/4] reset: toshiba: introduce a TC9564 SoC reset driver Alex Elder
@ 2026-11-04  9:49   ` Philipp Zabel
  0 siblings, 0 replies; 8+ messages in thread
From: Philipp Zabel @ 2026-11-04  9:49 UTC (permalink / raw)
  To: Alex Elder, sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt,
	conor+dt
  Cc: daniel, mohd.anwar, lorenzo.bianconi, fabrice.gasnier,
	alexandre.torgue, marex, changhuang.liang, devicetree, linux-clk,
	linux-kernel

On Di, 2026-11-03 at 18:43 -0600, Alex Elder wrote:
> Define a new platform driver that manages reset signals implemented by
> the Toshiba TC9564 SoC.  There are 13 reset signals available, but
> currently only the resets that are (or will soon be) used are defined
> to be controllable.
> 
> Two registers manage the state of the resets.  The registers are
> accessed via a regmap supplied by a system controller.  Access to
> the memory region is provided via a BAR on a PCIe endpoint function
> embedded in the TC9564 SoC.
> 
> Co-developed-by: Daniel Thompson <daniel@riscstar.com>
> Signed-off-by: Daniel Thompson <daniel@riscstar.com>
> Signed-off-by: Alex Elder <elder@riscstar.com>
> ---
>  MAINTAINERS                  |   7 ++
>  drivers/reset/Kconfig        |  12 ++++
>  drivers/reset/Makefile       |   1 +
>  drivers/reset/reset-tc9564.c | 135 +++++++++++++++++++++++++++++++++++
>  4 files changed, 155 insertions(+)
>  create mode 100644 drivers/reset/reset-tc9564.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ee01aed56508d..8389b11fe6e1a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -28355,6 +28355,13 @@ F:	Documentation/devicetree/bindings/soc/toshiba/toshiba,tc9564-config-syscon.ya
>  F:	drivers/soc/toshiba/tc9564-syscon.c
>  F:	include/dt-bindings/soc/toshiba,tc9564.h
>  
> +TOSHIBA TC9564 RESET DRIVER
> +M:	Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
> +M:	Alex Elder <elder@kernel.org>
> +M:	Daniel Thompson <danielt@kernel.org>
> +S:	Maintained
> +F:	drivers/reset/reset-tc9564.c
> +
>  TOSHIBA WMI HOTKEYS DRIVER
>  M:	Azael Avalos <coproscefalo@gmail.com>
>  L:	platform-driver-x86@vger.kernel.org
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index eda9c698a95f3..8c1b08f4eebe6 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -358,6 +358,18 @@ config RESET_SUNXI
>  	help
>  	  This enables the reset driver for Allwinner SoCs.
>  
> +config RESET_TC9564
> +	tristate "Toshiba TC9564 reset support"
> +	depends on SOC_TOSHIBA_TC9564_SYSCON
> +	select MFD_SYSCON
> +	default SOC_TOSHIBA_TC9564_SYSCON
> +	help
> +	  This enables support for the reset controller embedded in the
> +	  Toshiba TC9564 SoC.  The state of reset lines is controlled
> +	  via MMIO to a region managed by a system controller; this
> +	  ensures access to the region is coordinated between this and
> +	  the clock and XGMAC (stmmac) drivers.

Drop the second sentence, explaining driver details to a user that just
needs to decide whether to enable the driver or not is not helpful.

> +
>  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 489fafd6bbe3f..6ddded26309ef 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -45,6 +45,7 @@ obj-$(CONFIG_RESET_SKY1_AUDSS) += reset-sky1-audss.o
>  obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
>  obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
>  obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
> +obj-$(CONFIG_RESET_TC9564) += reset-tc9564.o
>  obj-$(CONFIG_RESET_TENSTORRENT_ATLANTIS) += reset-tenstorrent-atlantis.o
>  obj-$(CONFIG_RESET_TH1520) += reset-th1520.o
>  obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
> diff --git a/drivers/reset/reset-tc9564.c b/drivers/reset/reset-tc9564.c
> new file mode 100644
> index 0000000000000..fcd58d5f1962f
> --- /dev/null
> +++ b/drivers/reset/reset-tc9564.c
> @@ -0,0 +1,135 @@
[...]
> +static void reset_manage(struct reset_controller_dev *rcdev,
> +			 unsigned long id, bool assert)
> +{
> +	const struct tc9564_reset *reset = &tc9564_reset[id];
> +	struct regmap *regmap = dev_get_drvdata(rcdev->dev);
> +	u32 mask = reset->mask;
> +
> +	regmap_update_bits(regmap, reset->offset, mask, assert ? mask : 0);

Just propagating the error value ...

> +}
> +
> +static int reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> +	reset_manage(rcdev, id, true);
> +
> +	return 0;

... makes this even shorter.

> +}
> +
> +static int reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> +	reset_manage(rcdev, id, false);
> +
> +	return 0;
> +}
> +
> +static int reset_status(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> +	const struct tc9564_reset *reset = &tc9564_reset[id];
> +	struct regmap *regmap = dev_get_drvdata(rcdev->dev);
> +	u32 val;
> +
> +	regmap_read(regmap, reset->offset, &val);
> +
> +	return val & reset->mask ? 1 : 0;

Consider using regmap_test_bits() here.

> +}
> +
> +static const struct reset_control_ops reset_control_ops = {
> +	.assert = reset_assert,
> +	.deassert = reset_deassert,
> +	.status = reset_status,
> +};
> +
> +static int tc9564_reset_probe(struct platform_device *pdev)
> +{
> +	struct reset_controller_dev *rcdev;
> +	struct device *dev = &pdev->dev;
> +	struct device_node *parent_np;
> +	struct regmap *regmap;
> +	int ret;
> +
> +	parent_np = dev_of_node(dev->parent);
> +	if (!parent_np)
> +		return dev_err_probe(dev, -EINVAL, "no devicetree node\n");
> +
> +	/* Note: MMIO regmap (no error checking needed when used) */

I suggest you just add the unneeded error checks and drop this comment.

> +	regmap = device_node_to_regmap(parent_np);

Can't you just use "dev_get_regmap(dev->parent, NULL)" ?

regards
Philipp

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

end of thread, other threads:[~2026-11-04  9:49 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04  0:43 [PATCH 0/4] soc: toshiba: tc9564: config system controller Alex Elder
2026-11-04  0:43 ` [PATCH 1/4] dt-bindings: soc: introduce toshiba,tc9564-config-syscon.yaml Alex Elder
2026-11-04  0:43 ` [PATCH 2/4] soc: toshiba: tc9564: add a new syscon driver Alex Elder
2026-11-04  0:50   ` sashiko-bot
2026-11-04  0:43 ` [PATCH 3/4] clk: toshiba: introduce a TC9564 SoC clock driver Alex Elder
2026-11-04  0:54   ` sashiko-bot
2026-11-04  0:43 ` [PATCH 4/4] reset: toshiba: introduce a TC9564 SoC reset driver Alex Elder
2026-11-04  9:49   ` Philipp Zabel

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