1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2014 MediaTek Inc.
6 #include <linux/mfd/syscon.h>
7 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/regmap.h>
11 #include <linux/slab.h>
15 static inline struct mtk_clk_rst_data
*to_mtk_clk_rst_data(struct reset_controller_dev
*rcdev
)
17 return container_of(rcdev
, struct mtk_clk_rst_data
, rcdev
);
20 static int mtk_reset_update(struct reset_controller_dev
*rcdev
,
21 unsigned long id
, bool deassert
)
23 struct mtk_clk_rst_data
*data
= to_mtk_clk_rst_data(rcdev
);
24 unsigned int val
= deassert
? 0 : ~0;
26 return regmap_update_bits(data
->regmap
,
27 data
->desc
->rst_bank_ofs
[id
/ RST_NR_PER_BANK
],
28 BIT(id
% RST_NR_PER_BANK
), val
);
31 static int mtk_reset_assert(struct reset_controller_dev
*rcdev
,
34 return mtk_reset_update(rcdev
, id
, false);
37 static int mtk_reset_deassert(struct reset_controller_dev
*rcdev
,
40 return mtk_reset_update(rcdev
, id
, true);
43 static int mtk_reset(struct reset_controller_dev
*rcdev
, unsigned long id
)
47 ret
= mtk_reset_assert(rcdev
, id
);
51 return mtk_reset_deassert(rcdev
, id
);
54 static int mtk_reset_update_set_clr(struct reset_controller_dev
*rcdev
,
55 unsigned long id
, bool deassert
)
57 struct mtk_clk_rst_data
*data
= to_mtk_clk_rst_data(rcdev
);
58 unsigned int deassert_ofs
= deassert
? 0x4 : 0;
60 return regmap_write(data
->regmap
,
61 data
->desc
->rst_bank_ofs
[id
/ RST_NR_PER_BANK
] +
63 BIT(id
% RST_NR_PER_BANK
));
66 static int mtk_reset_assert_set_clr(struct reset_controller_dev
*rcdev
,
69 return mtk_reset_update_set_clr(rcdev
, id
, false);
72 static int mtk_reset_deassert_set_clr(struct reset_controller_dev
*rcdev
,
75 return mtk_reset_update_set_clr(rcdev
, id
, true);
78 static int mtk_reset_set_clr(struct reset_controller_dev
*rcdev
,
83 ret
= mtk_reset_assert_set_clr(rcdev
, id
);
86 return mtk_reset_deassert_set_clr(rcdev
, id
);
89 static const struct reset_control_ops mtk_reset_ops
= {
90 .assert = mtk_reset_assert
,
91 .deassert
= mtk_reset_deassert
,
95 static const struct reset_control_ops mtk_reset_ops_set_clr
= {
96 .assert = mtk_reset_assert_set_clr
,
97 .deassert
= mtk_reset_deassert_set_clr
,
98 .reset
= mtk_reset_set_clr
,
101 static int reset_xlate(struct reset_controller_dev
*rcdev
,
102 const struct of_phandle_args
*reset_spec
)
104 struct mtk_clk_rst_data
*data
= to_mtk_clk_rst_data(rcdev
);
106 if (reset_spec
->args
[0] >= rcdev
->nr_resets
||
107 reset_spec
->args
[0] >= data
->desc
->rst_idx_map_nr
)
110 return data
->desc
->rst_idx_map
[reset_spec
->args
[0]];
113 int mtk_register_reset_controller_with_dev(struct device
*dev
,
114 const struct mtk_clk_rst_desc
*desc
)
116 struct device_node
*np
= dev
->of_node
;
117 struct regmap
*regmap
;
118 const struct reset_control_ops
*rcops
= NULL
;
119 struct mtk_clk_rst_data
*data
;
123 dev_err(dev
, "mtk clock reset desc is NULL\n");
127 switch (desc
->version
) {
129 rcops
= &mtk_reset_ops
;
131 case MTK_RST_SET_CLR
:
132 rcops
= &mtk_reset_ops_set_clr
;
135 dev_err(dev
, "Unknown reset version %d\n", desc
->version
);
139 regmap
= device_node_to_regmap(np
);
140 if (IS_ERR(regmap
)) {
141 dev_err(dev
, "Cannot find regmap %pe\n", regmap
);
142 return PTR_ERR(regmap
);
145 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
150 data
->regmap
= regmap
;
151 data
->rcdev
.owner
= THIS_MODULE
;
152 data
->rcdev
.ops
= rcops
;
153 data
->rcdev
.of_node
= np
;
154 data
->rcdev
.dev
= dev
;
156 if (data
->desc
->rst_idx_map_nr
> 0) {
157 data
->rcdev
.of_reset_n_cells
= 1;
158 data
->rcdev
.nr_resets
= desc
->rst_idx_map_nr
;
159 data
->rcdev
.of_xlate
= reset_xlate
;
161 data
->rcdev
.nr_resets
= desc
->rst_bank_nr
* RST_NR_PER_BANK
;
164 ret
= devm_reset_controller_register(dev
, &data
->rcdev
);
166 dev_err(dev
, "could not register reset controller: %d\n", ret
);
172 EXPORT_SYMBOL_GPL(mtk_register_reset_controller_with_dev
);
174 MODULE_LICENSE("GPL");