From: Alex Elder <elder@riscstar.com>
To: p.zabel@pengutronix.de, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org
Cc: mohd.anwar@oss.qualcomm.com, lorenzo.bianconi@oss.qualcomm.com,
danielt@kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Daniel Thompson <daniel@riscstar.com>
Subject: [PATCH 2/2] reset: toshiba: introduce a TC9564 SoC reset driver
Date: Mon, 12 Oct 2026 11:43:53 -0500 [thread overview]
Message-ID: <20261012164354.3872326-3-elder@riscstar.com> (raw)
In-Reply-To: <20261012164354.3872326-1-elder@riscstar.com>
Define a new platform driver that manages reset signals implemented by
the Toshiba TC9564 SoC. There are 13 reset signals available, although
only 11 can be controlled.
Two registers manage the state of the resets. The registers are
accessed via a regmap supplied by a system controller, because the
region of memory accessed is shared with other drivers.
Access to the memory region is provided via a BAR on a PCIe endpoint
function embedded in the TC9564 SoC. For that reason the PCIe reset
cannot be manipulated by this driver (it is assumed to be deasserted).
Similarly, control is not available for the I2C reset, because the
PCIe subsystem on the TC9564 relies on I2C.
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 | 1 +
drivers/reset/Kconfig | 12 +++
drivers/reset/Makefile | 1 +
drivers/reset/reset-tc9564.c | 192 +++++++++++++++++++++++++++++++++++
4 files changed, 206 insertions(+)
create mode 100644 drivers/reset/reset-tc9564.c
diff --git a/MAINTAINERS b/MAINTAINERS
index d0eb44079fe17..a8f4982ed1a43 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28185,6 +28185,7 @@ M: Alex Elder <elder@kernel.org>
M: Daniel Thompson <danielt@kernel.org>
S: Maintained
F: Documentation/devicetree/bindings/reset/toshiba,tc9564-reset.yaml
+F: drivers/reset/reset-tc9564.c
F: include/dt-bindings/reset/toshiba,tc9564.h
TOSHIBA WMI HOTKEYS DRIVER
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index eda9c698a95f3..b40736368894c 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 TC9564_PCI
+ select MFD_SYSCON
+ default TC9564_PCI
+ 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..0243c2e0efd54
--- /dev/null
+++ b/drivers/reset/reset-tc9564.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2026 by RISCstar Solutions Corporation. All rights reserved.
+ */
+
+#include <linux/bits.h>
+#include <linux/device-id/of.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/reset/toshiba,tc9564.h>
+
+#define RST_CTRL0_OFFSET 0x1008
+#define RST_CTRL1_OFFSET 0x1010
+
+struct tc9564_reset {
+ u32 offset; /* RST_CTRL0_OFFSET or RST_CTRL1_OFFSET */
+ u32 mask; /* Zero means undefined reset */
+};
+
+struct tc9564_resets {
+ struct regmap *regmap;
+ struct reset_controller_dev rcdev;
+};
+
+#define TC9564_RESET_INIT0(_name, _bit) __TC9564_RESET_INIT(_name, 0, _bit)
+#define TC9564_RESET_INIT1(_name, _bit) __TC9564_RESET_INIT(_name, 1, _bit)
+
+#define __TC9564_RESET_INIT(_name, _reg, _bit) \
+ [RESET_##_name] = { \
+ .offset = RST_CTRL ## _reg ## _OFFSET, \
+ .mask = BIT(_bit), \
+ }
+
+/*
+ * The PCIe and I2C resets are controllable, but we depend on PCIe
+ * and that relies on I2C, so we don't allow them to be asserted.
+ */
+static const struct tc9564_reset tc9564_reset[] = {
+ TC9564_RESET_INIT0(MCU, 0),
+ TC9564_RESET_INIT0(MCU1, 1),
+ TC9564_RESET_INIT0(INTC, 4),
+ /* TC9564_RESET_INIT0(PCIE, 9), */
+ /* TC9564_RESET_INIT0(I2C, 12), */
+ TC9564_RESET_INIT0(UART, 16),
+ TC9564_RESET_INIT0(MSIGEN, 18),
+
+ TC9564_RESET_INIT0(MAC0_MAC, 7),
+ TC9564_RESET_INIT0(MAC0_PMA, 30),
+ TC9564_RESET_INIT0(MAC0_XPCS, 31),
+
+ TC9564_RESET_INIT1(MAC1_MAC, 7),
+ TC9564_RESET_INIT1(MAC1_PMA, 30),
+ TC9564_RESET_INIT1(MAC1_XPCS, 31),
+};
+#define TC9564_RESET_COUNT ARRAY_SIZE(tc9564_reset)
+
+static const struct tc9564_resets *
+rcdev_to_tc9564_resets(struct reset_controller_dev *rcdev)
+{
+ return container_of_const(rcdev, struct tc9564_resets, rcdev);
+}
+
+static int tc9564_reset_manage(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ const struct tc9564_resets *resets = rcdev_to_tc9564_resets(rcdev);
+
+ if (id < rcdev->nr_resets) {
+ const struct tc9564_reset *reset = &tc9564_reset[id];
+ u32 mask = reset->mask;
+
+ if (mask)
+ return regmap_update_bits(resets->regmap,
+ reset->offset, mask,
+ assert ? mask : 0);
+ }
+
+ dev_err(rcdev->dev, "invalid reset (%s id %lu)\n",
+ assert ? "assert" : "deassert", id);
+
+ return -ENXIO;
+}
+
+static int tc9564_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return tc9564_reset_manage(rcdev, id, true);
+}
+
+static int tc9564_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return tc9564_reset_manage(rcdev, id, false);
+}
+
+static const struct reset_control_ops tc9564_reset_control_ops = {
+ .assert = tc9564_reset_assert,
+ .deassert = tc9564_reset_deassert,
+};
+
+static void tc9564_reset_assert_all(struct tc9564_resets *resets)
+{
+ for (u32 id = 0; id < TC9564_RESET_COUNT; id++)
+ if (tc9564_reset[id].mask)
+ tc9564_reset_manage(&resets->rcdev, id, true);
+}
+
+static struct tc9564_resets *tc9564_reset_init(struct device *dev)
+{
+ struct reset_controller_dev *rcdev;
+ struct tc9564_resets *resets;
+ struct regmap *regmap;
+ int ret;
+
+ regmap = syscon_node_to_regmap(dev_of_node(dev->parent));
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "failed to get config regmap\n");
+ return ERR_CAST(regmap);
+ }
+
+ resets = devm_kzalloc(dev, sizeof(*resets), GFP_KERNEL);
+ if (!resets)
+ return ERR_PTR(-ENOMEM);
+ resets->regmap = regmap;
+
+ rcdev = &resets->rcdev;
+ rcdev->ops = &tc9564_reset_control_ops;
+ rcdev->owner = THIS_MODULE;
+ rcdev->dev = dev;
+ rcdev->of_node = dev_of_node(dev);
+ rcdev->nr_resets = TC9564_RESET_COUNT;
+
+ ret = devm_reset_controller_register(dev, rcdev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return resets;
+}
+
+static int tc9564_reset_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct tc9564_resets *resets;
+
+ if (!dev_of_node(dev))
+ return dev_err_probe(dev, -EINVAL, "no devicetree node\n");
+
+ resets = tc9564_reset_init(dev);
+ if (IS_ERR(resets))
+ return dev_err_probe(dev, PTR_ERR(resets),
+ "failed to initialize resets\n");
+
+ /* Force all resets to be initially asserted */
+ tc9564_reset_assert_all(resets);
+
+ platform_set_drvdata(pdev, resets);
+
+ return 0;
+}
+
+static void tc9564_reset_remove(struct platform_device *pdev)
+{
+ struct tc9564_resets *resets = platform_get_drvdata(pdev);
+
+ /* Leave all resets asserted when done */
+ tc9564_reset_assert_all(resets);
+}
+
+static const struct of_device_id tc9564_reset_ids[] = {
+ { .compatible = "toshiba,tc9564-reset" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tc9564_reset_ids);
+
+static struct platform_driver tc9564_reset_driver = {
+ .probe = tc9564_reset_probe,
+ .remove = tc9564_reset_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = tc9564_reset_ids,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+};
+module_platform_driver(tc9564_reset_driver);
+
+MODULE_DESCRIPTION("Toshiba TC9564 Reset Driver");
+MODULE_LICENSE("GPL");
--
2.53.0
next prev parent reply other threads:[~2026-10-12 16:44 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 16:43 [PATCH 0/2] reset: introduce TC9564 reset support Alex Elder
2026-10-12 16:43 ` [PATCH 1/2] dt-bindings: reset: introduce toshiba,tc9564-reset.yaml Alex Elder
2026-10-12 18:51 ` Conor Dooley
2026-10-12 19:10 ` Alex Elder
2026-10-12 21:22 ` Conor Dooley
2026-10-13 13:22 ` Alex Elder
2026-10-13 17:51 ` Conor Dooley
2026-10-13 9:25 ` Krzysztof Kozlowski
2026-10-12 16:43 ` Alex Elder [this message]
2026-10-13 13:28 ` [PATCH 2/2] reset: toshiba: introduce a TC9564 SoC reset driver Philipp Zabel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261012164354.3872326-3-elder@riscstar.com \
--to=elder@riscstar.com \
--cc=conor+dt@kernel.org \
--cc=daniel@riscstar.com \
--cc=danielt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lorenzo.bianconi@oss.qualcomm.com \
--cc=mohd.anwar@oss.qualcomm.com \
--cc=p.zabel@pengutronix.de \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®