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;
+}