Merge "platform: msm_shared: Update MDP5 for msm8916 support"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index a27901b..e09955d 100755
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -2484,7 +2484,7 @@
 		}
 		else
 		{
-			reboot_device(0);
+			reboot_device(DLOAD);
 			dprintf(CRITICAL,"Failed to reboot into dload mode\n");
 		}
 		boot_into_fastboot = true;
diff --git a/platform/msm_shared/debug.c b/platform/msm_shared/debug.c
index 28c053e..45d1c32 100644
--- a/platform/msm_shared/debug.c
+++ b/platform/msm_shared/debug.c
@@ -144,7 +144,7 @@
 	if (set_download_mode(NORMAL_DLOAD) == 0)
 	{
 		dprintf(CRITICAL, "HALT: reboot into dload mode...\n");
-		reboot_device(0);
+		reboot_device(DLOAD);
 		dprintf(CRITICAL, "HALT: reboot_device failed\n");
 	}
 	else
diff --git a/platform/msm_shared/include/dload_util.h b/platform/msm_shared/include/dload_util.h
index 8415773..d8e02b0 100644
--- a/platform/msm_shared/include/dload_util.h
+++ b/platform/msm_shared/include/dload_util.h
@@ -31,9 +31,12 @@
 
 #include <sys/types.h>
 
+#define DLOAD 1
+
 enum dload_mode {
 	NORMAL_DLOAD,
-	EMERGENCY_DLOAD
+	EMERGENCY_DLOAD,
+	NORMAL_MODE
 };
 
 void dload_util_write_cookie(uint32_t target_dload_mode_addr,
diff --git a/platform/msm_shared/include/scm.h b/platform/msm_shared/include/scm.h
index ba6ed88..6c8f7ef 100644
--- a/platform/msm_shared/include/scm.h
+++ b/platform/msm_shared/include/scm.h
@@ -117,6 +117,7 @@
 } el1_system_param;
 
 /* Service IDs */
+#define SCM_SVC_BOOT                0x01
 #define TZBSP_SVC_INFO              0x06
 #define SCM_SVC_SSD                 0x07
 #define SVC_MEMORY_PROTECTION       0x0C
@@ -127,7 +128,8 @@
 #define SSD_PROTECT_KEYSTORE_ID     0x05
 #define SSD_PARSE_MD_ID             0x06
 #define SSD_DECRYPT_IMG_FRAG_ID     0x07
-
+#define WDOG_DEBUG_DISABLE          0x09
+#define SCM_DLOAD_CMD               0x10
 
 #define SECURE_DEVICE_MDSS          0x01
 
@@ -135,6 +137,10 @@
 
 #define TZ_INFO_GET_FEATURE_ID      0x03
 
+/* Download Mode specific arguments to be passed to TZ */
+#define SCM_EDLOAD_MODE 0x02
+#define SCM_DLOAD_MODE  0x10
+
 /* SSD parsing status messages from TZ */
 #define SSD_PMD_ENCRYPTED           0
 #define SSD_PMD_NOT_ENCRYPTED       1
@@ -207,6 +213,7 @@
 void set_tamper_fuse_cmd();
 
 int scm_halt_pmic_arbiter();
+int scm_call_atomic2(uint32_t svc, uint32_t cmd, uint32_t arg1, uint32_t arg2);
 
 void scm_elexec_call(paddr_t kernel_entry, paddr_t dtb_offset);
 
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index b2bfc9e..ea5d9d3 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -169,6 +169,7 @@
 		$(LOCAL_DIR)/bam.o \
 		$(LOCAL_DIR)/scm.o \
 		$(LOCAL_DIR)/qpic_nand.o \
+		$(LOCAL_DIR)/dload_util.o \
 		$(LOCAL_DIR)/gpio.o \
 		$(LOCAL_DIR)/dev_tree.o \
 		$(LOCAL_DIR)/mdp5.o \
diff --git a/platform/msm_shared/scm.c b/platform/msm_shared/scm.c
index 4294168..90a500a 100644
--- a/platform/msm_shared/scm.c
+++ b/platform/msm_shared/scm.c
@@ -159,6 +159,36 @@
 }
 
 /**
+ * scm_call_atomic2() - Send an atomic SCM command with two arguments
+ * @svc_id: service identifier
+ * @cmd_id: command identifier
+ * @arg1: first argument
+ * @arg2: second argument
+ *
+ * This shall only be used with commands that are guaranteed to be
+ * uninterruptable, atomic and SMP safe.
+ */
+int scm_call_atomic2(uint32_t svc, uint32_t cmd, uint32_t arg1, uint32_t arg2)
+{
+	int context_id;
+	register uint32_t r0 __asm__("r0") = SCM_ATOMIC(svc, cmd, 2);
+	register uint32_t r1 __asm__("r1") = &context_id;
+	register uint32_t r2 __asm__("r2") = arg1;
+	register uint32_t r3 __asm__("r3") = arg2;
+
+	__asm__ volatile(
+		__asmeq("%0", "r0")
+		__asmeq("%1", "r0")
+		__asmeq("%2", "r1")
+		__asmeq("%3", "r2")
+		__asmeq("%4", "r3")
+		"smc	#0	@ switch to secure world\n"
+		: "=r" (r0)
+		: "r" (r0), "r" (r1), "r" (r2), "r" (r3));
+	return r0;
+}
+
+/**
  * scm_call() - Send an SCM command
  * @svc_id: service identifier
  * @cmd_id: command identifier
diff --git a/target/msm8916/init.c b/target/msm8916/init.c
index cb6dc35..de53133 100644
--- a/target/msm8916/init.c
+++ b/target/msm8916/init.c
@@ -40,6 +40,7 @@
 #include <board.h>
 #include <baseband.h>
 #include <hsusb.h>
+#include <scm.h>
 #include <platform/gpio.h>
 #include <platform/gpio.h>
 #include <platform/irqs.h>
@@ -48,6 +49,8 @@
 #define PMIC_ARB_OWNER_ID       0
 #define TLMM_VOL_UP_BTN_GPIO    107
 
+#define FASTBOOT_MODE           0x77665500
+
 static void set_sdc_power_ctrl(void);
 
 struct mmc_device *dev;
@@ -185,12 +188,55 @@
 	return restart_reason;
 }
 
+static int scm_dload_mode(int mode)
+{
+	int ret = 0;
+	uint32_t dload_type;
+
+	dprintf(SPEW, "DLOAD mode: %d\n", mode);
+	if (mode == NORMAL_DLOAD)
+		dload_type = SCM_DLOAD_MODE;
+	else if(mode == EMERGENCY_DLOAD)
+		dload_type = SCM_EDLOAD_MODE;
+	else
+		dload_type = 0;
+
+	ret = scm_call_atomic2(SCM_SVC_BOOT, SCM_DLOAD_CMD, dload_type, 0);
+	if (ret)
+		dprintf(CRITICAL, "Failed to write to boot misc: %d\n", ret);
+
+	ret = scm_call_atomic2(SCM_SVC_BOOT, WDOG_DEBUG_DISABLE, 1, 0);
+	if (ret)
+		dprintf(CRITICAL, "Failed to disable the wdog debug \n");
+
+	return ret;
+}
 void reboot_device(unsigned reboot_reason)
 {
+	uint8_t reset_type = 0;
+	uint32_t ret = 0;
+
+	/* Need to clear the SW_RESET_ENTRY register and
+	 * write to the BOOT_MISC_REG for known reset cases
+	 */
+	if(reboot_reason != DLOAD)
+		scm_dload_mode(NORMAL_MODE);
+
 	writel(reboot_reason, RESTART_REASON_ADDR);
 
-	/* Configure PMIC for warm reset */
-	pm8x41_reset_configure(PON_PSHOLD_WARM_RESET);
+	/* For Reboot-bootloader and Dload cases do a warm reset
+	 * For Reboot cases do a hard reset
+	 */
+	if((reboot_reason == FASTBOOT_MODE) || (reboot_reason == DLOAD))
+		reset_type = PON_PSHOLD_WARM_RESET;
+	else
+		reset_type = PON_PSHOLD_HARD_RESET;
+
+	pm8x41_reset_configure(reset_type);
+
+	ret = scm_halt_pmic_arbiter();
+	if (ret)
+		dprintf(CRITICAL , "Failed to halt pmic arbiter: %d\n", ret);
 
 	/* Drop PS_HOLD for MSM */
 	writel(0x00, MPM2_MPM_PS_HOLD);
@@ -293,3 +339,13 @@
 	/* Set the BOOT_DONE flag in PM8916 */
 	pm8x41_set_boot_done();
 }
+
+int set_download_mode(enum dload_mode mode)
+{
+	int ret = 0;
+	ret = scm_dload_mode(mode);
+
+	pm8x41_clear_pmic_watchdog();
+
+	return ret;
+}