Lines Matching +full:ti +full:- +full:sci
2 * SCI Clock driver for keystone based devices
4 * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
5 * Tero Kristo <t-kristo@ti.com>
16 #include <linux/clk-provider.h>
24 #include <linux/soc/ti/ti_sci_protocol.h>
33 * struct sci_clk_provider - TI SCI clock provider representation
34 * @sci: Handle to the System Control Interface protocol handler
35 * @ops: Pointer to the SCI ops to be used by the clocks
41 const struct ti_sci_handle *sci; member
49 * struct sci_clk - TI SCI clock representation
75 * sci_clk_prepare - Prepare (enable) a TI SCI clock
78 * Prepares a clock to be actively used. Returns the SCI protocol status.
83 bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE; in sci_clk_prepare()
84 bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE; in sci_clk_prepare()
85 bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION; in sci_clk_prepare()
87 return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id, in sci_clk_prepare()
88 clk->clk_id, enable_ssc, in sci_clk_prepare()
94 * sci_clk_unprepare - Un-prepares (disables) a TI SCI clock
97 * Un-prepares a clock from active state.
104 ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id, in sci_clk_unprepare()
105 clk->clk_id); in sci_clk_unprepare()
107 dev_err(clk->provider->dev, in sci_clk_unprepare()
109 clk->dev_id, clk->clk_id, ret); in sci_clk_unprepare()
113 * sci_clk_is_prepared - Check if a TI SCI clock is prepared or not
116 * Checks if a clock is prepared (enabled) in hardware. Returns non-zero
125 ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id, in sci_clk_is_prepared()
126 clk->clk_id, &req_state, in sci_clk_is_prepared()
129 dev_err(clk->provider->dev, in sci_clk_is_prepared()
131 clk->dev_id, clk->clk_id, ret); in sci_clk_is_prepared()
139 * sci_clk_recalc_rate - Get clock rate for a TI SCI clock
143 * Gets the current clock rate of a TI SCI clock. Returns the current
153 ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id, in sci_clk_recalc_rate()
154 clk->clk_id, &freq); in sci_clk_recalc_rate()
156 dev_err(clk->provider->dev, in sci_clk_recalc_rate()
157 "recalc-rate failed for dev=%d, clk=%d, ret=%d\n", in sci_clk_recalc_rate()
158 clk->dev_id, clk->clk_id, ret); in sci_clk_recalc_rate()
166 * sci_clk_determine_rate - Determines a clock rate a clock can be set to
170 * Determines a suitable clock rate and parent for a TI SCI clock.
171 * The parent handling is un-used, as generally the parent clock rates
182 if (clk->cached_req && clk->cached_req == req->rate) { in sci_clk_determine_rate()
183 req->rate = clk->cached_res; in sci_clk_determine_rate()
187 ret = clk->provider->ops->get_best_match_freq(clk->provider->sci, in sci_clk_determine_rate()
188 clk->dev_id, in sci_clk_determine_rate()
189 clk->clk_id, in sci_clk_determine_rate()
190 req->min_rate, in sci_clk_determine_rate()
191 req->rate, in sci_clk_determine_rate()
192 req->max_rate, in sci_clk_determine_rate()
195 dev_err(clk->provider->dev, in sci_clk_determine_rate()
196 "determine-rate failed for dev=%d, clk=%d, ret=%d\n", in sci_clk_determine_rate()
197 clk->dev_id, clk->clk_id, ret); in sci_clk_determine_rate()
201 clk->cached_req = req->rate; in sci_clk_determine_rate()
202 clk->cached_res = new_rate; in sci_clk_determine_rate()
204 req->rate = new_rate; in sci_clk_determine_rate()
210 * sci_clk_set_rate - Set rate for a TI SCI clock
213 * @parent_rate: rate of the clock parent, not used for TI SCI clocks
215 * Sets a clock frequency for a TI SCI clock. Returns the TI SCI
223 return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id, in sci_clk_set_rate()
224 clk->clk_id, rate / 10 * 9, rate, in sci_clk_set_rate()
229 * sci_clk_get_parent - Get the current parent of a TI SCI clock
232 * Returns the index of the currently selected parent for a TI SCI clock.
240 ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id, in sci_clk_get_parent()
241 clk->clk_id, (void *)&parent_id); in sci_clk_get_parent()
243 dev_err(clk->provider->dev, in sci_clk_get_parent()
244 "get-parent failed for dev=%d, clk=%d, ret=%d\n", in sci_clk_get_parent()
245 clk->dev_id, clk->clk_id, ret); in sci_clk_get_parent()
249 parent_id = parent_id - clk->clk_id - 1; in sci_clk_get_parent()
255 * sci_clk_set_parent - Set the parent of a TI SCI clock
259 * Sets the parent of a TI SCI clock. Return TI SCI protocol status.
265 clk->cached_req = 0; in sci_clk_set_parent()
267 return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id, in sci_clk_set_parent()
268 clk->clk_id, in sci_clk_set_parent()
269 index + 1 + clk->clk_id); in sci_clk_set_parent()
284 * _sci_clk_get - Gets a handle for an SCI clock
285 * @provider: Handle to SCI clock provider
286 * @sci_clk: Handle to the SCI clock to populate
288 * Gets a handle to an existing TI SCI hw clock, or builds a new clock
303 name = kasprintf(GFP_KERNEL, "clk:%d:%d", sci_clk->dev_id, in _sci_clk_build()
304 sci_clk->clk_id); in _sci_clk_build()
314 if (sci_clk->num_parents < 2) in _sci_clk_build()
315 sci_clk->num_parents = 0; in _sci_clk_build()
317 if (sci_clk->num_parents) { in _sci_clk_build()
318 parent_names = kcalloc(sci_clk->num_parents, sizeof(char *), in _sci_clk_build()
322 ret = -ENOMEM; in _sci_clk_build()
326 for (i = 0; i < sci_clk->num_parents; i++) { in _sci_clk_build()
330 sci_clk->dev_id, in _sci_clk_build()
331 sci_clk->clk_id + 1 + i); in _sci_clk_build()
333 ret = -ENOMEM; in _sci_clk_build()
342 init.num_parents = sci_clk->num_parents; in _sci_clk_build()
343 sci_clk->hw.init = &init; in _sci_clk_build()
345 ret = devm_clk_hw_register(provider->dev, &sci_clk->hw); in _sci_clk_build()
347 dev_err(provider->dev, "failed clk register with %d\n", ret); in _sci_clk_build()
351 for (i = 0; i < sci_clk->num_parents; i++) in _sci_clk_build()
367 if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id) in _cmp_sci_clk()
369 if (ca->dev_id > cb->dev_id || in _cmp_sci_clk()
370 (ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id)) in _cmp_sci_clk()
372 return -1; in _cmp_sci_clk()
376 * sci_clk_get - Xlate function for getting clock handles
380 * Xlate function for retrieving clock TI SCI hw clock handles based on
383 * to the TI SCI hw clock struct, or ERR_PTR value in failure.
391 if (clkspec->args_count != 2) in sci_clk_get()
392 return ERR_PTR(-EINVAL); in sci_clk_get()
394 key.dev_id = clkspec->args[0]; in sci_clk_get()
395 key.clk_id = clkspec->args[1]; in sci_clk_get()
397 clk = bsearch(&key, provider->clocks, provider->num_clocks, in sci_clk_get()
401 return ERR_PTR(-ENODEV); in sci_clk_get()
403 return &(*clk)->hw; in sci_clk_get()
411 for (i = 0; i < p->num_clocks; i++) { in ti_sci_init_clocks()
412 ret = _sci_clk_build(p, p->clocks[i]); in ti_sci_init_clocks()
421 { .compatible = "ti,k2g-sci-clk" },
439 struct device *dev = provider->dev; in ti_sci_scan_clocks_from_fw()
442 ret = provider->ops->get_num_parents(provider->sci, dev_id, in ti_sci_scan_clocks_from_fw()
478 return -ENOMEM; in ti_sci_scan_clocks_from_fw()
479 sci_clk->dev_id = dev_id; in ti_sci_scan_clocks_from_fw()
480 sci_clk->clk_id = clk_id; in ti_sci_scan_clocks_from_fw()
481 sci_clk->provider = provider; in ti_sci_scan_clocks_from_fw()
482 sci_clk->num_parents = num_parents; in ti_sci_scan_clocks_from_fw()
490 provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk), in ti_sci_scan_clocks_from_fw()
492 if (!provider->clocks) in ti_sci_scan_clocks_from_fw()
493 return -ENOMEM; in ti_sci_scan_clocks_from_fw()
495 memcpy(provider->clocks, clks, num_clks * sizeof(sci_clk)); in ti_sci_scan_clocks_from_fw()
497 provider->num_clocks = num_clks; in ti_sci_scan_clocks_from_fw()
517 struct device *dev = provider->dev; in ti_sci_scan_clocks_from_dt()
528 "clocks", "assigned-clocks", "assigned-clock-parents", NULL in ti_sci_scan_clocks_from_dt()
550 "#clock-cells", index, in ti_sci_scan_clocks_from_dt()
555 if (args.args_count == 2 && args.np == dev->of_node) { in ti_sci_scan_clocks_from_dt()
559 return -ENOMEM; in ti_sci_scan_clocks_from_dt()
561 sci_clk->dev_id = args.args[0]; in ti_sci_scan_clocks_from_dt()
562 sci_clk->clk_id = args.args[1]; in ti_sci_scan_clocks_from_dt()
563 sci_clk->provider = provider; in ti_sci_scan_clocks_from_dt()
564 provider->ops->get_num_parents(provider->sci, in ti_sci_scan_clocks_from_dt()
565 sci_clk->dev_id, in ti_sci_scan_clocks_from_dt()
566 sci_clk->clk_id, in ti_sci_scan_clocks_from_dt()
567 (void *)&sci_clk->num_parents); in ti_sci_scan_clocks_from_dt()
568 list_add_tail(&sci_clk->node, &clks); in ti_sci_scan_clocks_from_dt()
572 num_parents = sci_clk->num_parents; in ti_sci_scan_clocks_from_dt()
580 * any mux clock from sci-clk driver in ti_sci_scan_clocks_from_dt()
588 sci_clk->dev_id, in ti_sci_scan_clocks_from_dt()
589 sci_clk->clk_id, num_parents); in ti_sci_scan_clocks_from_dt()
595 while (num_parents--) { in ti_sci_scan_clocks_from_dt()
600 return -ENOMEM; in ti_sci_scan_clocks_from_dt()
601 sci_clk->dev_id = args.args[0]; in ti_sci_scan_clocks_from_dt()
602 sci_clk->clk_id = clk_id++; in ti_sci_scan_clocks_from_dt()
603 sci_clk->provider = provider; in ti_sci_scan_clocks_from_dt()
604 list_add_tail(&sci_clk->node, &clks); in ti_sci_scan_clocks_from_dt()
616 provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk), in ti_sci_scan_clocks_from_dt()
618 if (!provider->clocks) in ti_sci_scan_clocks_from_dt()
619 return -ENOMEM; in ti_sci_scan_clocks_from_dt()
625 if (prev && prev->dev_id == sci_clk->dev_id && in ti_sci_scan_clocks_from_dt()
626 prev->clk_id == sci_clk->clk_id) in ti_sci_scan_clocks_from_dt()
629 provider->clocks[num_clks++] = sci_clk; in ti_sci_scan_clocks_from_dt()
633 provider->num_clocks = num_clks; in ti_sci_scan_clocks_from_dt()
640 * ti_sci_clk_probe - Probe function for the TI SCI clock driver
643 * Probes the TI SCI clock device. Allocates a new clock provider
651 struct device *dev = &pdev->dev; in ti_sci_clk_probe()
652 struct device_node *np = dev->of_node; in ti_sci_clk_probe()
663 return -ENOMEM; in ti_sci_clk_probe()
665 provider->sci = handle; in ti_sci_clk_probe()
666 provider->ops = &handle->ops.clk_ops; in ti_sci_clk_probe()
667 provider->dev = dev; in ti_sci_clk_probe()
685 pr_err("ti-sci-init-clocks failed.\n"); in ti_sci_clk_probe()
693 * ti_sci_clk_remove - Remove TI SCI clock device
696 * Removes the TI SCI device. Unregisters the clock provider registered
702 of_clk_del_provider(pdev->dev.of_node); in ti_sci_clk_remove()
711 .name = "ti-sci-clk",
718 MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
720 MODULE_ALIAS("platform:ti-sci-clk");