|
@@ -0,0 +1,100 @@
|
|
|
+/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
+/*
|
|
|
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
|
|
+ */
|
|
|
+
|
|
|
+#include <linux/clk.h>
|
|
|
+#include <linux/clk-provider.h>
|
|
|
+#include <linux/ratelimit.h>
|
|
|
+#include <dsp/digital-cdc-rsc-mgr.h>
|
|
|
+
|
|
|
+struct mutex hw_vote_lock;
|
|
|
+static bool is_init_done;
|
|
|
+
|
|
|
+/**
|
|
|
+ * digital_cdc_rsc_mgr_hw_vote_enable - Enables hw vote in DSP
|
|
|
+ *
|
|
|
+ * @vote_handle: vote handle for which voting needs to be done
|
|
|
+ *
|
|
|
+ * Returns 0 on success or -EINVAL/error code on failure
|
|
|
+ */
|
|
|
+int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!is_init_done || vote_handle == NULL) {
|
|
|
+ pr_err_ratelimited("%s: init failed or vote handle NULL\n",
|
|
|
+ __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_lock(&hw_vote_lock);
|
|
|
+ ret = clk_prepare_enable(vote_handle);
|
|
|
+ mutex_unlock(&hw_vote_lock);
|
|
|
+
|
|
|
+ pr_debug("%s: return %d\n", __func__, ret);
|
|
|
+ trace_printk("%s: return %d\n", __func__, ret);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_enable);
|
|
|
+
|
|
|
+/**
|
|
|
+ * digital_cdc_rsc_mgr_hw_vote_disable - Disables hw vote in DSP
|
|
|
+ *
|
|
|
+ * @vote_handle: vote handle for which voting needs to be disabled
|
|
|
+ *
|
|
|
+ */
|
|
|
+void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle)
|
|
|
+{
|
|
|
+ if (!is_init_done || vote_handle == NULL) {
|
|
|
+ pr_err_ratelimited("%s: init failed or vote handle NULL\n",
|
|
|
+ __func__);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_lock(&hw_vote_lock);
|
|
|
+ clk_disable_unprepare(vote_handle);
|
|
|
+ mutex_unlock(&hw_vote_lock);
|
|
|
+ trace_printk("%s\n", __func__);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_disable);
|
|
|
+
|
|
|
+/**
|
|
|
+ * digital_cdc_rsc_mgr_hw_vote_reset - Resets hw vote count
|
|
|
+ *
|
|
|
+ */
|
|
|
+void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle)
|
|
|
+{
|
|
|
+ int count = 0;
|
|
|
+
|
|
|
+ if (!is_init_done || vote_handle == NULL) {
|
|
|
+ pr_err_ratelimited("%s: init failed or vote handle NULL\n",
|
|
|
+ __func__);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_lock(&hw_vote_lock);
|
|
|
+ while (__clk_is_enabled(vote_handle)) {
|
|
|
+ clk_disable_unprepare(vote_handle);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ pr_debug("%s: Vote count after SSR: %d\n", __func__, count);
|
|
|
+ trace_printk("%s: Vote count after SSR: %d\n", __func__, count);
|
|
|
+
|
|
|
+ while (count--)
|
|
|
+ clk_prepare_enable(vote_handle);
|
|
|
+ mutex_unlock(&hw_vote_lock);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset);
|
|
|
+
|
|
|
+void digital_cdc_rsc_mgr_init()
|
|
|
+{
|
|
|
+ mutex_init(&hw_vote_lock);
|
|
|
+ is_init_done = true;
|
|
|
+}
|
|
|
+
|
|
|
+void digital_cdc_rsc_mgr_exit()
|
|
|
+{
|
|
|
+ mutex_destroy(&hw_vote_lock);
|
|
|
+ is_init_done = false;
|
|
|
+}
|