Lines Matching +full:k2g +full:- +full:sci

1 // SPDX-License-Identifier: GPL-2.0-only
3 * SCI Clock driver for keystone based devices
5 * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
6 * Tero Kristo <t-kristo@ti.com>
8 #include <linux/clk-provider.h>
24 * struct sci_clk_provider - TI SCI clock provider representation
25 * @sci: Handle to the System Control Interface protocol handler
26 * @ops: Pointer to the SCI ops to be used by the clocks
32 const struct ti_sci_handle *sci; member
40 * struct sci_clk - TI SCI clock representation
66 * sci_clk_prepare - Prepare (enable) a TI SCI clock
69 * Prepares a clock to be actively used. Returns the SCI protocol status.
74 bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE; in sci_clk_prepare()
75 bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE; in sci_clk_prepare()
76 bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION; in sci_clk_prepare()
78 return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id, in sci_clk_prepare()
79 clk->clk_id, enable_ssc, in sci_clk_prepare()
85 * sci_clk_unprepare - Un-prepares (disables) a TI SCI clock
88 * Un-prepares a clock from active state.
95 ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id, in sci_clk_unprepare()
96 clk->clk_id); in sci_clk_unprepare()
98 dev_err(clk->provider->dev, in sci_clk_unprepare()
100 clk->dev_id, clk->clk_id, ret); in sci_clk_unprepare()
104 * sci_clk_is_prepared - Check if a TI SCI clock is prepared or not
107 * Checks if a clock is prepared (enabled) in hardware. Returns non-zero
116 ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id, in sci_clk_is_prepared()
117 clk->clk_id, &req_state, in sci_clk_is_prepared()
120 dev_err(clk->provider->dev, in sci_clk_is_prepared()
122 clk->dev_id, clk->clk_id, ret); in sci_clk_is_prepared()
130 * sci_clk_recalc_rate - Get clock rate for a TI SCI clock
134 * Gets the current clock rate of a TI SCI clock. Returns the current
144 ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id, in sci_clk_recalc_rate()
145 clk->clk_id, &freq); in sci_clk_recalc_rate()
147 dev_err(clk->provider->dev, in sci_clk_recalc_rate()
148 "recalc-rate failed for dev=%d, clk=%d, ret=%d\n", in sci_clk_recalc_rate()
149 clk->dev_id, clk->clk_id, ret); in sci_clk_recalc_rate()
157 * sci_clk_determine_rate - Determines a clock rate a clock can be set to
161 * Determines a suitable clock rate and parent for a TI SCI clock.
162 * The parent handling is un-used, as generally the parent clock rates
173 if (clk->cached_req && clk->cached_req == req->rate) { in sci_clk_determine_rate()
174 req->rate = clk->cached_res; in sci_clk_determine_rate()
178 ret = clk->provider->ops->get_best_match_freq(clk->provider->sci, in sci_clk_determine_rate()
179 clk->dev_id, in sci_clk_determine_rate()
180 clk->clk_id, in sci_clk_determine_rate()
181 req->min_rate, in sci_clk_determine_rate()
182 req->rate, in sci_clk_determine_rate()
183 req->max_rate, in sci_clk_determine_rate()
186 dev_err(clk->provider->dev, in sci_clk_determine_rate()
187 "determine-rate failed for dev=%d, clk=%d, ret=%d\n", in sci_clk_determine_rate()
188 clk->dev_id, clk->clk_id, ret); in sci_clk_determine_rate()
192 clk->cached_req = req->rate; in sci_clk_determine_rate()
193 clk->cached_res = new_rate; in sci_clk_determine_rate()
195 req->rate = new_rate; in sci_clk_determine_rate()
201 * sci_clk_set_rate - Set rate for a TI SCI clock
204 * @parent_rate: rate of the clock parent, not used for TI SCI clocks
206 * Sets a clock frequency for a TI SCI clock. Returns the TI SCI
214 return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id, in sci_clk_set_rate()
215 clk->clk_id, rate / 10 * 9, rate, in sci_clk_set_rate()
220 * sci_clk_get_parent - Get the current parent of a TI SCI clock
223 * Returns the index of the currently selected parent for a TI SCI clock.
231 ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id, in sci_clk_get_parent()
232 clk->clk_id, (void *)&parent_id); in sci_clk_get_parent()
234 dev_err(clk->provider->dev, in sci_clk_get_parent()
235 "get-parent failed for dev=%d, clk=%d, ret=%d\n", in sci_clk_get_parent()
236 clk->dev_id, clk->clk_id, ret); in sci_clk_get_parent()
240 parent_id = parent_id - clk->clk_id - 1; in sci_clk_get_parent()
246 * sci_clk_set_parent - Set the parent of a TI SCI clock
250 * Sets the parent of a TI SCI clock. Return TI SCI protocol status.
256 clk->cached_req = 0; in sci_clk_set_parent()
258 return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id, in sci_clk_set_parent()
259 clk->clk_id, in sci_clk_set_parent()
260 index + 1 + clk->clk_id); in sci_clk_set_parent()
275 * _sci_clk_build - Gets a handle for an SCI clock
276 * @provider: Handle to SCI clock provider
277 * @sci_clk: Handle to the SCI clock to populate
279 * Gets a handle to an existing TI SCI hw clock, or builds a new clock
294 name = kasprintf(GFP_KERNEL, "clk:%d:%d", sci_clk->dev_id, in _sci_clk_build()
295 sci_clk->clk_id); in _sci_clk_build()
297 return -ENOMEM; in _sci_clk_build()
307 if (sci_clk->num_parents < 2) in _sci_clk_build()
308 sci_clk->num_parents = 0; in _sci_clk_build()
310 if (sci_clk->num_parents) { in _sci_clk_build()
311 parent_names = kcalloc(sci_clk->num_parents, sizeof(char *), in _sci_clk_build()
315 ret = -ENOMEM; in _sci_clk_build()
319 for (i = 0; i < sci_clk->num_parents; i++) { in _sci_clk_build()
323 sci_clk->dev_id, in _sci_clk_build()
324 sci_clk->clk_id + 1 + i); in _sci_clk_build()
326 ret = -ENOMEM; in _sci_clk_build()
335 init.num_parents = sci_clk->num_parents; in _sci_clk_build()
336 sci_clk->hw.init = &init; in _sci_clk_build()
338 ret = devm_clk_hw_register(provider->dev, &sci_clk->hw); in _sci_clk_build()
340 dev_err(provider->dev, "failed clk register with %d\n", ret); in _sci_clk_build()
344 for (i = 0; i < sci_clk->num_parents; i++) in _sci_clk_build()
360 if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id) in _cmp_sci_clk()
362 if (ca->dev_id > cb->dev_id || in _cmp_sci_clk()
363 (ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id)) in _cmp_sci_clk()
365 return -1; in _cmp_sci_clk()
369 * sci_clk_get - Xlate function for getting clock handles
373 * Xlate function for retrieving clock TI SCI hw clock handles based on
376 * to the TI SCI hw clock struct, or ERR_PTR value in failure.
384 if (clkspec->args_count != 2) in sci_clk_get()
385 return ERR_PTR(-EINVAL); in sci_clk_get()
387 key.dev_id = clkspec->args[0]; in sci_clk_get()
388 key.clk_id = clkspec->args[1]; in sci_clk_get()
390 clk = bsearch(&key, provider->clocks, provider->num_clocks, in sci_clk_get()
394 return ERR_PTR(-ENODEV); in sci_clk_get()
396 return &(*clk)->hw; in sci_clk_get()
404 for (i = 0; i < p->num_clocks; i++) { in ti_sci_init_clocks()
405 ret = _sci_clk_build(p, p->clocks[i]); in ti_sci_init_clocks()
414 { .compatible = "ti,k2g-sci-clk" },
432 struct device *dev = provider->dev; in ti_sci_scan_clocks_from_fw()
435 ret = provider->ops->get_num_parents(provider->sci, dev_id, in ti_sci_scan_clocks_from_fw()
471 return -ENOMEM; in ti_sci_scan_clocks_from_fw()
472 sci_clk->dev_id = dev_id; in ti_sci_scan_clocks_from_fw()
473 sci_clk->clk_id = clk_id; in ti_sci_scan_clocks_from_fw()
474 sci_clk->provider = provider; in ti_sci_scan_clocks_from_fw()
475 sci_clk->num_parents = num_parents; in ti_sci_scan_clocks_from_fw()
483 provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk), in ti_sci_scan_clocks_from_fw()
485 if (!provider->clocks) in ti_sci_scan_clocks_from_fw()
486 return -ENOMEM; in ti_sci_scan_clocks_from_fw()
488 memcpy(provider->clocks, clks, num_clks * sizeof(sci_clk)); in ti_sci_scan_clocks_from_fw()
490 provider->num_clocks = num_clks; in ti_sci_scan_clocks_from_fw()
510 struct device *dev = provider->dev; in ti_sci_scan_clocks_from_dt()
522 "clocks", "assigned-clocks", "assigned-clock-parents", NULL in ti_sci_scan_clocks_from_dt()
544 "#clock-cells", index, in ti_sci_scan_clocks_from_dt()
549 if (args.args_count == 2 && args.np == dev->of_node) { in ti_sci_scan_clocks_from_dt()
553 return -ENOMEM; in ti_sci_scan_clocks_from_dt()
555 sci_clk->dev_id = args.args[0]; in ti_sci_scan_clocks_from_dt()
556 sci_clk->clk_id = args.args[1]; in ti_sci_scan_clocks_from_dt()
557 sci_clk->provider = provider; in ti_sci_scan_clocks_from_dt()
558 provider->ops->get_num_parents(provider->sci, in ti_sci_scan_clocks_from_dt()
559 sci_clk->dev_id, in ti_sci_scan_clocks_from_dt()
560 sci_clk->clk_id, in ti_sci_scan_clocks_from_dt()
561 (void *)&sci_clk->num_parents); in ti_sci_scan_clocks_from_dt()
562 list_add_tail(&sci_clk->node, &clks); in ti_sci_scan_clocks_from_dt()
566 num_parents = sci_clk->num_parents; in ti_sci_scan_clocks_from_dt()
574 * any mux clock from sci-clk driver in ti_sci_scan_clocks_from_dt()
582 sci_clk->dev_id, in ti_sci_scan_clocks_from_dt()
583 sci_clk->clk_id, num_parents); in ti_sci_scan_clocks_from_dt()
589 while (num_parents--) { in ti_sci_scan_clocks_from_dt()
591 ret = provider->ops->is_auto(provider->sci, in ti_sci_scan_clocks_from_dt()
592 sci_clk->dev_id, clk_id, &state); in ti_sci_scan_clocks_from_dt()
603 return -ENOMEM; in ti_sci_scan_clocks_from_dt()
604 sci_clk->dev_id = args.args[0]; in ti_sci_scan_clocks_from_dt()
605 sci_clk->clk_id = clk_id++; in ti_sci_scan_clocks_from_dt()
606 sci_clk->provider = provider; in ti_sci_scan_clocks_from_dt()
607 list_add_tail(&sci_clk->node, &clks); in ti_sci_scan_clocks_from_dt()
619 provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk), in ti_sci_scan_clocks_from_dt()
621 if (!provider->clocks) in ti_sci_scan_clocks_from_dt()
622 return -ENOMEM; in ti_sci_scan_clocks_from_dt()
628 if (prev && prev->dev_id == sci_clk->dev_id && in ti_sci_scan_clocks_from_dt()
629 prev->clk_id == sci_clk->clk_id) in ti_sci_scan_clocks_from_dt()
632 provider->clocks[num_clks++] = sci_clk; in ti_sci_scan_clocks_from_dt()
636 provider->num_clocks = num_clks; in ti_sci_scan_clocks_from_dt()
643 * ti_sci_clk_probe - Probe function for the TI SCI clock driver
646 * Probes the TI SCI clock device. Allocates a new clock provider
654 struct device *dev = &pdev->dev; in ti_sci_clk_probe()
655 struct device_node *np = dev->of_node; in ti_sci_clk_probe()
666 return -ENOMEM; in ti_sci_clk_probe()
668 provider->sci = handle; in ti_sci_clk_probe()
669 provider->ops = &handle->ops.clk_ops; in ti_sci_clk_probe()
670 provider->dev = dev; in ti_sci_clk_probe()
688 pr_err("ti-sci-init-clocks failed.\n"); in ti_sci_clk_probe()
696 * ti_sci_clk_remove - Remove TI SCI clock device
699 * Removes the TI SCI device. Unregisters the clock provider registered
705 of_clk_del_provider(pdev->dev.of_node); in ti_sci_clk_remove()
712 .name = "ti-sci-clk",
719 MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
721 MODULE_ALIAS("platform:ti-sci-clk");