Skip to content

Commit 89b23af

Browse files
Anirudh Srinivasanpdp7
authored andcommitted
reset: tenstorrent: Add reset controller for Atlantis
Adds Atlantis Reset Controller driver, which shares the same regmap as prcm ( clock controller). This version of the reset controller driver covers resets from the RCPU prcm. Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Acked-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com> Reviewed-by: Drew Fustini <fustini@kernel.org> Signed-off-by: Drew Fustini <fustini@kernel.org>
1 parent 1227a8f commit 89b23af

4 files changed

Lines changed: 186 additions & 0 deletions

File tree

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22812,6 +22812,7 @@ T: git https://github.com/tenstorrent/linux.git
2281222812
F: Documentation/devicetree/bindings/clock/tenstorrent,atlantis-prcm-rcpu.yaml
2281322813
F: Documentation/devicetree/bindings/riscv/tenstorrent.yaml
2281422814
F: arch/riscv/boot/dts/tenstorrent/
22815+
F: drivers/reset/reset-tenstorrent-atlantis.c
2281522816
F: include/dt-bindings/clock/tenstorrent,atlantis-prcm-rcpu.h
2281622817

2281722818
RISC-V THEAD SoC SUPPORT

drivers/reset/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,17 @@ config RESET_SUNXI
315315
help
316316
This enables the reset driver for Allwinner SoCs.
317317

318+
config RESET_TENSTORRENT_ATLANTIS
319+
tristate "Tenstorrent atlantis reset driver"
320+
depends on ARCH_TENSTORRENT || COMPILE_TEST
321+
select AUXILIARY_BUS
322+
default ARCH_TENSTORRENT
323+
help
324+
This enables the driver for the reset controller
325+
present in the Tenstorrent Atlantis SoC.
326+
Enable this option to be able to use hardware
327+
resets on Atalantis based systems.
328+
318329
config RESET_TH1520
319330
tristate "T-HEAD TH1520 reset controller"
320331
depends on ARCH_THEAD || COMPILE_TEST

drivers/reset/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
4141
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
4242
obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
4343
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
44+
obj-$(CONFIG_RESET_TENSTORRENT_ATLANTIS) += reset-tenstorrent-atlantis.o
4445
obj-$(CONFIG_RESET_TH1520) += reset-th1520.o
4546
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
4647
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Tenstorrent Atlantis PRCM Reset Driver
4+
*
5+
* Copyright (c) 2026 Tenstorrent
6+
*/
7+
8+
#include <dt-bindings/clock/tenstorrent,atlantis-prcm-rcpu.h>
9+
#include <linux/auxiliary_bus.h>
10+
#include <linux/reset-controller.h>
11+
#include <linux/regmap.h>
12+
13+
/* RCPU Reset Register Offsets */
14+
#define RCPU_BLK_RST_REG 0x001c
15+
#define LSIO_BLK_RST_REG 0x0020
16+
#define HSIO_BLK_RST_REG 0x000c
17+
#define PCIE_SUBS_RST_REG 0x0000
18+
#define MM_RSTN_REG 0x0014
19+
20+
struct atlantis_reset_data {
21+
u8 bit;
22+
u16 reg;
23+
bool active_low;
24+
};
25+
26+
struct atlantis_reset_controller_data {
27+
const struct atlantis_reset_data *reset_data;
28+
size_t count;
29+
};
30+
31+
struct atlantis_reset_controller {
32+
struct reset_controller_dev rcdev;
33+
const struct atlantis_reset_controller_data *data;
34+
struct regmap *regmap;
35+
};
36+
37+
static inline struct atlantis_reset_controller *
38+
to_atlantis_reset_controller(struct reset_controller_dev *rcdev)
39+
{
40+
return container_of(rcdev, struct atlantis_reset_controller, rcdev);
41+
}
42+
43+
#define RESET_DATA(_reg, _bit, _active_low) \
44+
{ \
45+
.bit = _bit, .reg = _reg, .active_low = _active_low, \
46+
}
47+
48+
static const struct atlantis_reset_data atlantis_rcpu_resets[] = {
49+
[RST_SMNDMA0] = RESET_DATA(RCPU_BLK_RST_REG, 0, true),
50+
[RST_SMNDMA1] = RESET_DATA(RCPU_BLK_RST_REG, 1, true),
51+
[RST_WDT0] = RESET_DATA(RCPU_BLK_RST_REG, 2, true),
52+
[RST_WDT1] = RESET_DATA(RCPU_BLK_RST_REG, 3, true),
53+
[RST_TMR] = RESET_DATA(RCPU_BLK_RST_REG, 4, true),
54+
[RST_PVTC] = RESET_DATA(RCPU_BLK_RST_REG, 12, true),
55+
[RST_PMU] = RESET_DATA(RCPU_BLK_RST_REG, 13, true),
56+
[RST_MAILBOX] = RESET_DATA(RCPU_BLK_RST_REG, 14, true),
57+
[RST_SPACC] = RESET_DATA(RCPU_BLK_RST_REG, 26, true),
58+
[RST_OTP] = RESET_DATA(RCPU_BLK_RST_REG, 28, true),
59+
[RST_TRNG] = RESET_DATA(RCPU_BLK_RST_REG, 29, true),
60+
[RST_CRC] = RESET_DATA(RCPU_BLK_RST_REG, 30, true),
61+
[RST_QSPI] = RESET_DATA(LSIO_BLK_RST_REG, 0, true),
62+
[RST_I2C0] = RESET_DATA(LSIO_BLK_RST_REG, 1, true),
63+
[RST_I2C1] = RESET_DATA(LSIO_BLK_RST_REG, 2, true),
64+
[RST_I2C2] = RESET_DATA(LSIO_BLK_RST_REG, 3, true),
65+
[RST_I2C3] = RESET_DATA(LSIO_BLK_RST_REG, 4, true),
66+
[RST_I2C4] = RESET_DATA(LSIO_BLK_RST_REG, 5, true),
67+
[RST_UART0] = RESET_DATA(LSIO_BLK_RST_REG, 6, true),
68+
[RST_UART1] = RESET_DATA(LSIO_BLK_RST_REG, 7, true),
69+
[RST_UART2] = RESET_DATA(LSIO_BLK_RST_REG, 8, true),
70+
[RST_UART3] = RESET_DATA(LSIO_BLK_RST_REG, 9, true),
71+
[RST_UART4] = RESET_DATA(LSIO_BLK_RST_REG, 10, true),
72+
[RST_SPI0] = RESET_DATA(LSIO_BLK_RST_REG, 11, true),
73+
[RST_SPI1] = RESET_DATA(LSIO_BLK_RST_REG, 12, true),
74+
[RST_SPI2] = RESET_DATA(LSIO_BLK_RST_REG, 13, true),
75+
[RST_SPI3] = RESET_DATA(LSIO_BLK_RST_REG, 14, true),
76+
[RST_GPIO] = RESET_DATA(LSIO_BLK_RST_REG, 15, true),
77+
[RST_CAN0] = RESET_DATA(LSIO_BLK_RST_REG, 17, true),
78+
[RST_CAN1] = RESET_DATA(LSIO_BLK_RST_REG, 18, true),
79+
[RST_I2S0] = RESET_DATA(LSIO_BLK_RST_REG, 19, true),
80+
[RST_I2S1] = RESET_DATA(LSIO_BLK_RST_REG, 20, true),
81+
82+
};
83+
84+
static const struct atlantis_reset_controller_data atlantis_rcpu_reset_data = {
85+
.reset_data = atlantis_rcpu_resets,
86+
.count = ARRAY_SIZE(atlantis_rcpu_resets),
87+
};
88+
89+
static int atlantis_reset_update(struct reset_controller_dev *rcdev,
90+
unsigned long id, bool assert)
91+
{
92+
unsigned int val;
93+
struct atlantis_reset_controller *rst =
94+
to_atlantis_reset_controller(rcdev);
95+
const struct atlantis_reset_data *data = &rst->data->reset_data[id];
96+
unsigned int mask = BIT(data->bit);
97+
struct regmap *regmap = rst->regmap;
98+
99+
if (data->active_low ^ assert)
100+
val = mask;
101+
else
102+
val = 0;
103+
104+
return regmap_update_bits(regmap, data->reg, mask, val);
105+
}
106+
107+
static int atlantis_reset_assert(struct reset_controller_dev *rcdev,
108+
unsigned long id)
109+
{
110+
return atlantis_reset_update(rcdev, id, true);
111+
}
112+
113+
static int atlantis_reset_deassert(struct reset_controller_dev *rcdev,
114+
unsigned long id)
115+
{
116+
return atlantis_reset_update(rcdev, id, false);
117+
}
118+
119+
static const struct reset_control_ops atlantis_reset_control_ops = {
120+
.assert = atlantis_reset_assert,
121+
.deassert = atlantis_reset_deassert,
122+
};
123+
124+
static int
125+
atlantis_reset_controller_register(struct device *dev,
126+
struct atlantis_reset_controller *controller)
127+
{
128+
struct reset_controller_dev *rcdev = &controller->rcdev;
129+
130+
rcdev->ops = &atlantis_reset_control_ops;
131+
rcdev->owner = THIS_MODULE;
132+
rcdev->of_node = dev->of_node;
133+
rcdev->nr_resets = controller->data->count;
134+
135+
return devm_reset_controller_register(dev, &controller->rcdev);
136+
}
137+
static int atlantis_reset_probe(struct auxiliary_device *adev,
138+
const struct auxiliary_device_id *id)
139+
{
140+
struct atlantis_reset_controller *controller;
141+
struct device *dev = &adev->dev;
142+
struct regmap *regmap;
143+
144+
regmap = dev_get_regmap(dev->parent, NULL);
145+
if (!regmap)
146+
return -ENODEV;
147+
148+
controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
149+
if (!controller)
150+
return -ENOMEM;
151+
controller->data =
152+
(const struct atlantis_reset_controller_data *)id->driver_data;
153+
controller->regmap = regmap;
154+
155+
return atlantis_reset_controller_register(dev, controller);
156+
}
157+
158+
static const struct auxiliary_device_id atlantis_reset_ids[] = {
159+
{ .name = "atlantis_prcm.rcpu-reset",
160+
.driver_data = (kernel_ulong_t)&atlantis_rcpu_reset_data },
161+
{},
162+
};
163+
MODULE_DEVICE_TABLE(auxiliary, atlantis_reset_ids);
164+
165+
static struct auxiliary_driver atlantis_reset_driver = {
166+
.probe = atlantis_reset_probe,
167+
.id_table = atlantis_reset_ids,
168+
};
169+
module_auxiliary_driver(atlantis_reset_driver);
170+
171+
MODULE_AUTHOR("Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>");
172+
MODULE_DESCRIPTION("Atlantis PRCM reset controller driver");
173+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)