Merge "msm: cpr: Disable CPR based on fused bits in 8x25"
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 189a616..5296048 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1809,6 +1809,7 @@
 	.max_nom_freq = 700800,
 	.max_freq = 1401600,
 	.max_quot = 0,
+	.disable_cpr = false,
 	.vp_data = &vp_data,
 	.get_quot = msm_cpr_get_quot,
 	.clk_enable = msm_cpr_clk_enable,
@@ -1841,6 +1842,7 @@
 	}
 
 	msm_smem_get_cpr_info(cpr_info);
+	msm_cpr_pdata.disable_cpr = cpr_info->disable_cpr;
 
 	/**
 	 * Set the ring_osc based on efuse BIT(0)
diff --git a/arch/arm/mach-msm/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index c00352d..b68a8db 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -50,6 +50,7 @@
 static struct platform_device *cpr_pdev;
 
 static bool enable = 1;
+static bool disable_cpr;
 module_param(enable, bool, 0644);
 MODULE_PARM_DESC(enable, "CPR Enable");
 
@@ -329,12 +330,12 @@
 	cpr_write_reg(cpr, RBIF_CONT_NACK_CMD, 0x1);
 }
 
-static void cpr_irq_set(struct msm_cpr *cpr, uint32_t irq, bool enable)
+static void cpr_irq_set(struct msm_cpr *cpr, uint32_t irq, bool enable_irq)
 {
 	uint32_t irq_enabled;
 
 	irq_enabled = cpr_read_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line));
-	if (enable == 1)
+	if (enable_irq == 1)
 		irq_enabled |= irq;
 	else
 		irq_enabled &= ~irq;
@@ -832,7 +833,7 @@
 
 void msm_cpr_pm_resume(void)
 {
-	if (!enable)
+	if (!enable || disable_cpr)
 		return;
 
 	msm_cpr_resume(&cpr_pdev->dev);
@@ -841,7 +842,7 @@
 
 void msm_cpr_pm_suspend(void)
 {
-	if (!enable)
+	if (!enable || disable_cpr)
 		return;
 
 	msm_cpr_suspend(&cpr_pdev->dev);
@@ -853,7 +854,7 @@
 {
 	struct msm_cpr *cpr;
 
-	if (!enable)
+	if (!enable || disable_cpr)
 		return;
 
 	cpr = platform_get_drvdata(cpr_pdev);
@@ -866,7 +867,7 @@
 {
 	struct msm_cpr *cpr;
 
-	if (!enable)
+	if (!enable || disable_cpr)
 		return;
 
 	cpr = platform_get_drvdata(cpr_pdev);
@@ -893,6 +894,12 @@
 		return -EIO;
 	}
 
+	if (pdata->disable_cpr == true) {
+		pr_err("CPR disabled by modem\n");
+		disable_cpr = true;
+		return -EPERM;
+	}
+
 	cpr = devm_kzalloc(&pdev->dev, sizeof(struct msm_cpr), GFP_KERNEL);
 	if (!cpr) {
 		enable = false;
diff --git a/arch/arm/mach-msm/msm_cpr.h b/arch/arm/mach-msm/msm_cpr.h
index 005d9b1..3d10478 100644
--- a/arch/arm/mach-msm/msm_cpr.h
+++ b/arch/arm/mach-msm/msm_cpr.h
@@ -188,6 +188,7 @@
 	uint32_t max_nom_freq;
 	uint32_t max_freq;
 	uint32_t max_quot;
+	bool disable_cpr;
 	struct msm_cpr_vp_data *vp_data;
 	uint32_t (*get_quot)(uint32_t max_quot, uint32_t max_freq,
 				uint32_t new_freq);
diff --git a/arch/arm/mach-msm/msm_smem_iface.c b/arch/arm/mach-msm/msm_smem_iface.c
index b35467b..5ae5772 100644
--- a/arch/arm/mach-msm/msm_smem_iface.c
+++ b/arch/arm/mach-msm/msm_smem_iface.c
@@ -42,4 +42,5 @@
 	cpr_info->turbo_quot = temp_cpr_info->turbo_quot;
 	cpr_info->pvs_fuse = temp_cpr_info->pvs_fuse;
 	cpr_info->floor_fuse = temp_cpr_info->floor_fuse;
+	cpr_info->disable_cpr = temp_cpr_info->disable_cpr;
 }
diff --git a/arch/arm/mach-msm/msm_smem_iface.h b/arch/arm/mach-msm/msm_smem_iface.h
index a6d6714..2daf76d 100644
--- a/arch/arm/mach-msm/msm_smem_iface.h
+++ b/arch/arm/mach-msm/msm_smem_iface.h
@@ -16,7 +16,6 @@
 #define __ARCH_ARM_MACH_MSM_SMEM_IFACE_H
 
 #include <mach/msm_smsm.h>
-#include "smd_private.h"
 
 #define MAX_KEY_EVENTS 10
 #define MAX_SEC_KEY_PAYLOAD 32
@@ -39,6 +38,7 @@
 	uint8_t turbo_quot; /* CPRFUSE[1:7] : TURBO QUOT*/
 	uint8_t pvs_fuse;   /* TURBO PVS FUSE */
 	uint8_t floor_fuse; /* Vmin Selection. b1: FAB_ID(2), b0: CPR_fuse[0] */
+	bool    disable_cpr;
 };
 
 struct boot_info_for_apps {
@@ -49,7 +49,7 @@
 	uint16_t boot_keys_pressed[MAX_KEY_EVENTS]; /* Log of key presses */
 	uint32_t timetick; /* Modem tick timer value before apps out of reset */
 	struct cpr_info_type cpr_info;
-	uint8_t PAD[24];
+	uint8_t PAD[23];
 };
 
 void msm_smem_get_cpr_info(struct cpr_info_type *cpr_info);