Merge "platform: msm8916: Add Chip info for 8x3x and modify function declaration."
diff --git a/platform/msm_shared/include/mmc_sdhci.h b/platform/msm_shared/include/mmc_sdhci.h
index 7ea664e..d7c19ce 100644
--- a/platform/msm_shared/include/mmc_sdhci.h
+++ b/platform/msm_shared/include/mmc_sdhci.h
@@ -89,6 +89,7 @@
 #define MMC_EXT_MMC_BUS_WIDTH                     183
 #define MMC_EXT_MMC_HS_TIMING                     185
 #define MMC_DEVICE_TYPE                           196
+#define MMC_EXT_MMC_DRV_STRENGTH                  197
 #define MMC_EXT_HC_WP_GRP_SIZE                    221
 #define MMC_SEC_COUNT4                            215
 #define MMC_SEC_COUNT3                            214
@@ -330,4 +331,6 @@
 uint32_t mmc_get_wp_status(struct mmc_device *dev, uint32_t addr, uint8_t *wp_status);
 /* API: Put the mmc card in sleep mode */
 void mmc_put_card_to_sleep(struct mmc_device *dev);
+/* API: Change the driver type of the card */
+bool mmc_set_drv_type(struct sdhci_host *host, struct mmc_card *card, uint8_t drv_type);
 #endif
diff --git a/platform/msm_shared/include/sdhci_msm.h b/platform/msm_shared/include/sdhci_msm.h
index 180f23a..ea8a1a3 100644
--- a/platform/msm_shared/include/sdhci_msm.h
+++ b/platform/msm_shared/include/sdhci_msm.h
@@ -118,6 +118,6 @@
 };
 
 void sdhci_msm_init(struct sdhci_host *host, struct sdhci_msm_data *data);
-uint32_t sdhci_msm_execute_tuning(struct sdhci_host *host, uint32_t bus_width);
+uint32_t sdhci_msm_execute_tuning(struct sdhci_host *host, struct mmc_card * card, uint32_t bus_width);
 void sdhci_mode_disable(struct sdhci_host *host);
 #endif
diff --git a/platform/msm_shared/mmc_sdhci.c b/platform/msm_shared/mmc_sdhci.c
index c9083db..8d607d9 100644
--- a/platform/msm_shared/mmc_sdhci.c
+++ b/platform/msm_shared/mmc_sdhci.c
@@ -739,7 +739,7 @@
 	}
 
 	if (MMC_CARD_STATUS(mmc_status) != MMC_TRAN_STATE) {
-		dprintf(CRITICAL, "Switch cmd failed. Card not in tran state\n");
+		dprintf(CRITICAL, "Switch cmd failed. Card not in tran state %x\n", mmc_status);
 		mmc_ret = 1;
 	}
 
@@ -751,6 +751,20 @@
 	return mmc_ret;
 }
 
+bool mmc_set_drv_type(struct sdhci_host *host, struct mmc_card *card, uint8_t drv_type)
+{
+	uint32_t ret = 0;
+	bool drv_type_changed = false;
+
+	uint32_t value = ((drv_type << 4) | MMC_HS200_TIMING);
+
+	if (card->ext_csd[MMC_EXT_MMC_DRV_STRENGTH] & (1 << drv_type))
+		ret = mmc_switch_cmd(host, card, MMC_ACCESS_WRITE, MMC_EXT_MMC_HS_TIMING, value);
+	if (!ret)
+		drv_type_changed = true;
+
+	return drv_type_changed;
+}
 /*
  * Function: mmc set bus width
  * Arg     : Host, card structure & width
@@ -871,7 +885,7 @@
 	}
 
 	/* Execute Tuning for hs200 mode */
-	if ((mmc_ret = sdhci_msm_execute_tuning(host, width)))
+	if ((mmc_ret = sdhci_msm_execute_tuning(host, card, width)))
 		dprintf(CRITICAL, "Tuning for hs200 failed\n");
 
 	DBG("\n Enabling HS200 Mode Done\n");
@@ -1022,7 +1036,7 @@
 	sdhci_msm_set_mci_clk(host);
 
 	/* 7. Execute Tuning for hs400 mode */
-	if ((mmc_ret = sdhci_msm_execute_tuning(host, width)))
+	if ((mmc_ret = sdhci_msm_execute_tuning(host, card, width)))
 		dprintf(CRITICAL, "Tuning for hs400 failed\n");
 
 	DBG("\n Enabling HS400 Mode Done\n");
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index c4e4eae..83724c6 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -355,7 +355,8 @@
 			$(LOCAL_DIR)/clock_lib2.o \
 			$(LOCAL_DIR)/gpio.o \
 			$(LOCAL_DIR)/scm.o \
-			$(LOCAL_DIR)/qmp_usb30_phy.o
+			$(LOCAL_DIR)/qmp_usb30_phy.o \
+			$(LOCAL_DIR)/qusb2_phy.o
 endif
 
 ifeq ($(PLATFORM),fsm9900)
@@ -410,7 +411,8 @@
 			$(LOCAL_DIR)/image_verify.o \
 			$(LOCAL_DIR)/crypto_hash.o \
 			$(LOCAL_DIR)/crypto5_eng.o \
-			$(LOCAL_DIR)/crypto5_wrapper.o
+			$(LOCAL_DIR)/crypto5_wrapper.o \
+			$(LOCAL_DIR)/qusb2_phy.o
 endif
 
 ifeq ($(ENABLE_BOOT_CONFIG_SUPPORT), 1)
diff --git a/platform/msm_shared/sdhci_msm.c b/platform/msm_shared/sdhci_msm.c
index 81b6538..5c1a09e 100644
--- a/platform/msm_shared/sdhci_msm.c
+++ b/platform/msm_shared/sdhci_msm.c
@@ -40,6 +40,9 @@
 #include <sdhci.h>
 #include <sdhci_msm.h>
 
+
+#define MX_DRV_SUPPORTED_HS200 3
+
 /* Known data stored in the card & read during tuning
  * process. 64 bytes for 4bit bus width & 128 bytes
  * of data for 8 bit bus width.
@@ -551,7 +554,7 @@
  * Return  : 0 on Success, 1 on Failure
  * Flow:   : Execute Tuning sequence for HS200
  */
-uint32_t sdhci_msm_execute_tuning(struct sdhci_host *host, uint32_t bus_width)
+uint32_t sdhci_msm_execute_tuning(struct sdhci_host *host, struct mmc_card *card, uint32_t bus_width)
 {
 	uint32_t *tuning_block;
 	uint32_t *tuning_data;
@@ -559,6 +562,8 @@
 	uint32_t size;
 	uint32_t phase = 0;
 	uint32_t tuned_phase_cnt = 0;
+	uint8_t drv_type = 0;
+	bool drv_type_changed = false;
 	int ret = 0;
 	int i;
 	struct sdhci_msm_data *msm_host;
@@ -599,6 +604,10 @@
 			goto free;
 	}
 
+retry_tuning:
+	tuned_phase_cnt = 0;
+	phase = 0;
+
 	while (phase < MAX_PHASES)
 	{
 		struct mmc_command cmd = {0};
@@ -627,6 +636,25 @@
 		phase++;
 	}
 
+	/*
+	 * Check if all the tuning phases passed */
+	if (tuned_phase_cnt == MAX_PHASES)
+	{
+		/* Change the driver type & rerun tuning */
+		while(++drv_type < MX_DRV_SUPPORTED_HS200)
+		{
+			drv_type_changed = mmc_set_drv_type(host, card, drv_type);
+			if (drv_type_changed)
+			{
+				goto retry_tuning;
+			}
+		}
+	}
+
+	/* Restore the driver strength to default value */
+	if (drv_type_changed)
+		mmc_set_drv_type(host, card, 0);
+
 	/* Find the appropriate tuned phase */
 	if (tuned_phase_cnt)
 	{
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index 12a777c..e058db3 100644
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -357,6 +357,7 @@
 	MSM8928  = 224,
 	MSM8510  = 225,
 	MSM8512  = 226,
+	MSM8936  = 233,
 	MSMZIRC  = 234,
 	MSM8939  = 239,
 	APQ8036  = 240,
diff --git a/platform/msmzirc/include/platform/iomap.h b/platform/msmzirc/include/platform/iomap.h
index a35ed30..1add071 100644
--- a/platform/msmzirc/include/platform/iomap.h
+++ b/platform/msmzirc/include/platform/iomap.h
@@ -166,6 +166,11 @@
 /* USB 3.0 phy */
 #define USB3_PHY_BCR                (CLK_CTL_BASE + 0x0005E034)
 
+/* QUSB2 PHY */
+#define QUSB2_PHY_BASE              0x00079000
+#define QUSB2PHY_PORT_POWERDOWN     (QUSB2_PHY_BASE + 0x000000B4)
+#define GCC_QUSB2_PHY_BCR           (CLK_CTL_BASE + 0x00041028)
+
 /* SS QMP (Qulacomm Multi Protocol) */
 #define QMP_PHY_BASE                0x78000
 
diff --git a/target/fsm9900/init.c b/target/fsm9900/init.c
index 850359d..43100e1 100644
--- a/target/fsm9900/init.c
+++ b/target/fsm9900/init.c
@@ -165,7 +165,7 @@
 	struct mmc_config_data config = {0};
 
 	config.bus_width = DATA_BUS_WIDTH_8BIT;
-	config.max_clk_rate = MMC_CLK_200MHZ;
+	config.max_clk_rate = MMC_CLK_96MHZ;
 
 	/* Trying Slot 1*/
 	config.slot = 1;
@@ -478,7 +478,7 @@
 	/* Drive strength configs for sdc pins */
 	struct tlmm_cfgs sdc1_hdrv_cfg[] =
 	{
-		{ SDC1_CLK_HDRV_CTL_OFF,  TLMM_CUR_VAL_16MA, TLMM_HDRV_MASK },
+		{ SDC1_CLK_HDRV_CTL_OFF,  TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
 		{ SDC1_CMD_HDRV_CTL_OFF,  TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
 		{ SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
 	};
diff --git a/target/mdm9635/init.c b/target/mdm9635/init.c
index 5b2e00c..9409e81 100644
--- a/target/mdm9635/init.c
+++ b/target/mdm9635/init.c
@@ -291,15 +291,25 @@
 	}
 
 	/*
-	 * check if cmdline contains "root=" at the beginning of buffer or
-	 * " root=" in the middle of buffer.
+	 * check if cmdline contains "root="/"ubi.mtd" at the beginning of buffer or
+	 * " root="/"ubi.mtd" in the middle of buffer.
 	 */
-	if (((!strncmp(cmdline, "root=", strlen("root="))) ||
-	     (strstr(cmdline, " root="))))
-		dprintf(DEBUG, "DEBUG: cmdline has root=\n");
-	else
-		snprintf(buf, buflen, " root=/dev/mtdblock%d",
-			 system_ptn_index);
+
+	if (strstr(cmdline, "rootfstype=yaffs2")) {
+		if (((!strncmp(cmdline, "root=", strlen("root="))) ||
+			(strstr(cmdline, " root="))))
+			dprintf(DEBUG, "DEBUG: cmdline has root=\n");
+		else
+			snprintf(buf, buflen, " root=/dev/mtdblock%d",
+					system_ptn_index);
+	} else if (strstr(cmdline, "rootfstype=ubifs")){
+		if (((!strncmp(cmdline, "ubi.mtd=", strlen("ubi.mtd="))) ||
+			(strstr(cmdline, " ubi.mtd="))))
+			dprintf(DEBUG, "DEBUG: cmdline has ubi.mtd=\n");
+		else
+			snprintf(buf, buflen, " ubi.mtd=%d",
+				system_ptn_index);
+	}
 
 	return 0;
 }
diff --git a/target/msm8226/include/target/display.h b/target/msm8226/include/target/display.h
index 5fd54f4..8e87a7a 100755
--- a/target/msm8226/include/target/display.h
+++ b/target/msm8226/include/target/display.h
@@ -108,6 +108,8 @@
 #define MIPI_VSYNC_BACK_PORCH_LINES  3
 #define MIPI_VSYNC_FRONT_PORCH_LINES 9
 
+#define PWM_BL_LPG_CHAN_ID           8
+
 enum target_subtype {
 	HW_PLATFORM_SUBTYPE_720P = 0,
 	HW_PLATFORM_SUBTYPE_SKUAA = 1,
diff --git a/target/msm8226/target_display.c b/target/msm8226/target_display.c
index b26d3e6..5fbfa86 100755
--- a/target/msm8226/target_display.c
+++ b/target/msm8226/target_display.c
@@ -198,8 +198,53 @@
 	return pll_locked;
 }
 
+static int msm8226_wled_backlight_ctrl(uint8_t enable)
+{
+	if (enable) {
+		pm8x41_wled_config(&wled_ctrl);
+		pm8x41_wled_sink_control(enable);
+		pm8x41_wled_iled_sync_control(enable);
+		pm8x41_wled_led_mod_enable(enable);
+	}
+	pm8x41_wled_enable(enable);
+
+	return NO_ERROR;
+}
+
+static int msm8226_pwm_backlight_ctrl(int gpio_num, int lpg_chan, int enable)
+{
+	struct pm8x41_gpio gpio_param = {
+		.direction = PM_GPIO_DIR_OUT,
+		.function = PM_GPIO_FUNC_2,
+		.vin_sel = 2,   /* VIN_2 */
+		.pull = PM_GPIO_PULL_UP_1_5 | PM_GPIO_PULLDOWN_10,
+		.output_buffer = PM_GPIO_OUT_CMOS,
+		.out_strength = PM_GPIO_OUT_DRIVE_HIGH,
+	};
+
+	dprintf(SPEW, "%s: gpio=%d lpg=%d enable=%d\n", __func__,
+				gpio_num, lpg_chan, enable);
+
+	if (enable) {
+		pm8x41_gpio_config(gpio_num, &gpio_param);
+		pm8x41_lpg_write(lpg_chan, 0x41, 0x33); /* LPG_PWM_SIZE_CLK, */
+		pm8x41_lpg_write(lpg_chan, 0x42, 0x01); /* LPG_PWM_FREQ_PREDIV */
+		pm8x41_lpg_write(lpg_chan, 0x43, 0x20); /* LPG_PWM_TYPE_CONFIG */
+		pm8x41_lpg_write(lpg_chan, 0x44, 0xb2); /* LPG_VALUE_LSB */
+		pm8x41_lpg_write(lpg_chan, 0x45, 0x01);  /* LPG_VALUE_MSB */
+		pm8x41_lpg_write(lpg_chan, 0x46, 0xe4); /* LPG_ENABLE_CONTROL */
+	} else {
+		pm8x41_lpg_write(lpg_chan, 0x46, 0x00);
+	}
+
+	return NO_ERROR;
+}
+
+
 int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
 {
+	uint32_t ret = NO_ERROR;
+
 	dprintf(SPEW, "target_backlight_ctrl\n");
 
 	if (!bl) {
@@ -207,22 +252,22 @@
 		return ERR_INVALID_ARGS;
 	}
 
-	if (bl->bl_interface_type != BL_WLED) {
-		dprintf(CRITICAL, "backlight type:%d not supported\n",
+	switch (bl->bl_interface_type) {
+		case BL_WLED:
+			ret = msm8226_wled_backlight_ctrl(enable);
+			break;
+		case BL_PWM:
+			ret = msm8226_pwm_backlight_ctrl(pwm_gpio.pin_id,
+							PWM_BL_LPG_CHAN_ID,
+							enable);
+			break;
+		default:
+			dprintf(CRITICAL, "backlight type:%d not supported\n",
 							bl->bl_interface_type);
-		return ERR_NOT_SUPPORTED;
+			return ERR_NOT_SUPPORTED;
 	}
 
-	if (enable) {
-		pm8x41_wled_config(&wled_ctrl);
-		pm8x41_wled_sink_control(enable);
-		pm8x41_wled_iled_sync_control(enable);
-		pm8x41_wled_led_mod_enable(enable);
-	}
-
-	pm8x41_wled_enable(enable);
-
-	return 0;
+	return ret;
 }
 
 static void dsi_pll_enable_seq(uint32_t pll_base)
diff --git a/target/msm8994/init.c b/target/msm8994/init.c
index 19ca81b..caa5e49 100644
--- a/target/msm8994/init.c
+++ b/target/msm8994/init.c
@@ -54,6 +54,7 @@
 #include <ufs.h>
 #include <boot_device.h>
 #include <qmp_phy.h>
+#include <qusb2_phy.h>
 
 #define CE_INSTANCE             3
 #define CE_EE                   1
@@ -156,19 +157,7 @@
 		/* Select the QUSB2 PHY */
 		writel(0x1, USB2_PHY_SEL);
 
-		/* Block Reset */
-		val = readl(GCC_QUSB2_PHY_BCR) | BIT(0);
-		writel(val, GCC_QUSB2_PHY_BCR);
-		udelay(10);
-		writel(val & ~BIT(0), GCC_QUSB2_PHY_BCR);
-
-		/* Deassert POWERDOWN by clearing bit 0 to enable the PHY */
-		val = readl(QUSB2PHY_PORT_POWERDOWN);
-		writel(val & ~BIT(0), QUSB2PHY_PORT_POWERDOWN);
-		udelay(10);
-
-		/* set CLAMP_N_EN and FREEZIO_N */
-		writel(0x22, QUSB2PHY_PORT_POWERDOWN);
+		qusb2_phy_reset();
 	}
 
 	/* Select and enable external configuration with USB PHY */
diff --git a/target/msmzirc/init.c b/target/msmzirc/init.c
index 23ee685..a94ef0d 100644
--- a/target/msmzirc/init.c
+++ b/target/msmzirc/init.c
@@ -45,6 +45,7 @@
 #include <platform/gpio.h>
 #include <platform/clock.h>
 #include <qmp_phy.h>
+#include <qusb2_phy.h>
 
 extern void smem_ptable_init(void);
 extern void smem_add_modem_partitions(struct ptable *flash_ptable);
@@ -316,6 +317,12 @@
 	}
 }
 
+void target_usb_phy_reset(void)
+{
+	qusb2_phy_reset();
+	usb30_qmp_phy_reset();
+}
+
 target_usb_iface_t* target_usb30_init()
 {
 	target_usb_iface_t *t_usb_iface;
@@ -325,7 +332,7 @@
 
 	t_usb_iface->mux_config = NULL;
 	t_usb_iface->phy_init   = usb30_qmp_phy_init;
-	t_usb_iface->phy_reset  = usb30_qmp_phy_reset;
+	t_usb_iface->phy_reset  = target_usb_phy_reset;
 	t_usb_iface->clock_init = clock_usb30_init;
 	t_usb_iface->vbus_override = 1;