aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2018-07-09 05:58:28 -0700
committerLinux Build Service Account <lnxbuild@localhost>2018-07-09 05:58:28 -0700
commit0af07ac8a44d9a4970d1299cefaf235edcbfc148 (patch)
treefe72492153e6c45147639ed43647e2c607d506fa
parent404fa617fe7bfd66f0ff0290d1099bb400fa9304 (diff)
parentaf6c12919000fc0891eb4347653091bc93bd13fc (diff)
Merge af6c12919000fc0891eb4347653091bc93bd13fc on remote branchLA.UM.6.3.r6-01900-sdm845.0
Change-Id: I25e45f1d2072d218a8002609d6e3480735b7663a
-rw-r--r--Documentation/devicetree/bindings/sound/qcom-audio-dev.txt8
-rw-r--r--arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-audio.dtsi13
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi24
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-v2.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi2
-rw-r--r--drivers/gpu/msm/adreno.c7
-rw-r--r--drivers/gpu/msm/adreno.h7
-rw-r--r--drivers/gpu/msm/adreno_a6xx.c34
-rw-r--r--drivers/gpu/msm/adreno_a6xx_preempt.c73
-rw-r--r--drivers/gpu/msm/kgsl_gmu.c27
-rw-r--r--drivers/gpu/msm/kgsl_gmu.h8
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c19
20 files changed, 202 insertions, 78 deletions
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 593aad56c0ba..3253a8fdc93f 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -298,6 +298,12 @@ Required properties:
Required properties:
- compatible : "qcom,msm-audio-apr"
+ This device is added to represent APR module.
+
+ - qcom,subsys-name: This value provides the subsystem name where codec
+ is present. It can be "apr_modem" or "apr_adsp". This
+ property enable apr driver to receive subsystem up/down
+ notification from modem/adsp.
* msm-ocmem-audio
@@ -648,6 +654,8 @@ Example:
qcom,msm-audio-apr {
compatible = "qcom,msm-audio-apr";
+
+ qcom,subsys-name = "apr_adsp";
};
qcom,msm-ocmem-audio {
diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
index ac205ddc2e6b..a6e47ba6d1a9 100644
--- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -299,6 +299,7 @@
audio_apr: qcom,msm-audio-apr {
compatible = "qcom,msm-audio-apr";
+ qcom,subsys-name = "apr_adsp";
};
dai_pri_auxpcm: qcom,msm-pri-auxpcm {
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
index 025d9a2b61aa..479e8ffa9c59 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -179,6 +179,10 @@
/delete-property/ parent-supply;
};
+&gpu_cx_gdsc {
+ /delete-property/ parent-supply;
+};
+
&mdss_dsi_phy0 {
/delete-property/ vdda-0p9-supply;
};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi b/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
index a881ec408587..f9179cb3af0d 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -102,7 +102,8 @@
pm8005_s1_level: regulator-pm8005-s1-level {
regulator-name = "pm8005_s1_level";
qcom,set = <RPMH_REGULATOR_SET_ALL>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
@@ -110,7 +111,8 @@
pm8005_s1_level_ao: regulator-pm8005-s1-level-ao {
regulator-name = "pm8005_s1_level_ao";
qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
index 9898ada429cc..f4889e0c6c07 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -133,7 +133,8 @@
pm660l_s3_level: regulator-pm660l-s3-level {
regulator-name = "pm660l_s3_level";
qcom,set = <RPMH_REGULATOR_SET_ALL>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
@@ -141,7 +142,8 @@
pm660l_s3_level_ao: regulator-pm660l-s3-level-ao {
regulator-name = "pm660l_s3_level_ao";
qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 8438f07f82df..4797f0c6fadc 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -2860,6 +2860,7 @@
};
&gpu_cx_gdsc {
+ parent-supply = <&pm660l_s3_level>;
status = "ok";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
index a5c6d84ccdbe..b5c1ded20fc7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -27,7 +27,9 @@
qcom,clk-div = <192>;
qcom,clk-mult = <10>;
};
+};
+&audio_apr {
snd_934x: sound-tavil {
compatible = "qcom,sdm845-asoc-snd-tavil";
qcom,model = "sdm845-tavil-snd-card";
@@ -37,15 +39,6 @@
qcom,auxpcm-audio-intf;
qcom,msm-mi2s-master = <1>, <1>, <1>, <1>;
- reg = <0x1711a000 0x4>,
- <0x1711b000 0x4>,
- <0x1711c000 0x4>,
- <0x1711d000 0x4>;
- reg-names = "lpaif_pri_mode_muxsel",
- "lpaif_sec_mode_muxsel",
- "lpaif_tert_mode_muxsel",
- "lpaif_quat_mode_muxsel";
-
asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
<&loopback>, <&compress>, <&hostless>,
<&afe>, <&lsm>, <&routing>, <&compr>,
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
index 68f2e51fea20..99798ff1c162 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,9 +13,7 @@
#include "sdm845-audio-overlay.dtsi"
-&soc {
- sound-tavil {
- qcom,us-euro-gpios = <&tavil_us_euro_sw>;
- };
+&snd_934x {
+ qcom,us-euro-gpios = <&tavil_us_euro_sw>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
index d6be6d49586e..0a02bfb636f7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
@@ -265,6 +265,10 @@
/delete-property/ vdd_mx-supply;
};
+&gpu_cx_gdsc {
+ /delete-property/ parent-supply;
+};
+
&gpu_gx_gdsc {
/delete-property/ parent-supply;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
index 361fa2fa9bec..ed7550758a37 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,21 +13,19 @@
#include "sdm845-audio-overlay.dtsi"
-&soc {
- sound-tavil {
- qcom,model = "sdm845-tavil-qrd-snd-card";
+&snd_934x {
+ qcom,model = "sdm845-tavil-qrd-snd-card";
- qcom,wsa-max-devs = <1>;
- qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
- qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrRight";
+ qcom,wsa-max-devs = <1>;
+ qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
+ qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrRight";
- qcom,msm-mbhc-usbc-audio-supported = <1>;
+ qcom,msm-mbhc-usbc-audio-supported = <1>;
- qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
- pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&wcd_usbc_analog_en2_active>;
- pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
- };
+ qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&wcd_usbc_analog_en2_active>;
+ pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
};
&us_euro_sw_wcd_active {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index f215eca36ade..2a6aca0bf6c3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -142,7 +142,8 @@
pm8998_s9_level: regulator-s9-level {
regulator-name = "pm8998_s9_level";
qcom,set = <RPMH_REGULATOR_SET_ALL>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
@@ -150,7 +151,8 @@
pm8998_s9_level_ao: regulator-s9-level-ao {
regulator-name = "pm8998_s9_level_ao";
qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
- regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+ regulator-min-microvolt
+ = <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
index 05fa2514fc75..a2ab8d70d03a 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
@@ -417,11 +417,11 @@
652800 31
748800 37
825600 42
- 902400 47
+ 864000 47
979200 52
1056000 57
1132800 62
- 1228800 70
+ 1248000 70
1324800 78
1420800 89
1516800 103
@@ -442,7 +442,7 @@
652800 1273
748800 1536
825600 1736
- 902400 1926
+ 864000 1926
979200 2108
1056000 2284
1132800 2456
@@ -462,7 +462,7 @@
2246400 8628
2323200 9344
2400000 10030
- 2476800 10806
+ 2496000 10806
2553600 12045
2649600 15686
2745600 25586
@@ -485,11 +485,11 @@
652800 5
748800 5
825600 6
- 902400 7
+ 864000 7
979200 7
1056000 8
1132800 9
- 1228800 9
+ 1248000 9
1324800 10
1420800 11
1516800 12
@@ -510,7 +510,7 @@
652800 26
748800 27
825600 28
- 902400 29
+ 864000 29
979200 30
1056000 32
1132800 34
@@ -530,7 +530,7 @@
2246400 127
2323200 130
2400000 135
- 2476800 140
+ 2496000 140
2553600 145
2649600 150
2745600 155
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 180874fa754b..407c8e1d93ed 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -776,6 +776,7 @@
<0x17a60000 0x100000>; /* GICR * 8 */
interrupts = <1 9 4>;
interrupt-parent = <&intc>;
+ ignored-save-restore-irqs = <38>;
};
pdc: interrupt-controller@b220000{
@@ -4050,6 +4051,7 @@
};
&gpu_cx_gdsc {
+ parent-supply = <&pm8998_s9_level>;
status = "ok";
};
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index ae61bec1f0ab..39c6239a46c1 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1814,11 +1814,6 @@ error_oob_clear:
error_mmu_off:
kgsl_mmu_stop(&device->mmu);
- if (gpudev->oob_clear &&
- ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
- gpudev->oob_clear(adreno_dev,
- OOB_BOOT_SLUMBER_CLEAR_MASK);
- }
error_pwr_off:
/* set the state back to original state */
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index e0f8d5a66030..8b0cf1f638f9 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1851,8 +1851,11 @@ static inline int adreno_perfcntr_active_oob_get(
ret = gpudev->oob_set(adreno_dev, OOB_PERFCNTR_SET_MASK,
OOB_PERFCNTR_CHECK_MASK,
OOB_PERFCNTR_CLEAR_MASK);
- if (ret)
+ if (ret) {
+ adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
+ adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev));
kgsl_active_count_put(KGSL_DEVICE(adreno_dev));
+ }
}
return ret;
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 18a06a41d371..82b138a72f9b 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -64,6 +64,9 @@ static const struct adreno_vbif_platform a6xx_vbif_platforms[] = {
{ adreno_is_a615, a615_gbif },
};
+
+static unsigned long a6xx_oob_state_bitmask;
+
struct kgsl_hwcg_reg {
unsigned int off;
unsigned int val;
@@ -1449,7 +1452,7 @@ static int a6xx_oob_set(struct adreno_device *adreno_dev,
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
int ret = 0;
- if (!kgsl_gmu_isenabled(device))
+ if (!kgsl_gmu_isenabled(device) || !clear_mask)
return 0;
kgsl_gmu_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, set_mask);
@@ -1465,6 +1468,8 @@ static int a6xx_oob_set(struct adreno_device *adreno_dev,
kgsl_gmu_regwrite(device, A6XX_GMU_GMU2HOST_INTR_CLR, clear_mask);
+ set_bit((fls(clear_mask) - 1), &a6xx_oob_state_bitmask);
+
trace_kgsl_gmu_oob_set(set_mask);
return ret;
}
@@ -1479,10 +1484,15 @@ static inline void a6xx_oob_clear(struct adreno_device *adreno_dev,
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
- if (!kgsl_gmu_isenabled(device))
+ if (!kgsl_gmu_isenabled(device) || !clear_mask)
return;
- kgsl_gmu_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, clear_mask);
+ if (test_and_clear_bit(fls(clear_mask) - 1,
+ &a6xx_oob_state_bitmask))
+ kgsl_gmu_regwrite(device,
+ A6XX_GMU_HOST2GMU_INTR_SET,
+ clear_mask);
+
trace_kgsl_gmu_oob_clear(clear_mask);
}
@@ -1694,6 +1704,10 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)
struct device *dev = &gmu->pdev->dev;
int val;
+ /* Only trigger wakeup sequence if sleep sequence was done earlier */
+ if (!test_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags))
+ return 0;
+
kgsl_gmu_regread(device, A6XX_GPU_CC_GX_DOMAIN_MISC, &val);
if (!(val & 0x1))
dev_err_ratelimited(&gmu->pdev->dev,
@@ -1723,6 +1737,9 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)
kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0);
+ /* Clear sleep sequence flag as wakeup sequence is successful */
+ clear_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags);
+
/* Enable the power counter because it was disabled before slumber */
kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);
@@ -1738,6 +1755,9 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int ret;
+ if (test_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags))
+ return 0;
+
/* RSC sleep sequence is different on v1 */
if (adreno_is_a630v1(adreno_dev))
kgsl_gmu_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
@@ -1779,6 +1799,7 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)
test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag))
kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 0);
+ set_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags);
return 0;
}
@@ -1797,15 +1818,13 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device,
unsigned int chipid = 0;
switch (boot_state) {
- case GMU_RESET:
- /* fall through */
case GMU_COLD_BOOT:
/* Turn on TCM retention */
kgsl_gmu_regwrite(device, A6XX_GMU_GENERAL_7, 1);
if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags))
_load_gmu_rpmh_ucode(device);
- else if (boot_state != GMU_RESET) {
+ else {
ret = a6xx_rpmh_power_on_gpu(device);
if (ret)
return ret;
@@ -2306,6 +2325,9 @@ static int a6xx_rpmh_gpu_pwrctrl(struct adreno_device *adreno_dev,
ret = a6xx_gmu_suspend(device);
break;
case GMU_FW_STOP:
+ if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
+ a6xx_oob_clear(adreno_dev,
+ OOB_BOOT_SLUMBER_CLEAR_MASK);
ret = a6xx_rpmh_power_off_gpu(device);
break;
case GMU_DCVS_NOHFI:
diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c
index b9dd5f4564b5..28d4005fbc52 100644
--- a/drivers/gpu/msm/adreno_a6xx_preempt.c
+++ b/drivers/gpu/msm/adreno_a6xx_preempt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -49,8 +49,13 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer)
OOB_PREEMPTION_SET_MASK,
OOB_PREEMPTION_CHECK_MASK,
OOB_PREEMPTION_CLEAR_MASK);
- if (status)
+ if (status) {
+ adreno_set_gpu_fault(adreno_dev,
+ ADRENO_GMU_FAULT);
+ adreno_dispatcher_schedule(
+ KGSL_DEVICE(adreno_dev));
return;
+ }
}
}
@@ -227,6 +232,38 @@ static struct adreno_ringbuffer *a6xx_next_ringbuffer(
return NULL;
}
+#define GMU_ACTIVE_STATE_RETRY_MAX 100
+
+static int adreno_gmu_wait_for_active(struct adreno_device *adreno_dev)
+{
+ unsigned int reg, num_retries = 0;
+ struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
+
+ if (!kgsl_gmu_isenabled(device))
+ return 0;
+
+ kgsl_gmu_regread(device,
+ A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, &reg);
+
+ while (reg != GPU_HW_ACTIVE) {
+ /* Wait for small time before trying again */
+ udelay(5);
+ kgsl_gmu_regread(device,
+ A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, &reg);
+
+ if (num_retries == GMU_ACTIVE_STATE_RETRY_MAX &&
+ reg != GPU_HW_ACTIVE) {
+ dev_err(adreno_dev->dev.dev,
+ "GMU failed to move to ACTIVE state: 0x%x\n",
+ reg);
+ return -ETIMEDOUT;
+ }
+ num_retries++;
+ }
+
+ return 0;
+}
+
void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@@ -356,6 +393,23 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
upper_32_bits(gpuaddr),
FENCE_STATUS_WRITEDROPPED1_MASK);
+ /*
+ * Above fence writes will make sure GMU comes out of
+ * IFPC state if its was in IFPC state but it doesn't
+ * guarantee that GMU FW actually moved to ACTIVE state
+ * i.e. wake-up from IFPC is complete.
+ * Wait for GMU to move to ACTIVE state before triggering
+ * preemption. This is require to make sure CP doesn't
+ * interrupt GMU during wake-up from IFPC.
+ */
+ if (adreno_gmu_wait_for_active(adreno_dev)) {
+ adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);
+
+ adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
+ adreno_dispatcher_schedule(device);
+ return;
+ }
+
adreno_dev->next_rb = next;
/* Start the timer to detect a stuck preemption */
@@ -370,14 +424,6 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
/* Trigger the preemption */
adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_PREEMPT, cntl,
FENCE_STATUS_WRITEDROPPED1_MASK);
-
- /*
- * Once preemption has been requested with the final register write,
- * the preemption process starts and the GPU is considered busy.
- * We can now safely clear the preemption keepalive bit, allowing
- * power collapse to resume its regular activity.
- */
- kgsl_gmu_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, 0x2, 0x0);
}
void a6xx_preemption_callback(struct adreno_device *adreno_dev, int bit)
@@ -405,6 +451,13 @@ void a6xx_preemption_callback(struct adreno_device *adreno_dev, int bit)
return;
}
+ /*
+ * We can now safely clear the preemption keepalive bit, allowing
+ * power collapse to resume its regular activity.
+ */
+ kgsl_gmu_regrmw(KGSL_DEVICE(adreno_dev), A6XX_GMU_AO_SPARE_CNTL, 0x2,
+ 0x0);
+
del_timer(&adreno_dev->preempt.timer);
adreno_readreg(adreno_dev, ADRENO_REG_CP_PREEMPT_LEVEL_STATUS, &status);
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 77edd1e96aba..a7b2e42a5ac5 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -1307,15 +1307,18 @@ static int gmu_disable_gdsc(struct gmu_device *gmu)
do {
if (!regulator_is_enabled(gmu->cx_gdsc))
return 0;
- cond_resched();
+ usleep_range(10, 100);
} while (!(time_after(jiffies, t)));
+ if (!regulator_is_enabled(gmu->cx_gdsc))
+ return 0;
+
dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout");
return -ETIMEDOUT;
}
-static int gmu_suspend(struct kgsl_device *device)
+int gmu_suspend(struct kgsl_device *device)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
@@ -1401,6 +1404,7 @@ int gmu_start(struct kgsl_device *device)
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct gmu_device *gmu = &device->gmu;
+ unsigned int boot_state = GMU_WARM_BOOT;
switch (device->state) {
case KGSL_STATE_INIT:
@@ -1437,12 +1441,21 @@ int gmu_start(struct kgsl_device *device)
gmu_enable_clks(gmu);
gmu_irq_enable(device);
+ /*
+ * If unrecovered is set that means last
+ * wakeup from SLUMBER state failed. Use GMU
+ * and HFI boot state as COLD as this is a
+ * boot after RESET.
+ */
+ if (gmu->unrecovered)
+ boot_state = GMU_COLD_BOOT;
+
ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START,
- GMU_WARM_BOOT, 0);
+ boot_state, 0);
if (ret)
goto error_gmu;
- ret = hfi_start(gmu, GMU_WARM_BOOT);
+ ret = hfi_start(gmu, boot_state);
if (ret)
goto error_gmu;
@@ -1458,7 +1471,7 @@ int gmu_start(struct kgsl_device *device)
gmu_irq_enable(device);
ret = gpudev->rpmh_gpu_pwrctrl(
- adreno_dev, GMU_FW_START, GMU_RESET, 0);
+ adreno_dev, GMU_FW_START, GMU_COLD_BOOT, 0);
if (ret)
goto error_gmu;
@@ -1475,7 +1488,7 @@ int gmu_start(struct kgsl_device *device)
hfi_stop(gmu);
ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START,
- GMU_RESET, 0);
+ GMU_COLD_BOOT, 0);
if (ret)
goto error_gmu;
@@ -1488,6 +1501,8 @@ int gmu_start(struct kgsl_device *device)
break;
}
+ /* Clear unrecovered as GMU start is successful */
+ gmu->unrecovered = false;
return ret;
error_gmu:
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index 19fa9728ca67..130d4004bf77 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.h
@@ -102,6 +102,7 @@ enum gmu_flags {
GMU_HFI_ON = 2,
GMU_FAULT = 3,
GMU_DCVS_REPLAY = 4,
+ GMU_RSCC_SLEEP_SEQ_DONE = 5,
};
/**
@@ -139,13 +140,11 @@ struct rpmh_votes_t {
/*
* These are the different ways the GMU can boot. GMU_WARM_BOOT is waking up
- * from slumber. GMU_COLD_BOOT is booting for the first time. GMU_RESET
- * is a soft reset of the GMU.
+ * from slumber. GMU_COLD_BOOT is booting for the first time.
*/
enum gmu_boot {
GMU_WARM_BOOT = 0,
GMU_COLD_BOOT = 1,
- GMU_RESET = 2
};
enum gmu_load_mode {
@@ -213,6 +212,7 @@ enum gpu_idle_level {
* @ccl: CNOC BW scaling client
* @idle_level: Minimal GPU idle power level
* @fault_count: GMU fault count
+ * @unrecovered: Indicates whether GMU recovery failed or not
*/
struct gmu_device {
unsigned int ver;
@@ -247,6 +247,7 @@ struct gmu_device {
unsigned int ccl;
unsigned int idle_level;
unsigned int fault_count;
+ bool unrecovered;
};
void gmu_snapshot(struct kgsl_device *device);
@@ -256,6 +257,7 @@ void gmu_remove(struct kgsl_device *device);
int allocate_gmu_image(struct gmu_device *gmu, unsigned int size);
int gmu_start(struct kgsl_device *device);
void gmu_stop(struct kgsl_device *device);
+int gmu_suspend(struct kgsl_device *device);
int gmu_dcvs_set(struct gmu_device *gmu, unsigned int gpu_pwrlevel,
unsigned int bus_level);
#endif /* __KGSL_GMU_H */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 9a735368aa8b..9ebed976beb3 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -2737,6 +2737,25 @@ _aware(struct kgsl_device *device)
WARN_ONCE(1, "Failed to recover GMU\n");
if (device->snapshot)
device->snapshot->recovered = false;
+ /*
+ * On recovery failure, we are clearing
+ * GMU_FAULT bit and also not keeping
+ * the state as RESET to make sure any
+ * attempt to wake GMU/GPU after this
+ * is treated as a fresh start. But on
+ * recovery failure, GMU HS, clocks and
+ * IRQs are still ON/enabled because of
+ * which next GMU/GPU wakeup results in
+ * multiple warnings from GMU start as HS,
+ * clocks and IRQ were ON while doing a
+ * fresh start i.e. wake from SLUMBER.
+ *
+ * Suspend the GMU on recovery failure
+ * to make sure next attempt to wake up
+ * GMU/GPU is indeed a fresh start.
+ */
+ gmu_suspend(device);
+ gmu->unrecovered = true;
kgsl_pwrctrl_set_state(device, state);
} else {
if (device->snapshot)