diff options
| author | Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com> | 2026-03-06 11:12:18 -0600 |
|---|---|---|
| committer | Drew Fustini <fustini@kernel.org> | 2026-03-09 20:10:26 -0700 |
| commit | 89b23af16276a6d4d06064d72e3fd548de090375 (patch) | |
| tree | 7cc6a0f44ec21b407311d85d0ad7a17aa1c69566 /drivers/reset | |
| parent | 1227a8f6c34e297b5fada96aa140129eced771dc (diff) | |
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>
Diffstat (limited to 'drivers/reset')
| -rw-r--r-- | drivers/reset/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/reset/Makefile | 1 | ||||
| -rw-r--r-- | drivers/reset/reset-tenstorrent-atlantis.c | 173 |
3 files changed, 185 insertions, 0 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 7ce151f6a7e4..85ee9da809ee 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -315,6 +315,17 @@ config RESET_SUNXI help This enables the reset driver for Allwinner SoCs. +config RESET_TENSTORRENT_ATLANTIS + tristate "Tenstorrent atlantis reset driver" + depends on ARCH_TENSTORRENT || COMPILE_TEST + select AUXILIARY_BUS + default ARCH_TENSTORRENT + help + This enables the driver for the reset controller + present in the Tenstorrent Atlantis SoC. + Enable this option to be able to use hardware + resets on Atalantis based systems. + config RESET_TH1520 tristate "T-HEAD TH1520 reset controller" depends on ARCH_THEAD || COMPILE_TEST diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index fc0cc99f8514..7c086baeb02a 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_RESET_SIMPLE) += reset-simple.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_TENSTORRENT_ATLANTIS) += reset-tenstorrent-atlantis.o obj-$(CONFIG_RESET_TH1520) += reset-th1520.o obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o diff --git a/drivers/reset/reset-tenstorrent-atlantis.c b/drivers/reset/reset-tenstorrent-atlantis.c new file mode 100644 index 000000000000..ab8be52fdd5e --- /dev/null +++ b/drivers/reset/reset-tenstorrent-atlantis.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Tenstorrent Atlantis PRCM Reset Driver + * + * Copyright (c) 2026 Tenstorrent + */ + +#include <dt-bindings/clock/tenstorrent,atlantis-prcm-rcpu.h> +#include <linux/auxiliary_bus.h> +#include <linux/reset-controller.h> +#include <linux/regmap.h> + +/* RCPU Reset Register Offsets */ +#define RCPU_BLK_RST_REG 0x001c +#define LSIO_BLK_RST_REG 0x0020 +#define HSIO_BLK_RST_REG 0x000c +#define PCIE_SUBS_RST_REG 0x0000 +#define MM_RSTN_REG 0x0014 + +struct atlantis_reset_data { + u8 bit; + u16 reg; + bool active_low; +}; + +struct atlantis_reset_controller_data { + const struct atlantis_reset_data *reset_data; + size_t count; +}; + +struct atlantis_reset_controller { + struct reset_controller_dev rcdev; + const struct atlantis_reset_controller_data *data; + struct regmap *regmap; +}; + +static inline struct atlantis_reset_controller * +to_atlantis_reset_controller(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct atlantis_reset_controller, rcdev); +} + +#define RESET_DATA(_reg, _bit, _active_low) \ + { \ + .bit = _bit, .reg = _reg, .active_low = _active_low, \ + } + +static const struct atlantis_reset_data atlantis_rcpu_resets[] = { + [RST_SMNDMA0] = RESET_DATA(RCPU_BLK_RST_REG, 0, true), + [RST_SMNDMA1] = RESET_DATA(RCPU_BLK_RST_REG, 1, true), + [RST_WDT0] = RESET_DATA(RCPU_BLK_RST_REG, 2, true), + [RST_WDT1] = RESET_DATA(RCPU_BLK_RST_REG, 3, true), + [RST_TMR] = RESET_DATA(RCPU_BLK_RST_REG, 4, true), + [RST_PVTC] = RESET_DATA(RCPU_BLK_RST_REG, 12, true), + [RST_PMU] = RESET_DATA(RCPU_BLK_RST_REG, 13, true), + [RST_MAILBOX] = RESET_DATA(RCPU_BLK_RST_REG, 14, true), + [RST_SPACC] = RESET_DATA(RCPU_BLK_RST_REG, 26, true), + [RST_OTP] = RESET_DATA(RCPU_BLK_RST_REG, 28, true), + [RST_TRNG] = RESET_DATA(RCPU_BLK_RST_REG, 29, true), + [RST_CRC] = RESET_DATA(RCPU_BLK_RST_REG, 30, true), + [RST_QSPI] = RESET_DATA(LSIO_BLK_RST_REG, 0, true), + [RST_I2C0] = RESET_DATA(LSIO_BLK_RST_REG, 1, true), + [RST_I2C1] = RESET_DATA(LSIO_BLK_RST_REG, 2, true), + [RST_I2C2] = RESET_DATA(LSIO_BLK_RST_REG, 3, true), + [RST_I2C3] = RESET_DATA(LSIO_BLK_RST_REG, 4, true), + [RST_I2C4] = RESET_DATA(LSIO_BLK_RST_REG, 5, true), + [RST_UART0] = RESET_DATA(LSIO_BLK_RST_REG, 6, true), + [RST_UART1] = RESET_DATA(LSIO_BLK_RST_REG, 7, true), + [RST_UART2] = RESET_DATA(LSIO_BLK_RST_REG, 8, true), + [RST_UART3] = RESET_DATA(LSIO_BLK_RST_REG, 9, true), + [RST_UART4] = RESET_DATA(LSIO_BLK_RST_REG, 10, true), + [RST_SPI0] = RESET_DATA(LSIO_BLK_RST_REG, 11, true), + [RST_SPI1] = RESET_DATA(LSIO_BLK_RST_REG, 12, true), + [RST_SPI2] = RESET_DATA(LSIO_BLK_RST_REG, 13, true), + [RST_SPI3] = RESET_DATA(LSIO_BLK_RST_REG, 14, true), + [RST_GPIO] = RESET_DATA(LSIO_BLK_RST_REG, 15, true), + [RST_CAN0] = RESET_DATA(LSIO_BLK_RST_REG, 17, true), + [RST_CAN1] = RESET_DATA(LSIO_BLK_RST_REG, 18, true), + [RST_I2S0] = RESET_DATA(LSIO_BLK_RST_REG, 19, true), + [RST_I2S1] = RESET_DATA(LSIO_BLK_RST_REG, 20, true), + +}; + +static const struct atlantis_reset_controller_data atlantis_rcpu_reset_data = { + .reset_data = atlantis_rcpu_resets, + .count = ARRAY_SIZE(atlantis_rcpu_resets), +}; + +static int atlantis_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + unsigned int val; + struct atlantis_reset_controller *rst = + to_atlantis_reset_controller(rcdev); + const struct atlantis_reset_data *data = &rst->data->reset_data[id]; + unsigned int mask = BIT(data->bit); + struct regmap *regmap = rst->regmap; + + if (data->active_low ^ assert) + val = mask; + else + val = 0; + + return regmap_update_bits(regmap, data->reg, mask, val); +} + +static int atlantis_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return atlantis_reset_update(rcdev, id, true); +} + +static int atlantis_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return atlantis_reset_update(rcdev, id, false); +} + +static const struct reset_control_ops atlantis_reset_control_ops = { + .assert = atlantis_reset_assert, + .deassert = atlantis_reset_deassert, +}; + +static int +atlantis_reset_controller_register(struct device *dev, + struct atlantis_reset_controller *controller) +{ + struct reset_controller_dev *rcdev = &controller->rcdev; + + rcdev->ops = &atlantis_reset_control_ops; + rcdev->owner = THIS_MODULE; + rcdev->of_node = dev->of_node; + rcdev->nr_resets = controller->data->count; + + return devm_reset_controller_register(dev, &controller->rcdev); +} +static int atlantis_reset_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct atlantis_reset_controller *controller; + struct device *dev = &adev->dev; + struct regmap *regmap; + + regmap = dev_get_regmap(dev->parent, NULL); + if (!regmap) + return -ENODEV; + + controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL); + if (!controller) + return -ENOMEM; + controller->data = + (const struct atlantis_reset_controller_data *)id->driver_data; + controller->regmap = regmap; + + return atlantis_reset_controller_register(dev, controller); +} + +static const struct auxiliary_device_id atlantis_reset_ids[] = { + { .name = "atlantis_prcm.rcpu-reset", + .driver_data = (kernel_ulong_t)&atlantis_rcpu_reset_data }, + {}, +}; +MODULE_DEVICE_TABLE(auxiliary, atlantis_reset_ids); + +static struct auxiliary_driver atlantis_reset_driver = { + .probe = atlantis_reset_probe, + .id_table = atlantis_reset_ids, +}; +module_auxiliary_driver(atlantis_reset_driver); + +MODULE_AUTHOR("Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>"); +MODULE_DESCRIPTION("Atlantis PRCM reset controller driver"); +MODULE_LICENSE("GPL"); |
