target/platform: msm8994: Add usb30 support
Add support for usb30 clocks, phy and target init
code.
CRs-Fixed: 636135
Change-Id: I260eef5fff73a431ba89b095def92fe0070b1662
diff --git a/platform/msm8994/acpuclock.c b/platform/msm8994/acpuclock.c
index c90718e..64c2a14 100644
--- a/platform/msm8994/acpuclock.c
+++ b/platform/msm8994/acpuclock.c
@@ -205,3 +205,71 @@
clock_ce_enable(instance);
}
+
+void clock_usb30_gdsc_enable(void)
+{
+ uint32_t reg = readl(GCC_USB30_GDSCR);
+
+ reg &= ~(0x1);
+
+ writel(reg, GCC_USB30_GDSCR);
+}
+
+/* enables usb30 clocks */
+void clock_usb30_init(void)
+{
+ int ret;
+
+ ret = clk_get_set_enable("usb30_iface_clk", 0, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb30_iface_clk. ret = %d\n", ret);
+ ASSERT(0);
+ }
+
+ clock_usb30_gdsc_enable();
+
+ ret = clk_get_set_enable("usb30_master_clk", 125000000, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb30_master_clk. ret = %d\n", ret);
+ ASSERT(0);
+ }
+
+ ret = clk_get_set_enable("usb30_phy_aux_clk", 1200000, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb30_phy_aux_clk. ret = %d\n", ret);
+ ASSERT(0);
+ }
+
+ ret = clk_get_set_enable("usb30_mock_utmi_clk", 60000000, 1);
+ 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, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb30_sleep_clk ret = %d\n", ret);
+ ASSERT(0);
+ }
+
+ pm8x41_lnbb_clock_ctrl(1);
+}
+
+void clock_bumpup_pipe3_clk()
+{
+ int ret = 0;
+
+ ret = clk_get_set_enable("usb30_pipe_clk", 0, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb30_pipe_clk. ret = %d\n", ret);
+ ASSERT(0);
+ }
+
+ return;
+}
diff --git a/platform/msm8994/include/platform/clock.h b/platform/msm8994/include/platform/clock.h
index c6b0ab4..bad5743 100644
--- a/platform/msm8994/include/platform/clock.h
+++ b/platform/msm8994/include/platform/clock.h
@@ -45,5 +45,6 @@
void mdp_clock_init(void);
void clock_ce_enable(uint8_t instance);
void clock_ce_disable(uint8_t instance);
+void clock_usb30_init(void);
#endif
diff --git a/platform/msm8994/include/platform/iomap.h b/platform/msm8994/include/platform/iomap.h
index 4a6c22d..592a369 100644
--- a/platform/msm8994/include/platform/iomap.h
+++ b/platform/msm8994/include/platform/iomap.h
@@ -76,6 +76,12 @@
#define MSM_USB_BASE (PERIPH_SS_BASE + 0x00255000)
+#define MSM_USB30_BASE 0xF9200000
+#define MSM_USB30_QSCRATCH_BASE 0xF92F8800
+
+/* SS QMP (Qulacomm Multi Protocol) */
+#define QMP_PHY_BASE 0xF9B38000
+
/* Clocks */
#define CLK_CTL_BASE 0xFC400000
@@ -109,6 +115,29 @@
#define USB_HS_SYSTEM_CMD_RCGR (CLK_CTL_BASE + 0x490)
#define USB_HS_SYSTEM_CFG_RCGR (CLK_CTL_BASE + 0x494)
+/* USB3 clocks */
+#define SYS_NOC_USB3_AXI_CBCR (CLK_CTL_BASE + 0x03FC)
+#define USB2B_PHY_SLEEP_CBCR (CLK_CTL_BASE + 0x04AC)
+#define USB2B_PHY_BCR (CLK_CTL_BASE + 0x04A8)
+#define USB30_MASTER_CMD_RCGR (CLK_CTL_BASE + 0x03D4)
+#define USB30_MASTER_CFG_RCGR (CLK_CTL_BASE + 0x03D8)
+#define USB30_MASTER_M (CLK_CTL_BASE + 0x03DC)
+#define USB30_MASTER_N (CLK_CTL_BASE + 0x03E0)
+#define USB30_MASTER_D (CLK_CTL_BASE + 0x03E4)
+#define USB30_MASTER_CBCR (CLK_CTL_BASE + 0x03C8)
+#define USB_30_BCR (CLK_CTL_BASE + 0x03C0)
+#define USB30_MOCK_UTMI_CMD_RCGR (CLK_CTL_BASE + 0x03E8)
+#define USB30_MOCK_UTMI_CFG_RCGR (CLK_CTL_BASE + 0x03EC)
+#define USB30_MOCK_UTMI_CBCR (CLK_CTL_BASE + 0x03D0)
+#define USB30_SLEEP_CBCR (CLK_CTL_BASE + 0x03CC)
+#define USB30_PHY_AUX_CMD_RCGR (CLK_CTL_BASE + 0x1414)
+#define USB30_PHY_AUX_CFG_RCGR (CLK_CTL_BASE + 0x1418)
+#define USB30_PHY_AUX_CBCR (CLK_CTL_BASE + 0x1408)
+#define USB30_PHY_PIPE_CBCR (CLK_CTL_BASE + 0x140C)
+#define USB30_PHY_BCR (CLK_CTL_BASE + 0x1400)
+#define USB30PHY_PHY_BCR (CLK_CTL_BASE + 0x1404)
+#define GCC_USB30_GDSCR (CLK_CTL_BASE + 0x03C4)
+
/* SDCC */
#define SDCC1_BCR (CLK_CTL_BASE + 0x4C0) /* block reset */
#define SDCC1_APPS_CBCR (CLK_CTL_BASE + 0x4C4) /* branch control */
@@ -167,4 +196,7 @@
#define MPM2_MPM_SLEEP_TIMETICK_COUNT_VAL 0xFC4A3000
+#define TCSR_PHSS_USB2_PHY_SEL 0xFD4AB000
+#define PLATFORM_QMP_OFFSET 0x8
+
#endif
diff --git a/platform/msm8994/include/platform/irqs.h b/platform/msm8994/include/platform/irqs.h
index aeb5cb8..25383cb 100644
--- a/platform/msm8994/include/platform/irqs.h
+++ b/platform/msm8994/include/platform/irqs.h
@@ -45,6 +45,7 @@
#define INT_QTMR_FRM_0_PHYSICAL_TIMER_EXP (GIC_SPI_START + 9)
+#define USB30_EE1_IRQ (GIC_SPI_START + 131)
#define USB1_HS_IRQ (GIC_SPI_START + 134)
#define SDCC1_PWRCTL_IRQ (GIC_SPI_START + 138)
diff --git a/platform/msm8994/msm8994-clock.c b/platform/msm8994/msm8994-clock.c
index 0bf5ce0..e876088 100644
--- a/platform/msm8994/msm8994-clock.c
+++ b/platform/msm8994/msm8994-clock.c
@@ -50,11 +50,17 @@
/* Clock Operations */
+static struct clk_ops clk_ops_rst =
+{
+ .reset = clock_lib2_reset_clk_reset,
+};
+
static struct clk_ops clk_ops_branch =
{
.enable = clock_lib2_branch_clk_enable,
.disable = clock_lib2_branch_clk_disable,
.set_rate = clock_lib2_branch_set_rate,
+ .reset = clock_lib2_branch_clk_reset,
};
static struct clk_ops clk_ops_rcg_mnd =
@@ -327,6 +333,148 @@
},
};
+static struct branch_clk gcc_sys_noc_usb30_axi_clk = {
+ .cbcr_reg = (uint32_t *) SYS_NOC_USB3_AXI_CBCR,
+ .has_sibling = 1,
+
+ .c = {
+ .dbg_name = "sys_noc_usb30_axi_clk",
+ .ops = &clk_ops_branch,
+ },
+};
+
+static struct branch_clk gcc_usb2b_phy_sleep_clk = {
+ .cbcr_reg = (uint32_t *) USB2B_PHY_SLEEP_CBCR,
+ .bcr_reg = (uint32_t *) USB2B_PHY_BCR,
+ .has_sibling = 1,
+
+ .c = {
+ .dbg_name = "usb2b_phy_sleep_clk",
+ .ops = &clk_ops_branch,
+ },
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
+ F( 125000000, gpll0, 1, 5, 24),
+ F_END
+};
+
+static struct rcg_clk usb30_master_clk_src = {
+ .cmd_reg = (uint32_t *) USB30_MASTER_CMD_RCGR,
+ .cfg_reg = (uint32_t *) USB30_MASTER_CFG_RCGR,
+ .m_reg = (uint32_t *) USB30_MASTER_M,
+ .n_reg = (uint32_t *) USB30_MASTER_N,
+ .d_reg = (uint32_t *) USB30_MASTER_D,
+
+ .set_rate = clock_lib2_rcg_set_rate_mnd,
+ .freq_tbl = ftbl_gcc_usb30_master_clk,
+ .current_freq = &rcg_dummy_freq,
+
+ .c = {
+ .dbg_name = "usb30_master_clk_src",
+ .ops = &clk_ops_rcg,
+ },
+};
+
+static struct branch_clk gcc_usb30_master_clk = {
+ .cbcr_reg = (uint32_t *) USB30_MASTER_CBCR,
+ .bcr_reg = (uint32_t *) USB_30_BCR,
+ .parent = &usb30_master_clk_src.c,
+
+ .c = {
+ .dbg_name = "usb30_master_clk",
+ .ops = &clk_ops_branch,
+ },
+};
+
+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_freq_tbl ftbl_gcc_usb30_phy_aux_clk_src[] = {
+ F( 1200000, cxo, 16, 0, 0),
+ F_END
+};
+
+static struct rcg_clk usb30_phy_aux_clk_src = {
+ .cmd_reg = (uint32_t *) USB30_PHY_AUX_CMD_RCGR,
+ .cfg_reg = (uint32_t *) USB30_PHY_AUX_CFG_RCGR,
+ .set_rate = clock_lib2_rcg_set_rate_hid,
+ .freq_tbl = ftbl_gcc_usb30_phy_aux_clk_src,
+ .current_freq = &rcg_dummy_freq,
+
+ .c = {
+ .dbg_name = "usb30_phy_aux_clk_src",
+ .ops = &clk_ops_rcg,
+ },
+};
+
+static struct branch_clk gcc_usb30_phy_aux_clk = {
+ .cbcr_reg = (uint32_t *)USB30_PHY_AUX_CBCR,
+ .has_sibling = 0,
+ .parent = &usb30_phy_aux_clk_src.c,
+
+ .c = {
+ .dbg_name = "usb30_phy_aux_clk",
+ .ops = &clk_ops_branch,
+ },
+};
+
+static struct branch_clk gcc_usb30_pipe_clk = {
+ .bcr_reg = (uint32_t *) USB30PHY_PHY_BCR,
+ .cbcr_reg = (uint32_t *) USB30_PHY_PIPE_CBCR,
+ .has_sibling = 1,
+
+ .c = {
+ .dbg_name = "usb30_pipe_clk",
+ .ops = &clk_ops_branch,
+ },
+};
+
+static struct reset_clk gcc_usb30_phy_reset = {
+ .bcr_reg = (uint32_t *)USB30_PHY_BCR,
+
+ .c = {
+ .dbg_name = "usb30_phy_reset",
+ .ops = &clk_ops_rst,
+ },
+};
+
/* Clock lookup table */
static struct clk_lookup msm_8994_clocks[] =
{
@@ -338,6 +486,16 @@
CLK_LOOKUP("usb_iface_clk", gcc_usb_hs_ahb_clk.c),
CLK_LOOKUP("usb_core_clk", gcc_usb_hs_system_clk.c),
+
+ /* USB30 clocks */
+ CLK_LOOKUP("usb2b_phy_sleep_clk", gcc_usb2b_phy_sleep_clk.c),
+ CLK_LOOKUP("usb30_master_clk", gcc_usb30_master_clk.c),
+ CLK_LOOKUP("usb30_iface_clk", gcc_sys_noc_usb30_axi_clk),
+ CLK_LOOKUP("usb30_mock_utmi_clk", gcc_usb30_mock_utmi_clk.c),
+ CLK_LOOKUP("usb30_sleep_clk", gcc_usb30_sleep_clk.c),
+ CLK_LOOKUP("usb30_phy_aux_clk", gcc_usb30_phy_aux_clk.c),
+ CLK_LOOKUP("usb30_pipe_clk", gcc_usb30_pipe_clk.c),
+ CLK_LOOKUP("usb30_phy_reset", gcc_usb30_phy_reset.c),
};
void platform_clock_init(void)
diff --git a/target/msm8994/init.c b/target/msm8994/init.c
index 5890110..71ee5d2 100644
--- a/target/msm8994/init.c
+++ b/target/msm8994/init.c
@@ -53,6 +53,7 @@
#include <stdlib.h>
#include <ufs.h>
#include <boot_device.h>
+#include <qmp_phy.h>
#define PMIC_ARB_CHANNEL_NUM 0
#define PMIC_ARB_OWNER_ID 0
@@ -326,3 +327,41 @@
{
return _emmc_recovery_init();
}
+
+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 = usb30_qmp_phy_init;
+ t_usb_iface->phy_reset = usb30_qmp_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";
+}
+
+/* mux hs phy to route to dwc controller */
+static void phy_mux_configure_with_tcsr()
+{
+ /* As per the hardware team, set the mux for snps controller */
+ RMWREG32(TCSR_PHSS_USB2_PHY_SEL, 0x0, 0x1, 0x1);
+}
+
+/* configure hs phy mux if using dwc controller */
+void target_usb_phy_mux_configure(void)
+{
+ if(!strcmp(target_usb_controller(), "dwc"))
+ {
+ phy_mux_configure_with_tcsr();
+ }
+}