platform: fsm9010: Bring up on ASIC

- Enable SDHC controller at 200 MHz
- Enable UART
- Enable USB3 with HS PHY
- Fixed memory map

Change-Id: If655edbc2e7a6c1e6f55c1ac8299046621e47d7e
diff --git a/target/fsm9010/init.c b/target/fsm9010/init.c
index 8f3da01..7e47d47 100644
--- a/target/fsm9010/init.c
+++ b/target/fsm9010/init.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -50,6 +50,8 @@
 #include <platform/gpio.h>
 #include <platform/timer.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sdhci_msm.h>
 
 extern  bool target_use_signed_kernel(void);
 static void set_sdc_power_ctrl();
@@ -91,7 +93,7 @@
 void target_early_init(void)
 {
 #if WITH_DEBUG_UART
-	uart_dm_init(2, 0, BLSP1_UART2_BASE);
+	uart_dm_init(3, 0, BLSP1_UART3_BASE);
 #endif
 }
 
@@ -155,31 +157,39 @@
 }
 
 #if MMC_SDHCI_SUPPORT
+
 static void target_mmc_sdhci_init()
 {
-	struct mmc_config_data config = {0};
+	static uint32_t mmc_clks[] = {
+		MMC_CLK_200MHZ, MMC_CLK_96MHZ, MMC_CLK_50MHZ };
 
+	struct mmc_config_data config;
+	unsigned int i;
+
+	memset(&config, 0, sizeof config);
 	config.bus_width = DATA_BUS_WIDTH_8BIT;
-	config.max_clk_rate = MMC_CLK_96MHZ;
 
 	/* Trying Slot 1*/
 	config.slot = 1;
 	config.sdhc_base = mmc_sdhci_base[config.slot - 1];
 	config.pwrctl_base = mmc_sdc_base[config.slot - 1];
 	config.pwr_irq     = mmc_sdc_pwrctl_irq[config.slot - 1];
+	config.hs400_support = 0;
 
-	if (!(dev = mmc_init(&config))) {
+	for (i = 0; i < ARRAY_SIZE(mmc_clks); ++i) {
+		config.max_clk_rate = mmc_clks[i];
+		dprintf(INFO, "SDHC Running at %u MHz\n",
+			config.max_clk_rate / 1000000);
+		dev = mmc_init(&config);
+		if (dev && partition_read_table() == 0)
+			return;
+	}
+
+	if (dev == NULL)
 		dprintf(CRITICAL, "mmc init failed!");
-		ASSERT(0);
-	}
-
-	/*
-	 * MMC initialization is complete, read the partition table info
-	 */
-	if (partition_read_table()) {
+	else
 		dprintf(CRITICAL, "Error reading the partition table info\n");
-		ASSERT(0);
-	}
+	ASSERT(0);
 }
 
 void *target_mmc_device()
@@ -347,34 +357,6 @@
 	return 0;
 }
 
-/* Check if MSM needs VBUS mimic for USB */
-static int target_needs_vbus_mimic()
-{
-	return 1;
-}
-
-/* Do target specific usb initialization */
-void target_usb_init(void)
-{
-	uint32_t val;
-
-	extern void ulpi_write(unsigned val, unsigned reg);
-
-	if (target_needs_vbus_mimic()) {
-		/* 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);
-	}
-}
-
 /* Returns 1 if target supports continuous splash screen. */
 int target_cont_splash_screen()
 {
@@ -390,6 +372,7 @@
 {
 #if MMC_SDHCI_SUPPORT
 	mmc_put_card_to_sleep(dev);
+	sdhci_mode_disable(&dev->host);
 #else
 	mmc_put_card_to_sleep();
 #endif
@@ -412,17 +395,41 @@
 	/* Drive strength configs for sdc pins */
 	struct tlmm_cfgs sdc1_hdrv_cfg[] =
 	{
-		{ 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 },
+		{
+			off: SDC1_CLK_HDRV_CTL_OFF,
+			val: TLMM_CUR_VAL_10MA,
+			mask: TLMM_HDRV_MASK
+		},
+		{
+			off: SDC1_CMD_HDRV_CTL_OFF,
+			val: TLMM_CUR_VAL_10MA,
+			mask: TLMM_HDRV_MASK
+		},
+		{
+			off: SDC1_DATA_HDRV_CTL_OFF,
+			val: TLMM_CUR_VAL_10MA,
+			mask: 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 },
+		{
+			off: SDC1_CLK_PULL_CTL_OFF,
+			val: TLMM_NO_PULL,
+			mask: TLMM_PULL_MASK
+		},
+		{
+			off: SDC1_CMD_PULL_CTL_OFF,
+			val: TLMM_PULL_UP,
+			mask: TLMM_PULL_MASK
+		},
+		{
+			off: SDC1_DATA_PULL_CTL_OFF,
+			val: TLMM_PULL_UP,
+			mask: TLMM_PULL_MASK
+		},
 	};
 
 	/* Set the drive strength & pull control values */
@@ -437,6 +444,92 @@
 	return _emmc_recovery_init();
 }
 
+#define USB30_QSCRATCH_GENERAL_CFG			(MSM_USB30_QSCRATCH_BASE + 0x08)
+#define USB30_QSCRATCH_GENERAL_CFG_PIPE_UTMI_CLK_SEL	(1 << 0)
+#define USB30_QSCRATCH_GENERAL_CFG_PIPE3_PHYSTATUS_SW	(1 << 3)
+#define USB30_QSCRATCH_GENERAL_CFG_PIPE_UTMI_CLK_DIS	(1 << 8)
+
+#define CM_DWC_USB2_USB_PHY_UTMI_CTRL5			(CM_DWC_USB2_CM_DWC_USB2_BASE + 0x74)
+#define CM_DWC_USB2_USB_PHY_HS_PHY_CTRL_COMMON0		(CM_DWC_USB2_CM_DWC_USB2_BASE + 0x78)
+#define CM_DWC_USB2_USB_PHY_PARAMETER_OVERRIDE_X0	(CM_DWC_USB2_CM_DWC_USB2_BASE + 0x98)
+#define CM_DWC_USB2_USB_PHY_PARAMETER_OVERRIDE_X1	(CM_DWC_USB2_CM_DWC_USB2_BASE + 0x9c)
+#define CM_DWC_USB2_USB_PHY_PARAMETER_OVERRIDE_X2	(CM_DWC_USB2_CM_DWC_USB2_BASE + 0xa0)
+#define CM_DWC_USB2_USB_PHY_PARAMETER_OVERRIDE_X3	(CM_DWC_USB2_CM_DWC_USB2_BASE + 0xa4)
+#define CM_DWC_USB2_USB_PHY_REFCLK_CTRL			(CM_DWC_USB2_CM_DWC_USB2_BASE + 0xe8)
+
+void target_usb_phy_mux_configure(void)
+{
+}
+
+void target_usb_phy_init(void)
+{
+	uint32_t val;
+
+	/* Disable clock */
+	val = readl(USB30_QSCRATCH_GENERAL_CFG);
+	val |= USB30_QSCRATCH_GENERAL_CFG_PIPE_UTMI_CLK_DIS;
+	writel(val, USB30_QSCRATCH_GENERAL_CFG);
+	mdelay(1);
+
+	/* Select UTMI instead of PIPE3 */
+	val |= USB30_QSCRATCH_GENERAL_CFG_PIPE_UTMI_CLK_SEL;
+	writel(val, USB30_QSCRATCH_GENERAL_CFG);
+	val |= USB30_QSCRATCH_GENERAL_CFG_PIPE3_PHYSTATUS_SW;
+	writel(val, USB30_QSCRATCH_GENERAL_CFG);
+	mdelay(1);
+
+	/* Enable clock */
+	val &= ~USB30_QSCRATCH_GENERAL_CFG_PIPE_UTMI_CLK_DIS;
+	writel(val, USB30_QSCRATCH_GENERAL_CFG);
+
+	/* Initialize HS PICO PHY */
+	writel(0xc4, CM_DWC_USB2_USB_PHY_PARAMETER_OVERRIDE_X0);
+	writel(0x88, CM_DWC_USB2_USB_PHY_PARAMETER_OVERRIDE_X1);
+	writel(0x11, CM_DWC_USB2_USB_PHY_PARAMETER_OVERRIDE_X2);
+	writel(0x03, CM_DWC_USB2_USB_PHY_PARAMETER_OVERRIDE_X3);
+
+	writel(0x02, CM_DWC_USB2_USB_PHY_UTMI_CTRL5);
+	mdelay(1);
+	writel(0x00, CM_DWC_USB2_USB_PHY_UTMI_CTRL5);
+
+	val = readl(CM_DWC_USB2_USB_PHY_REFCLK_CTRL);
+	val &= ~(7 << 1);
+	val |= (6 << 1);
+	writel(val, CM_DWC_USB2_USB_PHY_REFCLK_CTRL);
+
+	val = readl(CM_DWC_USB2_USB_PHY_HS_PHY_CTRL_COMMON0);
+	val &= ~(7 << 4);
+	val |= (7 << 4);
+	writel(val, CM_DWC_USB2_USB_PHY_HS_PHY_CTRL_COMMON0);
+}
+
+void target_usb_phy_reset(void)
+{
+}
+
+target_usb_iface_t* target_usb30_init()
+{
+	target_usb_iface_t *t_usb_iface;
+
+	t_usb_iface = calloc(1, sizeof(target_usb_iface_t));
+	ASSERT(t_usb_iface);
+
+	t_usb_iface->mux_config = target_usb_phy_mux_configure;
+	t_usb_iface->phy_init   = target_usb_phy_init;
+	t_usb_iface->phy_reset  = target_usb_phy_reset;
+	t_usb_iface->clock_init = clock_usb30_init;
+	t_usb_iface->vbus_override = 1;
+
+	return t_usb_iface;
+}
+
+/* identify the usb controller to be used for the target */
+const char * target_usb_controller()
+{
+	return "dwc";
+}
+
+/* configure hs phy mux if using dwc controller */
 void target_usb_stop(void)
 {
 }