diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index e793ed9..931922b 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
 obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
 obj-$(CONFIG_SDHCI) += sdhci.o
 obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o
+obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o
 obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
 obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o
diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c
new file mode 100644
index 0000000..77e42c8
--- /dev/null
+++ b/drivers/mmc/kona_sdhci.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <sdhci.h>
+#include <asm/errno.h>
+#include <asm/kona-common/clk.h>
+
+#define SDHCI_CORECTRL_OFFSET		0x00008000
+#define SDHCI_CORECTRL_EN		0x01
+#define SDHCI_CORECTRL_RESET		0x02
+
+#define SDHCI_CORESTAT_OFFSET		0x00008004
+#define SDHCI_CORESTAT_CD_SW		0x01
+
+#define SDHCI_COREIMR_OFFSET		0x00008008
+#define SDHCI_COREIMR_IP		0x01
+
+static int init_kona_mmc_core(struct sdhci_host *host)
+{
+	unsigned int mask;
+	unsigned int timeout;
+
+	if (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) {
+		printf("%s: sd host controller reset error\n", __func__);
+		return 1;
+	}
+
+	/* For kona a hardware reset before anything else. */
+	mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET) | SDHCI_CORECTRL_RESET;
+	sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);
+
+	/* Wait max 100 ms */
+	timeout = 1000;
+	do {
+		if (timeout == 0) {
+			printf("%s: reset timeout error\n", __func__);
+			return 1;
+		}
+		timeout--;
+		udelay(100);
+	} while (0 ==
+		 (sdhci_readl(host, SDHCI_CORECTRL_OFFSET) &
+		  SDHCI_CORECTRL_RESET));
+
+	/* Clear the reset bit. */
+	mask = mask & ~SDHCI_CORECTRL_RESET;
+	sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);
+
+	/* Enable AHB clock */
+	mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET);
+	sdhci_writel(host, mask | SDHCI_CORECTRL_EN, SDHCI_CORECTRL_OFFSET);
+
+	/* Enable interrupts */
+	sdhci_writel(host, SDHCI_COREIMR_IP, SDHCI_COREIMR_OFFSET);
+
+	/* Make sure Card is detected in controller */
+	mask = sdhci_readl(host, SDHCI_CORESTAT_OFFSET);
+	sdhci_writel(host, mask | SDHCI_CORESTAT_CD_SW, SDHCI_CORESTAT_OFFSET);
+
+	/* Wait max 100 ms */
+	timeout = 1000;
+	while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
+		if (timeout == 0) {
+			printf("%s: CARD DETECT timeout error\n", __func__);
+			return 1;
+		}
+		timeout--;
+		udelay(100);
+	}
+	return 0;
+}
+
+int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks)
+{
+	int ret = 0;
+	u32 max_clk;
+	void *reg_base;
+	struct sdhci_host *host = NULL;
+
+	host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
+	if (!host) {
+		printf("%s: sdhci host malloc fail!\n", __func__);
+		return -ENOMEM;
+	}
+	switch (dev_index) {
+	case 0:
+		reg_base = (void *)CONFIG_SYS_SDIO_BASE0;
+		ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO0_MAX_CLK,
+				      &max_clk);
+		break;
+	case 1:
+		reg_base = (void *)CONFIG_SYS_SDIO_BASE1;
+		ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO1_MAX_CLK,
+				      &max_clk);
+		break;
+	case 2:
+		reg_base = (void *)CONFIG_SYS_SDIO_BASE2;
+		ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO2_MAX_CLK,
+				      &max_clk);
+		break;
+	case 3:
+		reg_base = (void *)CONFIG_SYS_SDIO_BASE3;
+		ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO3_MAX_CLK,
+				      &max_clk);
+		break;
+	default:
+		printf("%s: sdio dev index %d not supported\n",
+		       __func__, dev_index);
+		ret = -EINVAL;
+	}
+	if (ret)
+		return ret;
+
+	host->name = "kona-sdhci";
+	host->ioaddr = reg_base;
+	host->quirks = quirks;
+	host->host_caps = MMC_MODE_HC;
+
+	if (init_kona_mmc_core(host))
+		return -EINVAL;
+
+	if (quirks & SDHCI_QUIRK_REG32_RW)
+		host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
+	else
+		host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+
+	add_sdhci(host, max_clk, min_clk);
+	return ret;
+}
