Merge "MPQ8092: SDHCI: Adding support for SDHCI"
diff --git a/platform/mpq8092/acpuclock.c b/platform/mpq8092/acpuclock.c
index 1e2ee63..e93788a 100644
--- a/platform/mpq8092/acpuclock.c
+++ b/platform/mpq8092/acpuclock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -114,7 +114,6 @@
 	char clk_name[64];
 
 	snprintf(clk_name, sizeof(clk_name), "sdc%u_core_clk", interface);
-	mmc_boot_mci_clk_disable();
 	if(freq == MMC_CLK_400KHZ)
 	{
 		ret = clk_get_set_enable(clk_name, 400000, 1);
@@ -142,8 +141,6 @@
 		dprintf(CRITICAL, "failed to set sdc%u_core_clk ret = %d\n", interface, ret);
 		ASSERT(0);
 	}
-	/* Enable MCI clk */
-	mmc_boot_mci_clk_enable();
 }
 
 /* Configure UART clock based on the UART block id*/
diff --git a/platform/mpq8092/include/platform/iomap.h b/platform/mpq8092/include/platform/iomap.h
index 4957aa0..d942192 100644
--- a/platform/mpq8092/include/platform/iomap.h
+++ b/platform/mpq8092/include/platform/iomap.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -53,12 +53,14 @@
 #define MSM_SDC1_BAM_BASE           (PERIPH_SS_BASE + 0x00004000)
 #define MSM_SDC1_BASE               (PERIPH_SS_BASE + 0x00024000)
 #define MSM_SDC1_DML_BASE           (PERIPH_SS_BASE + 0x00024800)
+#define MSM_SDC1_SDHCI_BASE         (PERIPH_SS_BASE + 0x00024900)
 #define MSM_SDC3_BAM_BASE           (PERIPH_SS_BASE + 0x00044000)
 #define MSM_SDC3_BASE               (PERIPH_SS_BASE + 0x00064000)
 #define MSM_SDC3_DML_BASE           (PERIPH_SS_BASE + 0x00064800)
 #define MSM_SDC2_BAM_BASE           (PERIPH_SS_BASE + 0x00084000)
 #define MSM_SDC2_BASE               (PERIPH_SS_BASE + 0x000A4000)
 #define MSM_SDC2_DML_BASE           (PERIPH_SS_BASE + 0x000A4800)
+#define MSM_SDC2_SDHCI_BASE         (PERIPH_SS_BASE + 0x000A4900)
 #define MSM_SDC4_BAM_BASE           (PERIPH_SS_BASE + 0x000C4000)
 #define MSM_SDC4_BASE               (PERIPH_SS_BASE + 0x000E4000)
 #define MSM_SDC4_DML_BASE           (PERIPH_SS_BASE + 0x000E4800)
@@ -144,6 +146,24 @@
 
 #define SDC1_HDRV_PULL_CTL          (TLMM_BASE_ADDR + 0x00002044)
 
+/* SDCC2 */
+#define SDCC2_BCR                   (CLK_CTL_BASE + 0x500) /* block reset */
+#define SDCC2_APPS_CBCR             (CLK_CTL_BASE + 0x504) /* branch control */
+#define SDCC2_AHB_CBCR              (CLK_CTL_BASE + 0x508)
+#define SDCC2_INACTIVITY_TIMER_CBCR (CLK_CTL_BASE + 0x50C)
+#define SDCC2_CMD_RCGR              (CLK_CTL_BASE + 0x510) /* cmd */
+#define SDCC2_CFG_RCGR              (CLK_CTL_BASE + 0x514) /* cfg */
+#define SDCC2_M                     (CLK_CTL_BASE + 0x518) /* m */
+#define SDCC2_N                     (CLK_CTL_BASE + 0x51C) /* n */
+#define SDCC2_D                     (CLK_CTL_BASE + 0x520) /* d */
+
+/* SDHCI */
+#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)
+
 /* UART */
 #define BLSP1_UART2_APPS_CBCR       (CLK_CTL_BASE + 0x704)
 #define BLSP1_UART2_APPS_CMD_RCGR   (CLK_CTL_BASE + 0x70C)
diff --git a/platform/mpq8092/include/platform/irqs.h b/platform/mpq8092/include/platform/irqs.h
index 33430cb..ce914af 100644
--- a/platform/mpq8092/include/platform/irqs.h
+++ b/platform/mpq8092/include/platform/irqs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -47,6 +47,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/mpq8092/mpq8092-clock.c b/platform/mpq8092/mpq8092-clock.c
index 2da2809..9fa9095 100644
--- a/platform/mpq8092/mpq8092-clock.c
+++ b/platform/mpq8092/mpq8092-clock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -282,6 +282,46 @@
 	},
 };
 
+static struct rcg_clk sdcc2_apps_clk_src = {
+
+	.cmd_reg      = (uint32_t *) SDCC2_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) SDCC2_CFG_RCGR,
+	.m_reg        = (uint32_t *) SDCC2_M,
+	.n_reg        = (uint32_t *) SDCC2_N,
+	.d_reg        = (uint32_t *) SDCC2_D,
+
+	.set_rate     = clock_lib2_rcg_set_rate_mnd,
+	.freq_tbl     = ftbl_gcc_sdcc1_2_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "sdc2_clk",
+		.ops      = &clk_ops_rcg_mnd,
+	},
+};
+
+static struct branch_clk gcc_sdcc2_apps_clk = {
+
+	.cbcr_reg     = (uint32_t *) SDCC2_APPS_CBCR,
+	.parent       = &sdcc2_apps_clk_src.c,
+
+	.c = {
+		.dbg_name = "gcc_sdcc2_apps_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gcc_sdcc2_ahb_clk = {
+
+	.cbcr_reg     = (uint32_t *) SDCC2_AHB_CBCR,
+	.has_sibling  = 1,
+
+	.c = {
+		.dbg_name = "gcc_sdcc2_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 
 /* Clock lookup table */
 static struct clk_lookup msm_clocks_8092[] =
@@ -289,6 +329,9 @@
 	CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c),
 	CLK_LOOKUP("sdc1_core_clk",  gcc_sdcc1_apps_clk.c),
 
+	CLK_LOOKUP("sdc2_iface_clk", gcc_sdcc2_ahb_clk.c),
+	CLK_LOOKUP("sdc2_core_clk",  gcc_sdcc2_apps_clk.c),
+
 	CLK_LOOKUP("uart4_iface_clk", gcc_blsp1_ahb_clk.c),
 	CLK_LOOKUP("uart4_core_clk",  gcc_blsp1_uart5_apps_clk.c),
 
diff --git a/project/mpq8092.mk b/project/mpq8092.mk
index be71729..36be395 100644
--- a/project/mpq8092.mk
+++ b/project/mpq8092.mk
@@ -7,7 +7,7 @@
 MODULES += app/aboot
 
 DEBUG := 1
-
+ENABLE_SDHCI_SUPPORT := 1
 #DEFINES += WITH_DEBUG_DCC=1
 DEFINES += WITH_DEBUG_UART=1
 #DEFINES += WITH_DEBUG_FBCON=1
@@ -20,3 +20,7 @@
 DEFINES += ABOOT_FORCE_KERNEL_ADDR=0x00008000
 DEFINES += ABOOT_FORCE_RAMDISK_ADDR=0x02000000
 DEFINES += ABOOT_FORCE_TAGS_ADDR=0x01e00000
+
+ifeq ($(ENABLE_SDHCI_SUPPORT),1)
+DEFINES += MMC_SDHCI_SUPPORT=1
+endif
diff --git a/target/mpq8092/init.c b/target/mpq8092/init.c
index 162322b..92dda35 100644
--- a/target/mpq8092/init.c
+++ b/target/mpq8092/init.c
@@ -41,16 +41,24 @@
 #include <dev/keys.h>
 #include <pm8x41.h>
 #include <platform/gpio.h>
+#include <platform/irqs.h>
 
 #define PMIC_ARB_CHANNEL_NUM    0
 #define PMIC_ARB_OWNER_ID       0
 #define FASTBOOT_MODE           0x77665500
 
-static uint32_t mmc_sdc_base[] =
+static uint32_t mmc_pwrctl_base[] =
 	{ MSM_SDC1_BASE, MSM_SDC2_BASE, MSM_SDC3_BASE, MSM_SDC4_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 };
+
 static void set_sdc_power_ctrl();
 
+struct mmc_device *dev;
 void target_early_init(void)
 {
 #if WITH_DEBUG_UART
@@ -58,14 +66,6 @@
 #endif
 }
 
-void target_mmc_caps(struct mmc_host *host)
-{
-	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;
-}
-
 /* Return 1 if vol_down pressed */
 uint32_t target_volume_down()
 {
@@ -104,6 +104,37 @@
 	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();
+
+	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];
+
+	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);
+		}
+	}
+}
+
+
 /*Turn on DVB tuner regulator required by
  * kernel drivers for probing devices*/
 static void dvb_tuner_enable(void)
@@ -122,31 +153,21 @@
 
 void target_init(void)
 {
-	uint32_t base_addr;
-	uint8_t slot;
-
 	dprintf(INFO, "target_init()\n");
 
 	spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
 
 	target_keystatus();
 
-	set_sdc_power_ctrl();
+	target_sdc_init();
 
-	/* Trying Slot 1*/
-	slot = 1;
-	base_addr = mmc_sdc_base[slot - 1];
-	if (mmc_boot_main(slot, base_addr))
+	/* Storage initialization is complete, read the partition table info */
+	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);
 	}
-	}
+
 	dvb_tuner_enable();
 }
 
@@ -264,3 +285,8 @@
 {
 	return board_baseband();
 }
+
+void *target_mmc_device()
+{
+	return (void *) dev;
+}