Lines Matching +full:max +full:- +full:rpm
1 // SPDX-License-Identifier: GPL-2.0-only
7 #include <linux/clk-provider.h>
18 #include <dt-bindings/mfd/qcom-rpm.h>
19 #include <dt-bindings/clock/qcom,rpmcc.h>
96 struct qcom_rpm *rpm; member
121 * RPM clock. in clk_rpm_handoff()
123 if (r->rpm_clk_id == QCOM_RPM_PLL_4 || in clk_rpm_handoff()
124 r->rpm_clk_id == QCOM_RPM_CXO_BUFFERS) in clk_rpm_handoff()
127 ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, in clk_rpm_handoff()
128 r->rpm_clk_id, &value, 1); in clk_rpm_handoff()
131 ret = qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE, in clk_rpm_handoff()
132 r->rpm_clk_id, &value, 1); in clk_rpm_handoff()
143 return qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, in clk_rpm_set_rate_active()
144 r->rpm_clk_id, &value, 1); in clk_rpm_set_rate_active()
151 return qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE, in clk_rpm_set_rate_sleep()
152 r->rpm_clk_id, &value, 1); in clk_rpm_set_rate_sleep()
161 * Active-only clocks don't care what the rate is during sleep. So, in to_active_sleep()
164 if (r->active_only) in to_active_sleep()
173 struct clk_rpm *peer = r->peer; in clk_rpm_prepare()
181 /* Don't send requests to the RPM if the rate has not been set. */ in clk_rpm_prepare()
182 if (!r->rate) in clk_rpm_prepare()
185 to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate); in clk_rpm_prepare()
188 if (peer->enabled) in clk_rpm_prepare()
189 to_active_sleep(peer, peer->rate, in clk_rpm_prepare()
192 active_rate = max(this_rate, peer_rate); in clk_rpm_prepare()
194 if (r->branch) in clk_rpm_prepare()
201 sleep_rate = max(this_sleep_rate, peer_sleep_rate); in clk_rpm_prepare()
202 if (r->branch) in clk_rpm_prepare()
212 r->enabled = true; in clk_rpm_prepare()
222 struct clk_rpm *peer = r->peer; in clk_rpm_unprepare()
229 if (!r->rate) in clk_rpm_unprepare()
233 if (peer->enabled) in clk_rpm_unprepare()
234 to_active_sleep(peer, peer->rate, &peer_rate, in clk_rpm_unprepare()
237 active_rate = r->branch ? !!peer_rate : peer_rate; in clk_rpm_unprepare()
242 sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate; in clk_rpm_unprepare()
247 r->enabled = false; in clk_rpm_unprepare()
256 struct rpm_cc *rcc = r->rpm_cc; in clk_rpm_xo_prepare()
257 int ret, clk_id = r->rpm_clk_id; in clk_rpm_xo_prepare()
260 mutex_lock(&rcc->xo_lock); in clk_rpm_xo_prepare()
262 value = rcc->xo_buffer_value | (QCOM_RPM_XO_MODE_ON << r->xo_offset); in clk_rpm_xo_prepare()
263 ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1); in clk_rpm_xo_prepare()
265 r->enabled = true; in clk_rpm_xo_prepare()
266 rcc->xo_buffer_value = value; in clk_rpm_xo_prepare()
269 mutex_unlock(&rcc->xo_lock); in clk_rpm_xo_prepare()
277 struct rpm_cc *rcc = r->rpm_cc; in clk_rpm_xo_unprepare()
278 int ret, clk_id = r->rpm_clk_id; in clk_rpm_xo_unprepare()
281 mutex_lock(&rcc->xo_lock); in clk_rpm_xo_unprepare()
283 value = rcc->xo_buffer_value & ~(QCOM_RPM_XO_MODE_ON << r->xo_offset); in clk_rpm_xo_unprepare()
284 ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1); in clk_rpm_xo_unprepare()
286 r->enabled = false; in clk_rpm_xo_unprepare()
287 rcc->xo_buffer_value = value; in clk_rpm_xo_unprepare()
290 mutex_unlock(&rcc->xo_lock); in clk_rpm_xo_unprepare()
299 ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, in clk_rpm_fixed_prepare()
300 r->rpm_clk_id, &value, 1); in clk_rpm_fixed_prepare()
302 r->enabled = true; in clk_rpm_fixed_prepare()
313 ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, in clk_rpm_fixed_unprepare()
314 r->rpm_clk_id, &value, 1); in clk_rpm_fixed_unprepare()
316 r->enabled = false; in clk_rpm_fixed_unprepare()
323 struct clk_rpm *peer = r->peer; in clk_rpm_set_rate()
331 if (!r->enabled) in clk_rpm_set_rate()
337 if (peer->enabled) in clk_rpm_set_rate()
338 to_active_sleep(peer, peer->rate, in clk_rpm_set_rate()
341 active_rate = max(this_rate, peer_rate); in clk_rpm_set_rate()
346 sleep_rate = max(this_sleep_rate, peer_sleep_rate); in clk_rpm_set_rate()
351 r->rate = rate; in clk_rpm_set_rate()
363 * RPM handles rate rounding and we don't have a way to in clk_rpm_round_rate()
376 * RPM handles rate rounding and we don't have a way to in clk_rpm_recalc_rate()
380 return r->rate; in clk_rpm_recalc_rate()
508 { .compatible = "qcom,rpmcc-msm8660", .data = &rpm_clk_msm8660 },
509 { .compatible = "qcom,rpmcc-apq8060", .data = &rpm_clk_msm8660 },
510 { .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 },
511 { .compatible = "qcom,rpmcc-ipq806x", .data = &rpm_clk_ipq806x },
520 unsigned int idx = clkspec->args[0]; in qcom_rpm_clk_hw_get()
522 if (idx >= rcc->num_clks) { in qcom_rpm_clk_hw_get()
524 return ERR_PTR(-EINVAL); in qcom_rpm_clk_hw_get()
527 return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT); in qcom_rpm_clk_hw_get()
535 struct qcom_rpm *rpm; in rpm_clk_probe() local
539 rpm = dev_get_drvdata(pdev->dev.parent); in rpm_clk_probe()
540 if (!rpm) { in rpm_clk_probe()
541 dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n"); in rpm_clk_probe()
542 return -ENODEV; in rpm_clk_probe()
545 desc = of_device_get_match_data(&pdev->dev); in rpm_clk_probe()
547 return -EINVAL; in rpm_clk_probe()
549 rpm_clks = desc->clks; in rpm_clk_probe()
550 num_clks = desc->num_clks; in rpm_clk_probe()
552 rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL); in rpm_clk_probe()
554 return -ENOMEM; in rpm_clk_probe()
556 rcc->clks = rpm_clks; in rpm_clk_probe()
557 rcc->num_clks = num_clks; in rpm_clk_probe()
558 mutex_init(&rcc->xo_lock); in rpm_clk_probe()
564 rpm_clks[i]->rpm = rpm; in rpm_clk_probe()
565 rpm_clks[i]->rpm_cc = rcc; in rpm_clk_probe()
576 ret = devm_clk_hw_register(&pdev->dev, &rpm_clks[i]->hw); in rpm_clk_probe()
581 ret = devm_of_clk_add_hw_provider(&pdev->dev, qcom_rpm_clk_hw_get, in rpm_clk_probe()
588 dev_err(&pdev->dev, "Error registering RPM Clock driver (%d)\n", ret); in rpm_clk_probe()
594 .name = "qcom-clk-rpm",
612 MODULE_DESCRIPTION("Qualcomm RPM Clock Controller Driver");
614 MODULE_ALIAS("platform:qcom-clk-rpm");