platform: msm_shared: Add property for io switch

For some platforms the SDC controller is shared between
emmc and sd card. In such case the voltage switch should happen
to 1.8 for emmc card functionality. Add target specific property
to enable the IO_PAD power switch.

Change-Id: Ia5585fff31359f8bd5c7f3b9fb8e909a7e673a90
diff --git a/platform/msm_shared/include/mmc_sdhci.h b/platform/msm_shared/include/mmc_sdhci.h
index d7c19ce..0098c0e 100644
--- a/platform/msm_shared/include/mmc_sdhci.h
+++ b/platform/msm_shared/include/mmc_sdhci.h
@@ -305,6 +305,7 @@
 	uint16_t bus_width;    /* Bus width used */
 	uint32_t max_clk_rate; /* Max clock rate supported */
 	uint8_t hs400_support; /* SDHC HS400 mode supported or not */
+	uint8_t use_io_switch; /* IO pad switch flag for shared sdc controller */
 };
 
 /* mmc device structure */
diff --git a/platform/msm_shared/include/sdhci_msm.h b/platform/msm_shared/include/sdhci_msm.h
index 79ae142..4682694 100644
--- a/platform/msm_shared/include/sdhci_msm.h
+++ b/platform/msm_shared/include/sdhci_msm.h
@@ -118,6 +118,9 @@
 #define SDHCI_DLL_TIMEOUT                         50
 #define CDC_STATUS_TIMEOUT                        50
 
+#define HC_IO_PAD_PWR_SWITCH_EN                   BIT(15)
+#define HC_IO_PAD_PWR_SWITCH                      BIT(16)
+
 struct sdhci_msm_data
 {
 	uint32_t pwrctl_base;
@@ -126,6 +129,7 @@
 	uint8_t calibration_done;
 	uint8_t saved_phase;
 	uint8_t slot;
+	uint8_t use_io_switch;
 	event_t*  sdhc_event;
 };
 
diff --git a/platform/msm_shared/mmc_sdhci.c b/platform/msm_shared/mmc_sdhci.c
index a31cf87..411f22c 100644
--- a/platform/msm_shared/mmc_sdhci.c
+++ b/platform/msm_shared/mmc_sdhci.c
@@ -1091,6 +1091,7 @@
 	data->pwrctl_base = cfg->pwrctl_base;
 	data->pwr_irq = cfg->pwr_irq;
 	data->slot = cfg->slot;
+	data->use_io_switch = cfg->use_io_switch;
 
 	host->msm_host = data;
 
diff --git a/platform/msm_shared/sdhci_msm.c b/platform/msm_shared/sdhci_msm.c
index a54752b..d72d90d 100644
--- a/platform/msm_shared/sdhci_msm.c
+++ b/platform/msm_shared/sdhci_msm.c
@@ -142,6 +142,8 @@
  */
 void sdhci_msm_init(struct sdhci_host *host, struct sdhci_msm_data *config)
 {
+	uint32_t io_switch;
+
 	/* Disable HC mode */
 	RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), SDHCI_HC_START_BIT, SDHCI_HC_WIDTH, 0);
 
@@ -163,6 +165,19 @@
 	sdhci_reset(host, SDHCI_SOFT_RESET);
 
 	/*
+	 * Some platforms have same SDC instance shared between emmc & sd card.
+	 * For such platforms the emmc IO voltage has to be switched from 3.3 to
+	 * 1.8 for the contoller to work with emmc.
+	 */
+
+	if(config->use_io_switch)
+	{
+		io_switch = REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC);
+		io_switch |= HC_IO_PAD_PWR_SWITCH | HC_IO_PAD_PWR_SWITCH_EN;
+		REG_WRITE32(host, io_switch, SDCC_VENDOR_SPECIFIC_FUNC);
+	}
+
+	/*
 	 * CORE_SW_RST may trigger power irq if previous status of PWRCTL
 	 * was either BUS_ON or IO_HIGH. So before we enable the power irq
 	 * interrupt in GIC (by registering the interrupt handler), we need to