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>
18 static int mtk_cg_bit_is_cleared(struct clk_hw
*hw
)
20 struct mtk_clk_gate
*cg
= to_mtk_clk_gate(hw
);
23 regmap_read(cg
->regmap
, cg
->sta_ofs
, &val
);
30 static int mtk_cg_bit_is_set(struct clk_hw
*hw
)
32 struct mtk_clk_gate
*cg
= to_mtk_clk_gate(hw
);
35 regmap_read(cg
->regmap
, cg
->sta_ofs
, &val
);
42 static void mtk_cg_set_bit(struct clk_hw
*hw
)
44 struct mtk_clk_gate
*cg
= to_mtk_clk_gate(hw
);
46 regmap_write(cg
->regmap
, cg
->set_ofs
, BIT(cg
->bit
));
49 static void mtk_cg_clr_bit(struct clk_hw
*hw
)
51 struct mtk_clk_gate
*cg
= to_mtk_clk_gate(hw
);
53 regmap_write(cg
->regmap
, cg
->clr_ofs
, BIT(cg
->bit
));
56 static void mtk_cg_set_bit_no_setclr(struct clk_hw
*hw
)
58 struct mtk_clk_gate
*cg
= to_mtk_clk_gate(hw
);
59 u32 cgbit
= BIT(cg
->bit
);
61 regmap_update_bits(cg
->regmap
, cg
->sta_ofs
, cgbit
, cgbit
);
64 static void mtk_cg_clr_bit_no_setclr(struct clk_hw
*hw
)
66 struct mtk_clk_gate
*cg
= to_mtk_clk_gate(hw
);
67 u32 cgbit
= BIT(cg
->bit
);
69 regmap_update_bits(cg
->regmap
, cg
->sta_ofs
, cgbit
, 0);
72 static int mtk_cg_enable(struct clk_hw
*hw
)
79 static void mtk_cg_disable(struct clk_hw
*hw
)
84 static int mtk_cg_enable_inv(struct clk_hw
*hw
)
91 static void mtk_cg_disable_inv(struct clk_hw
*hw
)
96 static int mtk_cg_enable_no_setclr(struct clk_hw
*hw
)
98 mtk_cg_clr_bit_no_setclr(hw
);
103 static void mtk_cg_disable_no_setclr(struct clk_hw
*hw
)
105 mtk_cg_set_bit_no_setclr(hw
);
108 static int mtk_cg_enable_inv_no_setclr(struct clk_hw
*hw
)
110 mtk_cg_set_bit_no_setclr(hw
);
115 static void mtk_cg_disable_inv_no_setclr(struct clk_hw
*hw
)
117 mtk_cg_clr_bit_no_setclr(hw
);
120 const struct clk_ops mtk_clk_gate_ops_setclr
= {
121 .is_enabled
= mtk_cg_bit_is_cleared
,
122 .enable
= mtk_cg_enable
,
123 .disable
= mtk_cg_disable
,
126 const struct clk_ops mtk_clk_gate_ops_setclr_inv
= {
127 .is_enabled
= mtk_cg_bit_is_set
,
128 .enable
= mtk_cg_enable_inv
,
129 .disable
= mtk_cg_disable_inv
,
132 const struct clk_ops mtk_clk_gate_ops_no_setclr
= {
133 .is_enabled
= mtk_cg_bit_is_cleared
,
134 .enable
= mtk_cg_enable_no_setclr
,
135 .disable
= mtk_cg_disable_no_setclr
,
138 const struct clk_ops mtk_clk_gate_ops_no_setclr_inv
= {
139 .is_enabled
= mtk_cg_bit_is_set
,
140 .enable
= mtk_cg_enable_inv_no_setclr
,
141 .disable
= mtk_cg_disable_inv_no_setclr
,
144 struct clk
*mtk_clk_register_gate(
146 const char *parent_name
,
147 struct regmap
*regmap
,
152 const struct clk_ops
*ops
,
156 struct mtk_clk_gate
*cg
;
158 struct clk_init_data init
= {};
160 cg
= kzalloc(sizeof(*cg
), GFP_KERNEL
);
162 return ERR_PTR(-ENOMEM
);
165 init
.flags
= flags
| CLK_SET_RATE_PARENT
;
166 init
.parent_names
= parent_name
? &parent_name
: NULL
;
167 init
.num_parents
= parent_name
? 1 : 0;
171 cg
->set_ofs
= set_ofs
;
172 cg
->clr_ofs
= clr_ofs
;
173 cg
->sta_ofs
= sta_ofs
;
178 clk
= clk_register(dev
, &cg
->hw
);