1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Clock driver for TPS68470 PMIC |
4 | * |
5 | * Copyright (c) 2021 Red Hat Inc. |
6 | * Copyright (C) 2018 Intel Corporation |
7 | * |
8 | * Authors: |
9 | * Hans de Goede <hdegoede@redhat.com> |
10 | * Zaikuo Wang <zaikuo.wang@intel.com> |
11 | * Tianshu Qiu <tian.shu.qiu@intel.com> |
12 | * Jian Xu Zheng <jian.xu.zheng@intel.com> |
13 | * Yuning Pu <yuning.pu@intel.com> |
14 | * Antti Laakso <antti.laakso@intel.com> |
15 | */ |
16 | |
17 | #include <linux/clk-provider.h> |
18 | #include <linux/clkdev.h> |
19 | #include <linux/kernel.h> |
20 | #include <linux/mfd/tps68470.h> |
21 | #include <linux/module.h> |
22 | #include <linux/platform_device.h> |
23 | #include <linux/platform_data/tps68470.h> |
24 | #include <linux/regmap.h> |
25 | |
26 | #define TPS68470_CLK_NAME "tps68470-clk" |
27 | |
28 | #define to_tps68470_clkdata(clkd) \ |
29 | container_of(clkd, struct tps68470_clkdata, clkout_hw) |
30 | |
31 | static struct tps68470_clkout_freqs { |
32 | unsigned long freq; |
33 | unsigned int xtaldiv; |
34 | unsigned int plldiv; |
35 | unsigned int postdiv; |
36 | unsigned int buckdiv; |
37 | unsigned int boostdiv; |
38 | } clk_freqs[] = { |
39 | /* |
40 | * The PLL is used to multiply the crystal oscillator |
41 | * frequency range of 3 MHz to 27 MHz by a programmable |
42 | * factor of F = (M/N)*(1/P) such that the output |
43 | * available at the HCLK_A or HCLK_B pins are in the range |
44 | * of 4 MHz to 64 MHz in increments of 0.1 MHz. |
45 | * |
46 | * hclk_# = osc_in * (((plldiv*2)+320) / (xtaldiv+30)) * (1 / 2^postdiv) |
47 | * |
48 | * PLL_REF_CLK should be as close as possible to 100kHz |
49 | * PLL_REF_CLK = input clk / XTALDIV[7:0] + 30) |
50 | * |
51 | * PLL_VCO_CLK = (PLL_REF_CLK * (plldiv*2 + 320)) |
52 | * |
53 | * BOOST should be as close as possible to 2Mhz |
54 | * BOOST = PLL_VCO_CLK / (BOOSTDIV[4:0] + 16) * |
55 | * |
56 | * BUCK should be as close as possible to 5.2Mhz |
57 | * BUCK = PLL_VCO_CLK / (BUCKDIV[3:0] + 5) |
58 | * |
59 | * osc_in xtaldiv plldiv postdiv hclk_# |
60 | * 20Mhz 170 32 1 19.2Mhz |
61 | * 20Mhz 170 40 1 20Mhz |
62 | * 20Mhz 170 80 1 24Mhz |
63 | */ |
64 | { 19200000, 170, 32, 1, 2, 3 }, |
65 | { 20000000, 170, 40, 1, 3, 4 }, |
66 | { 24000000, 170, 80, 1, 4, 8 }, |
67 | }; |
68 | |
69 | struct tps68470_clkdata { |
70 | struct clk_hw clkout_hw; |
71 | struct regmap *regmap; |
72 | unsigned long rate; |
73 | }; |
74 | |
75 | static int tps68470_clk_is_prepared(struct clk_hw *hw) |
76 | { |
77 | struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); |
78 | int val; |
79 | |
80 | if (regmap_read(map: clkdata->regmap, TPS68470_REG_PLLCTL, val: &val)) |
81 | return 0; |
82 | |
83 | return val & TPS68470_PLL_EN_MASK; |
84 | } |
85 | |
86 | static int tps68470_clk_prepare(struct clk_hw *hw) |
87 | { |
88 | struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); |
89 | |
90 | regmap_write(map: clkdata->regmap, TPS68470_REG_CLKCFG1, |
91 | val: (TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_A_SHIFT) | |
92 | (TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_B_SHIFT)); |
93 | |
94 | regmap_update_bits(map: clkdata->regmap, TPS68470_REG_PLLCTL, |
95 | TPS68470_PLL_EN_MASK, TPS68470_PLL_EN_MASK); |
96 | |
97 | /* |
98 | * The PLLCTL reg lock bit is set by the PMIC after approx. 4ms and |
99 | * does not indicate a true lock, so just wait 4 ms. |
100 | */ |
101 | usleep_range(min: 4000, max: 5000); |
102 | |
103 | return 0; |
104 | } |
105 | |
106 | static void tps68470_clk_unprepare(struct clk_hw *hw) |
107 | { |
108 | struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); |
109 | |
110 | /* Disable clock first ... */ |
111 | regmap_update_bits(map: clkdata->regmap, TPS68470_REG_PLLCTL, TPS68470_PLL_EN_MASK, val: 0); |
112 | |
113 | /* ... and then tri-state the clock outputs. */ |
114 | regmap_write(map: clkdata->regmap, TPS68470_REG_CLKCFG1, val: 0); |
115 | } |
116 | |
117 | static unsigned long tps68470_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
118 | { |
119 | struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); |
120 | |
121 | return clkdata->rate; |
122 | } |
123 | |
124 | /* |
125 | * This returns the index of the clk_freqs[] cfg with the closest rate for |
126 | * use in tps68470_clk_round_rate(). tps68470_clk_set_rate() checks that |
127 | * the rate of the returned cfg is an exact match. |
128 | */ |
129 | static unsigned int tps68470_clk_cfg_lookup(unsigned long rate) |
130 | { |
131 | long diff, best_diff = LONG_MAX; |
132 | unsigned int i, best_idx = 0; |
133 | |
134 | for (i = 0; i < ARRAY_SIZE(clk_freqs); i++) { |
135 | diff = clk_freqs[i].freq - rate; |
136 | if (diff == 0) |
137 | return i; |
138 | |
139 | diff = abs(diff); |
140 | if (diff < best_diff) { |
141 | best_diff = diff; |
142 | best_idx = i; |
143 | } |
144 | } |
145 | |
146 | return best_idx; |
147 | } |
148 | |
149 | static long tps68470_clk_round_rate(struct clk_hw *hw, unsigned long rate, |
150 | unsigned long *parent_rate) |
151 | { |
152 | unsigned int idx = tps68470_clk_cfg_lookup(rate); |
153 | |
154 | return clk_freqs[idx].freq; |
155 | } |
156 | |
157 | static int tps68470_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
158 | unsigned long parent_rate) |
159 | { |
160 | struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); |
161 | unsigned int idx = tps68470_clk_cfg_lookup(rate); |
162 | |
163 | if (rate != clk_freqs[idx].freq) |
164 | return -EINVAL; |
165 | |
166 | regmap_write(map: clkdata->regmap, TPS68470_REG_BOOSTDIV, val: clk_freqs[idx].boostdiv); |
167 | regmap_write(map: clkdata->regmap, TPS68470_REG_BUCKDIV, val: clk_freqs[idx].buckdiv); |
168 | regmap_write(map: clkdata->regmap, TPS68470_REG_PLLSWR, TPS68470_PLLSWR_DEFAULT); |
169 | regmap_write(map: clkdata->regmap, TPS68470_REG_XTALDIV, val: clk_freqs[idx].xtaldiv); |
170 | regmap_write(map: clkdata->regmap, TPS68470_REG_PLLDIV, val: clk_freqs[idx].plldiv); |
171 | regmap_write(map: clkdata->regmap, TPS68470_REG_POSTDIV, val: clk_freqs[idx].postdiv); |
172 | regmap_write(map: clkdata->regmap, TPS68470_REG_POSTDIV2, val: clk_freqs[idx].postdiv); |
173 | regmap_write(map: clkdata->regmap, TPS68470_REG_CLKCFG2, TPS68470_CLKCFG2_DRV_STR_2MA); |
174 | |
175 | regmap_write(map: clkdata->regmap, TPS68470_REG_PLLCTL, |
176 | TPS68470_OSC_EXT_CAP_DEFAULT << TPS68470_OSC_EXT_CAP_SHIFT | |
177 | TPS68470_CLK_SRC_XTAL << TPS68470_CLK_SRC_SHIFT); |
178 | |
179 | clkdata->rate = rate; |
180 | |
181 | return 0; |
182 | } |
183 | |
184 | static const struct clk_ops tps68470_clk_ops = { |
185 | .is_prepared = tps68470_clk_is_prepared, |
186 | .prepare = tps68470_clk_prepare, |
187 | .unprepare = tps68470_clk_unprepare, |
188 | .recalc_rate = tps68470_clk_recalc_rate, |
189 | .round_rate = tps68470_clk_round_rate, |
190 | .set_rate = tps68470_clk_set_rate, |
191 | }; |
192 | |
193 | static int tps68470_clk_probe(struct platform_device *pdev) |
194 | { |
195 | struct tps68470_clk_platform_data *pdata = pdev->dev.platform_data; |
196 | struct clk_init_data tps68470_clk_initdata = { |
197 | .name = TPS68470_CLK_NAME, |
198 | .ops = &tps68470_clk_ops, |
199 | /* Changing the dividers when the PLL is on is not allowed */ |
200 | .flags = CLK_SET_RATE_GATE, |
201 | }; |
202 | struct tps68470_clkdata *tps68470_clkdata; |
203 | struct tps68470_clk_consumer *consumer; |
204 | int ret; |
205 | int i; |
206 | |
207 | tps68470_clkdata = devm_kzalloc(dev: &pdev->dev, size: sizeof(*tps68470_clkdata), |
208 | GFP_KERNEL); |
209 | if (!tps68470_clkdata) |
210 | return -ENOMEM; |
211 | |
212 | tps68470_clkdata->regmap = dev_get_drvdata(dev: pdev->dev.parent); |
213 | tps68470_clkdata->clkout_hw.init = &tps68470_clk_initdata; |
214 | |
215 | /* Set initial rate */ |
216 | tps68470_clk_set_rate(hw: &tps68470_clkdata->clkout_hw, rate: clk_freqs[0].freq, parent_rate: 0); |
217 | |
218 | ret = devm_clk_hw_register(dev: &pdev->dev, hw: &tps68470_clkdata->clkout_hw); |
219 | if (ret) |
220 | return ret; |
221 | |
222 | ret = devm_clk_hw_register_clkdev(dev: &pdev->dev, hw: &tps68470_clkdata->clkout_hw, |
223 | TPS68470_CLK_NAME, NULL); |
224 | if (ret) |
225 | return ret; |
226 | |
227 | if (pdata) { |
228 | for (i = 0; i < pdata->n_consumers; i++) { |
229 | consumer = &pdata->consumers[i]; |
230 | ret = devm_clk_hw_register_clkdev(dev: &pdev->dev, |
231 | hw: &tps68470_clkdata->clkout_hw, |
232 | con_id: consumer->consumer_con_id, |
233 | dev_id: consumer->consumer_dev_name); |
234 | } |
235 | } |
236 | |
237 | return ret; |
238 | } |
239 | |
240 | static struct platform_driver tps68470_clk_driver = { |
241 | .driver = { |
242 | .name = TPS68470_CLK_NAME, |
243 | }, |
244 | .probe = tps68470_clk_probe, |
245 | }; |
246 | |
247 | /* |
248 | * The ACPI tps68470 probe-ordering depends on the clk/gpio/regulator drivers |
249 | * registering before the drivers for the camera-sensors which use them bind. |
250 | * subsys_initcall() ensures this when the drivers are builtin. |
251 | */ |
252 | static int __init tps68470_clk_init(void) |
253 | { |
254 | return platform_driver_register(&tps68470_clk_driver); |
255 | } |
256 | subsys_initcall(tps68470_clk_init); |
257 | |
258 | static void __exit tps68470_clk_exit(void) |
259 | { |
260 | platform_driver_unregister(&tps68470_clk_driver); |
261 | } |
262 | module_exit(tps68470_clk_exit); |
263 | |
264 | MODULE_ALIAS("platform:tps68470-clk" ); |
265 | MODULE_DESCRIPTION("clock driver for TPS68470 pmic" ); |
266 | MODULE_LICENSE("GPL" ); |
267 | |