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/mfd/syscon.h>
15 #include <linux/device.h>
20 struct clk_onecell_data
*mtk_alloc_clk_data(unsigned int clk_num
)
23 struct clk_onecell_data
*clk_data
;
25 clk_data
= kzalloc(sizeof(*clk_data
), GFP_KERNEL
);
29 clk_data
->clks
= kcalloc(clk_num
, sizeof(*clk_data
->clks
), GFP_KERNEL
);
33 clk_data
->clk_num
= clk_num
;
35 for (i
= 0; i
< clk_num
; i
++)
36 clk_data
->clks
[i
] = ERR_PTR(-ENOENT
);
45 void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk
*clks
,
46 int num
, struct clk_onecell_data
*clk_data
)
51 for (i
= 0; i
< num
; i
++) {
52 const struct mtk_fixed_clk
*rc
= &clks
[i
];
54 if (clk_data
&& !IS_ERR_OR_NULL(clk_data
->clks
[rc
->id
]))
57 clk
= clk_register_fixed_rate(NULL
, rc
->name
, rc
->parent
, 0,
61 pr_err("Failed to register clk %s: %ld\n",
62 rc
->name
, PTR_ERR(clk
));
67 clk_data
->clks
[rc
->id
] = clk
;
71 void mtk_clk_register_factors(const struct mtk_fixed_factor
*clks
,
72 int num
, struct clk_onecell_data
*clk_data
)
77 for (i
= 0; i
< num
; i
++) {
78 const struct mtk_fixed_factor
*ff
= &clks
[i
];
80 if (clk_data
&& !IS_ERR_OR_NULL(clk_data
->clks
[ff
->id
]))
83 clk
= clk_register_fixed_factor(NULL
, ff
->name
, ff
->parent_name
,
84 CLK_SET_RATE_PARENT
, ff
->mult
, ff
->div
);
87 pr_err("Failed to register clk %s: %ld\n",
88 ff
->name
, PTR_ERR(clk
));
93 clk_data
->clks
[ff
->id
] = clk
;
97 int mtk_clk_register_gates_with_dev(struct device_node
*node
,
98 const struct mtk_gate
*clks
,
99 int num
, struct clk_onecell_data
*clk_data
,
104 struct regmap
*regmap
;
109 regmap
= syscon_node_to_regmap(node
);
110 if (IS_ERR(regmap
)) {
111 pr_err("Cannot find regmap for %pOF: %ld\n", node
,
113 return PTR_ERR(regmap
);
116 for (i
= 0; i
< num
; i
++) {
117 const struct mtk_gate
*gate
= &clks
[i
];
119 if (!IS_ERR_OR_NULL(clk_data
->clks
[gate
->id
]))
122 clk
= mtk_clk_register_gate(gate
->name
, gate
->parent_name
,
127 gate
->shift
, gate
->ops
, gate
->flags
, dev
);
130 pr_err("Failed to register clk %s: %ld\n",
131 gate
->name
, PTR_ERR(clk
));
135 clk_data
->clks
[gate
->id
] = clk
;
141 int mtk_clk_register_gates(struct device_node
*node
,
142 const struct mtk_gate
*clks
,
143 int num
, struct clk_onecell_data
*clk_data
)
145 return mtk_clk_register_gates_with_dev(node
,
146 clks
, num
, clk_data
, NULL
);
149 struct clk
*mtk_clk_register_composite(const struct mtk_composite
*mc
,
150 void __iomem
*base
, spinlock_t
*lock
)
153 struct clk_mux
*mux
= NULL
;
154 struct clk_gate
*gate
= NULL
;
155 struct clk_divider
*div
= NULL
;
156 struct clk_hw
*mux_hw
= NULL
, *gate_hw
= NULL
, *div_hw
= NULL
;
157 const struct clk_ops
*mux_ops
= NULL
, *gate_ops
= NULL
, *div_ops
= NULL
;
158 const char * const *parent_names
;
163 if (mc
->mux_shift
>= 0) {
164 mux
= kzalloc(sizeof(*mux
), GFP_KERNEL
);
166 return ERR_PTR(-ENOMEM
);
168 mux
->reg
= base
+ mc
->mux_reg
;
169 mux
->mask
= BIT(mc
->mux_width
) - 1;
170 mux
->shift
= mc
->mux_shift
;
172 mux
->flags
= mc
->mux_flags
;
174 mux_ops
= &clk_mux_ops
;
176 parent_names
= mc
->parent_names
;
177 num_parents
= mc
->num_parents
;
180 parent_names
= &parent
;
184 if (mc
->gate_shift
>= 0) {
185 gate
= kzalloc(sizeof(*gate
), GFP_KERNEL
);
191 gate
->reg
= base
+ mc
->gate_reg
;
192 gate
->bit_idx
= mc
->gate_shift
;
193 gate
->flags
= CLK_GATE_SET_TO_DISABLE
;
197 gate_ops
= &clk_gate_ops
;
200 if (mc
->divider_shift
>= 0) {
201 div
= kzalloc(sizeof(*div
), GFP_KERNEL
);
207 div
->reg
= base
+ mc
->divider_reg
;
208 div
->shift
= mc
->divider_shift
;
209 div
->width
= mc
->divider_width
;
213 div_ops
= &clk_divider_ops
;
216 clk
= clk_register_composite(NULL
, mc
->name
, parent_names
, num_parents
,
236 void mtk_clk_register_composites(const struct mtk_composite
*mcs
,
237 int num
, void __iomem
*base
, spinlock_t
*lock
,
238 struct clk_onecell_data
*clk_data
)
243 for (i
= 0; i
< num
; i
++) {
244 const struct mtk_composite
*mc
= &mcs
[i
];
246 if (clk_data
&& !IS_ERR_OR_NULL(clk_data
->clks
[mc
->id
]))
249 clk
= mtk_clk_register_composite(mc
, base
, lock
);
252 pr_err("Failed to register clk %s: %ld\n",
253 mc
->name
, PTR_ERR(clk
));
258 clk_data
->clks
[mc
->id
] = clk
;
262 void mtk_clk_register_dividers(const struct mtk_clk_divider
*mcds
,
263 int num
, void __iomem
*base
, spinlock_t
*lock
,
264 struct clk_onecell_data
*clk_data
)
269 for (i
= 0; i
< num
; i
++) {
270 const struct mtk_clk_divider
*mcd
= &mcds
[i
];
272 if (clk_data
&& !IS_ERR_OR_NULL(clk_data
->clks
[mcd
->id
]))
275 clk
= clk_register_divider(NULL
, mcd
->name
, mcd
->parent_name
,
276 mcd
->flags
, base
+ mcd
->div_reg
, mcd
->div_shift
,
277 mcd
->div_width
, mcd
->clk_divider_flags
, lock
);
280 pr_err("Failed to register clk %s: %ld\n",
281 mcd
->name
, PTR_ERR(clk
));
286 clk_data
->clks
[mcd
->id
] = clk
;