Merge "msm: keypad: Initialize keypad detected to -1"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 392bdae..2f526f4 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -49,6 +49,8 @@
 #include "fastboot.h"
 #include "sparse_format.h"
 
+#include "scm_decrypt.h"
+
 #define EXPAND(NAME) #NAME
 #define TARGET(NAME) EXPAND(NAME)
 #define DEFAULT_CMDLINE "mem=100M console=null";
@@ -118,7 +120,7 @@
 	*ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
 }
 
-void boot_linux(void *kernel, unsigned *tags, 
+void boot_linux(void *kernel, unsigned *tags,
 		const char *cmdline, unsigned machtype,
 		void *ramdisk, unsigned ramdisk_size)
 {
@@ -695,13 +697,27 @@
 void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
 {
 	sparse_header_t *sparse_header;
-	sparse_header = (sparse_header_t *) data;
+	/* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
+	unsigned int *magic_number = (unsigned int *) data;
+	int ret=0;
 
+	if (magic_number[0] == SSD_HEADER_MAGIC_0 &&
+		magic_number[1] == SSD_HEADER_MAGIC_1)
+	{
+#ifdef SSD_ENABLE
+		ret = decrypt_img_scm(&data, &sz);
+#endif
+		if(ret != 0)
+		{
+			dprintf(CRITICAL, "ERROR: Invalid secure image\n");
+			return;
+		}
+	}
+	sparse_header = (sparse_header_t *) data;
 	if (sparse_header->magic != SPARSE_HEADER_MAGIC)
 		cmd_flash_mmc_img(arg, data, sz);
 	else
 		cmd_flash_mmc_sparse_img(arg, data, sz);
-
 	return;
 }
 
diff --git a/platform/msm7x27a/acpuclock.c b/platform/msm7x27a/acpuclock.c
index 4a26a75..7b4128a 100755
--- a/platform/msm7x27a/acpuclock.c
+++ b/platform/msm7x27a/acpuclock.c
@@ -31,29 +31,52 @@
 #include <kernel/thread.h>
 #include <platform/iomap.h>
 #include <reg.h>
+#include <smem.h>
 
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+#define BIT(x)	(1 << (x))
 
 #define A11S_CLK_CNTL_ADDR	(MSM_CSR_BASE + 0x100)
 #define A11S_CLK_SEL_ADDR	(MSM_CSR_BASE + 0x104)
 #define VDD_SVS_PLEVEL_ADDR	(MSM_CSR_BASE + 0x124)
-#define PLL2_L_VAL_ADDR		(MSM_CLK_CTL_BASE + 0x33C)
 
-#define SRC_SEL_PLL1	1 /* PLL1. */
-#define SRC_SEL_PLL2	2 /* PLL2. */
-#define SRC_SEL_PLL3	3 /* PLL3. Used for 7x25. */
-#define DIV_4		3
+#define PLL2_MODE_ADDR		(MSM_CLK_CTL_BASE + 0x338)
+#define PLL4_MODE_ADDR		(MSM_CLK_CTL_BASE + 0x374)
+
+#define PLL_RESET_N			BIT(2)
+#define PLL_BYPASSNL		BIT(1)
+#define PLL_OUTCTRL			BIT(0)
+
+#define SRC_SEL_TCX0	0 /* TCXO */
+#define SRC_SEL_PLL1	1 /* PLL1: modem_pll */
+#define SRC_SEL_PLL2	2 /* PLL2: backup_pll_0 */
+#define SRC_SEL_PLL3	3 /* PLL3: backup_pll_1 */
+#define SRC_SEL_PLL4	6 /* PLL4: sparrow_pll */
+
+#define DIV_1		0
 #define DIV_2		1
+#define DIV_3		2
+#define DIV_4		3
+#define DIV_5		4
+#define DIV_6		5
+#define DIV_7		6
+#define DIV_8		7
+#define DIV_9		8
+#define DIV_10		9
+#define DIV_11		10
+#define DIV_12		11
+#define DIV_13		12
+#define DIV_14		13
+#define DIV_15		14
+#define DIV_16		15
+
 #define WAIT_CNT	100
 #define VDD_LEVEL	7
 #define MIN_AXI_HZ	120000000
 #define ACPU_800MHZ	41
 
-void pll_request(unsigned pll, unsigned enable);
-void axi_clock_init(unsigned rate);
-
 /* The stepping frequencies have been choosen to make sure the step
- * is <= 256 MHz for both turbo mode and normal mode targets.  The
+ * is <= 256 MHz for both 7x27a and 7x25a targets.  The
  * table also assumes the ACPU is running at TCXO freq and AHB div is
  * set to DIV_1.
  *
@@ -61,89 +84,151 @@
  * - Start at location 0/1 depending on clock source sel bit.
  * - Set values till end of table skipping every other entry.
  * - When you reach the end of the table, you are done scaling.
- *
- * TODO: Need to fix SRC_SEL_PLL1 for 7x25.
  */
 
-uint32_t const clk_cntl_reg_val_7625[] = {
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4)  | DIV_4,
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
-	(WAIT_CNT << 16) | (SRC_SEL_PLL3 << 4)  | DIV_2,
-	(WAIT_CNT << 16) | (SRC_SEL_PLL3 << 12) | (DIV_2 << 8),
-};
-
-uint32_t const clk_cntl_reg_val_7627[] = {
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4)  | DIV_4,
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
-	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4)  | DIV_2,
+uint32_t const clk_cntl_reg_val_7627A[] = {
+	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4)  | DIV_16,
+	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_8 << 8),
+	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4)  | DIV_4,
 	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
+
+	/* TODO: Fix it for 800MHz */
+#if 0
+	(WAIT_CNT << 16) | (SRC_SEL_PLL4 << 4)  | DIV_1,
+#endif
 };
 
-uint32_t const clk_cntl_reg_val_7627T[] = {
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4)  | DIV_4,
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
-	(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
-	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4),
-	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12),
+uint32_t const clk_cntl_reg_val_7625A[] = {
+	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4)  | DIV_16,
+	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_8 << 8),
+	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4)  | DIV_4,
+	(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
 };
 
 /* Using DIV_4 for all cases to avoid worrying about turbo vs. normal
  * mode. Able to use DIV_4 for all steps because it's the largest AND
  * the final value. */
 uint32_t const clk_sel_reg_val[] = {
-	DIV_4 << 1 | 1,
-	DIV_4 << 1 | 0,
-	DIV_4 << 1 | 0,
-	DIV_4 << 1 | 1,
-	DIV_4 << 1 | 1,
-	DIV_4 << 1 | 0,
+	DIV_1 << 1 | 1, /* Switch to src1 */
+	DIV_1 << 1 | 0, /* Switch to src0 */
+};
+
+/*
+ * Mask to make sure current selected src frequency doesn't change.
+ */
+uint32_t const clk_cntl_mask[] = {
+	0x0000FF00, /* Mask to read src0 */
+	0x000000FF  /* Mask to read src1 */
 };
 
 void mdelay(unsigned msecs);
+unsigned board_msm_id(void);
 
+void pll_enable(void *pll_mode_addr)
+{
+	/* TODO: Need to add spin-lock to avoid race conditions */
+
+	uint32_t nVal;
+	/* Check status */
+	nVal =  readl(pll_mode_addr);
+	if(nVal & PLL_OUTCTRL)
+		return;
+
+	/* Put the PLL in reset mode */
+	nVal = 0;
+	nVal &= ~PLL_RESET_N;
+	nVal &= ~PLL_BYPASSNL;
+	nVal &= ~PLL_OUTCTRL;
+	writel(nVal, pll_mode_addr);
+
+	/* Put the PLL in warm-up mode */
+	nVal |= PLL_RESET_N;
+	nVal |= PLL_BYPASSNL;
+	writel(nVal, pll_mode_addr);
+
+	/* Wait for the PLL warm-up time */
+	udelay(50);
+
+	/* Put the PLL in active mode */
+	nVal |= PLL_RESET_N;
+	nVal |= PLL_BYPASSNL;
+	nVal |= PLL_OUTCTRL;
+	writel(nVal, pll_mode_addr);
+}
+
+void pll_request(unsigned pll, unsigned enable)
+{
+	int val = 0;
+	if(!enable) {
+		/* Disable not supported */
+		return;
+	}
+	switch(pll) {
+		case 2:
+			pll_enable(PLL2_MODE_ADDR);
+			return;
+		case 4:
+			pll_enable(PLL4_MODE_ADDR);
+			return;
+		default:
+			return;
+	};
+}
 
 void acpu_clock_init(void)
 {
-	unsigned i,clk;
-
-#if (!ENABLE_NANDWRITE)
-		int *modem_stat_check = (MSM_SHARED_BASE + 0x14);
-
-		/* Wait for modem to be ready before clock init */
-		while (readl(modem_stat_check) != 1);
-#endif
+	uint32_t i,clk;
+	uint32_t val;
+	uint32_t *clk_cntl_reg_val, size;
+	unsigned msm_id;
 
 	/* Increase VDD level to the final value. */
 	writel((1 << 7) | (VDD_LEVEL << 3), VDD_SVS_PLEVEL_ADDR);
+
 #if (!ENABLE_NANDWRITE)
 	thread_sleep(1);
 #else
-		mdelay(1);
+	mdelay(1);
 #endif
 
+	msm_id = board_msm_id();
+	switch(msm_id) {
+		case MSM7227A:
+		case MSM7627A:
+		case ESM7227A:
+			clk_cntl_reg_val = clk_cntl_reg_val_7627A;
+			size = ARRAY_SIZE(clk_cntl_reg_val_7627A);
+			pll_request(2, 1);
+			pll_request(4, 1);
+			break;
+
+		case MSM7225A:
+		case MSM7625A:
+		default:
+			clk_cntl_reg_val = clk_cntl_reg_val_7625A;
+			size = ARRAY_SIZE(clk_cntl_reg_val_7625A);
+			pll_request(2, 1);
+			break;
+	};
+
 	/* Read clock source select bit. */
-	i = readl(A11S_CLK_SEL_ADDR) & 1;
-	clk = readl(PLL2_L_VAL_ADDR) & 0x3F;
+	val = readl(A11S_CLK_SEL_ADDR);
+	i = val & 1;
 
-	/* Jump into table and set every other entry. */
-	for(; i < ARRAY_SIZE(clk_cntl_reg_val_7627); i += 2) {
-#ifdef ENABLE_PLL3
-		writel(clk_cntl_reg_val_7625[i], A11S_CLK_CNTL_ADDR);
-#else
-		if(clk == ACPU_800MHZ)
-			writel(clk_cntl_reg_val_7627T[i], A11S_CLK_CNTL_ADDR);
-		else
-			writel(clk_cntl_reg_val_7627[i], A11S_CLK_CNTL_ADDR);
-#endif
+	/* Jump into table and set every entry. */
+	for(; i < size; i++) {
+
+		val = readl(A11S_CLK_CNTL_ADDR);
+
+		/* Make sure not to disturb already used src */
+		val &= clk_cntl_mask[i%2];
+		val += clk_cntl_reg_val[i];
+		writel(val, A11S_CLK_CNTL_ADDR);
+
 		/* Would need a dmb() here but the whole address space is
 		 * strongly ordered, so it should be fine.
 		 */
-		writel(clk_sel_reg_val[i], A11S_CLK_SEL_ADDR);
+		writel(clk_sel_reg_val[i%2], A11S_CLK_SEL_ADDR);
 #if (!ENABLE_NANDWRITE)
 		thread_sleep(1);
 #else
diff --git a/platform/msm7x27a/gpio.c b/platform/msm7x27a/gpio.c
index a49efec..9615d33 100644
--- a/platform/msm7x27a/gpio.c
+++ b/platform/msm7x27a/gpio.c
@@ -40,6 +40,7 @@
 #define GPIO_OUT_2		 GPIO1_REG(0x04)  /* gpio  67-43 */
 #define GPIO_OUT_3		 GPIO1_REG(0x08)  /* gpio  94-68 */
 #define GPIO_OUT_4		 GPIO1_REG(0x0C)  /* gpio 106-95 */
+#define GPIO_OUT_5		 GPIO1_REG(0x50)  /* gpio 132-107 */
 
 /* same pin map as above, output enable */
 #define GPIO_OE_0		  GPIO1_REG(0x10)
@@ -47,6 +48,7 @@
 #define GPIO_OE_2		  GPIO1_REG(0x14)
 #define GPIO_OE_3		  GPIO1_REG(0x18)
 #define GPIO_OE_4		  GPIO1_REG(0x1C)
+#define GPIO_OE_5		  GPIO1_REG(0x54)
 
 /* same pin map as above, input read */
 #define GPIO_IN_0		  GPIO1_REG(0x34)
@@ -54,6 +56,7 @@
 #define GPIO_IN_2		  GPIO1_REG(0x38)
 #define GPIO_IN_3		  GPIO1_REG(0x3C)
 #define GPIO_IN_4		  GPIO1_REG(0x40)
+#define GPIO_IN_5		  GPIO1_REG(0x44)
 
 /* same pin map as above, 1=edge 0=level interrup */
 #define GPIO_INT_EDGE_0	GPIO1_REG(0x60)
@@ -61,6 +64,7 @@
 #define GPIO_INT_EDGE_2	GPIO1_REG(0x64)
 #define GPIO_INT_EDGE_3	GPIO1_REG(0x68)
 #define GPIO_INT_EDGE_4	GPIO1_REG(0x6C)
+#define GPIO_INT_EDGE_5	GPIO1_REG(0xC0)
 
 /* same pin map as above, 1=positive 0=negative */
 #define GPIO_INT_POS_0	 GPIO1_REG(0x70)
@@ -68,6 +72,7 @@
 #define GPIO_INT_POS_2	 GPIO1_REG(0x74)
 #define GPIO_INT_POS_3	 GPIO1_REG(0x78)
 #define GPIO_INT_POS_4	 GPIO1_REG(0x7C)
+#define GPIO_INT_POS_5	 GPIO1_REG(0xBC)
 
 /* same pin map as above, interrupt enable */
 #define GPIO_INT_EN_0	  GPIO1_REG(0x80)
@@ -75,6 +80,7 @@
 #define GPIO_INT_EN_2	  GPIO1_REG(0x84)
 #define GPIO_INT_EN_3	  GPIO1_REG(0x88)
 #define GPIO_INT_EN_4	  GPIO1_REG(0x8C)
+#define GPIO_INT_EN_5	  GPIO1_REG(0xB8)
 
 /* same pin map as above, write 1 to clear interrupt */
 #define GPIO_INT_CLEAR_0   GPIO1_REG(0x90)
@@ -82,6 +88,7 @@
 #define GPIO_INT_CLEAR_2   GPIO1_REG(0x94)
 #define GPIO_INT_CLEAR_3   GPIO1_REG(0x98)
 #define GPIO_INT_CLEAR_4   GPIO1_REG(0x9C)
+#define GPIO_INT_CLEAR_5   GPIO1_REG(0xB4)
 
 /* same pin map as above, 1=interrupt pending */
 #define GPIO_INT_STATUS_0  GPIO1_REG(0xA0)
@@ -89,6 +96,7 @@
 #define GPIO_INT_STATUS_2  GPIO1_REG(0xA4)
 #define GPIO_INT_STATUS_3  GPIO1_REG(0xA8)
 #define GPIO_INT_STATUS_4  GPIO1_REG(0xAC)
+#define GPIO_INT_STATUS_5  GPIO1_REG(0xB0)
 
 typedef struct gpioregs gpioregs;
 
@@ -155,12 +163,26 @@
 		.int_pos =	 GPIO_INT_POS_4,
 		.oe =		  GPIO_OE_4,
 	},
+	{
+		.out =		 GPIO_OUT_5,
+		.in =		  GPIO_IN_5,
+		.int_status =  GPIO_INT_STATUS_5,
+		.int_clear =   GPIO_INT_CLEAR_5,
+		.int_en =	  GPIO_INT_EN_5,
+		.int_edge =	GPIO_INT_EDGE_5,
+		.int_pos =	 GPIO_INT_POS_5,
+		.oe =		  GPIO_OE_5,
+	},
 };
 
 static gpioregs *find_gpio(unsigned n, unsigned *bit)
 {
-	if(n > 106)
+	if(n > 132)
 		return 0;
+	if(n > 106) {
+		*bit = 1 << (n - 107);
+		return GPIO_REGS + 5;
+	}
 	if(n > 94) {
 		*bit = 1 << (n - 95);
 		return GPIO_REGS + 4;
diff --git a/platform/msm7x27a/platform.c b/platform/msm7x27a/platform.c
index 43ea05b..e06618b 100644
--- a/platform/msm7x27a/platform.c
+++ b/platform/msm7x27a/platform.c
@@ -51,9 +51,10 @@
 
 void platform_early_init(void)
 {
-		//uart3_clock_init();
-	//uart_init();
-
+#if WITH_DEBUG_UART
+	uart1_clock_init();
+	uart_init();
+#endif
 	platform_init_interrupts();
 	platform_init_timer();
 }
@@ -61,9 +62,7 @@
 void platform_init(void)
 {
 	dprintf(INFO, "platform_init()\n");
-#if 0
 	acpu_clock_init();
-#endif
 }
 
 void display_init(void)
diff --git a/platform/msm8x60/include/platform/pmic.h b/platform/msm8x60/include/platform/pmic.h
index 94f4b8f..d1c0a2d 100755
--- a/platform/msm8x60/include/platform/pmic.h
+++ b/platform/msm8x60/include/platform/pmic.h
@@ -1,5 +1,5 @@
 /*
- * * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ * * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -88,6 +88,8 @@
 
 typedef enum
 {
+    PM_KYPD_PWRON_IRQ_ID        = 51,
+
     /* Block 24 Interrupts */
     PM_GPIO01_CHGED_ST_IRQ_ID   = 192,
     PM_GPIO02_CHGED_ST_IRQ_ID   = 193,
@@ -137,6 +139,6 @@
     PM_GPIO38_CHGED_ST_IRQ_ID   = 229,
     PM_GPIO39_CHGED_ST_IRQ_ID   = 230,
     PM_GPIO40_CHGED_ST_IRQ_ID   = 231,
-}pm_sec_gpio_irq_id_type;
+}pm_irq_id_type;
 
 #endif
diff --git a/platform/msm8x60/pmic.c b/platform/msm8x60/pmic.c
index 0da7291..8c71600 100755
--- a/platform/msm8x60/pmic.c
+++ b/platform/msm8x60/pmic.c
@@ -54,12 +54,12 @@
 
 }
 
-int pm8058_get_gpio_status( pm_sec_gpio_irq_id_type gpio_irq, bool *rt_status)
+int pm8058_get_irq_status( pm_irq_id_type irq, bool *rt_status)
 {
     unsigned block_index, reg_data, reg_mask;
     int errFlag;
 
-    block_index = PM_IRQ_ID_TO_BLOCK_INDEX(gpio_irq);
+    block_index = PM_IRQ_ID_TO_BLOCK_INDEX(irq);
 
     /* select the irq block */
     errFlag =pa1_ssbi2_write_bytes(&block_index,1,IRQ_BLOCK_SEL_USR_ADDR);
@@ -76,7 +76,7 @@
         dprintf(INFO,"Device Timeout");
         return 1;
     }
-    reg_mask = PM_IRQ_ID_TO_BIT_MASK(gpio_irq);
+    reg_mask = PM_IRQ_ID_TO_BIT_MASK(irq);
 
     if ((reg_data & reg_mask) == reg_mask )
     {
@@ -93,12 +93,12 @@
 
 bool pm8058_gpio_get(unsigned int gpio)
 {
-	pm_sec_gpio_irq_id_type gpio_irq;
+	pm_irq_id_type gpio_irq;
 	bool status;
 	int ret;
 
 	gpio_irq = gpio + PM_GPIO01_CHGED_ST_IRQ_ID;
-	ret = pm8058_get_gpio_status(gpio_irq, &status);
+	ret = pm8058_get_irq_status(gpio_irq, &status);
 
 	if(ret)
 		dprintf(CRITICAL,"pm8058_gpio_get failed\n");
diff --git a/platform/msm8x60/rules.mk b/platform/msm8x60/rules.mk
index e4adc5b..f258110 100644
--- a/platform/msm8x60/rules.mk
+++ b/platform/msm8x60/rules.mk
@@ -8,7 +8,9 @@
 MMC_SLOT         := 1
 
 DEFINES += WITH_CPU_EARLY_INIT=0 WITH_CPU_WARM_BOOT=0 \
-	   MMC_SLOT=$(MMC_SLOT) MDP4=1
+	   MMC_SLOT=$(MMC_SLOT) MDP4=1 \
+	   SSD_ENABLE
+
 
 DEFINES += QT_8660_KEYPAD_HW_BUG=1
 
diff --git a/platform/msm_shared/crypto_eng.c b/platform/msm_shared/crypto_eng.c
index e4d511b..d36c9a4 100644
--- a/platform/msm_shared/crypto_eng.c
+++ b/platform/msm_shared/crypto_eng.c
@@ -256,12 +256,13 @@
         memset(data,0,sizeof(unsigned int));
 
         if(sha1_ctx->saved_buff_indx)
-        {
-            data[4-bytes_left] = *(sha1_ctx->saved_buff + bytes_to_write - 1);
-        }
+            buff_ptr = (sha1_ctx->saved_buff + bytes_to_write - 1);
         else
+            buff_ptr = (((unsigned char *)data_ptr) + buff_size - 1);
+
+        for(i=0;i<bytes_left;i++)
         {
-            data[4-bytes_left] = *(((unsigned char *)data_ptr) + buff_size - 1);
+            data[3-i] = *(buff_ptr-bytes_left+i+1);
         }
 
         ce_status = rd_ce(CRYPTO3_STATUS);
diff --git a/platform/msm_shared/include/scm_decrypt.h b/platform/msm_shared/include/scm_decrypt.h
new file mode 100644
index 0000000..4740759
--- /dev/null
+++ b/platform/msm_shared/include/scm_decrypt.h
@@ -0,0 +1,71 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+
+/* 8 Byte SSD magic number (LE) */
+#define SSD_HEADER_MAGIC_0     0x73737A74
+#define SSD_HEADER_MAGIC_1     0x676D6964
+#define SSD_HEADER_MAGIC_SIZE  8
+#define SSD_HEADER_XML_SIZE    2048
+
+typedef unsigned int uint32;
+
+typedef struct
+{
+    uint32  len;
+    uint32  buf_offset;
+    uint32  resp_hdr_offset;
+    uint32  id;
+} scm_command;
+
+typedef struct
+{
+    uint32  len;
+    uint32  buf_offset;
+    uint32  is_complete;
+} scm_response;
+
+typedef struct
+{
+    scm_command     common_req;
+    uint32*         img_ptr;
+    uint32*         img_len_ptr;
+} decrypt_img_req;
+
+#define SYSCALL_CREATE_CMD_ID(s, f) \
+  ((uint32)(((s & 0x3ff) << 10) | (f & 0x3ff)))
+
+#define SCM_SVC_SSD                7
+#define SSD_DECRYPT_IMG_ID SYSCALL_CREATE_CMD_ID(SCM_SVC_SSD, 0x01)
+
+void setup_decrypt_cmd ( decrypt_img_req* dec_cmd,
+                         uint32** img_ptr,
+                         uint32* img_len_ptr);
+static uint32 smc(uint32 cmd_addr);
+int decrypt_img_scm(uint32** img_ptr, uint32* img_len_ptr);
diff --git a/platform/msm_shared/nand.c b/platform/msm_shared/nand.c
index af6d3ff..e69fa24 100644
--- a/platform/msm_shared/nand.c
+++ b/platform/msm_shared/nand.c
@@ -108,6 +108,8 @@
 static struct flash_info flash_info;
 static unsigned flash_pagesize = 0;
 static int interleaved_mode = 0;
+static unsigned num_pages_per_blk = 0;
+static unsigned num_pages_per_blk_mask = 0;
 
 struct flash_identification {
 	unsigned flash_id;
@@ -246,8 +248,8 @@
 	cwperpage = (flash_pagesize >> 9);
 
 	/* Check first page of this block */
-	if(page & 63)
-		page = page - (page & 63);
+	if(page & num_pages_per_blk_mask)
+		page = page - (page & num_pages_per_blk_mask);
 
 	/* Check bad block marker */
 	data[0] = NAND_CMD_PAGE_READ;	/* command */
@@ -493,13 +495,13 @@
 	int isbad = 0;
 
 	/* only allow erasing on block boundaries */
-	if(page & 63) return -1;
+	if(page & num_pages_per_blk_mask) return -1;
 
 	/* Check for bad block and erase only if block is not marked bad */
 	isbad = flash_nand_block_isbad(cmdlist, ptrlist, page);
 
 	if (isbad) {
-		dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
+		dprintf(INFO, "skipping @ %d (bad block)\n", page / num_pages_per_blk);
 		return -1;
 	}
 
@@ -1692,8 +1694,8 @@
 {
   memset(empty_buf,0,528);
   /* Going to first page of the block */
-  if(page & 63)
-	page = page - (page & 63);
+  if(page & num_pages_per_blk_mask)
+	page = page - (page & num_pages_per_blk_mask);
   return _flash_nand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
 }
 
@@ -1887,8 +1889,8 @@
 	unsigned char *oobptr = &(page_data[2048]);
 
 	/* Going to first page of the block */
-	if(page & 63)
-		page = page - (page & 63);
+	if(page & num_pages_per_blk_mask)
+		page = page - (page & num_pages_per_blk_mask);
 
 	/* Reading page in raw mode */
 	if (_flash_onenand_read_page(cmdlist, ptrlist,page, page_data, 0, 1))
@@ -1913,7 +1915,7 @@
 	unsigned *ptr = ptrlist;
 	struct data_onenand_erase *data = (void *)ptrlist + 4;
 	int isbad = 0;
-	unsigned erasesize = (flash_pagesize << 6);
+	unsigned erasesize = (flash_pagesize * num_pages_per_blk);
 	unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 | (page * flash_pagesize)/erasesize;
 	unsigned onenand_startaddr8 = 0x0000;
 	unsigned onenand_startaddr2 = DEVICE_BUFFERRAM_0 << 15;
@@ -1929,7 +1931,7 @@
 	isbad = flash_onenand_block_isbad(cmdlist, ptrlist, page);
 	if (isbad)
 	{
-		dprintf(INFO, "skipping @ %d (bad block)\n", page >> 6);
+		dprintf(INFO, "skipping @ %d (bad block)\n", page / num_pages_per_blk);
 		return -1;
 	}
 
@@ -2223,7 +2225,7 @@
 	unsigned curr_addr = (unsigned) _addr;
 	unsigned spareaddr = (unsigned) _spareaddr;
 	unsigned i;
-	unsigned erasesize = (flash_pagesize<<6);
+	unsigned erasesize = (flash_pagesize * num_pages_per_blk);
 	unsigned writesize = flash_pagesize;
 
 	unsigned onenand_startaddr1 = DEVICE_FLASHCORE_0 |
@@ -2676,7 +2678,7 @@
 	char * spareaddr = (char *) _spareaddr;
 	unsigned i, j, k;
 
-	unsigned erasesize = (flash_pagesize<<6);
+	unsigned erasesize = (flash_pagesize * num_pages_per_blk);
 	unsigned writesize = flash_pagesize;
 
 	unsigned onenand_startaddr1 = (page * flash_pagesize) / erasesize;
@@ -3098,8 +3100,8 @@
 {
   memset(empty_buf,0,528);
   /* Going to first page of the block */
-  if(page & 63)
-	page = page - (page & 63);
+  if(page & num_pages_per_blk_mask)
+	page = page - (page & num_pages_per_blk_mask);
   return _flash_onenand_write_page(cmdlist, ptrlist, page, empty_buf, 0, 1);
 }
 
@@ -3176,6 +3178,9 @@
 			flash_info.num_blocks = 0;
 		}
 		ASSERT(flash_info.num_blocks);
+		// Use this for getting the next/current blocks
+		num_pages_per_blk = flash_info.block_size / flash_pagesize;
+		num_pages_per_blk_mask = num_pages_per_blk - 1;
 		return;
 	}
 
@@ -3300,7 +3305,7 @@
 
 	set_nand_configuration(ptn->type);
 	while(count-- > 0) {
-		if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * 64)) {
+		if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * num_pages_per_blk)) {
 			dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
 		}
 		block++;
@@ -3311,13 +3316,13 @@
 int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
 			unsigned offset, void *data, unsigned bytes)
 {
-	unsigned page = (ptn->start * 64) + (offset / flash_pagesize);
-	unsigned lastpage = (ptn->start + ptn->length) * 64;
+	unsigned page = (ptn->start * num_pages_per_blk) + (offset / flash_pagesize);
+	unsigned lastpage = (ptn->start + ptn->length) * num_pages_per_blk;
 	unsigned count = (bytes + flash_pagesize - 1 + extra_per_page) / (flash_pagesize + extra_per_page);
 	unsigned *spare = (unsigned*) flash_spare;
 	unsigned errors = 0;
 	unsigned char *image = data;
-	unsigned current_block = (page - (page & 63)) >> 6;
+	unsigned current_block = (page - (page & num_pages_per_blk_mask)) / num_pages_per_blk;
 	unsigned start_block = ptn->start;
 	int result = 0;
 	int isbad = 0;
@@ -3334,9 +3339,9 @@
 	{
 		start_block_count = (current_block - start_block);
 		while (start_block_count && (start_block < (ptn->start + ptn->length))) {
-			isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*64);
+			isbad = _flash_block_isbad(flash_cmdlist, flash_ptrlist, start_block*num_pages_per_blk);
 			if (isbad)
-				page += 64;
+				page += num_pages_per_blk;
 			else
 				start_block_count--;
 			start_block++;
@@ -3359,7 +3364,7 @@
 		}
 		else if (result == -2) {
 			// bad block, go to next block same offset
-			page += 64;
+			page += num_pages_per_blk;
 			errors++;
 			continue;
 		}
@@ -3379,8 +3384,8 @@
 int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
 		unsigned bytes)
 {
-	unsigned page = ptn->start * 64;
-	unsigned lastpage = (ptn->start + ptn->length) * 64;
+	unsigned page = ptn->start * num_pages_per_blk;
+	unsigned lastpage = (ptn->start + ptn->length) * num_pages_per_blk;
 	unsigned *spare = (unsigned*) flash_spare;
 	const unsigned char *image = data;
 	unsigned wsize = flash_pagesize + extra_per_page;
@@ -3406,10 +3411,10 @@
 			return -1;
 		}
 
-		if((page & 63) == 0) {
+		if((page & num_pages_per_blk_mask) == 0) {
 			if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
-				dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
-				page += 64;
+				dprintf(INFO, "flash_write_image: bad block @ %d\n", page / num_pages_per_blk);
+				page += num_pages_per_blk;
 				continue;
 			}
 		}
@@ -3421,9 +3426,9 @@
 		}
 		if(r) {
 			dprintf(INFO, "flash_write_image: write failure @ page %d (src %d)\n", page, image - (const unsigned char *)data);
-			image -= (page & 63) * wsize;
-			bytes += (page & 63) * wsize;
-			page &= ~63;
+			image -= (page & num_pages_per_blk_mask) * wsize;
+			bytes += (page & num_pages_per_blk_mask) * wsize;
+			page &= ~num_pages_per_blk_mask;
 			if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
 				dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
 			}
@@ -3431,7 +3436,7 @@
 				flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
 			}
 			dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
-			page += 64;
+			page += num_pages_per_blk;
 			continue;
 		}
 		page++;
@@ -3440,12 +3445,12 @@
 	}
 
 	/* erase any remaining pages in the partition */
-	page = (page + 63) & (~63);
+	page = (page + num_pages_per_blk_mask) & (~num_pages_per_blk_mask);
 	while(page < lastpage){
 		if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
-			dprintf(INFO, "flash_write_image: bad block @ %d\n", page >> 6);
+			dprintf(INFO, "flash_write_image: bad block @ %d\n", page / num_pages_per_blk);
 		}
-		page += 64;
+		page += num_pages_per_blk;
 	}
 
 	dprintf(INFO, "flash_write_image: success\n");
diff --git a/platform/msm_shared/proc_comm.c b/platform/msm_shared/proc_comm.c
index eff7a43..fca1358 100644
--- a/platform/msm_shared/proc_comm.c
+++ b/platform/msm_shared/proc_comm.c
@@ -257,6 +257,12 @@
 	clock_set_rate(UART2_CLK, 19200000);
 }
 
+void uart1_clock_init(void)
+{
+	clock_enable(UART1_CLK);
+	clock_set_rate(UART1_CLK, 19200000 / 4);
+}
+
 void mddi_clock_init(unsigned num, unsigned rate)
 {
 	unsigned clock_id;
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index d01ca40..25cba45 100644
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -45,5 +45,6 @@
 
 ifeq ($(PLATFORM),msm8x60)
 	OBJS += $(LOCAL_DIR)/crypto_eng.o \
-	        $(LOCAL_DIR)/crypto_hash.o
+	        $(LOCAL_DIR)/crypto_hash.o \
+		$(LOCAL_DIR)/scm_decrypt.o
 endif
diff --git a/platform/msm_shared/scm_decrypt.c b/platform/msm_shared/scm_decrypt.c
new file mode 100644
index 0000000..df1b399
--- /dev/null
+++ b/platform/msm_shared/scm_decrypt.c
@@ -0,0 +1,82 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "scm_decrypt.h"
+
+#pragma GCC optimize ("O0")
+
+/* From Linux Kernel asm/system.h */
+#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
+
+void setup_decrypt_cmd ( decrypt_img_req* dec_cmd,
+                         uint32_t** img_ptr,
+                         uint32_t* img_len_ptr)
+{
+    dec_cmd->common_req.len = sizeof(decrypt_img_req);
+    dec_cmd->common_req.buf_offset = sizeof(scm_command);
+    dec_cmd->common_req.resp_hdr_offset = 0;
+    dec_cmd->common_req.id = SSD_DECRYPT_IMG_ID;
+
+    dec_cmd->img_ptr = img_ptr;
+    dec_cmd->img_len_ptr = img_len_ptr;
+}
+
+static uint32_t smc(uint32_t cmd_addr)
+{
+	uint32_t context_id;
+	register uint32_t r0 __asm__("r0") = 1;
+	register uint32_t r1 __asm__("r1") = (uint32_t)&context_id;
+	register uint32_t r2 __asm__("r2") = cmd_addr;
+	__asm__(
+		"1:smc	#0	@ switch to secure world\n"
+		"cmp	r0, #1				\n"
+		"beq	1b				\n"
+		: "=r" (r0)
+		: "r" (r0), "r" (r1), "r" (r2)
+		: "r3", "cc");
+	return r0;
+}
+
+
+int decrypt_img_scm(uint32_t** img_ptr, uint32_t* img_len_ptr)
+{
+   int ret = 0;
+   decrypt_img_req *decrypt_cmd;
+
+   /* allocate memory for the command structure */
+   /* NEEDS TO BE CONTIGUOUS MEMORY */
+   decrypt_cmd = malloc(sizeof(decrypt_img_req));
+
+   /* setup the command for decryption */
+   setup_decrypt_cmd(decrypt_cmd, img_ptr, img_len_ptr);
+
+   ret = smc(decrypt_cmd);
+   free(decrypt_cmd);
+   return ret;
+}
+
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index 71da345..5dda467 100644
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -116,6 +116,11 @@
     MSM8260 = 70,
     MSM8660 = 71,
     APQ8060 = 86,
+    MSM7225A = 88,
+    MSM7625A = 89,
+    MSM7227A = 90,
+    MSM7627A = 91,
+    ESM7227A = 92,
 };
 
 enum platform
diff --git a/platform/msm_shared/timer.c b/platform/msm_shared/timer.c
index 2a5600f..be3ac0f 100644
--- a/platform/msm_shared/timer.c
+++ b/platform/msm_shared/timer.c
@@ -96,7 +96,7 @@
 #else
 #define DGT_HZ 6144000	/* Uses LPXO/4 (24.576 MHz / 4) */
 #endif
-#elif defined PLATFORM_MSM8X60
+#elif (defined(PLATFORM_MSM8X60) || defined(PLATFORM_MSM8960))
 #define DGT_HZ 6750000	/* Uses LPXO/4 (27.0 MHz / 4) */
 #else
 #define DGT_HZ 19200000	/* Uses TCXO (19.2 MHz) */
@@ -127,7 +127,7 @@
 	if(val >= 1)
 	    writel(1, DGT_CLK_CTL);
 #endif
-#ifdef PLATFORM_MSM8X60
+#if (defined(PLATFORM_MSM8X60) || defined(PLATFORM_MSM8960))
 	writel(3, DGT_CLK_CTL);
 #endif
 	enter_critical_section();
@@ -160,7 +160,7 @@
 
 static void wait_for_timer_op(void)
 {
-#if PLATFORM_QSD8K || PLATFORM_MSM7X30 || PLATFORM_MSM8X60
+#if PLATFORM_QSD8K || PLATFORM_MSM7X30 || PLATFORM_MSM8X60 || PLATFORM_MSM8960
 	while( readl(SPSS_TIMER_STATUS) & SPSS_TIMER_STATUS_DGT_EN );
 #endif
 }
diff --git a/platform/msm_shared/uart.c b/platform/msm_shared/uart.c
index 7f5c7e2..af6dcd9 100644
--- a/platform/msm_shared/uart.c
+++ b/platform/msm_shared/uart.c
@@ -121,6 +121,8 @@
 static unsigned uart_ready = 0;
 #if PLATFORM_MSM7X30
 static unsigned uart_base = MSM_UART2_BASE;
+#elif PLATFORM_MSM7X27A
+static unsigned uart_base = MSM_UART1_BASE;
 #else
 static unsigned uart_base = MSM_UART3_BASE;
 #endif
@@ -136,7 +138,7 @@
 	uwr(0x10, UART_CR);  /* reset receiver */
 	uwr(0x20, UART_CR);  /* reset transmitter */
 	
-#if PLATFORM_QSD8K || PLATFORM_MSM7X30
+#if PLATFORM_QSD8K || PLATFORM_MSM7X30 || PLATFORM_MSM7X27A
 	/* TCXO */
 	uwr(0x06, UART_MREG);
 	uwr(0xF1, UART_NREG);
diff --git a/target/msm7627a/init.c b/target/msm7627a/init.c
index c6dbe3d..a591f46 100644
--- a/target/msm7627a/init.c
+++ b/target/msm7627a/init.c
@@ -48,6 +48,8 @@
 #define NUM_PAGES_PER_BLOCK	0x40
 
 static struct ptable flash_ptable;
+unsigned hw_platform = 0;
+unsigned target_msm_id = 0;
 
 /* for these partitions, start will be offset by either what we get from
  * smem, or from the above offset if smem is not useful. Also, we should
@@ -114,13 +116,10 @@
 
 	dprintf(INFO, "target_init()\n");
 
-/* TODO: Enable keypad support */
-#if 0
 #if (!ENABLE_NANDWRITE)
 	keys_init();
 	keypad_init();
 #endif
-#endif
 
 	if (target_is_emmc_boot())
 	{
@@ -179,9 +178,67 @@
 	flash_set_ptable(&flash_ptable);
 }
 
+void board_info(void)
+{
+	struct smem_board_info_v4 board_info_v4;
+	unsigned int board_info_len = 0;
+	unsigned smem_status;
+	unsigned format = 0;
+	unsigned id = 0;
+
+	if (hw_platform && target_msm_id)
+		return;
+
+	hw_platform = MSM7X27A_SURF;
+	target_msm_id = MSM7225A;
+
+	smem_status = smem_read_alloc_entry_offset(SMEM_BOARD_INFO_LOCATION,
+											&format, sizeof(format), 0);
+	if(!smem_status)
+	{
+		if(format == 4)
+		{
+			board_info_len = sizeof(board_info_v4);
+			smem_status = smem_read_alloc_entry(SMEM_BOARD_INFO_LOCATION,
+										&board_info_v4, board_info_len);
+			if(!smem_status)
+			{
+				id = board_info_v4.board_info_v3.hw_platform;
+				target_msm_id = board_info_v4.board_info_v3.msm_id;
+			}
+		}
+
+		/* Detect SURF v/s FFA v/s Fluid */
+		switch(id)
+		{
+			case 0x1:
+				hw_platform = MSM7X27A_SURF;
+				break;
+			case 0x2:
+				hw_platform = MSM7X27A_FFA;
+				break;
+			default:
+				hw_platform = MSM7X27A_SURF;
+		};
+
+		if ((target_msm_id < MSM7225A) || (target_msm_id > ESM7227A))
+		{
+			target_msm_id = MSM7225A;
+		}
+	}
+	return;
+}
+
 unsigned board_machtype(void)
 {
-	return LINUX_MACHTYPE;
+	board_info();
+	return hw_platform;
+}
+
+unsigned board_msm_id(void)
+{
+	board_info();
+	return target_msm_id;
 }
 
 void reboot_device(unsigned reboot_reason)
diff --git a/target/msm7627a/keypad.c b/target/msm7627a/keypad.c
index c51c015..2657e02 100644
--- a/target/msm7627a/keypad.c
+++ b/target/msm7627a/keypad.c
@@ -38,61 +38,41 @@
 /* don't turn this on without updating the ffa support */
 #define SCAN_FUNCTION_KEYS 0
 
-static unsigned int halibut_row_gpios[] = {
-	31, 32, 33, 34, 35, 41
-#if SCAN_FUNCTION_KEYS
-	, 42
-#endif
-};
-
-static unsigned int halibut_col_gpios[] = { 36, 37, 38, 39, 40 };
+static unsigned int halibut_row_gpios[] = {31, 32, 33, 34, 35};
+static unsigned int halibut_col_gpios[] = {36, 37, 38, 39, 40};
 
 #define KEYMAP_INDEX(row, col) ((row)*ARRAY_SIZE(halibut_col_gpios) + (col))
 
 static const unsigned short halibut_keymap[ARRAY_SIZE(halibut_col_gpios) * ARRAY_SIZE(halibut_row_gpios)] = {
-	[KEYMAP_INDEX(0, 0)] = KEY_5,
-	[KEYMAP_INDEX(0, 1)] = KEY_9,
-	[KEYMAP_INDEX(0, 2)] = KEY_SOFT1,
-	[KEYMAP_INDEX(0, 3)] = KEY_6,
-	[KEYMAP_INDEX(0, 4)] = KEY_LEFT,
+	[KEYMAP_INDEX(0, 0)] = KEY_7,
+	[KEYMAP_INDEX(0, 1)] = KEY_DOWN,
+	[KEYMAP_INDEX(0, 2)] = KEY_UP,
+	[KEYMAP_INDEX(0, 3)] = KEY_RIGHT,
+	[KEYMAP_INDEX(0, 4)] = KEY_CENTER,
 
-	[KEYMAP_INDEX(1, 0)] = KEY_0,
-	[KEYMAP_INDEX(1, 1)] = KEY_RIGHT,
+	[KEYMAP_INDEX(1, 0)] = KEY_LEFT,
+	[KEYMAP_INDEX(1, 1)] = KEY_SEND,
 	[KEYMAP_INDEX(1, 2)] = KEY_1,
-	[KEYMAP_INDEX(1, 3)] = KEY_SHARP,
-	[KEYMAP_INDEX(1, 4)] = KEY_SEND,
+	[KEYMAP_INDEX(1, 3)] = KEY_4,
+	[KEYMAP_INDEX(1, 4)] = KEY_CLEAR,
 
-	[KEYMAP_INDEX(2, 0)] = KEY_VOLUMEUP,
-	[KEYMAP_INDEX(2, 1)] = KEY_HOME,	  /* FA   */
-	[KEYMAP_INDEX(2, 2)] = KEY_F8,		/* QCHT */
-	[KEYMAP_INDEX(2, 3)] = KEY_F6,		/* R+   */
-	[KEYMAP_INDEX(2, 4)] = KEY_F7,		/* R-   */
+	[KEYMAP_INDEX(2, 0)] = KEY_6,
+	[KEYMAP_INDEX(2, 1)] = KEY_5,
+	[KEYMAP_INDEX(2, 2)] = KEY_8,
+	[KEYMAP_INDEX(2, 3)] = KEY_3,
+	[KEYMAP_INDEX(2, 4)] = KEY_STAR,
 
-	[KEYMAP_INDEX(3, 0)] = KEY_UP,
-	[KEYMAP_INDEX(3, 1)] = KEY_CLEAR,
-	[KEYMAP_INDEX(3, 2)] = KEY_4,
-	[KEYMAP_INDEX(3, 3)] = KEY_MUTE,	  /* SPKR */
-	[KEYMAP_INDEX(3, 4)] = KEY_2,
+	[KEYMAP_INDEX(3, 0)] = KEY_9,
+	[KEYMAP_INDEX(3, 1)] = KEY_SOFT1,
+	[KEYMAP_INDEX(3, 2)] = KEY_0,
+	[KEYMAP_INDEX(3, 3)] = KEY_2,
+	[KEYMAP_INDEX(3, 4)] = KEY_SOFT2,
 
-	[KEYMAP_INDEX(4, 0)] = KEY_SOFT2,		   /* SOFT2 */
-	[KEYMAP_INDEX(4, 1)] = KEY_CENTER,	/* KEY_CENTER */
-	[KEYMAP_INDEX(4, 2)] = KEY_DOWN,
-	[KEYMAP_INDEX(4, 3)] = KEY_BACK,	  /* FB */
-	[KEYMAP_INDEX(4, 4)] = KEY_8,
-
-	[KEYMAP_INDEX(5, 0)] = KEY_VOLUMEDOWN,
-	[KEYMAP_INDEX(5, 1)] = KEY_STAR,	  /* KEY_STAR */
-	[KEYMAP_INDEX(5, 2)] = KEY_MAIL,	  /* MESG */
-	[KEYMAP_INDEX(5, 3)] = KEY_3,
-	[KEYMAP_INDEX(5, 4)] = KEY_7,
-
-#if SCAN_FUNCTION_KEYS
-	[KEYMAP_INDEX(6, 0)] = KEY_F5,
-	[KEYMAP_INDEX(6, 1)] = KEY_F4,
-	[KEYMAP_INDEX(6, 2)] = KEY_F3,
-	[KEYMAP_INDEX(6, 3)] = KEY_F2,
-	[KEYMAP_INDEX(6, 4)] = KEY_F1
-#endif
+	[KEYMAP_INDEX(4, 0)] = KEY_MENU,		/*R-*/
+	[KEYMAP_INDEX(4, 1)] = KEY_HOME,		/*L+*/
+	[KEYMAP_INDEX(4, 2)] = KEY_BACK,		/*L-*/
+	[KEYMAP_INDEX(4, 3)] = KEY_VOLUMEUP,
+	[KEYMAP_INDEX(4, 4)] = KEY_VOLUMEDOWN,
 };
 
 static struct gpio_keypad_info halibut_keypad_info = {
diff --git a/target/msm8960/atags.c b/target/msm8960/atags.c
index d75aa2c..328a10b 100644
--- a/target/msm8960/atags.c
+++ b/target/msm8960/atags.c
@@ -27,9 +27,10 @@
  */
 
 /* Note: As of now, kernel crashes when RAM size is configured as 2GB.
- *       Configuring to 64MB for now.
+ *       Configuring to 141MB for now.
  */
-#define SIZE_64M            0x04000000
+#define SIZE_1M             (1024 * 1024)
+#define SIZE_141M           (141 * SIZE_1M)
 #define EBI1_ADDR_1026M     0x40200000
 
 unsigned* target_atag_mem(unsigned* ptr)
@@ -37,7 +38,7 @@
 	/* ATAG_MEM */
 	*ptr++ = 4;
 	*ptr++ = 0x54410002;
-	*ptr++ = SIZE_64M;
+	*ptr++ = SIZE_141M;
 	*ptr++ = EBI1_ADDR_1026M;
 
 	return ptr;