Merge "dev: pm8x41: Fix WLED macro values"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 0115289..71c6128 100755
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -1543,17 +1543,24 @@
 {
 	BUF_DMA_ALIGN(out, DEFAULT_ERASE_SIZE);
 	unsigned long long ptn = 0;
-	unsigned long long size;
+	unsigned long long size = 0;
 	int index = INVALID_PTN;
 
 	index = partition_get_index(arg);
 	ptn = partition_get_offset(index);
+	size = partition_get_size(index);
 
 	if(ptn == 0) {
 		fastboot_fail("Partition table doesn't exist\n");
 		return;
 	}
 
+#if MMC_SDHCI_SUPPORT
+	if (mmc_erase_card(ptn, size)) {
+		fastboot_fail("failed to erase partition\n");
+		return;
+	}
+#else
 	size = partition_get_size(index);
 	if (size > DEFAULT_ERASE_SIZE)
 		size = DEFAULT_ERASE_SIZE;
@@ -1564,6 +1571,7 @@
 		fastboot_fail("failed to erase partition");
 		return;
 	}
+#endif
 	fastboot_okay("");
 }
 
diff --git a/dev/pmic/pm8x41/include/pm8x41_wled.h b/dev/pmic/pm8x41/include/pm8x41_wled.h
index de1bf4a..389d470 100644
--- a/dev/pmic/pm8x41/include/pm8x41_wled.h
+++ b/dev/pmic/pm8x41/include/pm8x41_wled.h
@@ -53,9 +53,9 @@
 #define PM_WLED_LED2_SINK_MASK       BIT(6)
 #define PM_WLED_LED3_SINK_MASK       BIT(7)
 
-#define PM_WLED_LED1_ILED_SYNC_MASK  BIT(2)
+#define PM_WLED_LED1_ILED_SYNC_MASK  BIT(0)
 #define PM_WLED_LED2_ILED_SYNC_MASK  BIT(1)
-#define PM_WLED_LED3_ILED_SYNC_MASK  BIT(0)
+#define PM_WLED_LED3_ILED_SYNC_MASK  BIT(2)
 
 #define PM_WLED_ENABLE_MODULE_MASK   BIT(7)
 #define DEFAULT_SLAVE_ID             0x1
diff --git a/platform/msm_shared/mmc_wrapper.c b/platform/msm_shared/mmc_wrapper.c
index 2a89af4..bfbdf95 100644
--- a/platform/msm_shared/mmc_wrapper.c
+++ b/platform/msm_shared/mmc_wrapper.c
@@ -32,6 +32,7 @@
 #include <mmc_wrapper.h>
 #include <sdhci.h>
 #include <target.h>
+#include <string.h>
 
 /*
  * Function: get mmc card
@@ -141,6 +142,83 @@
 }
 
 /*
+ * Function: mmc get erase unit size
+ * Arg     : None
+ * Return  : Returns the erase unit size of the storage
+ * Flow    : Get the erase unit size from the card
+ */
+
+uint32_t mmc_get_eraseunit_size()
+{
+	uint32_t erase_unit_sz = 0;
+	struct mmc_device *dev;
+	struct mmc_card *card;
+
+	dev = target_mmc_device();
+	card = &dev->card;
+	/*
+	 * Calculate the erase unit size,
+	 * 1. Based on emmc 4.5 spec for emmc card
+	 * 2. Use SD Card Status info for SD cards
+	 */
+	if (MMC_CARD_MMC(card))
+	{
+		/*
+		 * Calculate the erase unit size as per the emmc specification v4.5
+		 */
+		if (dev->card.ext_csd[MMC_ERASE_GRP_DEF])
+			erase_unit_sz = (MMC_HC_ERASE_MULT * dev->card.ext_csd[MMC_HC_ERASE_GRP_SIZE]) / MMC_BLK_SZ;
+		else
+			erase_unit_sz = (dev->card.csd.erase_grp_size + 1) * (dev->card.csd.erase_grp_mult + 1);
+	}
+	else
+		erase_unit_sz = dev->card.ssr.au_size * dev->card.ssr.num_aus;
+
+	return erase_unit_sz;
+}
+
+/*
+ * Function: Zero out blk_len blocks at the blk_addr by writing zeros. The
+ *           function can be used when we want to erase the blocks not
+ *           aligned with the mmc erase group.
+ * Arg     : Block address & length
+ * Return  : Returns 0
+ * Flow    : Erase the card from specified addr
+ */
+
+static uint32_t mmc_zero_out(struct mmc_device* dev, uint32_t blk_addr, uint32_t num_blks)
+{
+	uint32_t *out;
+	uint32_t block_size;
+	int i;
+
+	dprintf(INFO, "erasing 0x%x:0x%x\n", blk_addr, num_blks);
+	block_size = mmc_get_device_blocksize();
+
+	/* Assume there are at least block_size bytes available in the heap */
+	out = memalign(CACHE_LINE, ROUNDUP(block_size, CACHE_LINE));
+
+	if (!out)
+	{
+		dprintf(CRITICAL, "Error allocating memory\n");
+		return 1;
+	}
+	memset((void *)out, 0, ROUNDUP(block_size, CACHE_LINE));
+
+	for (i = 0; i < num_blks; i++)
+	{
+		if (mmc_sdhci_write(dev, out, blk_addr + i, 1))
+		{
+			dprintf(CRITICAL, "failed to erase the partition: %x\n", blk_addr);
+			free(out);
+			return 1;
+		}
+	}
+	free(out);
+	return 0;
+}
+
+/*
  * Function: mmc erase card
  * Arg     : Block address & length
  * Return  : Returns 0
@@ -149,17 +227,69 @@
 uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
 {
 	struct mmc_device *dev;
+	uint32_t block_size;
+	uint32_t unaligned_blks;
+	uint32_t head_unit;
+	uint32_t tail_unit;
+	uint32_t erase_unit_sz;
+	uint32_t blk_addr;
+	uint32_t blk_count;
+	uint64_t blks_to_erase;
 
-	dev = target_mmc_device();
+	block_size = mmc_get_device_blocksize();
+	erase_unit_sz = mmc_get_eraseunit_size();
+	dprintf(SPEW, "erase_unit_sz:0x%x\n", erase_unit_sz);
 
 	ASSERT(!(addr % MMC_BLK_SZ));
 	ASSERT(!(len % MMC_BLK_SZ));
 
-	if (mmc_sdhci_erase(dev, (addr / MMC_BLK_SZ), len))
+	blk_addr = addr / block_size;
+	blk_count = len / block_size;
+
+	dev = target_mmc_device();
+
+	dprintf(INFO, "Erasing card: 0x%x:0x%x\n", blk_addr, blk_count);
+
+	head_unit = blk_addr / erase_unit_sz;
+	tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
+
+	if (tail_unit - head_unit <= 1)
+	{
+		dprintf(INFO, "SDHCI unit erase not required\n");
+		return mmc_zero_out(dev, blk_addr, blk_count);
+	}
+
+	unaligned_blks = erase_unit_sz - (blk_addr % erase_unit_sz);
+
+	if (unaligned_blks < erase_unit_sz)
+	{
+		dprintf(SPEW, "Handling unaligned head blocks\n");
+		if (mmc_zero_out(dev, blk_addr, unaligned_blks))
+			return 1;
+
+		blk_addr += unaligned_blks;
+		blk_count -= unaligned_blks;
+	}
+
+	unaligned_blks = blk_count % erase_unit_sz;
+	blks_to_erase = blk_count - unaligned_blks;
+
+	dprintf(SPEW, "Performing SDHCI erase: 0x%x:0x%x\n", blk_addr, blks_to_erase);
+	if (mmc_sdhci_erase((struct mmc_device *)dev, blk_addr, blks_to_erase * block_size))
 	{
 		dprintf(CRITICAL, "MMC erase failed\n");
 		return 1;
 	}
+
+	blk_addr += blks_to_erase;
+
+	if (unaligned_blks)
+	{
+		dprintf(SPEW, "Handling unaligned tail blocks\n");
+		if (mmc_zero_out(dev, blk_addr, unaligned_blks))
+			return 1;
+	}
+
 	return 0;
 }
 
diff --git a/target/msm8226/oem_panel.c b/target/msm8226/oem_panel.c
index 56dcc06..5dcfdbf 100755
--- a/target/msm8226/oem_panel.c
+++ b/target/msm8226/oem_panel.c
@@ -255,6 +255,7 @@
 					= NT35596_1080P_VIDEO_ON_COMMAND;
 		memcpy(phy_db->timing,
 				nt35596_1080p_video_timings, TIMING_SIZE);
+		break;
 	case JDI_1080P_VIDEO_PANEL:
 		panelstruct->paneldata    = &jdi_1080p_video_panel_data;
 		panelstruct->paneldata->panel_with_enable_gpio = 1;