^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) * Copyright (c) 2014 MundoReader S.L.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Heiko Stuebner <heiko@sntech.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/reset-controller.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct rockchip_softrst {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct reset_controller_dev rcdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) void __iomem *reg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) int num_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int num_per_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u8 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct rockchip_softrst *softrst = container_of(rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct rockchip_softrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) rcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int bank = id / softrst->num_per_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int offset = id % softrst->num_per_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) writel(BIT(offset) | (BIT(offset) << 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) softrst->reg_base + (bank * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) spin_lock_irqsave(&softrst->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) reg = readl(softrst->reg_base + (bank * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) writel(reg | BIT(offset), softrst->reg_base + (bank * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) spin_unlock_irqrestore(&softrst->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct rockchip_softrst *softrst = container_of(rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct rockchip_softrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) rcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int bank = id / softrst->num_per_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int offset = id % softrst->num_per_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) spin_lock_irqsave(&softrst->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) reg = readl(softrst->reg_base + (bank * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) spin_unlock_irqrestore(&softrst->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const struct reset_control_ops rockchip_softrst_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .assert = rockchip_softrst_assert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .deassert = rockchip_softrst_deassert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void rockchip_register_softrst(struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int num_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) void __iomem *base, u8 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct rockchip_softrst *softrst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) softrst = kzalloc(sizeof(*softrst), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!softrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) spin_lock_init(&softrst->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) softrst->reg_base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) softrst->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) softrst->num_regs = num_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) : 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) softrst->rcdev.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) softrst->rcdev.ops = &rockchip_softrst_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) softrst->rcdev.of_node = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ret = reset_controller_register(&softrst->rcdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) pr_err("%s: could not register reset controller, %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) kfree(softrst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) EXPORT_SYMBOL_GPL(rockchip_register_softrst);