1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2014 MediaTek Inc.
4 * Author: James Liao <jamesjj.liao@mediatek.com>
8 #include <linux/of_address.h>
11 #include <linux/slab.h>
12 #include <linux/delay.h>
13 #include <linux/clkdev.h>
14 #include <linux/module.h>
19 static u32 mtk_get_clockgating(struct clk_hw *hw)
21 struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
24 regmap_read(cg->regmap, cg->sta_ofs, &val);
26 return val & BIT(cg->bit);
29 static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
31 return mtk_get_clockgating(hw) == 0;
34 static int mtk_cg_bit_is_set(struct clk_hw *hw)
36 return mtk_get_clockgating(hw) != 0;
39 static void mtk_cg_set_bit(struct clk_hw *hw)
41 struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
43 regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
46 static void mtk_cg_clr_bit(struct clk_hw *hw)
48 struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
50 regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
53 static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
55 struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
57 regmap_set_bits(cg->regmap, cg->sta_ofs, BIT(cg->bit));
60 static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
62 struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
64 regmap_clear_bits(cg->regmap, cg->sta_ofs, BIT(cg->bit));
67 static int mtk_cg_enable(struct clk_hw *hw)
74 static void mtk_cg_disable(struct clk_hw *hw)
79 static int mtk_cg_enable_inv(struct clk_hw *hw)
86 static void mtk_cg_disable_inv(struct clk_hw *hw)
91 static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
93 mtk_cg_clr_bit_no_setclr(hw);
98 static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
100 mtk_cg_set_bit_no_setclr(hw);
103 static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
105 mtk_cg_set_bit_no_setclr(hw);
110 static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
112 mtk_cg_clr_bit_no_setclr(hw);
115 const struct clk_ops mtk_clk_gate_ops_setclr = {
116 .is_enabled = mtk_cg_bit_is_cleared,
117 .enable = mtk_cg_enable,
118 .disable = mtk_cg_disable,
120 EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_setclr);
122 const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
123 .is_enabled = mtk_cg_bit_is_set,
124 .enable = mtk_cg_enable_inv,
125 .disable = mtk_cg_disable_inv,
127 EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_setclr_inv);
129 const struct clk_ops mtk_clk_gate_ops_no_setclr = {
130 .is_enabled = mtk_cg_bit_is_cleared,
131 .enable = mtk_cg_enable_no_setclr,
132 .disable = mtk_cg_disable_no_setclr,
134 EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr);
136 const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
137 .is_enabled = mtk_cg_bit_is_set,
138 .enable = mtk_cg_enable_inv_no_setclr,
139 .disable = mtk_cg_disable_inv_no_setclr,
141 EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr_inv);
143 struct clk *mtk_clk_register_gate(
145 const char *parent_name,
146 struct regmap *regmap,
151 const struct clk_ops *ops,
155 struct mtk_clk_gate *cg;
157 struct clk_init_data init = {};
159 cg = kzalloc(sizeof(*cg), GFP_KERNEL);
161 return ERR_PTR(-ENOMEM);
164 init.flags = flags | CLK_SET_RATE_PARENT;
165 init.parent_names = parent_name ? &parent_name : NULL;
166 init.num_parents = parent_name ? 1 : 0;
170 cg->set_ofs = set_ofs;
171 cg->clr_ofs = clr_ofs;
172 cg->sta_ofs = sta_ofs;
177 clk = clk_register(dev, &cg->hw);
183 EXPORT_SYMBOL_GPL(mtk_clk_register_gate);
185 MODULE_LICENSE("GPL");