]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/clk/mediatek/reset.c
UBUNTU: Ubuntu-5.15.0-39.42
[mirror_ubuntu-jammy-kernel.git] / drivers / clk / mediatek / reset.c
CommitLineData
1802d0be 1// SPDX-License-Identifier: GPL-2.0-only
d633fb7a
SH
2/*
3 * Copyright (c) 2014 MediaTek Inc.
d633fb7a
SH
4 */
5
6#include <linux/mfd/syscon.h>
7#include <linux/module.h>
8#include <linux/of.h>
9#include <linux/platform_device.h>
10#include <linux/regmap.h>
11#include <linux/reset-controller.h>
12#include <linux/slab.h>
13
14#include "clk-mtk.h"
15
16struct mtk_reset {
17 struct regmap *regmap;
18 int regofs;
19 struct reset_controller_dev rcdev;
20};
21
64ebb57a 22static int mtk_reset_assert_set_clr(struct reset_controller_dev *rcdev,
23 unsigned long id)
24{
25 struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
26 unsigned int reg = data->regofs + ((id / 32) << 4);
27
28 return regmap_write(data->regmap, reg, 1);
29}
30
31static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev,
32 unsigned long id)
33{
34 struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
35 unsigned int reg = data->regofs + ((id / 32) << 4) + 0x4;
36
37 return regmap_write(data->regmap, reg, 1);
38}
39
d633fb7a
SH
40static int mtk_reset_assert(struct reset_controller_dev *rcdev,
41 unsigned long id)
42{
43 struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
44
45 return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
46 BIT(id % 32), ~0);
47}
48
49static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
50 unsigned long id)
51{
52 struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
53
54 return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
55 BIT(id % 32), 0);
56}
57
58static int mtk_reset(struct reset_controller_dev *rcdev,
59 unsigned long id)
60{
61 int ret;
62
63 ret = mtk_reset_assert(rcdev, id);
64 if (ret)
65 return ret;
66
67 return mtk_reset_deassert(rcdev, id);
68}
69
64ebb57a 70static int mtk_reset_set_clr(struct reset_controller_dev *rcdev,
71 unsigned long id)
72{
73 int ret;
74
75 ret = mtk_reset_assert_set_clr(rcdev, id);
76 if (ret)
77 return ret;
78 return mtk_reset_deassert_set_clr(rcdev, id);
79}
80
f39bb457 81static const struct reset_control_ops mtk_reset_ops = {
d633fb7a
SH
82 .assert = mtk_reset_assert,
83 .deassert = mtk_reset_deassert,
84 .reset = mtk_reset,
85};
86
64ebb57a 87static const struct reset_control_ops mtk_reset_ops_set_clr = {
88 .assert = mtk_reset_assert_set_clr,
89 .deassert = mtk_reset_deassert_set_clr,
90 .reset = mtk_reset_set_clr,
91};
92
93static void mtk_register_reset_controller_common(struct device_node *np,
94 unsigned int num_regs, int regofs,
95 const struct reset_control_ops *reset_ops)
d633fb7a
SH
96{
97 struct mtk_reset *data;
98 int ret;
99 struct regmap *regmap;
100
197ee543 101 regmap = device_node_to_regmap(np);
d633fb7a 102 if (IS_ERR(regmap)) {
16673931 103 pr_err("Cannot find regmap for %pOF: %ld\n", np,
d633fb7a
SH
104 PTR_ERR(regmap));
105 return;
106 }
107
108 data = kzalloc(sizeof(*data), GFP_KERNEL);
109 if (!data)
110 return;
111
112 data->regmap = regmap;
113 data->regofs = regofs;
114 data->rcdev.owner = THIS_MODULE;
115 data->rcdev.nr_resets = num_regs * 32;
64ebb57a 116 data->rcdev.ops = reset_ops;
d633fb7a
SH
117 data->rcdev.of_node = np;
118
119 ret = reset_controller_register(&data->rcdev);
120 if (ret) {
121 pr_err("could not register reset controller: %d\n", ret);
122 kfree(data);
123 return;
124 }
125}
64ebb57a 126
127void mtk_register_reset_controller(struct device_node *np,
128 unsigned int num_regs, int regofs)
129{
130 mtk_register_reset_controller_common(np, num_regs, regofs,
131 &mtk_reset_ops);
132}
133
134void mtk_register_reset_controller_set_clr(struct device_node *np,
135 unsigned int num_regs, int regofs)
136{
137 mtk_register_reset_controller_common(np, num_regs, regofs,
138 &mtk_reset_ops_set_clr);
139}