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