^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Simple Reset Controller Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on Allwinner SoCs Reset Controller driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2013 Maxime Ripard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Maxime Ripard <maxime.ripard@free-electrons.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/reset-controller.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/reset/reset-simple.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static inline struct reset_simple_data *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) to_reset_simple_data(struct reset_controller_dev *rcdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return container_of(rcdev, struct reset_simple_data, rcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int reset_simple_update(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) unsigned long id, bool assert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct reset_simple_data *data = to_reset_simple_data(rcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int reg_width = sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int bank = id / (reg_width * BITS_PER_BYTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int offset = id % (reg_width * BITS_PER_BYTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) spin_lock_irqsave(&data->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) reg = readl(data->membase + (bank * reg_width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (assert ^ data->active_low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) reg |= BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) reg &= ~BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) writel(reg, data->membase + (bank * reg_width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) spin_unlock_irqrestore(&data->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int reset_simple_assert(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return reset_simple_update(rcdev, id, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int reset_simple_deassert(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return reset_simple_update(rcdev, id, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int reset_simple_reset(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct reset_simple_data *data = to_reset_simple_data(rcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!data->reset_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ret = reset_simple_assert(rcdev, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) usleep_range(data->reset_us, data->reset_us * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return reset_simple_deassert(rcdev, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int reset_simple_status(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct reset_simple_data *data = to_reset_simple_data(rcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int reg_width = sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int bank = id / (reg_width * BITS_PER_BYTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int offset = id % (reg_width * BITS_PER_BYTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) reg = readl(data->membase + (bank * reg_width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return !(reg & BIT(offset)) ^ !data->status_active_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) const struct reset_control_ops reset_simple_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .assert = reset_simple_assert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .deassert = reset_simple_deassert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .reset = reset_simple_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .status = reset_simple_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) EXPORT_SYMBOL_GPL(reset_simple_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * struct reset_simple_devdata - simple reset controller properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @reg_offset: offset between base address and first reset register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @nr_resets: number of resets. If not set, default to resource size in bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * @active_low: if true, bits are cleared to assert the reset. Otherwise, bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * are set to assert the reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * @status_active_low: if true, bits read back as cleared while the reset is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * asserted. Otherwise, bits read back as set while the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * reset is asserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct reset_simple_devdata {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u32 reg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u32 nr_resets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) bool active_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) bool status_active_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define SOCFPGA_NR_BANKS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const struct reset_simple_devdata reset_simple_socfpga = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .reg_offset = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .nr_resets = SOCFPGA_NR_BANKS * 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .status_active_low = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static const struct reset_simple_devdata reset_simple_active_low = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .active_low = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .status_active_low = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct of_device_id reset_simple_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) { .compatible = "altr,stratix10-rst-mgr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .data = &reset_simple_socfpga },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { .compatible = "st,stm32-rcc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) { .compatible = "allwinner,sun6i-a31-clock-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .data = &reset_simple_active_low },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) { .compatible = "zte,zx296718-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .data = &reset_simple_active_low },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) { .compatible = "aspeed,ast2400-lpc-reset" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { .compatible = "aspeed,ast2500-lpc-reset" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) { .compatible = "bitmain,bm1880-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .data = &reset_simple_active_low },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { .compatible = "snps,dw-high-reset" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { .compatible = "snps,dw-low-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .data = &reset_simple_active_low },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int reset_simple_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) const struct reset_simple_devdata *devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct reset_simple_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) void __iomem *membase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u32 reg_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) devdata = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) membase = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (IS_ERR(membase))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return PTR_ERR(membase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) spin_lock_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) data->membase = membase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) data->rcdev.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) data->rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) data->rcdev.ops = &reset_simple_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) data->rcdev.of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (devdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) reg_offset = devdata->reg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (devdata->nr_resets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) data->rcdev.nr_resets = devdata->nr_resets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) data->active_low = devdata->active_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) data->status_active_low = devdata->status_active_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) data->membase += reg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return devm_reset_controller_register(dev, &data->rcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static struct platform_driver reset_simple_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .probe = reset_simple_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .name = "simple-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .of_match_table = reset_simple_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) builtin_platform_driver(reset_simple_driver);