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