xref: /linux/drivers/reset/reset-tenstorrent-atlantis.c (revision 4ee64205ffaa587e8114d84a67ac721399ccb369)
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");
174