+ cfg->f_min = get_mci_clk_rate() / (2*256);
+ cfg->f_max = get_mci_clk_rate() / (2*1);
+
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ mmc = mmc_create(cfg, priv);
+
+ if (mmc == NULL) {
+ free(priv);
+ return -ENODEV;
+ }
+ /* NOTE: possibly leaking the priv structure */
+
+ 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 udevice *dev)
+{
+ struct atmel_mci_plat *plat = dev_get_platdata(dev);
+ struct atmel_mci_priv *priv = dev_get_priv(dev);
+ struct mmc_config *cfg;
+ u32 version;
+
+ cfg = &plat->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(plat->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_plat *plat = dev_get_platdata(dev);
+ struct mmc *mmc;
+ int ret;
+
+ ret = atmel_mci_enable_clk(dev);
+ if (ret)
+ return ret;
+
+ plat->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev);
+
+ atmel_mci_setup_cfg(dev);