Merge tag 'for-5.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / drivers / clk / mediatek / reset.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014 MediaTek Inc.
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
16 struct mtk_reset {
17         struct regmap *regmap;
18         int regofs;
19         struct reset_controller_dev rcdev;
20 };
21
22 static 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
31 static 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
40 static 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
49 static 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
58 static 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
70 static 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
81 static const struct reset_control_ops mtk_reset_ops = {
82         .assert = mtk_reset_assert,
83         .deassert = mtk_reset_deassert,
84         .reset = mtk_reset,
85 };
86
87 static 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
93 static 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)
96 {
97         struct mtk_reset *data;
98         int ret;
99         struct regmap *regmap;
100
101         regmap = syscon_node_to_regmap(np);
102         if (IS_ERR(regmap)) {
103                 pr_err("Cannot find regmap for %pOF: %ld\n", np,
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;
116         data->rcdev.ops = reset_ops;
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 }
126
127 void 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
134 void 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 }