CHROMIUM: MALI: Better framework to allow platform code to override devfreq

Depending on the platform, we require custom logic to handle devfreq.
The framework we used on r14p0 used 3 functions pointers, but we
can use a single one now (accepting a little bit of code duplication).

BUG=b:149806107
TEST=build kukui

Change-Id: I3b19abed242e5c1ca95338eafc93c4a35a5547b6
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
diff --git a/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c b/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c
index 6ad1581..e42fa23 100644
--- a/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c
+++ b/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c
@@ -92,6 +92,83 @@
 }
 
 static int
+default_set_freqs_volts(struct kbase_device *kbdev,
+			unsigned long *freqs, unsigned long *volts)
+{
+	unsigned int i;
+
+#ifdef 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++) {
+		if (kbdev->regulators[i] &&
+				kbdev->current_voltages[i] != volts[i] &&
+				kbdev->current_freqs[i] < freqs[i]) {
+			int err;
+
+			err = regulator_set_voltage(kbdev->regulators[i],
+				volts[i], volts[i]);
+			if (!err) {
+				kbdev->current_voltages[i] = volts[i];
+			} else {
+				dev_err(kbdev->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(kbdev->dev, "Failed to set clock %d to %lu\n",
+					i, freqs[i]);
+				return err;
+			}
+		}
+	}
+
+#ifdef CONFIG_REGULATOR
+	for (i = 0; i < kbdev->nr_clocks; i++) {
+		if (kbdev->regulators[i] &&
+				kbdev->current_voltages[i] != volts[i] &&
+				kbdev->current_freqs[i] > freqs[i]) {
+			int err;
+
+			err = regulator_set_voltage(kbdev->regulators[i],
+				volts[i], volts[i]);
+			if (!err) {
+				kbdev->current_voltages[i] = volts[i];
+			} else {
+				dev_err(kbdev->dev, "Failed to decrease voltage (%d) (target %lu)\n",
+					err, volts[i]);
+				return err;
+			}
+		}
+	}
+#endif
+
+	return 0;
+}
+
+static int
 kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
 {
 	struct kbase_device *kbdev = dev_get_drvdata(dev);
@@ -99,7 +176,7 @@
 	unsigned long nominal_freq;
 	unsigned long freqs[BASE_MAX_NR_CLOCKS_REGULATORS] = {0};
 	unsigned long volts[BASE_MAX_NR_CLOCKS_REGULATORS] = {0};
-	unsigned int i;
+	int err;
 	u64 core_mask;
 
 	nominal_freq = *target_freq;
@@ -129,73 +206,12 @@
 
 	opp_translate(kbdev, nominal_freq, &core_mask, freqs, volts);
 
-#ifdef 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++) {
-		if (kbdev->regulators[i] &&
-				kbdev->current_voltages[i] != volts[i] &&
-				kbdev->current_freqs[i] < freqs[i]) {
-			int err;
-
-			err = regulator_set_voltage(kbdev->regulators[i],
-				volts[i], volts[i]);
-			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;
-			}
-		}
-	}
-
-#ifdef CONFIG_REGULATOR
-	for (i = 0; i < kbdev->nr_clocks; i++) {
-		if (kbdev->regulators[i] &&
-				kbdev->current_voltages[i] != volts[i] &&
-				kbdev->current_freqs[i] > freqs[i]) {
-			int err;
-
-			err = regulator_set_voltage(kbdev->regulators[i],
-				volts[i], volts[i]);
-			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
+	if (kbdev->devfreq_set_freqs_volts)
+		err = kbdev->devfreq_set_freqs_volts(kbdev, freqs, volts);
+	else
+		err = default_set_freqs_volts(kbdev, freqs, volts);
+	if (err < 0)
+		return err;
 
 	kbase_devfreq_set_core_mask(kbdev, core_mask);
 
diff --git a/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
index 315ecfa..d442f3a 100644
--- a/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
+++ b/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
@@ -3471,7 +3471,8 @@
 #endif
 
 	/* Having more clocks than regulators is acceptable, while the
-	 * opposite shall not happen.
+	 * opposite shall not happen, unless the platform code has
+	 * a special handler for devfreq.
 	 *
 	 * Since the error code EPROBE_DEFER causes the entire probing
 	 * procedure to be restarted from scratch at a later time,
diff --git a/drivers/gpu/arm/midgard/mali_kbase_defs.h b/drivers/gpu/arm/midgard/mali_kbase_defs.h
index ca73872..c63330b 100644
--- a/drivers/gpu/arm/midgard/mali_kbase_defs.h
+++ b/drivers/gpu/arm/midgard/mali_kbase_defs.h
@@ -1627,6 +1627,15 @@
 	struct kbase_devfreq_queue_info devfreq_queue;
 #endif
 
+	/*
+	 * An optional callback to set frequencies and voltages, if a custom
+	 * implementation is required by the chip.
+	 *
+	 * This function needs to update kbdev->current_voltages/freqs.
+	 */
+	int (*devfreq_set_freqs_volts)(struct kbase_device *kbdev,
+				unsigned long *freqs, unsigned long *volts);
+
 #ifdef CONFIG_DEVFREQ_THERMAL
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
 	struct devfreq_cooling_device *devfreq_cooling;