platform/target: Add clock driver support and enable SDHCI
Add support to enable SDHCI and USB. This patch also
enables the clock driver for various peripherals.
Change-Id: I96d3079b0615cee34c2b3f6d8b2c13517aa5a442
diff --git a/platform/msm8952/acpuclock.c b/platform/msm8952/acpuclock.c
index ffb8b92..0c03f4d 100644
--- a/platform/msm8952/acpuclock.c
+++ b/platform/msm8952/acpuclock.c
@@ -38,24 +38,144 @@
void hsusb_clock_init(void)
{
+ int ret;
+ struct clk *iclk, *cclk;
+ ret = clk_get_set_enable("usb_iface_clk", 0, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb_iface_clk ret = %d\n", ret);
+ ASSERT(0);
+ }
+
+ ret = clk_get_set_enable("usb_core_clk", 80000000, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb_core_clk ret = %d\n", ret);
+ ASSERT(0);
+ }
+
+ mdelay(20);
+
+ iclk = clk_get("usb_iface_clk");
+ cclk = clk_get("usb_core_clk");
+
+ clk_disable(iclk);
+ clk_disable(cclk);
+
+ mdelay(20);
+
+ /* Start the block reset for usb */
+ writel(1, USB_HS_BCR);
+
+ mdelay(20);
+
+ /* Take usb block out of reset */
+ writel(0, USB_HS_BCR);
+
+ mdelay(20);
+
+ ret = clk_enable(iclk);
+
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb_iface_clk after async ret = %d\n", ret);
+ ASSERT(0);
+ }
+
+ ret = clk_enable(cclk);
+
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set usb_iface_clk after async ret = %d\n", ret);
+ ASSERT(0);
+ }
}
void clock_init_mmc(uint32_t interface)
{
+ char clk_name[64];
+ int ret;
+ snprintf(clk_name, sizeof(clk_name), "sdc%u_iface_clk", interface);
+
+ /* enable interface clock */
+ ret = clk_get_set_enable(clk_name, 0, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set sdc1_iface_clk ret = %d\n", ret);
+ ASSERT(0);
+ }
}
/* Configure MMC clock */
void clock_config_mmc(uint32_t interface, uint32_t freq)
{
- mmc_boot_mci_clk_enable();
+ int ret = 1;
+ char clk_name[64];
+
+ snprintf(clk_name, sizeof(clk_name), "sdc%u_core_clk", interface);
+
+ if(freq == MMC_CLK_400KHZ)
+ {
+ ret = clk_get_set_enable(clk_name, 400000, 1);
+ }
+ else if(freq == MMC_CLK_50MHZ)
+ {
+ ret = clk_get_set_enable(clk_name, 50000000, 1);
+ }
+ else if(freq == MMC_CLK_177MHZ)
+ {
+ ret = clk_get_set_enable(clk_name, 177770000, 1);
+ }
+ else if(freq == MMC_CLK_192MHZ)
+ {
+ ret = clk_get_set_enable(clk_name, 192000000, 1);
+ }
+ else if(freq == MMC_CLK_200MHZ)
+ {
+ ret = clk_get_set_enable(clk_name, 200000000, 1);
+ }
+ else if(freq == MMC_CLK_400MHZ)
+ {
+ ret = clk_get_set_enable(clk_name, 384000000, 1);
+ }
+ else
+ {
+ dprintf(CRITICAL, "sdc frequency (%u) is not supported\n", freq);
+ ASSERT(0);
+ }
+
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
+ ASSERT(0);
+ }
}
/* Configure UART clock based on the UART block id*/
void clock_config_uart_dm(uint8_t id)
{
+ int ret;
+ char iclk[64];
+ char cclk[64];
+ snprintf(iclk, sizeof(iclk), "uart%u_iface_clk", id);
+ snprintf(cclk, sizeof(cclk), "uart%u_core_clk", id);
+
+ ret = clk_get_set_enable(iclk, 0, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set %s ret = %d\n", iclk, ret);
+ ASSERT(0);
+ }
+
+ ret = clk_get_set_enable(cclk, 7372800, 1);
+ if(ret)
+ {
+ dprintf(CRITICAL, "failed to set %s ret = %d\n", cclk, ret);
+ ASSERT(0);
+ }
}
/* Function to asynchronously reset CE.
diff --git a/platform/msm8952/include/platform/iomap.h b/platform/msm8952/include/platform/iomap.h
index ac40933..f4712d7 100644
--- a/platform/msm8952/include/platform/iomap.h
+++ b/platform/msm8952/include/platform/iomap.h
@@ -62,6 +62,7 @@
#define MSM_SDC1_BASE (PERIPH_SS_BASE + 0x00024000)
#define MSM_SDC2_BASE (PERIPH_SS_BASE + 0x00064000)
+/* UART */
#define BLSP1_UART0_BASE (PERIPH_SS_BASE + 0x000AF000)
#define BLSP1_UART1_BASE (PERIPH_SS_BASE + 0x000B0000)
#define MSM_USB_BASE (PERIPH_SS_BASE + 0x000DB000)
@@ -84,12 +85,18 @@
/* CRYPTO ENGINE */
#define MSM_CE1_BASE 0x073A000
#define MSM_CE1_BAM_BASE 0x0704000
-
+#define GCC_CRYPTO_BCR (CLK_CTL_BASE + 0x16000)
+#define GCC_CRYPTO_CMD_RCGR (CLK_CTL_BASE + 0x16004)
+#define GCC_CRYPTO_CFG_RCGR (CLK_CTL_BASE + 0x16008)
+#define GCC_CRYPTO_CBCR (CLK_CTL_BASE + 0x1601C)
+#define GCC_CRYPTO_AXI_CBCR (CLK_CTL_BASE + 0x16020)
+#define GCC_CRYPTO_AHB_CBCR (CLK_CTL_BASE + 0x16024)
/* GPLL */
#define GPLL0_STATUS (CLK_CTL_BASE + 0x2101C)
#define APCS_GPLL_ENA_VOTE (CLK_CTL_BASE + 0x45000)
#define APCS_CLOCK_BRANCH_ENA_VOTE (CLK_CTL_BASE + 0x45004)
+#define GPLL4_MODE (CLK_CTL_BASE + 0x24000)
/* SDCC */
#define SDC1_HDRV_PULL_CTL (TLMM_BASE_ADDR + 0x10A000)
@@ -102,6 +109,25 @@
#define SDCC1_N (CLK_CTL_BASE + 0x42010) /* n */
#define SDCC1_D (CLK_CTL_BASE + 0x42014) /* d */
+/* SDHCI */
+#define MSM_SDC1_SDHCI_BASE (PERIPH_SS_BASE + 0x00024900)
+#define MSM_SDC2_SDHCI_BASE (PERIPH_SS_BASE + 0x00064900)
+
+#define SDCC_MCI_HC_MODE (0x00000078)
+#define SDCC_HC_PWRCTL_STATUS_REG (0x000000DC)
+#define SDCC_HC_PWRCTL_MASK_REG (0x000000E0)
+#define SDCC_HC_PWRCTL_CLEAR_REG (0x000000E4)
+#define SDCC_HC_PWRCTL_CTL_REG (0x000000E8)
+
+#define SDCC2_BCR (CLK_CTL_BASE + 0x43000) /* block reset */
+#define SDCC2_APPS_CBCR (CLK_CTL_BASE + 0x43018) /* branch control */
+#define SDCC2_AHB_CBCR (CLK_CTL_BASE + 0x4301C)
+#define SDCC2_CMD_RCGR (CLK_CTL_BASE + 0x43004) /* cmd */
+#define SDCC2_CFG_RCGR (CLK_CTL_BASE + 0x43008) /* cfg */
+#define SDCC2_M (CLK_CTL_BASE + 0x4300C) /* m */
+#define SDCC2_N (CLK_CTL_BASE + 0x43010) /* n */
+#define SDCC2_D (CLK_CTL_BASE + 0x43014) /* d */
+
/* UART */
#define BLSP1_AHB_CBCR (CLK_CTL_BASE + 0x1008)
#define BLSP1_UART2_APPS_CBCR (CLK_CTL_BASE + 0x302C)
diff --git a/platform/msm8952/include/platform/irqs.h b/platform/msm8952/include/platform/irqs.h
index 31da373..810f113 100644
--- a/platform/msm8952/include/platform/irqs.h
+++ b/platform/msm8952/include/platform/irqs.h
@@ -46,6 +46,8 @@
#define USB1_HS_BAM_IRQ (GIC_SPI_START + 135)
#define USB1_HS_IRQ (GIC_SPI_START + 134)
+#define SDCC1_PWRCTL_IRQ (GIC_SPI_START + 138)
+#define SDCC2_PWRCTL_IRQ (GIC_SPI_START + 221)
/* Retrofit universal macro names */
#define INT_USB_HS USB1_HS_IRQ
diff --git a/platform/msm8952/msm8952-clock.c b/platform/msm8952/msm8952-clock.c
index ed39611..f464cc8 100644
--- a/platform/msm8952/msm8952-clock.c
+++ b/platform/msm8952/msm8952-clock.c
@@ -111,6 +111,21 @@
},
};
+static struct pll_vote_clk gpll4_clk_src =
+{
+ .en_reg = (void *) APCS_GPLL_ENA_VOTE,
+ .en_mask = BIT(5),
+ .status_reg = (void *) GPLL4_MODE,
+ .status_mask = BIT(30),
+ .parent = &cxo_clk_src.c,
+
+ .c = {
+ .rate = 1152000000,
+ .dbg_name = "gpll4_clk_src",
+ .ops = &clk_ops_pll_vote,
+ },
+};
+
/* SDCC Clocks */
static struct clk_freq_tbl ftbl_gcc_sdcc1_apps_clk[] =
{
@@ -121,8 +136,8 @@
F( 50000000, gpll0, 16, 0, 0),
F(100000000, gpll0, 8, 0, 0),
F(177770000, gpll0, 4.5, 0, 0),
- F(200000000, gpll0, 4, 0, 0),
- F(400000000, gpll4, 3, 0, 0),
+ F(192000000, gpll0, 6, 0, 0),
+ F(384000000, gpll4, 3, 0, 0),
F_END
};
@@ -135,7 +150,7 @@
.d_reg = (uint32_t *) SDCC1_D,
.set_rate = clock_lib2_rcg_set_rate_mnd,
- .freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+ .freq_tbl = ftbl_gcc_sdcc1_apps_clk,
.current_freq = &rcg_dummy_freq,
.c = {
diff --git a/platform/msm8952/platform.c b/platform/msm8952/platform.c
index 4648638..1ee7cdc 100644
--- a/platform/msm8952/platform.c
+++ b/platform/msm8952/platform.c
@@ -29,12 +29,16 @@
#include <debug.h>
#include <reg.h>
#include <platform/iomap.h>
+#include <platform/irqs.h>
+#include <platform/clock.h>
#include <qgic.h>
#include <qtimer.h>
#include <mmu.h>
#include <arch/arm/mmu.h>
#include <smem.h>
#include <board.h>
+#include <boot_stats.h>
+#include <platform.h>
#define MSM_IOMAP_SIZE ((MSM_IOMAP_END - MSM_IOMAP_BASE)/MB)
#define APPS_SS_SIZE ((APPS_SS_END - APPS_SS_BASE)/MB)
@@ -66,6 +70,7 @@
void platform_early_init(void)
{
board_init();
+ platform_clock_init();
qgic_init();
qtimer_init();
scm_init();
diff --git a/platform/msm8952/rules.mk b/platform/msm8952/rules.mk
index ebae71e..fbbece0 100644
--- a/platform/msm8952/rules.mk
+++ b/platform/msm8952/rules.mk
@@ -19,6 +19,7 @@
OBJS += \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/acpuclock.o \
+ $(LOCAL_DIR)/msm8952-clock.o \
$(LOCAL_DIR)/gpio.o
LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld
diff --git a/target/msm8952/init.c b/target/msm8952/init.c
index c61c631..3893d9a 100644
--- a/target/msm8952/init.c
+++ b/target/msm8952/init.c
@@ -60,23 +60,82 @@
#define FASTBOOT_MODE 0x77665500
#define PON_SOFT_RB_SPARE 0x88F
-static uint32_t mmc_sdc_base[] =
+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)
+static void set_sdc_power_ctrl()
{
- 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;
+ /* Drive strength configs for sdc pins */
+ struct tlmm_cfgs sdc1_hdrv_cfg[] =
+ {
+ { SDC1_CLK_HDRV_CTL_OFF, TLMM_CUR_VAL_16MA, TLMM_HDRV_MASK, 0},
+ { SDC1_CMD_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK, 0},
+ { SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK , 0},
+ };
+
+ /* Pull configs for sdc pins */
+ struct tlmm_cfgs sdc1_pull_cfg[] =
+ {
+ { SDC1_CLK_PULL_CTL_OFF, TLMM_NO_PULL, TLMM_PULL_MASK, 0},
+ { SDC1_CMD_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK, 0},
+ { SDC1_DATA_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK, 0},
+ };
+
+ /* 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_sdc_init()
+{
+ struct mmc_config_data config;
+
+ /* Set drive strength & pull ctrl values */
+ set_sdc_power_ctrl();
+
+ /* Try slot 1*/
+ config.slot = 1;
+ config.bus_width = DATA_BUS_WIDTH_8BIT;
+ config.max_clk_rate = MMC_CLK_177MHZ;
+ 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 = 1;
+
+ if (!(dev = mmc_init(&config))) {
+ /* Try slot 2 */
+ config.slot = 2;
+ config.max_clk_rate = MMC_CLK_200MHZ;
+ 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))) {
+ dprintf(CRITICAL, "mmc init failed!");
+ ASSERT(0);
+ }
+ }
+}
+
+void *target_mmc_device()
+{
+ return (void *) dev;
}
/* Return 1 if vol_up pressed */
@@ -144,20 +203,13 @@
target_keystatus();
- /* 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);
- }
}
+
#if LONG_PRESS_POWER_ON
shutdown_detect();
#endif
@@ -314,8 +366,37 @@
if (is_cold_boot &&
(!(pon_reason & HARD_RST)) &&
(!(pon_reason & KPDPWR_N)) &&
- ((pon_reason & USB_CHG) || (pon_reason & DC_CHG) || (pon_reason & CBLPWR_N)))
+ ((pon_reason & USB_CHG)))
return 1;
else
return 0;
}
+
+void target_uninit(void)
+{
+ mmc_put_card_to_sleep(dev);
+ sdhci_mode_disable(&dev->host);
+}
+
+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);
+}