diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 0c07781115..70e3c8cf81 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -36,6 +36,15 @@ config DM_MMC_OPS
 
 if MMC
 
+config GENERIC_ATMEL_MCI
+	bool "Atmel Multimedia Card Interface support"
+	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91
+	help
+	  This enables support for Atmel High Speed Multimedia Card Interface
+	  (HSMCI), which supports the MultiMedia Card (MMC) Specification V4.3,
+	  the SD Memory Card Specification V2.0, the SDIO V2.0 specification
+	  and CE-ATA V1.1.
+
 config SPL_MMC_TINY
 	bool "Tiny MMC framework in SPL"
 	help
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index 7dc4a5de74..0ca68c05be 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -10,6 +10,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <mmc.h>
 #include <part.h>
 #include <malloc.h>
@@ -18,8 +19,11 @@
 #include <asm/byteorder.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
+#include <dm/device.h>
 #include "atmel_mci.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #ifndef CONFIG_SYS_MMC_CLK_OD
 # define CONFIG_SYS_MMC_CLK_OD	150000
 #endif
@@ -37,6 +41,10 @@ struct atmel_mci_priv {
 	struct atmel_mci	*mci;
 	unsigned int		initialized:1;
 	unsigned int		curr_clk;
+#ifdef CONFIG_DM_MMC
+	struct mmc	mmc;
+	ulong		bus_clk_rate;
+#endif
 };
 
 /* Read Atmel MCI IP version */
@@ -58,11 +66,19 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
 }
 
 /* Setup for MCI Clock and Block Size */
+#ifdef CONFIG_DM_MMC
+static void mci_set_mode(struct atmel_mci_priv *priv, u32 hz, u32 blklen)
+{
+	struct mmc *mmc = &priv->mmc;
+	u32 bus_hz = priv->bus_clk_rate;
+#else
 static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 {
 	struct atmel_mci_priv *priv = mmc->priv;
-	atmel_mci_t *mci = priv->mci;
 	u32 bus_hz = get_mci_clk_rate();
+#endif
+
+	atmel_mci_t *mci = priv->mci;
 	u32 clkdiv = 255;
 	unsigned int version = atmel_mci_get_version(mci);
 	u32 clkodd = 0;
@@ -202,10 +218,18 @@ io_fail:
  * Sends a command out on the bus and deals with the block data.
  * Takes the mmc pointer, a command pointer, and an optional data pointer.
  */
+#ifdef CONFIG_DM_MMC
+static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+			      struct mmc_data *data)
+{
+	struct atmel_mci_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
 static int
 mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
 	struct atmel_mci_priv *priv = mmc->priv;
+#endif
 	atmel_mci_t *mci = priv->mci;
 	u32 cmdr;
 	u32 error_flags = 0;
@@ -335,17 +359,29 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 	return 0;
 }
 
+#ifdef CONFIG_DM_MMC
+static int atmel_mci_set_ios(struct udevice *dev)
+{
+	struct atmel_mci_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
 /* Entered into mmc structure during driver init */
 static int mci_set_ios(struct mmc *mmc)
 {
 	struct atmel_mci_priv *priv = mmc->priv;
+#endif
+
 	atmel_mci_t *mci = priv->mci;
 	int bus_width = mmc->bus_width;
 	unsigned int version = atmel_mci_get_version(mci);
 	int busw;
 
 	/* Set the clock speed */
+#ifdef CONFIG_DM_MMC
+	mci_set_mode(priv, mmc->clock, MMC_DEFAULT_BLKLEN);
+#else
 	mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
+#endif
 
 	/*
 	 * set the bus width and select slot for this interface
@@ -374,10 +410,17 @@ static int mci_set_ios(struct mmc *mmc)
 	return 0;
 }
 
+
+#ifdef CONFIG_DM_MMC
+static int atmel_mci_hw_init(struct atmel_mci_priv *priv)
+{
+#else
 /* Entered into mmc structure during driver init */
 static int mci_init(struct mmc *mmc)
 {
 	struct atmel_mci_priv *priv = mmc->priv;
+#endif
+
 	atmel_mci_t *mci = priv->mci;
 
 	/* Initialize controller */
@@ -392,11 +435,16 @@ static int mci_init(struct mmc *mmc)
 	writel(~0UL, &mci->idr);
 
 	/* Set default clocks and blocklen */
+#ifdef CONFIG_DM_MMC
+	mci_set_mode(priv, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
+#else
 	mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
+#endif
 
 	return 0;
 }
 
+#ifndef CONFIG_DM_MMC
 static const struct mmc_ops atmel_mci_ops = {
 	.send_cmd	= mci_send_cmd,
 	.set_ios	= mci_set_ios,
@@ -456,3 +504,114 @@ int atmel_mci_init(void *regs)
 
 	return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_MMC
+static const struct dm_mmc_ops atmel_mci_mmc_ops = {
+	.send_cmd = atmel_mci_send_cmd,
+	.set_ios = atmel_mci_set_ios,
+};
+
+static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv)
+{
+	struct mmc_config *cfg;
+	u32 version;
+
+	cfg = &priv->cfg;
+	cfg->name = "Atmel mci";
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	/*
+	 * If the version is above 3.0, the capabilities of the 8-bit
+	 * bus width and high speed are supported.
+	 */
+	version = atmel_mci_get_version(priv->mci);
+	if ((version & 0xf00) >= 0x300) {
+		cfg->host_caps = MMC_MODE_8BIT |
+				 MMC_MODE_HS | MMC_MODE_HS_52MHz;
+	}
+
+	cfg->host_caps |= MMC_MODE_4BIT;
+	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+	cfg->f_min = priv->bus_clk_rate / (2 * 256);
+	cfg->f_max = priv->bus_clk_rate / 2;
+}
+
+static int atmel_mci_enable_clk(struct udevice *dev)
+{
+	struct atmel_mci_priv *priv = dev_get_priv(dev);
+	struct clk clk;
+	ulong clk_rate;
+	int ret = 0;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret) {
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	ret = clk_enable(&clk);
+	if (ret)
+		goto failed;
+
+	clk_rate = clk_get_rate(&clk);
+	if (!clk_rate) {
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	priv->bus_clk_rate = clk_rate;
+
+failed:
+	clk_free(&clk);
+
+	return ret;
+}
+
+static int atmel_mci_probe(struct udevice *dev)
+{
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct atmel_mci_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc;
+	int ret;
+
+	ret = atmel_mci_enable_clk(dev);
+	if (ret)
+		return ret;
+
+	priv->mci = (struct atmel_mci *)dev_get_addr_ptr(dev);
+
+	atmel_mci_setup_cfg(priv);
+
+	mmc = &priv->mmc;
+	mmc->cfg = &priv->cfg;
+	mmc->dev = dev;
+	upriv->mmc = mmc;
+
+	atmel_mci_hw_init(priv);
+
+	return 0;
+}
+
+static int atmel_mci_bind(struct udevice *dev)
+{
+	struct atmel_mci_priv *priv = dev_get_priv(dev);
+
+	return mmc_bind(dev, &priv->mmc, &priv->cfg);
+}
+
+static const struct udevice_id atmel_mci_ids[] = {
+	{ .compatible = "atmel,hsmci" },
+	{ }
+};
+
+U_BOOT_DRIVER(atmel_mci) = {
+	.name = "atmel-mci",
+	.id = UCLASS_MMC,
+	.of_match = atmel_mci_ids,
+	.bind = atmel_mci_bind,
+	.probe = atmel_mci_probe,
+	.priv_auto_alloc_size = sizeof(struct atmel_mci_priv),
+	.ops = &atmel_mci_mmc_ops,
+};
+#endif
