target: msm8916: Add support for SDHCI and volume keys on MSM8916.

This patch adds support for the SDHCI mode and volume keys
on MSM8916. Reboot and baseband detection support are also added
in this patch.

Change-Id: I0b9a817e350495dfd0d6eec3959c3526e671d90c
diff --git a/target/msm8916/init.c b/target/msm8916/init.c
index 285b866..2ab3bc7 100644
--- a/target/msm8916/init.c
+++ b/target/msm8916/init.c
@@ -33,30 +33,110 @@
 #include <platform.h>
 #include <uart_dm.h>
 #include <mmc.h>
-#include <spmi.h>
+#include <platform/gpio.h>
+#include <dev/keys.h>
+#include <spmi_v2.h>
+#include <pm8x41.h>
 #include <board.h>
+#include <baseband.h>
+#include <hsusb.h>
+#include <platform/gpio.h>
+#include <platform/gpio.h>
+#include <platform/irqs.h>
 
 #define PMIC_ARB_CHANNEL_NUM    0
 #define PMIC_ARB_OWNER_ID       0
+#define TLMM_VOL_UP_BTN_GPIO    107
 
-static uint32_t mmc_sdc_base[] =
+static void set_sdc_power_ctrl(void);
+
+struct mmc_device *dev;
+
+static uint32_t mmc_pwrctl_base[] =
 	{ MSM_SDC1_BASE, MSM_SDC2_BASE };
 
+static uint32_t mmc_sdhci_base[] =
+        { MSM_SDC1_SDHCI_BASE, MSM_SDC2_SDHCI_BASE };
+
+static uint32_t  mmc_sdc_pwrctl_irq[] =
+        { SDCC1_PWRCTL_IRQ, SDCC2_PWRCTL_IRQ };
+
 void target_early_init(void)
 {
 #if WITH_DEBUG_UART
-	uart_dm_init(1, 0, BLSP1_UART1_BASE);
+	uart_dm_init(2, 0, BLSP1_UART1_BASE);
 #endif
 }
-void target_mmc_caps(struct mmc_host *host)
+
+void target_sdc_init()
 {
-	host->caps.ddr_mode = 0;
-	host->caps.hs200_mode = 0;
-	host->caps.bus_width = MMC_BOOT_BUS_WIDTH_8_BIT;
-	host->caps.hs_clk_rate = MMC_CLK_50MHZ;
+	struct mmc_config_data config;
+
+	/* Set drive strength & pull ctrl values */
+	set_sdc_power_ctrl();
+
+	config.bus_width = DATA_BUS_WIDTH_8BIT;
+	config.max_clk_rate = MMC_CLK_200MHZ;
+
+	/* Try slot 1*/
+	config.slot         = 1;
+	config.sdhc_base    = mmc_sdhci_base[config.slot - 1];
+	config.pwrctl_base  = mmc_pwrctl_base[config.slot - 1];
+	config.pwr_irq      = mmc_sdc_pwrctl_irq[config.slot - 1];
+	config.hs400_support = 0;
+
+	if (!(dev = mmc_init(&config))) {
+	/* Try slot 2 */
+		config.slot         = 2;
+		config.sdhc_base    = mmc_sdhci_base[config.slot - 1];
+		config.pwrctl_base  = mmc_pwrctl_base[config.slot - 1];
+		config.pwr_irq      = mmc_sdc_pwrctl_irq[config.slot - 1];
+
+		if (!(dev = mmc_init(&config))) {
+			dprintf(CRITICAL, "mmc init failed!");
+			ASSERT(0);
+		}
+	}
 }
+
+void *target_mmc_device()
+{
+	return (void *) dev;
+}
+
+/* Return 1 if vol_up pressed */
+static int target_volume_up()
+{
+	uint8_t status = 0;
+
+	gpio_tlmm_config(TLMM_VOL_UP_BTN_GPIO, 0, GPIO_INPUT, GPIO_PULL_UP, GPIO_2MA, GPIO_ENABLE);
+
+	/* Wait for the gpio config to take effect - debounce time */
+	thread_sleep(10);
+
+	/* Get status of GPIO */
+	status = gpio_status(TLMM_VOL_UP_BTN_GPIO);
+
+	/* Active low signal. */
+	return !status;
+}
+
+/* Return 1 if vol_down pressed */
+uint32_t target_volume_down()
+{
+	/* Volume down button tied in with PMIC RESIN. */
+	return pm8x41_resin_status();
+}
+
 static void target_keystatus()
 {
+	keys_init();
+
+	if(target_volume_down())
+		keys_post_event(KEY_VOLUMEDOWN, 1);
+
+	if(target_volume_up())
+		keys_post_event(KEY_VOLUMEUP, 1);
 }
 
 void target_init(void)
@@ -69,21 +149,14 @@
 	spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
 
 	target_keystatus();
+	set_sdc_power_ctrl();
 
-	/* Trying Slot 1*/
-	slot = 1;
-	base_addr = mmc_sdc_base[slot - 1];
-	if (mmc_boot_main(slot, base_addr))
+	target_sdc_init();
+	if (partition_read_table())
 	{
-
-	/* Trying Slot 2 next */
-	slot = 2;
-	base_addr = mmc_sdc_base[slot - 1];
-	if (mmc_boot_main(slot, base_addr)) {
-		dprintf(CRITICAL, "mmc init failed!");
+		dprintf(CRITICAL, "Error reading the partition table info\n");
 		ASSERT(0);
 	}
-	}
 }
 
 void target_serialno(unsigned char *buf)
@@ -97,4 +170,125 @@
 
 unsigned board_machtype(void)
 {
+	return LINUX_MACHTYPE_UNKNOWN;
+}
+
+unsigned check_reboot_mode(void)
+{
+	uint32_t restart_reason = 0;
+
+	/* Read reboot reason and scrub it */
+	restart_reason = readl(RESTART_REASON_ADDR);
+	writel(0x00, RESTART_REASON_ADDR);
+
+	return restart_reason;
+}
+
+void reboot_device(unsigned reboot_reason)
+{
+	writel(reboot_reason, RESTART_REASON_ADDR);
+
+	/* Configure PMIC for warm reset */
+	pm8x41_reset_configure(PON_PSHOLD_WARM_RESET);
+
+	/* Drop PS_HOLD for MSM */
+	writel(0x00, MPM2_MPM_PS_HOLD);
+
+	mdelay(5000);
+
+	dprintf(CRITICAL, "Rebooting failed\n");
+}
+
+/* Detect the target type */
+void target_detect(struct board_data *board)
+{
+	/*
+	* already fill the board->target on board.c
+	*/
+}
+
+void target_baseband_detect(struct board_data *board)
+{
+	uint32_t platform;
+
+	platform = board->platform;
+	switch(platform)
+	{
+	case MSM8916:
+		board->baseband = BASEBAND_MSM;
+	break;
+	default:
+		dprintf(CRITICAL, "Platform type: %u is not supported\n", platform);
+	ASSERT(0);
+	};
+}
+
+unsigned target_baseband()
+{
+	return board_baseband();
+}
+
+int emmc_recovery_init(void)
+{
+	return _emmc_recovery_init();
+}
+
+static void set_sdc_power_ctrl()
+{
+	/* 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_CMD_HDRV_CTL_OFF,  TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
+		{ SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_6MA, TLMM_HDRV_MASK },
+	};
+
+	/* Pull configs for sdc pins */
+	struct tlmm_cfgs sdc1_pull_cfg[] =
+	{
+		{ SDC1_CLK_PULL_CTL_OFF,  TLMM_NO_PULL, TLMM_PULL_MASK },
+		{ SDC1_CMD_PULL_CTL_OFF,  TLMM_PULL_UP, TLMM_PULL_MASK },
+		{ SDC1_DATA_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK },
+	};
+
+	/* Set the drive strength & pull control values */
+	tlmm_set_hdrive_ctrl(sdc1_hdrv_cfg, ARRAY_SIZE(sdc1_hdrv_cfg));
+	tlmm_set_pull_ctrl(sdc1_pull_cfg, ARRAY_SIZE(sdc1_pull_cfg));
+}
+
+void target_usb_init(void)
+{
+	uint32_t val;
+
+	/* Select and enable external configuration with USB PHY */
+	ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_SET);
+
+	/* Enable sess_vld */
+	val = readl(USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
+	writel(val, USB_GENCONFIG_2);
+
+	/* Enable external vbus configuration in the LINK */
+	val = readl(USB_USBCMD);
+	val |= SESS_VLD_CTRL;
+	writel(val, USB_USBCMD);
+}
+
+void target_usb_stop(void)
+{
+	/* Disable VBUS mimicing in the controller. */
+	ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_CLEAR);
+}
+
+
+void target_uninit(void)
+{
+	mmc_put_card_to_sleep(dev);
+	sdhci_mode_disable(&dev->host);
+}
+
+/* Do any target specific intialization needed before entering fastboot mode */
+void target_fastboot_init(void)
+{
+	/* Set the BOOT_DONE flag in PM8916 */
+	pm8x41_set_boot_done();
 }
diff --git a/target/msm8916/meminfo.c b/target/msm8916/meminfo.c
index 708cde3..9d76bf6 100644
--- a/target/msm8916/meminfo.c
+++ b/target/msm8916/meminfo.c
@@ -35,37 +35,42 @@
 #include <platform/iomap.h>
 #include <dev_tree.h>
 
-/* Funtion to add the ram partition entries into device tree.
- * The function assumes that all the entire fixed memory regions should
- * be listed in the first bank of the passed in ddr regions.
- */
 uint32_t target_dev_tree_mem(void *fdt, uint32_t memory_node_offset)
 {
-	struct smem_ram_ptable ram_ptable;
-	uint32_t i;
+	ram_partition ptn_entry;
+	unsigned int index;
 	int ret = 0;
+	uint32_t len = 0;
 
 	/* Make sure RAM partition table is initialized */
-	ASSERT(smem_ram_ptable_init(&ram_ptable));
+	ASSERT(smem_ram_ptable_init_v1());
+
+	len = smem_get_ram_ptable_len();
 
 	/* Calculating the size of the mem_info_ptr */
-	for (i = 0 ; i < ram_ptable.len; i++)
+	for (index = 0 ; index < len; index++)
 	{
-		if ((ram_ptable.parts[i].category == SDRAM) &&
-			(ram_ptable.parts[i].type == SYS_MEMORY)) {
+		smem_get_ram_ptable_entry(&ptn_entry, index);
+
+		if((ptn_entry.category == SDRAM) &&
+			(ptn_entry.type == SYS_MEMORY))
+		{
 
 			/* Pass along all other usable memory regions to Linux */
 			ret = dev_tree_add_mem_info(fdt,
-					memory_node_offset,
-					ram_ptable.parts[i].start,
-					ram_ptable.parts[i].size);
-			if (ret) {
+							memory_node_offset,
+							ptn_entry.start,
+							ptn_entry.size);
+
+			if (ret)
+			{
 				dprintf(CRITICAL, "Failed to add secondary banks memory addresses\n");
 				goto target_dev_tree_mem_err;
 			}
 		}
 	}
 target_dev_tree_mem_err:
+
 	return ret;
 }