xref: /openbmc/linux/drivers/clk/at91/clk-utmi.c (revision d7955ce4)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
4  */
5 
6 #include <linux/clk-provider.h>
7 #include <linux/clkdev.h>
8 #include <linux/clk/at91_pmc.h>
9 #include <linux/of.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/regmap.h>
12 #include <soc/at91/atmel-sfr.h>
13 
14 #include "pmc.h"
15 
16 /*
17  * The purpose of this clock is to generate a 480 MHz signal. A different
18  * rate can't be configured.
19  */
20 #define UTMI_RATE	480000000
21 
22 struct clk_utmi {
23 	struct clk_hw hw;
24 	struct regmap *regmap_pmc;
25 	struct regmap *regmap_sfr;
26 	struct at91_clk_pms pms;
27 };
28 
29 #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
30 
31 static inline bool clk_utmi_ready(struct regmap *regmap)
32 {
33 	unsigned int status;
34 
35 	regmap_read(regmap, AT91_PMC_SR, &status);
36 
37 	return status & AT91_PMC_LOCKU;
38 }
39 
40 static int clk_utmi_prepare(struct clk_hw *hw)
41 {
42 	struct clk_hw *hw_parent;
43 	struct clk_utmi *utmi = to_clk_utmi(hw);
44 	unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT |
45 			    AT91_PMC_BIASEN;
46 	unsigned int utmi_ref_clk_freq;
47 	unsigned long parent_rate;
48 
49 	/*
50 	 * If mainck rate is different from 12 MHz, we have to configure the
51 	 * FREQ field of the SFR_UTMICKTRIM register to generate properly
52 	 * the utmi clock.
53 	 */
54 	hw_parent = clk_hw_get_parent(hw);
55 	parent_rate = clk_hw_get_rate(hw_parent);
56 
57 	switch (parent_rate) {
58 	case 12000000:
59 		utmi_ref_clk_freq = 0;
60 		break;
61 	case 16000000:
62 		utmi_ref_clk_freq = 1;
63 		break;
64 	case 24000000:
65 		utmi_ref_clk_freq = 2;
66 		break;
67 	/*
68 	 * Not supported on SAMA5D2 but it's not an issue since MAINCK
69 	 * maximum value is 24 MHz.
70 	 */
71 	case 48000000:
72 		utmi_ref_clk_freq = 3;
73 		break;
74 	default:
75 		pr_err("UTMICK: unsupported mainck rate\n");
76 		return -EINVAL;
77 	}
78 
79 	if (utmi->regmap_sfr) {
80 		regmap_update_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM,
81 				   AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq);
82 	} else if (utmi_ref_clk_freq) {
83 		pr_err("UTMICK: sfr node required\n");
84 		return -EINVAL;
85 	}
86 
87 	regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr);
88 
89 	while (!clk_utmi_ready(utmi->regmap_pmc))
90 		cpu_relax();
91 
92 	return 0;
93 }
94 
95 static int clk_utmi_is_prepared(struct clk_hw *hw)
96 {
97 	struct clk_utmi *utmi = to_clk_utmi(hw);
98 
99 	return clk_utmi_ready(utmi->regmap_pmc);
100 }
101 
102 static void clk_utmi_unprepare(struct clk_hw *hw)
103 {
104 	struct clk_utmi *utmi = to_clk_utmi(hw);
105 
106 	regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR,
107 			   AT91_PMC_UPLLEN, 0);
108 }
109 
110 static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw,
111 					  unsigned long parent_rate)
112 {
113 	/* UTMI clk rate is fixed. */
114 	return UTMI_RATE;
115 }
116 
117 static int clk_utmi_save_context(struct clk_hw *hw)
118 {
119 	struct clk_utmi *utmi = to_clk_utmi(hw);
120 
121 	utmi->pms.status = clk_utmi_is_prepared(hw);
122 
123 	return 0;
124 }
125 
126 static void clk_utmi_restore_context(struct clk_hw *hw)
127 {
128 	struct clk_utmi *utmi = to_clk_utmi(hw);
129 
130 	if (utmi->pms.status)
131 		clk_utmi_prepare(hw);
132 }
133 
134 static const struct clk_ops utmi_ops = {
135 	.prepare = clk_utmi_prepare,
136 	.unprepare = clk_utmi_unprepare,
137 	.is_prepared = clk_utmi_is_prepared,
138 	.recalc_rate = clk_utmi_recalc_rate,
139 	.save_context = clk_utmi_save_context,
140 	.restore_context = clk_utmi_restore_context,
141 };
142 
143 static struct clk_hw * __init
144 at91_clk_register_utmi_internal(struct regmap *regmap_pmc,
145 				struct regmap *regmap_sfr,
146 				const char *name, const char *parent_name,
147 				struct clk_hw *parent_hw,
148 				const struct clk_ops *ops, unsigned long flags)
149 {
150 	struct clk_utmi *utmi;
151 	struct clk_hw *hw;
152 	struct clk_init_data init = {};
153 	int ret;
154 
155 	if (!(parent_name || parent_hw))
156 		return ERR_PTR(-EINVAL);
157 
158 	utmi = kzalloc(sizeof(*utmi), GFP_KERNEL);
159 	if (!utmi)
160 		return ERR_PTR(-ENOMEM);
161 
162 	init.name = name;
163 	init.ops = ops;
164 	if (parent_hw) {
165 		init.parent_hws = parent_hw ? (const struct clk_hw **)&parent_hw : NULL;
166 		init.num_parents = parent_hw ? 1 : 0;
167 	} else {
168 		init.parent_names = parent_name ? &parent_name : NULL;
169 		init.num_parents = parent_name ? 1 : 0;
170 	}
171 	init.flags = flags;
172 
173 	utmi->hw.init = &init;
174 	utmi->regmap_pmc = regmap_pmc;
175 	utmi->regmap_sfr = regmap_sfr;
176 
177 	hw = &utmi->hw;
178 	ret = clk_hw_register(NULL, &utmi->hw);
179 	if (ret) {
180 		kfree(utmi);
181 		hw = ERR_PTR(ret);
182 	}
183 
184 	return hw;
185 }
186 
187 struct clk_hw * __init
188 at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
189 		       const char *name, const char *parent_name,
190 		       struct clk_hw *parent_hw)
191 {
192 	return at91_clk_register_utmi_internal(regmap_pmc, regmap_sfr, name,
193 			parent_name, parent_hw, &utmi_ops, CLK_SET_RATE_GATE);
194 }
195 
196 static int clk_utmi_sama7g5_prepare(struct clk_hw *hw)
197 {
198 	struct clk_utmi *utmi = to_clk_utmi(hw);
199 	struct clk_hw *hw_parent;
200 	unsigned long parent_rate;
201 	unsigned int val;
202 
203 	hw_parent = clk_hw_get_parent(hw);
204 	parent_rate = clk_hw_get_rate(hw_parent);
205 
206 	switch (parent_rate) {
207 	case 16000000:
208 		val = 0;
209 		break;
210 	case 20000000:
211 		val = 2;
212 		break;
213 	case 24000000:
214 		val = 3;
215 		break;
216 	case 32000000:
217 		val = 5;
218 		break;
219 	default:
220 		pr_err("UTMICK: unsupported main_xtal rate\n");
221 		return -EINVAL;
222 	}
223 
224 	regmap_write(utmi->regmap_pmc, AT91_PMC_XTALF, val);
225 
226 	return 0;
227 
228 }
229 
230 static int clk_utmi_sama7g5_is_prepared(struct clk_hw *hw)
231 {
232 	struct clk_utmi *utmi = to_clk_utmi(hw);
233 	struct clk_hw *hw_parent;
234 	unsigned long parent_rate;
235 	unsigned int val;
236 
237 	hw_parent = clk_hw_get_parent(hw);
238 	parent_rate = clk_hw_get_rate(hw_parent);
239 
240 	regmap_read(utmi->regmap_pmc, AT91_PMC_XTALF, &val);
241 	switch (val & 0x7) {
242 	case 0:
243 		if (parent_rate == 16000000)
244 			return 1;
245 		break;
246 	case 2:
247 		if (parent_rate == 20000000)
248 			return 1;
249 		break;
250 	case 3:
251 		if (parent_rate == 24000000)
252 			return 1;
253 		break;
254 	case 5:
255 		if (parent_rate == 32000000)
256 			return 1;
257 		break;
258 	default:
259 		break;
260 	}
261 
262 	return 0;
263 }
264 
265 static int clk_utmi_sama7g5_save_context(struct clk_hw *hw)
266 {
267 	struct clk_utmi *utmi = to_clk_utmi(hw);
268 
269 	utmi->pms.status = clk_utmi_sama7g5_is_prepared(hw);
270 
271 	return 0;
272 }
273 
274 static void clk_utmi_sama7g5_restore_context(struct clk_hw *hw)
275 {
276 	struct clk_utmi *utmi = to_clk_utmi(hw);
277 
278 	if (utmi->pms.status)
279 		clk_utmi_sama7g5_prepare(hw);
280 }
281 
282 static const struct clk_ops sama7g5_utmi_ops = {
283 	.prepare = clk_utmi_sama7g5_prepare,
284 	.is_prepared = clk_utmi_sama7g5_is_prepared,
285 	.recalc_rate = clk_utmi_recalc_rate,
286 	.save_context = clk_utmi_sama7g5_save_context,
287 	.restore_context = clk_utmi_sama7g5_restore_context,
288 };
289 
290 struct clk_hw * __init
291 at91_clk_sama7g5_register_utmi(struct regmap *regmap_pmc, const char *name,
292 			       const char *parent_name, struct clk_hw *parent_hw)
293 {
294 	return at91_clk_register_utmi_internal(regmap_pmc, NULL, name,
295 			parent_name, parent_hw, &sama7g5_utmi_ops, 0);
296 }
297