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