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(n: nr_clks, size: 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, clk_src_get: of_clk_src_onecell_get, data: &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, name: clks[i].name, |
35 | parent_name: clks[i].parent_name, |
36 | flags: clks[i].flags, |
37 | fixed_rate: clks[i].fixed_rate); |
38 | if (IS_ERR(ptr: 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, name: clks[i].name, |
57 | parent_name: clks[i].parent_name, |
58 | flags: clks[i].flags, mult: clks[i].mult, |
59 | div: clks[i].div); |
60 | if (IS_ERR(ptr: 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, name: clks[i].name, |
79 | parent_name: clks[i].parent_name, |
80 | flags: clks[i].flags, |
81 | reg: base + clks[i].offset, |
82 | bit_idx: clks[i].bit_idx, |
83 | clk_gate_flags: clks[i].gate_flags, |
84 | lock: clks[i].lock); |
85 | |
86 | if (IS_ERR(ptr: 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, name: clks[i].name, |
105 | parent_name: clks[i].parent_name, |
106 | flags: clks[i].flags, |
107 | reg: base + clks[i].offset, |
108 | mask: clks[i].mask, |
109 | val_enable: clks[i].val_enable, |
110 | val_disable: clks[i].val_disable, |
111 | gate_flags: clks[i].gate_flags, |
112 | lock: clks[i].lock); |
113 | |
114 | if (IS_ERR(ptr: 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(ptr: 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(ptr: 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(ptr: 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 | |