platform/target: mdm9640: Add support for mdmcalifornium

* USB mock_utmi, sleep, pipe clock support
* Get qmp phy settings from target
* Voldown support
* Reset phy from target
* Fix data abort when get_target_boot_params return null
* Add register to differentiate single ended and differential clocks

Change-Id: I22ac90cd0b5b39793aeb7493422fc8f479642788
diff --git a/platform/mdm9640/acpuclock.c b/platform/mdm9640/acpuclock.c
index 40827eb..99fd7d0 100644
--- a/platform/mdm9640/acpuclock.c
+++ b/platform/mdm9640/acpuclock.c
@@ -35,6 +35,7 @@
 #include <platform/clock.h>
 #include <platform/iomap.h>
 #include <platform/timer.h>
+#include <platform.h>
 
 void clock_config_uart_dm(uint8_t id)
 {
@@ -92,7 +93,11 @@
 		ASSERT(0);
 	}
 
-	ret = clk_get_set_enable("usb30_pipe_clk", 19200000, 1);
+	if (platform_is_mdmcalifornium())
+		ret = clk_get_set_enable("usb30_pipe_clk_mdmcalifornium", 0, 1);
+	else
+		ret = clk_get_set_enable("usb30_pipe_clk", 19200000, 1);
+
 	if(ret)
 	{
 		dprintf(CRITICAL, "failed to set usb30_pipe_clk. ret = %d\n", ret);
@@ -106,6 +111,20 @@
 		ASSERT(0);
 	}
 
+	ret = clk_get_set_enable("usb30_mock_utmi_clk", 60000000, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb30_mock_utmi_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("usb30_sleep_clk", 0, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb30_sleep_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
 	ret = clk_get_set_enable("usb_phy_cfg_ahb_clk", 0, 1);
 	if(ret)
 	{
@@ -169,12 +188,85 @@
 
 void clock_bumpup_pipe3_clk()
 {
-	int ret = 0;
+	int ret =0;
 
-	ret = clk_get_set_enable("usb30_pipe_clk", 125000000, 0);
+	if (platform_is_mdmcalifornium())
+		ret = clk_get_set_enable("usb30_pipe_clk", 0, true);
+	else
+		ret = clk_get_set_enable("usb30_pipe_clk", 125000000, true);
+
 	if(ret)
 	{
 		dprintf(CRITICAL, "failed to set usb30_pipe_clk. ret = %d\n", ret);
 		ASSERT(0);
 	}
 }
+
+void clock_reset_usb_phy()
+{
+	int ret;
+
+	struct clk *phy_reset_clk = NULL;
+	struct clk *pipe_reset_clk = NULL;
+	struct clk *master_clk = NULL;
+
+	master_clk = clk_get("usb30_master_clk");
+	ASSERT(master_clk);
+
+	/* Look if phy com clock is present */
+	phy_reset_clk = clk_get("usb30_phy_reset");
+	ASSERT(phy_reset_clk);
+
+	pipe_reset_clk = clk_get("usb30_pipe_clk");
+	ASSERT(pipe_reset_clk);
+
+	/* ASSERT */
+	ret = clk_reset(master_clk, CLK_RESET_ASSERT);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to assert usb30_master_reset clk\n");
+		return;
+	}
+	ret = clk_reset(phy_reset_clk, CLK_RESET_ASSERT);
+
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to assert usb30_phy_reset clk\n");
+		goto deassert_master_clk;
+	}
+
+	ret = clk_reset(pipe_reset_clk, CLK_RESET_ASSERT);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to assert usb30_pipe_clk\n");
+		goto deassert_phy_clk;
+	}
+
+	udelay(100);
+
+	/* DEASSERT */
+	ret = clk_reset(pipe_reset_clk, CLK_RESET_DEASSERT);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to deassert usb_pipe_clk\n");
+		return;
+	}
+
+deassert_phy_clk:
+
+	ret = clk_reset(phy_reset_clk, CLK_RESET_DEASSERT);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to deassert usb30_phy_com_reset clk\n");
+		return;
+	}
+deassert_master_clk:
+
+	ret = clk_reset(master_clk, CLK_RESET_DEASSERT);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to deassert usb30_master clk\n");
+		return;
+	}
+
+}
diff --git a/platform/mdm9640/include/platform/clock.h b/platform/mdm9640/include/platform/clock.h
index e450661..7fdf8a7 100644
--- a/platform/mdm9640/include/platform/clock.h
+++ b/platform/mdm9640/include/platform/clock.h
@@ -35,5 +35,6 @@
 void platform_clock_init(void);
 void clock_config_uart_dm(uint8_t id);
 void clock_usb30_init(void);
+void clock_reset_usb_phy();
 
 #endif
diff --git a/platform/mdm9640/include/platform/iomap.h b/platform/mdm9640/include/platform/iomap.h
index f92f556..2a21206 100644
--- a/platform/mdm9640/include/platform/iomap.h
+++ b/platform/mdm9640/include/platform/iomap.h
@@ -170,9 +170,16 @@
 #define USB3_AUX_D                  (CLK_CTL_BASE + 0x5E06C)
 #define USB3_AUX_CBCR               (CLK_CTL_BASE + 0x5E044)
 
+#define USB30_MOCK_UTMI_CBCR        (CLK_CTL_BASE + 0x5E008)
+#define USB30_SLEEP_CBCR            (CLK_CTL_BASE + 0x5E004)
+#define USB30_MOCK_UTMI_CMD_RCGR    (CLK_CTL_BASE + 0x5E020)
+#define USB30_MOCK_UTMI_CFG_RCGR    (CLK_CTL_BASE + 0x5E024)
+
 /* USB 3.0 phy */
 #define USB3_PHY_BCR                (CLK_CTL_BASE + 0x0005E034)
 
+#define USB_30_BCR                  (CLK_CTL_BASE + 0x0005E070)
+
 /* QUSB2 PHY */
 #define QUSB2_PHY_BASE              0x00079000
 #define GCC_QUSB2_PHY_BCR           (CLK_CTL_BASE + 0x00041028)
@@ -197,5 +204,17 @@
 #define APCS_ALIAS0_IPC_INTERRUPT   0xB011008
 /* eMMC Display */
 #define TLMM_EBI2_EMMC_GPIO_CFG     0x01111000
+
+/* QMP rev registers */
+#define USB3_PHY_REVISION_ID0       (QMP_PHY_BASE + 0x988)
+#define USB3_PHY_REVISION_ID1       (QMP_PHY_BASE + 0x98C)
+#define USB3_PHY_REVISION_ID2       (QMP_PHY_BASE + 0x990)
+#define USB3_PHY_REVISION_ID3       (QMP_PHY_BASE + 0x994)
+
 #define EBI2_BOOT_SELECT            0x2
+#define GCC_RX2_USB2_CLKREF_EN      0x01841030
+#define USB3_PHY_STATUS             0x78974
+/* Register for finding out if single ended or differential clock enablement */
+#define TCSR_PHY_CLK_SCHEME_SEL     0x01956044
+
 #endif
diff --git a/platform/mdm9640/mdm9640-clock.c b/platform/mdm9640/mdm9640-clock.c
index f6b85fb..0d4c26f 100644
--- a/platform/mdm9640/mdm9640-clock.c
+++ b/platform/mdm9640/mdm9640-clock.c
@@ -276,10 +276,10 @@
 	},
 };
 
-
 static struct branch_clk gcc_usb30_master_clk =
 {
 	.cbcr_reg     = (uint32_t *) GCC_USB30_MASTER_CBCR,
+	.bcr_reg      = (uint32_t *) USB_30_BCR,
 	.parent       = &usb30_master_clk_src.c,
 
 	.c = {
@@ -319,6 +319,19 @@
 	},
 };
 
+
+static struct branch_clk gcc_usb30_pipe_clk_mdmcalifornium = {
+	.bcr_reg      = (uint32_t *) USB3_PIPE_BCR,
+	.cbcr_reg     = (uint32_t *) USB3_PIPE_CBCR,
+	.has_sibling  = 1,
+	.halt_check   = 0,
+
+	.c = {
+		.dbg_name = "usb30_pipe_clk_mdmcalifornium",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct clk_freq_tbl ftbl_gcc_usb30_aux_clk[] = {
 	F(   1000000,         cxo,    1,    5,    96),
 	F_END
@@ -369,6 +382,47 @@
 	},
 };
 
+static struct clk_freq_tbl ftbl_gcc_usb30_mock_utmi_clk_src[] = {
+	F(  60000000, gpll0,   10,    0,     0),
+	F_END
+};
+
+static struct rcg_clk usb30_mock_utmi_clk_src = {
+	.cmd_reg      = (uint32_t *) USB30_MOCK_UTMI_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) USB30_MOCK_UTMI_CFG_RCGR,
+	.set_rate     = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl     = ftbl_gcc_usb30_mock_utmi_clk_src,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "usb30_mock_utmi_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
+static struct branch_clk gcc_usb30_mock_utmi_clk = {
+	.cbcr_reg    = (uint32_t *) USB30_MOCK_UTMI_CBCR,
+	.has_sibling = 0,
+	.parent      = &usb30_mock_utmi_clk_src.c,
+
+	.c = {
+		.dbg_name = "usb30_mock_utmi_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gcc_usb30_sleep_clk = {
+	.cbcr_reg    = (uint32_t *) USB30_SLEEP_CBCR,
+	.has_sibling = 1,
+
+	.c = {
+		.dbg_name = "usb30_sleep_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+
+
 static struct clk_lookup msm_clocks_9640[] =
 {
 	CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c),
@@ -380,12 +434,15 @@
 	CLK_LOOKUP("usb30_iface_clk",  gcc_sys_noc_usb30_axi_clk.c),
 	CLK_LOOKUP("usb30_master_clk", gcc_usb30_master_clk.c),
 	CLK_LOOKUP("usb30_pipe_clk",   gcc_usb30_pipe_clk.c),
+	CLK_LOOKUP("usb30_pipe_clk_mdmcalifornium",   gcc_usb30_pipe_clk_mdmcalifornium.c),
 	CLK_LOOKUP("usb30_aux_clk",    gcc_usb30_aux_clk.c),
 
 	CLK_LOOKUP("usb2b_phy_sleep_clk", gcc_usb2a_phy_sleep_clk.c),
 	CLK_LOOKUP("usb30_phy_reset",     gcc_usb30_phy_reset.c),
 
+	CLK_LOOKUP("usb30_mock_utmi_clk", gcc_usb30_mock_utmi_clk.c),
 	CLK_LOOKUP("usb_phy_cfg_ahb_clk", gcc_usb_phy_cfg_ahb_clk.c),
+	CLK_LOOKUP("usb30_sleep_clk",     gcc_usb30_sleep_clk.c),
 };
 
 void platform_clock_init(void)
diff --git a/platform/mdm9640/platform.c b/platform/mdm9640/platform.c
index 6ccbe19..f69053c 100644
--- a/platform/mdm9640/platform.c
+++ b/platform/mdm9640/platform.c
@@ -156,14 +156,45 @@
 	return phys_addr;
 }
 
+
+bool platform_is_mdmcalifornium()
+{
+	uint32_t platform_id = board_platform_id();
+	bool ret;
+
+	switch(platform_id)
+	{
+		case MDMCALIFORNIUM1:
+		case MDMCALIFORNIUM2:
+		case MDMCALIFORNIUM3:
+		case MDMCALIFORNIUM4:
+				ret = true;
+				break;
+		default:
+				ret = false;
+	};
+
+	return ret;
+}
+
 uint32_t platform_boot_config()
 {
 	uint32_t boot_config;
 
-	if (board_soc_version() >= 0x20000)
+	if (platform_is_mdmcalifornium())
+		boot_config = BOOT_CONFIG_REG_V2;
+	/* Else the platform is 9x45 */
+	else if (board_soc_version() >= 0x20000)
 		boot_config = BOOT_CONFIG_REG_V2;
 	else
 		boot_config = BOOT_CONFIG_REG_V1;
 
 	return boot_config;
 }
+
+uint32_t platform_get_qmp_rev()
+{
+	return readl(USB3_PHY_REVISION_ID3) << 24 | readl(USB3_PHY_REVISION_ID2) << 16 |
+		   readl(USB3_PHY_REVISION_ID1) << 8 | readl(USB3_PHY_REVISION_ID0);
+}
+