From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB

---
 kernel/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c |  297 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 265 insertions(+), 32 deletions(-)

diff --git a/kernel/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c b/kernel/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c
index ba5aaad..c32526a 100755
--- a/kernel/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c
+++ b/kernel/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c
@@ -13,19 +13,31 @@
 #include <mali_kbase.h>
 #include <mali_kbase_defs.h>
 #include <mali_kbase_config.h>
+#include <backend/gpu/mali_kbase_devfreq.h>
 #include <backend/gpu/mali_kbase_pm_internal.h>
 #include <backend/gpu/mali_kbase_pm_defs.h>
 
+#if MALI_USE_CSF
+#include <asm/arch_timer.h>
+#endif
+
+#include <linux/clk.h>
 #include <linux/pm_runtime.h>
 #include <linux/suspend.h>
 #include <linux/of.h>
 #include <linux/delay.h>
+#include <linux/mfd/syscon.h>
 #include <linux/nvmem-consumer.h>
+#include <linux/regmap.h>
 #include <linux/soc/rockchip/pvtm.h>
 #include <linux/thermal.h>
 #include <soc/rockchip/rockchip_opp_select.h>
+#include <soc/rockchip/rockchip_system_monitor.h>
 
+#include "mali_kbase_config_platform.h"
 #include "mali_kbase_rk.h"
+
+#define POWER_DOWN_FREQ	200000000
 
 /**
  * @file mali_kbase_config_rk.c
@@ -45,6 +57,13 @@
  */
 
 /*---------------------------------------------------------------------------*/
+#ifndef CONFIG_MALI_BIFROST_DEVFREQ
+static inline void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev,
+					     struct kbasep_pm_metrics *last,
+					     struct kbasep_pm_metrics *diff)
+{
+}
+#endif
 
 #ifdef CONFIG_REGULATOR
 static int rk_pm_enable_regulator(struct kbase_device *kbdev);
@@ -76,20 +95,32 @@
 		container_of(to_delayed_work(work), struct rk_context, work);
 	struct kbase_device *kbdev = platform->kbdev;
 
+	mutex_lock(&platform->lock);
+
 	if (!platform->is_powered) {
 		D("mali_dev is already powered off.");
+		mutex_unlock(&platform->lock);
 		return;
 	}
 
+	rockchip_monitor_volt_adjust_lock(kbdev->mdev_info);
 	if (pm_runtime_enabled(kbdev->dev)) {
 		D("to put_sync_suspend mali_dev.");
 		pm_runtime_put_sync_suspend(kbdev->dev);
 	}
+	rockchip_monitor_volt_adjust_unlock(kbdev->mdev_info);
 
-	rk_pm_disable_regulator(kbdev);
+	rk_pm_disable_clk(kbdev);
+
+	if (pm_runtime_suspended(kbdev->dev)) {
+		rk_pm_disable_regulator(kbdev);
+		platform->is_regulator_on = false;
+	}
 
 	platform->is_powered = false;
 	wake_unlock(&platform->wake_lock);
+
+	mutex_unlock(&platform->lock);
 }
 
 static int kbase_platform_rk_init(struct kbase_device *kbdev)
@@ -117,7 +148,7 @@
 		ret = -ENOMEM;
 		goto err_wq;
 	}
-	INIT_DELAYED_WORK(&platform->work, rk_pm_power_off_delay_work);
+	INIT_DEFERRABLE_WORK(&platform->work, rk_pm_power_off_delay_work);
 
 	wake_lock_init(&platform->wake_lock, WAKE_LOCK_SUSPEND, "gpu");
 
@@ -131,6 +162,8 @@
 
 	kbdev->platform_context = (void *)platform;
 	pm_runtime_enable(kbdev->dev);
+
+	mutex_init(&platform->lock);
 
 	return 0;
 
@@ -169,11 +202,39 @@
 
 static int rk_pm_callback_runtime_on(struct kbase_device *kbdev)
 {
+	struct rockchip_opp_info *opp_info = &kbdev->opp_info;
+	int ret = 0;
+
+	if (!kbdev->current_nominal_freq)
+		return 0;
+
+	ret = clk_bulk_prepare_enable(opp_info->num_clks,  opp_info->clks);
+	if (ret) {
+		dev_err(kbdev->dev, "failed to enable opp clks\n");
+		return ret;
+	}
+	if (opp_info->data && opp_info->data->set_read_margin)
+		opp_info->data->set_read_margin(kbdev->dev, opp_info,
+						opp_info->target_rm);
+	if (opp_info->scmi_clk) {
+		if (clk_set_rate(opp_info->scmi_clk,
+				 kbdev->current_nominal_freq))
+			dev_err(kbdev->dev, "failed to restore clk rate\n");
+	}
+	clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks);
+
 	return 0;
 }
 
 static void rk_pm_callback_runtime_off(struct kbase_device *kbdev)
 {
+	struct rockchip_opp_info *opp_info = &kbdev->opp_info;
+
+	if (opp_info->scmi_clk) {
+		if (clk_set_rate(opp_info->scmi_clk, POWER_DOWN_FREQ))
+			dev_err(kbdev->dev, "failed to set power down rate\n");
+	}
+	opp_info->current_rm = UINT_MAX;
 }
 
 static int rk_pm_callback_power_on(struct kbase_device *kbdev)
@@ -184,24 +245,33 @@
 
 	cancel_delayed_work_sync(&platform->work);
 
-	err = rk_pm_enable_clk(kbdev);
-	if (err) {
-		E("failed to enable clk: %d", err);
-		return err;
-	}
+	mutex_lock(&platform->lock);
 
 	if (platform->is_powered) {
 		D("mali_device is already powered.");
-		return 0;
+		ret = 0;
+		goto out;
 	}
 
 	/* we must enable vdd_gpu before pd_gpu_in_chip. */
-	err = rk_pm_enable_regulator(kbdev);
-	if (err) {
-		E("fail to enable regulator, err : %d.", err);
-		return err;
+	if (!platform->is_regulator_on) {
+		err = rk_pm_enable_regulator(kbdev);
+		if (err) {
+			E("fail to enable regulator, err : %d.", err);
+			ret = err;
+			goto out;
+		}
+		platform->is_regulator_on = true;
 	}
 
+	err = rk_pm_enable_clk(kbdev);
+	if (err) {
+		E("failed to enable clk: %d", err);
+		ret = err;
+		goto out;
+	}
+
+	rockchip_monitor_volt_adjust_lock(kbdev->mdev_info);
 	/* 若 mali_dev 的 runtime_pm 是 enabled 的, 则... */
 	if (pm_runtime_enabled(kbdev->dev)) {
 		D("to resume mali_dev syncly.");
@@ -211,16 +281,20 @@
 		err = pm_runtime_get_sync(kbdev->dev);
 		if (err < 0) {
 			E("failed to runtime resume device: %d.", err);
-			return err;
+			ret = err;
+			goto out;
 		} else if (err == 1) { /* runtime_pm_status is still active */
 			D("chip has NOT been powered off, no need to re-init.");
 			ret = 0;
 		}
 	}
+	rockchip_monitor_volt_adjust_unlock(kbdev->mdev_info);
 
 	platform->is_powered = true;
 	wake_lock(&platform->wake_lock);
 
+out:
+	mutex_unlock(&platform->lock);
 	return ret;
 }
 
@@ -228,17 +302,18 @@
 {
 	struct rk_context *platform = get_rk_context(kbdev);
 
-	rk_pm_disable_clk(kbdev);
+	D("enter");
+
 	queue_delayed_work(platform->power_off_wq, &platform->work,
 			   msecs_to_jiffies(platform->delay_ms));
 }
 
-int rk_kbase_device_runtime_init(struct kbase_device *kbdev)
+static int rk_kbase_device_runtime_init(struct kbase_device *kbdev)
 {
 	return 0;
 }
 
-void rk_kbase_device_runtime_disable(struct kbase_device *kbdev)
+static void rk_kbase_device_runtime_disable(struct kbase_device *kbdev)
 {
 }
 
@@ -257,20 +332,6 @@
 	.power_runtime_off_callback = NULL,
 #endif				/* CONFIG_PM */
 };
-
-int kbase_platform_early_init(void)
-{
-	/* Nothing needed at this stage */
-	return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-
-void kbase_platform_rk_shutdown(struct kbase_device *kbdev)
-{
-	I("to make vdd_gpu enabled for turning off pd_gpu in pm_framework.");
-	rk_pm_enable_regulator(kbdev);
-}
 
 /*---------------------------------------------------------------------------*/
 
@@ -398,7 +459,7 @@
 	unsigned long period_in_us = platform->utilisation_period * 1000;
 	u32 utilisation;
 	struct kbasep_pm_metrics metrics_when_start;
-	struct kbasep_pm_metrics metrics_diff; /* between start and end. */
+	struct kbasep_pm_metrics metrics_diff = {}; /* between start and end. */
 	u32 total_time = 0;
 	u32 busy_time = 0;
 
@@ -452,8 +513,180 @@
 	device_remove_file(dev, &dev_attr_utilisation);
 }
 
+static int rk3588_gpu_get_soc_info(struct device *dev, struct device_node *np,
+			       int *bin, int *process)
+{
+	int ret = 0;
+	u8 value = 0;
+
+	if (!bin)
+		return 0;
+
+	if (of_property_match_string(np, "nvmem-cell-names",
+				     "specification_serial_number") >= 0) {
+		ret = rockchip_nvmem_cell_read_u8(np,
+						  "specification_serial_number",
+						  &value);
+		if (ret) {
+			dev_err(dev,
+				"Failed to get specification_serial_number\n");
+			return ret;
+		}
+		/* RK3588M */
+		if (value == 0xd)
+			*bin = 1;
+		/* RK3588J */
+		else if (value == 0xa)
+			*bin = 2;
+	}
+	if (*bin < 0)
+		*bin = 0;
+	dev_info(dev, "bin=%d\n", *bin);
+
+	return ret;
+}
+
+static int rk3588_gpu_set_soc_info(struct device *dev, struct device_node *np,
+			       int bin, int process, int volt_sel)
+{
+	struct opp_table *opp_table;
+	u32 supported_hw[2];
+
+	if (volt_sel < 0)
+		return 0;
+	if (bin < 0)
+		bin = 0;
+
+	if (!of_property_read_bool(np, "rockchip,supported-hw"))
+		return 0;
+
+	/* SoC Version */
+	supported_hw[0] = BIT(bin);
+	/* Speed Grade */
+	supported_hw[1] = BIT(volt_sel);
+	opp_table = dev_pm_opp_set_supported_hw(dev, supported_hw, 2);
+	if (IS_ERR(opp_table)) {
+		dev_err(dev, "failed to set supported opp\n");
+		return PTR_ERR(opp_table);
+	}
+
+	return 0;
+}
+
+static int rk3588_gpu_set_read_margin(struct device *dev,
+				      struct rockchip_opp_info *opp_info,
+				      u32 rm)
+{
+	int ret = 0;
+	u32 val;
+
+	if (!opp_info->grf || !opp_info->volt_rm_tbl)
+		return 0;
+	if (rm == opp_info->current_rm || rm == UINT_MAX)
+		return 0;
+
+	dev_dbg(dev, "set rm to %d\n", rm);
+
+	ret = regmap_read(opp_info->grf, 0x24, &val);
+	if (ret < 0) {
+		dev_err(dev, "failed to get rm from 0x24\n");
+		return ret;
+	}
+	val &= ~0x1c;
+	regmap_write(opp_info->grf, 0x24, val | (rm << 2));
+
+	ret = regmap_read(opp_info->grf, 0x28, &val);
+	if (ret < 0) {
+		dev_err(dev, "failed to get rm from 0x28\n");
+		return ret;
+	}
+	val &= ~0x1c;
+	regmap_write(opp_info->grf, 0x28, val | (rm << 2));
+
+	opp_info->current_rm = rm;
+
+	return 0;
+}
+
+static const struct rockchip_opp_data rk3588_gpu_opp_data = {
+	.get_soc_info = rk3588_gpu_get_soc_info,
+	.set_soc_info = rk3588_gpu_set_soc_info,
+	.set_read_margin = rk3588_gpu_set_read_margin,
+};
+
+static const struct of_device_id rockchip_mali_of_match[] = {
+	{
+		.compatible = "rockchip,rk3588",
+		.data = (void *)&rk3588_gpu_opp_data,
+	},
+	{},
+};
+
 int kbase_platform_rk_init_opp_table(struct kbase_device *kbdev)
 {
-	return rockchip_init_opp_table(kbdev->dev, NULL,
+	rockchip_get_opp_data(rockchip_mali_of_match, &kbdev->opp_info);
+
+	return rockchip_init_opp_table(kbdev->dev, &kbdev->opp_info,
 				       "gpu_leakage", "mali");
 }
+
+int kbase_platform_rk_enable_regulator(struct kbase_device *kbdev)
+{
+	struct rk_context *platform = get_rk_context(kbdev);
+	int err = 0;
+
+	if (!platform->is_regulator_on) {
+		err = rk_pm_enable_regulator(kbdev);
+		if (err) {
+			E("fail to enable regulator, err : %d.", err);
+			return err;
+		}
+		platform->is_regulator_on = true;
+	}
+
+	return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void *enumerate_gpu_clk(struct kbase_device *kbdev,
+		unsigned int index)
+{
+	if (index >= kbdev->nr_clocks)
+		return NULL;
+
+	return kbdev->clocks[index];
+}
+
+static unsigned long get_gpu_clk_rate(struct kbase_device *kbdev,
+		void *gpu_clk_handle)
+{
+	return clk_get_rate((struct clk *)gpu_clk_handle);
+}
+
+static int gpu_clk_notifier_register(struct kbase_device *kbdev,
+		void *gpu_clk_handle, struct notifier_block *nb)
+{
+	compiletime_assert(offsetof(struct clk_notifier_data, clk) ==
+		offsetof(struct kbase_gpu_clk_notifier_data, gpu_clk_handle),
+		"mismatch in the offset of clk member");
+
+	compiletime_assert(sizeof(((struct clk_notifier_data *)0)->clk) ==
+	     sizeof(((struct kbase_gpu_clk_notifier_data *)0)->gpu_clk_handle),
+	     "mismatch in the size of clk member");
+
+	return clk_notifier_register((struct clk *)gpu_clk_handle, nb);
+}
+
+static void gpu_clk_notifier_unregister(struct kbase_device *kbdev,
+		void *gpu_clk_handle, struct notifier_block *nb)
+{
+	clk_notifier_unregister((struct clk *)gpu_clk_handle, nb);
+}
+
+struct kbase_clk_rate_trace_op_conf clk_rate_trace_ops = {
+	.get_gpu_clk_rate = get_gpu_clk_rate,
+	.enumerate_gpu_clk = enumerate_gpu_clk,
+	.gpu_clk_notifier_register = gpu_clk_notifier_register,
+	.gpu_clk_notifier_unregister = gpu_clk_notifier_unregister,
+};

--
Gitblit v1.6.2