Merge "Revert "project: msm8974: Assert on finding a tampered kernel image.""
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 7c7f78b..59f43dd 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -1977,15 +1977,15 @@
 	/* Check if we should do something other than booting up */
 	if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN))
 	{
-		dprintf(ALWAYS,"dload mode key sequence detected");
-		if (set_download_mode())
+		dprintf(ALWAYS,"dload mode key sequence detected\n");
+		if (set_download_mode(EMERGENCY_DLOAD))
 		{
-			dprintf(CRITICAL,"dload mode not supported by target");
+			dprintf(CRITICAL,"dload mode not supported by target\n");
 		}
 		else
 		{
 			reboot_device(0);
-			dprintf(CRITICAL,"Failed to reboot into dload mode");
+			dprintf(CRITICAL,"Failed to reboot into dload mode\n");
 		}
 		boot_into_fastboot = true;
 	}
diff --git a/app/aboot/recovery.c b/app/aboot/recovery.c
index 8c79f28..817a6be 100644
--- a/app/aboot/recovery.c
+++ b/app/aboot/recovery.c
@@ -95,6 +95,7 @@
 	unsigned offset = 0;
 	unsigned pagesize = flash_page_size();
 	unsigned n = 0;
+	void *scratch_addr = target_get_scratch_address();
 
 	ptable = flash_get_ptable();
 
@@ -111,15 +112,15 @@
 
 	n = pagesize * (MISC_COMMAND_PAGE + 1);
 
-	if (flash_read(ptn, offset, (void *) SCRATCH_ADDR, n)) {
+	if (flash_read(ptn, offset, scratch_addr, n)) {
 		dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
 		return -1;
 	}
 
 	offset += (pagesize * MISC_COMMAND_PAGE);
-	offset += SCRATCH_ADDR;
+	offset += (unsigned) scratch_addr;
 	memcpy((void *) offset, in, sizeof(*in));
-	if (flash_write(ptn, 0, (void *)SCRATCH_ADDR, n)) {
+	if (flash_write(ptn, 0, scratch_addr, n)) {
 		dprintf(CRITICAL, "ERROR: flash write fail!\n");
 		return -1;
 	}
@@ -165,6 +166,7 @@
 	unsigned pagesize = flash_page_size();
 	unsigned pagemask = pagesize -1;
 	unsigned n = 0;
+	void *scratch_addr = target_get_scratch_address();
 
 	ptable = flash_get_ptable();
 	if (ptable == NULL) {
@@ -181,7 +183,7 @@
 	offset += header->image_offset;
 	n = (header->image_length + pagemask) & (~pagemask);
 
-	if (flash_read(ptn, offset, (void *) SCRATCH_ADDR, n)) {
+	if (flash_read(ptn, offset, scratch_addr, n)) {
 		dprintf(CRITICAL, "ERROR: Cannot read radio image\n");
 		return -1;
 	}
@@ -192,7 +194,7 @@
 		return -1;
 	}
 
-	if (flash_write(ptn, 0, (void *) SCRATCH_ADDR, n)) {
+	if (flash_write(ptn, 0, scratch_addr, n)) {
 		dprintf(CRITICAL, "ERROR: flash write fail!\n");
 		return -1;
 	}
diff --git a/dev/pmic/pm8x41/include/pm8x41_wled.h b/dev/pmic/pm8x41/include/pm8x41_wled.h
index 74c91bc..b357794 100644
--- a/dev/pmic/pm8x41/include/pm8x41_wled.h
+++ b/dev/pmic/pm8x41/include/pm8x41_wled.h
@@ -32,6 +32,7 @@
 
 #define PM_WLED_BASE                 0x1D800
 #define PM_WLED_CTNL_REG(n)          (PM_WLED_BASE + n)
+#define PM_WLED_LED_CTNL_REG(n)      (PM_WLED_BASE + 0x60 + (n-1)*10)
 
 #define PM_WLED_LED1_BRIGHTNESS_LSB  PM_WLED_CTNL_REG(0x40)
 #define PM_WLED_LED1_BRIGHTNESS_MSB  PM_WLED_CTNL_REG(0x41)
@@ -43,7 +44,9 @@
 #define PM_WLED_ILED_SYNC_BIT        PM_WLED_CTNL_REG(0x47)
 #define PM_WLED_MODULATION_SCHEME    PM_WLED_CTNL_REG(0x4A)
 #define PM_WLED_MAX_DUTY_CYCLE       PM_WLED_CTNL_REG(0x4B)
+#define PM_WLED_OVP                  PM_WLED_CTNL_REG(0x4D)
 #define PM_WLED_CURRENT_SINK         PM_WLED_CTNL_REG(0x4F)
+#define LEDn_FULL_SCALE_CURRENT(n)   (PM_WLED_LED_CTNL_REG(n) + 0x2)
 
 #define PM_WLED_LED1_SINK_MASK       BIT(7)
 #define PM_WLED_LED2_SINK_MASK       BIT(6)
@@ -61,6 +64,8 @@
 	uint16_t led2_brightness;
 	uint16_t led3_brightness;
 	uint8_t max_duty_cycle;
+	uint8_t ovp;
+	uint8_t full_current_scale;;
 };
 
 void pm8x41_wled_config(struct pm8x41_wled_data *wled_ctrl);
diff --git a/dev/pmic/pm8x41/pm8x41_wled.c b/dev/pmic/pm8x41/pm8x41_wled.c
index 5693590..fd8b48f 100644
--- a/dev/pmic/pm8x41/pm8x41_wled.c
+++ b/dev/pmic/pm8x41/pm8x41_wled.c
@@ -48,6 +48,10 @@
 	REG_WRITE(PM_WLED_LED3_BRIGHTNESS_MSB, ((wled_ctrl->led3_brightness >> 8) & 0xFF));
 
 	REG_WRITE(PM_WLED_MAX_DUTY_CYCLE, wled_ctrl->max_duty_cycle);
+	REG_WRITE(PM_WLED_OVP, wled_ctrl->ovp);
+	REG_WRITE(LEDn_FULL_SCALE_CURRENT(1), wled_ctrl->full_current_scale);
+	REG_WRITE(LEDn_FULL_SCALE_CURRENT(2), wled_ctrl->full_current_scale);
+	REG_WRITE(LEDn_FULL_SCALE_CURRENT(3), wled_ctrl->full_current_scale);
 
 	dprintf(SPEW, "WLED Configuration Success.\n");
 
diff --git a/include/platform.h b/include/platform.h
index 1c5b27e..aa63431 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -23,6 +23,8 @@
 #ifndef __PLATFORM_H
 #define __PLATFORM_H
 
+#include <dload_util.h>
+
 #define PA(x) platform_get_virt_to_phys_mapping(x)
 #define VA(x) platform_get_phys_to_virt_mapping(x)
 
@@ -50,6 +52,6 @@
 unsigned check_reboot_mode(void);
 void platform_uninit_timer(void);
 void reboot_device(unsigned);
-int set_download_mode(void);
+int set_download_mode(enum dload_mode mode);
 
 #endif
diff --git a/platform/msm8226/include/platform/iomap.h b/platform/msm8226/include/platform/iomap.h
index 2fe4b42..851e798 100644
--- a/platform/msm8226/include/platform/iomap.h
+++ b/platform/msm8226/include/platform/iomap.h
@@ -42,7 +42,8 @@
 #define MSM_SHARED_IMEM_BASE        0xFE805000
 
 #define RESTART_REASON_ADDR         (MSM_SHARED_IMEM_BASE + 0x65C)
-#define FORCE_DLOAD_MODE_ADDR       (MSM_SHARED_IMEM_BASE + 0xFE0)
+#define DLOAD_MODE_ADDR             (MSM_SHARED_IMEM_BASE + 0x0)
+#define EMERGENCY_DLOAD_MODE_ADDR   (MSM_SHARED_IMEM_BASE + 0xFE0)
 
 #define MSM_GIC_DIST_BASE           APPS_SS_BASE
 #define MSM_GIC_CPU_BASE            (APPS_SS_BASE + 0x2000)
diff --git a/platform/msm8974/include/platform/iomap.h b/platform/msm8974/include/platform/iomap.h
index 12f0015..ff7ab1b 100644
--- a/platform/msm8974/include/platform/iomap.h
+++ b/platform/msm8974/include/platform/iomap.h
@@ -41,10 +41,10 @@
 #define SYSTEM_IMEM_BASE            0xFE800000
 #define MSM_SHARED_IMEM_BASE        0xFE805000
 
-#define RESTART_REASON_ADDR         (RPM_MSG_RAM_BASE     + 0x65C)
-#define RESTART_REASON_ADDR_V2      (MSM_SHARED_IMEM_BASE + 0x65C)
-
-#define FORCE_DLOAD_MODE_ADDR_V2    (MSM_SHARED_IMEM_BASE + 0xFE0)
+#define RESTART_REASON_ADDR             (RPM_MSG_RAM_BASE     + 0x65C)
+#define RESTART_REASON_ADDR_V2          (MSM_SHARED_IMEM_BASE + 0x65C)
+#define DLOAD_MODE_ADDR_V2              (MSM_SHARED_IMEM_BASE + 0x0)
+#define EMERGENCY_DLOAD_MODE_ADDR_V2    (MSM_SHARED_IMEM_BASE + 0xFE0)
 
 #define KPSS_BASE                   0xF9000000
 
diff --git a/platform/msm_shared/debug.c b/platform/msm_shared/debug.c
index 36dc420..3349db7 100644
--- a/platform/msm_shared/debug.c
+++ b/platform/msm_shared/debug.c
@@ -30,12 +30,14 @@
  * SUCH DAMAGE.
  */
 
+#include <stdlib.h>
 #include <debug.h>
 #include <printf.h>
 #include <arch/arm/dcc.h>
 #include <dev/fbcon.h>
 #include <dev/uart.h>
 #include <platform/timer.h>
+#include <platform.h>
 
 static void write_dcc(char c)
 {
@@ -52,8 +54,49 @@
 		timeout--;
 	}
 }
+
+#if WITH_DEBUG_LOG_BUF
+
+#ifndef LK_LOG_BUF_SIZE
+#define LK_LOG_BUF_SIZE    (4096) /* align on 4k */
+#endif
+
+#define LK_LOG_COOKIE    0x474f4c52 /* "RLOG" in ASCII */
+
+struct lk_log {
+	struct lk_log_header {
+		unsigned cookie;
+		unsigned max_size;
+		unsigned size_written;
+		unsigned idx;
+	} header;
+	char data[LK_LOG_BUF_SIZE];
+};
+
+static struct lk_log log = {
+	.header = {
+		.cookie = LK_LOG_COOKIE,
+		.max_size = sizeof(log.data),
+		.size_written = 0,
+		.idx = 0,
+	},
+	.data = {0}
+};
+
+static void log_putc(char c)
+{
+	log.data[log.header.idx++] = c;
+	log.header.size_written++;
+	if (unlikely(log.header.idx >= log.header.max_size))
+		log.header.idx = 0;
+}
+#endif /* WITH_DEBUG_LOG_BUF */
+
 void _dputc(char c)
 {
+#if WITH_DEBUG_LOG_BUF
+	log_putc(c);
+#endif
 #if WITH_DEBUG_DCC
 	if (c == '\n') {
 		write_dcc('\r');
@@ -91,6 +134,16 @@
 
 void platform_halt(void)
 {
-	dprintf(INFO, "HALT: spinning forever...\n");
+	if (set_download_mode(NORMAL_DLOAD) == 0)
+	{
+		dprintf(CRITICAL, "HALT: reboot into dload mode...\n");
+		reboot_device(0);
+		dprintf(CRITICAL, "HALT: reboot_device failed\n");
+	}
+	else
+	{
+		dprintf(CRITICAL, "HALT: set_download_mode not supported\n");
+	}
+	dprintf(CRITICAL, "HALT: spinning forever...\n");
 	for (;;) ;
 }
diff --git a/platform/msm_shared/dload_util.c b/platform/msm_shared/dload_util.c
index 4b7d08b..06140f2 100644
--- a/platform/msm_shared/dload_util.c
+++ b/platform/msm_shared/dload_util.c
@@ -28,18 +28,34 @@
 
 #include <stdlib.h>
 #include <reg.h>
+#include <dload_util.h>
 
-#define FORCE_DLOAD_COOKIE_0    0x322A4F99
-#define FORCE_DLOAD_COOKIE_1    0xC67E4350
-#define FORCE_DLOAD_COOKIE_2    0x77777777
+#define NORMAL_DLOAD_COOKIE_0       0xE47B337D
+#define NORMAL_DLOAD_COOKIE_1       0xCE14091A
+
+#define EMERGENCY_DLOAD_COOKIE_0    0x322A4F99
+#define EMERGENCY_DLOAD_COOKIE_1    0xC67E4350
+#define EMERGENCY_DLOAD_COOKIE_2    0x77777777
 
 extern void dsb();
 
-void dload_util_write_cookie(uint32_t target_dload_mode_addr)
+void dload_util_write_cookie(uint32_t target_dload_mode_addr,
+		enum dload_mode mode)
 {
-	writel(FORCE_DLOAD_COOKIE_0, target_dload_mode_addr);
-	writel(FORCE_DLOAD_COOKIE_1, target_dload_mode_addr + sizeof(uint32_t));
-	writel(FORCE_DLOAD_COOKIE_2, target_dload_mode_addr + 2 * sizeof(uint32_t));
+	if (mode == NORMAL_DLOAD)
+	{
+		writel(NORMAL_DLOAD_COOKIE_0, target_dload_mode_addr);
+		writel(NORMAL_DLOAD_COOKIE_1,
+				target_dload_mode_addr + sizeof(uint32_t));
+	}
+	else
+	{
+		writel(EMERGENCY_DLOAD_COOKIE_0, target_dload_mode_addr);
+		writel(EMERGENCY_DLOAD_COOKIE_1,
+				target_dload_mode_addr + sizeof(uint32_t));
+		writel(EMERGENCY_DLOAD_COOKIE_2,
+				target_dload_mode_addr + 2 * sizeof(uint32_t));
+	}
 
 	dsb();
 }
diff --git a/platform/msm_shared/include/dload_util.h b/platform/msm_shared/include/dload_util.h
index 71d045d..8415773 100644
--- a/platform/msm_shared/include/dload_util.h
+++ b/platform/msm_shared/include/dload_util.h
@@ -31,6 +31,12 @@
 
 #include <sys/types.h>
 
-void dload_util_write_cookie(uint32_t target_dload_mode_addr);
+enum dload_mode {
+	NORMAL_DLOAD,
+	EMERGENCY_DLOAD
+};
+
+void dload_util_write_cookie(uint32_t target_dload_mode_addr,
+		enum dload_mode mode);
 
 #endif
diff --git a/project/msm8226.mk b/project/msm8226.mk
index 262abc8..6896d27 100644
--- a/project/msm8226.mk
+++ b/project/msm8226.mk
@@ -11,6 +11,7 @@
 
 #DEFINES += WITH_DEBUG_DCC=1
 DEFINES += WITH_DEBUG_UART=1
+DEFINES += WITH_DEBUG_LOG_BUF=1
 #DEFINES += WITH_DEBUG_FBCON=1
 DEFINES += DEVICE_TREE=1
 #DEFINES += MMC_BOOT_BAM=1
diff --git a/target/init.c b/target/init.c
index 937f136..1f4362a 100644
--- a/target/init.c
+++ b/target/init.c
@@ -24,6 +24,7 @@
 #include <debug.h>
 #include <target.h>
 #include <compiler.h>
+#include <dload_util.h>
 
 #define EXPAND(NAME) #NAME
 #define TARGET(NAME) EXPAND(NAME)
@@ -68,7 +69,7 @@
 {
 }
 
-__WEAK int set_download_mode(void)
+__WEAK int set_download_mode(enum dload_mode mode)
 {
 	return -1;
 }
diff --git a/target/msm8226/init.c b/target/msm8226/init.c
index ac648e8..026aa53 100644
--- a/target/msm8226/init.c
+++ b/target/msm8226/init.c
@@ -328,9 +328,10 @@
 	return _emmc_recovery_init();
 }
 
-int set_download_mode(void)
+int set_download_mode(enum dload_mode mode)
 {
-	dload_util_write_cookie(FORCE_DLOAD_MODE_ADDR);
+	dload_util_write_cookie(mode == NORMAL_DLOAD ?
+		DLOAD_MODE_ADDR : EMERGENCY_DLOAD_MODE_ADDR, mode);
 
 	return 0;
 }
diff --git a/target/msm8974/init.c b/target/msm8974/init.c
index 5a0057c..daa98b7 100644
--- a/target/msm8974/init.c
+++ b/target/msm8974/init.c
@@ -488,9 +488,10 @@
 	dprintf(CRITICAL, "Rebooting failed\n");
 }
 
-int set_download_mode(void)
+int set_download_mode(enum dload_mode mode)
 {
-	dload_util_write_cookie(FORCE_DLOAD_MODE_ADDR_V2);
+	dload_util_write_cookie(mode == NORMAL_DLOAD ?
+		DLOAD_MODE_ADDR_V2 : EMERGENCY_DLOAD_MODE_ADDR_V2, mode);
 
 	return 0;
 }
diff --git a/target/msm8974/target_display.c b/target/msm8974/target_display.c
index 883cead..da6b3cc 100644
--- a/target/msm8974/target_display.c
+++ b/target/msm8974/target_display.c
@@ -46,16 +46,18 @@
 extern int mdss_dsi_uniphy_pll_config(void);
 extern int mdss_sharp_dsi_uniphy_pll_config(void);
 
+static struct pm8x41_wled_data wled_ctrl = {
+	.mod_scheme      = 0xC3,
+	.led1_brightness = (0x0F << 8) | 0xEF,
+	.led2_brightness = (0x0F << 8) | 0xEF,
+	.led3_brightness = (0x0F << 8) | 0xEF,
+	.max_duty_cycle  = 0x01,
+	.ovp = 0x2,
+	.full_current_scale = 0x19
+};
+
 static int msm8974_backlight_on()
 {
-	static struct pm8x41_wled_data wled_ctrl = {
-		.mod_scheme      = 0xC3,
-		.led1_brightness = (0x0F << 8) | 0xEF,
-		.led2_brightness = (0x0F << 8) | 0xEF,
-		.led3_brightness = (0x0F << 8) | 0xEF,
-		.max_duty_cycle  = 0x01,
-	};
-
 	pm8x41_wled_config(&wled_ctrl);
 	pm8x41_wled_sink_control(1);
 	pm8x41_wled_iled_sync_control(1);
@@ -187,6 +189,8 @@
 		break;
 	case HW_PLATFORM_DRAGON:
 		mipi_sharp_video_qhd_init(&(panel.panel_info));
+		wled_ctrl.ovp = 0x1; /* 32V */
+		wled_ctrl.full_current_scale = 0x14; /* 20mA */
 		panel.clk_func = msm8974_mdss_sharp_dsi_panel_clock;
 		panel.power_func = msm8974_mipi_panel_power;
 		panel.fb.base = MIPI_FB_ADDR;