1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2014 MundoReader S.L.
4 * Author: Heiko Stuebner <heiko@sntech.de>
7 #include <linux/slab.h>
9 #include <linux/reset-controller.h>
10 #include <linux/spinlock.h>
13 struct rockchip_softrst
{
14 struct reset_controller_dev rcdev
;
16 void __iomem
*reg_base
;
23 static int rockchip_softrst_assert(struct reset_controller_dev
*rcdev
,
26 struct rockchip_softrst
*softrst
= container_of(rcdev
,
27 struct rockchip_softrst
,
32 id
= softrst
->lut
[id
];
34 bank
= id
/ softrst
->num_per_reg
;
35 offset
= id
% softrst
->num_per_reg
;
37 if (softrst
->flags
& ROCKCHIP_SOFTRST_HIWORD_MASK
) {
38 writel(BIT(offset
) | (BIT(offset
) << 16),
39 softrst
->reg_base
+ (bank
* 4));
44 spin_lock_irqsave(&softrst
->lock
, flags
);
46 reg
= readl(softrst
->reg_base
+ (bank
* 4));
47 writel(reg
| BIT(offset
), softrst
->reg_base
+ (bank
* 4));
49 spin_unlock_irqrestore(&softrst
->lock
, flags
);
55 static int rockchip_softrst_deassert(struct reset_controller_dev
*rcdev
,
58 struct rockchip_softrst
*softrst
= container_of(rcdev
,
59 struct rockchip_softrst
,
64 id
= softrst
->lut
[id
];
66 bank
= id
/ softrst
->num_per_reg
;
67 offset
= id
% softrst
->num_per_reg
;
69 if (softrst
->flags
& ROCKCHIP_SOFTRST_HIWORD_MASK
) {
70 writel((BIT(offset
) << 16), softrst
->reg_base
+ (bank
* 4));
75 spin_lock_irqsave(&softrst
->lock
, flags
);
77 reg
= readl(softrst
->reg_base
+ (bank
* 4));
78 writel(reg
& ~BIT(offset
), softrst
->reg_base
+ (bank
* 4));
80 spin_unlock_irqrestore(&softrst
->lock
, flags
);
86 static const struct reset_control_ops rockchip_softrst_ops
= {
87 .assert = rockchip_softrst_assert
,
88 .deassert
= rockchip_softrst_deassert
,
91 void rockchip_register_softrst_lut(struct device_node
*np
,
92 const int *lookup_table
,
93 unsigned int num_regs
,
94 void __iomem
*base
, u8 flags
)
96 struct rockchip_softrst
*softrst
;
99 softrst
= kzalloc(sizeof(*softrst
), GFP_KERNEL
);
103 spin_lock_init(&softrst
->lock
);
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
) ? 16
112 softrst
->rcdev
.owner
= THIS_MODULE
;
114 softrst
->rcdev
.nr_resets
= num_regs
;
116 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
);
121 pr_err("%s: could not register reset controller, %d\n",
126 EXPORT_SYMBOL_GPL(rockchip_register_softrst_lut
);