xref: /openbmc/linux/drivers/clk/mmp/clk.c (revision d47a97bd)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/io.h>
3 #include <linux/clk-provider.h>
4 #include <linux/slab.h>
5 #include <linux/of.h>
6 #include <linux/of_address.h>
7 
8 #include "clk.h"
9 
10 void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
11 		int nr_clks)
12 {
13 	struct clk **clk_table;
14 
15 	clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
16 	if (!clk_table)
17 		return;
18 
19 	unit->clk_table = clk_table;
20 	unit->nr_clks = nr_clks;
21 	unit->clk_data.clks = clk_table;
22 	unit->clk_data.clk_num = nr_clks;
23 	of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data);
24 }
25 
26 void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
27 				struct mmp_param_fixed_rate_clk *clks,
28 				int size)
29 {
30 	int i;
31 	struct clk *clk;
32 
33 	for (i = 0; i < size; i++) {
34 		clk = clk_register_fixed_rate(NULL, clks[i].name,
35 					clks[i].parent_name,
36 					clks[i].flags,
37 					clks[i].fixed_rate);
38 		if (IS_ERR(clk)) {
39 			pr_err("%s: failed to register clock %s\n",
40 			       __func__, clks[i].name);
41 			continue;
42 		}
43 		if (clks[i].id)
44 			unit->clk_table[clks[i].id] = clk;
45 	}
46 }
47 
48 void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
49 				struct mmp_param_fixed_factor_clk *clks,
50 				int size)
51 {
52 	struct clk *clk;
53 	int i;
54 
55 	for (i = 0; i < size; i++) {
56 		clk = clk_register_fixed_factor(NULL, clks[i].name,
57 						clks[i].parent_name,
58 						clks[i].flags, clks[i].mult,
59 						clks[i].div);
60 		if (IS_ERR(clk)) {
61 			pr_err("%s: failed to register clock %s\n",
62 			       __func__, clks[i].name);
63 			continue;
64 		}
65 		if (clks[i].id)
66 			unit->clk_table[clks[i].id] = clk;
67 	}
68 }
69 
70 void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
71 				struct mmp_param_general_gate_clk *clks,
72 				void __iomem *base, int size)
73 {
74 	struct clk *clk;
75 	int i;
76 
77 	for (i = 0; i < size; i++) {
78 		clk = clk_register_gate(NULL, clks[i].name,
79 					clks[i].parent_name,
80 					clks[i].flags,
81 					base + clks[i].offset,
82 					clks[i].bit_idx,
83 					clks[i].gate_flags,
84 					clks[i].lock);
85 
86 		if (IS_ERR(clk)) {
87 			pr_err("%s: failed to register clock %s\n",
88 			       __func__, clks[i].name);
89 			continue;
90 		}
91 		if (clks[i].id)
92 			unit->clk_table[clks[i].id] = clk;
93 	}
94 }
95 
96 void mmp_register_gate_clks(struct mmp_clk_unit *unit,
97 			struct mmp_param_gate_clk *clks,
98 			void __iomem *base, int size)
99 {
100 	struct clk *clk;
101 	int i;
102 
103 	for (i = 0; i < size; i++) {
104 		clk = mmp_clk_register_gate(NULL, clks[i].name,
105 					clks[i].parent_name,
106 					clks[i].flags,
107 					base + clks[i].offset,
108 					clks[i].mask,
109 					clks[i].val_enable,
110 					clks[i].val_disable,
111 					clks[i].gate_flags,
112 					clks[i].lock);
113 
114 		if (IS_ERR(clk)) {
115 			pr_err("%s: failed to register clock %s\n",
116 			       __func__, clks[i].name);
117 			continue;
118 		}
119 		if (clks[i].id)
120 			unit->clk_table[clks[i].id] = clk;
121 	}
122 }
123 
124 void mmp_register_mux_clks(struct mmp_clk_unit *unit,
125 			struct mmp_param_mux_clk *clks,
126 			void __iomem *base, int size)
127 {
128 	struct clk *clk;
129 	int i;
130 
131 	for (i = 0; i < size; i++) {
132 		clk = clk_register_mux(NULL, clks[i].name,
133 					clks[i].parent_name,
134 					clks[i].num_parents,
135 					clks[i].flags,
136 					base + clks[i].offset,
137 					clks[i].shift,
138 					clks[i].width,
139 					clks[i].mux_flags,
140 					clks[i].lock);
141 
142 		if (IS_ERR(clk)) {
143 			pr_err("%s: failed to register clock %s\n",
144 			       __func__, clks[i].name);
145 			continue;
146 		}
147 		if (clks[i].id)
148 			unit->clk_table[clks[i].id] = clk;
149 	}
150 }
151 
152 void mmp_register_div_clks(struct mmp_clk_unit *unit,
153 			struct mmp_param_div_clk *clks,
154 			void __iomem *base, int size)
155 {
156 	struct clk *clk;
157 	int i;
158 
159 	for (i = 0; i < size; i++) {
160 		clk = clk_register_divider(NULL, clks[i].name,
161 					clks[i].parent_name,
162 					clks[i].flags,
163 					base + clks[i].offset,
164 					clks[i].shift,
165 					clks[i].width,
166 					clks[i].div_flags,
167 					clks[i].lock);
168 
169 		if (IS_ERR(clk)) {
170 			pr_err("%s: failed to register clock %s\n",
171 			       __func__, clks[i].name);
172 			continue;
173 		}
174 		if (clks[i].id)
175 			unit->clk_table[clks[i].id] = clk;
176 	}
177 }
178 
179 void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
180 			struct clk *clk)
181 {
182 	if (IS_ERR_OR_NULL(clk)) {
183 		pr_err("CLK %d has invalid pointer %p\n", id, clk);
184 		return;
185 	}
186 	if (id >= unit->nr_clks) {
187 		pr_err("CLK %d is invalid\n", id);
188 		return;
189 	}
190 
191 	unit->clk_table[id] = clk;
192 }
193