CHROMIUM: MALI: mediatek: Adapt to new mali core and devfreq framework

Variable names changed, change the framework to change devfreq to a
single function, instead of a triplet, as the core assumes that
frequencies and voltages are paired (but we have 2 voltages for a
single frequency).

BUG=b:149806107
TEST=boot kukui, webgl aquarium

Change-Id: I474cc23be465634e8ba2d61a5b805e8829f6a8e3
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
diff --git a/drivers/gpu/arm/midgard/platform/mediatek/mali_kbase_runtime_pm.c b/drivers/gpu/arm/midgard/platform/mediatek/mali_kbase_runtime_pm.c
index b40e407..6c1aa86 100644
--- a/drivers/gpu/arm/midgard/platform/mediatek/mali_kbase_runtime_pm.c
+++ b/drivers/gpu/arm/midgard/platform/mediatek/mali_kbase_runtime_pm.c
@@ -324,6 +324,170 @@
 	return 0;
 }
 
+static void voltage_range_check(struct kbase_device *kbdev,
+				unsigned long *voltages)
+{
+	if (voltages[1] - voltages[0] < MIN_VOLT_BIAS ||
+	    voltages[1] - voltages[0] > MAX_VOLT_BIAS)
+		voltages[1] = voltages[0] + MIN_VOLT_BIAS;
+	voltages[1] = clamp_t(unsigned long, voltages[1], VSRAM_GPU_MIN_VOLT,
+			      VSRAM_GPU_MAX_VOLT);
+}
+
+#ifdef CONFIG_REGULATOR
+static bool get_step_volt(unsigned long *step_volt, unsigned long *target_volt,
+			  int count, bool inc)
+{
+	unsigned long regulator_min_volt;
+	unsigned long regulator_max_volt;
+	unsigned long current_bias;
+	long adjust_step;
+	int i;
+
+	if (inc) {
+		current_bias = target_volt[1] - step_volt[0];
+		adjust_step = MIN_VOLT_BIAS;
+	} else {
+		current_bias = step_volt[1] - target_volt[0];
+		adjust_step = -MIN_VOLT_BIAS;
+	}
+
+	for (i = 0; i < count; ++i)
+		if (step_volt[i] != target_volt[i])
+			break;
+
+	if (i == count)
+		return 0;
+
+	for (i = 0; i < count; i++) {
+		if (i) {
+			regulator_min_volt = VSRAM_GPU_MIN_VOLT;
+			regulator_max_volt = VSRAM_GPU_MAX_VOLT;
+		} else {
+			regulator_min_volt = VGPU_MIN_VOLT;
+			regulator_max_volt = VGPU_MAX_VOLT;
+		}
+
+		if (current_bias > MAX_VOLT_BIAS) {
+			step_volt[i] = clamp_val(step_volt[0] + adjust_step,
+						 regulator_min_volt,
+						 regulator_max_volt);
+		} else {
+			step_volt[i] = target_volt[i];
+		}
+	}
+	return 1;
+}
+
+static int set_voltages(struct kbase_device *kbdev, unsigned long *voltages,
+			bool inc)
+{
+	unsigned long step_volt[BASE_MAX_NR_CLOCKS_REGULATORS];
+	int first, step;
+	int i;
+	int err;
+
+	for (i = 0; i < kbdev->nr_regulators; ++i)
+		step_volt[i] = kbdev->current_voltages[i];
+
+	if (inc) {
+		first = kbdev->nr_regulators - 1;
+		step = -1;
+	} else {
+		first = 0;
+		step = 1;
+	}
+
+	while (get_step_volt(step_volt, voltages, kbdev->nr_regulators, inc)) {
+		for (i = first; i >= 0 && i < kbdev->nr_regulators; i += step) {
+			if (kbdev->current_voltages[i] == step_volt[i])
+				continue;
+
+			err = regulator_set_voltage(kbdev->regulators[i],
+						    step_volt[i],
+						    step_volt[i] + VOLT_TOL);
+
+			if (err) {
+				dev_err(kbdev->dev,
+					"Failed to set reg %d voltage err:(%d)\n",
+					i, err);
+				return err;
+			}
+
+			kbdev->current_voltages[i] = step_volt[i];
+		}
+	}
+
+	return 0;
+}
+#endif
+
+static int set_frequency(struct kbase_device *kbdev, unsigned long freq)
+{
+	int err;
+	struct mfg_base *mfg = kbdev->platform_context;
+
+	if (kbdev->current_freqs[0] != freq) {
+		err = clk_set_parent(mfg->clk_mux, mfg->clk_sub_parent);
+		if (err) {
+			dev_err(kbdev->dev, "Failed to select sub clock src\n");
+			return err;
+		}
+
+		err = clk_set_rate(kbdev->clocks[0], freq);
+		if (err)
+			return err;
+
+		err = clk_set_parent(mfg->clk_mux, mfg->clk_main_parent);
+		if (err) {
+			dev_err(kbdev->dev,
+				"Failed to select main clock src\n");
+			return err;
+		}
+
+		kbdev->current_freqs[0] = freq;
+	}
+
+	return 0;
+}
+
+static int
+set_freqs_volts(struct kbase_device *kbdev,
+			unsigned long *freqs, unsigned long *volts)
+{
+	int err;
+
+	voltage_range_check(kbdev, volts);
+
+#ifdef CONFIG_REGULATOR
+        if (kbdev->current_voltages[0] < volts[0]) {
+                err = set_voltages(kbdev, volts, true);
+                if (err) {
+                        dev_err(kbdev->dev, "Failed to increase voltage\n");
+                        return err;
+                }
+        }
+#endif
+
+        err = set_frequency(kbdev, freqs[0]);
+        if (err) {
+                dev_err(kbdev->dev, "Failed to set clock %lu\n", freqs[0]);
+                return err;
+        }
+
+#ifdef CONFIG_REGULATOR
+        if (kbdev->current_voltages[0] > volts[0]) {
+                err = set_voltages(kbdev, volts, false);
+                if (err) {
+                        dev_err(kbdev->dev, "Failed to decrease voltage\n");
+                        return err;
+                }
+        }
+#endif
+
+	return 0;
+}
+
 static int platform_init(struct kbase_device *kbdev)
 {
 	int err;
@@ -361,6 +525,8 @@
 		goto platform_init_err;
 	}
 
+	kbdev->devfreq_set_freqs_volts = set_freqs_volts;
+
 	return 0;
 
 platform_init_err: