xref: /openbmc/linux/drivers/clk/mediatek/reset.c (revision 50df3be7)
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 }
140