diff --git a/kernel/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/kernel/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
index 0b01bc9a0531..bf99e3ad8844 100644
--- a/kernel/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
+++ b/kernel/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
@@ -510,6 +510,7 @@ ov5645_3_ep: endpoint {
 };
 
 &gpu {
+	vdd-supply = <&vdd_gfx>;
 	status = "okay";
 };
 
@@ -1014,8 +1015,9 @@ &pmi8994_spmi_regulators {
 	vdd_gfx: s2@1700 {
 		reg = <0x1700 0x100>;
 		regulator-name = "VDD_GFX";
-		regulator-min-microvolt = <400000>;
+		regulator-min-microvolt = <980000>;
 		regulator-max-microvolt = <1015000>;
+		regulator-always-on;
 	};
 };
 
@@ -1418,8 +1420,3 @@ &wcd9335 {
 	vdd-rx-supply = <&vreg_s4a_1p8>;
 	vdd-io-supply = <&vreg_s4a_1p8>;
 };
-
-&cpr3_gfx {
-	status = "okay";
-	vdd-supply = <&vdd_gfx>;
-};
diff --git a/kernel/arch/arm64/boot/dts/qcom/msm8996.dtsi b/kernel/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 79c34274f165..2cd8a4dc9559 100644
--- a/kernel/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/kernel/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -54,9 +54,6 @@ L2_0: l2-cache {
 			      compatible = "cache";
 			      cache-level = <2>;
 			};
-			CPU0_WARM: warming {
-				#cooling-cells = <2>;
-			};
 		};
 
 		CPU1: cpu@1 {
@@ -70,9 +67,6 @@ CPU1: cpu@1 {
 			operating-points-v2 = <&cluster0_opp>;
 			#cooling-cells = <2>;
 			next-level-cache = <&L2_0>;
-			CPU1_WARM: warming {
-				#cooling-cells = <2>;
-			};
 		};
 
 		CPU2: cpu@100 {
@@ -90,9 +84,6 @@ L2_1: l2-cache {
 			      compatible = "cache";
 			      cache-level = <2>;
 			};
-			CPU2_WARM: warming {
-				#cooling-cells = <2>;
-			};
 		};
 
 		CPU3: cpu@101 {
@@ -106,9 +97,6 @@ CPU3: cpu@101 {
 			operating-points-v2 = <&cluster1_opp>;
 			#cooling-cells = <2>;
 			next-level-cache = <&L2_1>;
-			CPU3_WARM: warming {
-				#cooling-cells = <2>;
-			};
 		};
 
 		cpu-map {
@@ -408,96 +396,6 @@ memory@80000000 {
 		reg = <0x0 0x80000000 0x0 0x0>;
 	};
 
-	pd_cx_cooling: pd-cx-cooling {
-		compatible = "power-domain-cooling";
-		power-domains = <&rpmpd MSM8996_VDDCX>;
-		#cooling-cells = <2>;
-
-		operating-points-v2 = <&cx_cool_opp_table>;
-
-		cx_cool_opp_table: opp-table {
-			opp1 {
-				opp-level = <1>;
-				required-opps = <&rpmpd_opp1>;
-			};
-
-			opp2 {
-				opp-level = <2>;
-				required-opps = <&rpmpd_opp2>;
-			};
-
-			opp3 {
-				opp-level = <3>;
-				required-opps = <&rpmpd_opp3>;
-			};
-
-			opp4 {
-				opp-level = <4>;
-				required-opps = <&rpmpd_opp4>;
-			};
-
-			opp5 {
-				opp-level = <5>;
-				required-opps = <&rpmpd_opp5>;
-			};
-
-			opp6 {
-				opp-level = <6>;
-				required-opps = <&rpmpd_opp6>;
-			};
-
-			opp7 {
-				opp-level = <7>;
-				required-opps = <&rpmpd_opp7>;
-			};
-		};
-	};
-
-	pd_mx_cooling: pd-mx-cooling {
-		compatible = "power-domain-cooling";
-		power-domains = <&rpmpd MSM8996_VDDMX>;
-		#cooling-cells = <2>;
-
-		operating-points-v2 = <&mx_cool_opp_table>;
-
-		mx_cool_opp_table: opp-table {
-			opp1 {
-				opp-level = <1>;
-				required-opps = <&rpmpd_opp1>;
-			};
-
-			opp2 {
-				opp-level = <2>;
-				required-opps = <&rpmpd_opp2>;
-			};
-
-			opp3 {
-				opp-level = <3>;
-				required-opps = <&rpmpd_opp3>;
-			};
-
-			opp4 {
-				opp-level = <4>;
-				required-opps = <&rpmpd_opp4>;
-			};
-
-			opp5 {
-				opp-level = <5>;
-				required-opps = <&rpmpd_opp5>;
-			};
-
-			opp6 {
-				opp-level = <6>;
-				required-opps = <&rpmpd_opp6>;
-			};
-
-			opp7 {
-				opp-level = <7>;
-				required-opps = <&rpmpd_opp7>;
-			};
-		};
-	};
-
 	psci {
 		compatible = "arm,psci-1.0";
 		method = "smc";
@@ -615,10 +513,6 @@ rpmpd_opp5: opp5 {
 					rpmpd_opp6: opp6 {
 						opp-level = <6>;
 					};
-
-					rpmpd_opp7: opp7 {
-						opp-level = <7>;
-					};
 				};
 			};
 		};
@@ -791,31 +685,6 @@ speedbin_efuse: speedbin@133 {
 				reg = <0x133 0x1>;
 				bits = <5 3>;
 			};
-
-			cpr_fuse_revision: fuse-revn@13e {
-				reg = <0x13e 0x1>;
-				bits = <3 3>;
-			};
-
-			cpr_gfx_init_voltage3: gfx-init-voltage3@1fd{
-				reg = <0x1fd 0x1>;
-				bits = <0 5>;
-			};
-
-			cpr_gfx_init_voltage2: gfx-init-voltage2@1fd{
-				reg = <0x1fd 0x2>;
-				bits = <5 5>;
-			};
-
-			cpr_gfx_init_voltage1: gfx-init-voltage1@1fe{
-				reg = <0x1fe 0x1>;
-				bits = <2 5>;
-			};
-
-			cpr_gfx_init_voltage0: gfx-init-voltage0@1fe{
-				reg = <0x1fe 0x2>;
-				bits = <7 5>;
-			};
 		};
 
 		rng: rng@83000 {
@@ -971,81 +840,6 @@ tcsr: syscon@7a0000 {
 			reg = <0x007a0000 0x18000>;
 		};
 
-		cpr3_gfx: power-controller@838000 {
-			compatible = "qcom,msm8996-gfx-cpr3", "qcom,cpr3";
-			reg = <0x00838000 0x4000>;
-			interrupts = <GIC_SPI 166 IRQ_TYPE_EDGE_RISING>;
-			clocks = <&mmcc MMSS_RBCPR_CLK>, <&mmcc MMSS_RBCPR_AHB_CLK>, <&mmcc MMSS_MMAGIC_AHB_CLK>;
-			clock-names = "ref", "iface", "bus";
-
-			acc-syscon = <&tcsr>;
-
-			#power-domain-cells = <1>;
-			operating-points-v2 = <&cpr3_gfx_opp_table>;
-
-			nvmem-cells = <&speedbin_efuse>,
-				      <&cpr_fuse_revision>,
-				      <&cpr_gfx_init_voltage0>,
-				      <&cpr_gfx_init_voltage1>,
-				      <&cpr_gfx_init_voltage2>,
-				      <&cpr_gfx_init_voltage3>;
-
-			nvmem-cell-names = "cpr_speed_bin",
-					   "cpr_fuse_revision",
-					   "cpr0_init_voltage1",
-					   "cpr0_init_voltage2",
-					   "cpr0_init_voltage3",
-					   "cpr0_init_voltage4";
-
-			status = "disabled";
-
-			cpr3_gfx_opp_table: opp-table-cpr3 {
-				compatible = "operating-points-v2-qcom-level";
-
-				cpr3_gfx_opp1: opp1 {
-					opp-level = <1>;
-					qcom,opp-fuse-level = <1>;
-					qcom,opp-cloop-vadj = <0>; /* 45000 for fusing_rev 0-1, 30000 for 2 */
-				};
-
-				cpr3_gfx_opp2: opp2 {
-					opp-level = <2>;
-					qcom,opp-fuse-level = <2>;
-					qcom,opp-cloop-vadj = <30000>; /* -5000 for fusing_rev 0-1, 60000 for 2 */
-				};
-
-				cpr3_gfx_opp3: opp3 {
-					opp-level = <3>;
-					qcom,opp-fuse-level = <2>;
-					qcom,opp-cloop-vadj = <10000>; /* 20000 for fusing_rev 0-1, 40000 for 2 */
-				};
-
-				cpr3_gfx_opp4: opp4 {
-					opp-level = <4>;
-					qcom,opp-fuse-level = <3>;
-					qcom,opp-cloop-vadj = <10000>; /* 20000 for fusing_rev 0-1, 40000 for 2 */
-				};
-
-				cpr3_gfx_opp5: opp5 {
-					opp-level = <5>;
-					qcom,opp-fuse-level = <3>;
-					qcom,opp-cloop-vadj = <45000>; /* 30000 for fusing_rev 0-1 */
-				};
-
-				cpr3_gfx_opp6: opp6 {
-					opp-level = <6>;
-					qcom,opp-fuse-level = <4>;
-					qcom,opp-cloop-vadj = <25000>; /* 10000 for fusing_rev 0-1 */
-				};
-
-				cpr3_gfx_opp7: opp7 {
-					opp-level = <7>;
-					qcom,opp-fuse-level = <4>;
-					qcom,opp-cloop-vadj = <25000>; /* -5000 for fusing_rev 0-1, 35000 for 2 */
-				};
-			};
-		};
-
 		mmcc: clock-controller@8c0000 {
 			compatible = "qcom,mmcc-msm8996";
 			#clock-cells = <1>;
@@ -1300,8 +1094,7 @@ gpu: gpu@b00000 {
 			interconnects = <&bimc MASTER_GRAPHICS_3D &bimc SLAVE_EBI_CH0>;
 			interconnect-names = "gfx-mem";
 
-			power-domains = <&mmcc GPU_GX_GDSC>, <&cpr3_gfx 0>, <&rpmpd MSM8996_VDDMX>;
-			power-domain-names = "gx", "cpr", "mx";
+			power-domains = <&mmcc GPU_GX_GDSC>;
 			iommus = <&adreno_smmu 0>;
 
 			nvmem-cells = <&speedbin_efuse>;
@@ -1313,10 +1106,6 @@ gpu: gpu@b00000 {
 
 			#cooling-cells = <2>;
 
-			gpu_warm: warming {
-				#cooling-cells = <2>;
-			};
-
 			gpu_opp_table: opp-table {
 				compatible  ="operating-points-v2";
 
@@ -1328,37 +1117,30 @@ gpu_opp_table: opp-table {
 				opp-624000000 {
 					opp-hz = /bits/ 64 <624000000>;
 					opp-supported-hw = <0x09>;
-					required-opps = <&cpr3_gfx_opp7 &rpmpd_opp7>;
 				};
 				opp-560000000 {
 					opp-hz = /bits/ 64 <560000000>;
 					opp-supported-hw = <0x0d>;
-					required-opps = <&cpr3_gfx_opp6 &rpmpd_opp7>;
 				};
 				opp-510000000 {
 					opp-hz = /bits/ 64 <510000000>;
 					opp-supported-hw = <0xFF>;
-					required-opps = <&cpr3_gfx_opp5 &rpmpd_opp5>;
 				};
 				opp-401800000 {
 					opp-hz = /bits/ 64 <401800000>;
 					opp-supported-hw = <0xFF>;
-					required-opps = <&cpr3_gfx_opp4 &rpmpd_opp5>;
 				};
 				opp-315000000 {
 					opp-hz = /bits/ 64 <315000000>;
 					opp-supported-hw = <0xFF>;
-					required-opps = <&cpr3_gfx_opp3 &rpmpd_opp4>;
 				};
 				opp-214000000 {
 					opp-hz = /bits/ 64 <214000000>;
 					opp-supported-hw = <0xFF>;
-					required-opps = <&cpr3_gfx_opp2 &rpmpd_opp4>;
 				};
 				opp-133000000 {
 					opp-hz = /bits/ 64 <133000000>;
 					opp-supported-hw = <0xFF>;
-					required-opps = <&cpr3_gfx_opp1 &rpmpd_opp4>;
 				};
 			};
 
@@ -3583,36 +3365,12 @@ cpu0_alert0: trip-point0 {
 					type = "passive";
 				};
 
-				cpu0_warm: cpu-warm {
-					temperature = <15000>;
-					hysteresis = <2000>;
-					type = "passive";
-					monitor-falling;
-				};
-
 				cpu0_crit: cpu_crit {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
-
-			cooling-maps {
-				map0 {
-					trip = <&cpu0_alert0>;
-					cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
-
-				map1 {
-					trip = <&cpu0_warm>;
-					cooling-device = <&CPU0_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU1_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU2_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU3_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_cx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_mx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
-			};
 		};
 
 		cpu1-thermal {
@@ -3628,36 +3386,12 @@ cpu1_alert0: trip-point0 {
 					type = "passive";
 				};
 
-				cpu1_warm: cpu-warm {
-					temperature = <15000>;
-					hysteresis = <2000>;
-					type = "passive";
-					monitor-falling;
-				};
-
 				cpu1_crit: cpu_crit {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
-
-			cooling-maps {
-				map0 {
-					trip = <&cpu1_alert0>;
-					cooling-device = <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
-
-				map1 {
-					trip = <&cpu1_warm>;
-					cooling-device = <&CPU0_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU1_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU2_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU3_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_cx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_mx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
-			};
 		};
 
 		cpu2-thermal {
@@ -3673,36 +3407,12 @@ cpu2_alert0: trip-point0 {
 					type = "passive";
 				};
 
-				cpu2_warm: cpu-warm {
-					temperature = <15000>;
-					hysteresis = <2000>;
-					type = "passive";
-					monitor-falling;
-				};
-
 				cpu2_crit: cpu_crit {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
-
-			cooling-maps {
-				map0 {
-					trip = <&cpu2_alert0>;
-					cooling-device = <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
-
-				map1 {
-					trip = <&cpu2_warm>;
-					cooling-device = <&CPU0_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU1_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU2_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU3_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_cx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_mx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
-			};
 		};
 
 		cpu3-thermal {
@@ -3718,36 +3428,12 @@ cpu3_alert0: trip-point0 {
 					type = "passive";
 				};
 
-				cpu3_warm: cpu-warm {
-					temperature = <15000>;
-					hysteresis = <2000>;
-					type = "passive";
-					monitor-falling;
-				};
-
 				cpu3_crit: cpu_crit {
 					temperature = <110000>;
 					hysteresis = <2000>;
 					type = "critical";
 				};
 			};
-
-			cooling-maps {
-				map0 {
-					trip = <&cpu3_alert0>;
-					cooling-device = <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
-
-				map1 {
-					trip = <&cpu3_warm>;
-					cooling-device = <&CPU0_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU1_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU2_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU3_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_cx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_mx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
-			};
 		};
 
 		gpu-thermal-top {
@@ -3762,13 +3448,6 @@ gpu1_alert0: trip-point0 {
 					hysteresis = <2000>;
 					type = "passive";
 				};
-
-				gpu1_warm: trip-warm {
-					temperature = <15000>;
-					hysteresis = <2000>;
-					type = "passive";
-					monitor-falling;
-				};
 			};
 
 			cooling-maps {
@@ -3776,17 +3455,6 @@ map0 {
 					trip = <&gpu1_alert0>;
 					cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
 				};
-
-				map1 {
-					trip = <&gpu1_warm>;
-					cooling-device = <&CPU0_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU1_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU2_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU3_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&gpu_warm THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_cx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_mx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
 			};
 		};
 
@@ -3802,13 +3470,6 @@ gpu2_alert0: trip-point0 {
 					hysteresis = <2000>;
 					type = "passive";
 				};
-
-				gpu2_warm: trip-warm {
-					temperature = <15000>;
-					hysteresis = <2000>;
-					type = "passive";
-					monitor-falling;
-				};
 			};
 
 			cooling-maps {
@@ -3816,17 +3477,6 @@ map0 {
 					trip = <&gpu2_alert0>;
 					cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
 				};
-
-				map1 {
-					trip = <&gpu2_warm>;
-					cooling-device = <&CPU0_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU1_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU2_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&CPU3_WARM THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&gpu_warm THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_cx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
-							 <&pd_mx_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-				};
 			};
 		};
 
diff --git a/kernel/arch/arm64/configs/db820c_defconfig b/kernel/arch/arm64/configs/db820c_defconfig
index bc9fb4ec97d0..b3791de5fe6a 100644
--- a/kernel/arch/arm64/configs/db820c_defconfig
+++ b/kernel/arch/arm64/configs/db820c_defconfig
@@ -447,7 +447,6 @@ CONFIG_THERMAL_EMULATION=y
 CONFIG_QCOM_TSENS=y
 CONFIG_QCOM_SPMI_ADC_TM5=y
 CONFIG_QCOM_SPMI_TEMP_ALARM=y
-CONFIG_PD_COOLING=y
 CONFIG_WATCHDOG=y
 CONFIG_ARM_SP805_WATCHDOG=y
 CONFIG_ARM_SBSA_WATCHDOG=y
@@ -779,7 +778,6 @@ CONFIG_FSL_RCPM=y
 CONFIG_QCOM_AOSS_QMP=y
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_QCOM_CPR=y
-CONFIG_QCOM_CPR3_GFX=y
 CONFIG_QCOM_GENI_SE=y
 CONFIG_QCOM_RMTFS_MEM=y
 CONFIG_QCOM_RPMH=y
diff --git a/kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 1264f4eff6e8..02a1c94a9ab2 100644
--- a/kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1081,9 +1081,6 @@ static void a5xx_destroy(struct msm_gpu *gpu)
 #endif
 	adreno_gpu_cleanup(adreno_gpu);
 
-	if (a5xx_gpu->mx_link)
-		device_link_del(a5xx_gpu->mx_link);
-
 	if (a5xx_gpu->gxpd)
 		dev_pm_domain_detach(a5xx_gpu->gxpd, true);
 
@@ -1838,7 +1835,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
 	 * If the device has several power domain (gx and cpr3), none are attached by the core.
 	 */
 	if (!pdev->dev.pm_domain) {
-		struct device **opp_virt_dev;
 		struct device *pd;
 		static const char *cpr_genpd_names[] = { "cpr", "mx", NULL };
 
@@ -1853,18 +1849,11 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
 
 		a5xx_gpu->gxpd = pd;
 
-		ret = devm_pm_opp_attach_genpd(&pdev->dev, cpr_genpd_names, &opp_virt_dev);
+		ret = devm_pm_opp_attach_genpd(&pdev->dev, cpr_genpd_names, NULL);
 		if (ret) {
 			dev_pm_domain_detach(a5xx_gpu->gxpd, true);
 			return ERR_PTR(ret);
 		}
-
-		a5xx_gpu->mx_link = device_link_add(&pdev->dev, opp_virt_dev[1],
-						    DL_FLAG_RPM_ACTIVE |
-						    DL_FLAG_PM_RUNTIME |
-						    DL_FLAG_STATELESS);
-		if (!a5xx_gpu->mx_link)
-			return ERR_PTR(-ENODEV);
 	}
 
 	check_speed_bin(&pdev->dev);
diff --git a/kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
index 36e910397c14..f3fd8826d1ee 100644
--- a/kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
+++ b/kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
@@ -46,7 +46,8 @@ struct a5xx_gpu {
 	bool has_whereami;
 
 	struct device *gxpd;
-	struct device_link *mx_link;
+	struct device *mxpd;
+	struct device *cprpd;
 };
 
 #define to_a5xx_gpu(x) container_of(x, struct a5xx_gpu, base)
diff --git a/kernel/drivers/soc/qcom/Kconfig b/kernel/drivers/soc/qcom/Kconfig
index 45fd3389e855..fe3c486ae32d 100644
--- a/kernel/drivers/soc/qcom/Kconfig
+++ b/kernel/drivers/soc/qcom/Kconfig
@@ -26,15 +26,11 @@ config QCOM_COMMAND_DB
 	  resource on a RPM-hardened platform must use this database to get
 	  SoC specific identifier and information for the shared resources.
 
-config QCOM_CPR_COMMON
-	tristate
-
 config QCOM_CPR
 	tristate "QCOM Core Power Reduction (CPR) support"
 	depends on ARCH_QCOM && HAS_IOMEM
 	select PM_OPP
 	select REGMAP
-	select QCOM_CPR_COMMON
 	help
 	  Say Y here to enable support for the CPR hardware found on Qualcomm
 	  SoCs like QCS404.
@@ -46,42 +42,6 @@ config QCOM_CPR
 	  To compile this driver as a module, choose M here: the module will
 	  be called qcom-cpr
 
-config QCOM_CPR3
-	tristate "QCOM Core Power Reduction (CPR v3/v4/Hardened) support"
-	depends on ARCH_QCOM && HAS_IOMEM
-	select PM_OPP
-	select REGMAP
-	select QCOM_CPR_COMMON
-	help
-	  Say Y here to enable support for the CPR hardware found on a broad
-	  variety of Qualcomm SoCs like MSM8996, MSM8998, SDM630, SDM660,
-	  SDM845 and others.
-
-	  This driver populates OPP tables and makes adjustments to them
-	  based on feedback from the CPR hardware. If you want to do CPU
-	  frequency scaling say Y here.
-
-	  To compile this driver as a module, choose M here: the module will
-	  be called qcom-cpr3
-
-config QCOM_CPR3_GFX
-	tristate "QCOM Core Power Reduction for GPU support"
-	depends on ARCH_QCOM && HAS_IOMEM
-	select PM_OPP
-	select REGMAP
-	select QCOM_CPR_COMMON
-	help
-	  Say Y here to enable support for the CPR hardware used to control GPU
-	  supplies as found on a broad variety of Qualcomm SoCs like MSM8996,
-	  MSM8998, SDM630, SDM660, SDM845 and others.
-
-	  This driver populates OPP tables and makes adjustments to them
-	  based on feedback from the CPR hardware. If you want to do GPU
-	  frequency scaling say Y here.
-
-	  To compile this driver as a module, choose M here: the module will
-	  be called qcom-cpr3-gfx
-
 config QCOM_GENI_SE
 	tristate "QCOM GENI Serial Engine Driver"
 	depends on ARCH_QCOM || COMPILE_TEST
diff --git a/kernel/drivers/soc/qcom/Makefile b/kernel/drivers/soc/qcom/Makefile
index 83657d7b5b61..24514c722832 100644
--- a/kernel/drivers/soc/qcom/Makefile
+++ b/kernel/drivers/soc/qcom/Makefile
@@ -3,10 +3,7 @@ CFLAGS_rpmh-rsc.o := -I$(src)
 obj-$(CONFIG_QCOM_AOSS_QMP) +=	qcom_aoss.o
 obj-$(CONFIG_QCOM_GENI_SE) +=	qcom-geni-se.o
 obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
-obj-$(CONFIG_QCOM_CPR_COMMON)	+= cpr-common.o
 obj-$(CONFIG_QCOM_CPR)		+= cpr.o
-obj-$(CONFIG_QCOM_CPR3)		+= cpr3.o
-obj-$(CONFIG_QCOM_CPR3_GFX)	+= cpr3-gfx.o
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
 obj-$(CONFIG_QCOM_MDT_LOADER)	+= mdt_loader.o
 obj-$(CONFIG_QCOM_OCMEM)	+= ocmem.o
diff --git a/kernel/drivers/soc/qcom/cpr-common.c b/kernel/drivers/soc/qcom/cpr-common.c
deleted file mode 100644
index 95ab34dbe13f..000000000000
--- a/kernel/drivers/soc/qcom/cpr-common.c
+++ /dev/null
@@ -1,368 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
- * Copyright (c) 2019, Linaro Limited
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/debugfs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_opp.h>
-#include <linux/interrupt.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regulator/consumer.h>
-#include <linux/clk.h>
-#include <linux/nvmem-consumer.h>
-#include "cpr-common.h"
-
-int cpr_populate_ring_osc_idx(struct device *dev,
-			      struct fuse_corner *fuse_corner,
-			      const struct cpr_fuse *cpr_fuse,
-			      int num_fuse_corners)
-{
-	struct fuse_corner *end = fuse_corner + num_fuse_corners;
-	u32 data;
-	int ret;
-
-	for (; fuse_corner < end; fuse_corner++, cpr_fuse++) {
-		ret = nvmem_cell_read_variable_le_u32(dev, cpr_fuse->ring_osc, &data);
-		if (ret)
-			return ret;
-		fuse_corner->ring_osc_idx = data;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpr_populate_ring_osc_idx);
-
-int cpr_read_fuse_uV(int init_v_width, int step_size_uV, int ref_uV,
-		     int adj, int step_volt, const char *init_v_efuse,
-		     struct device *dev)
-{
-	int steps, uV;
-	u32 bits = 0;
-	int ret;
-
-	ret = nvmem_cell_read_variable_le_u32(dev, init_v_efuse, &bits);
-	if (ret)
-		return ret;
-
-	steps = bits & (BIT(init_v_width - 1) - 1);
-	/* Not two's complement.. instead highest bit is sign bit */
-	if (bits & BIT(init_v_width - 1))
-		steps = -steps;
-
-	uV = ref_uV + steps * step_size_uV;
-
-	/* Apply open-loop fixed adjustments to fused values */
-	uV += adj;
-
-	return DIV_ROUND_UP(uV, step_volt) * step_volt;
-}
-EXPORT_SYMBOL_GPL(cpr_read_fuse_uV);
-
-const struct cpr_fuse *cpr_get_fuses(struct device *dev, int tid,
-				     int num_fuse_corners)
-{
-	struct cpr_fuse *fuses;
-	int i;
-
-	fuses = devm_kcalloc(dev, num_fuse_corners,
-			     sizeof(struct cpr_fuse),
-			     GFP_KERNEL);
-	if (!fuses)
-		return ERR_PTR(-ENOMEM);
-
-	for (i = 0; i < num_fuse_corners; i++) {
-		char tbuf[50];
-
-		snprintf(tbuf, sizeof(tbuf), "cpr%d_ring_osc%d", tid, i + 1);
-		fuses[i].ring_osc = devm_kstrdup(dev, tbuf, GFP_KERNEL);
-		if (!fuses[i].ring_osc)
-			return ERR_PTR(-ENOMEM);
-
-		snprintf(tbuf, sizeof(tbuf),
-			 "cpr%d_init_voltage%d", tid, i + 1);
-		fuses[i].init_voltage = devm_kstrdup(dev, tbuf,
-						     GFP_KERNEL);
-		if (!fuses[i].init_voltage)
-			return ERR_PTR(-ENOMEM);
-
-		snprintf(tbuf, sizeof(tbuf), "cpr%d_quotient%d", tid, i + 1);
-		fuses[i].quotient = devm_kstrdup(dev, tbuf, GFP_KERNEL);
-		if (!fuses[i].quotient)
-			return ERR_PTR(-ENOMEM);
-
-		snprintf(tbuf, sizeof(tbuf),
-			 "cpr%d_quotient_offset%d", tid, i + 1);
-		fuses[i].quotient_offset = devm_kstrdup(dev, tbuf,
-							GFP_KERNEL);
-		if (!fuses[i].quotient_offset)
-			return ERR_PTR(-ENOMEM);
-	}
-
-	return fuses;
-}
-EXPORT_SYMBOL_GPL(cpr_get_fuses);
-
-int cpr_read_fuse_common(struct device *dev,
-			 struct fuse_corner_data *fdata,
-			 const struct cpr_fuse *cpr_fuse,
-			 struct fuse_corner *fuse_corner,
-			 int step_volt, int init_v_width,
-			 int init_v_step)
-{
-	int uV;
-
-	/* Populate uV */
-	uV = cpr_read_fuse_uV(init_v_width, init_v_step,
-			      fdata->ref_uV, fdata->volt_oloop_adjust,
-			      step_volt, cpr_fuse->init_voltage, dev);
-	if (uV < 0)
-		return uV;
-
-	/*
-	 * Update SoC voltages: platforms might choose a different
-	 * regulators than the one used to characterize the algorithms
-	 * (ie, init_voltage_step).
-	 */
-	fdata->min_uV = roundup(fdata->min_uV, step_volt);
-	fdata->max_uV = roundup(fdata->max_uV, step_volt);
-
-	fuse_corner->min_uV = fdata->min_uV;
-	fuse_corner->max_uV = fdata->max_uV;
-	fuse_corner->uV = clamp(uV, fuse_corner->min_uV, fuse_corner->max_uV);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpr_read_fuse_common);
-
-int cpr_populate_fuse_common(struct device *dev,
-			     struct fuse_corner_data *fdata,
-			     const struct cpr_fuse *cpr_fuse,
-			     struct fuse_corner *fuse_corner,
-			     int step_volt, int init_v_width,
-			     int init_v_step)
-{
-	int ret;
-
-	ret = cpr_read_fuse_common(dev, fdata, cpr_fuse, fuse_corner,
-				   step_volt, init_v_width, init_v_step);
-	if (ret < 0)
-		return ret;
-
-	/* Populate target quotient by scaling */
-	ret = nvmem_cell_read_variable_le_u32(dev, cpr_fuse->quotient, &fuse_corner->quot);
-	if (ret)
-		return ret;
-
-	fuse_corner->quot *= fdata->quot_scale;
-	fuse_corner->quot += fdata->quot_offset;
-	fuse_corner->quot += fdata->quot_adjust;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpr_populate_fuse_common);
-
-u32 cpr_get_fuse_corner(struct dev_pm_opp *opp, u32 tid)
-{
-	struct device_node *np;
-	u32 fc;
-
-	np = dev_pm_opp_get_of_node(opp);
-	if (of_property_read_u32_index(np, "qcom,opp-fuse-level", tid, &fc)) {
-		pr_debug("%s: missing 'qcom,opp-fuse-level' property\n",
-			 __func__);
-		fc = 0;
-	}
-
-	of_node_put(np);
-
-	return fc;
-}
-EXPORT_SYMBOL_GPL(cpr_get_fuse_corner);
-
-void cpr_get_corner_post_vadj(struct dev_pm_opp *opp, u32 tid,
-			      s32 *open_loop, s32 *closed_loop)
-{
-	struct device_node *np;
-
-	/*
-	 * There is no of_property_read_s32_index, so we just store the
-	 * result into a s32 variable. After all, the OF API is doing
-	 * the exact same for of_property_read_s32...
-	 */
-	np = dev_pm_opp_get_of_node(opp);
-	if (of_property_read_u32_index(np, "qcom,opp-oloop-vadj", tid,
-				       open_loop))
-		*open_loop = 0;
-
-	if (of_property_read_u32_index(np, "qcom,opp-cloop-vadj", tid,
-				       closed_loop))
-		*closed_loop = 0;
-
-	of_node_put(np);
-}
-EXPORT_SYMBOL_GPL(cpr_get_corner_post_vadj);
-
-unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
-				     struct device *cpu_dev)
-{
-	u64 rate = 0;
-	struct device_node *ref_np;
-	struct device_node *desc_np;
-	struct device_node *child_np = NULL;
-	struct device_node *child_req_np = NULL;
-
-	desc_np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
-	if (!desc_np)
-		return 0;
-
-	ref_np = dev_pm_opp_get_of_node(ref);
-	if (!ref_np)
-		goto out_ref;
-
-	do {
-		of_node_put(child_req_np);
-		child_np = of_get_next_available_child(desc_np, child_np);
-		child_req_np = of_parse_phandle(child_np, "required-opps", 0);
-	} while (child_np && child_req_np != ref_np);
-
-	if (child_np && child_req_np == ref_np)
-		of_property_read_u64(child_np, "opp-hz", &rate);
-
-	of_node_put(child_req_np);
-	of_node_put(child_np);
-	of_node_put(ref_np);
-out_ref:
-	of_node_put(desc_np);
-
-	return (unsigned long) rate;
-}
-EXPORT_SYMBOL_GPL(cpr_get_opp_hz_for_req);
-
-int cpr_calculate_scaling_raw(u32 quot_diff,
-			      struct device *dev,
-			      const struct fuse_corner_data *fdata,
-			      const struct corner *corner)
-{
-	u64 freq_diff;
-	const struct fuse_corner *fuse, *prev_fuse;
-	int scaling;
-
-	fuse = corner->fuse_corner;
-	prev_fuse = fuse - 1;
-
-	freq_diff = fuse->max_freq - prev_fuse->max_freq;
-	freq_diff = div_u64(freq_diff, 1000000); /* Convert to MHz */
-	scaling = 1000 * quot_diff;
-	do_div(scaling, freq_diff);
-
-	return scaling;
-}
-EXPORT_SYMBOL_GPL(cpr_calculate_scaling_raw);
-
-int cpr_calculate_scaling(const char *quot_offset,
-			  struct device *dev,
-			  const struct fuse_corner_data *fdata,
-			  const struct corner *corner)
-{
-	const struct fuse_corner *fuse, *prev_fuse;
-	u32 quot_diff;
-	int ret;
-
-	fuse = corner->fuse_corner;
-	prev_fuse = fuse - 1;
-
-	if (quot_offset) {
-		ret = nvmem_cell_read_variable_le_u32(dev, quot_offset, &quot_diff);
-		if (ret)
-			return ret;
-
-		quot_diff *= fdata->quot_offset_scale;
-		quot_diff += fdata->quot_offset_adjust;
-	} else {
-		quot_diff = fuse->quot - prev_fuse->quot;
-	}
-
-	return cpr_calculate_scaling_raw(quot_diff, dev, fdata, corner);
-}
-EXPORT_SYMBOL_GPL(cpr_calculate_scaling);
-
-int cpr_interpolate(const struct corner *corner, int step_volt,
-		    const struct fuse_corner_data *fdata)
-{
-	unsigned long f_high, f_low, f_diff;
-	int uV_high, uV_low, uV;
-	u64 temp, temp_limit;
-	const struct fuse_corner *fuse, *prev_fuse;
-
-	fuse = corner->fuse_corner;
-	prev_fuse = fuse - 1;
-
-	f_high = fuse->max_freq;
-	f_low = prev_fuse->max_freq;
-	uV_high = fuse->uV;
-	uV_low = prev_fuse->uV;
-	f_diff = fuse->max_freq - corner->freq;
-
-	/*
-	 * Don't interpolate in the wrong direction. This could happen
-	 * if the adjusted fuse voltage overlaps with the previous fuse's
-	 * adjusted voltage.
-	 */
-	if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq)
-		return corner->uV;
-
-	temp = f_diff * (uV_high - uV_low);
-	temp = div64_ul(temp, f_high - f_low);
-
-	/*
-	 * max_volt_scale has units of uV/MHz while freq values
-	 * have units of Hz.  Divide by 1000000 to convert to.
-	 */
-	temp_limit = f_diff * fdata->max_volt_scale;
-	do_div(temp_limit, 1000000);
-
-	uV = uV_high - min(temp, temp_limit);
-	return roundup(uV, step_volt);
-}
-EXPORT_SYMBOL_GPL(cpr_interpolate);
-
-int cpr_check_vreg_constraints(struct device *dev, struct regulator *vreg,
-			       struct fuse_corner *f)
-{
-	int ret;
-
-	ret = regulator_is_supported_voltage(vreg, f->min_uV, f->min_uV);
-	if (!ret) {
-		dev_err(dev, "min uV: %d not supported by regulator\n",
-			f->min_uV);
-		return -EINVAL;
-	}
-
-	ret = regulator_is_supported_voltage(vreg, f->max_uV, f->max_uV);
-	if (!ret) {
-		dev_err(dev, "max uV: %d not supported by regulator\n",
-			f->max_uV);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpr_check_vreg_constraints);
-
-MODULE_DESCRIPTION("Core Power Reduction (CPR) common");
-MODULE_LICENSE("GPL v2");
diff --git a/kernel/drivers/soc/qcom/cpr-common.h b/kernel/drivers/soc/qcom/cpr-common.h
deleted file mode 100644
index 4c7223b26ed7..000000000000
--- a/kernel/drivers/soc/qcom/cpr-common.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/pm_opp.h>
-#include <linux/regulator/consumer.h>
-
-enum voltage_change_dir {
-	NO_CHANGE,
-	DOWN,
-	UP,
-};
-
-struct fuse_corner_data {
-	int ref_uV;
-	int max_uV;
-	int min_uV;
-	int range_uV;
-	/* fuse volt: closed/open loop */
-	int volt_cloop_adjust;
-	int volt_oloop_adjust;
-	int max_volt_scale;
-	int max_quot_scale;
-	/* fuse quot */
-	int quot_offset;
-	int quot_scale;
-	int quot_adjust;
-	/* fuse quot_offset */
-	int quot_offset_scale;
-	int quot_offset_adjust;
-};
-
-struct cpr_fuse {
-	char *ring_osc;
-	char *init_voltage;
-	char *quotient;
-	char *quotient_offset;
-};
-
-struct fuse_corner {
-	int min_uV;
-	int max_uV;
-	int uV;
-	int quot;
-	int step_quot;
-	const struct reg_sequence *accs;
-	int num_accs;
-	unsigned long max_freq;
-	u8 ring_osc_idx;
-};
-
-struct corner {
-	int min_uV;
-	int max_uV;
-	int uV;
-	unsigned long freq;
-	struct fuse_corner *fuse_corner;
-};
-
-struct corner_data {
-	unsigned int fuse_corner;
-	unsigned long freq;
-	int oloop_vadj;
-	int cloop_vadj;
-};
-
-struct acc_desc {
-	unsigned int	enable_reg;
-	u32		enable_mask;
-
-	struct reg_sequence	*config;
-	struct reg_sequence	*settings;
-	int			num_regs_per_fuse;
-};
-
-struct cpr_acc_desc {
-	const struct cpr_desc *cpr_desc;
-	const struct acc_desc *acc_desc;
-};
-
-int cpr_populate_ring_osc_idx(struct device *dev,
-			      struct fuse_corner *fuse_corner,
-			      const struct cpr_fuse *cpr_fuse,
-			      int num_fuse_corners);
-int cpr_read_fuse_uV(int init_v_width, int step_size_uV, int ref_uV,
-		     int adj, int step_volt, const char *init_v_efuse,
-		     struct device *dev);
-const struct cpr_fuse *cpr_get_fuses(struct device *dev, int tid,
-				     int num_fuse_corners);
-int cpr_read_fuse_common(struct device *dev,
-			 struct fuse_corner_data *fdata,
-			 const struct cpr_fuse *cpr_fuse,
-			 struct fuse_corner *fuse_corner,
-			 int step_volt, int init_v_width,
-			 int init_v_step);
-int cpr_populate_fuse_common(struct device *dev,
-			     struct fuse_corner_data *fdata,
-			     const struct cpr_fuse *cpr_fuse,
-			     struct fuse_corner *fuse_corner,
-			     int step_volt, int init_v_width,
-			     int init_v_step);
-u32 cpr_get_fuse_corner(struct dev_pm_opp *opp, u32 tid);
-void cpr_get_corner_post_vadj(struct dev_pm_opp *opp, u32 tid,
-			      s32 *open_loop, s32 *closed_loop);
-unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
-				     struct device *cpu_dev);
-int cpr_calculate_scaling_raw(u32 quot_diff,
-			      struct device *dev,
-			      const struct fuse_corner_data *fdata,
-			      const struct corner *corner);
-int cpr_calculate_scaling(const char *quot_offset,
-			  struct device *dev,
-			  const struct fuse_corner_data *fdata,
-			  const struct corner *corner);
-int cpr_interpolate(const struct corner *corner, int step_volt,
-		    const struct fuse_corner_data *fdata);
-int cpr_check_vreg_constraints(struct device *dev, struct regulator *vreg,
-			       struct fuse_corner *f);
diff --git a/kernel/drivers/soc/qcom/cpr.c b/kernel/drivers/soc/qcom/cpr.c
index 32019be002d9..84dd93472a25 100644
--- a/kernel/drivers/soc/qcom/cpr.c
+++ b/kernel/drivers/soc/qcom/cpr.c
@@ -25,7 +25,6 @@
 #include <linux/regulator/consumer.h>
 #include <linux/clk.h>
 #include <linux/nvmem-consumer.h>
-#include "cpr-common.h"
 
 /* Register Offsets for RB-CPR and Bit Definitions */
 
@@ -125,13 +124,32 @@
 
 #define FUSE_REVISION_UNKNOWN		(-1)
 
-struct cpr_corner {
-	struct corner corner;
-	int last_uV;
+enum voltage_change_dir {
+	NO_CHANGE,
+	DOWN,
+	UP,
+};
+
+struct cpr_fuse {
+	char *ring_osc;
+	char *init_voltage;
+	char *quotient;
+	char *quotient_offset;
+};
+
+struct fuse_corner_data {
+	int ref_uV;
+	int max_uV;
+	int min_uV;
+	int max_volt_scale;
+	int max_quot_scale;
+	/* fuse quot */
+	int quot_offset;
+	int quot_scale;
 	int quot_adjust;
-	u32 save_ctl;
-	u32 save_irq;
-	bool is_open_loop;
+	/* fuse quot_offset */
+	int quot_offset_scale;
+	int quot_offset_adjust;
 };
 
 struct cpr_fuses {
@@ -140,6 +158,11 @@ struct cpr_fuses {
 	struct fuse_corner_data *fuse_corner_data;
 };
 
+struct corner_data {
+	unsigned int fuse_corner;
+	unsigned long freq;
+};
+
 struct cpr_desc {
 	unsigned int num_fuse_corners;
 	int min_diff_quot;
@@ -161,6 +184,44 @@ struct cpr_desc {
 	bool reduce_to_corner_uV;
 };
 
+struct acc_desc {
+	unsigned int	enable_reg;
+	u32		enable_mask;
+
+	struct reg_sequence	*config;
+	struct reg_sequence	*settings;
+	int			num_regs_per_fuse;
+};
+
+struct cpr_acc_desc {
+	const struct cpr_desc *cpr_desc;
+	const struct acc_desc *acc_desc;
+};
+
+struct fuse_corner {
+	int min_uV;
+	int max_uV;
+	int uV;
+	int quot;
+	int step_quot;
+	const struct reg_sequence *accs;
+	int num_accs;
+	unsigned long max_freq;
+	u8 ring_osc_idx;
+};
+
+struct corner {
+	int min_uV;
+	int max_uV;
+	int uV;
+	int last_uV;
+	int quot_adjust;
+	u32 save_ctl;
+	u32 save_irq;
+	unsigned long freq;
+	struct fuse_corner *fuse_corner;
+};
+
 struct cpr_drv {
 	unsigned int		num_corners;
 	unsigned int		ref_clk_khz;
@@ -170,7 +231,7 @@ struct cpr_drv {
 	struct device		*attached_cpu_dev;
 	struct mutex		lock;
 	void __iomem		*base;
-	struct cpr_corner		*corner;
+	struct corner		*corner;
 	struct regulator	*vdd_apc;
 	struct clk		*cpu_clk;
 	struct regmap		*tcsr;
@@ -179,7 +240,7 @@ struct cpr_drv {
 	unsigned long		flags;
 
 	struct fuse_corner	*fuse_corners;
-	struct cpr_corner		*corners;
+	struct corner		*corners;
 
 	const struct cpr_desc *desc;
 	const struct acc_desc *acc_desc;
@@ -241,7 +302,7 @@ static void cpr_ctl_modify(struct cpr_drv *drv, u32 mask, u32 value)
 	cpr_masked_write(drv, REG_RBCPR_CTL, mask, value);
 }
 
-static void cpr_ctl_enable(struct cpr_drv *drv, struct cpr_corner *corner)
+static void cpr_ctl_enable(struct cpr_drv *drv, struct corner *corner)
 {
 	u32 val, mask;
 	const struct cpr_desc *desc = drv->desc;
@@ -257,7 +318,7 @@ static void cpr_ctl_enable(struct cpr_drv *drv, struct cpr_corner *corner)
 			 corner->save_ctl);
 	cpr_irq_set(drv, corner->save_irq);
 
-	if (cpr_is_allowed(drv) && corner->corner.max_uV > corner->corner.min_uV)
+	if (cpr_is_allowed(drv) && corner->max_uV > corner->min_uV)
 		val = RBCPR_CTL_LOOP_EN;
 	else
 		val = 0;
@@ -294,16 +355,16 @@ static bool cpr_ctl_is_busy(struct cpr_drv *drv)
 	return reg_val & RBCPR_RESULT0_BUSY_MASK;
 }
 
-static void cpr_corner_save(struct cpr_drv *drv, struct cpr_corner *corner)
+static void cpr_corner_save(struct cpr_drv *drv, struct corner *corner)
 {
 	corner->save_ctl = cpr_read(drv, REG_RBCPR_CTL);
 	corner->save_irq = cpr_read(drv, REG_RBIF_IRQ_EN(0));
 }
 
-static void cpr_corner_restore(struct cpr_drv *drv, struct cpr_corner *corner)
+static void cpr_corner_restore(struct cpr_drv *drv, struct corner *corner)
 {
 	u32 gcnt, ctl, irq, ro_sel, step_quot;
-	struct fuse_corner *fuse = corner->corner.fuse_corner;
+	struct fuse_corner *fuse = corner->fuse_corner;
 	const struct cpr_desc *desc = drv->desc;
 	int i;
 
@@ -348,7 +409,7 @@ static int cpr_pre_voltage(struct cpr_drv *drv,
 			   struct fuse_corner *fuse_corner,
 			   enum voltage_change_dir dir)
 {
-	struct fuse_corner *prev_fuse_corner = drv->corner->corner.fuse_corner;
+	struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner;
 
 	if (drv->tcsr && dir == DOWN)
 		cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner);
@@ -360,7 +421,7 @@ static int cpr_post_voltage(struct cpr_drv *drv,
 			    struct fuse_corner *fuse_corner,
 			    enum voltage_change_dir dir)
 {
-	struct fuse_corner *prev_fuse_corner = drv->corner->corner.fuse_corner;
+	struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner;
 
 	if (drv->tcsr && dir == UP)
 		cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner);
@@ -368,11 +429,11 @@ static int cpr_post_voltage(struct cpr_drv *drv,
 	return 0;
 }
 
-static int cpr_scale_voltage(struct cpr_drv *drv, struct cpr_corner *corner,
+static int cpr_scale_voltage(struct cpr_drv *drv, struct corner *corner,
 			     int new_uV, enum voltage_change_dir dir)
 {
 	int ret;
-	struct fuse_corner *fuse_corner = corner->corner.fuse_corner;
+	struct fuse_corner *fuse_corner = corner->fuse_corner;
 
 	ret = cpr_pre_voltage(drv, fuse_corner, dir);
 	if (ret)
@@ -401,7 +462,7 @@ static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir)
 {
 	u32 val, error_steps, reg_mask;
 	int last_uV, new_uV, step_uV, ret;
-	struct cpr_corner *corner;
+	struct corner *corner;
 	const struct cpr_desc *desc = drv->desc;
 
 	if (dir != UP && dir != DOWN)
@@ -431,7 +492,7 @@ static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir)
 					  desc->vdd_apc_step_up_limit);
 		}
 
-		if (last_uV >= corner->corner.max_uV) {
+		if (last_uV >= corner->max_uV) {
 			cpr_irq_clr_nack(drv);
 
 			/* Maximize the UP threshold */
@@ -451,7 +512,7 @@ static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir)
 
 		/* Calculate new voltage */
 		new_uV = last_uV + error_steps * step_uV;
-		new_uV = min(new_uV, corner->corner.max_uV);
+		new_uV = min(new_uV, corner->max_uV);
 
 		dev_dbg(drv->dev,
 			"UP: -> new_uV: %d last_uV: %d perf state: %u\n",
@@ -468,7 +529,7 @@ static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir)
 					  desc->vdd_apc_step_down_limit);
 		}
 
-		if (last_uV <= corner->corner.min_uV) {
+		if (last_uV <= corner->min_uV) {
 			cpr_irq_clr_nack(drv);
 
 			/* Enable auto nack down */
@@ -488,7 +549,7 @@ static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir)
 
 		/* Calculate new voltage */
 		new_uV = last_uV - error_steps * step_uV;
-		new_uV = max(new_uV, corner->corner.min_uV);
+		new_uV = max(new_uV, corner->min_uV);
 
 		dev_dbg(drv->dev,
 			"DOWN: -> new_uV: %d last_uV: %d perf state: %u\n",
@@ -620,7 +681,7 @@ static int cpr_config(struct cpr_drv *drv)
 {
 	int i;
 	u32 val, gcnt;
-	struct cpr_corner *corner;
+	struct corner *corner;
 	const struct cpr_desc *desc = drv->desc;
 
 	/* Disable interrupt and CPR */
@@ -685,7 +746,7 @@ static int cpr_set_performance_state(struct generic_pm_domain *domain,
 				     unsigned int state)
 {
 	struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
-	struct cpr_corner *corner, *end;
+	struct corner *corner, *end;
 	enum voltage_change_dir dir;
 	int ret = 0, new_uV;
 
@@ -716,7 +777,7 @@ static int cpr_set_performance_state(struct generic_pm_domain *domain,
 	if (cpr_is_allowed(drv))
 		new_uV = corner->last_uV;
 	else
-		new_uV = corner->corner.uV;
+		new_uV = corner->uV;
 
 	if (cpr_is_allowed(drv))
 		cpr_ctl_disable(drv);
@@ -740,6 +801,50 @@ static int cpr_set_performance_state(struct generic_pm_domain *domain,
 	return ret;
 }
 
+static int
+cpr_populate_ring_osc_idx(struct cpr_drv *drv)
+{
+	struct fuse_corner *fuse = drv->fuse_corners;
+	struct fuse_corner *end = fuse + drv->desc->num_fuse_corners;
+	const struct cpr_fuse *fuses = drv->cpr_fuses;
+	u32 data;
+	int ret;
+
+	for (; fuse < end; fuse++, fuses++) {
+		ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data);
+		if (ret)
+			return ret;
+		fuse->ring_osc_idx = data;
+	}
+
+	return 0;
+}
+
+static int cpr_read_fuse_uV(const struct cpr_desc *desc,
+			    const struct fuse_corner_data *fdata,
+			    const char *init_v_efuse,
+			    int step_volt,
+			    struct cpr_drv *drv)
+{
+	int step_size_uV, steps, uV;
+	u32 bits = 0;
+	int ret;
+
+	ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits);
+	if (ret)
+		return ret;
+
+	steps = bits & ~BIT(desc->cpr_fuses.init_voltage_width - 1);
+	/* Not two's complement.. instead highest bit is sign bit */
+	if (bits & BIT(desc->cpr_fuses.init_voltage_width - 1))
+		steps = -steps;
+
+	step_size_uV = desc->cpr_fuses.init_voltage_step;
+
+	uV = fdata->ref_uV + steps * step_size_uV;
+	return DIV_ROUND_UP(uV, step_volt) * step_volt;
+}
+
 static int cpr_fuse_corner_init(struct cpr_drv *drv)
 {
 	const struct cpr_desc *desc = drv->desc;
@@ -749,6 +854,7 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
 	unsigned int step_volt;
 	struct fuse_corner_data *fdata;
 	struct fuse_corner *fuse, *end;
+	int uV;
 	const struct reg_sequence *accs;
 	int ret;
 
@@ -764,15 +870,23 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
 	fdata = desc->cpr_fuses.fuse_corner_data;
 
 	for (i = 0; fuse <= end; fuse++, fuses++, i++, fdata++) {
-		ret = cpr_populate_fuse_common(
-					drv->dev, fdata, fuses,
-					fuse, step_volt,
-					desc->cpr_fuses.init_voltage_width,
-					desc->cpr_fuses.init_voltage_step);
-		if (ret)
-			return ret;
+		/*
+		 * Update SoC voltages: platforms might choose a different
+		 * regulators than the one used to characterize the algorithms
+		 * (ie, init_voltage_step).
+		 */
+		fdata->min_uV = roundup(fdata->min_uV, step_volt);
+		fdata->max_uV = roundup(fdata->max_uV, step_volt);
 
-		fuse->step_quot = desc->step_quot[fuse->ring_osc_idx];
+		/* Populate uV */
+		uV = cpr_read_fuse_uV(desc, fdata, fuses->init_voltage,
+				      step_volt, drv);
+		if (uV < 0)
+			return uV;
+
+		fuse->min_uV = fdata->min_uV;
+		fuse->max_uV = fdata->max_uV;
+		fuse->uV = clamp(uV, fuse->min_uV, fuse->max_uV);
 
 		if (fuse == end) {
 			/*
@@ -784,6 +898,16 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
 			end->max_uV = max(end->max_uV, end->uV);
 		}
 
+		/* Populate target quotient by scaling */
+		ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot);
+		if (ret)
+			return ret;
+
+		fuse->quot *= fdata->quot_scale;
+		fuse->quot += fdata->quot_offset;
+		fuse->quot += fdata->quot_adjust;
+		fuse->step_quot = desc->step_quot[fuse->ring_osc_idx];
+
 		/* Populate acc settings */
 		fuse->accs = accs;
 		fuse->num_accs = acc_desc->num_regs_per_fuse;
@@ -800,9 +924,25 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
 		else if (fuse->uV < fuse->min_uV)
 			fuse->uV = fuse->min_uV;
 
-		ret = cpr_check_vreg_constraints(drv->dev, drv->vdd_apc, fuse);
-		if (ret)
-			return ret;
+		ret = regulator_is_supported_voltage(drv->vdd_apc,
+						     fuse->min_uV,
+						     fuse->min_uV);
+		if (!ret) {
+			dev_err(drv->dev,
+				"min uV: %d (fuse corner: %d) not supported by regulator\n",
+				fuse->min_uV, i);
+			return -EINVAL;
+		}
+
+		ret = regulator_is_supported_voltage(drv->vdd_apc,
+						     fuse->max_uV,
+						     fuse->max_uV);
+		if (!ret) {
+			dev_err(drv->dev,
+				"max uV: %d (fuse corner: %d) not supported by regulator\n",
+				fuse->max_uV, i);
+			return -EINVAL;
+		}
 
 		dev_dbg(drv->dev,
 			"fuse corner %d: [%d %d %d] RO%hhu quot %d squot %d\n",
@@ -813,6 +953,126 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
 	return 0;
 }
 
+static int cpr_calculate_scaling(const char *quot_offset,
+				 struct cpr_drv *drv,
+				 const struct fuse_corner_data *fdata,
+				 const struct corner *corner)
+{
+	u32 quot_diff = 0;
+	unsigned long freq_diff;
+	int scaling;
+	const struct fuse_corner *fuse, *prev_fuse;
+	int ret;
+
+	fuse = corner->fuse_corner;
+	prev_fuse = fuse - 1;
+
+	if (quot_offset) {
+		ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, &quot_diff);
+		if (ret)
+			return ret;
+
+		quot_diff *= fdata->quot_offset_scale;
+		quot_diff += fdata->quot_offset_adjust;
+	} else {
+		quot_diff = fuse->quot - prev_fuse->quot;
+	}
+
+	freq_diff = fuse->max_freq - prev_fuse->max_freq;
+	freq_diff /= 1000000; /* Convert to MHz */
+	scaling = 1000 * quot_diff / freq_diff;
+	return min(scaling, fdata->max_quot_scale);
+}
+
+static int cpr_interpolate(const struct corner *corner, int step_volt,
+			   const struct fuse_corner_data *fdata)
+{
+	unsigned long f_high, f_low, f_diff;
+	int uV_high, uV_low, uV;
+	u64 temp, temp_limit;
+	const struct fuse_corner *fuse, *prev_fuse;
+
+	fuse = corner->fuse_corner;
+	prev_fuse = fuse - 1;
+
+	f_high = fuse->max_freq;
+	f_low = prev_fuse->max_freq;
+	uV_high = fuse->uV;
+	uV_low = prev_fuse->uV;
+	f_diff = fuse->max_freq - corner->freq;
+
+	/*
+	 * Don't interpolate in the wrong direction. This could happen
+	 * if the adjusted fuse voltage overlaps with the previous fuse's
+	 * adjusted voltage.
+	 */
+	if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq)
+		return corner->uV;
+
+	temp = f_diff * (uV_high - uV_low);
+	temp = div64_ul(temp, f_high - f_low);
+
+	/*
+	 * max_volt_scale has units of uV/MHz while freq values
+	 * have units of Hz.  Divide by 1000000 to convert to.
+	 */
+	temp_limit = f_diff * fdata->max_volt_scale;
+	do_div(temp_limit, 1000000);
+
+	uV = uV_high - min(temp, temp_limit);
+	return roundup(uV, step_volt);
+}
+
+static unsigned int cpr_get_fuse_corner(struct dev_pm_opp *opp)
+{
+	struct device_node *np;
+	unsigned int fuse_corner = 0;
+
+	np = dev_pm_opp_get_of_node(opp);
+	if (of_property_read_u32(np, "qcom,opp-fuse-level", &fuse_corner))
+		pr_err("%s: missing 'qcom,opp-fuse-level' property\n",
+		       __func__);
+
+	of_node_put(np);
+
+	return fuse_corner;
+}
+
+static unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
+					    struct device *cpu_dev)
+{
+	u64 rate = 0;
+	struct device_node *ref_np;
+	struct device_node *desc_np;
+	struct device_node *child_np = NULL;
+	struct device_node *child_req_np = NULL;
+
+	desc_np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
+	if (!desc_np)
+		return 0;
+
+	ref_np = dev_pm_opp_get_of_node(ref);
+	if (!ref_np)
+		goto out_ref;
+
+	do {
+		of_node_put(child_req_np);
+		child_np = of_get_next_available_child(desc_np, child_np);
+		child_req_np = of_parse_phandle(child_np, "required-opps", 0);
+	} while (child_np && child_req_np != ref_np);
+
+	if (child_np && child_req_np == ref_np)
+		of_property_read_u64(child_np, "opp-hz", &rate);
+
+	of_node_put(child_req_np);
+	of_node_put(child_np);
+	of_node_put(ref_np);
+out_ref:
+	of_node_put(desc_np);
+
+	return (unsigned long) rate;
+}
+
 static int cpr_corner_init(struct cpr_drv *drv)
 {
 	const struct cpr_desc *desc = drv->desc;
@@ -821,7 +1081,7 @@ static int cpr_corner_init(struct cpr_drv *drv)
 	unsigned int fnum, fc;
 	const char *quot_offset;
 	struct fuse_corner *fuse, *prev_fuse;
-	struct cpr_corner *corner, *end;
+	struct corner *corner, *end;
 	struct corner_data *cdata;
 	const struct fuse_corner_data *fdata;
 	bool apply_scaling;
@@ -850,7 +1110,7 @@ static int cpr_corner_init(struct cpr_drv *drv)
 		opp = dev_pm_opp_find_level_exact(&drv->pd.dev, level);
 		if (IS_ERR(opp))
 			return -EINVAL;
-		fc = cpr_get_fuse_corner(opp, 0);
+		fc = cpr_get_fuse_corner(opp);
 		if (!fc) {
 			dev_pm_opp_put(opp);
 			return -EINVAL;
@@ -921,49 +1181,90 @@ static int cpr_corner_init(struct cpr_drv *drv)
 		else
 			prev_fuse = NULL;
 
-		corner->corner.fuse_corner = fuse;
-		corner->corner.freq = cdata[i].freq;
-		corner->corner.uV = fuse->uV;
+		corner->fuse_corner = fuse;
+		corner->freq = cdata[i].freq;
+		corner->uV = fuse->uV;
 
 		if (prev_fuse && cdata[i - 1].freq == prev_fuse->max_freq) {
-			scaling = cpr_calculate_scaling(quot_offset, drv->dev,
-							fdata, &corner->corner);
+			scaling = cpr_calculate_scaling(quot_offset, drv,
+							fdata, corner);
 			if (scaling < 0)
 				return scaling;
 
 			apply_scaling = true;
-		} else if (corner->corner.freq == fuse->max_freq) {
+		} else if (corner->freq == fuse->max_freq) {
 			/* This is a fuse corner; don't scale anything */
 			apply_scaling = false;
 		}
 
 		if (apply_scaling) {
-			freq_diff = fuse->max_freq - corner->corner.freq;
+			freq_diff = fuse->max_freq - corner->freq;
 			freq_diff_mhz = freq_diff / 1000000;
 			corner->quot_adjust = scaling * freq_diff_mhz / 1000;
 
-			corner->corner.uV = cpr_interpolate(&corner->corner, step_volt, fdata);
+			corner->uV = cpr_interpolate(corner, step_volt, fdata);
 		}
 
-		corner->corner.max_uV = fuse->max_uV;
-		corner->corner.min_uV = fuse->min_uV;
-		corner->corner.uV = clamp(corner->corner.uV, corner->corner.min_uV, corner->corner.max_uV);
-		corner->last_uV = corner->corner.uV;
+		corner->max_uV = fuse->max_uV;
+		corner->min_uV = fuse->min_uV;
+		corner->uV = clamp(corner->uV, corner->min_uV, corner->max_uV);
+		corner->last_uV = corner->uV;
 
 		/* Reduce the ceiling voltage if needed */
-		if (desc->reduce_to_corner_uV && corner->corner.uV < corner->corner.max_uV)
-			corner->corner.max_uV = corner->corner.uV;
-		else if (desc->reduce_to_fuse_uV && fuse->uV < corner->corner.max_uV)
-			corner->corner.max_uV = max(corner->corner.min_uV, fuse->uV);
+		if (desc->reduce_to_corner_uV && corner->uV < corner->max_uV)
+			corner->max_uV = corner->uV;
+		else if (desc->reduce_to_fuse_uV && fuse->uV < corner->max_uV)
+			corner->max_uV = max(corner->min_uV, fuse->uV);
 
 		dev_dbg(drv->dev, "corner %d: [%d %d %d] quot %d\n", i,
-			corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV,
+			corner->min_uV, corner->uV, corner->max_uV,
 			fuse->quot - corner->quot_adjust);
 	}
 
 	return 0;
 }
 
+static const struct cpr_fuse *cpr_get_fuses(struct cpr_drv *drv)
+{
+	const struct cpr_desc *desc = drv->desc;
+	struct cpr_fuse *fuses;
+	int i;
+
+	fuses = devm_kcalloc(drv->dev, desc->num_fuse_corners,
+			     sizeof(struct cpr_fuse),
+			     GFP_KERNEL);
+	if (!fuses)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < desc->num_fuse_corners; i++) {
+		char tbuf[32];
+
+		snprintf(tbuf, 32, "cpr_ring_osc%d", i + 1);
+		fuses[i].ring_osc = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
+		if (!fuses[i].ring_osc)
+			return ERR_PTR(-ENOMEM);
+
+		snprintf(tbuf, 32, "cpr_init_voltage%d", i + 1);
+		fuses[i].init_voltage = devm_kstrdup(drv->dev, tbuf,
+						     GFP_KERNEL);
+		if (!fuses[i].init_voltage)
+			return ERR_PTR(-ENOMEM);
+
+		snprintf(tbuf, 32, "cpr_quotient%d", i + 1);
+		fuses[i].quotient = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
+		if (!fuses[i].quotient)
+			return ERR_PTR(-ENOMEM);
+
+		snprintf(tbuf, 32, "cpr_quotient_offset%d", i + 1);
+		fuses[i].quotient_offset = devm_kstrdup(drv->dev, tbuf,
+							GFP_KERNEL);
+		if (!fuses[i].quotient_offset)
+			return ERR_PTR(-ENOMEM);
+	}
+
+	return fuses;
+}
+
 static void cpr_set_loop_allowed(struct cpr_drv *drv)
 {
 	drv->loop_disabled = false;
@@ -995,6 +1296,54 @@ static int cpr_init_parameters(struct cpr_drv *drv)
 	return 0;
 }
 
+static int cpr_find_initial_corner(struct cpr_drv *drv)
+{
+	unsigned long rate;
+	const struct corner *end;
+	struct corner *iter;
+	unsigned int i = 0;
+
+	if (!drv->cpu_clk) {
+		dev_err(drv->dev, "cannot get rate from NULL clk\n");
+		return -EINVAL;
+	}
+
+	end = &drv->corners[drv->num_corners - 1];
+	rate = clk_get_rate(drv->cpu_clk);
+
+	/*
+	 * Some bootloaders set a CPU clock frequency that is not defined
+	 * in the OPP table. When running at an unlisted frequency,
+	 * cpufreq_online() will change to the OPP which has the lowest
+	 * frequency, at or above the unlisted frequency.
+	 * Since cpufreq_online() always "rounds up" in the case of an
+	 * unlisted frequency, this function always "rounds down" in case
+	 * of an unlisted frequency. That way, when cpufreq_online()
+	 * triggers the first ever call to cpr_set_performance_state(),
+	 * it will correctly determine the direction as UP.
+	 */
+	for (iter = drv->corners; iter <= end; iter++) {
+		if (iter->freq > rate)
+			break;
+		i++;
+		if (iter->freq == rate) {
+			drv->corner = iter;
+			break;
+		}
+		if (iter->freq < rate)
+			drv->corner = iter;
+	}
+
+	if (!drv->corner) {
+		dev_err(drv->dev, "boot up corner not found\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(drv->dev, "boot up perf state: %u\n", i);
+
+	return 0;
+}
+
 static const struct cpr_desc qcs404_cpr_desc = {
 	.num_fuse_corners = 3,
 	.min_diff_quot = CPR_FUSE_MIN_QUOT_DIFF,
@@ -1096,56 +1445,6 @@ static int cpr_power_on(struct generic_pm_domain *domain)
 	return cpr_enable(drv);
 }
 
-/*
- * Returns: Index of the initial corner or negative number for error.
- */
-static int cpr_find_initial_corner(struct device *dev, struct clk *cpu_clk,
-			    struct cpr_corner *corners, int num_corners)
-{
-	unsigned long rate;
-	struct cpr_corner *iter, *corner;
-	const struct cpr_corner *end;
-	unsigned int ret = 0;
-
-	if (!cpu_clk)
-		return -EINVAL;
-
-	end = &corners[num_corners - 1];
-	rate = clk_get_rate(cpu_clk);
-
-	/*
-	 * Some bootloaders set a CPU clock frequency that is not defined
-	 * in the OPP table. When running at an unlisted frequency,
-	 * cpufreq_online() will change to the OPP which has the lowest
-	 * frequency, at or above the unlisted frequency.
-	 * Since cpufreq_online() always "rounds up" in the case of an
-	 * unlisted frequency, this function always "rounds down" in case
-	 * of an unlisted frequency. That way, when cpufreq_online()
-	 * triggers the first ever call to cpr_set_performance_state(),
-	 * it will correctly determine the direction as UP.
-	 */
-	for (iter = corners; iter <= end; iter++) {
-		if (iter->corner.freq > rate)
-			break;
-		ret++;
-		if (iter->corner.freq == rate) {
-			corner = iter;
-			break;
-		}
-		if (iter->corner.freq < rate)
-			corner = iter;
-	}
-
-	if (!corner) {
-		dev_err(dev, "boot up corner not found\n");
-		return -EINVAL;
-	}
-
-	dev_dbg(dev, "boot up perf state: %u\n", ret);
-
-	return ret;
-}
-
 static int cpr_pd_attach_dev(struct generic_pm_domain *domain,
 			     struct device *dev)
 {
@@ -1232,9 +1531,8 @@ static int cpr_pd_attach_dev(struct generic_pm_domain *domain,
 	if (ret)
 		goto unlock;
 
-	ret = cpr_find_initial_corner(drv->dev, drv->cpu_clk, drv->corners,
-				      drv->num_corners);
-	if (ret < 0)
+	ret = cpr_find_initial_corner(drv);
+	if (ret)
 		goto unlock;
 
 	if (acc_desc->config)
@@ -1262,10 +1560,10 @@ static int cpr_debug_info_show(struct seq_file *s, void *unused)
 	u32 step_dn, step_up, error, error_lt0, busy;
 	struct cpr_drv *drv = s->private;
 	struct fuse_corner *fuse_corner;
-	struct cpr_corner *corner;
+	struct corner *corner;
 
 	corner = drv->corner;
-	fuse_corner = corner->corner.fuse_corner;
+	fuse_corner = corner->fuse_corner;
 
 	seq_printf(s, "corner, current_volt = %d uV\n",
 		       corner->last_uV);
@@ -1319,7 +1617,6 @@ static int cpr_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct device *dev = &pdev->dev;
 	struct cpr_drv *drv;
-	const struct cpr_desc *desc;
 	int irq, ret;
 	const struct cpr_acc_desc *data;
 	struct device_node *np;
@@ -1335,7 +1632,6 @@ static int cpr_probe(struct platform_device *pdev)
 	drv->dev = dev;
 	drv->desc = data->cpr_desc;
 	drv->acc_desc = data->acc_desc;
-	desc = drv->desc;
 
 	drv->fuse_corners = devm_kcalloc(dev, drv->desc->num_fuse_corners,
 					 sizeof(*drv->fuse_corners),
@@ -1376,15 +1672,11 @@ static int cpr_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	dev_dbg(dev, "Fusing revision %d\n", cpr_rev);
-
-	drv->cpr_fuses = cpr_get_fuses(drv->dev, 0, desc->num_fuse_corners);
+	drv->cpr_fuses = cpr_get_fuses(drv);
 	if (IS_ERR(drv->cpr_fuses))
 		return PTR_ERR(drv->cpr_fuses);
 
-	ret = cpr_populate_ring_osc_idx(drv->dev, drv->fuse_corners,
-					drv->cpr_fuses,
-					desc->num_fuse_corners);
+	ret = cpr_populate_ring_osc_idx(drv);
 	if (ret)
 		return ret;
 
diff --git a/kernel/drivers/soc/qcom/cpr3-gfx.c b/kernel/drivers/soc/qcom/cpr3-gfx.c
deleted file mode 100644
index 3a29f41be044..000000000000
--- a/kernel/drivers/soc/qcom/cpr3-gfx.c
+++ /dev/null
@@ -1,2327 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
- * Copyright (c) 2019 Linaro Limited
- * Copyright (c) 2021, AngeloGioacchino Del Regno
- *                     <angelogioacchino.delregno@somainline.org>
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/debugfs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_opp.h>
-#include <linux/interrupt.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regulator/consumer.h>
-#include <linux/workqueue.h>
-#include <linux/clk.h>
-#include <linux/nvmem-consumer.h>
-#include <soc/qcom/cpr.h>
-#include "cpr-common.h"
-
-#define CPR3_RO_COUNT				16
-#define CPR3_RO_MASK				GENMASK(CPR3_RO_COUNT - 1, 0)
-
-/* CPR3 registers */
-#define CPR3_REG_CPR_VERSION			0x0
-#define CPRH_CPR_VERSION_4P5			0x40050000
-
-#define CPR3_REG_CPR_CTL			0x4
-#define CPR3_CPR_CTL_LOOP_EN_MASK		BIT(0)
-#define CPR3_CPR_CTL_IDLE_CLOCKS_MASK		GENMASK(5, 1)
-#define CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT		1
-#define CPR3_CPR_CTL_COUNT_MODE_MASK		GENMASK(7, 6)
-#define CPR3_CPR_CTL_COUNT_MODE_SHIFT		6
-#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN	0
-#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MAX	1
-#define CPR3_CPR_CTL_COUNT_MODE_STAGGERED	2
-#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE	3
-#define CPR3_CPR_CTL_COUNT_REPEAT_MASK		GENMASK(31, 9)
-#define CPR3_CPR_CTL_COUNT_REPEAT_SHIFT		9
-
-#define CPR3_REG_CPR_STATUS			0x8
-#define CPR3_CPR_STATUS_BUSY_MASK		BIT(0)
-
-/*
- * This register is not present on controllers that support HW closed-loop
- * except CPR4 APSS controller.
- */
-#define CPR3_REG_CPR_TIMER_AUTO_CONT		0xC
-
-#define CPR3_REG_CPR_STEP_QUOT			0x14
-#define CPR3_CPR_STEP_QUOT_MIN_MASK		GENMASK(5, 0)
-#define CPR3_CPR_STEP_QUOT_MIN_SHIFT		0
-#define CPR3_CPR_STEP_QUOT_MAX_MASK		GENMASK(11, 6)
-#define CPR3_CPR_STEP_QUOT_MAX_SHIFT		6
-#define CPRH_DELTA_QUOT_STEP_FACTOR		4
-
-#define CPR3_REG_GCNT(ro)			(0xA0 + 0x4 * (ro))
-#define CPR3_REG_SENSOR_OWNER(sensor)		(0x200 + 0x4 * (sensor))
-
-#define CPR3_REG_CONT_CMD			0x800
-#define CPR3_CONT_CMD_ACK			0x1
-#define CPR3_CONT_CMD_NACK			0x0
-
-#define CPR3_REG_THRESH(thread)			(0x808 + 0x440 * (thread))
-#define CPR3_THRESH_CONS_DOWN_MASK		GENMASK(3, 0)
-#define CPR3_THRESH_CONS_DOWN_SHIFT		0
-#define CPR3_THRESH_CONS_UP_MASK		GENMASK(7, 4)
-#define CPR3_THRESH_CONS_UP_SHIFT		4
-#define CPR3_THRESH_DOWN_THRESH_MASK		GENMASK(12, 8)
-#define CPR3_THRESH_DOWN_THRESH_SHIFT		8
-#define CPR3_THRESH_UP_THRESH_MASK		GENMASK(17, 13)
-#define CPR3_THRESH_UP_THRESH_SHIFT		13
-
-#define CPR3_REG_RO_MASK(thread)		(0x80C + 0x440 * (thread))
-
-#define CPR3_REG_RESULT0(thread)		(0x810 + 0x440 * (thread))
-#define CPR3_RESULT0_BUSY_MASK			BIT(0)
-#define CPR3_RESULT0_STEP_DN_MASK		BIT(1)
-#define CPR3_RESULT0_STEP_UP_MASK		BIT(2)
-#define CPR3_RESULT0_ERROR_STEPS_MASK		GENMASK(7, 3)
-#define CPR3_RESULT0_ERROR_STEPS_SHIFT		3
-#define CPR3_RESULT0_ERROR_MASK			GENMASK(19, 8)
-#define CPR3_RESULT0_ERROR_SHIFT		8
-
-#define CPR3_REG_RESULT1(thread)		(0x814 + 0x440 * (thread))
-#define CPR3_RESULT1_QUOT_MIN_MASK		GENMASK(11, 0)
-#define CPR3_RESULT1_QUOT_MIN_SHIFT		0
-#define CPR3_RESULT1_QUOT_MAX_MASK		GENMASK(23, 12)
-#define CPR3_RESULT1_QUOT_MAX_SHIFT		12
-#define CPR3_RESULT1_RO_MIN_MASK		GENMASK(27, 24)
-#define CPR3_RESULT1_RO_MIN_SHIFT		24
-#define CPR3_RESULT1_RO_MAX_MASK		GENMASK(31, 28)
-#define CPR3_RESULT1_RO_MAX_SHIFT		28
-
-#define CPR3_REG_RESULT2(thread)		(0x818 + 0x440 * (thread))
-#define CPR3_RESULT2_STEP_QUOT_MIN_MASK		GENMASK(5, 0)
-#define CPR3_RESULT2_STEP_QUOT_MIN_SHIFT	0
-#define CPR3_RESULT2_STEP_QUOT_MAX_MASK		GENMASK(11, 6)
-#define CPR3_RESULT2_STEP_QUOT_MAX_SHIFT	6
-#define CPR3_RESULT2_SENSOR_MIN_MASK		GENMASK(23, 16)
-#define CPR3_RESULT2_SENSOR_MIN_SHIFT		16
-#define CPR3_RESULT2_SENSOR_MAX_MASK		GENMASK(31, 24)
-#define CPR3_RESULT2_SENSOR_MAX_SHIFT		24
-
-#define CPR3_REG_IRQ_EN				0x81C
-#define CPR3_REG_IRQ_CLEAR			0x820
-#define CPR3_REG_IRQ_STATUS			0x824
-#define CPR3_IRQ_UP				BIT(3)
-#define CPR3_IRQ_MID				BIT(2)
-#define CPR3_IRQ_DOWN				BIT(1)
-#define CPR3_IRQ_ALL				(CPR3_IRQ_UP | CPR3_IRQ_MID | CPR3_IRQ_DOWN)
-
-#define CPR3_REG_TARGET_QUOT(thread, ro)	(0x840 + 0x440 * (thread) + 0x4 * (ro))
-
-/* Registers found only on controllers that support HW closed-loop. */
-#define CPR3_REG_PD_THROTTLE			0xE8
-
-#define CPR3_REG_HW_CLOSED_LOOP_DISABLED	0x3000
-#define CPR3_REG_CPR_TIMER_MID_CONT		0x3004
-#define CPR3_REG_CPR_TIMER_UP_DN_CONT		0x3008
-
-enum cpr_type {
-	CTRL_TYPE_CPR3,
-	CTRL_TYPE_CPR4,
-	CTRL_TYPE_CPRH,
-	CTRL_TYPE_MAX,
-};
-
-struct gfx_fuse_corner_data {
-	struct fuse_corner_data fcd;
-	int quot[CPR3_RO_COUNT];
-};
-
-struct cpr_corner {
-	struct corner corner;
-	int last_uV;
-	int quot[CPR3_RO_COUNT];
-	bool is_open_loop;
-};
-
-/*
- * struct cpr_thread_desc - CPR Thread-specific parameters
- *
- * @controller_id:      Identifier of the CPR controller expected by the HW
- * @ro_scaling_factor:  Scaling factor for each ring oscillator entry
- * @hw_tid:             Identifier of the CPR thread expected by the HW
- * @init_voltage_step:  Voltage in uV for number of steps read from fuse array
- * @init_voltage_width: Bit-width of the voltage read from the fuse array
- * @sensor_range_start: First sensor ID used by a thread
- * @sensor_range_end:   Last sensor ID used by a thread
- * @sensor_owner:   	The ID to program for sensor ownership
- * @num_fuse_corners:   Number of valid entries in fuse_corner_data
- * @step_quot_init_min: Minimum achievable step quotient for this corner
- * @step_quot_init_max: Maximum achievable step quotient for this corner
- * @fuse_corner_data:   Parameters for calculation of each fuse corner
- */
-struct cpr_thread_desc {
-	u8		controller_id;
-	u8		hw_tid;
-	const int	(*ro_scaling_factor)[CPR3_RO_COUNT];
-	int		ro_avail_corners;
-	int		init_voltage_step;
-	int		init_voltage_width;
-	u8		sensor_range_start;
-	u8		sensor_range_end;
-	u8		sensor_owner;
-	u8		step_quot_init_min;
-	u8		step_quot_init_max;
-	unsigned int	num_fuse_corners;
-	struct gfx_fuse_corner_data *fuse_corner_data;
-};
-
-/*
- * struct cpr_desc - Driver instance-wide CPR parameters
- *
- * @cpr_type:              Type (base version) of the CPR controller
- * @num_threads:           Max. number of threads supported by this controller
- * @timer_delay_us:        Loop delay time in uS
- * @timer_updn_delay_us:   Voltage after-up/before-down delay time in uS
- * @timer_cons_up:         Wait between consecutive up requests in uS
- * @timer_cons_down:       Wait between consecutive down requests in uS
- * @up_threshold:          Generic corner up threshold
- * @down_threshold:        Generic corner down threshold
- * @idle_clocks:           CPR Sensor: idle timer in cpr clocks unit
- * @count_mode:            CPR Sensor: counting mode
- * @count_repeat:          CPR Sensor: number of times to repeat reading
- * @gcnt_us:               CPR measurement interval in uS
- * @vreg_step_fixed:       Regulator voltage per step (if vreg unusable)
- * @vreg_step_up_limit:    Num. of steps up at once before re-measuring sensors
- * @vreg_step_down_limit:  Num. of steps dn at once before re-measuring sensors
- * @vdd_settle_time_us:    Settling timer to account for one VDD supply step
- * @corner_settle_time_us: Settle time for corner switch request
- * @mem_acc_threshold:     Memory Accelerator (MEM-ACC) voltage threshold
- * @cpr_base_voltage:      Safety: Absolute minimum voltage (uV) on this CPR
- * @cpr_max_voltage:       Safety: Absolute maximum voltage (uV) on this CPR
- * @pd_throttle_val:       CPR Power Domain throttle during voltage switch
- * @threads:               Array containing "CPR Thread" specific parameters
- * @reduce_to_fuse_uV:     Reduce corner max volts (if higher) to fuse ceiling
- * @reduce_to_corner_uV:   Reduce corner max volts (if higher) to corner ceil.
- * @hw_closed_loop_en:     Enable CPR HW Closed-Loop voltage auto-adjustment
- */
-struct cpr_desc {
-	enum cpr_type		cpr_type;
-	unsigned int		num_threads;
-	unsigned int		timer_delay_us;
-	u8			timer_updn_delay_us;
-	u8			timer_cons_up;
-	u8			timer_cons_down;
-	u8			up_threshold;
-	u8			down_threshold;
-	u8			idle_clocks;
-	u8			count_mode;
-	u8			count_repeat;
-	u8			gcnt_us;
-	u16			vreg_step_fixed;
-	u8			vreg_step_up_limit;
-	u8			vreg_step_down_limit;
-	u8			vdd_settle_time_us;
-	u8			corner_settle_time_us;
-	int			mem_acc_threshold;
-	u32			cpr_base_voltage;
-	u32			cpr_max_voltage;
-	u32			pd_throttle_val;
-
-	const struct cpr_thread_desc **threads;
-	bool reduce_to_fuse_uV;
-	bool reduce_to_corner_uV;
-	bool hw_closed_loop_en;
-};
-
-struct cpr_drv;
-struct cpr_thread {
-	int			num_corners;
-	int			id;
-	bool			enabled;
-	void __iomem		*base;
-	struct clk		*cpu_clk;
-	struct cpr_corner		*corner;
-	struct cpr_corner		*corners;
-	struct fuse_corner	*fuse_corners;
-	struct cpr_drv		*drv;
-	struct cpr_ext_data	ext_data;
-	struct generic_pm_domain pd;
-	struct device		*attached_cpu_dev;
-	struct work_struct	restart_work;
-	bool			restarting;
-
-	const struct cpr_fuse	*cpr_fuses;
-	const struct cpr_thread_desc *desc;
-};
-
-struct cpr_drv {
-	int			irq;
-	unsigned int		ref_clk_khz;
-	struct device		*dev;
-	struct mutex		lock;
-	struct regulator	*vreg;
-	struct regmap		*tcsr;
-	u32			gcnt;
-	u32			speed_bin;
-	u32			fusing_rev;
-	u32			last_uV;
-	int			fuse_level_set;
-	int			extra_corners;
-	unsigned int		vreg_step;
-	bool			enabled;
-
-	struct cpr_thread	*threads;
-	struct genpd_onecell_data cell_data;
-
-	const struct cpr_desc	*desc;
-	const struct acc_desc	*acc_desc;
-	struct dentry		*debugfs;
-};
-
-/**
- * cpr_get_ro_factor() - Get fuse corner ring oscillator factor
- * @tdesc:  CPR Thread-specific parameters
- * @fnum:   Fuse corner
- * @ro_idx: Ring Oscillator fuse number
- *
- * Not all threads have different scaling factors for each
- * Fuse Corner: if the RO factors are the same for all corners,
- * then only one is specified, instead of uselessly repeating
- * the same array for FC-times.
- * This function checks for the same and gives back the right
- * factor for the requested ring oscillator.
- *
- * Return: Ring oscillator factor
- */
-static int cpr_get_ro_factor(const struct cpr_thread_desc *tdesc,
-			     int fnum, int ro_idx)
-{
-	int ro_fnum;
-
-	if (tdesc->ro_avail_corners == tdesc->num_fuse_corners)
-		ro_fnum = fnum;
-	else
-		ro_fnum = 0;
-
-	return tdesc->ro_scaling_factor[ro_fnum][ro_idx];
-}
-
-static void cpr_write(struct cpr_thread *thread, u32 offset, u32 value)
-{
-	writel(value, thread->base + offset);
-}
-
-static u32 cpr_read(struct cpr_thread *thread, u32 offset)
-{
-	return readl(thread->base + offset);
-}
-
-static void
-cpr_masked_write(struct cpr_thread *thread, u32 offset, u32 mask, u32 value)
-{
-	u32 val;
-
-	val = readl(thread->base + offset);
-	val &= ~mask;
-	val |= value & mask;
-	writel(val, thread->base + offset);
-}
-
-static void cpr_irq_clr(struct cpr_thread *thread)
-{
-	cpr_write(thread, CPR3_REG_IRQ_CLEAR, CPR3_IRQ_ALL);
-}
-
-static void cpr_irq_clr_nack(struct cpr_thread *thread)
-{
-	cpr_irq_clr(thread);
-	cpr_write(thread, CPR3_REG_CONT_CMD, CPR3_CONT_CMD_NACK);
-}
-
-static void cpr_irq_clr_ack(struct cpr_thread *thread)
-{
-	cpr_irq_clr(thread);
-	cpr_write(thread, CPR3_REG_CONT_CMD, CPR3_CONT_CMD_ACK);
-}
-
-static void cpr_irq_set(struct cpr_thread *thread, u32 int_bits)
-{
-	/* On CPR-hardened, interrupts are managed by and on firmware */
-	if (thread->drv->desc->cpr_type == CTRL_TYPE_CPRH)
-		return;
-
-	cpr_write(thread, CPR3_REG_IRQ_EN, int_bits);
-}
-
-/**
- * cpr_ctl_enable() - Enable CPR thread
- * @thread:     Structure holding CPR thread-specific parameters
- */
-static void cpr_ctl_enable(struct cpr_thread *thread)
-{
-	if (thread->drv->enabled && !thread->restarting) {
-		cpr_masked_write(thread, CPR3_REG_CPR_CTL,
-				 CPR3_CPR_CTL_LOOP_EN_MASK,
-				 CPR3_CPR_CTL_LOOP_EN_MASK);
-	}
-}
-
-/**
- * cpr_ctl_disable() - Disable CPR thread
- * @thread:     Structure holding CPR thread-specific parameters
- */
-static void cpr_ctl_disable(struct cpr_thread *thread)
-{
-	const struct cpr_desc *desc = thread->drv->desc;
-
-	if (desc->cpr_type != CTRL_TYPE_CPRH) {
-		cpr_irq_set(thread, 0);
-		cpr_irq_clr(thread);
-	}
-
-	cpr_masked_write(thread, CPR3_REG_CPR_CTL,
-			 CPR3_CPR_CTL_LOOP_EN_MASK, 0);
-}
-
-/**
- * cpr_ctl_is_enabled() - Check if thread is enabled
- * @thread:     Structure holding CPR thread-specific parameters
- *
- * Return: true if the CPR is enabled, false if it is disabled.
- */
-static bool cpr_ctl_is_enabled(struct cpr_thread *thread)
-{
-	u32 reg_val;
-
-	reg_val = cpr_read(thread, CPR3_REG_CPR_CTL);
-	return reg_val & CPR3_CPR_CTL_LOOP_EN_MASK;
-}
-
-/**
- * cpr_check_any_thread_busy() - Check if HW is done processing
- * @thread:     Structure holding CPR thread-specific parameters
- *
- * Return: true if the CPR is busy, false if it is ready.
- */
-static bool cpr_check_any_thread_busy(struct cpr_thread *thread)
-{
-	int i;
-
-	for (i = 0; i < thread->drv->desc->num_threads; i++)
-		if (cpr_read(thread, CPR3_REG_RESULT0(i)) &
-		    CPR3_RESULT0_BUSY_MASK)
-			return true;
-
-	return false;
-}
-
-static void cpr_restart_worker(struct work_struct *work)
-{
-	struct cpr_thread *thread = container_of(work, struct cpr_thread,
-						 restart_work);
-	struct cpr_drv *drv = thread->drv;
-	int i;
-
-	mutex_lock(&drv->lock);
-
-	thread->restarting = true;
-	cpr_ctl_disable(thread);
-	disable_irq(drv->irq);
-
-	mutex_unlock(&drv->lock);
-
-	for (i = 0; i < 20; i++) {
-		u32 cpr_status = cpr_read(thread, CPR3_REG_CPR_STATUS);
-		u32 ctl = cpr_read(thread, CPR3_REG_CPR_CTL);
-
-		if ((cpr_status & CPR3_CPR_STATUS_BUSY_MASK) &&
-		   !(ctl & CPR3_CPR_CTL_LOOP_EN_MASK))
-			break;
-
-		udelay(10);
-	}
-
-	cpr_irq_clr(thread);
-
-	for (i = 0; i < 20; i++) {
-		u32 status = cpr_read(thread, CPR3_REG_IRQ_STATUS);
-
-		if (!(status & CPR3_IRQ_ALL))
-			break;
-		udelay(10);
-	}
-
-	mutex_lock(&drv->lock);
-
-	thread->restarting = false;
-	enable_irq(drv->irq);
-	cpr_ctl_enable(thread);
-
-	mutex_unlock(&drv->lock);
-}
-
-/**
- * cpr_corner_restore() - Restore saved corner level
- * @thread: Structure holding CPR thread-specific parameters
- * @corner: Structure holding the saved corner level
- */
-static void cpr_corner_restore(struct cpr_thread *thread,
-			       struct cpr_corner *corner)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_thread_desc *tdesc = thread->desc;
-	u32 ro_mask = CPR3_RO_MASK;
-	u32 ro;
-
-	for (ro = 0; ro < CPR3_RO_COUNT; ro++) {
-		// FIXME: check the condition
-		if (corner->quot[ro] == 0)
-			continue;
-
-		ro_mask &= ~BIT(ro);
-		cpr_write(thread, CPR3_REG_GCNT(ro), drv->gcnt);
-
-		cpr_write(thread, CPR3_REG_TARGET_QUOT(tdesc->hw_tid, ro),
-			  corner->quot[ro]);
-
-	}
-
-	cpr_write(thread, CPR3_REG_RO_MASK(tdesc->hw_tid), ro_mask);
-
-	thread->corner = corner;
-	corner->last_uV = corner->corner.uV;
-}
-
-/**
- * cpr_set_acc() - Set fuse level to the mem-acc
- * @drv: Main driver structure
- * @f:   Fuse level
- */
-static void cpr_set_acc(struct cpr_drv *drv, int f)
-{
-	const struct acc_desc *desc = drv->acc_desc;
-	struct reg_sequence *s = desc->settings;
-	int n = desc->num_regs_per_fuse;
-
-	if (!s || f == drv->fuse_level_set)
-		return;
-
-	regmap_multi_reg_write(drv->tcsr, s + (n * f), n);
-	drv->fuse_level_set = f;
-}
-
-/**
- * cpr_pre_voltage() - Actions to execute before setting voltage
- * @thread:     Structure holding CPR thread-specific parameters
- * @dir:        Enumeration for voltage change direction
- * @fuse_level: Fuse corner for mem-acc, if supported.
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_pre_voltage(struct cpr_thread *thread,
-			   enum voltage_change_dir dir,
-			   int fuse_level)
-{
-	struct cpr_drv *drv = thread->drv;
-
-	if (drv->desc->cpr_type == CTRL_TYPE_CPR3 &&
-	    drv->desc->pd_throttle_val)
-		cpr_write(thread, CPR3_REG_PD_THROTTLE,
-			  drv->desc->pd_throttle_val);
-
-	if (drv->tcsr && dir == DOWN)
-		cpr_set_acc(drv, fuse_level);
-
-	return 0;
-}
-
-/**
- * cpr_post_voltage() - Actions to execute after setting voltage
- * @thread:     Structure holding CPR thread-specific parameters
- * @dir:        Enumeration for voltage change direction
- * @fuse_level: Fuse corner for mem-acc, if supported.
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_post_voltage(struct cpr_thread *thread,
-			    enum voltage_change_dir dir,
-			    int fuse_level)
-{
-	struct cpr_drv *drv = thread->drv;
-
-	if (drv->tcsr && dir == UP)
-		cpr_set_acc(drv, fuse_level);
-
-	if (drv->desc->cpr_type == CTRL_TYPE_CPR3)
-		cpr_write(thread, CPR3_REG_PD_THROTTLE, 0);
-
-	return 0;
-}
-
-/**
- * cpr_commit_state() - Set the newly requested voltage
- * @thread:     Structure holding CPR thread-specific parameters
- *
- * Return: IRQ_SUCCESS for success, IRQ_NONE if the CPR is disabled.
- */
-static int cpr_commit_state(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	int min_uV = 0, max_uV = 0, new_uV = 0, fuse_level = 0;
-	enum voltage_change_dir dir;
-	u32 next_irqmask = 0;
-	int ret, i;
-
-	/* On CPRhardened, control states are managed in firmware */
-	if (drv->desc->cpr_type == CTRL_TYPE_CPRH)
-		return 0;
-
-	for (i = 0; i < drv->desc->num_threads; i++) {
-		struct cpr_thread *thread = &drv->threads[i];
-
-		if (!thread->corner)
-			continue;
-
-		fuse_level = max(fuse_level,
-				 (int) (thread->corner->corner.fuse_corner -
-				 &thread->fuse_corners[0]));
-
-		max_uV = max(max_uV, thread->corner->corner.max_uV);
-		min_uV = max(min_uV, thread->corner->corner.min_uV);
-		new_uV = max(new_uV, thread->corner->last_uV);
-	}
-	dev_vdbg(drv->dev, "%s: new uV: %d, last uV: %d\n",
-		 __func__, new_uV, drv->last_uV);
-
-	/*
-	 * Safety measure: if the voltage is out of the globally allowed
-	 * range, then go out and warn the user.
-	 * This should *never* happen.
-	 */
-	if (new_uV > drv->desc->cpr_max_voltage ||
-	    new_uV < drv->desc->cpr_base_voltage) {
-		dev_warn(drv->dev, "Voltage (%u uV) out of range.", new_uV);
-		return -EINVAL;
-	}
-
-	if (new_uV == drv->last_uV || fuse_level == drv->fuse_level_set)
-		goto out;
-
-	if (fuse_level > drv->fuse_level_set)
-		dir = UP;
-	else
-		dir = DOWN;
-
-	ret = cpr_pre_voltage(thread, fuse_level, dir);
-	if (ret)
-		return ret;
-
-	dev_vdbg(drv->dev, "setting voltage: %d\n", new_uV);
-
-	ret = regulator_set_voltage(drv->vreg, new_uV, new_uV);
-	if (ret) {
-		dev_err_ratelimited(drv->dev, "failed to set voltage %d: %d\n", new_uV, ret);
-		return ret;
-	}
-
-	ret = cpr_post_voltage(thread, fuse_level, dir);
-	if (ret)
-		return ret;
-
-	drv->last_uV = new_uV;
-out:
-	if (new_uV > min_uV)
-		next_irqmask |= CPR3_IRQ_DOWN;
-	if (new_uV < max_uV)
-		next_irqmask |= CPR3_IRQ_UP;
-
-	cpr_irq_set(thread, next_irqmask);
-
-	return 0;
-}
-
-static unsigned int cpr_get_cur_perf_state(struct cpr_thread *thread)
-{
-	return thread->corner ? thread->corner - thread->corners + 1 : 0;
-}
-
-/**
- * cpr_scale() - Calculate new voltage for the received direction
- * @thread: Structure holding CPR thread-specific parameters
- * @dir:    Enumeration for voltage change direction
- *
- * The CPR scales one by one: this function calculates the new
- * voltage to set when a voltage-UP or voltage-DOWN request comes
- * and stores it into the per-thread structure that gets passed.
- */
-static void cpr_scale(struct cpr_thread *thread, enum voltage_change_dir dir)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_thread_desc *tdesc = thread->desc;
-	u32 val, error_steps;
-	int last_uV, new_uV;
-	struct cpr_corner *corner;
-
-	if (dir != UP && dir != DOWN)
-		return;
-
-	corner = thread->corner;
-	val = cpr_read(thread, CPR3_REG_RESULT0(tdesc->hw_tid));
-	error_steps = val >> CPR3_RESULT0_ERROR_STEPS_SHIFT;
-	error_steps &= CPR3_RESULT0_ERROR_STEPS_MASK;
-
-	last_uV = corner->last_uV;
-
-	if (dir == UP) {
-		if (!(val & CPR3_RESULT0_STEP_UP_MASK))
-			return;
-
-		/* Calculate new voltage */
-		new_uV = last_uV + drv->vreg_step;
-		new_uV = min(new_uV, corner->corner.max_uV);
-
-		dev_vdbg(drv->dev, "[T%u] UP - new_uV=%d last_uV=%d p-state=%u st=%u\n",
-			thread->id, new_uV, last_uV,
-			cpr_get_cur_perf_state(thread), error_steps);
-	} else {
-		if (!(val & CPR3_RESULT0_STEP_DN_MASK))
-			return;
-
-		/* Calculate new voltage */
-		new_uV = last_uV - drv->vreg_step;
-		new_uV = max(new_uV, corner->corner.min_uV);
-		dev_vdbg(drv->dev, "[T%u] DOWN - new_uV=%d last_uV=%d p-state=%u st=%u\n",
-			thread->id, new_uV, last_uV,
-			cpr_get_cur_perf_state(thread), error_steps);
-	}
-	corner->last_uV = new_uV;
-}
-
-/**
- * cpr_irq_handler() - Handle CPR3/CPR4 status interrupts
- * @irq: Number of the interrupt
- * @dev: Pointer to the cpr_thread structure
- *
- * Handle the interrupts coming from non-hardened CPR HW as to get
- * an ok to scale voltages immediately, or to pass error status to
- * the hardware (either success/ACK or failure/NACK).
- *
- * Return: IRQ_SUCCESS for success, IRQ_NONE if the CPR is disabled.
- */
-static irqreturn_t cpr_irq_handler(int irq, void *dev)
-{
-	struct cpr_thread *thread = dev;
-	struct cpr_drv *drv = thread->drv;
-	irqreturn_t ret = IRQ_HANDLED;
-	int i, rc;
-	enum voltage_change_dir dir = NO_CHANGE;
-	u32 val;
-
-	mutex_lock(&drv->lock);
-
-	val = cpr_read(thread, CPR3_REG_IRQ_STATUS);
-
-	dev_vdbg(drv->dev, "IRQ_STATUS = %#02x\n", val);
-
-	if (!cpr_ctl_is_enabled(thread)) {
-		dev_vdbg(drv->dev, "CPR is disabled\n");
-		ret = IRQ_NONE;
-	} else if (cpr_check_any_thread_busy(thread)) {
-		cpr_irq_clr_nack(thread);
-		dev_dbg(drv->dev, "CPR measurement is not ready\n");
-	} else {
-		/*
-		 * Following sequence of handling is as per each IRQ's
-		 * priority
-		 */
-		if (val & CPR3_IRQ_UP)
-			dir = UP;
-		else if (val & CPR3_IRQ_DOWN)
-			dir = DOWN;
-
-		if (dir != NO_CHANGE) {
-			for (i = 0; i < drv->desc->num_threads; i++) {
-				thread = &drv->threads[i];
-				cpr_scale(thread, dir);
-			}
-
-			rc = cpr_commit_state(thread);
-			if (rc)
-				cpr_irq_clr_nack(thread);
-			else
-				cpr_irq_clr_ack(thread);
-		} else if (val & CPR3_IRQ_MID) {
-			dev_dbg(drv->dev, "IRQ occurred for Mid Flag\n");
-		} else {
-			dev_warn(drv->dev, "IRQ occurred for unknown flag (%#08x)\n", val);
-			schedule_work(&thread->restart_work);
-		}
-	}
-
-	mutex_unlock(&drv->lock);
-
-	return ret;
-}
-
-static int cpr_switch(struct cpr_drv *drv)
-{
-	int i, ret;
-	bool enabled = false;
-
-	if (drv->desc->cpr_type == CTRL_TYPE_CPRH)
-		return 0;
-
-	for (i = 0; i < drv->desc->num_threads && !enabled; i++)
-		enabled = drv->threads[i].enabled;
-
-	dev_vdbg(drv->dev, "%s: enabled = %d\n", __func__, enabled);
-
-	if (enabled == drv->enabled)
-		return 0;
-
-	if (enabled) {
-		ret = regulator_enable(drv->vreg);
-		if (ret)
-			return ret;
-
-		drv->enabled = enabled;
-
-		for (i = 0; i < drv->desc->num_threads; i++)
-			if (drv->threads[i].corner)
-				break;
-
-		if (i < drv->desc->num_threads) {
-			cpr_irq_clr(&drv->threads[i]);
-
-			cpr_commit_state(&drv->threads[i]);
-			cpr_ctl_enable(&drv->threads[i]);
-		}
-	} else {
-		for (i = 0; i < drv->desc->num_threads && !enabled; i++)
-			cpr_ctl_disable(&drv->threads[i]);
-
-		drv->enabled = enabled;
-
-		ret = regulator_disable(drv->vreg);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-/**
- * cpr_enable() - Enables a CPR thread
- * @thread: Structure holding CPR thread-specific parameters
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_enable(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	int ret;
-
-	dev_dbg(drv->dev, "Enabling thread %d\n", thread->id);
-
-	mutex_lock(&drv->lock);
-
-	thread->enabled = true;
-	ret = cpr_switch(thread->drv);
-
-	mutex_unlock(&drv->lock);
-
-	return ret;
-}
-
-/**
- * cpr_disable() - Disables a CPR thread
- * @thread: Structure holding CPR thread-specific parameters
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_disable(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	int ret;
-
-	dev_dbg(drv->dev, "Disabling thread %d\n", thread->id);
-
-	mutex_lock(&drv->lock);
-
-	thread->enabled = false;
-	ret = cpr_switch(thread->drv);
-
-	mutex_unlock(&drv->lock);
-
-	return ret;
-}
-
-/**
- * cpr_configure() - Configure main HW parameters
- * @thread: Structure holding CPR thread-specific parameters
- *
- * This function configures the main CPR hardware parameters, such as
- * internal timers (and delays), sensor ownerships, activates and/or
- * deactivates cpr-threads and others, as one sequence for all of the
- * versions supported in this driver. By design, the function may
- * return a success earlier if the sequence for "a previous version"
- * has ended.
- *
- * Context: The CPR must be clocked before calling this function!
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_configure(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_desc *desc = drv->desc;
-	const struct cpr_thread_desc *tdesc = thread->desc;
-	u32 val;
-	int i;
-
-	/* Disable interrupt and CPR */
-	cpr_irq_set(thread, 0);
-	cpr_write(thread, CPR3_REG_CPR_CTL, 0);
-
-	/* Init and save gcnt */
-	drv->gcnt = drv->ref_clk_khz * desc->gcnt_us;
-	do_div(drv->gcnt, 1000);
-
-	/* Program the delay count for the timer */
-	val = drv->ref_clk_khz * desc->timer_delay_us;
-	do_div(val, 1000);
-	/* GFX doesn't support hw closed loop */
-	cpr_write(thread, CPR3_REG_CPR_TIMER_AUTO_CONT, val);
-	dev_dbg(drv->dev, "Timer count: %#0x (for %d us)\n", val,
-		desc->timer_delay_us);
-
-	/* Program the control register */
-	val = desc->idle_clocks << CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT;
-	val |= desc->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT;
-	val |= desc->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT;
-	cpr_write(thread, CPR3_REG_CPR_CTL, val);
-
-	/* Configure CPR default step quotients */
-	val = tdesc->step_quot_init_min << CPR3_CPR_STEP_QUOT_MIN_SHIFT;
-	val |= tdesc->step_quot_init_max << CPR3_CPR_STEP_QUOT_MAX_SHIFT;
-
-	cpr_write(thread, CPR3_REG_CPR_STEP_QUOT, val);
-
-	/*
-	 * Configure the CPR sensor ownership always on thread 0
-	 * TODO: SDM845 has different ownership for sensors!!
-	 */
-	for (i = tdesc->sensor_range_start; i < tdesc->sensor_range_end; i++)
-		cpr_write(thread, CPR3_REG_SENSOR_OWNER(i), tdesc->sensor_owner);
-
-	/* Program Consecutive Up & Down */
-	val = desc->timer_cons_up << CPR3_THRESH_CONS_UP_SHIFT;
-	val |= desc->timer_cons_down << CPR3_THRESH_CONS_DOWN_SHIFT;
-	val |= desc->up_threshold << CPR3_THRESH_UP_THRESH_SHIFT;
-	val |= desc->down_threshold << CPR3_THRESH_DOWN_THRESH_SHIFT;
-	cpr_write(thread, CPR3_REG_THRESH(tdesc->hw_tid), val);
-
-	/* Mask all ring oscillators for all threads initially */
-	cpr_write(thread, CPR3_REG_RO_MASK(tdesc->hw_tid), CPR3_RO_MASK);
-
-	/* No HW Closed-loop control on GFX */
-
-	return 0;
-}
-
-
-static int cprh_dummy_set_performance_state(struct generic_pm_domain *domain,
-					    unsigned int state)
-{
-	return 0;
-}
-
-static int cpr_set_performance_state(struct generic_pm_domain *domain,
-				     unsigned int state)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-	struct cpr_drv *drv = thread->drv;
-	struct cpr_corner *corner, *end;
-	int ret = 0;
-
-	mutex_lock(&drv->lock);
-
-	dev_dbg(drv->dev, "setting perf state: %u (prev state: %u thread: %u)\n",
-		state, cpr_get_cur_perf_state(thread), thread->id);
-
-	/*
-	 * Determine new corner we're going to.
-	 * Remove one since lowest performance state is 1.
-	 */
-	corner = thread->corners + state - 1;
-	end = &thread->corners[thread->num_corners - 1];
-	if (corner > end || corner < thread->corners) {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	cpr_ctl_disable(thread);
-
-	cpr_irq_clr(thread);
-	if (thread->corner != corner)
-		cpr_corner_restore(thread, corner);
-
-	ret = cpr_commit_state(thread);
-	if (ret)
-		goto unlock;
-
-	cpr_ctl_enable(thread);
-unlock:
-	mutex_unlock(&drv->lock);
-
-	dev_dbg(drv->dev, "set perf state %u on thread %u\n", state, thread->id);
-
-	return ret;
-}
-
-/**
- * cpr3_adjust_quot - Adjust the closed-loop quotients
- * @ring_osc_factor:  Ring oscillator adjustment factor
- * @volt_closed_loop: Closed-loop voltage adjustment factor
- *
- * Calculates the quotient adjustment factor based on closed-loop
- * quotients and ring oscillator factor.
- *
- * Return: Adjusted quotient
- */
-static int cpr3_adjust_quot(int ring_osc_factor, int volt_closed_loop)
-{
-	s64 temp;
-
-	if (ring_osc_factor == 0 || volt_closed_loop == 0)
-		return 0;
-
-	temp = (s64)(ring_osc_factor * volt_closed_loop);
-	return (int)div_s64(temp, 1000000);
-}
-
-/**
- * cpr_fuse_corner_init() - Calculate fuse corner table
- * @thread: Structure holding CPR thread-specific parameters
- *
- * This function populates the fuse corners table by reading the
- * values from the fuses, eventually adjusting them with a fixed
- * per-corner offset and doing basic checks about them being
- * supported by the regulator that is assigned to this CPR - if
- * it is available (on CPR-Hardened, there is no usable vreg, as
- * that is protected by the hypervisor).
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr_fuse_corner_init(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_thread_desc *desc = thread->desc;
-	const struct cpr_fuse *cpr_fuse = thread->cpr_fuses;
-	struct gfx_fuse_corner_data *gfx_fdata;
-	struct fuse_corner_data *fdata;
-	struct fuse_corner *fuse, *prev_fuse, *end;
-	int i, ret;
-
-	/* Populate fuse_corner members */
-	fuse = thread->fuse_corners;
-	prev_fuse = &fuse[0];
-	end = &fuse[desc->num_fuse_corners - 1];
-	gfx_fdata = desc->fuse_corner_data;
-
-	for (i = 0; fuse <= end; fuse++, cpr_fuse++, i++, gfx_fdata++) {
-		int factor = cpr_get_ro_factor(desc, i, fuse->ring_osc_idx);
-
-		fdata = &gfx_fdata->fcd;
-
-		ret = cpr_read_fuse_common(drv->dev, fdata, cpr_fuse,
-					       fuse, drv->vreg_step,
-					       desc->init_voltage_width,
-					       desc->init_voltage_step);
-		if (ret)
-			return ret;
-
-		/*
-		 * Adjust the fuse quot with per-fuse-corner closed-loop
-		 * voltage adjustment parameters.
-		 */
-		fuse->quot += cpr3_adjust_quot(factor, fdata->volt_cloop_adjust);
-
-		/* CPRh: no regulator access... */
-		if (drv->desc->cpr_type == CTRL_TYPE_CPRH)
-			goto skip_pvs_restrict;
-
-		/* Re-check if corner voltage range is supported by regulator */
-		ret = cpr_check_vreg_constraints(drv->dev, drv->vreg, fuse);
-		if (ret)
-			return ret;
-
-skip_pvs_restrict:
-		if (fuse->uV < prev_fuse->uV)
-			fuse->uV = prev_fuse->uV;
-		prev_fuse = fuse;
-		dev_dbg(drv->dev, "fuse corner %d: [%d %d %d] RO%hhu quot %d\n",
-			i, fuse->min_uV, fuse->uV, fuse->max_uV,
-			fuse->ring_osc_idx, fuse->quot);
-
-#if 0
-		/* Check if constraints are valid */
-		if (fuse->uV < fuse->min_uV || fuse->uV > fuse->max_uV) {
-			dev_err(drv->dev, "fuse corner %d: Bad voltage range.\n", i);
-			return -EINVAL;
-		}
-#endif
-	}
-
-	return 0;
-}
-
-static void cpr3_restrict_corner(struct cpr_corner *corner, int threshold,
-				 int hysteresis, int step)
-{
-	if (threshold > corner->corner.min_uV && threshold <= corner->corner.max_uV) {
-		if (corner->corner.uV >= threshold) {
-			corner->corner.min_uV = max(corner->corner.min_uV,
-					     threshold - hysteresis);
-			if (corner->corner.min_uV > corner->corner.uV)
-				corner->corner.uV = corner->corner.min_uV;
-		} else {
-			corner->corner.max_uV = threshold;
-			corner->corner.max_uV -= step;
-		}
-	}
-}
-
-int cpr_gfx_calculate_freq_diff(struct device *dev,
-			  const struct fuse_corner_data *fdata,
-			  const struct corner *corner)
-{
-	u64 freq_diff;
-	const struct fuse_corner *fuse, *prev_fuse;
-
-	fuse = corner->fuse_corner;
-	prev_fuse = fuse - 1;
-
-	dev_dbg(dev, "Scalling %ld %ld\n", prev_fuse->max_freq, fuse->max_freq);
-
-	freq_diff = fuse->max_freq - prev_fuse->max_freq;
-	freq_diff = div_u64(freq_diff, 1000000); /* Convert to MHz */
-	return freq_diff;
-}
-
-/**
- * cpr3_corner_init() - Calculate and set-up corners for the CPR HW
- * @thread: Structure holding CPR thread-specific parameters
- *
- * This function calculates all the corner parameters by comparing
- * and interpolating the values read from the various set-points
- * read from the fuses (also called "fuse corners") to generate and
- * program to the CPR a lookup table that describes each voltage
- * step, mapped to a performance level (or corner number).
- *
- * It also programs other essential parameters on the CPR and - if
- * we are dealing with CPR-Hardened, it will also enable the internal
- * interface between the Operating State Manager (OSM) and the CPRh
- * in order to achieve CPU DVFS.
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr3_corner_init(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_desc *desc = drv->desc;
-	const struct cpr_thread_desc *tdesc = thread->desc;
-	const struct cpr_fuse *fuses = thread->cpr_fuses;
-	int i, total_corners, extra_corners, level, scaling = 0;
-	unsigned int fnum, fc;
-	const char *quot_offset;
-	const struct gfx_fuse_corner_data *gfx_fdata;
-	const struct gfx_fuse_corner_data *prev_gfx_fdata;
-	const struct fuse_corner_data *fdata;
-	struct fuse_corner *fuse, *prev_fuse;
-	struct cpr_corner *corner, *prev_corner, *end;
-	struct corner_data *cdata;
-	struct dev_pm_opp *opp;
-	unsigned long freq;
-	u32 ring_osc_mask = CPR3_RO_MASK, min_quotient = U32_MAX;
-
-	corner = thread->corners;
-	prev_corner = &thread->corners[0];
-	end = &corner[thread->num_corners - 1];
-
-	cdata = devm_kcalloc(drv->dev, thread->num_corners + drv->extra_corners,
-			     sizeof(struct corner_data), GFP_KERNEL);
-	if (!cdata)
-		return -ENOMEM;
-
-	for (level = 1; level <= thread->num_corners; level++) {
-		opp = dev_pm_opp_find_level_exact(&thread->pd.dev, level);
-		if (IS_ERR(opp))
-			return -EINVAL;
-
-		/*
-		 * If there is only one specified qcom,opp-fuse-level, then
-		 * it is assumed that this only one is global and valid for
-		 * all IDs, so try to get the specific one but, on failure,
-		 * go for the global one.
-		 */
-		fc = cpr_get_fuse_corner(opp, thread->id);
-		if (fc == 0) {
-			fc = cpr_get_fuse_corner(opp, 0);
-			if (fc == 0) {
-				dev_err(drv->dev, "qcom,opp-fuse-level is missing (%d)!\n", level);
-				dev_pm_opp_put(opp);
-				return -EINVAL;
-			}
-		}
-		fnum = fc - 1;
-
-		freq = cpr_get_opp_hz_for_req(opp, thread->attached_cpu_dev);
-		if (!freq) {
-			thread->num_corners = max(level - 1, 0);
-			end = &thread->corners[thread->num_corners - 1];
-			break;
-		}
-
-		/*
-		 * If any post-vadj (open/closed loop) is not specified, then
-		 * it's zero, meaning that it is not required for this corner.
-		 */
-		cpr_get_corner_post_vadj(opp, thread->id,
-					 &cdata[level - 1].oloop_vadj,
-					 &cdata[level - 1].cloop_vadj);
-		cdata[level - 1].fuse_corner = fnum;
-		cdata[level - 1].freq = freq;
-
-		fuse = &thread->fuse_corners[fnum];
-		dev_dbg(drv->dev, "freq: %lu level: %u fuse level: %u\n",
-			freq, dev_pm_opp_get_level(opp) - 1, fnum);
-		if (freq > fuse->max_freq)
-			fuse->max_freq = freq;
-		dev_pm_opp_put(opp);
-
-		/*
-		 * Make sure that the frequencies in the table are in ascending
-		 * order, as this is critical for the algorithm to work.
-		 */
-		if (cdata[level - 2].freq > freq) {
-			dev_err(drv->dev, "Frequency table not in ascending order.\n");
-			return -EINVAL;
-		}
-	}
-
-	if (thread->num_corners < 2) {
-		dev_err(drv->dev, "need at least 2 OPPs to use CPR\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Get the quotient adjustment scaling factor, according to:
-	 *
-	 * scaling = min(1000 * (QUOT(corner_N) - QUOT(corner_N-1))
-	 *		/ (freq(corner_N) - freq(corner_N-1)), max_factor)
-	 *
-	 * QUOT(corner_N):	quotient read from fuse for fuse corner N
-	 * QUOT(corner_N-1):	quotient read from fuse for fuse corner (N - 1)
-	 * freq(corner_N):	max frequency in MHz supported by fuse corner N
-	 * freq(corner_N-1):	max frequency in MHz supported by fuse corner
-	 *			 (N - 1)
-	 *
-	 * Then walk through the corners mapped to each fuse corner
-	 * and calculate the quotient adjustment for each one using the
-	 * following formula:
-	 *
-	 * quot_adjust = (freq_max - freq_corner) * scaling / 1000
-	 *
-	 * freq_max: max frequency in MHz supported by the fuse corner
-	 * freq_corner: frequency in MHz corresponding to the corner
-	 * scaling: calculated from above equation
-	 *
-	 *
-	 *     +                           +
-	 *     |                         v |
-	 *   q |           f c           o |           f c
-	 *   u |         c               l |         c
-	 *   o |       f                 t |       f
-	 *   t |     c                   a |     c
-	 *     | c f                     g | c f
-	 *     |                         e |
-	 *     +---------------            +----------------
-	 *       0 1 2 3 4 5 6               0 1 2 3 4 5 6
-	 *          corner                      corner
-	 *
-	 *    c = corner
-	 *    f = fuse corner
-	 *
-	 */
-	for (i = 0; corner <= end; corner++, i++) {
-		unsigned long freq_diff_mhz;
-		int ro, vadj, prev_quot;
-
-		fnum = cdata[i].fuse_corner;
-		gfx_fdata = &tdesc->fuse_corner_data[fnum];
-		fdata = &gfx_fdata->fcd;
-		quot_offset = fuses[fnum].quotient_offset;
-		fuse = &thread->fuse_corners[fnum];
-		//ring_osc_mask &= (u16)(~BIT(fuse->ring_osc_idx));
-		if (fnum) {
-			prev_fuse = &thread->fuse_corners[fnum - 1];
-			prev_gfx_fdata = &tdesc->fuse_corner_data[fnum - 1];
-		} else {
-			prev_fuse = NULL;
-			prev_gfx_fdata = NULL;
-		}
-
-		corner->corner.fuse_corner = fuse;
-		corner->corner.freq = cdata[i].freq;
-		corner->corner.uV = fuse->uV;
-
-		/* Fine-tune QUOT (closed-loop) based on fixed values */
-		vadj = cdata[i].cloop_vadj;
-
-		for (ro = 0; ro < CPR3_RO_COUNT; ro++) {
-			int ro_fac;
-
-			if (gfx_fdata->quot[ro] == 0)
-				continue;
-
-			ro_fac = cpr_get_ro_factor(tdesc, fnum, ro);
-
-			corner->quot[ro] = gfx_fdata->quot[ro];
-			dev_vdbg(drv->dev, "Quot RO%d set to %d\n",
-				 ro, corner->quot[ro]);
-			corner->quot[ro] += cpr3_adjust_quot(ro_fac, vadj);
-			if (vadj != 0)
-				dev_vdbg(drv->dev, "Quot RO%d fine-tuning to %d for post-vadj=%d\n",
-					 ro, corner->quot[ro], vadj);
-		}
-
-		if (prev_fuse) {
-			int quot_scale_adjust;
-
-			freq_diff_mhz = fuse->max_freq - corner->corner.freq;
-			do_div(freq_diff_mhz, 1000000); /* now in MHz */
-
-			for (ro = 0; ro < CPR3_RO_COUNT; ro++) {
-				if (gfx_fdata->quot[ro] == 0)
-					continue;
-
-				scaling = cpr_calculate_scaling_raw(gfx_fdata->quot[ro] - prev_gfx_fdata->quot[ro],
-								    drv->dev,
-								    fdata, &corner->corner);
-				if (scaling < 0) {
-					dev_warn(drv->dev, "Error calculating scaling: %d\n", scaling);
-					return scaling;
-				}
-
-				quot_scale_adjust = scaling * freq_diff_mhz;
-				do_div(quot_scale_adjust, 1000);
-
-				corner->quot[ro] -= quot_scale_adjust;
-				if (quot_scale_adjust != 0)
-					dev_vdbg(drv->dev, "Quot RO%d fine-tuning by %d to %d for interpolation\n",
-						 ro, quot_scale_adjust, corner->quot[ro]);
-
-				/*
-				 * Make sure that we scale (up) monotonically.
-				 * P.S.: Fuse quots can never be descending.
-				 */
-				prev_quot = prev_corner->quot[ro];
-				if (corner->quot[ro] < prev_quot) {
-					dev_vdbg(drv->dev, "Monotonic increase forced: %d->%d\n",
-						 corner->quot[ro], prev_quot);
-					corner->quot[ro] = prev_quot;
-				}
-			}
-
-			corner->corner.uV = cpr_interpolate(&corner->corner,
-						     drv->vreg_step, fdata);
-		}
-
-		for (ro = 0; ro < CPR3_RO_COUNT; ro++) {
-			/* Negative fuse quotients are nonsense. */
-			if (corner->quot[ro] < 0)
-				return -EINVAL;
-
-			min_quotient = min(min_quotient,
-					   (u32)(corner->quot[ro]));
-		}
-
-		/* Fine-tune voltages (open-loop) based on fixed values */
-		corner->corner.uV += cdata[i].oloop_vadj;
-		dev_dbg(drv->dev, "Voltage fine-tuning to %d for post-vadj=%d\n",
-			 corner->corner.uV, cdata[i].oloop_vadj);
-
-		corner->corner.max_uV = fuse->max_uV;
-		corner->corner.min_uV = fuse->min_uV;
-		corner->corner.uV = clamp(corner->corner.uV, corner->corner.min_uV, corner->corner.max_uV);
-		dev_vdbg(drv->dev, "Clamped after interpolation: [%d %d %d]\n",
-			corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV);
-
-		/* Make sure that we scale monotonically here, too. */
-		if (corner->corner.uV < prev_corner->corner.uV)
-			corner->corner.uV = prev_corner->corner.uV;
-
-		corner->last_uV = corner->corner.uV;
-
-		/* Reduce the ceiling voltage if needed */
-		if (desc->reduce_to_corner_uV && corner->corner.uV < corner->corner.max_uV)
-			corner->corner.max_uV = corner->corner.uV;
-		else if (desc->reduce_to_fuse_uV && fuse->uV < corner->corner.max_uV)
-			corner->corner.max_uV = max(corner->corner.min_uV, fuse->uV);
-		dev_vdbg(drv->dev, "Clamped after interpolation: [%d %d %d]\n",
-			corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV);
-
-		corner->corner.min_uV = max(corner->corner.max_uV - fdata->range_uV,
-				     corner->corner.min_uV);
-
-		dev_vdbg(drv->dev, "Clamped after interpolation: [%d %d %d (%d)]\n",
-			corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV, fdata->range_uV);
-		/*
-		 * Adjust per-corner floor and ceiling voltages so that
-		 * they do not overlap the memory Array Power Mux (APM)
-		 * nor the Memory Accelerator (MEM-ACC) threshold voltages.
-		 */
-		if (desc->mem_acc_threshold)
-			cpr3_restrict_corner(corner, desc->mem_acc_threshold,
-					     0, drv->vreg_step);
-
-		prev_corner = corner;
-	}
-
-	/* Additional setup for CPRh only */
-	if (desc->cpr_type < CTRL_TYPE_CPRH)
-		return 0;
-
-	total_corners = thread->num_corners;
-	extra_corners = drv->extra_corners;
-
-	if (desc->mem_acc_threshold && extra_corners) {
-		/* Program the Memory Accelerator threshold corner to CPRh */
-		thread->corners[total_corners].corner.uV = desc->mem_acc_threshold;
-		thread->corners[total_corners].corner.min_uV = desc->mem_acc_threshold;
-		thread->corners[total_corners].corner.max_uV = desc->mem_acc_threshold;
-		thread->corners[total_corners].is_open_loop = true;
-
-		/*
-		 * We have calculated a mem-acc threshold for this clock plan:
-		 * make it available to external callers.
-		 */
-		thread->ext_data.mem_acc_threshold_uV = desc->mem_acc_threshold;
-
-		dev_dbg(drv->dev, "corner %d (MEMACC): [%d %d %d] Open-Loop\n",
-			total_corners, desc->mem_acc_threshold,
-			desc->mem_acc_threshold, desc->mem_acc_threshold);
-
-		total_corners++;
-		extra_corners--;
-	}
-
-	/*
-	 * If there are any extra corners left, it means that even though we
-	 * expect to fill in both APM and MEM-ACC crossovers, one couldn't
-	 * satisfy requirements, which means that the specified parameters
-	 * are wrong: in this case, inform the user and bail out, otherwise
-	 * if we go on writing the (invalid) table to the CPR-Hardened, the
-	 * hardware (in this case, the CPU) will surely freeze and crash.
-	 */
-	if (unlikely(extra_corners)) {
-		dev_err(drv->dev, "APM/MEM-ACC corners: bad parameters.\n");
-		return -EINVAL;
-	}
-	/* Reassign extra_corners, as we have to exclude delta_quot for them */
-	extra_corners = drv->extra_corners;
-
-	/* Program the GCNT before unmasking ring oscillator(s) */
-	for (i = 0; i < CPR3_RO_COUNT; i++) {
-		if (!(ring_osc_mask & BIT(i))) {
-			cpr_write(thread, CPR3_REG_GCNT(i), drv->gcnt);
-			dev_vdbg(drv->dev, "RO%d gcnt=%d\n", i, drv->gcnt);
-		}
-	}
-
-	/*
-	 * Unmask the ring oscillator(s) that we're going to use: it seems
-	 * to be mandatory to do this *before* sending the rest of the
-	 * CPRhardened specific configuration.
-	 */
-	dev_dbg(drv->dev, "Unmasking ring oscillators with mask 0x%x\n", ring_osc_mask);
-	cpr_write(thread, CPR3_REG_RO_MASK(tdesc->hw_tid), ring_osc_mask);
-
-	/* Setup minimum quotients for ring oscillators */
-	for (i = 0; i < CPR3_RO_COUNT; i++) {
-		u32 tgt_quot_reg = CPR3_REG_TARGET_QUOT(tdesc->hw_tid, i);
-		u32 tgt_quot_val = 0;
-
-		if (!(ring_osc_mask & BIT(i)))
-			tgt_quot_val = min_quotient;
-
-		cpr_write(thread, tgt_quot_reg, tgt_quot_val);
-		dev_vdbg(drv->dev, "Programmed min quotient %u for Ring Oscillator %d\n",
-			 tgt_quot_val, tgt_quot_reg);
-	}
-
-	/* On success, free cdata manually */
-	devm_kfree(drv->dev, cdata);
-	return 0;
-}
-
-/**
- * cpr3_init_parameters() - Initialize CPR global parameters
- * @drv: Main driver structure
- *
- * Initial "integrity" checks and setup for the thread-independent parameters.
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr3_init_parameters(struct cpr_drv *drv)
-{
-	const struct cpr_desc *desc = drv->desc;
-	struct clk *clk;
-
-
-	clk = devm_clk_get_optional(drv->dev, "bus");
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	clk_prepare_enable(clk);
-
-	clk = devm_clk_get_optional(drv->dev, "iface");
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	clk_prepare_enable(clk);
-
-	clk = devm_clk_get(drv->dev, "ref");
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	drv->ref_clk_khz = clk_get_rate(clk);
-	do_div(drv->ref_clk_khz, 1000);
-
-	clk_prepare_enable(clk);
-
-	if (desc->timer_cons_up > CPR3_THRESH_CONS_UP_MASK ||
-	    desc->timer_cons_down > CPR3_THRESH_CONS_DOWN_MASK ||
-	    desc->up_threshold > CPR3_THRESH_UP_THRESH_MASK ||
-	    desc->down_threshold > CPR3_THRESH_DOWN_THRESH_MASK ||
-	    desc->idle_clocks > CPR3_CPR_CTL_IDLE_CLOCKS_MASK ||
-	    desc->count_mode > CPR3_CPR_CTL_COUNT_MODE_MASK ||
-	    desc->count_repeat > CPR3_CPR_CTL_COUNT_REPEAT_MASK)
-		return -EINVAL;
-
-	dev_dbg(drv->dev, "up threshold = %u, down threshold = %u\n",
-		desc->up_threshold, desc->down_threshold);
-
-	return 0;
-}
-
-/*
- * Returns: Index of the initial corner or negative number for error.
- */
-static int cpr_find_initial_corner(struct device *dev, struct clk *cpu_clk,
-			    struct cpr_corner *corners, int num_corners)
-{
-	unsigned long rate;
-	struct cpr_corner *iter, *corner;
-	const struct cpr_corner *end;
-	unsigned int ret = 0;
-
-	if (!cpu_clk)
-		return -EINVAL;
-
-	end = &corners[num_corners - 1];
-	rate = clk_get_rate(cpu_clk);
-
-	/*
-	 * Some bootloaders set a CPU clock frequency that is not defined
-	 * in the OPP table. When running at an unlisted frequency,
-	 * cpufreq_online() will change to the OPP which has the lowest
-	 * frequency, at or above the unlisted frequency.
-	 * Since cpufreq_online() always "rounds up" in the case of an
-	 * unlisted frequency, this function always "rounds down" in case
-	 * of an unlisted frequency. That way, when cpufreq_online()
-	 * triggers the first ever call to cpr_set_performance_state(),
-	 * it will correctly determine the direction as UP.
-	 */
-	for (iter = corners; iter <= end; iter++) {
-		if (iter->corner.freq > rate)
-			break;
-		ret++;
-		if (iter->corner.freq == rate) {
-			corner = iter;
-			break;
-		}
-		if (iter->corner.freq < rate)
-			corner = iter;
-	}
-
-	if (!corner) {
-		dev_err(dev, "boot up corner not found\n");
-		ret = 0;
-	}
-
-	dev_dbg(dev, "boot up perf state: %u\n", ret);
-
-	return ret;
-}
-
-/**
- * cpr3_find_initial_corner() - Finds boot-up p-state and enables CPR
- * @thread: Structure holding CPR thread-specific parameters
- *
- * Differently from CPRv1, from CPRv3 onwards when we successfully find
- * the target boot-up performance state, we must refresh the HW
- * immediately to guarantee system stability and to avoid overheating
- * during the boot process, thing that would more likely happen without
- * this driver doing its job.
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr3_find_initial_corner(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	struct cpr_corner *corner;
-	int uV, idx;
-
-	idx = cpr_find_initial_corner(drv->dev, thread->cpu_clk,
-				      thread->corners,
-				      thread->num_corners);
-	if (idx < 0)
-		return idx;
-
-	cpr_ctl_disable(thread);
-
-	corner = &thread->corners[idx];
-	cpr_corner_restore(thread, corner);
-
-	uV = regulator_get_voltage(drv->vreg);
-	uV = clamp(uV, corner->corner.min_uV, corner->corner.max_uV);
-
-	corner->last_uV = uV;
-	if (!drv->last_uV)
-		drv->last_uV = uV;
-
-	cpr_commit_state(thread);
-	thread->enabled = true;
-	cpr_switch(drv);
-
-	return 0;
-}
-
-static const int msm8996_gfx_scaling_factor[][CPR3_RO_COUNT] = {
-	/* Common to all fuse corners */
-	{
-		0, 0, 0, 0, 0, 0, 2035, 1917,
-		1959, 2131, 2246, 2253, 0, 0, 0, 0,
-	},
-};
-
-static const struct cpr_thread_desc msm8996_gfx_thread_gfx = {
-	.controller_id = 0,
-	.hw_tid = 0,
-	.ro_scaling_factor = msm8996_gfx_scaling_factor,
-	.ro_avail_corners = ARRAY_SIZE(msm8996_gfx_scaling_factor),
-	.sensor_range_start = 0,
-	.sensor_range_end = 35, // 34?
-	.init_voltage_step = 10000,
-	.init_voltage_width = 5,
-	.step_quot_init_min = 10,
-	.step_quot_init_max = 13,
-	.num_fuse_corners = 4,
-	.fuse_corner_data = (struct gfx_fuse_corner_data[]){
-		/* fuse corner 0 */
-		{
-		.fcd = {
-			.ref_uV = 670000,
-			.max_uV = 670000,
-			.min_uV = 520000,
-			.range_uV = 70000,
-			.volt_oloop_adjust = -70000, /* 0 for rev 0, -30000 for rev 1-2 */
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-		},
-		.quot = {0, 0, 0, 0, 0, 0, 185, 179, 291, 299, 304, 319, 0, 0, 0, 0},
-		},
-		/* fuse corner 1 */
-		{
-		.fcd = {
-			.ref_uV = 745000,
-			.max_uV = 745000,
-			.min_uV = 520000,
-			.range_uV = 75000,
-			.volt_oloop_adjust = 0, /* 0 for rev 0, -30000 for rev 1-2 */
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-		},
-		.quot = {0, 0, 0, 0, 0, 0, 414, 392, 584, 576, 608, 612, 0, 0, 0, 0},
-		},
-		/* fuse corner 2 */
-		{
-		.fcd = {
-			.ref_uV = 905000,
-			.max_uV = 905000,
-			.min_uV = 520000,
-			.range_uV = 90000,
-			.volt_oloop_adjust = 0, /* 30000 for rev 0 */
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-		},
-		.quot = {0, 0, 0, 0, 0, 0, 577, 543, 798, 768, 823, 810, 0, 0, 0, 0, }
-		},
-		/* fuse corner 3 */
-		{
-		.fcd = {
-			.ref_uV = 1015000,
-			.max_uV = 1015000,
-			.min_uV = 520000,
-			.range_uV = 100000,
-			.volt_oloop_adjust = 0, /* -10000 for rev 0-2 */
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-		},
-		.quot = {0, 0, 0, 0, 0, 0, 771, 725, 984, 970, 1036, 1024, 0, 0, 0, 0, },
-		},
-	},
-
-};
-
-static const struct cpr_desc msm8996_gfx_cpr_desc = {
-	.cpr_type = CTRL_TYPE_CPR3,
-	.num_threads = 1,
-	.cpr_base_voltage = 400000,
-	.cpr_max_voltage = 1015000,
-	.timer_cons_up = 0,
-	.timer_cons_down = 2,
-	.up_threshold = 0,
-	.down_threshold = 2,
-	.idle_clocks = 15,
-	.count_mode = CPR3_CPR_CTL_COUNT_MODE_STAGGERED,
-	.gcnt_us = 1,
-	.vreg_step_fixed = 5000,
-	.reduce_to_corner_uV = true,
-	.threads = (const struct cpr_thread_desc *[]) {
-		&msm8996_gfx_thread_gfx,
-	},
-};
-
-static const struct acc_desc msm8996_gfx_acc_desc = {
-	// FIXME
-};
-
-static const struct cpr_acc_desc msm8996_gfx_cpr_acc_desc = {
-	.cpr_desc = &msm8996_gfx_cpr_desc,
-	.acc_desc = &msm8996_gfx_acc_desc,
-};
-
-static unsigned int cpr_get_performance_state(struct generic_pm_domain *genpd,
-					      struct dev_pm_opp *opp)
-{
-	return dev_pm_opp_get_level(opp);
-}
-
-static int cpr_power_off(struct generic_pm_domain *domain)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-
-	return cpr_disable(thread);
-}
-
-static int cpr_power_on(struct generic_pm_domain *domain)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-
-	return cpr_enable(thread);
-}
-
-static void cpr_pd_detach_dev(struct generic_pm_domain *domain,
-			      struct device *dev)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-	struct cpr_drv *drv = thread->drv;
-
-	mutex_lock(&drv->lock);
-
-	dev_dbg(drv->dev, "detach callback for: %s\n", dev_name(dev));
-	thread->attached_cpu_dev = NULL;
-
-	mutex_unlock(&drv->lock);
-}
-
-static int cpr_pd_attach_dev(struct generic_pm_domain *domain,
-			     struct device *dev)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-	struct cpr_drv *drv = thread->drv;
-	const struct acc_desc *acc_desc = drv->acc_desc;
-	bool cprh_opp_remove_table = false;
-	int ret = 0;
-
-	mutex_lock(&drv->lock);
-
-	dev_dbg(drv->dev, "attach callback for: %s\n", dev_name(dev));
-
-	/*
-	 * This driver only supports scaling voltage for a CPU cluster
-	 * where all CPUs in the cluster share a single regulator.
-	 * Therefore, save the struct device pointer only for the first
-	 * CPU device that gets attached. There is no need to do any
-	 * additional initialization when further CPUs get attached.
-	 * This is not an error condition.
-	 */
-	if (thread->attached_cpu_dev)
-		goto unlock;
-
-	/*
-	 * cpr_scale_voltage() requires the direction (if we are changing
-	 * to a higher or lower OPP). The first time
-	 * cpr_set_performance_state() is called, there is no previous
-	 * performance state defined. Therefore, we call
-	 * cpr_find_initial_corner() that gets the CPU clock frequency
-	 * set by the bootloader, so that we can determine the direction
-	 * the first time cpr_set_performance_state() is called.
-	 */
-	thread->cpu_clk = devm_clk_get(dev, NULL);
-	if (drv->desc->cpr_type < CTRL_TYPE_CPRH && IS_ERR(thread->cpu_clk)) {
-		ret = PTR_ERR(thread->cpu_clk);
-		if (ret != -EPROBE_DEFER)
-			dev_err(drv->dev, "could not get cpu clk: %d\n", ret);
-		goto unlock;
-	}
-	thread->attached_cpu_dev = dev;
-
-	/*
-	 * We are exporting the APM and MEM-ACC thresholds to the caller;
-	 * while APM is necessary in the CPU CPR case, MEM-ACC may not be,
-	 * depending on the SoC and on fuses.
-	 * Initialize both to an invalid value, so that the caller can check
-	 * if they got calculated or read from fuses in this driver.
-	 */
-	thread->ext_data.apm_threshold_uV = -1;
-	thread->ext_data.mem_acc_threshold_uV = -1;
-	dev_set_drvdata(thread->attached_cpu_dev, &thread->ext_data);
-
-	dev_dbg(drv->dev, "using cpu clk from: %s\n",
-		dev_name(thread->attached_cpu_dev));
-
-	/*
-	 * Everything related to (virtual) corners has to be initialized
-	 * here, when attaching to the power domain, since we need to know
-	 * the maximum frequency for each fuse corner, and this is only
-	 * available after the cpufreq driver has attached to us.
-	 * The reason for this is that we need to know the highest
-	 * frequency associated with each fuse corner.
-	 */
-	ret = dev_pm_opp_get_opp_count(&thread->pd.dev);
-	if (ret < 0) {
-		dev_err(drv->dev, "could not get OPP count\n");
-		thread->attached_cpu_dev = NULL;
-		goto unlock;
-	}
-	thread->num_corners = ret;
-	dev_dbg(drv->dev, "using %d corners", thread->num_corners);
-
-	thread->corners = devm_kcalloc(drv->dev,
-				       thread->num_corners +
-				       drv->extra_corners,
-				       sizeof(*thread->corners),
-				       GFP_KERNEL);
-	if (!thread->corners) {
-		ret = -ENOMEM;
-		goto unlock;
-	}
-
-	/*
-	 * If we are on CPR-Hardened we have to make sure that the attached
-	 * device has a OPP table installed, as we're going to modify it here
-	 * with our calculations based on qfprom values.
-	 */
-	if (drv->desc->cpr_type == CTRL_TYPE_CPRH) {
-		ret = dev_pm_opp_of_add_table(dev);
-		if (ret && ret != -EEXIST) {
-			dev_err(drv->dev, "Cannot add table: %d\n", ret);
-			goto unlock;
-		}
-		cprh_opp_remove_table = true;
-	}
-
-	ret = cpr3_corner_init(thread);
-	if (ret)
-		goto exit;
-
-	if (drv->desc->cpr_type < CTRL_TYPE_CPRH) {
-		ret = cpr3_find_initial_corner(thread);
-		if (ret)
-			goto exit;
-
-		if (acc_desc->config)
-			regmap_multi_reg_write(drv->tcsr, acc_desc->config,
-					       acc_desc->num_regs_per_fuse);
-
-		/* Enable ACC if required */
-		if (acc_desc->enable_mask)
-			regmap_update_bits(drv->tcsr, acc_desc->enable_reg,
-					   acc_desc->enable_mask,
-					   acc_desc->enable_mask);
-	}
-	dev_info(drv->dev, "thread %d initialized with %u OPPs\n",
-		 thread->id, thread->num_corners);
-exit:
-	/*
-	 * If we are on CPRh and we reached an error condition, we installed
-	 * the OPP table but we haven't done any setup on it, nor we ever will.
-	 * In order to leave a clean state, remove the table.
-	 */
-	if (ret && cprh_opp_remove_table)
-		dev_pm_opp_of_remove_table(thread->attached_cpu_dev);
-unlock:
-	mutex_unlock(&drv->lock);
-
-	return ret;
-}
-
-static int cpr3_gfx_debug_info_show(struct seq_file *s, void *unused)
-{
-	u32 ro_sel, ctl, irq_status, reg, quot;
-	struct cpr_thread *thread = s->private;
-	struct cpr_corner *corner = thread->corners;
-	struct fuse_corner *fuse = thread->fuse_corners;
-	unsigned int i;
-
-	const struct {
-		const char *name;
-		uint32_t mask;
-		uint8_t shift;
-	} result0_fields[] = {
-		{ "busy", 1, 0 },
-		{ "step_dn", 1, 1 },
-		{ "step_up", 1, 2 },
-		{ "error_steps", CPR3_RESULT0_ERROR_STEPS_MASK,
-				 CPR3_RESULT0_ERROR_STEPS_SHIFT },
-		{ "error", CPR3_RESULT0_ERROR_MASK, CPR3_RESULT0_ERROR_SHIFT },
-		{ "negative", 1, 20 },
-	}, result1_fields[] = {
-		{ "quot_min", CPR3_RESULT1_QUOT_MIN_MASK,
-			      CPR3_RESULT1_QUOT_MIN_SHIFT },
-		{ "quot_max", CPR3_RESULT1_QUOT_MAX_MASK,
-			      CPR3_RESULT1_QUOT_MAX_SHIFT },
-		{ "ro_min", CPR3_RESULT1_RO_MIN_MASK,
-			    CPR3_RESULT1_RO_MIN_SHIFT },
-		{ "ro_max", CPR3_RESULT1_RO_MAX_MASK,
-			    CPR3_RESULT1_RO_MAX_SHIFT },
-	}, result2_fields[] = {
-		{ "qout_step_min", CPR3_RESULT2_STEP_QUOT_MIN_MASK,
-				   CPR3_RESULT2_STEP_QUOT_MIN_SHIFT },
-		{ "qout_step_max", CPR3_RESULT2_STEP_QUOT_MAX_MASK,
-				   CPR3_RESULT2_STEP_QUOT_MAX_SHIFT },
-		{ "sensor_min", CPR3_RESULT2_SENSOR_MIN_MASK,
-				CPR3_RESULT2_SENSOR_MIN_SHIFT },
-		{ "sensor_max", CPR3_RESULT2_SENSOR_MAX_MASK,
-				CPR3_RESULT2_SENSOR_MAX_SHIFT },
-	};
-
-	if (thread->drv->desc->cpr_type < CTRL_TYPE_CPRH)
-		seq_printf(s, "current_volt = %d uV\n", thread->drv->last_uV);
-
-	irq_status = cpr_read(thread, CPR3_REG_IRQ_STATUS);
-	seq_printf(s, "irq_status = %#02X\n", irq_status);
-
-	ctl = cpr_read(thread, CPR3_REG_CPR_CTL);
-	seq_printf(s, "cpr_ctl = %#02X\n", ctl);
-
-	seq_printf(s, "thread %d - hw tid: %u - enabled: %d:\n",
-		   thread->id, thread->desc->hw_tid, thread->enabled);
-	seq_printf(s, "%d corners, derived from %d fuse corners\n",
-		   thread->num_corners, thread->desc->num_fuse_corners);
-
-	for (i = 0; i < thread->num_corners; i++, corner++)
-		seq_printf(s, "corner %d - uV=[%d %d %d] quot=%d freq=%lu\n",
-			   i, corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV,
-			   corner->quot[0], corner->corner.freq); // FIXME: print all quots
-
-	for (i = 0; i < thread->desc->num_fuse_corners; i++, fuse++)
-		seq_printf(s, "fuse %d - uV=[%d %d %d] quot=%d freq=%lu\n",
-			   i, fuse->min_uV, fuse->uV, fuse->max_uV,
-			   fuse->quot, corner ? corner->corner.freq : 0UL);
-
-	seq_printf(s, "requested voltage: %d uV\n", thread->corner ? thread->corner->last_uV : 0);
-
-	if (corner && corner->corner.fuse_corner) {
-		ro_sel = corner->corner.fuse_corner->ring_osc_idx;
-		quot = cpr_read(thread, CPR3_REG_TARGET_QUOT(i, ro_sel));
-		seq_printf(s, "quot_target (%u) = %#02X\n", ro_sel, quot);
-	}
-
-	reg = cpr_read(thread, CPR3_REG_RESULT0(i));
-	seq_printf(s, "cpr_result_0 = %#02X\n  [", reg);
-	for (i = 0; i < ARRAY_SIZE(result0_fields); i++)
-		seq_printf(s, "%s%s = %u",
-			   i ? ", " : "",
-			   result0_fields[i].name,
-			   (reg >> result0_fields[i].shift) &
-				result0_fields[i].mask);
-	seq_puts(s, "]\n");
-	reg = cpr_read(thread, CPR3_REG_RESULT1(i));
-	seq_printf(s, "cpr_result_1 = %#02X\n  [", reg);
-	for (i = 0; i < ARRAY_SIZE(result1_fields); i++)
-		seq_printf(s, "%s%s = %u",
-			   i ? ", " : "",
-			   result1_fields[i].name,
-			   (reg >> result1_fields[i].shift) &
-				result1_fields[i].mask);
-	seq_puts(s, "]\n");
-	reg = cpr_read(thread, CPR3_REG_RESULT2(i));
-	seq_printf(s, "cpr_result_2 = %#02X\n  [", reg);
-	for (i = 0; i < ARRAY_SIZE(result2_fields); i++)
-		seq_printf(s, "%s%s = %u",
-			   i ? ", " : "",
-			   result2_fields[i].name,
-			   (reg >> result2_fields[i].shift) &
-				result2_fields[i].mask);
-	seq_puts(s, "]\n");
-
-	return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(cpr3_gfx_debug_info);
-
-static void cpr3_debugfs_init(struct cpr_drv *drv)
-{
-	int i;
-
-	drv->debugfs = debugfs_create_dir("qcom_cpr3_gfx", NULL);
-
-	for (i = 0; i < drv->desc->num_threads; i++) {
-		char buf[50];
-
-		snprintf(buf, sizeof(buf), "thread%d", i);
-
-		debugfs_create_file(buf, 0444, drv->debugfs, &drv->threads[i],
-				    &cpr3_gfx_debug_info_fops);
-	}
-}
-
-/**
- * cpr_thread_init() - Initialize CPR thread related parameters
- * @drv: Main driver structure
- * @tid: Thread ID
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr_thread_init(struct cpr_drv *drv, int tid)
-{
-	const struct cpr_desc *desc = drv->desc;
-	const struct cpr_thread_desc *tdesc = desc->threads[tid];
-	struct cpr_thread *thread = &drv->threads[tid];
-	int ret;
-
-	if (tdesc->step_quot_init_min > CPR3_CPR_STEP_QUOT_MIN_MASK ||
-	    tdesc->step_quot_init_max > CPR3_CPR_STEP_QUOT_MAX_MASK)
-		return -EINVAL;
-
-	thread->id = tid;
-	thread->drv = drv;
-	thread->desc = tdesc;
-	thread->fuse_corners = devm_kcalloc(drv->dev,
-					    tdesc->num_fuse_corners +
-					    drv->extra_corners,
-					    sizeof(*thread->fuse_corners),
-					    GFP_KERNEL);
-	if (!thread->fuse_corners)
-		return -ENOMEM;
-
-	thread->cpr_fuses = cpr_get_fuses(drv->dev, tid,
-					  tdesc->num_fuse_corners);
-	if (IS_ERR(thread->cpr_fuses))
-		return PTR_ERR(thread->cpr_fuses);
-
-	ret = cpr_fuse_corner_init(thread);
-	if (ret)
-		return ret;
-
-	thread->pd.name = devm_kasprintf(drv->dev, GFP_KERNEL,
-					 "%s_thread%d",
-					 drv->dev->of_node->full_name,
-					 thread->id);
-	if (!thread->pd.name)
-		return -EINVAL;
-
-	thread->pd.power_off = cpr_power_off;
-	thread->pd.power_on = cpr_power_on;
-	thread->pd.opp_to_performance_state = cpr_get_performance_state;
-	thread->pd.attach_dev = cpr_pd_attach_dev;
-	thread->pd.detach_dev = cpr_pd_detach_dev;
-
-	/* CPR-Hardened performance states are managed in firmware */
-	if (desc->cpr_type == CTRL_TYPE_CPRH) {
-		thread->pd.set_performance_state = cprh_dummy_set_performance_state;
-	} else {
-		thread->pd.set_performance_state = cpr_set_performance_state;
-	}
-
-	/* Anything later than CPR1 must be always-on for now */
-	thread->pd.flags = GENPD_FLAG_ALWAYS_ON;
-
-	drv->cell_data.domains[tid] = &thread->pd;
-
-	ret = pm_genpd_init(&thread->pd, NULL, false);
-	if (ret)
-		return ret;
-
-	/* On CPRhardened, the interrupts are managed in firmware */
-	if (desc->cpr_type < CTRL_TYPE_CPRH) {
-		INIT_WORK(&thread->restart_work, cpr_restart_worker);
-
-		ret = devm_request_threaded_irq(drv->dev, drv->irq,
-						NULL, cpr_irq_handler,
-						IRQF_SHARED |
-						IRQF_ONESHOT |
-						IRQF_TRIGGER_RISING,
-						"cpr", thread);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-/**
- * cpr3_resources_init() - Initialize resources used by this driver
- * @pdev: Platform device
- * @drv:  Main driver structure
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr3_resources_init(struct platform_device *pdev,
-			       struct cpr_drv *drv)
-{
-	const struct cpr_desc *desc = drv->desc;
-	struct cpr_thread *threads = drv->threads;
-	unsigned int i;
-	u8 cid_mask = 0;
-
-	/*
-	 * Here, we are accounting for the following usecases:
-	 * - One controller
-	 *   - One or multiple threads on the same iospace
-	 *
-	 * - Multiple controllers
-	 *   - Each controller has its own iospace and each
-	 *     may have one or multiple threads in their
-	 *     parent controller's iospace
-	 *
-	 * Then, to avoid complicating the code for no reason,
-	 * this also needs a mandatory order in the list of
-	 * threads which implies that all of them from the same
-	 * controllers are specified sequentially. As an example:
-	 *
-	 *      C0-T0, C0-T1...C0-Tn, C1-T0, C1-T1...C1-Tn
-	 */
-	for (i = 0; i < desc->num_threads; i++) {
-		u8 cid = desc->threads[i]->controller_id;
-
-		if (cid_mask & BIT(cid)) {
-			if (desc->threads[i - 1]->controller_id != cid) {
-				dev_err(drv->dev, "Bad threads order. Please fix!\n");
-				return -EINVAL;
-			}
-			threads[i].base = threads[i - 1].base;
-			continue;
-		}
-		threads[i].base = devm_platform_ioremap_resource(pdev, cid);
-		if (IS_ERR(threads[i].base))
-			return PTR_ERR(threads[i].base);
-		cid_mask |= BIT(cid);
-	}
-	return 0;
-}
-
-static int cpr_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct cpr_drv *drv;
-	const struct cpr_desc *desc;
-	const struct cpr_acc_desc *data;
-	struct device_node *np;
-	unsigned int i;
-	int ret;
-
-	data = of_device_get_match_data(dev);
-	if (!data || !data->cpr_desc)
-		return -EINVAL;
-
-	desc = data->cpr_desc;
-
-
-	/* CPRh disallows MEM-ACC access from the HLOS */
-	if (!data->acc_desc && desc->cpr_type < CTRL_TYPE_CPRH)
-		return -EINVAL;
-
-	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
-	if (!drv)
-		return -ENOMEM;
-
-	drv->dev = dev;
-	drv->desc = desc;
-	drv->threads = devm_kcalloc(dev, desc->num_threads,
-				    sizeof(*drv->threads), GFP_KERNEL);
-	if (!drv->threads)
-		return -ENOMEM;
-
-	drv->cell_data.num_domains = desc->num_threads;
-	drv->cell_data.domains = devm_kcalloc(drv->dev,
-					      drv->cell_data.num_domains,
-					      sizeof(*drv->cell_data.domains),
-					      GFP_KERNEL);
-	if (!drv->cell_data.domains)
-		return -ENOMEM;
-
-	if (data->acc_desc)
-		drv->acc_desc = data->acc_desc;
-
-	mutex_init(&drv->lock);
-
-	if (desc->cpr_type < CTRL_TYPE_CPRH) {
-		np = of_parse_phandle(dev->of_node, "acc-syscon", 0);
-		if (!np)
-			return -ENODEV;
-
-		drv->tcsr = syscon_node_to_regmap(np);
-		of_node_put(np);
-		if (IS_ERR(drv->tcsr))
-			return PTR_ERR(drv->tcsr);
-	}
-
-	ret = cpr3_resources_init(pdev, drv);
-	if (ret)
-		return ret;
-
-	drv->irq = platform_get_irq_optional(pdev, 0);
-	if ((desc->cpr_type != CTRL_TYPE_CPRH) && (drv->irq < 0))
-		return -EINVAL;
-
-	/* On CPRhardened, vreg access it not allowed */
-	drv->vreg = devm_regulator_get_optional(dev, "vdd");
-	if (desc->cpr_type != CTRL_TYPE_CPRH && IS_ERR(drv->vreg))
-		return PTR_ERR(drv->vreg);
-
-	/*
-	 * On at least CPRhardened, vreg is unaccessible and there is no
-	 * way to read linear step from that regulator, hence it is hardcoded
-	 * in the driver;
-	 * When the vreg_step is not declared in the cpr data (or is zero),
-	 * then having access to the vreg regulator is mandatory, as this
-	 * will be retrieved through the regulator API.
-	 */
-	if (desc->vreg_step_fixed)
-		drv->vreg_step = desc->vreg_step_fixed;
-	else
-		drv->vreg_step = regulator_get_linear_step(drv->vreg);
-
-	if (!drv->vreg_step)
-		return -EINVAL;
-
-	/*
-	 * Initialize fuse corners, since it simply depends
-	 * on data in efuses.
-	 * Everything related to (virtual) corners has to be
-	 * initialized after attaching to the power domain,
-	 * since it depends on the CPU's OPP table.
-	 */
-	ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &drv->fusing_rev);
-	if (ret)
-		return ret;
-
-	dev_dbg(dev, "Fusing revision %d\n", drv->fusing_rev);
-
-	ret = nvmem_cell_read_variable_le_u32(dev, "cpr_speed_bin", &drv->speed_bin);
-	if (ret)
-		return ret;
-
-	dev_dbg(dev, "Speed bin %d\n", drv->speed_bin);
-
-	/* Initialize all threads */
-	for (i = 0; i < desc->num_threads; i++) {
-		ret = cpr_thread_init(drv, i);
-		if (ret)
-			return ret;
-	}
-
-	/* Initialize global parameters */
-	ret = cpr3_init_parameters(drv);
-	if (ret)
-		return ret;
-
-	/* Write initial configuration on all threads */
-	for (i = 0; i < desc->num_threads; i++) {
-		ret = cpr_configure(&drv->threads[i]);
-		if (ret)
-			return ret;
-	}
-
-	ret = of_genpd_add_provider_onecell(dev->of_node, &drv->cell_data);
-	if (ret)
-		return ret;
-
-	platform_set_drvdata(pdev, drv);
-	cpr3_debugfs_init(drv);
-
-	return 0;
-}
-
-static int cpr_remove(struct platform_device *pdev)
-{
-	struct cpr_drv *drv = platform_get_drvdata(pdev);
-	int i;
-
-	of_genpd_del_provider(pdev->dev.of_node);
-
-	for (i = 0; i < drv->desc->num_threads; i++) {
-		cpr_ctl_disable(&drv->threads[i]);
-		cpr_irq_set(&drv->threads[i], 0);
-		pm_genpd_remove(&drv->threads[i].pd);
-	}
-
-	debugfs_remove_recursive(drv->debugfs);
-
-	return 0;
-}
-
-static const struct of_device_id cpr3_match_table[] = {
-	{ .compatible = "qcom,msm8996-gfx-cpr3", .data = &msm8996_gfx_cpr_acc_desc },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, cpr3_match_table);
-
-static struct platform_driver cpr3_driver = {
-	.probe		= cpr_probe,
-	.remove		= cpr_remove,
-	.driver		= {
-		.name	= "qcom-cpr3-gfx",
-		.of_match_table = cpr3_match_table,
-	},
-};
-static int __init cpr3_init(void)
-{
-	return platform_driver_register(&cpr3_driver);
-}
-arch_initcall(cpr3_init);
-
-static void __exit cpr3_exit(void)
-{
-	platform_driver_unregister(&cpr3_driver);
-}
-module_exit(cpr3_exit);
-
-MODULE_DESCRIPTION("GFX Core Power Reduction (CPR) v3/v4 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/kernel/drivers/soc/qcom/cpr3.c b/kernel/drivers/soc/qcom/cpr3.c
deleted file mode 100644
index 84e1f5e28ac7..000000000000
--- a/kernel/drivers/soc/qcom/cpr3.c
+++ /dev/null
@@ -1,2970 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
- * Copyright (c) 2019 Linaro Limited
- * Copyright (c) 2021, AngeloGioacchino Del Regno
- *                     <angelogioacchino.delregno@somainline.org>
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/debugfs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_opp.h>
-#include <linux/interrupt.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regulator/consumer.h>
-#include <linux/workqueue.h>
-#include <linux/clk.h>
-#include <linux/nvmem-consumer.h>
-#include <soc/qcom/cpr.h>
-#include "cpr-common.h"
-
-#define CPR3_RO_COUNT				16
-#define CPR3_RO_MASK				GENMASK(CPR3_RO_COUNT - 1, 0)
-
-/* CPR3 registers */
-#define CPR3_REG_CPR_VERSION			0x0
-#define CPRH_CPR_VERSION_4P5			0x40050000
-
-#define CPR3_REG_CPR_CTL			0x4
-#define CPR3_CPR_CTL_LOOP_EN_MASK		BIT(0)
-#define CPR3_CPR_CTL_IDLE_CLOCKS_MASK		GENMASK(5, 1)
-#define CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT		1
-#define CPR3_CPR_CTL_COUNT_MODE_MASK		GENMASK(7, 6)
-#define CPR3_CPR_CTL_COUNT_MODE_SHIFT		6
-#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN	0
-#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MAX	1
-#define CPR3_CPR_CTL_COUNT_MODE_STAGGERED	2
-#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE	3
-#define CPR3_CPR_CTL_COUNT_REPEAT_MASK		GENMASK(31, 9)
-#define CPR3_CPR_CTL_COUNT_REPEAT_SHIFT		9
-
-#define CPR3_REG_CPR_STATUS			0x8
-#define CPR3_CPR_STATUS_BUSY_MASK		BIT(0)
-
-/*
- * This register is not present on controllers that support HW closed-loop
- * except CPR4 APSS controller.
- */
-#define CPR3_REG_CPR_TIMER_AUTO_CONT		0xC
-
-#define CPR3_REG_CPR_STEP_QUOT			0x14
-#define CPR3_CPR_STEP_QUOT_MIN_MASK		GENMASK(5, 0)
-#define CPR3_CPR_STEP_QUOT_MIN_SHIFT		0
-#define CPR3_CPR_STEP_QUOT_MAX_MASK		GENMASK(11, 6)
-#define CPR3_CPR_STEP_QUOT_MAX_SHIFT		6
-#define CPRH_DELTA_QUOT_STEP_FACTOR		4
-
-#define CPR3_REG_GCNT(ro)			(0xA0 + 0x4 * (ro))
-#define CPR3_REG_SENSOR_OWNER(sensor)		(0x200 + 0x4 * (sensor))
-
-#define CPR3_REG_CONT_CMD			0x800
-#define CPR3_CONT_CMD_ACK			0x1
-#define CPR3_CONT_CMD_NACK			0x0
-
-#define CPR3_REG_THRESH(thread)			(0x808 + 0x440 * (thread))
-#define CPR3_THRESH_CONS_DOWN_MASK		GENMASK(3, 0)
-#define CPR3_THRESH_CONS_DOWN_SHIFT		0
-#define CPR3_THRESH_CONS_UP_MASK		GENMASK(7, 4)
-#define CPR3_THRESH_CONS_UP_SHIFT		4
-#define CPR3_THRESH_DOWN_THRESH_MASK		GENMASK(12, 8)
-#define CPR3_THRESH_DOWN_THRESH_SHIFT		8
-#define CPR3_THRESH_UP_THRESH_MASK		GENMASK(17, 13)
-#define CPR3_THRESH_UP_THRESH_SHIFT		13
-
-#define CPR3_REG_RO_MASK(thread)		(0x80C + 0x440 * (thread))
-
-#define CPR3_REG_RESULT0(thread)		(0x810 + 0x440 * (thread))
-#define CPR3_RESULT0_BUSY_MASK			BIT(0)
-#define CPR3_RESULT0_STEP_DN_MASK		BIT(1)
-#define CPR3_RESULT0_STEP_UP_MASK		BIT(2)
-#define CPR3_RESULT0_ERROR_STEPS_MASK		GENMASK(7, 3)
-#define CPR3_RESULT0_ERROR_STEPS_SHIFT		3
-#define CPR3_RESULT0_ERROR_MASK			GENMASK(19, 8)
-#define CPR3_RESULT0_ERROR_SHIFT		8
-
-#define CPR3_REG_RESULT1(thread)		(0x814 + 0x440 * (thread))
-#define CPR3_RESULT1_QUOT_MIN_MASK		GENMASK(11, 0)
-#define CPR3_RESULT1_QUOT_MIN_SHIFT		0
-#define CPR3_RESULT1_QUOT_MAX_MASK		GENMASK(23, 12)
-#define CPR3_RESULT1_QUOT_MAX_SHIFT		12
-#define CPR3_RESULT1_RO_MIN_MASK		GENMASK(27, 24)
-#define CPR3_RESULT1_RO_MIN_SHIFT		24
-#define CPR3_RESULT1_RO_MAX_MASK		GENMASK(31, 28)
-#define CPR3_RESULT1_RO_MAX_SHIFT		28
-
-#define CPR3_REG_RESULT2(thread)		(0x818 + 0x440 * (thread))
-#define CPR3_RESULT2_STEP_QUOT_MIN_MASK		GENMASK(5, 0)
-#define CPR3_RESULT2_STEP_QUOT_MIN_SHIFT	0
-#define CPR3_RESULT2_STEP_QUOT_MAX_MASK		GENMASK(11, 6)
-#define CPR3_RESULT2_STEP_QUOT_MAX_SHIFT	6
-#define CPR3_RESULT2_SENSOR_MIN_MASK		GENMASK(23, 16)
-#define CPR3_RESULT2_SENSOR_MIN_SHIFT		16
-#define CPR3_RESULT2_SENSOR_MAX_MASK		GENMASK(31, 24)
-#define CPR3_RESULT2_SENSOR_MAX_SHIFT		24
-
-#define CPR3_REG_IRQ_EN				0x81C
-#define CPR3_REG_IRQ_CLEAR			0x820
-#define CPR3_REG_IRQ_STATUS			0x824
-#define CPR3_IRQ_UP				BIT(3)
-#define CPR3_IRQ_MID				BIT(2)
-#define CPR3_IRQ_DOWN				BIT(1)
-#define CPR3_IRQ_ALL				(CPR3_IRQ_UP | CPR3_IRQ_MID | CPR3_IRQ_DOWN)
-
-#define CPR3_REG_TARGET_QUOT(thread, ro)	(0x840 + 0x440 * (thread) + 0x4 * (ro))
-
-/* Registers found only on controllers that support HW closed-loop. */
-#define CPR3_REG_PD_THROTTLE			0xE8
-
-#define CPR3_REG_HW_CLOSED_LOOP_DISABLED	0x3000
-#define CPR3_REG_CPR_TIMER_MID_CONT		0x3004
-#define CPR3_REG_CPR_TIMER_UP_DN_CONT		0x3008
-
-/* CPR4 controller specific registers and bit definitions */
-#define CPR4_REG_CPR_TIMER_CLAMP			0x10
-#define CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN	BIT(27)
-
-#define CPR4_REG_MISC				0x700
-#define CPR4_MISC_RESET_STEP_QUOT_LOOP_EN	BIT(2)
-#define CPR4_MISC_THREAD_HAS_ALWAYS_VOTE_EN	BIT(3)
-
-#define CPR4_REG_SAW_ERROR_STEP_LIMIT		0x7A4
-#define CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK	GENMASK(4, 0)
-#define CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT	0
-#define CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK	GENMASK(9, 5)
-#define CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT	5
-
-#define CPR4_REG_MARGIN_TEMP_CORE_TIMERS			0x7A8
-#define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK	GENMASK(28, 18)
-#define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHFT	18
-
-#define CPR4_REG_MARGIN_ADJ_CTL				0x7F8
-#define CPR4_MARGIN_ADJ_HW_CLOSED_LOOP_EN		BIT(4)
-#define CPR4_MARGIN_ADJ_PER_RO_KV_MARGIN_EN		BIT(7)
-#define CPR4_MARGIN_ADJ_PMIC_STEP_SIZE_MASK		GENMASK(16, 12)
-#define CPR4_MARGIN_ADJ_PMIC_STEP_SIZE_SHIFT		12
-#define CPR4_MARGIN_ADJ_KV_MARGIN_ADJ_STEP_QUOT_MASK	GENMASK(31, 26)
-#define CPR4_MARGIN_ADJ_KV_MARGIN_ADJ_STEP_QUOT_SHIFT	26
-
-#define CPR4_REG_CPR_MASK_THREAD(thread)		(0x80C + 0x440 * (thread))
-#define CPR4_CPR_MASK_THREAD_DISABLE_THREAD		BIT(31)
-#define CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK	GENMASK(15, 0)
-
-/* CPRh controller specific registers and bit definitions */
-#define __CPRH_REG_CORNER(rbase, tbase, tid, cnum) (rbase + (tbase * tid) + (0x4 * cnum))
-#define CPRH_REG_CORNER(d, t, c) __CPRH_REG_CORNER(d->reg_corner, d->reg_corner_tid, t, c)
-
-#define CPRH_CTL_OSM_ENABLED			BIT(0)
-#define CPRH_CTL_BASE_VOLTAGE_MASK		GENMASK(10, 1)
-#define CPRH_CTL_BASE_VOLTAGE_SHIFT		1
-#define CPRH_CTL_MODE_SWITCH_DELAY_MASK		GENMASK(24, 17)
-#define CPRH_CTL_MODE_SWITCH_DELAY_SHIFT	17
-#define CPRH_CTL_VOLTAGE_MULTIPLIER_MASK	GENMASK(28, 25)
-#define CPRH_CTL_VOLTAGE_MULTIPLIER_SHIFT	25
-
-#define CPRH_CORNER_INIT_VOLTAGE_MASK		GENMASK(7, 0)
-#define CPRH_CORNER_INIT_VOLTAGE_SHIFT		0
-#define CPRH_CORNER_FLOOR_VOLTAGE_MASK		GENMASK(15, 8)
-#define CPRH_CORNER_FLOOR_VOLTAGE_SHIFT		8
-#define CPRH_CORNER_QUOT_DELTA_MASK		GENMASK(24, 16)
-#define CPRH_CORNER_QUOT_DELTA_SHIFT		16
-#define CPRH_CORNER_RO_SEL_MASK			GENMASK(28, 25)
-#define CPRH_CORNER_RO_SEL_SHIFT		25
-#define CPRH_CORNER_CPR_CL_DISABLE		BIT(29)
-
-#define CPRH_CORNER_INIT_VOLTAGE_MAX_VALUE	255
-#define CPRH_CORNER_FLOOR_VOLTAGE_MAX_VALUE	255
-#define CPRH_CORNER_QUOT_DELTA_MAX_VALUE	511
-
-enum cpr_type {
-	CTRL_TYPE_CPR3,
-	CTRL_TYPE_CPR4,
-	CTRL_TYPE_CPRH,
-	CTRL_TYPE_MAX,
-};
-
-struct cpr_corner {
-	struct corner corner;
-	int last_uV;
-	int quot_adjust;
-	bool is_open_loop;
-};
-
-/*
- * struct cpr_thread_desc - CPR Thread-specific parameters
- *
- * @controller_id:      Identifier of the CPR controller expected by the HW
- * @ro_scaling_factor:  Scaling factor for each ring oscillator entry
- * @hw_tid:             Identifier of the CPR thread expected by the HW
- * @init_voltage_step:  Voltage in uV for number of steps read from fuse array
- * @init_voltage_width: Bit-width of the voltage read from the fuse array
- * @sensor_range_start: First sensor ID used by a thread
- * @sensor_range_end:   Last sensor ID used by a thread
- * @num_fuse_corners:   Number of valid entries in fuse_corner_data
- * @step_quot_init_min: Minimum achievable step quotient for this corner
- * @step_quot_init_max: Maximum achievable step quotient for this corner
- * @fuse_corner_data:   Parameters for calculation of each fuse corner
- */
-struct cpr_thread_desc {
-	u8		controller_id;
-	u8		hw_tid;
-	const int	(*ro_scaling_factor)[CPR3_RO_COUNT];
-	int		ro_avail_corners;
-	int		init_voltage_step;
-	int		init_voltage_width;
-	u8		sensor_range_start;
-	u8		sensor_range_end;
-	u8		step_quot_init_min;
-	u8		step_quot_init_max;
-	unsigned int	num_fuse_corners;
-	struct fuse_corner_data *fuse_corner_data;
-};
-
-/*
- * struct cpr_desc - Driver instance-wide CPR parameters
- *
- * @cpr_type:              Type (base version) of the CPR controller
- * @num_threads:           Max. number of threads supported by this controller
- * @timer_delay_us:        Loop delay time in uS
- * @timer_updn_delay_us:   Voltage after-up/before-down delay time in uS
- * @timer_cons_up:         Wait between consecutive up requests in uS
- * @timer_cons_down:       Wait between consecutive down requests in uS
- * @up_threshold:          Generic corner up threshold
- * @down_threshold:        Generic corner down threshold
- * @idle_clocks:           CPR Sensor: idle timer in cpr clocks unit
- * @count_mode:            CPR Sensor: counting mode
- * @count_repeat:          CPR Sensor: number of times to repeat reading
- * @gcnt_us:               CPR measurement interval in uS
- * @vreg_step_fixed:       Regulator voltage per step (if vreg unusable)
- * @vreg_step_up_limit:    Num. of steps up at once before re-measuring sensors
- * @vreg_step_down_limit:  Num. of steps dn at once before re-measuring sensors
- * @vdd_settle_time_us:    Settling timer to account for one VDD supply step
- * @corner_settle_time_us: Settle time for corner switch request
- * @mem_acc_threshold:     Memory Accelerator (MEM-ACC) voltage threshold
- * @apm_threshold:         Array Power Mux (APM) voltage threshold
- * @apm_crossover:         Array Power Mux (APM) corner crossover voltage
- * @apm_hysteresis:        Hysteresis for APM V-threshold related calculations
- * @cpr_base_voltage:      Safety: Absolute minimum voltage (uV) on this CPR
- * @cpr_max_voltage:       Safety: Absolute maximum voltage (uV) on this CPR
- * @pd_throttle_val:       CPR Power Domain throttle during voltage switch
- * @threads:               Array containing "CPR Thread" specific parameters
- * @reduce_to_fuse_uV:     Reduce corner max volts (if higher) to fuse ceiling
- * @reduce_to_corner_uV:   Reduce corner max volts (if higher) to corner ceil.
- * @hw_closed_loop_en:     Enable CPR HW Closed-Loop voltage auto-adjustment
- */
-struct cpr_desc {
-	enum cpr_type		cpr_type;
-	unsigned int		num_threads;
-	unsigned int		timer_delay_us;
-	u8			timer_updn_delay_us;
-	u8			timer_cons_up;
-	u8			timer_cons_down;
-	u8			up_threshold;
-	u8			down_threshold;
-	u8			idle_clocks;
-	u8			count_mode;
-	u8			count_repeat;
-	u8			gcnt_us;
-	u16			vreg_step_fixed;
-	u8			vreg_step_up_limit;
-	u8			vreg_step_down_limit;
-	u8			vdd_settle_time_us;
-	u8			corner_settle_time_us;
-	int			mem_acc_threshold;
-	int			apm_threshold;
-	int			apm_crossover;
-	int			apm_hysteresis;
-	u32			cpr_base_voltage;
-	u32			cpr_max_voltage;
-	u32			pd_throttle_val;
-
-	const struct cpr_thread_desc **threads;
-	bool reduce_to_fuse_uV;
-	bool reduce_to_corner_uV;
-	bool hw_closed_loop_en;
-};
-
-struct cpr_drv;
-struct cpr_thread {
-	int			num_corners;
-	int			id;
-	bool			enabled;
-	void __iomem		*base;
-	struct clk		*cpu_clk;
-	struct cpr_corner	*corner;
-	struct cpr_corner	*corners;
-	struct fuse_corner	*fuse_corners;
-	struct cpr_drv		*drv;
-	struct cpr_ext_data	ext_data;
-	struct generic_pm_domain pd;
-	struct device		*attached_cpu_dev;
-	struct work_struct	restart_work;
-	bool			restarting;
-
-	const struct cpr_fuse	*cpr_fuses;
-	const struct cpr_thread_desc *desc;
-};
-
-struct cpr_drv {
-	int			irq;
-	unsigned int		ref_clk_khz;
-	struct device		*dev;
-	struct mutex		lock;
-	struct regulator	*vreg;
-	struct regmap		*tcsr;
-	u32			gcnt;
-	u32			speed_bin;
-	u32			fusing_rev;
-	u32			last_uV;
-	u32			cpr_hw_rev;
-	u32			reg_corner;
-	u32			reg_corner_tid;
-	u32			reg_ctl;
-	u32			reg_status;
-	int			fuse_level_set;
-	int			extra_corners;
-	unsigned int		vreg_step;
-	bool			enabled;
-
-	struct cpr_thread	*threads;
-	struct genpd_onecell_data cell_data;
-
-	const struct cpr_desc	*desc;
-	const struct acc_desc	*acc_desc;
-	struct dentry		*debugfs;
-};
-
-/**
- * cpr_get_ro_factor() - Get fuse corner ring oscillator factor
- * @tdesc:  CPR Thread-specific parameters
- * @fnum:   Fuse corner
- * @ro_idx: Ring Oscillator fuse number
- *
- * Not all threads have different scaling factors for each
- * Fuse Corner: if the RO factors are the same for all corners,
- * then only one is specified, instead of uselessly repeating
- * the same array for FC-times.
- * This function checks for the same and gives back the right
- * factor for the requested ring oscillator.
- *
- * Return: Ring oscillator factor
- */
-static int cpr_get_ro_factor(const struct cpr_thread_desc *tdesc,
-			     int fnum, int ro_idx)
-{
-	int ro_fnum;
-
-	if (tdesc->ro_avail_corners == tdesc->num_fuse_corners)
-		ro_fnum = fnum;
-	else
-		ro_fnum = 0;
-
-	return tdesc->ro_scaling_factor[ro_fnum][ro_idx];
-}
-
-static void cpr_write(struct cpr_thread *thread, u32 offset, u32 value)
-{
-	writel(value, thread->base + offset);
-}
-
-static u32 cpr_read(struct cpr_thread *thread, u32 offset)
-{
-	return readl(thread->base + offset);
-}
-
-static void
-cpr_masked_write(struct cpr_thread *thread, u32 offset, u32 mask, u32 value)
-{
-	u32 val;
-
-	val = readl(thread->base + offset);
-	val &= ~mask;
-	val |= value & mask;
-	writel(val, thread->base + offset);
-}
-
-static void cpr_irq_clr(struct cpr_thread *thread)
-{
-	cpr_write(thread, CPR3_REG_IRQ_CLEAR, CPR3_IRQ_ALL);
-}
-
-static void cpr_irq_clr_nack(struct cpr_thread *thread)
-{
-	cpr_irq_clr(thread);
-	cpr_write(thread, CPR3_REG_CONT_CMD, CPR3_CONT_CMD_NACK);
-}
-
-static void cpr_irq_clr_ack(struct cpr_thread *thread)
-{
-	cpr_irq_clr(thread);
-	cpr_write(thread, CPR3_REG_CONT_CMD, CPR3_CONT_CMD_ACK);
-}
-
-static void cpr_irq_set(struct cpr_thread *thread, u32 int_bits)
-{
-	/* On CPR-hardened, interrupts are managed by and on firmware */
-	if (thread->drv->desc->cpr_type == CTRL_TYPE_CPRH)
-		return;
-
-	cpr_write(thread, CPR3_REG_IRQ_EN, int_bits);
-}
-
-/**
- * cpr_ctl_enable() - Enable CPR thread
- * @thread:     Structure holding CPR thread-specific parameters
- */
-static void cpr_ctl_enable(struct cpr_thread *thread)
-{
-	if (thread->drv->enabled && !thread->restarting) {
-		cpr_masked_write(thread, CPR3_REG_CPR_CTL,
-				 CPR3_CPR_CTL_LOOP_EN_MASK,
-				 CPR3_CPR_CTL_LOOP_EN_MASK);
-	}
-}
-
-/**
- * cpr_ctl_disable() - Disable CPR thread
- * @thread:     Structure holding CPR thread-specific parameters
- */
-static void cpr_ctl_disable(struct cpr_thread *thread)
-{
-	const struct cpr_desc *desc = thread->drv->desc;
-
-	if (desc->cpr_type != CTRL_TYPE_CPRH) {
-		cpr_irq_set(thread, 0);
-		cpr_irq_clr(thread);
-	}
-
-	cpr_masked_write(thread, CPR3_REG_CPR_CTL,
-			 CPR3_CPR_CTL_LOOP_EN_MASK, 0);
-}
-
-/**
- * cpr_ctl_is_enabled() - Check if thread is enabled
- * @thread:     Structure holding CPR thread-specific parameters
- *
- * Return: true if the CPR is enabled, false if it is disabled.
- */
-static bool cpr_ctl_is_enabled(struct cpr_thread *thread)
-{
-	u32 reg_val;
-
-	reg_val = cpr_read(thread, CPR3_REG_CPR_CTL);
-	return reg_val & CPR3_CPR_CTL_LOOP_EN_MASK;
-}
-
-/**
- * cpr_check_any_thread_busy() - Check if HW is done processing
- * @thread:     Structure holding CPR thread-specific parameters
- *
- * Return: true if the CPR is busy, false if it is ready.
- */
-static bool cpr_check_any_thread_busy(struct cpr_thread *thread)
-{
-	int i;
-
-	for (i = 0; i < thread->drv->desc->num_threads; i++)
-		if (cpr_read(thread, CPR3_REG_RESULT0(i)) &
-		    CPR3_RESULT0_BUSY_MASK)
-			return true;
-
-	return false;
-}
-
-static void cpr_restart_worker(struct work_struct *work)
-{
-	struct cpr_thread *thread = container_of(work, struct cpr_thread,
-						 restart_work);
-	struct cpr_drv *drv = thread->drv;
-	int i;
-
-	mutex_lock(&drv->lock);
-
-	thread->restarting = true;
-	cpr_ctl_disable(thread);
-	disable_irq(drv->irq);
-
-	mutex_unlock(&drv->lock);
-
-	for (i = 0; i < 20; i++) {
-		u32 cpr_status = cpr_read(thread, CPR3_REG_CPR_STATUS);
-		u32 ctl = cpr_read(thread, CPR3_REG_CPR_CTL);
-
-		if ((cpr_status & CPR3_CPR_STATUS_BUSY_MASK) &&
-		   !(ctl & CPR3_CPR_CTL_LOOP_EN_MASK))
-			break;
-
-		udelay(10);
-	}
-
-	cpr_irq_clr(thread);
-
-	for (i = 0; i < 20; i++) {
-		u32 status = cpr_read(thread, CPR3_REG_IRQ_STATUS);
-
-		if (!(status & CPR3_IRQ_ALL))
-			break;
-		udelay(10);
-	}
-
-	mutex_lock(&drv->lock);
-
-	thread->restarting = false;
-	enable_irq(drv->irq);
-	cpr_ctl_enable(thread);
-
-	mutex_unlock(&drv->lock);
-}
-
-/**
- * cpr_corner_restore() - Restore saved corner level
- * @thread: Structure holding CPR thread-specific parameters
- * @corner: Structure holding the saved corner level
- */
-static void cpr_corner_restore(struct cpr_thread *thread,
-			       struct cpr_corner *corner)
-{
-	struct cpr_drv *drv = thread->drv;
-	struct fuse_corner *fuse = corner->corner.fuse_corner;
-	const struct cpr_thread_desc *tdesc = thread->desc;
-	u32 ro_sel = fuse->ring_osc_idx;
-
-	cpr_write(thread, CPR3_REG_GCNT(ro_sel), drv->gcnt);
-
-	cpr_write(thread, CPR3_REG_RO_MASK(tdesc->hw_tid),
-		  CPR3_RO_MASK & ~BIT(ro_sel));
-
-	cpr_write(thread, CPR3_REG_TARGET_QUOT(tdesc->hw_tid, ro_sel),
-		  fuse->quot - corner->quot_adjust);
-
-	if (drv->desc->cpr_type == CTRL_TYPE_CPR4) {
-		cpr_masked_write(thread,
-				 CPR4_REG_CPR_MASK_THREAD(tdesc->hw_tid),
-				 CPR4_CPR_MASK_THREAD_DISABLE_THREAD |
-				 CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK, 0);
-	}
-
-	thread->corner = corner;
-	corner->last_uV = corner->corner.uV;
-}
-
-/**
- * cpr_set_acc() - Set fuse level to the mem-acc
- * @drv: Main driver structure
- * @f:   Fuse level
- */
-static void cpr_set_acc(struct cpr_drv *drv, int f)
-{
-	const struct acc_desc *desc = drv->acc_desc;
-	struct reg_sequence *s = desc->settings;
-	int n = desc->num_regs_per_fuse;
-
-	if (!s || f == drv->fuse_level_set)
-		return;
-
-	regmap_multi_reg_write(drv->tcsr, s + (n * f), n);
-	drv->fuse_level_set = f;
-}
-
-/**
- * cpr_pre_voltage() - Actions to execute before setting voltage
- * @thread:     Structure holding CPR thread-specific parameters
- * @dir:        Enumeration for voltage change direction
- * @fuse_level: Fuse corner for mem-acc, if supported.
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_pre_voltage(struct cpr_thread *thread,
-			   enum voltage_change_dir dir,
-			   int fuse_level)
-{
-	struct cpr_drv *drv = thread->drv;
-
-	if (drv->desc->cpr_type == CTRL_TYPE_CPR3 &&
-	    drv->desc->pd_throttle_val)
-		cpr_write(thread, CPR3_REG_PD_THROTTLE,
-			  drv->desc->pd_throttle_val);
-
-	if (drv->tcsr && dir == DOWN)
-		cpr_set_acc(drv, fuse_level);
-
-	return 0;
-}
-
-/**
- * cpr_post_voltage() - Actions to execute after setting voltage
- * @thread:     Structure holding CPR thread-specific parameters
- * @dir:        Enumeration for voltage change direction
- * @fuse_level: Fuse corner for mem-acc, if supported.
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_post_voltage(struct cpr_thread *thread,
-			    enum voltage_change_dir dir,
-			    int fuse_level)
-{
-	struct cpr_drv *drv = thread->drv;
-
-	if (drv->tcsr && dir == UP)
-		cpr_set_acc(drv, fuse_level);
-
-	if (drv->desc->cpr_type == CTRL_TYPE_CPR3)
-		cpr_write(thread, CPR3_REG_PD_THROTTLE, 0);
-
-	return 0;
-}
-
-/**
- * cpr_commit_state() - Set the newly requested voltage
- * @thread:     Structure holding CPR thread-specific parameters
- *
- * Return: IRQ_SUCCESS for success, IRQ_NONE if the CPR is disabled.
- */
-static int cpr_commit_state(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	int min_uV = 0, max_uV = 0, new_uV = 0, fuse_level = 0;
-	enum voltage_change_dir dir;
-	u32 next_irqmask = 0;
-	int ret, i;
-
-	/* On CPRhardened, control states are managed in firmware */
-	if (drv->desc->cpr_type == CTRL_TYPE_CPRH)
-		return 0;
-
-	for (i = 0; i < drv->desc->num_threads; i++) {
-		struct cpr_thread *thread = &drv->threads[i];
-
-		if (!thread->corner)
-			continue;
-
-		fuse_level = max(fuse_level,
-				 (int) (thread->corner->corner.fuse_corner -
-				 &thread->fuse_corners[0]));
-
-		max_uV = max(max_uV, thread->corner->corner.max_uV);
-		min_uV = max(min_uV, thread->corner->corner.min_uV);
-		new_uV = max(new_uV, thread->corner->last_uV);
-	}
-	dev_vdbg(drv->dev, "%s: new uV: %d, last uV: %d\n",
-		 __func__, new_uV, drv->last_uV);
-
-	/*
-	 * Safety measure: if the voltage is out of the globally allowed
-	 * range, then go out and warn the user.
-	 * This should *never* happen.
-	 */
-	if (new_uV > drv->desc->cpr_max_voltage ||
-	    new_uV < drv->desc->cpr_base_voltage) {
-		dev_warn(drv->dev, "Voltage (%u uV) out of range.", new_uV);
-		return -EINVAL;
-	}
-
-	if (new_uV == drv->last_uV || fuse_level == drv->fuse_level_set)
-		goto out;
-
-	if (fuse_level > drv->fuse_level_set)
-		dir = UP;
-	else
-		dir = DOWN;
-
-	ret = cpr_pre_voltage(thread, fuse_level, dir);
-	if (ret)
-		return ret;
-
-	dev_vdbg(drv->dev, "setting voltage: %d\n", new_uV);
-
-	ret = regulator_set_voltage(drv->vreg, new_uV, new_uV);
-	if (ret) {
-		dev_err_ratelimited(drv->dev, "failed to set voltage %d: %d\n", new_uV, ret);
-		return ret;
-	}
-
-	ret = cpr_post_voltage(thread, fuse_level, dir);
-	if (ret)
-		return ret;
-
-	drv->last_uV = new_uV;
-out:
-	if (new_uV > min_uV)
-		next_irqmask |= CPR3_IRQ_DOWN;
-	if (new_uV < max_uV)
-		next_irqmask |= CPR3_IRQ_UP;
-
-	cpr_irq_set(thread, next_irqmask);
-
-	return 0;
-}
-
-static unsigned int cpr_get_cur_perf_state(struct cpr_thread *thread)
-{
-	return thread->corner ? thread->corner - thread->corners + 1 : 0;
-}
-
-/**
- * cpr_scale() - Calculate new voltage for the received direction
- * @thread: Structure holding CPR thread-specific parameters
- * @dir:    Enumeration for voltage change direction
- *
- * The CPR scales one by one: this function calculates the new
- * voltage to set when a voltage-UP or voltage-DOWN request comes
- * and stores it into the per-thread structure that gets passed.
- */
-static void cpr_scale(struct cpr_thread *thread, enum voltage_change_dir dir)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_thread_desc *tdesc = thread->desc;
-	u32 val, error_steps;
-	int last_uV, new_uV;
-	struct cpr_corner *corner;
-
-	if (dir != UP && dir != DOWN)
-		return;
-
-	corner = thread->corner;
-	val = cpr_read(thread, CPR3_REG_RESULT0(tdesc->hw_tid));
-	error_steps = val >> CPR3_RESULT0_ERROR_STEPS_SHIFT;
-	error_steps &= CPR3_RESULT0_ERROR_STEPS_MASK;
-
-	last_uV = corner->last_uV;
-
-	if (dir == UP) {
-		if (!(val & CPR3_RESULT0_STEP_UP_MASK))
-			return;
-
-		/* Calculate new voltage */
-		new_uV = last_uV + drv->vreg_step;
-		new_uV = min(new_uV, corner->corner.max_uV);
-
-		dev_vdbg(drv->dev, "[T%u] UP - new_uV=%d last_uV=%d p-state=%u st=%u\n",
-			thread->id, new_uV, last_uV,
-			cpr_get_cur_perf_state(thread), error_steps);
-	} else {
-		if (!(val & CPR3_RESULT0_STEP_DN_MASK))
-			return;
-
-		/* Calculate new voltage */
-		new_uV = last_uV - drv->vreg_step;
-		new_uV = max(new_uV, corner->corner.min_uV);
-		dev_vdbg(drv->dev, "[T%u] DOWN - new_uV=%d last_uV=%d p-state=%u st=%u\n",
-			thread->id, new_uV, last_uV,
-			cpr_get_cur_perf_state(thread), error_steps);
-	}
-	corner->last_uV = new_uV;
-}
-
-/**
- * cpr_irq_handler() - Handle CPR3/CPR4 status interrupts
- * @irq: Number of the interrupt
- * @dev: Pointer to the cpr_thread structure
- *
- * Handle the interrupts coming from non-hardened CPR HW as to get
- * an ok to scale voltages immediately, or to pass error status to
- * the hardware (either success/ACK or failure/NACK).
- *
- * Return: IRQ_SUCCESS for success, IRQ_NONE if the CPR is disabled.
- */
-static irqreturn_t cpr_irq_handler(int irq, void *dev)
-{
-	struct cpr_thread *thread = dev;
-	struct cpr_drv *drv = thread->drv;
-	irqreturn_t ret = IRQ_HANDLED;
-	int i, rc;
-	enum voltage_change_dir dir = NO_CHANGE;
-	u32 val;
-
-	mutex_lock(&drv->lock);
-
-	val = cpr_read(thread, CPR3_REG_IRQ_STATUS);
-
-	dev_vdbg(drv->dev, "IRQ_STATUS = %#02x\n", val);
-
-	if (!cpr_ctl_is_enabled(thread)) {
-		dev_vdbg(drv->dev, "CPR is disabled\n");
-		ret = IRQ_NONE;
-	} else if (cpr_check_any_thread_busy(thread)) {
-		cpr_irq_clr_nack(thread);
-		dev_dbg(drv->dev, "CPR measurement is not ready\n");
-	} else {
-		/*
-		 * Following sequence of handling is as per each IRQ's
-		 * priority
-		 */
-		if (val & CPR3_IRQ_UP)
-			dir = UP;
-		else if (val & CPR3_IRQ_DOWN)
-			dir = DOWN;
-
-		if (dir != NO_CHANGE) {
-			for (i = 0; i < drv->desc->num_threads; i++) {
-				thread = &drv->threads[i];
-				cpr_scale(thread, dir);
-			}
-
-			rc = cpr_commit_state(thread);
-			if (rc)
-				cpr_irq_clr_nack(thread);
-			else
-				cpr_irq_clr_ack(thread);
-		} else if (val & CPR3_IRQ_MID) {
-			dev_dbg(drv->dev, "IRQ occurred for Mid Flag\n");
-		} else {
-			dev_warn(drv->dev, "IRQ occurred for unknown flag (%#08x)\n", val);
-			schedule_work(&thread->restart_work);
-		}
-	}
-
-	mutex_unlock(&drv->lock);
-
-	return ret;
-}
-
-static int cpr_switch(struct cpr_drv *drv)
-{
-	int i, ret;
-	bool enabled = false;
-
-	if (drv->desc->cpr_type == CTRL_TYPE_CPRH)
-		return 0;
-
-	for (i = 0; i < drv->desc->num_threads && !enabled; i++)
-		enabled = drv->threads[i].enabled;
-
-	dev_vdbg(drv->dev, "%s: enabled = %d\n", __func__, enabled);
-
-	if (enabled == drv->enabled)
-		return 0;
-
-	if (enabled) {
-		ret = regulator_enable(drv->vreg);
-		if (ret)
-			return ret;
-
-		drv->enabled = enabled;
-
-		for (i = 0; i < drv->desc->num_threads; i++)
-			if (drv->threads[i].corner)
-				break;
-
-		if (i < drv->desc->num_threads) {
-			cpr_irq_clr(&drv->threads[i]);
-
-			cpr_commit_state(&drv->threads[i]);
-			cpr_ctl_enable(&drv->threads[i]);
-		}
-	} else {
-		for (i = 0; i < drv->desc->num_threads && !enabled; i++)
-			cpr_ctl_disable(&drv->threads[i]);
-
-		drv->enabled = enabled;
-
-		ret = regulator_disable(drv->vreg);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-/**
- * cpr_enable() - Enables a CPR thread
- * @thread: Structure holding CPR thread-specific parameters
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_enable(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	int ret;
-
-	dev_dbg(drv->dev, "Enabling thread %d\n", thread->id);
-
-	mutex_lock(&drv->lock);
-
-	thread->enabled = true;
-	ret = cpr_switch(thread->drv);
-
-	mutex_unlock(&drv->lock);
-
-	return ret;
-}
-
-/**
- * cpr_disable() - Disables a CPR thread
- * @thread: Structure holding CPR thread-specific parameters
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_disable(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	int ret;
-
-	dev_dbg(drv->dev, "Disabling thread %d\n", thread->id);
-
-	mutex_lock(&drv->lock);
-
-	thread->enabled = false;
-	ret = cpr_switch(thread->drv);
-
-	mutex_unlock(&drv->lock);
-
-	return ret;
-}
-
-/**
- * cpr_configure() - Configure main HW parameters
- * @thread: Structure holding CPR thread-specific parameters
- *
- * This function configures the main CPR hardware parameters, such as
- * internal timers (and delays), sensor ownerships, activates and/or
- * deactivates cpr-threads and others, as one sequence for all of the
- * versions supported in this driver. By design, the function may
- * return a success earlier if the sequence for "a previous version"
- * has ended.
- *
- * Context: The CPR must be clocked before calling this function!
- *
- * Return: Zero for success or negative number on errors.
- */
-static int cpr_configure(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_desc *desc = drv->desc;
-	const struct cpr_thread_desc *tdesc = thread->desc;
-	u32 val;
-	int i;
-
-	/* Disable interrupt and CPR */
-	cpr_irq_set(thread, 0);
-	cpr_write(thread, CPR3_REG_CPR_CTL, 0);
-
-	/* Init and save gcnt */
-	drv->gcnt = drv->ref_clk_khz * desc->gcnt_us;
-	do_div(drv->gcnt, 1000);
-
-	/* Program the delay count for the timer */
-	val = drv->ref_clk_khz * desc->timer_delay_us;
-	do_div(val, 1000);
-	if (desc->cpr_type == CTRL_TYPE_CPR3) {
-		cpr_write(thread, CPR3_REG_CPR_TIMER_MID_CONT, val);
-
-		val = drv->ref_clk_khz * desc->timer_updn_delay_us;
-		do_div(val, 1000);
-		cpr_write(thread, CPR3_REG_CPR_TIMER_UP_DN_CONT, val);
-	} else {
-		cpr_write(thread, CPR3_REG_CPR_TIMER_AUTO_CONT, val);
-	}
-	dev_dbg(drv->dev, "Timer count: %#0x (for %d us)\n", val,
-		desc->timer_delay_us);
-
-	/* Program the control register */
-	val = desc->idle_clocks << CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT;
-	val |= desc->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT;
-	val |= desc->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT;
-	cpr_write(thread, CPR3_REG_CPR_CTL, val);
-
-	/* Configure CPR default step quotients */
-	val = tdesc->step_quot_init_min << CPR3_CPR_STEP_QUOT_MIN_SHIFT;
-	val |= tdesc->step_quot_init_max << CPR3_CPR_STEP_QUOT_MAX_SHIFT;
-
-	cpr_write(thread, CPR3_REG_CPR_STEP_QUOT, val);
-
-	/*
-	 * Configure the CPR sensor ownership always on thread 0
-	 * TODO: SDM845 has different ownership for sensors!!
-	 */
-	for (i = tdesc->sensor_range_start; i < tdesc->sensor_range_end; i++)
-		cpr_write(thread, CPR3_REG_SENSOR_OWNER(i), 0);
-
-	/* Program Consecutive Up & Down */
-	val = desc->timer_cons_up << CPR3_THRESH_CONS_UP_SHIFT;
-	val |= desc->timer_cons_down << CPR3_THRESH_CONS_DOWN_SHIFT;
-	val |= desc->up_threshold << CPR3_THRESH_UP_THRESH_SHIFT;
-	val |= desc->down_threshold << CPR3_THRESH_DOWN_THRESH_SHIFT;
-	cpr_write(thread, CPR3_REG_THRESH(tdesc->hw_tid), val);
-
-	/* Mask all ring oscillators for all threads initially */
-	cpr_write(thread, CPR3_REG_RO_MASK(tdesc->hw_tid), CPR3_RO_MASK);
-
-	/* HW Closed-loop control */
-	if (desc->cpr_type == CTRL_TYPE_CPR3) {
-		cpr_write(thread, CPR3_REG_HW_CLOSED_LOOP_DISABLED,
-			  !desc->hw_closed_loop_en);
-	} else {
-		cpr_masked_write(thread, CPR4_REG_MARGIN_ADJ_CTL,
-				CPR4_MARGIN_ADJ_HW_CLOSED_LOOP_EN,
-				desc->hw_closed_loop_en ?
-				CPR4_MARGIN_ADJ_HW_CLOSED_LOOP_EN : 0);
-	}
-
-	/* Additional configuration for CPR4 and beyond */
-	if (desc->cpr_type < CTRL_TYPE_CPR4)
-		return 0;
-
-	/* Disable threads initially only on non-hardened CPR4 */
-	if (desc->cpr_type == CTRL_TYPE_CPR4) {
-		cpr_masked_write(thread, CPR4_REG_CPR_MASK_THREAD(1),
-				CPR4_CPR_MASK_THREAD_DISABLE_THREAD |
-				CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
-				CPR4_CPR_MASK_THREAD_DISABLE_THREAD |
-				CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
-	}
-
-	if (tdesc->hw_tid > 0) {
-		cpr_masked_write(thread, CPR4_REG_MISC,
-				 CPR4_MISC_RESET_STEP_QUOT_LOOP_EN |
-				 CPR4_MISC_THREAD_HAS_ALWAYS_VOTE_EN,
-				 CPR4_MISC_RESET_STEP_QUOT_LOOP_EN |
-				 CPR4_MISC_THREAD_HAS_ALWAYS_VOTE_EN);
-	}
-
-	val = drv->vreg_step;
-	do_div(val, 1000);
-	cpr_masked_write(thread, CPR4_REG_MARGIN_ADJ_CTL,
-			 CPR4_MARGIN_ADJ_PMIC_STEP_SIZE_MASK,
-			 val << CPR4_MARGIN_ADJ_PMIC_STEP_SIZE_SHIFT);
-
-	cpr_masked_write(thread, CPR4_REG_SAW_ERROR_STEP_LIMIT,
-			 CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK,
-			 desc->vreg_step_down_limit <<
-			 CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT);
-
-	cpr_masked_write(thread, CPR4_REG_SAW_ERROR_STEP_LIMIT,
-			 CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK,
-			 desc->vreg_step_up_limit <<
-			 CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT);
-
-	cpr_masked_write(thread, CPR4_REG_MARGIN_ADJ_CTL,
-			 CPR4_MARGIN_ADJ_PER_RO_KV_MARGIN_EN,
-			 CPR4_MARGIN_ADJ_PER_RO_KV_MARGIN_EN);
-
-	if (tdesc->hw_tid > 0) {
-		cpr_masked_write(thread, CPR4_REG_CPR_TIMER_CLAMP,
-				 CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN,
-				 CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN);
-	}
-
-	/* Settling timer to account for one VDD supply step */
-	if (desc->vdd_settle_time_us > 0) {
-		u32 m = CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK;
-		u32 s = CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHFT;
-
-		cpr_masked_write(thread, CPR4_REG_MARGIN_TEMP_CORE_TIMERS,
-				 m, desc->vdd_settle_time_us << s);
-	}
-
-	/* Additional configuration for CPR-hardened */
-	if (desc->cpr_type < CTRL_TYPE_CPRH)
-		return 0;
-
-	/* Settling timer to account for one corner-switch request */
-	if (desc->corner_settle_time_us > 0) {
-		cpr_masked_write(thread, drv->reg_ctl,
-				 CPRH_CTL_MODE_SWITCH_DELAY_MASK,
-				 desc->corner_settle_time_us <<
-				 CPRH_CTL_MODE_SWITCH_DELAY_SHIFT);
-	}
-
-	/* Base voltage and multiplier values for CPRh internal calculations */
-	cpr_masked_write(thread, drv->reg_ctl,
-			 CPRH_CTL_BASE_VOLTAGE_MASK,
-			 (DIV_ROUND_UP(desc->cpr_base_voltage,
-				       drv->vreg_step) <<
-			  CPRH_CTL_BASE_VOLTAGE_SHIFT));
-
-	cpr_masked_write(thread, drv->reg_ctl,
-			 CPRH_CTL_VOLTAGE_MULTIPLIER_MASK,
-			 DIV_ROUND_UP(drv->vreg_step, 1000) <<
-			 CPRH_CTL_VOLTAGE_MULTIPLIER_SHIFT);
-
-	return 0;
-}
-
-
-static int cprh_dummy_set_performance_state(struct generic_pm_domain *domain,
-					    unsigned int state)
-{
-	return 0;
-}
-
-static int cpr_set_performance_state(struct generic_pm_domain *domain,
-				     unsigned int state)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-	struct cpr_drv *drv = thread->drv;
-	struct cpr_corner *corner, *end;
-	int ret = 0;
-
-	mutex_lock(&drv->lock);
-
-	dev_dbg(drv->dev, "setting perf state: %u (prev state: %u thread: %u)\n",
-		state, cpr_get_cur_perf_state(thread), thread->id);
-
-	/*
-	 * Determine new corner we're going to.
-	 * Remove one since lowest performance state is 1.
-	 */
-	corner = thread->corners + state - 1;
-	end = &thread->corners[thread->num_corners - 1];
-	if (corner > end || corner < thread->corners) {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	cpr_ctl_disable(thread);
-
-	cpr_irq_clr(thread);
-	if (thread->corner != corner)
-		cpr_corner_restore(thread, corner);
-
-	ret = cpr_commit_state(thread);
-	if (ret)
-		goto unlock;
-
-	cpr_ctl_enable(thread);
-unlock:
-	mutex_unlock(&drv->lock);
-
-	dev_dbg(drv->dev, "set perf state %u on thread %u\n", state, thread->id);
-
-	return ret;
-}
-
-/**
- * cpr3_adjust_quot - Adjust the closed-loop quotients
- * @ring_osc_factor:  Ring oscillator adjustment factor
- * @volt_closed_loop: Closed-loop voltage adjustment factor
- *
- * Calculates the quotient adjustment factor based on closed-loop
- * quotients and ring oscillator factor.
- *
- * Return: Adjusted quotient
- */
-static int cpr3_adjust_quot(int ring_osc_factor, int volt_closed_loop)
-{
-	s64 temp;
-
-	if (ring_osc_factor == 0 || volt_closed_loop == 0)
-		return 0;
-
-	temp = (s64)(ring_osc_factor * volt_closed_loop);
-	return (int)div_s64(temp, 1000000);
-}
-
-/**
- * cpr_fuse_corner_init() - Calculate fuse corner table
- * @thread: Structure holding CPR thread-specific parameters
- *
- * This function populates the fuse corners table by reading the
- * values from the fuses, eventually adjusting them with a fixed
- * per-corner offset and doing basic checks about them being
- * supported by the regulator that is assigned to this CPR - if
- * it is available (on CPR-Hardened, there is no usable vreg, as
- * that is protected by the hypervisor).
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr_fuse_corner_init(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_thread_desc *desc = thread->desc;
-	const struct cpr_fuse *cpr_fuse = thread->cpr_fuses;
-	struct fuse_corner_data *fdata;
-	struct fuse_corner *fuse, *prev_fuse, *end;
-	int i, ret;
-
-	/* Populate fuse_corner members */
-	fuse = thread->fuse_corners;
-	prev_fuse = &fuse[0];
-	end = &fuse[desc->num_fuse_corners - 1];
-	fdata = desc->fuse_corner_data;
-
-	for (i = 0; fuse <= end; fuse++, cpr_fuse++, i++, fdata++) {
-		int factor = cpr_get_ro_factor(desc, i, fuse->ring_osc_idx);
-
-		ret = cpr_populate_fuse_common(drv->dev, fdata, cpr_fuse,
-					       fuse, drv->vreg_step,
-					       desc->init_voltage_width,
-					       desc->init_voltage_step);
-		if (ret)
-			return ret;
-
-		/*
-		 * Adjust the fuse quot with per-fuse-corner closed-loop
-		 * voltage adjustment parameters.
-		 */
-		fuse->quot += cpr3_adjust_quot(factor, fdata->volt_cloop_adjust);
-
-		/* CPRh: no regulator access... */
-		if (drv->desc->cpr_type == CTRL_TYPE_CPRH)
-			goto skip_pvs_restrict;
-
-		/* Re-check if corner voltage range is supported by regulator */
-		ret = cpr_check_vreg_constraints(drv->dev, drv->vreg, fuse);
-		if (ret)
-			return ret;
-
-skip_pvs_restrict:
-		if (fuse->uV < prev_fuse->uV)
-			fuse->uV = prev_fuse->uV;
-		prev_fuse = fuse;
-		dev_dbg(drv->dev, "fuse corner %d: [%d %d %d] RO%hhu quot %d\n",
-			i, fuse->min_uV, fuse->uV, fuse->max_uV,
-			fuse->ring_osc_idx, fuse->quot);
-
-		/* Check if constraints are valid */
-		if (fuse->uV < fuse->min_uV || fuse->uV > fuse->max_uV) {
-			dev_err(drv->dev, "fuse corner %d: Bad voltage range.\n", i);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static void cpr3_restrict_corner(struct cpr_corner *corner, int threshold,
-				 int hysteresis, int step)
-{
-	if (threshold > corner->corner.min_uV && threshold <= corner->corner.max_uV) {
-		if (corner->corner.uV >= threshold) {
-			corner->corner.min_uV = max(corner->corner.min_uV,
-					     threshold - hysteresis);
-			if (corner->corner.min_uV > corner->corner.uV)
-				corner->corner.uV = corner->corner.min_uV;
-		} else {
-			corner->corner.max_uV = threshold;
-			corner->corner.max_uV -= step;
-		}
-	}
-}
-
-/*
- * cprh_corner_adjust_opps() - Set voltage on each CPU OPP table entry
- *
- * On CPR-Hardened, the voltage level is controlled internally through
- * the OSM hardware: in order to initialize the latter, we have to
- * communicate the voltage to its driver, so that it will be able to
- * write the right parameters (as they have to be set both on the CPRh
- * and on the OSM) on it.
- * This function is called only for CPRh.
- *
- * Return: Zero for success, negative number for error.
- */
-static int cprh_corner_adjust_opps(struct cpr_thread *thread)
-{
-	struct cpr_corner *corner = thread->corners;
-	struct cpr_drv *drv = thread->drv;
-	int i, ret;
-
-	for (i = 0; i < thread->num_corners; i++) {
-		ret = dev_pm_opp_adjust_voltage(thread->attached_cpu_dev,
-						corner[i].corner.freq,
-						corner[i].corner.uV,
-						corner[i].corner.min_uV,
-						corner[i].corner.max_uV);
-		if (ret)
-			break;
-
-		dev_dbg(drv->dev, "OPP voltage adjusted for %lu kHz, %d uV\n",
-			corner[i].corner.freq, corner[i].corner.uV);
-	}
-
-	/* If we couldn't adjust voltage for all corners, something went wrong */
-	if (i < thread->num_corners)
-		return -EINVAL;
-
-	return ret;
-}
-
-/**
- * cpr3_corner_init() - Calculate and set-up corners for the CPR HW
- * @thread: Structure holding CPR thread-specific parameters
- *
- * This function calculates all the corner parameters by comparing
- * and interpolating the values read from the various set-points
- * read from the fuses (also called "fuse corners") to generate and
- * program to the CPR a lookup table that describes each voltage
- * step, mapped to a performance level (or corner number).
- *
- * It also programs other essential parameters on the CPR and - if
- * we are dealing with CPR-Hardened, it will also enable the internal
- * interface between the Operating State Manager (OSM) and the CPRh
- * in order to achieve CPU DVFS.
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr3_corner_init(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	const struct cpr_desc *desc = drv->desc;
-	const struct cpr_thread_desc *tdesc = thread->desc;
-	const struct cpr_fuse *fuses = thread->cpr_fuses;
-	int i, ret, total_corners, extra_corners, level, scaling = 0;
-	unsigned int fnum, fc;
-	const char *quot_offset;
-	const struct fuse_corner_data *fdata;
-	struct fuse_corner *fuse, *prev_fuse;
-	struct cpr_corner *corner, *prev_corner, *end;
-	struct corner_data *cdata;
-	struct dev_pm_opp *opp;
-	unsigned long freq;
-	u32 ring_osc_mask = CPR3_RO_MASK, min_quotient = U32_MAX;
-
-	corner = thread->corners;
-	prev_corner = &thread->corners[0];
-	end = &corner[thread->num_corners - 1];
-
-	cdata = devm_kcalloc(drv->dev, thread->num_corners + drv->extra_corners,
-			     sizeof(struct corner_data), GFP_KERNEL);
-	if (!cdata)
-		return -ENOMEM;
-
-	for (level = 1; level <= thread->num_corners; level++) {
-		opp = dev_pm_opp_find_level_exact(&thread->pd.dev, level);
-		if (IS_ERR(opp))
-			return -EINVAL;
-
-		/*
-		 * If there is only one specified qcom,opp-fuse-level, then
-		 * it is assumed that this only one is global and valid for
-		 * all IDs, so try to get the specific one but, on failure,
-		 * go for the global one.
-		 */
-		fc = cpr_get_fuse_corner(opp, thread->id);
-		if (fc == 0) {
-			fc = cpr_get_fuse_corner(opp, 0);
-			if (fc == 0) {
-				dev_err(drv->dev, "qcom,opp-fuse-level is missing!\n");
-				dev_pm_opp_put(opp);
-				return -EINVAL;
-			}
-		}
-		fnum = fc - 1;
-
-		freq = cpr_get_opp_hz_for_req(opp, thread->attached_cpu_dev);
-		if (!freq) {
-			thread->num_corners = max(level - 1, 0);
-			end = &thread->corners[thread->num_corners - 1];
-			break;
-		}
-
-		/*
-		 * If any post-vadj (open/closed loop) is not specified, then
-		 * it's zero, meaning that it is not required for this corner.
-		 */
-		cpr_get_corner_post_vadj(opp, thread->id,
-					 &cdata[level - 1].oloop_vadj,
-					 &cdata[level - 1].cloop_vadj);
-		cdata[level - 1].fuse_corner = fnum;
-		cdata[level - 1].freq = freq;
-
-		fuse = &thread->fuse_corners[fnum];
-		dev_dbg(drv->dev, "freq: %lu level: %u fuse level: %u\n",
-			freq, dev_pm_opp_get_level(opp) - 1, fnum);
-		if (freq > fuse->max_freq)
-			fuse->max_freq = freq;
-		dev_pm_opp_put(opp);
-
-		/*
-		 * Make sure that the frequencies in the table are in ascending
-		 * order, as this is critical for the algorithm to work.
-		 */
-		if (cdata[level - 2].freq > freq) {
-			dev_err(drv->dev, "Frequency table not in ascending order.\n");
-			return -EINVAL;
-		}
-	}
-
-	if (thread->num_corners < 2) {
-		dev_err(drv->dev, "need at least 2 OPPs to use CPR\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Get the quotient adjustment scaling factor, according to:
-	 *
-	 * scaling = min(1000 * (QUOT(corner_N) - QUOT(corner_N-1))
-	 *		/ (freq(corner_N) - freq(corner_N-1)), max_factor)
-	 *
-	 * QUOT(corner_N):	quotient read from fuse for fuse corner N
-	 * QUOT(corner_N-1):	quotient read from fuse for fuse corner (N - 1)
-	 * freq(corner_N):	max frequency in MHz supported by fuse corner N
-	 * freq(corner_N-1):	max frequency in MHz supported by fuse corner
-	 *			 (N - 1)
-	 *
-	 * Then walk through the corners mapped to each fuse corner
-	 * and calculate the quotient adjustment for each one using the
-	 * following formula:
-	 *
-	 * quot_adjust = (freq_max - freq_corner) * scaling / 1000
-	 *
-	 * freq_max: max frequency in MHz supported by the fuse corner
-	 * freq_corner: frequency in MHz corresponding to the corner
-	 * scaling: calculated from above equation
-	 *
-	 *
-	 *     +                           +
-	 *     |                         v |
-	 *   q |           f c           o |           f c
-	 *   u |         c               l |         c
-	 *   o |       f                 t |       f
-	 *   t |     c                   a |     c
-	 *     | c f                     g | c f
-	 *     |                         e |
-	 *     +---------------            +----------------
-	 *       0 1 2 3 4 5 6               0 1 2 3 4 5 6
-	 *          corner                      corner
-	 *
-	 *    c = corner
-	 *    f = fuse corner
-	 *
-	 */
-	for (i = 0; corner <= end; corner++, i++) {
-		unsigned long freq_diff_mhz;
-		int ro_fac, vadj, prev_quot;
-
-		fnum = cdata[i].fuse_corner;
-		fdata = &tdesc->fuse_corner_data[fnum];
-		quot_offset = fuses[fnum].quotient_offset;
-		fuse = &thread->fuse_corners[fnum];
-		ring_osc_mask &= (u16)(~BIT(fuse->ring_osc_idx));
-		if (fnum)
-			prev_fuse = &thread->fuse_corners[fnum - 1];
-		else
-			prev_fuse = NULL;
-
-		corner->corner.fuse_corner = fuse;
-		corner->corner.freq = cdata[i].freq;
-		corner->corner.uV = fuse->uV;
-
-		if (prev_fuse) {
-			if (prev_fuse->ring_osc_idx == fuse->ring_osc_idx)
-				quot_offset = NULL;
-
-			scaling = cpr_calculate_scaling(quot_offset, drv->dev,
-							fdata, &corner->corner);
-			if (scaling < 0) {
-				dev_warn(drv->dev, "Error calculating scaling: %d\n", scaling);
-				return scaling;
-			}
-
-			freq_diff_mhz = fuse->max_freq - corner->corner.freq;
-			do_div(freq_diff_mhz, 1000000); /* now in MHz */
-
-			corner->quot_adjust = scaling * freq_diff_mhz;
-			do_div(corner->quot_adjust, 1000);
-
-			/* Fine-tune QUOT (closed-loop) based on fixed values */
-			ro_fac = cpr_get_ro_factor(tdesc, fnum, fuse->ring_osc_idx);
-			vadj = cdata[i].cloop_vadj;
-			corner->quot_adjust -= cpr3_adjust_quot(ro_fac, vadj);
-			dev_vdbg(drv->dev, "Quot fine-tuning to %d for post-vadj=%d\n",
-				 corner->quot_adjust, vadj);
-
-			/*
-			 * Make sure that we scale (up) monotonically.
-			 * P.S.: Fuse quots can never be descending.
-			 */
-			prev_quot = prev_corner->corner.fuse_corner->quot;
-			prev_quot -= prev_corner->quot_adjust;
-			if (fuse->quot - corner->quot_adjust < prev_quot) {
-				int new_adj = prev_corner->corner.fuse_corner->quot;
-				new_adj -= fuse->quot;
-				dev_vdbg(drv->dev, "Monotonic increase forced: %d->%d\n",
-					 corner->quot_adjust, new_adj);
-				corner->quot_adjust = new_adj;
-			}
-
-			corner->corner.uV = cpr_interpolate(&corner->corner,
-						     drv->vreg_step, fdata);
-		}
-		/* Negative fuse quotients are nonsense. */
-		if (fuse->quot < corner->quot_adjust)
-			return -EINVAL;
-
-		min_quotient = min(min_quotient,
-				   (u32)(fuse->quot - corner->quot_adjust));
-
-		/* Fine-tune voltages (open-loop) based on fixed values */
-		corner->corner.uV += cdata[i].oloop_vadj;
-		dev_dbg(drv->dev, "Voltage fine-tuning to %d for post-vadj=%d\n",
-			 corner->corner.uV, cdata[i].oloop_vadj);
-
-		corner->corner.max_uV = fuse->max_uV;
-		corner->corner.min_uV = fuse->min_uV;
-		corner->corner.uV = clamp(corner->corner.uV, corner->corner.min_uV, corner->corner.max_uV);
-		dev_vdbg(drv->dev, "Clamped after interpolation: [%d %d %d]\n",
-			corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV);
-
-		/* Make sure that we scale monotonically here, too. */
-		if (corner->corner.uV < prev_corner->corner.uV)
-			corner->corner.uV = prev_corner->corner.uV;
-
-		corner->last_uV = corner->corner.uV;
-
-		/* Reduce the ceiling voltage if needed */
-		if (desc->reduce_to_corner_uV && corner->corner.uV < corner->corner.max_uV)
-			corner->corner.max_uV = corner->corner.uV;
-		else if (desc->reduce_to_fuse_uV && fuse->uV < corner->corner.max_uV)
-			corner->corner.max_uV = max(corner->corner.min_uV, fuse->uV);
-		dev_vdbg(drv->dev, "Clamped after interpolation: [%d %d %d]\n",
-			corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV);
-
-		corner->corner.min_uV = max(corner->corner.max_uV - fdata->range_uV,
-				     corner->corner.min_uV);
-
-		dev_vdbg(drv->dev, "Clamped after interpolation: [%d %d %d (%d)]\n",
-			corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV, fdata->range_uV);
-		/*
-		 * Adjust per-corner floor and ceiling voltages so that
-		 * they do not overlap the memory Array Power Mux (APM)
-		 * nor the Memory Accelerator (MEM-ACC) threshold voltages.
-		 */
-		if (desc->apm_threshold)
-			cpr3_restrict_corner(corner, desc->apm_threshold,
-					     desc->apm_hysteresis,
-					     drv->vreg_step);
-		if (desc->mem_acc_threshold)
-			cpr3_restrict_corner(corner, desc->mem_acc_threshold,
-					     0, drv->vreg_step);
-
-		prev_corner = corner;
-		dev_dbg(drv->dev, "corner %d: [%d %d %d] scaling %d quot %d\n", i,
-			corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV, scaling,
-			fuse->quot - corner->quot_adjust);
-	}
-
-	/* Additional setup for CPRh only */
-	if (desc->cpr_type < CTRL_TYPE_CPRH)
-		return 0;
-
-	/* If the OPPs can't be adjusted, programming the CPRh is useless */
-	ret = cprh_corner_adjust_opps(thread);
-	if (ret) {
-		dev_err(drv->dev, "Cannot adjust CPU OPP voltages: %d\n", ret);
-		return ret;
-	}
-
-	total_corners = thread->num_corners;
-	extra_corners = drv->extra_corners;
-
-	/* If the APM extra corner exists, add it now. */
-	if (desc->apm_crossover && desc->apm_threshold && extra_corners) {
-		/* Program the APM crossover corner on the CPR-Hardened */
-		thread->corners[total_corners].corner.uV = desc->apm_crossover;
-		thread->corners[total_corners].corner.min_uV = desc->apm_crossover;
-		thread->corners[total_corners].corner.max_uV = desc->apm_crossover;
-		thread->corners[total_corners].is_open_loop = true;
-
-		/*
-		 * We have calculated the APM parameters for this clock plan:
-		 * make the APM *threshold* available to external callers.
-		 * The crossover is used only internally in the CPR.
-		 */
-		thread->ext_data.apm_threshold_uV = desc->apm_threshold;
-
-		dev_dbg(drv->dev, "corner %d (APM): [%d %d %d] Open-Loop\n",
-			total_corners, desc->apm_crossover,
-			desc->apm_crossover, desc->apm_crossover);
-
-		total_corners++;
-		extra_corners--;
-	}
-
-	if (desc->mem_acc_threshold && extra_corners) {
-		/* Program the Memory Accelerator threshold corner to CPRh */
-		thread->corners[total_corners].corner.uV = desc->mem_acc_threshold;
-		thread->corners[total_corners].corner.min_uV = desc->mem_acc_threshold;
-		thread->corners[total_corners].corner.max_uV = desc->mem_acc_threshold;
-		thread->corners[total_corners].is_open_loop = true;
-
-		/*
-		 * We have calculated a mem-acc threshold for this clock plan:
-		 * make it available to external callers.
-		 */
-		thread->ext_data.mem_acc_threshold_uV = desc->mem_acc_threshold;
-
-		dev_dbg(drv->dev, "corner %d (MEMACC): [%d %d %d] Open-Loop\n",
-			total_corners, desc->mem_acc_threshold,
-			desc->mem_acc_threshold, desc->mem_acc_threshold);
-
-		total_corners++;
-		extra_corners--;
-	}
-
-	/*
-	 * If there are any extra corners left, it means that even though we
-	 * expect to fill in both APM and MEM-ACC crossovers, one couldn't
-	 * satisfy requirements, which means that the specified parameters
-	 * are wrong: in this case, inform the user and bail out, otherwise
-	 * if we go on writing the (invalid) table to the CPR-Hardened, the
-	 * hardware (in this case, the CPU) will surely freeze and crash.
-	 */
-	if (unlikely(extra_corners)) {
-		dev_err(drv->dev, "APM/MEM-ACC corners: bad parameters.\n");
-		return -EINVAL;
-	}
-	/* Reassign extra_corners, as we have to exclude delta_quot for them */
-	extra_corners = drv->extra_corners;
-
-	/* Disable the interface between OSM and CPRh */
-	cpr_masked_write(thread, drv->reg_ctl,
-			 CPRH_CTL_OSM_ENABLED, 0);
-
-	/* Program the GCNT before unmasking ring oscillator(s) */
-	for (i = 0; i < CPR3_RO_COUNT; i++) {
-		if (!(ring_osc_mask & BIT(i))) {
-			cpr_write(thread, CPR3_REG_GCNT(i), drv->gcnt);
-			dev_vdbg(drv->dev, "RO%d gcnt=%d\n", i, drv->gcnt);
-		}
-	}
-
-	/*
-	 * Unmask the ring oscillator(s) that we're going to use: it seems
-	 * to be mandatory to do this *before* sending the rest of the
-	 * CPRhardened specific configuration.
-	 */
-	dev_dbg(drv->dev, "Unmasking ring oscillators with mask 0x%x\n", ring_osc_mask);
-	cpr_write(thread, CPR3_REG_RO_MASK(tdesc->hw_tid), ring_osc_mask);
-
-	/* Setup minimum quotients for ring oscillators */
-	for (i = 0; i < CPR3_RO_COUNT; i++) {
-		u32 tgt_quot_reg = CPR3_REG_TARGET_QUOT(tdesc->hw_tid, i);
-		u32 tgt_quot_val = 0;
-
-		if (!(ring_osc_mask & BIT(i)))
-			tgt_quot_val = min_quotient;
-
-		cpr_write(thread, tgt_quot_reg, tgt_quot_val);
-		dev_vdbg(drv->dev, "Programmed min quotient %u for Ring Oscillator %d\n",
-			 tgt_quot_val, tgt_quot_reg);
-	}
-
-	for (i = 0; i < total_corners; i++) {
-		int volt_oloop_steps, volt_floor_steps, delta_quot_steps;
-		int ring_osc;
-		u32 val;
-
-		fnum = cdata[i].fuse_corner;
-		fuse = &thread->fuse_corners[fnum];
-
-		val = thread->corners[i].corner.uV - desc->cpr_base_voltage;
-		volt_oloop_steps = DIV_ROUND_UP(val, drv->vreg_step);
-
-		val = thread->corners[i].corner.min_uV - desc->cpr_base_voltage;
-		volt_floor_steps = DIV_ROUND_UP(val, drv->vreg_step);
-
-		/*
-		 * If we are accessing corners that are not used as
-		 * an active DCVS set-point, then always select RO 0
-		 * and zero out the delta quotient.
-		 */
-		if (i >= thread->num_corners) {
-			ring_osc = 0;
-			delta_quot_steps = 0;
-		} else {
-			ring_osc = fuse->ring_osc_idx;
-			val = fuse->quot - thread->corners[i].quot_adjust;
-			val -= min_quotient;
-			delta_quot_steps = DIV_ROUND_UP(val,
-						CPRH_DELTA_QUOT_STEP_FACTOR);
-		}
-
-		if (volt_oloop_steps > CPRH_CORNER_INIT_VOLTAGE_MAX_VALUE  ||
-		    volt_floor_steps > CPRH_CORNER_FLOOR_VOLTAGE_MAX_VALUE ||
-		    delta_quot_steps > CPRH_CORNER_QUOT_DELTA_MAX_VALUE) {
-			dev_err(drv->dev, "Invalid cfg: oloop=%d, floor=%d, delta=%d\n",
-				volt_oloop_steps, volt_floor_steps,
-				delta_quot_steps);
-			return -EINVAL;
-		}
-		/* Green light: Go, Go, Go! */
-
-		/* Set number of open-loop steps */
-		val = volt_oloop_steps << CPRH_CORNER_INIT_VOLTAGE_SHIFT;
-		val &= CPRH_CORNER_INIT_VOLTAGE_MASK;
-
-		/* Set number of floor voltage steps */
-		val |= (volt_floor_steps << CPRH_CORNER_FLOOR_VOLTAGE_SHIFT) &
-		       CPRH_CORNER_FLOOR_VOLTAGE_MASK;
-
-		/* Set number of target quotient delta steps */
-		val |= (delta_quot_steps << CPRH_CORNER_QUOT_DELTA_SHIFT) &
-		       CPRH_CORNER_QUOT_DELTA_MASK;
-
-		/* Select ring oscillator for this corner */
-		val |= (ring_osc << CPRH_CORNER_RO_SEL_SHIFT) &
-		       CPRH_CORNER_RO_SEL_MASK;
-
-		/* Open loop corner is usually APM/ACC crossover */
-		if (thread->corners[i].is_open_loop) {
-			dev_dbg(drv->dev, "Disabling Closed-Loop on corner %d\n", i);
-			val |= CPRH_CORNER_CPR_CL_DISABLE;
-		}
-		cpr_write(thread, CPRH_REG_CORNER(drv, tdesc->hw_tid, i), val);
-
-		dev_dbg(drv->dev, "steps [%d]: open-loop %d, floor %d, delta_quot %d\n",
-			i, volt_oloop_steps, volt_floor_steps,
-			delta_quot_steps);
-	}
-
-	/* YAY! Setup is done! Enable the internal loop to start CPR. */
-	cpr_masked_write(thread, CPR3_REG_CPR_CTL,
-			CPR3_CPR_CTL_LOOP_EN_MASK,
-			CPR3_CPR_CTL_LOOP_EN_MASK);
-
-	/*
-	 * All the writes are going through before enabling internal
-	 * communication between the OSM and the CPRh controllers
-	 * because we are never using relaxed accessors, but should
-	 * we use them, it would be critical to issue a barrier here,
-	 * otherwise there is a high risk of hardware lockups due to
-	 * under-voltage for the selected CPU clock.
-	 *
-	 * Please note that the CPR-hardened gets set-up in Linux but
-	 * then gets actually used in firmware (and only by the OSM);
-	 * after handing it off we will have no more control on it.
-	 */
-
-	/* Enable the interface between OSM and CPRh */
-	cpr_masked_write(thread, drv->reg_ctl,
-			 CPRH_CTL_OSM_ENABLED,
-			 CPRH_CTL_OSM_ENABLED);
-
-	/* On success, free cdata manually */
-	devm_kfree(drv->dev, cdata);
-	return 0;
-}
-
-/**
- * cpr3_init_parameters() - Initialize CPR global parameters
- * @drv: Main driver structure
- *
- * Initial "integrity" checks and setup for the thread-independent parameters.
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr3_init_parameters(struct cpr_drv *drv)
-{
-	const struct cpr_desc *desc = drv->desc;
-	struct clk *clk;
-
-	clk = devm_clk_get(drv->dev, "ref");
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	drv->ref_clk_khz = clk_get_rate(clk);
-	do_div(drv->ref_clk_khz, 1000);
-
-	/* On CPRh this clock is not always-on... */
-	if (desc->cpr_type == CTRL_TYPE_CPRH)
-		clk_prepare_enable(clk);
-	else
-		devm_clk_put(drv->dev, clk);
-
-	if (desc->timer_cons_up > CPR3_THRESH_CONS_UP_MASK ||
-	    desc->timer_cons_down > CPR3_THRESH_CONS_DOWN_MASK ||
-	    desc->up_threshold > CPR3_THRESH_UP_THRESH_MASK ||
-	    desc->down_threshold > CPR3_THRESH_DOWN_THRESH_MASK ||
-	    desc->idle_clocks > CPR3_CPR_CTL_IDLE_CLOCKS_MASK ||
-	    desc->count_mode > CPR3_CPR_CTL_COUNT_MODE_MASK ||
-	    desc->count_repeat > CPR3_CPR_CTL_COUNT_REPEAT_MASK)
-		return -EINVAL;
-
-	/*
-	 * Read the CPR version register only from CPR3 onwards:
-	 * this is needed to get the additional register offsets.
-	 *
-	 * Note: When threaded, even if multi-controller, there
-	 *       is no chance to have different versions at the
-	 *       same time in the same domain, so it is safe to
-	 *       check this only on the first controller/thread.
-	 */
-	drv->cpr_hw_rev = cpr_read(&drv->threads[0],
-				   CPR3_REG_CPR_VERSION);
-	dev_dbg(drv->dev, "CPR hardware revision: 0x%x\n", drv->cpr_hw_rev);
-
-	if (drv->cpr_hw_rev >= CPRH_CPR_VERSION_4P5) {
-		drv->reg_corner = 0x3500;
-		drv->reg_corner_tid = 0xa0;
-		drv->reg_ctl = 0x3a80;
-		drv->reg_status = 0x3a84;
-	} else {
-		drv->reg_corner = 0x3a00;
-		drv->reg_corner_tid = 0;
-		drv->reg_ctl = 0x3aa0;
-		drv->reg_status = 0x3aa4;
-	}
-
-	dev_dbg(drv->dev, "up threshold = %u, down threshold = %u\n",
-		desc->up_threshold, desc->down_threshold);
-
-	return 0;
-}
-
-/*
- * Returns: Index of the initial corner or negative number for error.
- */
-static int cpr_find_initial_corner(struct device *dev, struct clk *cpu_clk,
-			    struct cpr_corner *corners, int num_corners)
-{
-	unsigned long rate;
-	struct cpr_corner *iter, *corner;
-	const struct cpr_corner *end;
-	unsigned int ret = 0;
-
-	if (!cpu_clk)
-		return -EINVAL;
-
-	end = &corners[num_corners - 1];
-	rate = clk_get_rate(cpu_clk);
-
-	/*
-	 * Some bootloaders set a CPU clock frequency that is not defined
-	 * in the OPP table. When running at an unlisted frequency,
-	 * cpufreq_online() will change to the OPP which has the lowest
-	 * frequency, at or above the unlisted frequency.
-	 * Since cpufreq_online() always "rounds up" in the case of an
-	 * unlisted frequency, this function always "rounds down" in case
-	 * of an unlisted frequency. That way, when cpufreq_online()
-	 * triggers the first ever call to cpr_set_performance_state(),
-	 * it will correctly determine the direction as UP.
-	 */
-	for (iter = corners; iter <= end; iter++) {
-		if (iter->corner.freq > rate)
-			break;
-		ret++;
-		if (iter->corner.freq == rate) {
-			corner = iter;
-			break;
-		}
-		if (iter->corner.freq < rate)
-			corner = iter;
-	}
-
-	if (!corner) {
-		dev_err(dev, "boot up corner not found\n");
-		return -EINVAL;
-	}
-
-	dev_dbg(dev, "boot up perf state: %u\n", ret);
-
-	return ret;
-}
-
-/**
- * cpr3_find_initial_corner() - Finds boot-up p-state and enables CPR
- * @thread: Structure holding CPR thread-specific parameters
- *
- * Differently from CPRv1, from CPRv3 onwards when we successfully find
- * the target boot-up performance state, we must refresh the HW
- * immediately to guarantee system stability and to avoid overheating
- * during the boot process, thing that would more likely happen without
- * this driver doing its job.
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr3_find_initial_corner(struct cpr_thread *thread)
-{
-	struct cpr_drv *drv = thread->drv;
-	struct cpr_corner *corner;
-	int uV, idx;
-
-	idx = cpr_find_initial_corner(drv->dev, thread->cpu_clk,
-				      thread->corners,
-				      thread->num_corners);
-	if (idx < 0)
-		return idx;
-
-	cpr_ctl_disable(thread);
-
-	corner = &thread->corners[idx];
-	cpr_corner_restore(thread, corner);
-
-	uV = regulator_get_voltage(drv->vreg);
-	uV = clamp(uV, corner->corner.min_uV, corner->corner.max_uV);
-
-	corner->last_uV = uV;
-	if (!drv->last_uV)
-		drv->last_uV = uV;
-
-	cpr_commit_state(thread);
-	thread->enabled = true;
-	cpr_switch(drv);
-
-	return 0;
-}
-
-static const int msm8998_gold_scaling_factor[][CPR3_RO_COUNT] = {
-	/* Fuse Corner 0 */
-	{
-		2857, 3057, 2828, 2952, 2699, 2798, 2446, 2631,
-		2629, 2578, 2244, 3344, 3289, 3137, 3164, 2655
-	},
-	/* Fuse Corner 1 */
-	{
-		2857, 3057, 2828, 2952, 2699, 2798, 2446, 2631,
-		2629, 2578, 2244, 3344, 3289, 3137, 3164, 2655
-	},
-	/* Fuse Corner 2 */
-	{
-		2603, 2755, 2676, 2777, 2573, 2685, 2465, 2610,
-		2312, 2423, 2243, 3104, 3022, 3036, 2740, 2303
-	},
-	/* Fuse Corner 3 */
-	{
-		1901, 2016, 2096, 2228, 2034, 2161, 2077, 2188,
-		1565, 1870, 1925, 2235, 2205, 2413, 1762, 1478
-	}
-};
-
-static const int msm8998_silver_scaling_factor[][CPR3_RO_COUNT] = {
-	/* Fuse Corner 0 */
-	{
-		2595, 2794, 2577, 2762, 2471, 2674, 2199, 2553,
-		3189, 3255, 3192, 2962, 3054, 2982, 2042, 2945
-	},
-	/* Fuse Corner 1 */
-	{
-		2595, 2794, 2577, 2762, 2471, 2674, 2199, 2553,
-		3189, 3255, 3192, 2962, 3054, 2982, 2042, 2945
-	},
-	/* Fuse Corner 2 */
-	{
-		2391, 2550, 2483, 2638, 2382, 2564, 2259, 2555,
-		2766, 3041, 2988, 2935, 2873, 2688, 2013, 2784
-	},
-	/* Fuse Corner 3 */
-	{
-		2066, 2153, 2300, 2434, 2220, 2386, 2288, 2465,
-		2028, 2511, 2487, 2734, 2554, 2117, 1892, 2377
-	}
-};
-
-static const struct cpr_thread_desc msm8998_thread_gold = {
-	.controller_id = 1,
-	.hw_tid = 0,
-	.ro_scaling_factor = msm8998_gold_scaling_factor,
-	.ro_avail_corners = ARRAY_SIZE(msm8998_gold_scaling_factor),
-	.sensor_range_start = 0,
-	.sensor_range_end = 9,
-	.init_voltage_step = 10000,
-	.init_voltage_width = 6,
-	.step_quot_init_min = 9,
-	.step_quot_init_max = 14,
-	.num_fuse_corners = 4,
-	.fuse_corner_data = (struct fuse_corner_data[]){
-		/* fuse corner 0 */
-		{
-			.ref_uV = 756000,
-			.max_uV = 828000,
-			.min_uV = 568000,
-			.range_uV = 32000,
-			.volt_cloop_adjust = 0,
-			.volt_oloop_adjust = 8000,
-			.max_volt_scale = 4,
-			.max_quot_scale = 10,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 1 */
-		{
-			.ref_uV = 756000,
-			.max_uV = 900000,
-			.min_uV = 624000,
-			.range_uV = 32000,
-			.volt_cloop_adjust = 0,
-			.volt_oloop_adjust = 0,
-			.max_volt_scale = 320,
-			.max_quot_scale = 350,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 2 */
-		{
-			.ref_uV = 828000,
-			.max_uV = 952000,
-			.min_uV = 632000,
-			.range_uV = 32000,
-			.volt_cloop_adjust = 12000,
-			.volt_oloop_adjust = 12000,
-			.max_volt_scale = 620,
-			.max_quot_scale = 750,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 3 */
-		{
-			.ref_uV = 1056000,
-			.max_uV = 1136000,
-			.min_uV = 772000,
-			.range_uV = 40000,
-			.volt_cloop_adjust = 50000,
-			.volt_oloop_adjust = 52000,
-			.max_volt_scale = 580,
-			.max_quot_scale = 1040,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-	},
-};
-
-static const struct cpr_thread_desc msm8998_thread_silver = {
-	.controller_id = 0,
-	.hw_tid = 0,
-	.ro_scaling_factor = msm8998_silver_scaling_factor,
-	.ro_avail_corners = ARRAY_SIZE(msm8998_silver_scaling_factor),
-	.sensor_range_start = 0,
-	.sensor_range_end = 6,
-	.init_voltage_step = 10000,
-	.init_voltage_width = 6,
-	.step_quot_init_min = 11,
-	.step_quot_init_max = 12,
-	.num_fuse_corners = 4,
-	.fuse_corner_data = (struct fuse_corner_data[]){
-		/* fuse corner 0 */
-		{
-			.ref_uV = 688000,
-			.max_uV = 828000,
-			.min_uV = 568000,
-			.range_uV = 32000,
-			.volt_cloop_adjust = 20000,
-			.volt_oloop_adjust = 40000,
-			.max_volt_scale = 4,
-			.max_quot_scale = 10,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 1 */
-		{
-			.ref_uV = 756000,
-			.max_uV = 900000,
-			.min_uV = 632000,
-			.range_uV = 32000,
-			.volt_cloop_adjust = 26000,
-			.volt_oloop_adjust = 24000,
-			.max_volt_scale = 500,
-			.max_quot_scale = 800,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 2 */
-		{
-			.ref_uV = 828000,
-			.max_uV = 952000,
-			.min_uV = 664000,
-			.range_uV = 32000,
-			.volt_cloop_adjust = 12000,
-			.volt_oloop_adjust = 12000,
-			.max_volt_scale = 280,
-			.max_quot_scale = 650,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-
-		},
-		/* fuse corner 3 */
-		{
-			.ref_uV = 1056000,
-			.max_uV = 1056000,
-			.min_uV = 772000,
-			.range_uV = 40000,
-			.volt_cloop_adjust = 30000,
-			.volt_oloop_adjust = 30000,
-			.max_volt_scale = 430,
-			.max_quot_scale = 800,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-	},
-};
-
-static const struct cpr_desc msm8998_cpr_desc = {
-	.cpr_type = CTRL_TYPE_CPRH,
-	.num_threads = 2,
-	.mem_acc_threshold = 852000,
-	.apm_threshold = 800000,
-	.apm_crossover = 880000,
-	.apm_hysteresis = 0,
-	.cpr_base_voltage = 352000,
-	.cpr_max_voltage = 1200000,
-	.timer_delay_us = 5000,
-	.timer_cons_up = 0,
-	.timer_cons_down = 2,
-	.up_threshold = 2,
-	.down_threshold = 2,
-	.idle_clocks = 15,
-	.count_mode = CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN,
-	.count_repeat = 14,
-	.gcnt_us = 1,
-	.vreg_step_fixed = 4000,
-	.vreg_step_up_limit = 1,
-	.vreg_step_down_limit = 1,
-	.vdd_settle_time_us = 34,
-	.corner_settle_time_us = 6,
-	.reduce_to_corner_uV = true,
-	.hw_closed_loop_en = true,
-	.threads = (const struct cpr_thread_desc *[]) {
-		&msm8998_thread_silver,
-		&msm8998_thread_gold,
-	},
-};
-
-static const struct cpr_acc_desc msm8998_cpr_acc_desc = {
-	.cpr_desc = &msm8998_cpr_desc,
-};
-
-static const int sdm630_gold_scaling_factor[][CPR3_RO_COUNT] = {
-	/* Same RO factors for all fuse corners */
-	{
-		4040, 3230,    0, 2210, 2560, 2450, 2230, 2220,
-		2410, 2300, 2560, 2470, 1600, 3120, 2620, 2280
-	}
-};
-
-static const int sdm630_silver_scaling_factor[][CPR3_RO_COUNT] = {
-	/* Same RO factors for all fuse corners */
-	{
-		3600, 3600, 3830, 2430, 2520, 2700, 1790, 1760,
-		1970, 1880, 2110, 2010, 2510, 4900, 4370, 4780,
-	}
-};
-
-static const struct cpr_thread_desc sdm630_thread_gold = {
-	.controller_id = 0,
-	.hw_tid = 0,
-	.ro_scaling_factor = sdm630_gold_scaling_factor,
-	.ro_avail_corners = ARRAY_SIZE(sdm630_gold_scaling_factor),
-	.sensor_range_start = 0,
-	.sensor_range_end = 6,
-	.init_voltage_step = 10000,
-	.init_voltage_width = 6,
-	.step_quot_init_min = 12,
-	.step_quot_init_max = 14,
-	.num_fuse_corners = 5,
-	.fuse_corner_data = (struct fuse_corner_data[]){
-		/* fuse corner 0 */
-		{
-			.ref_uV = 644000,
-			.max_uV = 724000,
-			.min_uV = 588000,
-			.range_uV = 40000,
-			.volt_cloop_adjust = -30000,
-			.volt_oloop_adjust = 15000,
-			.max_volt_scale = 10,
-			.max_quot_scale = 300,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 1 */
-		{
-			.ref_uV = 788000,
-			.max_uV = 788000,
-			.min_uV = 652000,
-			.range_uV = 40000,
-			.volt_cloop_adjust = -30000,
-			.volt_oloop_adjust = 5000,
-			.max_volt_scale = 320,
-			.max_quot_scale = 275,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 2 */
-		{
-			.ref_uV = 868000,
-			.max_uV = 868000,
-			.min_uV = 712000,
-			.range_uV = 40000,
-			.volt_cloop_adjust = -30000,
-			.volt_oloop_adjust = 5000,
-			.max_volt_scale = 350,
-			.max_quot_scale = 800,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 3 */
-		{
-			.ref_uV = 988000,
-			.max_uV = 988000,
-			.min_uV = 784000,
-			.range_uV = 66000,
-			.volt_cloop_adjust = -30000,
-			.volt_oloop_adjust = 0,
-			.max_volt_scale = 868,
-			.max_quot_scale = 980,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 4 */
-		{
-			.ref_uV = 1068000,
-			.max_uV = 1068000,
-			.min_uV = 844000,
-			.range_uV = 40000,
-			.volt_cloop_adjust = -30000,
-			.volt_oloop_adjust = 0,
-			.max_volt_scale = 868,
-			.max_quot_scale = 980,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-	},
-};
-
-static const struct cpr_thread_desc sdm630_thread_silver = {
-	.controller_id = 1,
-	.hw_tid = 0,
-	.ro_scaling_factor = sdm630_silver_scaling_factor,
-	.ro_avail_corners = ARRAY_SIZE(sdm630_silver_scaling_factor),
-	.sensor_range_start = 0,
-	.sensor_range_end = 6,
-	.init_voltage_step = 10000,
-	.init_voltage_width = 6,
-	.step_quot_init_min = 12,
-	.step_quot_init_max = 14,
-	.num_fuse_corners = 3,
-	.fuse_corner_data = (struct fuse_corner_data[]){
-		/* fuse corner 0 */
-		{
-			.ref_uV = 644000,
-			.max_uV = 724000,
-			.min_uV = 588000,
-			.range_uV = 32000,
-			.volt_cloop_adjust = -30000,
-			.volt_oloop_adjust = 0,
-			.max_volt_scale = 10,
-			.max_quot_scale = 360,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 1 */
-		{
-			.ref_uV = 788000,
-			.max_uV = 788000,
-			.min_uV = 652000,
-			.range_uV = 40000,
-			.volt_cloop_adjust = -30000,
-			.volt_oloop_adjust = 0,
-			.max_volt_scale = 500,
-			.max_quot_scale = 550,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-		/* fuse corner 2 */
-		{
-			.ref_uV = 1068000,
-			.max_uV = 1068000,
-			.min_uV = 800000,
-			.range_uV = 40000,
-			.volt_cloop_adjust = -30000,
-			.volt_oloop_adjust = 0,
-			.max_volt_scale = 2370,
-			.max_quot_scale = 550,
-			.quot_offset = 0,
-			.quot_scale = 1,
-			.quot_adjust = 0,
-			.quot_offset_scale = 5,
-			.quot_offset_adjust = 0,
-		},
-	},
-};
-
-static const struct cpr_desc sdm630_cpr_desc = {
-	.cpr_type = CTRL_TYPE_CPRH,
-	.num_threads = 2,
-	.apm_threshold = 872000,
-	.apm_crossover = 872000,
-	.apm_hysteresis = 20000,
-	.cpr_base_voltage = 400000,
-	.cpr_max_voltage = 1300000,
-	.timer_delay_us = 5000,
-	.timer_cons_up = 0,
-	.timer_cons_down = 2,
-	.up_threshold = 2,
-	.down_threshold = 2,
-	.idle_clocks = 15,
-	.count_mode = CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN,
-	.count_repeat = 14,
-	.gcnt_us = 1,
-	.vreg_step_fixed = 4000,
-	.vreg_step_up_limit = 1,
-	.vreg_step_down_limit = 1,
-	.vdd_settle_time_us = 34,
-	.corner_settle_time_us = 5,
-	.reduce_to_corner_uV = true,
-	.hw_closed_loop_en = true,
-	.threads = (const struct cpr_thread_desc *[]) {
-		&sdm630_thread_gold,
-		&sdm630_thread_silver,
-	},
-};
-
-static const struct cpr_acc_desc sdm630_cpr_acc_desc = {
-	.cpr_desc = &sdm630_cpr_desc,
-};
-
-static unsigned int cpr_get_performance_state(struct generic_pm_domain *genpd,
-					      struct dev_pm_opp *opp)
-{
-	return dev_pm_opp_get_level(opp);
-}
-
-static int cpr_power_off(struct generic_pm_domain *domain)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-
-	return cpr_disable(thread);
-}
-
-static int cpr_power_on(struct generic_pm_domain *domain)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-
-	return cpr_enable(thread);
-}
-
-static void cpr_pd_detach_dev(struct generic_pm_domain *domain,
-			      struct device *dev)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-	struct cpr_drv *drv = thread->drv;
-
-	mutex_lock(&drv->lock);
-
-	dev_dbg(drv->dev, "detach callback for: %s\n", dev_name(dev));
-	thread->attached_cpu_dev = NULL;
-
-	mutex_unlock(&drv->lock);
-}
-
-static int cpr_pd_attach_dev(struct generic_pm_domain *domain,
-			     struct device *dev)
-{
-	struct cpr_thread *thread = container_of(domain, struct cpr_thread, pd);
-	struct cpr_drv *drv = thread->drv;
-	const struct acc_desc *acc_desc = drv->acc_desc;
-	bool cprh_opp_remove_table = false;
-	int ret = 0;
-
-	mutex_lock(&drv->lock);
-
-	dev_dbg(drv->dev, "attach callback for: %s\n", dev_name(dev));
-
-	/*
-	 * This driver only supports scaling voltage for a CPU cluster
-	 * where all CPUs in the cluster share a single regulator.
-	 * Therefore, save the struct device pointer only for the first
-	 * CPU device that gets attached. There is no need to do any
-	 * additional initialization when further CPUs get attached.
-	 * This is not an error condition.
-	 */
-	if (thread->attached_cpu_dev)
-		goto unlock;
-
-	/*
-	 * cpr_scale_voltage() requires the direction (if we are changing
-	 * to a higher or lower OPP). The first time
-	 * cpr_set_performance_state() is called, there is no previous
-	 * performance state defined. Therefore, we call
-	 * cpr_find_initial_corner() that gets the CPU clock frequency
-	 * set by the bootloader, so that we can determine the direction
-	 * the first time cpr_set_performance_state() is called.
-	 */
-	thread->cpu_clk = devm_clk_get(dev, NULL);
-	if (drv->desc->cpr_type < CTRL_TYPE_CPRH && IS_ERR(thread->cpu_clk)) {
-		ret = PTR_ERR(thread->cpu_clk);
-		if (ret != -EPROBE_DEFER)
-			dev_err(drv->dev, "could not get cpu clk: %d\n", ret);
-		goto unlock;
-	}
-	thread->attached_cpu_dev = dev;
-
-	/*
-	 * We are exporting the APM and MEM-ACC thresholds to the caller;
-	 * while APM is necessary in the CPU CPR case, MEM-ACC may not be,
-	 * depending on the SoC and on fuses.
-	 * Initialize both to an invalid value, so that the caller can check
-	 * if they got calculated or read from fuses in this driver.
-	 */
-	thread->ext_data.apm_threshold_uV = -1;
-	thread->ext_data.mem_acc_threshold_uV = -1;
-	dev_set_drvdata(thread->attached_cpu_dev, &thread->ext_data);
-
-	dev_dbg(drv->dev, "using cpu clk from: %s\n",
-		dev_name(thread->attached_cpu_dev));
-
-	/*
-	 * Everything related to (virtual) corners has to be initialized
-	 * here, when attaching to the power domain, since we need to know
-	 * the maximum frequency for each fuse corner, and this is only
-	 * available after the cpufreq driver has attached to us.
-	 * The reason for this is that we need to know the highest
-	 * frequency associated with each fuse corner.
-	 */
-	ret = dev_pm_opp_get_opp_count(&thread->pd.dev);
-	if (ret < 0) {
-		dev_err(drv->dev, "could not get OPP count\n");
-		thread->attached_cpu_dev = NULL;
-		goto unlock;
-	}
-	thread->num_corners = ret;
-
-	thread->corners = devm_kcalloc(drv->dev,
-				       thread->num_corners +
-				       drv->extra_corners,
-				       sizeof(*thread->corners),
-				       GFP_KERNEL);
-	if (!thread->corners) {
-		ret = -ENOMEM;
-		goto unlock;
-	}
-
-	/*
-	 * If we are on CPR-Hardened we have to make sure that the attached
-	 * device has a OPP table installed, as we're going to modify it here
-	 * with our calculations based on qfprom values.
-	 */
-	if (drv->desc->cpr_type == CTRL_TYPE_CPRH) {
-		ret = dev_pm_opp_of_add_table(dev);
-		if (ret && ret != -EEXIST) {
-			dev_err(drv->dev, "Cannot add table: %d\n", ret);
-			goto unlock;
-		}
-		cprh_opp_remove_table = true;
-	}
-
-	ret = cpr3_corner_init(thread);
-	if (ret)
-		goto exit;
-
-	if (drv->desc->cpr_type < CTRL_TYPE_CPRH) {
-		ret = cpr3_find_initial_corner(thread);
-		if (ret)
-			goto exit;
-
-		if (acc_desc->config)
-			regmap_multi_reg_write(drv->tcsr, acc_desc->config,
-					       acc_desc->num_regs_per_fuse);
-
-		/* Enable ACC if required */
-		if (acc_desc->enable_mask)
-			regmap_update_bits(drv->tcsr, acc_desc->enable_reg,
-					   acc_desc->enable_mask,
-					   acc_desc->enable_mask);
-	}
-	dev_info(drv->dev, "thread %d initialized with %u OPPs\n",
-		 thread->id, thread->num_corners);
-exit:
-	/*
-	 * If we are on CPRh and we reached an error condition, we installed
-	 * the OPP table but we haven't done any setup on it, nor we ever will.
-	 * In order to leave a clean state, remove the table.
-	 */
-	if (ret && cprh_opp_remove_table)
-		dev_pm_opp_of_remove_table(thread->attached_cpu_dev);
-unlock:
-	mutex_unlock(&drv->lock);
-
-	return ret;
-}
-
-static int cpr3_debug_info_show(struct seq_file *s, void *unused)
-{
-	u32 ro_sel, ctl, irq_status, reg, quot;
-	struct cpr_thread *thread = s->private;
-	struct cpr_corner *corner = thread->corners;
-	struct fuse_corner *fuse = thread->fuse_corners;
-	unsigned int i;
-
-	const struct {
-		const char *name;
-		uint32_t mask;
-		uint8_t shift;
-	} result0_fields[] = {
-		{ "busy", 1, 0 },
-		{ "step_dn", 1, 1 },
-		{ "step_up", 1, 2 },
-		{ "error_steps", CPR3_RESULT0_ERROR_STEPS_MASK,
-				 CPR3_RESULT0_ERROR_STEPS_SHIFT },
-		{ "error", CPR3_RESULT0_ERROR_MASK, CPR3_RESULT0_ERROR_SHIFT },
-		{ "negative", 1, 20 },
-	}, result1_fields[] = {
-		{ "quot_min", CPR3_RESULT1_QUOT_MIN_MASK,
-			      CPR3_RESULT1_QUOT_MIN_SHIFT },
-		{ "quot_max", CPR3_RESULT1_QUOT_MAX_MASK,
-			      CPR3_RESULT1_QUOT_MAX_SHIFT },
-		{ "ro_min", CPR3_RESULT1_RO_MIN_MASK,
-			    CPR3_RESULT1_RO_MIN_SHIFT },
-		{ "ro_max", CPR3_RESULT1_RO_MAX_MASK,
-			    CPR3_RESULT1_RO_MAX_SHIFT },
-	}, result2_fields[] = {
-		{ "qout_step_min", CPR3_RESULT2_STEP_QUOT_MIN_MASK,
-				   CPR3_RESULT2_STEP_QUOT_MIN_SHIFT },
-		{ "qout_step_max", CPR3_RESULT2_STEP_QUOT_MAX_MASK,
-				   CPR3_RESULT2_STEP_QUOT_MAX_SHIFT },
-		{ "sensor_min", CPR3_RESULT2_SENSOR_MIN_MASK,
-				CPR3_RESULT2_SENSOR_MIN_SHIFT },
-		{ "sensor_max", CPR3_RESULT2_SENSOR_MAX_MASK,
-				CPR3_RESULT2_SENSOR_MAX_SHIFT },
-	};
-
-	if (thread->drv->desc->cpr_type < CTRL_TYPE_CPRH)
-		seq_printf(s, "current_volt = %d uV\n", thread->drv->last_uV);
-
-	irq_status = cpr_read(thread, CPR3_REG_IRQ_STATUS);
-	seq_printf(s, "irq_status = %#02X\n", irq_status);
-
-	ctl = cpr_read(thread, CPR3_REG_CPR_CTL);
-	seq_printf(s, "cpr_ctl = %#02X\n", ctl);
-
-	seq_printf(s, "thread %d - hw tid: %u - enabled: %d:\n",
-		   thread->id, thread->desc->hw_tid, thread->enabled);
-	seq_printf(s, "%d corners, derived from %d fuse corners\n",
-		   thread->num_corners, thread->desc->num_fuse_corners);
-
-	for (i = 0; i < thread->num_corners; i++, corner++)
-		seq_printf(s, "corner %d - uV=[%d %d %d] quot=%d freq=%lu\n",
-			   i, corner->corner.min_uV, corner->corner.uV, corner->corner.max_uV,
-			   corner->quot_adjust, corner->corner.freq);
-
-	for (i = 0; i < thread->desc->num_fuse_corners; i++, fuse++)
-		seq_printf(s, "fuse %d - uV=[%d %d %d] quot=%d freq=%lu\n",
-			   i, fuse->min_uV, fuse->uV, fuse->max_uV,
-			   fuse->quot, corner ? corner->corner.freq : 0UL);
-
-	seq_printf(s, "requested voltage: %d uV\n", thread->corner->last_uV);
-
-	if (corner && corner->corner.fuse_corner) {
-		ro_sel = corner->corner.fuse_corner->ring_osc_idx;
-		quot = cpr_read(thread, CPR3_REG_TARGET_QUOT(i, ro_sel));
-		seq_printf(s, "quot_target (%u) = %#02X\n", ro_sel, quot);
-	}
-
-	reg = cpr_read(thread, CPR3_REG_RESULT0(i));
-	seq_printf(s, "cpr_result_0 = %#02X\n  [", reg);
-	for (i = 0; i < ARRAY_SIZE(result0_fields); i++)
-		seq_printf(s, "%s%s = %u",
-			   i ? ", " : "",
-			   result0_fields[i].name,
-			   (reg >> result0_fields[i].shift) &
-				result0_fields[i].mask);
-	seq_puts(s, "]\n");
-	reg = cpr_read(thread, CPR3_REG_RESULT1(i));
-	seq_printf(s, "cpr_result_1 = %#02X\n  [", reg);
-	for (i = 0; i < ARRAY_SIZE(result1_fields); i++)
-		seq_printf(s, "%s%s = %u",
-			   i ? ", " : "",
-			   result1_fields[i].name,
-			   (reg >> result1_fields[i].shift) &
-				result1_fields[i].mask);
-	seq_puts(s, "]\n");
-	reg = cpr_read(thread, CPR3_REG_RESULT2(i));
-	seq_printf(s, "cpr_result_2 = %#02X\n  [", reg);
-	for (i = 0; i < ARRAY_SIZE(result2_fields); i++)
-		seq_printf(s, "%s%s = %u",
-			   i ? ", " : "",
-			   result2_fields[i].name,
-			   (reg >> result2_fields[i].shift) &
-				result2_fields[i].mask);
-	seq_puts(s, "]\n");
-
-	return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(cpr3_debug_info);
-
-static void cpr3_debugfs_init(struct cpr_drv *drv)
-{
-	int i;
-
-	drv->debugfs = debugfs_create_dir("qcom_cpr3", NULL);
-
-	for (i = 0; i < drv->desc->num_threads; i++) {
-		char buf[50];
-
-		snprintf(buf, sizeof(buf), "thread%d", i);
-
-		debugfs_create_file(buf, 0444, drv->debugfs, &drv->threads[i],
-				    &cpr3_debug_info_fops);
-	}
-}
-
-/**
- * cpr_thread_init() - Initialize CPR thread related parameters
- * @drv: Main driver structure
- * @tid: Thread ID
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr_thread_init(struct cpr_drv *drv, int tid)
-{
-	const struct cpr_desc *desc = drv->desc;
-	const struct cpr_thread_desc *tdesc = desc->threads[tid];
-	struct cpr_thread *thread = &drv->threads[tid];
-	int ret;
-
-	if (tdesc->step_quot_init_min > CPR3_CPR_STEP_QUOT_MIN_MASK ||
-	    tdesc->step_quot_init_max > CPR3_CPR_STEP_QUOT_MAX_MASK)
-		return -EINVAL;
-
-	thread->id = tid;
-	thread->drv = drv;
-	thread->desc = tdesc;
-	thread->fuse_corners = devm_kcalloc(drv->dev,
-					    tdesc->num_fuse_corners +
-					    drv->extra_corners,
-					    sizeof(*thread->fuse_corners),
-					    GFP_KERNEL);
-	if (!thread->fuse_corners)
-		return -ENOMEM;
-
-	thread->cpr_fuses = cpr_get_fuses(drv->dev, tid,
-					  tdesc->num_fuse_corners);
-	if (IS_ERR(thread->cpr_fuses))
-		return PTR_ERR(thread->cpr_fuses);
-
-	ret = cpr_populate_ring_osc_idx(thread->drv->dev, thread->fuse_corners,
-					thread->cpr_fuses,
-					tdesc->num_fuse_corners);
-	if (ret)
-		return ret;
-
-	ret = cpr_fuse_corner_init(thread);
-	if (ret)
-		return ret;
-
-	thread->pd.name = devm_kasprintf(drv->dev, GFP_KERNEL,
-					 "%s_thread%d",
-					 drv->dev->of_node->full_name,
-					 thread->id);
-	if (!thread->pd.name)
-		return -EINVAL;
-
-	thread->pd.power_off = cpr_power_off;
-	thread->pd.power_on = cpr_power_on;
-	thread->pd.opp_to_performance_state = cpr_get_performance_state;
-	thread->pd.attach_dev = cpr_pd_attach_dev;
-	thread->pd.detach_dev = cpr_pd_detach_dev;
-
-	/* CPR-Hardened performance states are managed in firmware */
-	if (desc->cpr_type == CTRL_TYPE_CPRH) {
-		thread->pd.set_performance_state = cprh_dummy_set_performance_state;
-	} else {
-		thread->pd.set_performance_state = cpr_set_performance_state;
-	}
-
-	/* Anything later than CPR1 must be always-on for now */
-	thread->pd.flags = GENPD_FLAG_ALWAYS_ON;
-
-	drv->cell_data.domains[tid] = &thread->pd;
-
-	ret = pm_genpd_init(&thread->pd, NULL, false);
-	if (ret)
-		return ret;
-
-	/* On CPRhardened, the interrupts are managed in firmware */
-	if (desc->cpr_type < CTRL_TYPE_CPRH) {
-		INIT_WORK(&thread->restart_work, cpr_restart_worker);
-
-		ret = devm_request_threaded_irq(drv->dev, drv->irq,
-						NULL, cpr_irq_handler,
-						IRQF_ONESHOT |
-						IRQF_TRIGGER_RISING,
-						"cpr", drv);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-/**
- * cpr3_resources_init() - Initialize resources used by this driver
- * @pdev: Platform device
- * @drv:  Main driver structure
- *
- * Return: Zero for success, negative number on error
- */
-static int cpr3_resources_init(struct platform_device *pdev,
-			       struct cpr_drv *drv)
-{
-	const struct cpr_desc *desc = drv->desc;
-	struct cpr_thread *threads = drv->threads;
-	unsigned int i;
-	u8 cid_mask = 0;
-
-	/*
-	 * Here, we are accounting for the following usecases:
-	 * - One controller
-	 *   - One or multiple threads on the same iospace
-	 *
-	 * - Multiple controllers
-	 *   - Each controller has its own iospace and each
-	 *     may have one or multiple threads in their
-	 *     parent controller's iospace
-	 *
-	 * Then, to avoid complicating the code for no reason,
-	 * this also needs a mandatory order in the list of
-	 * threads which implies that all of them from the same
-	 * controllers are specified sequentially. As an example:
-	 *
-	 *      C0-T0, C0-T1...C0-Tn, C1-T0, C1-T1...C1-Tn
-	 */
-	for (i = 0; i < desc->num_threads; i++) {
-		u8 cid = desc->threads[i]->controller_id;
-
-		if (cid_mask & BIT(cid)) {
-			if (desc->threads[i - 1]->controller_id != cid) {
-				dev_err(drv->dev, "Bad threads order. Please fix!\n");
-				return -EINVAL;
-			}
-			threads[i].base = threads[i - 1].base;
-			continue;
-		}
-		threads[i].base = devm_platform_ioremap_resource(pdev, cid);
-		if (IS_ERR(threads[i].base))
-			return PTR_ERR(threads[i].base);
-		cid_mask |= BIT(cid);
-	}
-	return 0;
-}
-
-static int cpr_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct cpr_drv *drv;
-	const struct cpr_desc *desc;
-	const struct cpr_acc_desc *data;
-	struct device_node *np;
-	unsigned int i;
-	int ret;
-
-	data = of_device_get_match_data(dev);
-	if (!data || !data->cpr_desc)
-		return -EINVAL;
-
-	desc = data->cpr_desc;
-
-	/* CPRh disallows MEM-ACC access from the HLOS */
-	if (!data->acc_desc && desc->cpr_type < CTRL_TYPE_CPRH)
-		return -EINVAL;
-
-	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
-	if (!drv)
-		return -ENOMEM;
-
-	drv->dev = dev;
-	drv->desc = desc;
-	drv->threads = devm_kcalloc(dev, desc->num_threads,
-				    sizeof(*drv->threads), GFP_KERNEL);
-	if (!drv->threads)
-		return -ENOMEM;
-
-	drv->cell_data.num_domains = desc->num_threads;
-	drv->cell_data.domains = devm_kcalloc(drv->dev,
-					      drv->cell_data.num_domains,
-					      sizeof(*drv->cell_data.domains),
-					      GFP_KERNEL);
-	if (!drv->cell_data.domains)
-		return -ENOMEM;
-
-	if (data->acc_desc)
-		drv->acc_desc = data->acc_desc;
-
-	mutex_init(&drv->lock);
-
-	if (desc->cpr_type < CTRL_TYPE_CPRH) {
-		np = of_parse_phandle(dev->of_node, "acc-syscon", 0);
-		if (!np)
-			return -ENODEV;
-
-		drv->tcsr = syscon_node_to_regmap(np);
-		of_node_put(np);
-		if (IS_ERR(drv->tcsr))
-			return PTR_ERR(drv->tcsr);
-	}
-
-	ret = cpr3_resources_init(pdev, drv);
-	if (ret)
-		return ret;
-
-	drv->irq = platform_get_irq_optional(pdev, 0);
-	if ((desc->cpr_type != CTRL_TYPE_CPRH) && (drv->irq < 0))
-		return -EINVAL;
-
-	/* On CPRhardened, vreg access it not allowed */
-	drv->vreg = devm_regulator_get_optional(dev, "vdd");
-	if (desc->cpr_type != CTRL_TYPE_CPRH && IS_ERR(drv->vreg))
-		return PTR_ERR(drv->vreg);
-
-	/*
-	 * On at least CPRhardened, vreg is unaccessible and there is no
-	 * way to read linear step from that regulator, hence it is hardcoded
-	 * in the driver;
-	 * When the vreg_step is not declared in the cpr data (or is zero),
-	 * then having access to the vreg regulator is mandatory, as this
-	 * will be retrieved through the regulator API.
-	 */
-	if (desc->vreg_step_fixed)
-		drv->vreg_step = desc->vreg_step_fixed;
-	else
-		drv->vreg_step = regulator_get_linear_step(drv->vreg);
-
-	if (!drv->vreg_step)
-		return -EINVAL;
-
-	/*
-	 * Initialize fuse corners, since it simply depends
-	 * on data in efuses.
-	 * Everything related to (virtual) corners has to be
-	 * initialized after attaching to the power domain,
-	 * since it depends on the CPU's OPP table.
-	 */
-	ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &drv->fusing_rev);
-	if (ret)
-		return ret;
-
-	dev_dbg(dev, "Fusing revision %d\n", drv->fusing_rev);
-
-	ret = nvmem_cell_read_variable_le_u32(dev, "cpr_speed_bin", &drv->speed_bin);
-	if (ret)
-		return ret;
-
-	dev_dbg(dev, "Speed bin %d\n", drv->speed_bin);
-
-	/*
-	 * Some SoCs require extra corners for MEM-ACC or APM: if
-	 * the related parameters have been specified, then reserve
-	 * a corner for the APM and/or MEM-ACC crossover, used by
-	 * OSM and CPRh HW to set the supply voltage during the APM
-	 * and/or MEM-ACC switch routine.
-	 */
-	if (desc->cpr_type == CTRL_TYPE_CPRH) {
-		if (desc->apm_crossover && desc->apm_hysteresis >= 0)
-			drv->extra_corners++;
-
-		if (desc->mem_acc_threshold)
-			drv->extra_corners++;
-	}
-
-	/* Initialize all threads */
-	for (i = 0; i < desc->num_threads; i++) {
-		ret = cpr_thread_init(drv, i);
-		if (ret)
-			return ret;
-	}
-
-	/* Initialize global parameters */
-	ret = cpr3_init_parameters(drv);
-	if (ret)
-		return ret;
-
-	/* Write initial configuration on all threads */
-	for (i = 0; i < desc->num_threads; i++) {
-		ret = cpr_configure(&drv->threads[i]);
-		if (ret)
-			return ret;
-	}
-
-	ret = of_genpd_add_provider_onecell(dev->of_node, &drv->cell_data);
-	if (ret)
-		return ret;
-
-	platform_set_drvdata(pdev, drv);
-	cpr3_debugfs_init(drv);
-
-	return 0;
-}
-
-static int cpr_remove(struct platform_device *pdev)
-{
-	struct cpr_drv *drv = platform_get_drvdata(pdev);
-	int i;
-
-	of_genpd_del_provider(pdev->dev.of_node);
-
-	for (i = 0; i < drv->desc->num_threads; i++) {
-		cpr_ctl_disable(&drv->threads[i]);
-		cpr_irq_set(&drv->threads[i], 0);
-		pm_genpd_remove(&drv->threads[i].pd);
-	}
-
-	debugfs_remove_recursive(drv->debugfs);
-
-	return 0;
-}
-
-static const struct of_device_id cpr3_match_table[] = {
-	{ .compatible = "qcom,msm8998-cprh", .data = &msm8998_cpr_acc_desc },
-	{ .compatible = "qcom,sdm630-cprh", .data = &sdm630_cpr_acc_desc },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, cpr3_match_table);
-
-static struct platform_driver cpr3_driver = {
-	.probe		= cpr_probe,
-	.remove		= cpr_remove,
-	.driver		= {
-		.name	= "qcom-cpr3",
-		.of_match_table = cpr3_match_table,
-	},
-};
-module_platform_driver(cpr3_driver)
-
-MODULE_DESCRIPTION("Core Power Reduction (CPR) v3/v4 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/kernel/drivers/thermal/Kconfig b/kernel/drivers/thermal/Kconfig
index 62157d0c099d..d7f44deab5b1 100644
--- a/kernel/drivers/thermal/Kconfig
+++ b/kernel/drivers/thermal/Kconfig
@@ -493,11 +493,4 @@ config KHADAS_MCU_FAN_THERMAL
 	  If you say yes here you get support for the FAN controlled
 	  by the Microcontroller found on the Khadas VIM boards.
 
-config PD_COOLING
-	tristate "Generic warming up device using power domains"
-	depends on OF || COMPILE_TEST
-	help
-	  If you say yes here support for the generic power-domain-based
-	  warming up will be enabled.
-
 endif
diff --git a/kernel/drivers/thermal/Makefile b/kernel/drivers/thermal/Makefile
index 29b5db085c2d..82fc3e616e54 100644
--- a/kernel/drivers/thermal/Makefile
+++ b/kernel/drivers/thermal/Makefile
@@ -60,4 +60,3 @@ obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
 obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
 obj-$(CONFIG_SPRD_THERMAL)	+= sprd_thermal.o
 obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL)	+= khadas_mcu_fan.o
-obj-$(CONFIG_PD_COOLING) 	+= pd_cooling.o
diff --git a/kernel/drivers/thermal/cpufreq_cooling.c b/kernel/drivers/thermal/cpufreq_cooling.c
index 47bc2ef006e1..43b1ae8a7789 100644
--- a/kernel/drivers/thermal/cpufreq_cooling.c
+++ b/kernel/drivers/thermal/cpufreq_cooling.c
@@ -67,7 +67,6 @@ struct time_in_idle {
  */
 struct cpufreq_cooling_device {
 	u32 last_load;
-	bool warming;
 	unsigned int cpufreq_state;
 	unsigned int max_level;
 	struct em_perf_domain *em;
@@ -76,7 +75,6 @@ struct cpufreq_cooling_device {
 	struct time_in_idle *idle_time;
 #endif
 	struct freq_qos_request qos_req;
-	struct thermal_cooling_device *warming_cdev;
 };
 
 #ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
@@ -389,9 +387,6 @@ static unsigned int get_state_freq(struct cpufreq_cooling_device *cpufreq_cdev,
 	struct cpufreq_policy *policy;
 	unsigned long idx;
 
-	if (cpufreq_cdev->warming)
-		state = cpufreq_cdev->max_level - state;
-
 #ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
 	/* Use the Energy Model table if available */
 	if (cpufreq_cdev->em) {
@@ -520,7 +515,6 @@ static struct thermal_cooling_device_ops cpufreq_cooling_ops = {
 static struct thermal_cooling_device *
 __cpufreq_cooling_register(struct device_node *np,
 			struct cpufreq_policy *policy,
-			bool warming,
 			struct em_perf_domain *em)
 {
 	struct thermal_cooling_device *cdev;
@@ -529,7 +523,6 @@ __cpufreq_cooling_register(struct device_node *np,
 	struct device *dev;
 	int ret;
 	struct thermal_cooling_device_ops *cooling_ops;
-	enum freq_qos_req_type req_type = warming ? FREQ_QOS_MIN : FREQ_QOS_MAX;
 	char *name;
 
 	dev = get_cpu_device(policy->cpu);
@@ -554,7 +547,6 @@ __cpufreq_cooling_register(struct device_node *np,
 	if (!cpufreq_cdev)
 		return ERR_PTR(-ENOMEM);
 
-	cpufreq_cdev->warming = warming;
 	cpufreq_cdev->policy = policy;
 
 	ret = allocate_idle_time(cpufreq_cdev);
@@ -584,7 +576,7 @@ __cpufreq_cooling_register(struct device_node *np,
 	}
 
 	ret = freq_qos_add_request(&policy->constraints,
-				   &cpufreq_cdev->qos_req, req_type,
+				   &cpufreq_cdev->qos_req, FREQ_QOS_MAX,
 				   get_state_freq(cpufreq_cdev, 0));
 	if (ret < 0) {
 		pr_err("%s: Failed to add freq constraint (%d)\n", __func__,
@@ -630,7 +622,7 @@ __cpufreq_cooling_register(struct device_node *np,
 struct thermal_cooling_device *
 cpufreq_cooling_register(struct cpufreq_policy *policy)
 {
-	return __cpufreq_cooling_register(NULL, policy, false, NULL);
+	return __cpufreq_cooling_register(NULL, policy, NULL);
 }
 EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
 
@@ -657,7 +649,6 @@ struct thermal_cooling_device *
 of_cpufreq_cooling_register(struct cpufreq_policy *policy)
 {
 	struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
-	struct device_node *warm_np;
 	struct thermal_cooling_device *cdev = NULL;
 
 	if (!np) {
@@ -669,7 +660,7 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
 	if (of_find_property(np, "#cooling-cells", NULL)) {
 		struct em_perf_domain *em = em_cpu_get(policy->cpu);
 
-		cdev = __cpufreq_cooling_register(np, policy, false, em);
+		cdev = __cpufreq_cooling_register(np, policy, em);
 		if (IS_ERR(cdev)) {
 			pr_err("cpufreq_cooling: cpu%d failed to register as cooling device: %ld\n",
 			       policy->cpu, PTR_ERR(cdev));
@@ -677,24 +668,6 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
 		}
 	}
 
-	warm_np = of_get_child_by_name(np, "warming");
-	if (warm_np) {
-		if (of_find_property(np, "#cooling-cells", NULL)) {
-			struct em_perf_domain *em = em_cpu_get(policy->cpu);
-			struct cpufreq_cooling_device *cpufreq_cdev;
-			struct thermal_cooling_device *warm_cdev;
-
-			cpufreq_cdev = cdev->devdata;
-
-			warm_cdev = __cpufreq_cooling_register(warm_np, policy, true, em);
-			if (IS_ERR(warm_cdev))
-				pr_err("cpufreq_cooling: cpu%d failed to register as warming up device: %ld\n",
-				       policy->cpu, PTR_ERR(warm_cdev));
-			else
-				cpufreq_cdev->warming_cdev = warm_cdev;
-		}
-	}
-
 	of_node_put(np);
 	return cdev;
 }
@@ -715,11 +688,6 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 	cpufreq_cdev = cdev->devdata;
 
-	if (cpufreq_cdev->warming_cdev) {
-		cpufreq_cooling_unregister(cpufreq_cdev->warming_cdev);
-		cpufreq_cdev->warming_cdev = NULL;
-	}
-
 	thermal_cooling_device_unregister(cdev);
 	freq_qos_remove_request(&cpufreq_cdev->qos_req);
 	free_idle_time(cpufreq_cdev);
diff --git a/kernel/drivers/thermal/devfreq_cooling.c b/kernel/drivers/thermal/devfreq_cooling.c
index 33e10950e035..d38a80adec73 100644
--- a/kernel/drivers/thermal/devfreq_cooling.c
+++ b/kernel/drivers/thermal/devfreq_cooling.c
@@ -48,18 +48,14 @@
  */
 struct devfreq_cooling_device {
 	struct thermal_cooling_device *cdev;
-	struct thermal_cooling_device *warm_cdev;
 	struct devfreq *devfreq;
 	unsigned long cooling_state;
-	unsigned long warming_state;
 	u32 *freq_table;
 	size_t max_state;
 	struct devfreq_cooling_power *power_ops;
 	u32 res_util;
 	int capped_state;
-	bool has_warming;
 	struct dev_pm_qos_request req_max_freq;
-	struct dev_pm_qos_request req_min_freq;
 	struct em_perf_domain *em_pd;
 };
 
@@ -115,43 +111,6 @@ static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev,
 	return 0;
 }
 
-static int devfreq_warming_get_cur_state(struct thermal_cooling_device *cdev,
-					 unsigned long *state)
-{
-	struct devfreq_cooling_device *dfc = cdev->devdata;
-
-	*state = dfc->warming_state;
-
-	return 0;
-}
-
-static int devfreq_warming_set_cur_state(struct thermal_cooling_device *cdev,
-					 unsigned long state)
-{
-	struct devfreq_cooling_device *dfc = cdev->devdata;
-	struct devfreq *df = dfc->devfreq;
-	struct device *dev = df->dev.parent;
-	unsigned long freq;
-
-	dev_info(dev, "Setting warming state %lu\n", state);
-	if (state == dfc->warming_state)
-		return 0;
-
-	dev_info(dev, "Setting warming state %lu\n", state);
-
-	if (state > dfc->max_state)
-		return -EINVAL;
-
-	freq = dfc->freq_table[dfc->max_state - state];
-
-	dev_pm_qos_update_request(&dfc->req_min_freq,
-				  DIV_ROUND_UP(freq, HZ_PER_KHZ));
-
-	dfc->warming_state = state;
-
-	return 0;
-}
-
 /**
  * get_perf_idx() - get the performance index corresponding to a frequency
  * @em_pd:	Pointer to device's Energy Model
@@ -337,12 +296,6 @@ static struct thermal_cooling_device_ops devfreq_cooling_ops = {
 	.set_cur_state = devfreq_cooling_set_cur_state,
 };
 
-static struct thermal_cooling_device_ops devfreq_warming_ops = {
-	.get_max_state = devfreq_cooling_get_max_state,
-	.get_cur_state = devfreq_warming_get_cur_state,
-	.set_cur_state = devfreq_warming_set_cur_state,
-};
-
 /**
  * devfreq_cooling_gen_tables() - Generate frequency table.
  * @dfc:	Pointer to devfreq cooling device.
@@ -402,11 +355,10 @@ struct thermal_cooling_device *
 of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
 				  struct devfreq_cooling_power *dfc_power)
 {
-	struct thermal_cooling_device *cdev, *warm_cdev;
+	struct thermal_cooling_device *cdev;
 	struct device *dev = df->dev.parent;
 	struct devfreq_cooling_device *dfc;
 	struct thermal_cooling_device_ops *ops;
-	struct device_node *warm_np;
 	char *name;
 	int err, num_opps;
 
@@ -475,38 +427,6 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
 
 	dfc->cdev = cdev;
 
-	if (np &&
-	    ((warm_np = of_get_child_by_name(np, "warming")) != NULL) &&
-	    of_find_property(warm_np, "#cooling-cells", NULL)) {
-		err = dev_pm_qos_add_request(dev, &dfc->req_min_freq,
-					     DEV_PM_QOS_MIN_FREQUENCY,
-					     PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE);
-		if (err < 0)
-			goto out;
-
-		name = kasprintf(GFP_KERNEL, "devfreq-%s-warm", dev_name(dev));
-		if (!name) {
-			dev_pm_qos_remove_request(&dfc->req_min_freq);
-			goto out;
-		}
-
-		warm_cdev = thermal_of_cooling_device_register(warm_np, name, dfc, &devfreq_warming_ops);
-		kfree(name);
-
-		if (IS_ERR(warm_cdev)) {
-			err = PTR_ERR(warm_cdev);
-			dev_err(dev,
-				"Failed to register devfreq warming device (%d)\n",
-				err);
-			dev_pm_qos_remove_request(&dfc->req_min_freq);
-			goto out;
-		}
-
-		dfc->warm_cdev = warm_cdev;
-		dfc->has_warming = true;
-	}
-
-out:
 	return cdev;
 
 remove_qos_req:
@@ -611,11 +531,6 @@ void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
 	thermal_cooling_device_unregister(dfc->cdev);
 	dev_pm_qos_remove_request(&dfc->req_max_freq);
 
-	if (dfc->has_warming) {
-		thermal_cooling_device_unregister(dfc->warm_cdev);
-		dev_pm_qos_remove_request(&dfc->req_min_freq);
-	}
-
 	em_dev_unregister_perf_domain(dev);
 
 	kfree(dfc->freq_table);
diff --git a/kernel/drivers/thermal/gov_bang_bang.c b/kernel/drivers/thermal/gov_bang_bang.c
index a662047e5961..991a1c54296d 100644
--- a/kernel/drivers/thermal/gov_bang_bang.c
+++ b/kernel/drivers/thermal/gov_bang_bang.c
@@ -99,18 +99,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
 static int bang_bang_control(struct thermal_zone_device *tz, int trip)
 {
 	struct thermal_instance *instance;
-	enum thermal_trip_monitor_type monitor_type =
-						THERMAL_TRIP_MONITOR_RISING;
-
-	/*
-	 * Return doing nothing if the trip point is monitored for
-	 * falling temperature
-	 */
-	if (tz->ops->get_trip_mon_type) {
-		tz->ops->get_trip_mon_type(tz, trip, &monitor_type);
-		if (monitor_type == THERMAL_TRIP_MONITOR_FALLING)
-			return 0;
-	}
 
 	thermal_zone_trip_update(tz, trip);
 
diff --git a/kernel/drivers/thermal/gov_fair_share.c b/kernel/drivers/thermal/gov_fair_share.c
index 646b6e512ffa..1e5abf4822be 100644
--- a/kernel/drivers/thermal/gov_fair_share.c
+++ b/kernel/drivers/thermal/gov_fair_share.c
@@ -81,18 +81,6 @@ static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
 	int total_weight = 0;
 	int total_instance = 0;
 	int cur_trip_level = get_trip_level(tz);
-	enum thermal_trip_monitor_type monitor_type =
-						THERMAL_TRIP_MONITOR_RISING;
-
-	/*
-	 * Return doing nothing if the trip point is monitored for
-	 * falling temperature
-	 */
-	if (tz->ops->get_trip_mon_type) {
-		tz->ops->get_trip_mon_type(tz, trip, &monitor_type);
-		if (monitor_type == THERMAL_TRIP_MONITOR_FALLING)
-			return 0;
-	}
 
 	mutex_lock(&tz->lock);
 
diff --git a/kernel/drivers/thermal/gov_power_allocator.c b/kernel/drivers/thermal/gov_power_allocator.c
index 50acfd183570..13e375751d22 100644
--- a/kernel/drivers/thermal/gov_power_allocator.c
+++ b/kernel/drivers/thermal/gov_power_allocator.c
@@ -709,8 +709,6 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
 {
 	int ret;
 	int switch_on_temp, control_temp;
-	enum thermal_trip_monitor_type monitor_type =
-						THERMAL_TRIP_MONITOR_RISING;
 	struct power_allocator_params *params = tz->governor_data;
 	bool update;
 
@@ -721,16 +719,6 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
 	if (trip != params->trip_max_desired_temperature)
 		return 0;
 
-	/*
-	 * Return doing nothing if the trip point is monitored for
-	 * falling temperature
-	 */
-	if (tz->ops->get_trip_mon_type) {
-		tz->ops->get_trip_mon_type(tz, trip, &monitor_type);
-		if (monitor_type == THERMAL_TRIP_MONITOR_FALLING)
-			return 0;
-	}
-
 	ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
 				     &switch_on_temp);
 	if (!ret && (tz->temperature < switch_on_temp)) {
diff --git a/kernel/drivers/thermal/gov_step_wise.c b/kernel/drivers/thermal/gov_step_wise.c
index 0e1f04fadc40..12acb12aac50 100644
--- a/kernel/drivers/thermal/gov_step_wise.c
+++ b/kernel/drivers/thermal/gov_step_wise.c
@@ -35,8 +35,7 @@
  *       deactivate the thermal instance
  */
 static unsigned long get_target_state(struct thermal_instance *instance,
-				enum thermal_trend trend, bool throttle,
-				enum thermal_trip_monitor_type type)
+				enum thermal_trend trend, bool throttle)
 {
 	struct thermal_cooling_device *cdev = instance->cdev;
 	unsigned long cur_state;
@@ -53,11 +52,10 @@ static unsigned long get_target_state(struct thermal_instance *instance,
 
 	if (!instance->initialized) {
 		if (throttle) {
-			/* Init both falling and raising monitors in the same way */
 			next_target = (cur_state + 1) >= instance->upper ?
-				instance->upper :
-				((cur_state + 1) < instance->lower ?
-				 instance->lower : (cur_state + 1));
+					instance->upper :
+					((cur_state + 1) < instance->lower ?
+					instance->lower : (cur_state + 1));
 		} else {
 			next_target = THERMAL_NO_TARGET;
 		}
@@ -67,24 +65,11 @@ static unsigned long get_target_state(struct thermal_instance *instance,
 
 	switch (trend) {
 	case THERMAL_TREND_RAISING:
-		if (type == THERMAL_TRIP_MONITOR_FALLING) {
-			if (cur_state <= instance->lower) {
-				if (!throttle)
-					next_target = THERMAL_NO_TARGET;
-			} else {
-				if (!throttle) {
-					next_target = cur_state - 1;
-					if (next_target > instance->upper)
-						next_target = instance->upper;
-				}
-			}
-		} else {
-			if (throttle) {
-				next_target = cur_state < instance->upper ?
-					    (cur_state + 1) : instance->upper;
-				if (next_target < instance->lower)
-					next_target = instance->lower;
-			}
+		if (throttle) {
+			next_target = cur_state < instance->upper ?
+				    (cur_state + 1) : instance->upper;
+			if (next_target < instance->lower)
+				next_target = instance->lower;
 		}
 		break;
 	case THERMAL_TREND_RAISE_FULL:
@@ -92,23 +77,14 @@ static unsigned long get_target_state(struct thermal_instance *instance,
 			next_target = instance->upper;
 		break;
 	case THERMAL_TREND_DROPPING:
-		if (type == THERMAL_TRIP_MONITOR_FALLING) {
-			if (throttle) {
-				next_target = cur_state < instance->upper ?
-					    (cur_state + 1) : instance->upper;
-				if (next_target < instance->lower)
-					next_target = instance->lower;
-			}
+		if (cur_state <= instance->lower) {
+			if (!throttle)
+				next_target = THERMAL_NO_TARGET;
 		} else {
-			if (cur_state <= instance->lower) {
-				if (!throttle)
-					next_target = THERMAL_NO_TARGET;
-			} else {
-				if (!throttle) {
-					next_target = cur_state - 1;
-					if (next_target > instance->upper)
-						next_target = instance->upper;
-				}
+			if (!throttle) {
+				next_target = cur_state - 1;
+				if (next_target > instance->upper)
+					next_target = instance->upper;
 			}
 		}
 		break;
@@ -137,29 +113,10 @@ static void update_passive_instance(struct thermal_zone_device *tz,
 		tz->passive += value;
 }
 
-static char get_trend(enum thermal_trend trend) {
-	switch (trend) {
-	case THERMAL_TREND_STABLE:
-		return '-';
-	case THERMAL_TREND_RAISING:
-		return '/';
-	case THERMAL_TREND_DROPPING:
-		return '\\';
-	case THERMAL_TREND_RAISE_FULL:
-		return '+';
-	case THERMAL_TREND_DROP_FULL:
-		return '_';
-	default:
-		return '?';
-	}
-}
-
 static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
 {
 	int trip_temp;
 	enum thermal_trip_type trip_type;
-	enum thermal_trip_monitor_type monitor_type =
-					THERMAL_TRIP_MONITOR_RISING;
 	enum thermal_trend trend;
 	struct thermal_instance *instance;
 	bool throttle = false;
@@ -168,21 +125,15 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
 	tz->ops->get_trip_temp(tz, trip, &trip_temp);
 	tz->ops->get_trip_type(tz, trip, &trip_type);
 
-	if (tz->ops->get_trip_mon_type)
-		tz->ops->get_trip_mon_type(tz, trip, &monitor_type);
-
 	trend = get_tz_trend(tz, trip);
 
-	if (((monitor_type == THERMAL_TRIP_MONITOR_RISING) &&
-	     (tz->temperature >= trip_temp)) ||
-	     ((monitor_type == THERMAL_TRIP_MONITOR_FALLING) &&
-	     (tz->temperature <= trip_temp))) {
+	if (tz->temperature >= trip_temp) {
 		throttle = true;
 		trace_thermal_zone_trip(tz, trip, trip_type);
 	}
 
-	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%c,throttle=%d\n",
-				trip, trip_type, trip_temp, get_trend(trend), throttle);
+	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
+				trip, trip_type, trip_temp, trend, throttle);
 
 	mutex_lock(&tz->lock);
 
@@ -191,8 +142,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
 			continue;
 
 		old_target = instance->target;
-		instance->target = get_target_state(instance, trend,
-						    throttle, monitor_type);
+		instance->target = get_target_state(instance, trend, throttle);
 		dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
 					old_target, (int)instance->target);
 
diff --git a/kernel/drivers/thermal/pd_cooling.c b/kernel/drivers/thermal/pd_cooling.c
deleted file mode 100644
index b6751c517762..000000000000
--- a/kernel/drivers/thermal/pd_cooling.c
+++ /dev/null
@@ -1,128 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  Copyright (C) 2022 Linaro Limited.
- */
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/idle_inject.h>
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/pm_opp.h>
-#include <linux/slab.h>
-#include <linux/thermal.h>
-
-struct pd_warm_data {
-	struct device *dev;
-	int nr_opps;
-	unsigned int state;
-	struct thermal_cooling_device *tcd;
-	unsigned int levels[];
-};
-
-static int pd_warm_get_max_state(struct thermal_cooling_device *cdev,
-				  unsigned long *state)
-{
-	struct pd_warm_data *data = cdev->devdata;
-
-	*state = data->nr_opps - 1;
-	return 0;
-}
-
-static int pd_warm_get_cur_state(struct thermal_cooling_device *cdev,
-				  unsigned long *state)
-{
-	struct pd_warm_data *data = cdev->devdata;
-
-	*state = data->state;
-
-	return 0;
-}
-
-static int pd_warm_set_cur_state(struct thermal_cooling_device *cdev,
-				  unsigned long state)
-{
-	struct pd_warm_data *data = cdev->devdata;
-	struct dev_pm_opp *opp;
-	int ret;
-
-	opp = dev_pm_opp_find_level_exact(data->dev, data->levels[state]);
-	if (IS_ERR(opp))
-		return PTR_ERR(opp);
-
-	ret = dev_pm_opp_set_opp(data->dev, opp);
-	if (!ret)
-		data->state = state;
-
-	dev_pm_opp_put(opp);
-
-	return ret;
-}
-
-static struct thermal_cooling_device_ops pd_warm_ops = {
-	.get_max_state = pd_warm_get_max_state,
-	.get_cur_state = pd_warm_get_cur_state,
-	.set_cur_state = pd_warm_set_cur_state,
-};
-
-static int pd_warm_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct pd_warm_data *data;
-	unsigned int level;
-	int i, ret, nr_opps;
-
-	ret = devm_pm_opp_of_add_table_noclk(dev, 0);
-	if (ret)
-		return ret;
-
-	nr_opps = dev_pm_opp_get_opp_count(dev);
-	if (nr_opps < 0)
-		return nr_opps;
-
-	/* No point in warming up if we have less than two possible states */
-	if (nr_opps < 2) {
-		dev_err(dev, "Invalid number of opp entries: %d\n", nr_opps);
-		return -EINVAL;
-	}
-
-	data = devm_kzalloc(dev, struct_size(data, levels, nr_opps), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->dev = dev;
-	data->nr_opps = nr_opps;
-
-	for (i = 0, level = 0; i < nr_opps; i++, level++) {
-		struct dev_pm_opp *opp = dev_pm_opp_find_level_ceil(dev, &level);
-
-		if (IS_ERR(opp))
-			return dev_err_probe(dev, PTR_ERR(opp), "Error getting level %d\n", i);
-
-		data->levels[i] = level;
-	}
-
-	data->tcd = devm_thermal_of_cooling_device_register(dev, dev->of_node, dev_name(dev), data, &pd_warm_ops);
-	if (IS_ERR(data->tcd))
-		return PTR_ERR(data->tcd);
-
-	return 0;
-}
-
-static const struct of_device_id pd_warm_match[] = {
-	{ .compatible = "power-domain-cooling" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, pd_warm_match);
-
-static struct platform_driver pd_warm_driver = {
-	.driver = {
-		.name = "pd-cooling",
-		.of_match_table = pd_warm_match,
-	},
-
-	.probe = pd_warm_probe,
-};
-
-module_platform_driver(pd_warm_driver);
diff --git a/kernel/drivers/thermal/thermal_core.c b/kernel/drivers/thermal/thermal_core.c
index fa3cce137c48..867c8aa92b3a 100644
--- a/kernel/drivers/thermal/thermal_core.c
+++ b/kernel/drivers/thermal/thermal_core.c
@@ -361,7 +361,6 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
 static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
 {
 	enum thermal_trip_type type;
-	enum thermal_trip_monitor_type mon_type;
 	int trip_temp, hyst = 0;
 
 	/* Ignore disabled trip points */
@@ -373,25 +372,13 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
 	if (tz->ops->get_trip_hyst)
 		tz->ops->get_trip_hyst(tz, trip, &hyst);
 
-	if (tz->ops->get_trip_mon_type)
-		tz->ops->get_trip_mon_type(tz, trip, &mon_type);
-
 	if (tz->last_temperature != THERMAL_TEMP_INVALID) {
-		if (mon_type == THERMAL_TRIP_MONITOR_FALLING) {
-			if (tz->last_temperature > trip_temp &&
-			    tz->temperature <= trip_temp)
-				thermal_notify_tz_trip_down(tz->id, trip);
-			if (tz->last_temperature <= trip_temp &&
-			    tz->temperature > (trip_temp + hyst))
-				thermal_notify_tz_trip_up(tz->id, trip);
-		} else {
-			if (tz->last_temperature < trip_temp &&
-			    tz->temperature >= trip_temp)
-				thermal_notify_tz_trip_up(tz->id, trip);
-			if (tz->last_temperature >= trip_temp &&
-			    tz->temperature < (trip_temp - hyst))
-				thermal_notify_tz_trip_down(tz->id, trip);
-		}
+		if (tz->last_temperature < trip_temp &&
+		    tz->temperature >= trip_temp)
+			thermal_notify_tz_trip_up(tz->id, trip);
+		if (tz->last_temperature >= trip_temp &&
+		    tz->temperature < (trip_temp - hyst))
+			thermal_notify_tz_trip_down(tz->id, trip);
 	}
 
 	if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
@@ -1040,7 +1027,7 @@ static void thermal_cooling_device_release(struct device *dev, void *res)
 struct thermal_cooling_device *
 devm_thermal_of_cooling_device_register(struct device *dev,
 				struct device_node *np,
-				const char *type, void *devdata,
+				char *type, void *devdata,
 				const struct thermal_cooling_device_ops *ops)
 {
 	struct thermal_cooling_device **ptr, *tcd;
diff --git a/kernel/drivers/thermal/thermal_core.h b/kernel/drivers/thermal/thermal_core.h
index e5a3e8041cd5..726e327b4205 100644
--- a/kernel/drivers/thermal/thermal_core.h
+++ b/kernel/drivers/thermal/thermal_core.h
@@ -74,14 +74,12 @@ void __thermal_cdev_update(struct thermal_cooling_device *cdev);
  * @temperature: temperature value in miliCelsius
  * @hysteresis: relative hysteresis in miliCelsius
  * @type: trip point type
- * @monitor_type: trip point monitor type
  */
 struct thermal_trip {
 	struct device_node *np;
 	int temperature;
 	int hysteresis;
 	enum thermal_trip_type type;
-	enum thermal_trip_monitor_type monitor_type;
 };
 
 int get_tz_trend(struct thermal_zone_device *tz, int trip);
diff --git a/kernel/drivers/thermal/thermal_of.c b/kernel/drivers/thermal/thermal_of.c
index 0d2adcfb0a93..9233f7e74454 100644
--- a/kernel/drivers/thermal/thermal_of.c
+++ b/kernel/drivers/thermal/thermal_of.c
@@ -331,20 +331,6 @@ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
 	return 0;
 }
 
-static int of_thermal_get_trip_monitor_type
-				(struct thermal_zone_device *tz, int trip,
-				 enum thermal_trip_monitor_type *type)
-{
-	struct __thermal_zone *data = tz->devdata;
-
-	if (trip >= data->ntrips || trip < 0)
-		return -EDOM;
-
-	*type = data->trips[trip].monitor_type;
-
-	return 0;
-}
-
 static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
 				    int hyst)
 {
@@ -380,7 +366,6 @@ static struct thermal_zone_device_ops of_thermal_ops = {
 	.set_trip_temp = of_thermal_set_trip_temp,
 	.get_trip_hyst = of_thermal_get_trip_hyst,
 	.set_trip_hyst = of_thermal_set_trip_hyst,
-	.get_trip_mon_type = of_thermal_get_trip_monitor_type,
 	.get_crit_temp = of_thermal_get_crit_temp,
 
 	.bind = of_thermal_bind,
@@ -825,7 +810,6 @@ static int thermal_of_populate_trip(struct device_node *np,
 {
 	int prop;
 	int ret;
-	bool is_monitor_falling;
 
 	ret = of_property_read_u32(np, "temperature", &prop);
 	if (ret < 0) {
@@ -847,12 +831,6 @@ static int thermal_of_populate_trip(struct device_node *np,
 		return ret;
 	}
 
-	is_monitor_falling = of_property_read_bool(np, "monitor-falling");
-	if (is_monitor_falling)
-		trip->monitor_type = THERMAL_TRIP_MONITOR_FALLING;
-	else
-		trip->monitor_type = THERMAL_TRIP_MONITOR_RISING;
-
 	/* Required for cooling map matching */
 	trip->np = np;
 	of_node_get(np);
diff --git a/kernel/drivers/thermal/thermal_sysfs.c b/kernel/drivers/thermal/thermal_sysfs.c
index a2b30f15c1e7..1c4aac8464a7 100644
--- a/kernel/drivers/thermal/thermal_sysfs.c
+++ b/kernel/drivers/thermal/thermal_sysfs.c
@@ -106,34 +106,6 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
 	}
 }
 
-static ssize_t
-trip_point_direction_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	struct thermal_zone_device *tz = to_thermal_zone(dev);
-	enum thermal_trip_monitor_type monitor_type = THERMAL_TRIP_MONITOR_RISING;
-	int trip, result;
-
-	if (!tz->ops->get_trip_mon_type)
-		return -EPERM;
-
-	if (sscanf(attr->attr.name, "trip_point_%d_direction", &trip) != 1)
-		return -EINVAL;
-
-	result = tz->ops->get_trip_mon_type(tz, trip, &monitor_type);
-	if (result)
-		return result;
-
-	switch (monitor_type) {
-	case THERMAL_TRIP_MONITOR_RISING:
-		return sprintf(buf, "rising\n");
-	case THERMAL_TRIP_MONITOR_FALLING:
-		return sprintf(buf, "falling\n");
-	default:
-		return sprintf(buf, "unknown\n");
-	}
-}
-
 static ssize_t
 trip_point_temp_store(struct device *dev, struct device_attribute *attr,
 		      const char *buf, size_t count)
@@ -470,18 +442,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 		}
 	}
 
-	if (tz->ops->get_trip_mon_type) {
-		tz->trip_direction_attrs = kcalloc(tz->trips,
-					      sizeof(*tz->trip_direction_attrs),
-					      GFP_KERNEL);
-		if (!tz->trip_direction_attrs) {
-			kfree(tz->trip_type_attrs);
-			kfree(tz->trip_temp_attrs);
-			return -ENOMEM;
-		}
-	}
-
-	attrs = kcalloc(tz->trips * 4 + 1, sizeof(*attrs), GFP_KERNEL);
+	attrs = kcalloc(tz->trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
 	if (!attrs) {
 		kfree(tz->trip_type_attrs);
 		kfree(tz->trip_temp_attrs);
@@ -520,39 +481,25 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 		attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr;
 
 		/* create Optional trip hyst attribute */
-		if (tz->ops->get_trip_hyst) {
-			snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
-				 "trip_point_%d_hyst", indx);
-
-			sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
-			tz->trip_hyst_attrs[indx].attr.attr.name =
-						tz->trip_hyst_attrs[indx].name;
-			tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
-			tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
-			if (tz->ops->set_trip_hyst) {
-				tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
-				tz->trip_hyst_attrs[indx].attr.store =
-						trip_point_hyst_store;
-			}
-			attrs[indx + tz->trips * 2] =
-						&tz->trip_hyst_attrs[indx].attr.attr;
-		}
-
-		/* create Optional trip direction attribute */
-		if (tz->ops->get_trip_mon_type) {
-			snprintf(tz->trip_direction_attrs[indx].name, THERMAL_NAME_LENGTH,
-				 "trip_point_%d_direction", indx);
-
-			sysfs_attr_init(&tz->trip_direction_attrs[indx].attr.attr);
-			tz->trip_direction_attrs[indx].attr.attr.name =
-						tz->trip_direction_attrs[indx].name;
-			tz->trip_direction_attrs[indx].attr.attr.mode = S_IRUGO;
-			tz->trip_direction_attrs[indx].attr.show = trip_point_direction_show;
-			attrs[indx + tz->trips * 3] =
-						&tz->trip_direction_attrs[indx].attr.attr;
+		if (!tz->ops->get_trip_hyst)
+			continue;
+		snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
+			 "trip_point_%d_hyst", indx);
+
+		sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
+		tz->trip_hyst_attrs[indx].attr.attr.name =
+					tz->trip_hyst_attrs[indx].name;
+		tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
+		tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
+		if (tz->ops->set_trip_hyst) {
+			tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
+			tz->trip_hyst_attrs[indx].attr.store =
+					trip_point_hyst_store;
 		}
+		attrs[indx + tz->trips * 2] =
+					&tz->trip_hyst_attrs[indx].attr.attr;
 	}
-	attrs[tz->trips * 4] = NULL;
+	attrs[tz->trips * 3] = NULL;
 
 	tz->trips_attribute_group.attrs = attrs;
 
diff --git a/kernel/include/linux/thermal.h b/kernel/include/linux/thermal.h
index 7f7f9b217855..c314893970b3 100644
--- a/kernel/include/linux/thermal.h
+++ b/kernel/include/linux/thermal.h
@@ -72,8 +72,6 @@ struct thermal_zone_device_ops {
 	int (*set_trip_temp) (struct thermal_zone_device *, int, int);
 	int (*get_trip_hyst) (struct thermal_zone_device *, int, int *);
 	int (*set_trip_hyst) (struct thermal_zone_device *, int, int);
-	int (*get_trip_mon_type)(struct thermal_zone_device *, int,
-				     enum thermal_trip_monitor_type *);
 	int (*get_crit_temp) (struct thermal_zone_device *, int *);
 	int (*set_emul_temp) (struct thermal_zone_device *, int);
 	int (*get_trend) (struct thermal_zone_device *, int,
@@ -153,7 +151,6 @@ struct thermal_zone_device {
 	struct thermal_attr *trip_temp_attrs;
 	struct thermal_attr *trip_type_attrs;
 	struct thermal_attr *trip_hyst_attrs;
-	struct thermal_attr *trip_direction_attrs;
 	enum thermal_device_mode mode;
 	void *devdata;
 	int trips;
@@ -385,7 +382,7 @@ thermal_of_cooling_device_register(struct device_node *np, const char *, void *,
 struct thermal_cooling_device *
 devm_thermal_of_cooling_device_register(struct device *dev,
 				struct device_node *np,
-				const char *type, void *devdata,
+				char *type, void *devdata,
 				const struct thermal_cooling_device_ops *ops);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
diff --git a/kernel/include/soc/qcom/cpr.h b/kernel/include/soc/qcom/cpr.h
deleted file mode 100644
index 2ba4324d18f6..000000000000
--- a/kernel/include/soc/qcom/cpr.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
- * Copyright (c) 2019 Linaro Limited
- * Copyright (c) 2021, AngeloGioacchino Del Regno
- *                     <angelogioacchino.delregno@somainline.org>
- */
-
-#ifndef __CPR_H__
-#define __CPR_H__
-
-struct cpr_ext_data {
-	int mem_acc_threshold_uV;
-	int apm_threshold_uV;
-};
-
-#endif /* __CPR_H__ */
diff --git a/kernel/include/uapi/linux/thermal.h b/kernel/include/uapi/linux/thermal.h
index d879c1191af0..9aa2fedfa309 100644
--- a/kernel/include/uapi/linux/thermal.h
+++ b/kernel/include/uapi/linux/thermal.h
@@ -16,11 +16,6 @@ enum thermal_trip_type {
 	THERMAL_TRIP_CRITICAL,
 };
 
-enum thermal_trip_monitor_type {
-	THERMAL_TRIP_MONITOR_RISING = 0,
-	THERMAL_TRIP_MONITOR_FALLING
-};
-
 /* Adding event notification support elements */
 #define THERMAL_GENL_FAMILY_NAME		"thermal"
 #define THERMAL_GENL_VERSION			0x01
