Merge tag 'imx-fixes-5.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo...
[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(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 }