1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Sysctrl clock implementation for ux500 platform. |
4 | * |
5 | * Copyright (C) 2013 ST-Ericsson SA |
6 | * Author: Ulf Hansson <ulf.hansson@linaro.org> |
7 | */ |
8 | |
9 | #include <linux/clk-provider.h> |
10 | #include <linux/mfd/abx500/ab8500-sysctrl.h> |
11 | #include <linux/device.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/io.h> |
15 | #include <linux/err.h> |
16 | #include "clk.h" |
17 | |
18 | #define SYSCTRL_MAX_NUM_PARENTS 4 |
19 | |
20 | #define to_clk_sysctrl(_hw) container_of(_hw, struct clk_sysctrl, hw) |
21 | |
22 | struct clk_sysctrl { |
23 | struct clk_hw hw; |
24 | struct device *dev; |
25 | u8 parent_index; |
26 | u16 reg_sel[SYSCTRL_MAX_NUM_PARENTS]; |
27 | u8 reg_mask[SYSCTRL_MAX_NUM_PARENTS]; |
28 | u8 reg_bits[SYSCTRL_MAX_NUM_PARENTS]; |
29 | unsigned long rate; |
30 | unsigned long enable_delay_us; |
31 | }; |
32 | |
33 | /* Sysctrl clock operations. */ |
34 | |
35 | static int clk_sysctrl_prepare(struct clk_hw *hw) |
36 | { |
37 | int ret; |
38 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); |
39 | |
40 | ret = ab8500_sysctrl_write(reg: clk->reg_sel[0], mask: clk->reg_mask[0], |
41 | value: clk->reg_bits[0]); |
42 | |
43 | if (!ret && clk->enable_delay_us) |
44 | usleep_range(min: clk->enable_delay_us, max: clk->enable_delay_us + |
45 | (clk->enable_delay_us >> 2)); |
46 | |
47 | return ret; |
48 | } |
49 | |
50 | static void clk_sysctrl_unprepare(struct clk_hw *hw) |
51 | { |
52 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); |
53 | if (ab8500_sysctrl_clear(reg: clk->reg_sel[0], bits: clk->reg_mask[0])) |
54 | dev_err(clk->dev, "clk_sysctrl: %s fail to clear %s.\n" , |
55 | __func__, clk_hw_get_name(hw)); |
56 | } |
57 | |
58 | static unsigned long clk_sysctrl_recalc_rate(struct clk_hw *hw, |
59 | unsigned long parent_rate) |
60 | { |
61 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); |
62 | return clk->rate; |
63 | } |
64 | |
65 | static int clk_sysctrl_set_parent(struct clk_hw *hw, u8 index) |
66 | { |
67 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); |
68 | u8 old_index = clk->parent_index; |
69 | int ret = 0; |
70 | |
71 | if (clk->reg_sel[old_index]) { |
72 | ret = ab8500_sysctrl_clear(reg: clk->reg_sel[old_index], |
73 | bits: clk->reg_mask[old_index]); |
74 | if (ret) |
75 | return ret; |
76 | } |
77 | |
78 | if (clk->reg_sel[index]) { |
79 | ret = ab8500_sysctrl_write(reg: clk->reg_sel[index], |
80 | mask: clk->reg_mask[index], |
81 | value: clk->reg_bits[index]); |
82 | if (ret) { |
83 | if (clk->reg_sel[old_index]) |
84 | ab8500_sysctrl_write(reg: clk->reg_sel[old_index], |
85 | mask: clk->reg_mask[old_index], |
86 | value: clk->reg_bits[old_index]); |
87 | return ret; |
88 | } |
89 | } |
90 | clk->parent_index = index; |
91 | |
92 | return ret; |
93 | } |
94 | |
95 | static u8 clk_sysctrl_get_parent(struct clk_hw *hw) |
96 | { |
97 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); |
98 | return clk->parent_index; |
99 | } |
100 | |
101 | static const struct clk_ops clk_sysctrl_gate_ops = { |
102 | .prepare = clk_sysctrl_prepare, |
103 | .unprepare = clk_sysctrl_unprepare, |
104 | }; |
105 | |
106 | static const struct clk_ops clk_sysctrl_gate_fixed_rate_ops = { |
107 | .prepare = clk_sysctrl_prepare, |
108 | .unprepare = clk_sysctrl_unprepare, |
109 | .recalc_rate = clk_sysctrl_recalc_rate, |
110 | }; |
111 | |
112 | static const struct clk_ops clk_sysctrl_set_parent_ops = { |
113 | .determine_rate = clk_hw_determine_rate_no_reparent, |
114 | .set_parent = clk_sysctrl_set_parent, |
115 | .get_parent = clk_sysctrl_get_parent, |
116 | }; |
117 | |
118 | static struct clk *clk_reg_sysctrl(struct device *dev, |
119 | const char *name, |
120 | const char **parent_names, |
121 | u8 num_parents, |
122 | u16 *reg_sel, |
123 | u8 *reg_mask, |
124 | u8 *reg_bits, |
125 | unsigned long rate, |
126 | unsigned long enable_delay_us, |
127 | unsigned long flags, |
128 | const struct clk_ops *clk_sysctrl_ops) |
129 | { |
130 | struct clk_sysctrl *clk; |
131 | struct clk_init_data clk_sysctrl_init; |
132 | struct clk *clk_reg; |
133 | int i; |
134 | |
135 | if (!dev) |
136 | return ERR_PTR(error: -EINVAL); |
137 | |
138 | if (!name || (num_parents > SYSCTRL_MAX_NUM_PARENTS)) { |
139 | dev_err(dev, "clk_sysctrl: invalid arguments passed\n" ); |
140 | return ERR_PTR(error: -EINVAL); |
141 | } |
142 | |
143 | clk = devm_kzalloc(dev, size: sizeof(*clk), GFP_KERNEL); |
144 | if (!clk) |
145 | return ERR_PTR(error: -ENOMEM); |
146 | |
147 | /* set main clock registers */ |
148 | clk->reg_sel[0] = reg_sel[0]; |
149 | clk->reg_bits[0] = reg_bits[0]; |
150 | clk->reg_mask[0] = reg_mask[0]; |
151 | |
152 | /* handle clocks with more than one parent */ |
153 | for (i = 1; i < num_parents; i++) { |
154 | clk->reg_sel[i] = reg_sel[i]; |
155 | clk->reg_bits[i] = reg_bits[i]; |
156 | clk->reg_mask[i] = reg_mask[i]; |
157 | } |
158 | |
159 | clk->parent_index = 0; |
160 | clk->rate = rate; |
161 | clk->enable_delay_us = enable_delay_us; |
162 | clk->dev = dev; |
163 | |
164 | clk_sysctrl_init.name = name; |
165 | clk_sysctrl_init.ops = clk_sysctrl_ops; |
166 | clk_sysctrl_init.flags = flags; |
167 | clk_sysctrl_init.parent_names = parent_names; |
168 | clk_sysctrl_init.num_parents = num_parents; |
169 | clk->hw.init = &clk_sysctrl_init; |
170 | |
171 | clk_reg = devm_clk_register(dev: clk->dev, hw: &clk->hw); |
172 | if (IS_ERR(ptr: clk_reg)) |
173 | dev_err(dev, "clk_sysctrl: clk_register failed\n" ); |
174 | |
175 | return clk_reg; |
176 | } |
177 | |
178 | struct clk *clk_reg_sysctrl_gate(struct device *dev, |
179 | const char *name, |
180 | const char *parent_name, |
181 | u16 reg_sel, |
182 | u8 reg_mask, |
183 | u8 reg_bits, |
184 | unsigned long enable_delay_us, |
185 | unsigned long flags) |
186 | { |
187 | const char **parent_names = (parent_name ? &parent_name : NULL); |
188 | u8 num_parents = (parent_name ? 1 : 0); |
189 | |
190 | return clk_reg_sysctrl(dev, name, parent_names, num_parents, |
191 | reg_sel: ®_sel, reg_mask: ®_mask, reg_bits: ®_bits, rate: 0, enable_delay_us, |
192 | flags, clk_sysctrl_ops: &clk_sysctrl_gate_ops); |
193 | } |
194 | |
195 | struct clk *clk_reg_sysctrl_gate_fixed_rate(struct device *dev, |
196 | const char *name, |
197 | const char *parent_name, |
198 | u16 reg_sel, |
199 | u8 reg_mask, |
200 | u8 reg_bits, |
201 | unsigned long rate, |
202 | unsigned long enable_delay_us, |
203 | unsigned long flags) |
204 | { |
205 | const char **parent_names = (parent_name ? &parent_name : NULL); |
206 | u8 num_parents = (parent_name ? 1 : 0); |
207 | |
208 | return clk_reg_sysctrl(dev, name, parent_names, num_parents, |
209 | reg_sel: ®_sel, reg_mask: ®_mask, reg_bits: ®_bits, |
210 | rate, enable_delay_us, flags, |
211 | clk_sysctrl_ops: &clk_sysctrl_gate_fixed_rate_ops); |
212 | } |
213 | |
214 | struct clk *clk_reg_sysctrl_set_parent(struct device *dev, |
215 | const char *name, |
216 | const char **parent_names, |
217 | u8 num_parents, |
218 | u16 *reg_sel, |
219 | u8 *reg_mask, |
220 | u8 *reg_bits, |
221 | unsigned long flags) |
222 | { |
223 | return clk_reg_sysctrl(dev, name, parent_names, num_parents, |
224 | reg_sel, reg_mask, reg_bits, rate: 0, enable_delay_us: 0, flags, |
225 | clk_sysctrl_ops: &clk_sysctrl_set_parent_ops); |
226 | } |
227 | |