From 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 16 May 2024 03:11:33 +0000
Subject: [PATCH] AX88772C_eeprom and ax8872c build together

---
 kernel/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c |  443 ++++++++++++++++++++++++++++++------------------------
 1 files changed, 245 insertions(+), 198 deletions(-)

diff --git a/kernel/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c b/kernel/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c
index d647609..02fb00d 100644
--- a/kernel/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c
+++ b/kernel/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
 /*
  *
- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2022 ARM Limited. All rights reserved.
  *
  * This program is free software and is provided to you under the terms of the
  * GNU General Public License version 2 as published by the Free Software
@@ -23,10 +23,12 @@
 
 #include <mali_kbase.h>
 #include <tl/mali_kbase_tracepoints.h>
+#include <backend/gpu/mali_kbase_devfreq.h>
 #include <backend/gpu/mali_kbase_pm_internal.h>
 
 #include <linux/of.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/devfreq.h>
 #if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
 #include <linux/devfreq_cooling.h>
@@ -34,6 +36,8 @@
 
 #include <linux/version.h>
 #include <linux/pm_opp.h>
+#include <linux/pm_runtime.h>
+#include "mali_kbase_devfreq.h"
 
 #include <soc/rockchip/rockchip_ipa.h>
 #include <soc/rockchip/rockchip_opp_select.h>
@@ -42,14 +46,53 @@
 static struct devfreq_simple_ondemand_data ondemand_data;
 
 static struct monitor_dev_profile mali_mdevp = {
-	.type = MONITOR_TPYE_DEV,
+	.type = MONITOR_TYPE_DEV,
 	.low_temp_adjust = rockchip_monitor_dev_low_temp_adjust,
 	.high_temp_adjust = rockchip_monitor_dev_high_temp_adjust,
+	.update_volt = rockchip_monitor_check_rate_volt,
 };
 
+/**
+ * get_voltage() - Get the voltage value corresponding to the nominal frequency
+ *                 used by devfreq.
+ * @kbdev:    Device pointer
+ * @freq:     Nominal frequency in Hz passed by devfreq.
+ *
+ * This function will be called only when the opp table which is compatible with
+ * "operating-points-v2-mali", is not present in the devicetree for GPU device.
+ *
+ * Return: Voltage value in micro volts, 0 in case of error.
+ */
+static unsigned long get_voltage(struct kbase_device *kbdev, unsigned long freq)
+{
+	struct dev_pm_opp *opp;
+	unsigned long voltage = 0;
+
+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
+	rcu_read_lock();
+#endif
+
+	opp = dev_pm_opp_find_freq_exact(kbdev->dev, freq, true);
+
+	if (IS_ERR_OR_NULL(opp))
+		dev_err(kbdev->dev, "Failed to get opp (%d)\n", PTR_ERR_OR_ZERO(opp));
+	else {
+		voltage = dev_pm_opp_get_voltage(opp);
+#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE
+		dev_pm_opp_put(opp);
+#endif
+	}
+
+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
+	rcu_read_unlock();
+#endif
+
+	/* Return the voltage in micro volts */
+	return voltage;
+}
+
 void kbase_devfreq_opp_translate(struct kbase_device *kbdev, unsigned long freq,
-				 unsigned long volt, u64 *core_mask,
-				 unsigned long *freqs, unsigned long *volts)
+	u64 *core_mask, unsigned long *freqs, unsigned long *volts)
 {
 	unsigned int i;
 
@@ -73,167 +116,161 @@
 	 * and nominal frequency and the corresponding voltage.
 	 */
 	if (i == kbdev->num_opps) {
+		unsigned long voltage = get_voltage(kbdev, freq);
+
 		*core_mask = kbdev->gpu_props.props.raw_props.shader_present;
 
 		for (i = 0; i < kbdev->nr_clocks; i++) {
 			freqs[i] = freq;
-			volts[i] = volt;
+			volts[i] = voltage;
 		}
 	}
 }
 
+int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data)
+{
+	struct device *dev = data->dev;
+	struct dev_pm_opp_supply *old_supply_vdd = &data->old_opp.supplies[0];
+	struct dev_pm_opp_supply *new_supply_vdd = &data->new_opp.supplies[0];
+	struct regulator *vdd_reg = data->regulators[0];
+	struct dev_pm_opp_supply *old_supply_mem;
+	struct dev_pm_opp_supply *new_supply_mem;
+	struct regulator *mem_reg;
+	struct clk *clk = data->clk;
+	struct kbase_device *kbdev = dev_get_drvdata(dev);
+	struct rockchip_opp_info *opp_info = &kbdev->opp_info;
+	unsigned long old_freq = data->old_opp.rate;
+	unsigned long new_freq = data->new_opp.rate;
+	unsigned int reg_count = data->regulator_count;
+	bool is_set_rm = true;
+	bool is_set_clk = true;
+	u32 target_rm = UINT_MAX;
+	int ret = 0;
+
+	if (reg_count > 1) {
+		old_supply_mem = &data->old_opp.supplies[1];
+		new_supply_mem = &data->new_opp.supplies[1];
+		mem_reg = data->regulators[1];
+	}
+
+	if (!pm_runtime_active(dev)) {
+		is_set_rm = false;
+		if (opp_info->scmi_clk)
+			is_set_clk = false;
+	}
+
+	ret = clk_bulk_prepare_enable(opp_info->num_clks,  opp_info->clks);
+	if (ret) {
+		dev_err(dev, "failed to enable opp clks\n");
+		return ret;
+	}
+	rockchip_get_read_margin(dev, opp_info, new_supply_vdd->u_volt,
+				 &target_rm);
+
+	/* Change frequency */
+	dev_dbg(dev, "switching OPP: %lu Hz --> %lu Hz\n", old_freq, new_freq);
+	/* Scaling up? Scale voltage before frequency */
+	if (new_freq >= old_freq) {
+		rockchip_set_intermediate_rate(dev, opp_info, clk, old_freq,
+					       new_freq, true, is_set_clk);
+		if (reg_count > 1) {
+			ret = regulator_set_voltage(mem_reg,
+						    new_supply_mem->u_volt,
+						    INT_MAX);
+			if (ret) {
+				dev_err(dev, "failed to set volt %lu uV for mem reg\n",
+					new_supply_mem->u_volt);
+				goto restore_voltage;
+			}
+		}
+		ret = regulator_set_voltage(vdd_reg, new_supply_vdd->u_volt,
+					    INT_MAX);
+		if (ret) {
+			dev_err(dev, "failed to set volt %lu uV for vdd reg\n",
+				new_supply_vdd->u_volt);
+			goto restore_voltage;
+		}
+		rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm);
+		if (is_set_clk && clk_set_rate(clk, new_freq)) {
+			ret = -EINVAL;
+			dev_err(dev, "failed to set clk rate\n");
+			goto restore_rm;
+		}
+	/* Scaling down? Scale voltage after frequency */
+	} else {
+		rockchip_set_intermediate_rate(dev, opp_info, clk, old_freq,
+					       new_freq, false, is_set_clk);
+		rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm);
+		if (is_set_clk && clk_set_rate(clk, new_freq)) {
+			ret = -EINVAL;
+			dev_err(dev, "failed to set clk rate\n");
+			goto restore_rm;
+		}
+		ret = regulator_set_voltage(vdd_reg, new_supply_vdd->u_volt,
+					    INT_MAX);
+		if (ret) {
+			dev_err(dev, "failed to set volt %lu uV for vdd reg\n",
+				new_supply_vdd->u_volt);
+			goto restore_freq;
+		}
+		if (reg_count > 1) {
+			ret = regulator_set_voltage(mem_reg,
+						    new_supply_mem->u_volt,
+						    INT_MAX);
+			if (ret) {
+				dev_err(dev, "failed to set volt %lu uV for mem reg\n",
+					new_supply_mem->u_volt);
+				goto restore_voltage;
+			}
+		}
+	}
+
+	clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks);
+
+	return 0;
+
+restore_freq:
+	if (is_set_clk && clk_set_rate(clk, old_freq))
+		dev_err(dev, "failed to restore old-freq %lu Hz\n", old_freq);
+restore_rm:
+	rockchip_get_read_margin(dev, opp_info, old_supply_vdd->u_volt,
+				 &target_rm);
+	rockchip_set_read_margin(dev, opp_info, opp_info->target_rm, is_set_rm);
+restore_voltage:
+	if (reg_count > 1 && old_supply_mem->u_volt)
+		regulator_set_voltage(mem_reg, old_supply_mem->u_volt, INT_MAX);
+	regulator_set_voltage(vdd_reg, old_supply_vdd->u_volt, INT_MAX);
+	clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks);
+
+	return ret;
+}
+
 static int
-kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
+kbase_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
 {
 	struct kbase_device *kbdev = dev_get_drvdata(dev);
 	struct dev_pm_opp *opp;
-	unsigned long nominal_freq, nominal_volt;
-	unsigned long freqs[BASE_MAX_NR_CLOCKS_REGULATORS] = {0};
-	unsigned long old_freqs[BASE_MAX_NR_CLOCKS_REGULATORS] = {0};
-	unsigned long volts[BASE_MAX_NR_CLOCKS_REGULATORS] = {0};
-	unsigned int i;
-	u64 core_mask = 0;
+	int ret = 0;
 
-	nominal_freq = *target_freq;
+	if (!mali_mdevp.is_checked)
+		return -EINVAL;
 
-#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
-	rcu_read_lock();
-#endif
-	opp = devfreq_recommended_opp(dev, &nominal_freq, flags);
-	if (IS_ERR_OR_NULL(opp)) {
-#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
-		rcu_read_unlock();
-#endif
-		dev_err(dev, "Failed to get opp (%ld)\n", PTR_ERR(opp));
+	opp = devfreq_recommended_opp(dev, freq, flags);
+	if (IS_ERR(opp))
 		return PTR_ERR(opp);
-	}
-	nominal_volt = dev_pm_opp_get_voltage(opp);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-	rcu_read_unlock();
-#endif
-#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE
 	dev_pm_opp_put(opp);
-#endif
 
-	kbase_devfreq_opp_translate(kbdev,
-				    nominal_freq,
-				    nominal_volt,
-				    &core_mask,
-				    freqs,
-				    volts);
-
-	/*
-	 * Only update if there is a change of frequency
-	 */
-	if (kbdev->current_nominal_freq == nominal_freq) {
-		unsigned int i;
-		int err;
-
-		*target_freq = nominal_freq;
-
-#ifdef CONFIG_REGULATOR
-		for (i = 0; i < kbdev->nr_regulators; i++) {
-			if (kbdev->current_voltages[i] == volts[i])
-				continue;
-
-			err = regulator_set_voltage(kbdev->regulators[i],
-						    volts[i],
-						    INT_MAX);
-			if (err) {
-				dev_err(dev, "Failed to set voltage (%d)\n", err);
-				return err;
-			}
-			kbdev->current_voltages[i] = volts[i];
-		}
-#endif
+	if (*freq == kbdev->current_nominal_freq)
 		return 0;
+	rockchip_monitor_volt_adjust_lock(kbdev->mdev_info);
+	ret = dev_pm_opp_set_rate(dev, *freq);
+	if (!ret) {
+		kbdev->current_nominal_freq = *freq;
+		KBASE_TLSTREAM_AUX_DEVFREQ_TARGET(kbdev, (u64)*freq);
 	}
+	rockchip_monitor_volt_adjust_unlock(kbdev->mdev_info);
 
-	dev_dbg(dev, "%lu-->%lu\n", kbdev->current_nominal_freq, nominal_freq);
-
-#if IS_ENABLED(CONFIG_REGULATOR)
-	/* Regulators and clocks work in pairs: every clock has a regulator,
-	 * and we never expect to have more regulators than clocks.
-	 *
-	 * We always need to increase the voltage before increasing
-	 * the frequency of a regulator/clock pair, otherwise the clock
-	 * wouldn't have enough power to perform the transition.
-	 *
-	 * It's always safer to decrease the frequency before decreasing
-	 * voltage of a regulator/clock pair, otherwise the clock could have
-	 * problems operating if it is deprived of the necessary power
-	 * to sustain its current frequency (even if that happens for a short
-	 * transition interval).
-	 */
-
-	for (i = 0; i < kbdev->nr_clocks; i++)
-		old_freqs[i] = kbdev->current_freqs[i];
-
-	for (i = 0; i < kbdev->nr_clocks; i++) {
-		if (kbdev->regulators[i] &&
-				kbdev->current_voltages[i] != volts[i] &&
-				old_freqs[i] < freqs[i]) {
-			int err;
-
-			err = regulator_set_voltage(kbdev->regulators[i],
-				volts[i], INT_MAX);
-			if (!err) {
-				kbdev->current_voltages[i] = volts[i];
-			} else {
-				dev_err(dev, "Failed to increase voltage (%d) (target %lu)\n",
-					err, volts[i]);
-				return err;
-			}
-		}
-	}
-#endif
-
-	for (i = 0; i < kbdev->nr_clocks; i++) {
-		if (kbdev->clocks[i]) {
-			int err;
-
-			err = clk_set_rate(kbdev->clocks[i], freqs[i]);
-			if (!err) {
-				kbdev->current_freqs[i] = freqs[i];
-			} else {
-				dev_err(dev, "Failed to set clock %lu (target %lu)\n",
-					freqs[i], *target_freq);
-				return err;
-			}
-		}
-	}
-
-#if IS_ENABLED(CONFIG_REGULATOR)
-	for (i = 0; i < kbdev->nr_clocks; i++) {
-		if (kbdev->regulators[i] &&
-				kbdev->current_voltages[i] != volts[i] &&
-				old_freqs[i] > freqs[i]) {
-			int err;
-
-			err = regulator_set_voltage(kbdev->regulators[i],
-				volts[i], INT_MAX);
-			if (!err) {
-				kbdev->current_voltages[i] = volts[i];
-			} else {
-				dev_err(dev, "Failed to decrease voltage (%d) (target %lu)\n",
-					err, volts[i]);
-				return err;
-			}
-		}
-	}
-#endif
-
-	kbase_devfreq_set_core_mask(kbdev, core_mask);
-
-	*target_freq = nominal_freq;
-	kbdev->current_nominal_freq = nominal_freq;
-	kbdev->current_core_mask = core_mask;
-	if (kbdev->devfreq)
-		kbdev->devfreq->last_status.current_frequency = nominal_freq;
-
-	KBASE_TLSTREAM_AUX_DEVFREQ_TARGET(kbdev, (u64)nominal_freq);
-
-	return 0;
+	return ret;
 }
 
 void kbase_devfreq_force_freq(struct kbase_device *kbdev, unsigned long freq)
@@ -267,7 +304,8 @@
 	stat->private_data = NULL;
 
 #if MALI_USE_CSF && defined CONFIG_DEVFREQ_THERMAL
-	kbase_ipa_reset_data(kbdev);
+	if (!kbdev->dfc_power.dyn_power_coeff)
+		kbase_ipa_reset_data(kbdev);
 #endif
 
 	return 0;
@@ -318,6 +356,7 @@
 				count, i);
 
 	dp->max_state = i;
+
 
 	/* Have the lowest clock as suspend clock.
 	 * It may be overridden by 'opp-mali-errata-1485982'.
@@ -642,19 +681,16 @@
 	return rockchip_ipa_get_static_power(kbdev->model_data, voltage);
 }
 
-static struct devfreq_cooling_power kbase_cooling_power = {
-	.get_static_power = &kbase_devfreq_get_static_power,
-};
-
 int kbase_devfreq_init(struct kbase_device *kbdev)
 {
-	struct devfreq_cooling_power *kbase_dcp = &kbase_cooling_power;
+	struct devfreq_cooling_power *kbase_dcp = &kbdev->dfc_power;
 	struct device_node *np = kbdev->dev->of_node;
+	struct device_node *model_node;
 	struct devfreq_dev_profile *dp;
 	int err;
 	struct dev_pm_opp *opp;
-	unsigned long opp_rate;
 	unsigned int i;
+	bool free_devfreq_freq_table = true;
 
 	if (kbdev->nr_clocks == 0) {
 		dev_err(kbdev->dev, "Clock not available for devfreq\n");
@@ -668,11 +704,18 @@
 		else
 			kbdev->current_freqs[i] = 0;
 	}
+	if (strstr(__clk_get_name(kbdev->clocks[0]), "scmi"))
+		kbdev->opp_info.scmi_clk = kbdev->clocks[0];
 	kbdev->current_nominal_freq = kbdev->current_freqs[0];
+
+	opp = devfreq_recommended_opp(kbdev->dev, &kbdev->current_nominal_freq, 0);
+	if (IS_ERR(opp))
+		return PTR_ERR(opp);
+	dev_pm_opp_put(opp);
 
 	dp = &kbdev->devfreq_profile;
 
-	dp->initial_freq = kbdev->current_freqs[0];
+	dp->initial_freq = kbdev->current_nominal_freq;
 	dp->polling_ms = 100;
 	dp->target = kbase_devfreq_target;
 	dp->get_dev_status = kbase_devfreq_status;
@@ -687,12 +730,9 @@
 		kbdev->gpu_props.props.core_props.gpu_freq_khz_max =
 			dp->freq_table[0] / 1000;
 	};
-
 	err = kbase_devfreq_init_core_mask_table(kbdev);
-	if (err) {
-		kbase_devfreq_term_freq_table(kbdev);
-		return err;
-	}
+	if (err)
+		goto init_core_mask_table_failed;
 
 	of_property_read_u32(np, "upthreshold",
 			     &ondemand_data.upthreshold);
@@ -703,21 +743,18 @@
 	if (IS_ERR(kbdev->devfreq)) {
 		err = PTR_ERR(kbdev->devfreq);
 		kbdev->devfreq = NULL;
-		kbase_devfreq_term_core_mask_table(kbdev);
-		kbase_devfreq_term_freq_table(kbdev);
-		dev_err(kbdev->dev, "Fail to add devfreq device(%d)\n", err);
-		return err;
+		dev_err(kbdev->dev, "Fail to add devfreq device(%d)", err);
+		goto devfreq_add_dev_failed;
 	}
+
+	/* Explicit free of freq table isn't needed after devfreq_add_device() */
+	free_devfreq_freq_table = false;
 
 	/* Initialize devfreq suspend/resume workqueue */
 	err = kbase_devfreq_work_init(kbdev);
 	if (err) {
-		if (devfreq_remove_device(kbdev->devfreq))
-			dev_err(kbdev->dev, "Fail to rm devfreq\n");
-		kbdev->devfreq = NULL;
-		kbase_devfreq_term_core_mask_table(kbdev);
-		dev_err(kbdev->dev, "Fail to init devfreq workqueue\n");
-		return err;
+		dev_err(kbdev->dev, "Fail to init devfreq workqueue");
+		goto devfreq_work_init_failed;
 	}
 
 	/* devfreq_add_device only copies a few of kbdev->dev's fields, so
@@ -728,44 +765,47 @@
 	err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq);
 	if (err) {
 		dev_err(kbdev->dev,
-			"Failed to register OPP notifier (%d)\n", err);
+			"Failed to register OPP notifier (%d)", err);
 		goto opp_notifier_failed;
 	}
 
-	opp_rate = kbdev->current_freqs[0]; /* Bifrost GPU has only 1 clock. */
-	opp = devfreq_recommended_opp(kbdev->dev, &opp_rate, 0);
-	if (!IS_ERR(opp))
-		dev_pm_opp_put(opp);
-	kbdev->devfreq->last_status.current_frequency = opp_rate;
-
 	mali_mdevp.data = kbdev->devfreq;
+	mali_mdevp.opp_info = &kbdev->opp_info;
 	kbdev->mdev_info = rockchip_system_monitor_register(kbdev->dev,
 			&mali_mdevp);
 	if (IS_ERR(kbdev->mdev_info)) {
 		dev_dbg(kbdev->dev, "without system monitor\n");
                kbdev->mdev_info = NULL;
+	       mali_mdevp.is_checked = true;
 	}
 #if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
-	if (of_find_compatible_node(kbdev->dev->of_node, NULL,
-				    "simple-power-model")) {
-		of_property_read_u32(kbdev->dev->of_node,
-				     "dynamic-power-coefficient",
-				     (u32 *)&kbase_dcp->dyn_power_coeff);
-		kbdev->model_data = rockchip_ipa_power_model_init(kbdev->dev,
-								  "gpu_leakage");
+	of_property_read_u32(kbdev->dev->of_node, "dynamic-power-coefficient",
+			     (u32 *)&kbase_dcp->dyn_power_coeff);
+	model_node = of_get_compatible_child(kbdev->dev->of_node,
+					     "simple-power-model");
+	if (model_node) {
+		of_node_put(model_node);
+		kbdev->model_data =
+			rockchip_ipa_power_model_init(kbdev->dev,
+						      "gpu_leakage");
 		if (IS_ERR_OR_NULL(kbdev->model_data)) {
 			kbdev->model_data = NULL;
-			dev_err(kbdev->dev, "failed to initialize power model\n");
-		} else if (kbdev->model_data->dynamic_coefficient) {
-			kbase_dcp->dyn_power_coeff =
-				kbdev->model_data->dynamic_coefficient;
+			if (kbase_dcp->dyn_power_coeff)
+				dev_info(kbdev->dev,
+					 "only calculate dynamic power\n");
+			else
+				dev_err(kbdev->dev,
+					"failed to initialize power model\n");
+		} else {
+			kbase_dcp->get_static_power =
+				kbase_devfreq_get_static_power;
+			if (kbdev->model_data->dynamic_coefficient)
+				kbase_dcp->dyn_power_coeff =
+					kbdev->model_data->dynamic_coefficient;
 		}
-		if (!kbase_dcp->dyn_power_coeff) {
-			err = -EINVAL;
-			dev_err(kbdev->dev, "failed to get dynamic-coefficient\n");
-			goto ipa_init_failed;
-		}
+	}
 
+	if (kbase_dcp->dyn_power_coeff) {
 		kbdev->devfreq_cooling =
 			of_devfreq_cooling_register_power(kbdev->dev->of_node,
 					kbdev->devfreq,
@@ -773,7 +813,7 @@
 		if (IS_ERR(kbdev->devfreq_cooling)) {
 			err = PTR_ERR(kbdev->devfreq_cooling);
 			dev_err(kbdev->dev, "failed to register cooling device\n");
-			goto cooling_reg_failed;
+			goto ipa_init_failed;
 		}
 	} else {
 		err = kbase_ipa_init(kbdev);
@@ -793,7 +833,6 @@
 					err);
 			goto cooling_reg_failed;
                }
-
 	}
 #endif
 
@@ -809,12 +848,18 @@
 opp_notifier_failed:
 	kbase_devfreq_work_term(kbdev);
 
+devfreq_work_init_failed:
 	if (devfreq_remove_device(kbdev->devfreq))
-		dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err);
+		dev_err(kbdev->dev, "Failed to terminate devfreq (%d)", err);
 
 	kbdev->devfreq = NULL;
 
+devfreq_add_dev_failed:
 	kbase_devfreq_term_core_mask_table(kbdev);
+
+init_core_mask_table_failed:
+	if (free_devfreq_freq_table)
+		kbase_devfreq_term_freq_table(kbdev);
 
 	return err;
 }
@@ -828,10 +873,6 @@
 #if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
 	if (kbdev->devfreq_cooling)
 		devfreq_cooling_unregister(kbdev->devfreq_cooling);
-
-	if (!kbdev->model_data)
-		kbase_ipa_term(kbdev);
-	kfree(kbdev->model_data);
 #endif
 
 	devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq);
@@ -845,4 +886,10 @@
 		kbdev->devfreq = NULL;
 
 	kbase_devfreq_term_core_mask_table(kbdev);
+
+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
+	if (!kbdev->model_data)
+		kbase_ipa_term(kbdev);
+	kfree(kbdev->model_data);
+#endif
 }

--
Gitblit v1.6.2