Merge "ipq807x: Removed spi gpio entries from device-tree"
diff --git a/arch/arm/dts/ipq5018-emulation.dts b/arch/arm/dts/ipq5018-emulation.dts
index f3a6a5c..d0b1b05 100644
--- a/arch/arm/dts/ipq5018-emulation.dts
+++ b/arch/arm/dts/ipq5018-emulation.dts
@@ -17,9 +17,15 @@
model ="QCA, IPQ5018-EMULATION";
compatible = "qca,ipq5018", "qca,ipq5018-emulation";
machid = <0x08010000>;
+ config_name = "config@1";
aliases {
console = "/serial@78AF000";
+ mmc = "/sdhci@7804000";
+ };
+
+ mmc: sdhci@7804000 {
+ compatible = "qcom,sdhci-msm";
};
timer {
diff --git a/board/qca/arm/ipq5018/ipq5018.c b/board/qca/arm/ipq5018/ipq5018.c
index dfc827d..90d4ce3 100644
--- a/board/qca/arm/ipq5018/ipq5018.c
+++ b/board/qca/arm/ipq5018/ipq5018.c
@@ -20,9 +20,14 @@
#include <asm/arch-qca-common/qpic_nand.h>
#include <asm/arch-qca-common/gpio.h>
#include <asm/arch-qca-common/uart.h>
+#include <asm/arch-qca-common/scm.h>
+#include <asm/arch-qca-common/iomap.h>
#include <ipq5018.h>
+#include <mmc.h>
+#include <sdhci.h>
DECLARE_GLOBAL_DATA_PTR;
+struct sdhci_host mmc_host;
extern int ipq_spi_init(u16);
void uart1_configure_mux(void)
@@ -124,6 +129,162 @@
qca_gpio_init(node);
}
+/*
+ * Set the uuid in bootargs variable for mounting rootfilesystem
+ */
+#ifdef CONFIG_QCA_MMC
+int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_flag)
+{
+ int ret, len;
+ block_dev_desc_t *blk_dev;
+ disk_partition_t disk_info;
+
+ blk_dev = mmc_get_dev(mmc_host.dev_num);
+ if (!blk_dev) {
+ printf("Invalid block device name\n");
+ return -EINVAL;
+ }
+
+ if (buflen <= 0 || buflen > MAX_BOOT_ARGS_SIZE)
+ return -EINVAL;
+
+#ifdef CONFIG_PARTITION_UUIDS
+ ret = get_partition_info_efi_by_name(blk_dev,
+ part_name, &disk_info);
+ if (ret) {
+ printf("bootipq: unsupported partition name %s\n",part_name);
+ return -EINVAL;
+ }
+ if ((len = strlcpy(boot_args, "root=PARTUUID=", buflen)) >= buflen)
+ return -EINVAL;
+#else
+ if ((len = strlcpy(boot_args, "rootfsname=", buflen)) >= buflen)
+ return -EINVAL;
+#endif
+ boot_args += len;
+ buflen -= len;
+
+#ifdef CONFIG_PARTITION_UUIDS
+ if ((len = strlcpy(boot_args, disk_info.uuid, buflen)) >= buflen)
+ return -EINVAL;
+#else
+ if ((len = strlcpy(boot_args, part_name, buflen)) >= buflen)
+ return -EINVAL;
+#endif
+ boot_args += len;
+ buflen -= len;
+
+ if (gpt_flag && strlcpy(boot_args, " gpt", buflen) >= buflen)
+ return -EINVAL;
+
+ return 0;
+}
+#else
+int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_flag)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_QCA_MMC
+void emmc_clock_config(void)
+{
+ /* Enable root clock generator */
+ writel(readl(GCC_SDCC1_APPS_CBCR)|0x1, GCC_SDCC1_APPS_CBCR);
+ /* Add 10us delay for CLK_OFF to get cleared */
+ udelay(10);
+ writel(readl(GCC_SDCC1_AHB_CBCR)|0x1, GCC_SDCC1_AHB_CBCR);
+ /* PLL0 - 192Mhz */
+ writel(0x20B, GCC_SDCC1_APPS_CFG_RCGR);
+ /* Delay for clock operation complete */
+ udelay(10);
+ writel(0x1, GCC_SDCC1_APPS_M);
+ writel(0xFC, GCC_SDCC1_APPS_N);
+ writel(0xFD, GCC_SDCC1_APPS_D);
+ /* Delay for clock operation complete */
+ udelay(10);
+ /* Update APPS_CMD_RCGR to reflect source selection */
+ writel(readl(GCC_SDCC1_APPS_CMD_RCGR)|0x1, GCC_SDCC1_APPS_CMD_RCGR);
+ /* Add 10us delay for clock update to complete */
+ udelay(10);
+}
+
+void mmc_iopad_config(struct sdhci_host *host)
+{
+ u32 val;
+ val = sdhci_readb(host, SDHCI_VENDOR_IOPAD);
+ /*set bit 15 & 16*/
+ val |= 0x18000;
+ writel(val, host->ioaddr + SDHCI_VENDOR_IOPAD);
+}
+
+void sdhci_bus_pwr_off(struct sdhci_host *host)
+{
+ u32 val;
+
+ val = sdhci_readb(host, SDHCI_HOST_CONTROL);
+ sdhci_writeb(host,(val & (~SDHCI_POWER_ON)), SDHCI_POWER_CONTROL);
+}
+
+void emmc_clock_disable(void)
+{
+ /* Clear divider */
+ writel(0x0, GCC_SDCC1_MISC);
+}
+
+void board_mmc_deinit(void)
+{
+ emmc_clock_disable();
+}
+
+void emmc_clock_reset(void)
+{
+ writel(0x1, GCC_SDCC1_BCR);
+ udelay(10);
+ writel(0x0, GCC_SDCC1_BCR);
+}
+
+int board_mmc_init(bd_t *bis)
+{
+ int node;
+ int ret = 0;
+ qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
+
+ node = fdt_path_offset(gd->fdt_blob, "mmc");
+ if (node < 0) {
+ printf("sdhci: Node Not found, skipping initialization\n");
+ return -1;
+ }
+
+ mmc_host.ioaddr = (void *)MSM_SDC1_SDHCI_BASE;
+ mmc_host.voltages = MMC_VDD_165_195;
+ mmc_host.version = SDHCI_SPEC_300;
+ mmc_host.cfg.part_type = PART_TYPE_EFI;
+ mmc_host.quirks = SDHCI_QUIRK_BROKEN_VOLTAGE;
+
+ emmc_clock_disable();
+ emmc_clock_reset();
+ udelay(10);
+ emmc_clock_config();
+
+ if (add_sdhci(&mmc_host, 200000000, 400000)) {
+ printf("add_sdhci fail!\n");
+ return -1;
+ }
+
+ if (!ret && sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
+ ret = board_mmc_env_init(mmc_host);
+ }
+
+ return ret;
+}
+#else
+int board_mmc_init(bd_t *bis)
+{
+ return 0;
+}
+#endif
+
void reset_crashdump(void)
{
return;
@@ -160,13 +321,6 @@
icache_disable();
dcache_disable();
}
-/**
- * * Set the uuid in bootargs variable for mounting rootfilesystem
- */
-int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_flag)
-{
- return 0;
-}
unsigned long timer_read_counter(void)
{
diff --git a/board/qca/arm/ipq5018/ipq5018.h b/board/qca/arm/ipq5018/ipq5018.h
index 581cd71..a220312 100644
--- a/board/qca/arm/ipq5018/ipq5018.h
+++ b/board/qca/arm/ipq5018/ipq5018.h
@@ -18,6 +18,23 @@
#include <asm/u-boot.h>
#include <asm/arch-qca-common/qca_common.h>
+#define MSM_SDC1_BASE 0x7800000
+#define MSM_SDC1_SDHCI_BASE 0x7804000
+
+/*
+ * GCC-SDCC Registers
+ */
+
+#define GCC_SDCC1_BCR 0x01842000
+#define GCC_SDCC1_APPS_CMD_RCGR 0x01842004
+#define GCC_SDCC1_APPS_CFG_RCGR 0x01842008
+#define GCC_SDCC1_APPS_M 0x0184200C
+#define GCC_SDCC1_APPS_N 0x01842010
+#define GCC_SDCC1_APPS_D 0x01842014
+#define GCC_SDCC1_APPS_CBCR 0x01842018
+#define GCC_SDCC1_AHB_CBCR 0x0184201C
+#define GCC_SDCC1_MISC 0x01842020
+
/* UART 1 */
#define GCC_BLSP1_UART1_BCR 0x01802038
#define GCC_BLSP1_UART1_APPS_CBCR 0x0180203C
diff --git a/configs/ipq5018_defconfig b/configs/ipq5018_defconfig
index 89bf236..d0fe426 100644
--- a/configs/ipq5018_defconfig
+++ b/configs/ipq5018_defconfig
@@ -101,6 +101,8 @@
#
# CONFIG_CMD_TIME is not set
CONFIG_CMD_MISC=y
+CONFIG_CMD_PART=y
+CONFIG_PARTITION_UUIDS=y
# CONFIG_CMD_TIMER is not set
#
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index b1fcd92..a3ec813 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -672,8 +672,11 @@
if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
host->cfg.voltages |= host->voltages;
-
- host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_8BIT;
+#ifdef CONFIG_MMC_FORCE_CAP_4BIT_BUSWIDTH
+ host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
+#else
+ host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_8BIT;
+#endif
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
if (caps & SDHCI_CAN_DO_8BIT)
host->cfg.host_caps |= MMC_MODE_8BIT;
diff --git a/include/configs/ipq5018.h b/include/configs/ipq5018.h
index 32b9b84..e9a893e 100644
--- a/include/configs/ipq5018.h
+++ b/include/configs/ipq5018.h
@@ -152,6 +152,29 @@
#define CONFIG_QUP_SPI_USE_DMA 1
#define CONFIG_EFI_PARTITION
#define CONFIG_QCA_BAM 1
+
+/*
+ * MMC configs
+ */
+#define CONFIG_QCA_MMC
+
+#ifdef CONFIG_QCA_MMC
+#define CONFIG_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_SDHCI
+#define CONFIG_SDHCI_QCA
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_SDHCI_SUPPORT
+#define CONFIG_MMC_ADMA
+/*
+* eMMC controller support only 4-bit
+* force SDHC driver to 4-bit mode
+*/
+#define CONFIG_MMC_FORCE_CAP_4BIT_BUSWIDTH
+#endif
+
/*
* Expose SPI driver as a pseudo NAND driver to make use
* of U-Boot's MTD framework.