1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Hisilicon clock driver
5 * Copyright (c) 2012-2013 Hisilicon Limited.
6 * Copyright (c) 2012-2013 Linaro Limited.
12 #include <linux/kernel.h>
13 #include <linux/clkdev.h>
14 #include <linux/clk-provider.h>
15 #include <linux/delay.h>
18 #include <linux/of_address.h>
19 #include <linux/of_device.h>
20 #include <linux/slab.h>
24 static DEFINE_SPINLOCK(hisi_clk_lock);
26 struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
29 struct hisi_clock_data *clk_data;
31 struct clk **clk_table;
33 clk_data = devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
37 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
40 clk_data->base = devm_ioremap(&pdev->dev,
41 res->start, resource_size(res));
45 clk_table = devm_kmalloc_array(&pdev->dev, nr_clks,
51 clk_data->clk_data.clks = clk_table;
52 clk_data->clk_data.clk_num = nr_clks;
56 EXPORT_SYMBOL_GPL(hisi_clk_alloc);
58 struct hisi_clock_data *hisi_clk_init(struct device_node *np,
61 struct hisi_clock_data *clk_data;
62 struct clk **clk_table;
65 base = of_iomap(np, 0);
67 pr_err("%s: failed to map clock registers\n", __func__);
71 clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
75 clk_data->base = base;
76 clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
80 clk_data->clk_data.clks = clk_table;
81 clk_data->clk_data.clk_num = nr_clks;
82 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
89 EXPORT_SYMBOL_GPL(hisi_clk_init);
91 int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
92 int nums, struct hisi_clock_data *data)
97 for (i = 0; i < nums; i++) {
98 clk = clk_register_fixed_rate(NULL, clks[i].name,
103 pr_err("%s: failed to register clock %s\n",
104 __func__, clks[i].name);
107 data->clk_data.clks[clks[i].id] = clk;
114 clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]);
118 EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);
120 int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
122 struct hisi_clock_data *data)
127 for (i = 0; i < nums; i++) {
128 clk = clk_register_fixed_factor(NULL, clks[i].name,
130 clks[i].flags, clks[i].mult,
133 pr_err("%s: failed to register clock %s\n",
134 __func__, clks[i].name);
137 data->clk_data.clks[clks[i].id] = clk;
144 clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]);
148 EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);
150 int hisi_clk_register_mux(const struct hisi_mux_clock *clks,
151 int nums, struct hisi_clock_data *data)
154 void __iomem *base = data->base;
157 for (i = 0; i < nums; i++) {
158 u32 mask = BIT(clks[i].width) - 1;
160 clk = clk_register_mux_table(NULL, clks[i].name,
161 clks[i].parent_names,
162 clks[i].num_parents, clks[i].flags,
163 base + clks[i].offset, clks[i].shift,
164 mask, clks[i].mux_flags,
165 clks[i].table, &hisi_clk_lock);
167 pr_err("%s: failed to register clock %s\n",
168 __func__, clks[i].name);
173 clk_register_clkdev(clk, clks[i].alias, NULL);
175 data->clk_data.clks[clks[i].id] = clk;
182 clk_unregister_mux(data->clk_data.clks[clks[i].id]);
186 EXPORT_SYMBOL_GPL(hisi_clk_register_mux);
188 int hisi_clk_register_phase(struct device *dev,
189 const struct hisi_phase_clock *clks,
190 int nums, struct hisi_clock_data *data)
192 void __iomem *base = data->base;
196 for (i = 0; i < nums; i++) {
197 clk = clk_register_hisi_phase(dev, &clks[i], base,
200 pr_err("%s: failed to register clock %s\n", __func__,
205 data->clk_data.clks[clks[i].id] = clk;
210 EXPORT_SYMBOL_GPL(hisi_clk_register_phase);
212 int hisi_clk_register_divider(const struct hisi_divider_clock *clks,
213 int nums, struct hisi_clock_data *data)
216 void __iomem *base = data->base;
219 for (i = 0; i < nums; i++) {
220 clk = clk_register_divider_table(NULL, clks[i].name,
223 base + clks[i].offset,
224 clks[i].shift, clks[i].width,
229 pr_err("%s: failed to register clock %s\n",
230 __func__, clks[i].name);
235 clk_register_clkdev(clk, clks[i].alias, NULL);
237 data->clk_data.clks[clks[i].id] = clk;
244 clk_unregister_divider(data->clk_data.clks[clks[i].id]);
248 EXPORT_SYMBOL_GPL(hisi_clk_register_divider);
250 int hisi_clk_register_gate(const struct hisi_gate_clock *clks,
251 int nums, struct hisi_clock_data *data)
254 void __iomem *base = data->base;
257 for (i = 0; i < nums; i++) {
258 clk = clk_register_gate(NULL, clks[i].name,
261 base + clks[i].offset,
266 pr_err("%s: failed to register clock %s\n",
267 __func__, clks[i].name);
272 clk_register_clkdev(clk, clks[i].alias, NULL);
274 data->clk_data.clks[clks[i].id] = clk;
281 clk_unregister_gate(data->clk_data.clks[clks[i].id]);
285 EXPORT_SYMBOL_GPL(hisi_clk_register_gate);
287 void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks,
288 int nums, struct hisi_clock_data *data)
291 void __iomem *base = data->base;
294 for (i = 0; i < nums; i++) {
295 clk = hisi_register_clkgate_sep(NULL, clks[i].name,
298 base + clks[i].offset,
303 pr_err("%s: failed to register clock %s\n",
304 __func__, clks[i].name);
309 clk_register_clkdev(clk, clks[i].alias, NULL);
311 data->clk_data.clks[clks[i].id] = clk;
314 EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep);
316 void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks,
317 int nums, struct hisi_clock_data *data)
320 void __iomem *base = data->base;
323 for (i = 0; i < nums; i++) {
324 clk = hi6220_register_clkdiv(NULL, clks[i].name,
327 base + clks[i].offset,
333 pr_err("%s: failed to register clock %s\n",
334 __func__, clks[i].name);
339 clk_register_clkdev(clk, clks[i].alias, NULL);
341 data->clk_data.clks[clks[i].id] = clk;