Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Anirudh Srinivasan and committed by
Drew Fustini
89b23af1 1227a8f6

+186
+1
MAINTAINERS
··· 22812 22812 F: Documentation/devicetree/bindings/clock/tenstorrent,atlantis-prcm-rcpu.yaml 22813 22813 F: Documentation/devicetree/bindings/riscv/tenstorrent.yaml 22814 22814 F: arch/riscv/boot/dts/tenstorrent/ 22815 + F: drivers/reset/reset-tenstorrent-atlantis.c 22815 22816 F: include/dt-bindings/clock/tenstorrent,atlantis-prcm-rcpu.h 22816 22817 22817 22818 RISC-V THEAD SoC SUPPORT
+11
drivers/reset/Kconfig
··· 315 315 help 316 316 This enables the reset driver for Allwinner SoCs. 317 317 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 + 318 329 config RESET_TH1520 319 330 tristate "T-HEAD TH1520 reset controller" 320 331 depends on ARCH_THEAD || COMPILE_TEST
+1
drivers/reset/Makefile
··· 41 41 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o 42 42 obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o 43 43 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o 44 + obj-$(CONFIG_RESET_TENSTORRENT_ATLANTIS) += reset-tenstorrent-atlantis.o 44 45 obj-$(CONFIG_RESET_TH1520) += reset-th1520.o 45 46 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o 46 47 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
+173
drivers/reset/reset-tenstorrent-atlantis.c
··· 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");