Warning: That file was not part of the compilation database. It may have many parsing errors.

1/*
2 * SCI Clock driver for keystone based devices
3 *
4 * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
5 * Tero Kristo <t-kristo@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16#include <linux/clk-provider.h>
17#include <linux/err.h>
18#include <linux/io.h>
19#include <linux/module.h>
20#include <linux/of_address.h>
21#include <linux/of_device.h>
22#include <linux/platform_device.h>
23#include <linux/slab.h>
24#include <linux/soc/ti/ti_sci_protocol.h>
25#include <linux/bsearch.h>
26
27#define SCI_CLK_SSC_ENABLE BIT(0)
28#define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1)
29#define SCI_CLK_INPUT_TERMINATION BIT(2)
30
31/**
32 * struct sci_clk_provider - TI SCI clock provider representation
33 * @sci: Handle to the System Control Interface protocol handler
34 * @ops: Pointer to the SCI ops to be used by the clocks
35 * @dev: Device pointer for the clock provider
36 * @clocks: Clocks array for this device
37 * @num_clocks: Total number of clocks for this provider
38 */
39struct sci_clk_provider {
40 const struct ti_sci_handle *sci;
41 const struct ti_sci_clk_ops *ops;
42 struct device *dev;
43 struct sci_clk **clocks;
44 int num_clocks;
45};
46
47/**
48 * struct sci_clk - TI SCI clock representation
49 * @hw: Hardware clock cookie for common clock framework
50 * @dev_id: Device index
51 * @clk_id: Clock index
52 * @num_parents: Number of parents for this clock
53 * @provider: Master clock provider
54 * @flags: Flags for the clock
55 */
56struct sci_clk {
57 struct clk_hw hw;
58 u16 dev_id;
59 u8 clk_id;
60 u8 num_parents;
61 struct sci_clk_provider *provider;
62 u8 flags;
63};
64
65#define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
66
67/**
68 * sci_clk_prepare - Prepare (enable) a TI SCI clock
69 * @hw: clock to prepare
70 *
71 * Prepares a clock to be actively used. Returns the SCI protocol status.
72 */
73static int sci_clk_prepare(struct clk_hw *hw)
74{
75 struct sci_clk *clk = to_sci_clk(hw);
76 bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE;
77 bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE;
78 bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION;
79
80 return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id,
81 clk->clk_id, enable_ssc,
82 allow_freq_change,
83 input_termination);
84}
85
86/**
87 * sci_clk_unprepare - Un-prepares (disables) a TI SCI clock
88 * @hw: clock to unprepare
89 *
90 * Un-prepares a clock from active state.
91 */
92static void sci_clk_unprepare(struct clk_hw *hw)
93{
94 struct sci_clk *clk = to_sci_clk(hw);
95 int ret;
96
97 ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id,
98 clk->clk_id);
99 if (ret)
100 dev_err(clk->provider->dev,
101 "unprepare failed for dev=%d, clk=%d, ret=%d\n",
102 clk->dev_id, clk->clk_id, ret);
103}
104
105/**
106 * sci_clk_is_prepared - Check if a TI SCI clock is prepared or not
107 * @hw: clock to check status for
108 *
109 * Checks if a clock is prepared (enabled) in hardware. Returns non-zero
110 * value if clock is enabled, zero otherwise.
111 */
112static int sci_clk_is_prepared(struct clk_hw *hw)
113{
114 struct sci_clk *clk = to_sci_clk(hw);
115 bool req_state, current_state;
116 int ret;
117
118 ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id,
119 clk->clk_id, &req_state,
120 &current_state);
121 if (ret) {
122 dev_err(clk->provider->dev,
123 "is_prepared failed for dev=%d, clk=%d, ret=%d\n",
124 clk->dev_id, clk->clk_id, ret);
125 return 0;
126 }
127
128 return req_state;
129}
130
131/**
132 * sci_clk_recalc_rate - Get clock rate for a TI SCI clock
133 * @hw: clock to get rate for
134 * @parent_rate: parent rate provided by common clock framework, not used
135 *
136 * Gets the current clock rate of a TI SCI clock. Returns the current
137 * clock rate, or zero in failure.
138 */
139static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
140 unsigned long parent_rate)
141{
142 struct sci_clk *clk = to_sci_clk(hw);
143 u64 freq;
144 int ret;
145
146 ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id,
147 clk->clk_id, &freq);
148 if (ret) {
149 dev_err(clk->provider->dev,
150 "recalc-rate failed for dev=%d, clk=%d, ret=%d\n",
151 clk->dev_id, clk->clk_id, ret);
152 return 0;
153 }
154
155 return freq;
156}
157
158/**
159 * sci_clk_determine_rate - Determines a clock rate a clock can be set to
160 * @hw: clock to change rate for
161 * @req: requested rate configuration for the clock
162 *
163 * Determines a suitable clock rate and parent for a TI SCI clock.
164 * The parent handling is un-used, as generally the parent clock rates
165 * are not known by the kernel; instead these are internally handled
166 * by the firmware. Returns 0 on success, negative error value on failure.
167 */
168static int sci_clk_determine_rate(struct clk_hw *hw,
169 struct clk_rate_request *req)
170{
171 struct sci_clk *clk = to_sci_clk(hw);
172 int ret;
173 u64 new_rate;
174
175 ret = clk->provider->ops->get_best_match_freq(clk->provider->sci,
176 clk->dev_id,
177 clk->clk_id,
178 req->min_rate,
179 req->rate,
180 req->max_rate,
181 &new_rate);
182 if (ret) {
183 dev_err(clk->provider->dev,
184 "determine-rate failed for dev=%d, clk=%d, ret=%d\n",
185 clk->dev_id, clk->clk_id, ret);
186 return ret;
187 }
188
189 req->rate = new_rate;
190
191 return 0;
192}
193
194/**
195 * sci_clk_set_rate - Set rate for a TI SCI clock
196 * @hw: clock to change rate for
197 * @rate: target rate for the clock
198 * @parent_rate: rate of the clock parent, not used for TI SCI clocks
199 *
200 * Sets a clock frequency for a TI SCI clock. Returns the TI SCI
201 * protocol status.
202 */
203static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
204 unsigned long parent_rate)
205{
206 struct sci_clk *clk = to_sci_clk(hw);
207
208 return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
209 clk->clk_id, rate, rate, rate);
210}
211
212/**
213 * sci_clk_get_parent - Get the current parent of a TI SCI clock
214 * @hw: clock to get parent for
215 *
216 * Returns the index of the currently selected parent for a TI SCI clock.
217 */
218static u8 sci_clk_get_parent(struct clk_hw *hw)
219{
220 struct sci_clk *clk = to_sci_clk(hw);
221 u8 parent_id;
222 int ret;
223
224 ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id,
225 clk->clk_id, &parent_id);
226 if (ret) {
227 dev_err(clk->provider->dev,
228 "get-parent failed for dev=%d, clk=%d, ret=%d\n",
229 clk->dev_id, clk->clk_id, ret);
230 return 0;
231 }
232
233 return parent_id - clk->clk_id - 1;
234}
235
236/**
237 * sci_clk_set_parent - Set the parent of a TI SCI clock
238 * @hw: clock to set parent for
239 * @index: new parent index for the clock
240 *
241 * Sets the parent of a TI SCI clock. Return TI SCI protocol status.
242 */
243static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
244{
245 struct sci_clk *clk = to_sci_clk(hw);
246
247 return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
248 clk->clk_id,
249 index + 1 + clk->clk_id);
250}
251
252static const struct clk_ops sci_clk_ops = {
253 .prepare = sci_clk_prepare,
254 .unprepare = sci_clk_unprepare,
255 .is_prepared = sci_clk_is_prepared,
256 .recalc_rate = sci_clk_recalc_rate,
257 .determine_rate = sci_clk_determine_rate,
258 .set_rate = sci_clk_set_rate,
259 .get_parent = sci_clk_get_parent,
260 .set_parent = sci_clk_set_parent,
261};
262
263/**
264 * _sci_clk_get - Gets a handle for an SCI clock
265 * @provider: Handle to SCI clock provider
266 * @sci_clk: Handle to the SCI clock to populate
267 *
268 * Gets a handle to an existing TI SCI hw clock, or builds a new clock
269 * entry and registers it with the common clock framework. Called from
270 * the common clock framework, when a corresponding of_clk_get call is
271 * executed, or recursively from itself when parsing parent clocks.
272 * Returns 0 on success, negative error code on failure.
273 */
274static int _sci_clk_build(struct sci_clk_provider *provider,
275 struct sci_clk *sci_clk)
276{
277 struct clk_init_data init = { NULL };
278 char *name = NULL;
279 char **parent_names = NULL;
280 int i;
281 int ret = 0;
282
283 name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
284 sci_clk->dev_id, sci_clk->clk_id);
285
286 init.name = name;
287
288 /*
289 * From kernel point of view, we only care about a clocks parents,
290 * if it has more than 1 possible parent. In this case, it is going
291 * to have mux functionality. Otherwise it is going to act as a root
292 * clock.
293 */
294 if (sci_clk->num_parents < 2)
295 sci_clk->num_parents = 0;
296
297 if (sci_clk->num_parents) {
298 parent_names = kcalloc(sci_clk->num_parents, sizeof(char *),
299 GFP_KERNEL);
300
301 if (!parent_names) {
302 ret = -ENOMEM;
303 goto err;
304 }
305
306 for (i = 0; i < sci_clk->num_parents; i++) {
307 char *parent_name;
308
309 parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
310 dev_name(provider->dev),
311 sci_clk->dev_id,
312 sci_clk->clk_id + 1 + i);
313 if (!parent_name) {
314 ret = -ENOMEM;
315 goto err;
316 }
317 parent_names[i] = parent_name;
318 }
319 init.parent_names = (void *)parent_names;
320 }
321
322 init.ops = &sci_clk_ops;
323 init.num_parents = sci_clk->num_parents;
324 sci_clk->hw.init = &init;
325
326 ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
327 if (ret)
328 dev_err(provider->dev, "failed clk register with %d\n", ret);
329
330err:
331 if (parent_names) {
332 for (i = 0; i < sci_clk->num_parents; i++)
333 kfree(parent_names[i]);
334
335 kfree(parent_names);
336 }
337
338 kfree(name);
339
340 return ret;
341}
342
343static int _cmp_sci_clk(const void *a, const void *b)
344{
345 const struct sci_clk *ca = a;
346 const struct sci_clk *cb = *(struct sci_clk **)b;
347
348 if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id)
349 return 0;
350 if (ca->dev_id > cb->dev_id ||
351 (ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id))
352 return 1;
353 return -1;
354}
355
356/**
357 * sci_clk_get - Xlate function for getting clock handles
358 * @clkspec: device tree clock specifier
359 * @data: pointer to the clock provider
360 *
361 * Xlate function for retrieving clock TI SCI hw clock handles based on
362 * device tree clock specifier. Called from the common clock framework,
363 * when a corresponding of_clk_get call is executed. Returns a pointer
364 * to the TI SCI hw clock struct, or ERR_PTR value in failure.
365 */
366static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
367{
368 struct sci_clk_provider *provider = data;
369 struct sci_clk **clk;
370 struct sci_clk key;
371
372 if (clkspec->args_count != 2)
373 return ERR_PTR(-EINVAL);
374
375 key.dev_id = clkspec->args[0];
376 key.clk_id = clkspec->args[1];
377
378 clk = bsearch(&key, provider->clocks, provider->num_clocks,
379 sizeof(clk), _cmp_sci_clk);
380
381 if (!clk)
382 return ERR_PTR(-ENODEV);
383
384 return &(*clk)->hw;
385}
386
387static int ti_sci_init_clocks(struct sci_clk_provider *p)
388{
389 int i;
390 int ret;
391
392 for (i = 0; i < p->num_clocks; i++) {
393 ret = _sci_clk_build(p, p->clocks[i]);
394 if (ret)
395 return ret;
396 }
397
398 return 0;
399}
400
401static const struct of_device_id ti_sci_clk_of_match[] = {
402 { .compatible = "ti,k2g-sci-clk" },
403 { /* Sentinel */ },
404};
405MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
406
407/**
408 * ti_sci_clk_probe - Probe function for the TI SCI clock driver
409 * @pdev: platform device pointer to be probed
410 *
411 * Probes the TI SCI clock device. Allocates a new clock provider
412 * and registers this to the common clock framework. Also applies
413 * any required flags to the identified clocks via clock lists
414 * supplied from DT. Returns 0 for success, negative error value
415 * for failure.
416 */
417static int ti_sci_clk_probe(struct platform_device *pdev)
418{
419 struct device *dev = &pdev->dev;
420 struct device_node *np = dev->of_node;
421 struct sci_clk_provider *provider;
422 const struct ti_sci_handle *handle;
423 int ret;
424 int num_clks = 0;
425 struct sci_clk **clks = NULL;
426 struct sci_clk **tmp_clks;
427 struct sci_clk *sci_clk;
428 int max_clks = 0;
429 int clk_id = 0;
430 int dev_id = 0;
431 u8 num_parents;
432 int gap_size = 0;
433
434 handle = devm_ti_sci_get_handle(dev);
435 if (IS_ERR(handle))
436 return PTR_ERR(handle);
437
438 provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
439 if (!provider)
440 return -ENOMEM;
441
442 provider->sci = handle;
443 provider->ops = &handle->ops.clk_ops;
444 provider->dev = dev;
445
446 while (1) {
447 ret = provider->ops->get_num_parents(provider->sci, dev_id,
448 clk_id, &num_parents);
449 if (ret) {
450 gap_size++;
451 if (!clk_id) {
452 if (gap_size >= 5)
453 break;
454 dev_id++;
455 } else {
456 if (gap_size >= 2) {
457 dev_id++;
458 clk_id = 0;
459 gap_size = 0;
460 } else {
461 clk_id++;
462 }
463 }
464 continue;
465 }
466
467 gap_size = 0;
468
469 if (num_clks == max_clks) {
470 tmp_clks = devm_kmalloc_array(dev, max_clks + 64,
471 sizeof(sci_clk),
472 GFP_KERNEL);
473 memcpy(tmp_clks, clks, max_clks * sizeof(sci_clk));
474 if (max_clks)
475 devm_kfree(dev, clks);
476 max_clks += 64;
477 clks = tmp_clks;
478 }
479
480 sci_clk = devm_kzalloc(dev, sizeof(*sci_clk), GFP_KERNEL);
481 if (!sci_clk)
482 return -ENOMEM;
483 sci_clk->dev_id = dev_id;
484 sci_clk->clk_id = clk_id;
485 sci_clk->provider = provider;
486 sci_clk->num_parents = num_parents;
487
488 clks[num_clks] = sci_clk;
489
490 clk_id++;
491 num_clks++;
492 }
493
494 provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk),
495 GFP_KERNEL);
496 if (!provider->clocks)
497 return -ENOMEM;
498
499 memcpy(provider->clocks, clks, num_clks * sizeof(sci_clk));
500
501 provider->num_clocks = num_clks;
502
503 devm_kfree(dev, clks);
504
505 ret = ti_sci_init_clocks(provider);
506 if (ret) {
507 pr_err("ti-sci-init-clocks failed.\n");
508 return ret;
509 }
510
511 return of_clk_add_hw_provider(np, sci_clk_get, provider);
512}
513
514/**
515 * ti_sci_clk_remove - Remove TI SCI clock device
516 * @pdev: platform device pointer for the device to be removed
517 *
518 * Removes the TI SCI device. Unregisters the clock provider registered
519 * via common clock framework. Any memory allocated for the device will
520 * be free'd silently via the devm framework. Returns 0 always.
521 */
522static int ti_sci_clk_remove(struct platform_device *pdev)
523{
524 of_clk_del_provider(pdev->dev.of_node);
525
526 return 0;
527}
528
529static struct platform_driver ti_sci_clk_driver = {
530 .probe = ti_sci_clk_probe,
531 .remove = ti_sci_clk_remove,
532 .driver = {
533 .name = "ti-sci-clk",
534 .of_match_table = of_match_ptr(ti_sci_clk_of_match),
535 },
536};
537module_platform_driver(ti_sci_clk_driver);
538
539MODULE_LICENSE("GPL v2");
540MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
541MODULE_AUTHOR("Tero Kristo");
542MODULE_ALIAS("platform:ti-sci-clk");
543

Warning: That file was not part of the compilation database. It may have many parsing errors.