feat(rk3588): support SCMI for clock/reset domain
rockchip scmi clock controls clocks which only available in secure mode.
Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com>
Change-Id: I5b983877a5b4e8acababbf7e0a3e2725e6479e08
diff --git a/plat/rockchip/common/scmi/scmi_clock.c b/plat/rockchip/common/scmi/scmi_clock.c
new file mode 100644
index 0000000..d6d4b37
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_clock.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+
+#include "scmi_clock.h"
+
+#pragma weak rockchip_scmi_clock_count
+#pragma weak rockchip_scmi_get_clock
+
+size_t rockchip_scmi_clock_count(unsigned int agent_id __unused)
+{
+ return 0;
+}
+
+rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id __unused,
+ uint32_t scmi_id __unused)
+{
+ return NULL;
+}
+
+size_t plat_scmi_clock_count(unsigned int agent_id)
+{
+ return rockchip_scmi_clock_count(agent_id);
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return NULL;
+
+ return clock->name;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned long *rates,
+ size_t *nb_elts,
+ uint32_t start_idx)
+{
+ uint32_t i;
+ unsigned long *rate_table;
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return SCMI_NOT_FOUND;
+
+ rate_table = clock->rate_table;
+ if (rate_table == NULL)
+ return SCMI_NOT_SUPPORTED;
+
+ if (rates == 0) {
+ *nb_elts = clock->rate_cnt;
+ goto out;
+ }
+
+ if (start_idx + *nb_elts > clock->rate_cnt)
+ return SCMI_OUT_OF_RANGE;
+
+ for (i = 0; i < *nb_elts; i++)
+ rates[i] = rate_table[start_idx + i];
+
+out:
+ return SCMI_SUCCESS;
+}
+
+int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ unsigned long *steps __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+ unsigned long rate = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return 0;
+
+ if (clock->clk_ops && clock->clk_ops->get_rate)
+ rate = clock->clk_ops->get_rate(clock);
+
+ /* return cur_rate if no get_rate ops or get_rate return 0 */
+ if (rate == 0)
+ rate = clock->cur_rate;
+
+ return rate;
+}
+
+int32_t plat_scmi_clock_set_rate(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned long rate)
+{
+ rk_scmi_clock_t *clock;
+ int32_t status = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return SCMI_NOT_FOUND;
+
+ if (clock->clk_ops && clock->clk_ops->set_rate) {
+ status = clock->clk_ops->set_rate(clock, rate);
+ if (status == SCMI_SUCCESS)
+ clock->cur_rate = rate;
+ } else {
+ status = SCMI_NOT_SUPPORTED;
+ }
+
+ return status;
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return 0;
+
+ return clock->enable;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id,
+ unsigned int scmi_id,
+ bool enable_not_disable)
+{
+ rk_scmi_clock_t *clock;
+ int32_t status = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return SCMI_NOT_FOUND;
+
+ if (clock->clk_ops && clock->clk_ops->set_status) {
+ status = clock->clk_ops->set_status(clock, enable_not_disable);
+ if (status == SCMI_SUCCESS)
+ clock->enable = enable_not_disable;
+ } else {
+ status = SCMI_NOT_SUPPORTED;
+ }
+
+ return status;
+}