From ace9429bb58fd418f0c81d4c2835699bddf6bde6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:27:49 +0200 Subject: Adding upstream version 6.6.15. Signed-off-by: Daniel Baumann --- drivers/clk/rockchip/softrst.c | 126 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 drivers/clk/rockchip/softrst.c (limited to 'drivers/clk/rockchip/softrst.c') diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c new file mode 100644 index 0000000000..fd56aaefe6 --- /dev/null +++ b/drivers/clk/rockchip/softrst.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner + */ + +#include +#include +#include +#include +#include "clk.h" + +struct rockchip_softrst { + struct reset_controller_dev rcdev; + const int *lut; + void __iomem *reg_base; + int num_regs; + int num_per_reg; + u8 flags; + spinlock_t lock; +}; + +static int rockchip_softrst_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rockchip_softrst *softrst = container_of(rcdev, + struct rockchip_softrst, + rcdev); + int bank, offset; + + if (softrst->lut) + id = softrst->lut[id]; + + bank = id / softrst->num_per_reg; + offset = id % softrst->num_per_reg; + + if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) { + writel(BIT(offset) | (BIT(offset) << 16), + softrst->reg_base + (bank * 4)); + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&softrst->lock, flags); + + reg = readl(softrst->reg_base + (bank * 4)); + writel(reg | BIT(offset), softrst->reg_base + (bank * 4)); + + spin_unlock_irqrestore(&softrst->lock, flags); + } + + return 0; +} + +static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rockchip_softrst *softrst = container_of(rcdev, + struct rockchip_softrst, + rcdev); + int bank, offset; + + if (softrst->lut) + id = softrst->lut[id]; + + bank = id / softrst->num_per_reg; + offset = id % softrst->num_per_reg; + + if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) { + writel((BIT(offset) << 16), softrst->reg_base + (bank * 4)); + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&softrst->lock, flags); + + reg = readl(softrst->reg_base + (bank * 4)); + writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4)); + + spin_unlock_irqrestore(&softrst->lock, flags); + } + + return 0; +} + +static const struct reset_control_ops rockchip_softrst_ops = { + .assert = rockchip_softrst_assert, + .deassert = rockchip_softrst_deassert, +}; + +void rockchip_register_softrst_lut(struct device_node *np, + const int *lookup_table, + unsigned int num_regs, + void __iomem *base, u8 flags) +{ + struct rockchip_softrst *softrst; + int ret; + + softrst = kzalloc(sizeof(*softrst), GFP_KERNEL); + if (!softrst) + return; + + spin_lock_init(&softrst->lock); + + softrst->reg_base = base; + softrst->lut = lookup_table; + softrst->flags = flags; + softrst->num_regs = num_regs; + softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16 + : 32; + + softrst->rcdev.owner = THIS_MODULE; + if (lookup_table) + softrst->rcdev.nr_resets = num_regs; + else + softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg; + softrst->rcdev.ops = &rockchip_softrst_ops; + softrst->rcdev.of_node = np; + ret = reset_controller_register(&softrst->rcdev); + if (ret) { + pr_err("%s: could not register reset controller, %d\n", + __func__, ret); + kfree(softrst); + } +}; +EXPORT_SYMBOL_GPL(rockchip_register_softrst_lut); -- cgit v1.2.3