xref: /linux/drivers/clk/mediatek/reset.c (revision 44f57d78)
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(struct reset_controller_dev *rcdev,
23 			      unsigned long id)
24 {
25 	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
26 
27 	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
28 			BIT(id % 32), ~0);
29 }
30 
31 static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
32 				unsigned long id)
33 {
34 	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
35 
36 	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
37 			BIT(id % 32), 0);
38 }
39 
40 static int mtk_reset(struct reset_controller_dev *rcdev,
41 			      unsigned long id)
42 {
43 	int ret;
44 
45 	ret = mtk_reset_assert(rcdev, id);
46 	if (ret)
47 		return ret;
48 
49 	return mtk_reset_deassert(rcdev, id);
50 }
51 
52 static const struct reset_control_ops mtk_reset_ops = {
53 	.assert = mtk_reset_assert,
54 	.deassert = mtk_reset_deassert,
55 	.reset = mtk_reset,
56 };
57 
58 void mtk_register_reset_controller(struct device_node *np,
59 			unsigned int num_regs, int regofs)
60 {
61 	struct mtk_reset *data;
62 	int ret;
63 	struct regmap *regmap;
64 
65 	regmap = syscon_node_to_regmap(np);
66 	if (IS_ERR(regmap)) {
67 		pr_err("Cannot find regmap for %pOF: %ld\n", np,
68 				PTR_ERR(regmap));
69 		return;
70 	}
71 
72 	data = kzalloc(sizeof(*data), GFP_KERNEL);
73 	if (!data)
74 		return;
75 
76 	data->regmap = regmap;
77 	data->regofs = regofs;
78 	data->rcdev.owner = THIS_MODULE;
79 	data->rcdev.nr_resets = num_regs * 32;
80 	data->rcdev.ops = &mtk_reset_ops;
81 	data->rcdev.of_node = np;
82 
83 	ret = reset_controller_register(&data->rcdev);
84 	if (ret) {
85 		pr_err("could not register reset controller: %d\n", ret);
86 		kfree(data);
87 		return;
88 	}
89 }
90