summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/Kconfig11
-rw-r--r--drivers/mmc/Makefile3
-rw-r--r--drivers/mmc/dw_mmc.c33
-rw-r--r--drivers/mmc/mmc-uclass.c146
-rw-r--r--drivers/mmc/mmc.c371
-rw-r--r--drivers/mmc/mmc_boot.c131
-rw-r--r--drivers/mmc/mmc_legacy.c91
-rw-r--r--drivers/mmc/mmc_private.h47
-rw-r--r--drivers/mmc/msm_sdhci.c35
-rw-r--r--drivers/mmc/rockchip_dw_mmc.c73
-rw-r--r--drivers/mmc/sandbox_mmc.c17
-rw-r--r--drivers/mmc/sdhci.c147
12 files changed, 689 insertions, 416 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c80efc3..79cf18f 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -16,9 +16,18 @@ config DM_MMC
appear as block devices in U-Boot and can support filesystems such
as EXT4 and FAT.
+config DM_MMC_OPS
+ bool "Support MMC controller operations using Driver Model"
+ depends on DM_MMC
+ help
+ Driver model provides a means of supporting device operations. This
+ option moves MMC operations under the control of driver model. The
+ option will be removed as soon as all DM_MMC drivers use it, as it
+ will the only supported behaviour.
+
config MSM_SDHCI
bool "Qualcomm SDHCI controller"
- depends on DM_MMC
+ depends on DM_MMC && BLK && DM_MMC_OPS
help
Enables support for SDHCI 2.0 controller present on some Qualcomm
Snapdragon devices. This device is compatible with eMMC v4.5 and
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 3da4817..b44a12e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -25,6 +25,9 @@ obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o
obj-$(CONFIG_FTSDC021) += ftsdc021_sdhci.o
obj-$(CONFIG_GENERIC_MMC) += mmc.o
+ifdef CONFIG_SUPPORT_EMMC_BOOT
+obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
+endif
obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o
obj-$(CONFIG_MMC_SPI) += mmc_spi.o
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index af6e04a..2cf7bae 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -181,9 +181,16 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host,
return mode;
}
+#ifdef CONFIG_DM_MMC_OPS
+int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
+#endif
struct dwmci_host *host = mmc->priv;
ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
data ? DIV_ROUND_UP(data->blocks, 8) : 0);
@@ -373,8 +380,14 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
return 0;
}
+#ifdef CONFIG_DM_MMC_OPS
+int dwmci_set_ios(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
static void dwmci_set_ios(struct mmc *mmc)
{
+#endif
struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
u32 ctype, regs;
@@ -405,6 +418,9 @@ static void dwmci_set_ios(struct mmc *mmc)
if (host->clksel)
host->clksel(host);
+#ifdef CONFIG_DM_MMC_OPS
+ return 0;
+#endif
}
static int dwmci_init(struct mmc *mmc)
@@ -448,17 +464,34 @@ static int dwmci_init(struct mmc *mmc)
return 0;
}
+#ifdef CONFIG_DM_MMC_OPS
+int dwmci_probe(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return dwmci_init(mmc);
+}
+
+const struct dm_mmc_ops dm_dwmci_ops = {
+ .send_cmd = dwmci_send_cmd,
+ .set_ios = dwmci_set_ios,
+};
+
+#else
static const struct mmc_ops dwmci_ops = {
.send_cmd = dwmci_send_cmd,
.set_ios = dwmci_set_ios,
.init = dwmci_init,
};
+#endif
void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
uint caps, u32 max_clk, u32 min_clk)
{
cfg->name = name;
+#ifndef CONFIG_DM_MMC_OPS
cfg->ops = &dwmci_ops;
+#endif
cfg->f_min = min_clk;
cfg->f_max = max_clk;
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 1b967d9..38ced41 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -8,8 +8,76 @@
#include <common.h>
#include <mmc.h>
#include <dm.h>
+#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/root.h>
+#include "mmc_private.h"
+
+#ifdef CONFIG_DM_MMC_OPS
+int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+ int ret;
+
+ mmmc_trace_before_send(mmc, cmd);
+ if (ops->send_cmd)
+ ret = ops->send_cmd(dev, cmd, data);
+ else
+ ret = -ENOSYS;
+ mmmc_trace_after_send(mmc, cmd, ret);
+
+ return ret;
+}
+
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+ return dm_mmc_send_cmd(mmc->dev, cmd, data);
+}
+
+int dm_mmc_set_ios(struct udevice *dev)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+ if (!ops->set_ios)
+ return -ENOSYS;
+ return ops->set_ios(dev);
+}
+
+int mmc_set_ios(struct mmc *mmc)
+{
+ return dm_mmc_set_ios(mmc->dev);
+}
+
+int dm_mmc_get_wp(struct udevice *dev)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+ if (!ops->get_wp)
+ return -ENOSYS;
+ return ops->get_wp(dev);
+}
+
+int mmc_getwp(struct mmc *mmc)
+{
+ return dm_mmc_get_wp(mmc->dev);
+}
+
+int dm_mmc_get_cd(struct udevice *dev)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+ if (!ops->get_cd)
+ return -ENOSYS;
+ return ops->get_cd(dev);
+}
+
+int mmc_getcd(struct mmc *mmc)
+{
+ return dm_mmc_get_cd(mmc->dev);
+}
+#endif
struct mmc *mmc_get_mmc_dev(struct udevice *dev)
{
@@ -125,6 +193,84 @@ void print_mmc_devices(char separator)
#else
void print_mmc_devices(char separator) { }
#endif
+
+int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
+{
+ struct blk_desc *bdesc;
+ struct udevice *bdev;
+ int ret;
+
+ ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
+ 0, &bdev);
+ if (ret) {
+ debug("Cannot create block device\n");
+ return ret;
+ }
+ bdesc = dev_get_uclass_platdata(bdev);
+ mmc->cfg = cfg;
+ mmc->priv = dev;
+
+ /* the following chunk was from mmc_register() */
+
+ /* Setup dsr related values */
+ mmc->dsr_imp = 0;
+ mmc->dsr = 0xffffffff;
+ /* Setup the universal parts of the block interface just once */
+ bdesc->removable = 1;
+
+ /* setup initial part type */
+ bdesc->part_type = cfg->part_type;
+ mmc->dev = dev;
+
+ return 0;
+}
+
+int mmc_unbind(struct udevice *dev)
+{
+ struct udevice *bdev;
+
+ device_find_first_child(dev, &bdev);
+ if (bdev) {
+ device_remove(bdev);
+ device_unbind(bdev);
+ }
+
+ return 0;
+}
+
+static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
+{
+ struct udevice *mmc_dev = dev_get_parent(bdev);
+ struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
+ struct blk_desc *desc = dev_get_uclass_platdata(bdev);
+ int ret;
+
+ if (desc->hwpart == hwpart)
+ return 0;
+
+ if (mmc->part_config == MMCPART_NOAVAILABLE)
+ return -EMEDIUMTYPE;
+
+ ret = mmc_switch_part(mmc, hwpart);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct blk_ops mmc_blk_ops = {
+ .read = mmc_bread,
+#ifndef CONFIG_SPL_BUILD
+ .write = mmc_bwrite,
+#endif
+ .select_hwpart = mmc_select_hwpart,
+};
+
+U_BOOT_DRIVER(mmc_blk) = {
+ .name = "mmc_blk",
+ .id = UCLASS_BLK,
+ .ops = &mmc_blk_ops,
+};
#endif /* CONFIG_BLK */
U_BOOT_DRIVER(mmc) = {
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index aabfc71..f8e5f7a 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -21,6 +21,7 @@
#include <div64.h>
#include "mmc_private.h"
+#ifndef CONFIG_DM_MMC_OPS
__weak int board_mmc_getwp(struct mmc *mmc)
{
return -1;
@@ -46,18 +47,20 @@ __weak int board_mmc_getcd(struct mmc *mmc)
{
return -1;
}
+#endif
-int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
{
- int ret;
+ printf("CMD_SEND:%d\n", cmd->cmdidx);
+ printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
+}
-#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
+{
int i;
u8 *ptr;
- printf("CMD_SEND:%d\n", cmd->cmdidx);
- printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
- ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
if (ret) {
printf("\t\tRET\t\t\t %d\n", ret);
} else {
@@ -103,19 +106,34 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
break;
}
}
-#else
- ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
+}
+
+void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+ int status;
+
+ status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9;
+ printf("CURR STATE:%d\n", status);
+}
#endif
+
+#ifndef CONFIG_DM_MMC_OPS
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+ int ret;
+
+ mmmc_trace_before_send(mmc, cmd);
+ ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
+ mmmc_trace_after_send(mmc, cmd, ret);
+
return ret;
}
+#endif
int mmc_send_status(struct mmc *mmc, int timeout)
{
struct mmc_cmd cmd;
int err, retries = 5;
-#ifdef CONFIG_MMC_TRACE
- int status;
-#endif
cmd.cmdidx = MMC_CMD_SEND_STATUS;
cmd.resp_type = MMC_RSP_R1;
@@ -145,10 +163,7 @@ int mmc_send_status(struct mmc *mmc, int timeout)
udelay(1000);
}
-#ifdef CONFIG_MMC_TRACE
- status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
- printf("CURR STATE:%d\n", status);
-#endif
+ mmc_trace_state(mmc, &cmd);
if (timeout <= 0) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("Timeout waiting card ready\n");
@@ -215,11 +230,10 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
}
#ifdef CONFIG_BLK
-static ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
- void *dst)
+ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
#else
-static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start,
- lbaint_t blkcnt, void *dst)
+ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
+ void *dst)
#endif
{
#ifdef CONFIG_BLK
@@ -464,8 +478,7 @@ static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
return err;
}
-
-static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
+int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
{
struct mmc_cmd cmd;
int timeout = 1000;
@@ -566,7 +579,7 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num)
return 0;
}
-static int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
+int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
{
int ret;
@@ -586,49 +599,6 @@ static int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
return ret;
}
-#ifdef CONFIG_BLK
-static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
-{
- struct udevice *mmc_dev = dev_get_parent(bdev);
- struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
- struct blk_desc *desc = dev_get_uclass_platdata(bdev);
- int ret;
-
- if (desc->hwpart == hwpart)
- return 0;
-
- if (mmc->part_config == MMCPART_NOAVAILABLE)
- return -EMEDIUMTYPE;
-
- ret = mmc_switch_part(mmc, hwpart);
- if (ret)
- return ret;
-
- return 0;
-}
-#else
-static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
-{
- struct mmc *mmc = find_mmc_device(desc->devnum);
- int ret;
-
- if (!mmc)
- return -ENODEV;
-
- if (mmc->block_dev.hwpart == hwpart)
- return 0;
-
- if (mmc->part_config == MMCPART_NOAVAILABLE)
- return -EMEDIUMTYPE;
-
- ret = mmc_switch_part(mmc, hwpart);
- if (ret)
- return ret;
-
- return 0;
-}
-#endif
-
int mmc_hwpart_config(struct mmc *mmc,
const struct mmc_hwpart_conf *conf,
enum mmc_hwpart_conf_mode mode)
@@ -823,6 +793,7 @@ int mmc_hwpart_config(struct mmc *mmc,
return 0;
}
+#ifndef CONFIG_DM_MMC_OPS
int mmc_getcd(struct mmc *mmc)
{
int cd;
@@ -838,6 +809,7 @@ int mmc_getcd(struct mmc *mmc)
return cd;
}
+#endif
static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
{
@@ -1001,11 +973,13 @@ static const u8 multipliers[] = {
80,
};
+#ifndef CONFIG_DM_MMC_OPS
static void mmc_set_ios(struct mmc *mmc)
{
if (mmc->cfg->ops->set_ios)
mmc->cfg->ops->set_ios(mmc);
}
+#endif
void mmc_set_clock(struct mmc *mmc, uint clock)
{
@@ -1532,115 +1506,6 @@ static int mmc_send_if_cond(struct mmc *mmc)
return 0;
}
-#ifdef CONFIG_BLK
-int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
-{
- struct blk_desc *bdesc;
- struct udevice *bdev;
- int ret;
-
- ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
- 0, &bdev);
- if (ret) {
- debug("Cannot create block device\n");
- return ret;
- }
- bdesc = dev_get_uclass_platdata(bdev);
- mmc->cfg = cfg;
- mmc->priv = dev;
-
- /* the following chunk was from mmc_register() */
-
- /* Setup dsr related values */
- mmc->dsr_imp = 0;
- mmc->dsr = 0xffffffff;
- /* Setup the universal parts of the block interface just once */
- bdesc->removable = 1;
-
- /* setup initial part type */
- bdesc->part_type = cfg->part_type;
- mmc->dev = dev;
-
- return 0;
-}
-
-int mmc_unbind(struct udevice *dev)
-{
- struct udevice *bdev;
-
- device_find_first_child(dev, &bdev);
- if (bdev) {
- device_remove(bdev);
- device_unbind(bdev);
- }
-
- return 0;
-}
-
-#else
-struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
-{
- struct blk_desc *bdesc;
- struct mmc *mmc;
-
- /* quick validation */
- if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL ||
- cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0)
- return NULL;
-
- mmc = calloc(1, sizeof(*mmc));
- if (mmc == NULL)
- return NULL;
-
- mmc->cfg = cfg;
- mmc->priv = priv;
-
- /* the following chunk was mmc_register() */
-
- /* Setup dsr related values */
- mmc->dsr_imp = 0;
- mmc->dsr = 0xffffffff;
- /* Setup the universal parts of the block interface just once */
- bdesc = mmc_get_blk_desc(mmc);
- bdesc->if_type = IF_TYPE_MMC;
- bdesc->removable = 1;
- bdesc->devnum = mmc_get_next_devnum();
- bdesc->block_read = mmc_bread;
- bdesc->block_write = mmc_bwrite;
- bdesc->block_erase = mmc_berase;
-
- /* setup initial part type */
- bdesc->part_type = mmc->cfg->part_type;
- mmc_list_add(mmc);
-
- return mmc;
-}
-
-void mmc_destroy(struct mmc *mmc)
-{
- /* only freeing memory for now */
- free(mmc);
-}
-#endif
-
-#ifndef CONFIG_BLK
-static int mmc_get_dev(int dev, struct blk_desc **descp)
-{
- struct mmc *mmc = find_mmc_device(dev);
- int ret;
-
- if (!mmc)
- return -ENODEV;
- ret = mmc_init(mmc);
- if (ret)
- return ret;
-
- *descp = &mmc->block_dev;
-
- return 0;
-}
-#endif
-
/* board-specific MMC power initializations. */
__weak void board_mmc_power_init(void)
{
@@ -1648,10 +1513,15 @@ __weak void board_mmc_power_init(void)
int mmc_start_init(struct mmc *mmc)
{
+ bool no_card;
int err;
/* we pretend there's no card when init is NULL */
- if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) {
+ no_card = mmc_getcd(mmc) == 0;
+#ifndef CONFIG_DM_MMC_OPS
+ no_card = no_card || (mmc->cfg->ops->init == NULL);
+#endif
+ if (no_card) {
mmc->has_init = 0;
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC: no card present\n");
@@ -1667,12 +1537,14 @@ int mmc_start_init(struct mmc *mmc)
#endif
board_mmc_power_init();
+#ifdef CONFIG_DM_MMC_OPS
+ /* The device has already been probed ready for use */
+#else
/* made sure it's not NULL earlier */
err = mmc->cfg->ops->init(mmc);
-
if (err)
return err;
-
+#endif
mmc->ddr_mode = 0;
mmc_set_bus_width(mmc, 1);
mmc_set_clock(mmc, 1);
@@ -1839,148 +1711,3 @@ int mmc_initialize(bd_t *bis)
mmc_do_preinit();
return 0;
}
-
-#ifdef CONFIG_SUPPORT_EMMC_BOOT
-/*
- * This function changes the size of boot partition and the size of rpmb
- * partition present on EMMC devices.
- *
- * Input Parameters:
- * struct *mmc: pointer for the mmc device strcuture
- * bootsize: size of boot partition
- * rpmbsize: size of rpmb partition
- *
- * Returns 0 on success.
- */
-
-int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
- unsigned long rpmbsize)
-{
- int err;
- struct mmc_cmd cmd;
-
- /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
- cmd.cmdidx = MMC_CMD_RES_MAN;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = MMC_CMD62_ARG1;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
- return err;
- }
-
- /* Boot partition changing mode */
- cmd.cmdidx = MMC_CMD_RES_MAN;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = MMC_CMD62_ARG2;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
- return err;
- }
- /* boot partition size is multiple of 128KB */
- bootsize = (bootsize * 1024) / 128;
-
- /* Arg: boot partition size */
- cmd.cmdidx = MMC_CMD_RES_MAN;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = bootsize;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
- return err;
- }
- /* RPMB partition size is multiple of 128KB */
- rpmbsize = (rpmbsize * 1024) / 128;
- /* Arg: RPMB partition size */
- cmd.cmdidx = MMC_CMD_RES_MAN;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = rpmbsize;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
- return err;
- }
- return 0;
-}
-
-/*
- * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
- * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
- * and BOOT_MODE.
- *
- * Returns 0 on success.
- */
-int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
-{
- int err;
-
- err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
- EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
- EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
- EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
-
- if (err)
- return err;
- return 0;
-}
-
-/*
- * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
- * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
- * PARTITION_ACCESS.
- *
- * Returns 0 on success.
- */
-int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
-{
- int err;
-
- err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
- EXT_CSD_BOOT_ACK(ack) |
- EXT_CSD_BOOT_PART_NUM(part_num) |
- EXT_CSD_PARTITION_ACCESS(access));
-
- if (err)
- return err;
- return 0;
-}
-
-/*
- * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
- * for enable. Note that this is a write-once field for non-zero values.
- *
- * Returns 0 on success.
- */
-int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
-{
- return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
- enable);
-}
-#endif
-
-#ifdef CONFIG_BLK
-static const struct blk_ops mmc_blk_ops = {
- .read = mmc_bread,
- .write = mmc_bwrite,
- .select_hwpart = mmc_select_hwpart,
-};
-
-U_BOOT_DRIVER(mmc_blk) = {
- .name = "mmc_blk",
- .id = UCLASS_BLK,
- .ops = &mmc_blk_ops,
-};
-#else
-U_BOOT_LEGACY_BLK(mmc) = {
- .if_typename = "mmc",
- .if_type = IF_TYPE_MMC,
- .max_devs = -1,
- .get_dev = mmc_get_dev,
- .select_hwpart = mmc_select_hwpartp,
-};
-#endif
diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c
new file mode 100644
index 0000000..756a982
--- /dev/null
+++ b/drivers/mmc/mmc_boot.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Amar <amarendra.xt@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include "mmc_private.h"
+
+/*
+ * This function changes the size of boot partition and the size of rpmb
+ * partition present on EMMC devices.
+ *
+ * Input Parameters:
+ * struct *mmc: pointer for the mmc device strcuture
+ * bootsize: size of boot partition
+ * rpmbsize: size of rpmb partition
+ *
+ * Returns 0 on success.
+ */
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+ unsigned long rpmbsize)
+{
+ int err;
+ struct mmc_cmd cmd;
+
+ /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = MMC_CMD62_ARG1;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
+ return err;
+ }
+
+ /* Boot partition changing mode */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = MMC_CMD62_ARG2;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
+ return err;
+ }
+ /* boot partition size is multiple of 128KB */
+ bootsize = (bootsize * 1024) / 128;
+
+ /* Arg: boot partition size */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = bootsize;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
+ return err;
+ }
+ /* RPMB partition size is multiple of 128KB */
+ rpmbsize = (rpmbsize * 1024) / 128;
+ /* Arg: RPMB partition size */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = rpmbsize;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
+ * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
+ * and BOOT_MODE.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
+{
+ int err;
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
+ EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
+ EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
+ EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
+
+ if (err)
+ return err;
+ return 0;
+}
+
+/*
+ * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
+ * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
+ * PARTITION_ACCESS.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+ int err;
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+ EXT_CSD_BOOT_ACK(ack) |
+ EXT_CSD_BOOT_PART_NUM(part_num) |
+ EXT_CSD_PARTITION_ACCESS(access));
+
+ if (err)
+ return err;
+ return 0;
+}
+
+/*
+ * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
+ * for enable. Note that this is a write-once field for non-zero values.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
+{
+ return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
+ enable);
+}
diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c
index 3ec649f..040728b 100644
--- a/drivers/mmc/mmc_legacy.c
+++ b/drivers/mmc/mmc_legacy.c
@@ -6,7 +6,9 @@
*/
#include <common.h>
+#include <malloc.h>
#include <mmc.h>
+#include "mmc_private.h"
static struct list_head mmc_devices;
static int cur_dev_num = -1;
@@ -106,3 +108,92 @@ void print_mmc_devices(char separator)
#else
void print_mmc_devices(char separator) { }
#endif
+
+struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
+{
+ struct blk_desc *bdesc;
+ struct mmc *mmc;
+
+ /* quick validation */
+ if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL ||
+ cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0)
+ return NULL;
+
+ mmc = calloc(1, sizeof(*mmc));
+ if (mmc == NULL)
+ return NULL;
+
+ mmc->cfg = cfg;
+ mmc->priv = priv;
+
+ /* the following chunk was mmc_register() */
+
+ /* Setup dsr related values */
+ mmc->dsr_imp = 0;
+ mmc->dsr = 0xffffffff;
+ /* Setup the universal parts of the block interface just once */
+ bdesc = mmc_get_blk_desc(mmc);
+ bdesc->if_type = IF_TYPE_MMC;
+ bdesc->removable = 1;
+ bdesc->devnum = mmc_get_next_devnum();
+ bdesc->block_read = mmc_bread;
+ bdesc->block_write = mmc_bwrite;
+ bdesc->block_erase = mmc_berase;
+
+ /* setup initial part type */
+ bdesc->part_type = mmc->cfg->part_type;
+ mmc_list_add(mmc);
+
+ return mmc;
+}
+
+void mmc_destroy(struct mmc *mmc)
+{
+ /* only freeing memory for now */
+ free(mmc);
+}
+
+static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
+{
+ struct mmc *mmc = find_mmc_device(desc->devnum);
+ int ret;
+
+ if (!mmc)
+ return -ENODEV;
+
+ if (mmc->block_dev.hwpart == hwpart)
+ return 0;
+
+ if (mmc->part_config == MMCPART_NOAVAILABLE)
+ return -EMEDIUMTYPE;
+
+ ret = mmc_switch_part(mmc, hwpart);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_get_dev(int dev, struct blk_desc **descp)
+{
+ struct mmc *mmc = find_mmc_device(dev);
+ int ret;
+
+ if (!mmc)
+ return -ENODEV;
+ ret = mmc_init(mmc);
+ if (ret)
+ return ret;
+
+ *descp = &mmc->block_dev;
+
+ return 0;
+}
+
+U_BOOT_LEGACY_BLK(mmc) = {
+ .if_typename = "mmc",
+ .if_type = IF_TYPE_MMC,
+ .max_devs = -1,
+ .get_dev = mmc_get_dev,
+ .select_hwpart = mmc_select_hwpartp,
+};
diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
index 9f0d5c2..49ec022 100644
--- a/drivers/mmc/mmc_private.h
+++ b/drivers/mmc/mmc_private.h
@@ -20,6 +20,14 @@ extern int mmc_set_blocklen(struct mmc *mmc, int len);
void mmc_adapter_card_type_ident(void);
#endif
+#ifdef CONFIG_BLK
+ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
+ void *dst);
+#else
+ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
+ void *dst);
+#endif
+
#ifndef CONFIG_SPL_BUILD
unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start,
@@ -65,6 +73,25 @@ static inline ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start,
#endif /* CONFIG_SPL_BUILD */
+#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd);
+void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret);
+void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd);
+#else
+static inline void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+}
+
+static inline void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd,
+ int ret)
+{
+}
+
+static inline void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+}
+#endif
+
/**
* mmc_get_next_devnum() - Get the next available MMC device number
*
@@ -89,4 +116,24 @@ void mmc_list_init(void);
*/
void mmc_list_add(struct mmc *mmc);
+/**
+ * mmc_switch_part() - Switch to a new MMC hardware partition
+ *
+ * @mmc: MMC device
+ * @part_num: Hardware partition number
+ * @return 0 if OK, -ve on error
+ */
+int mmc_switch_part(struct mmc *mmc, unsigned int part_num);
+
+/**
+ * mmc_switch() - Issue and MMC switch mode command
+ *
+ * @mmc: MMC device
+ * @set: Unused
+ * @index: Cmdarg index
+ * @value: Cmdarg value
+ * @return 0 if OK, -ve on error
+ */
+int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value);
+
#endif /* _MMC_PRIVATE_H_ */
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 96dcdbe..70a8d96 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -36,6 +36,11 @@
/* Non standard (?) SDHCI register */
#define SDHCI_VENDOR_SPEC_CAPABILITIES0 0x11c
+struct msm_sdhc_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
struct msm_sdhc {
struct sdhci_host host;
void *base;
@@ -81,9 +86,12 @@ static int msm_sdc_clk_init(struct udevice *dev)
static int msm_sdc_probe(struct udevice *dev)
{
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct msm_sdhc_plat *plat = dev_get_platdata(dev);
struct msm_sdhc *prv = dev_get_priv(dev);
struct sdhci_host *host = &prv->host;
u32 core_version, core_minor, core_major;
+ u32 caps;
int ret;
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
@@ -127,7 +135,7 @@ static int msm_sdc_probe(struct udevice *dev)
* controller versions and must be explicitly enabled.
*/
if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
- u32 caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
+ caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0);
}
@@ -135,13 +143,17 @@ static int msm_sdc_probe(struct udevice *dev)
/* Set host controller version */
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
- /* automatically detect max and min speed */
- ret = add_sdhci(host, 0, 0);
+ caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ ret = sdhci_setup_cfg(&plat->cfg, dev->name, host->bus_width,
+ caps, 0, 0, host->version, host->quirks, 0);
+ host->mmc = &plat->mmc;
if (ret)
return ret;
+ host->mmc->priv = &prv->host;
host->mmc->dev = dev;
+ upriv->mmc = host->mmc;
- return 0;
+ return sdhci_probe(dev);
}
static int msm_sdc_remove(struct udevice *dev)
@@ -176,6 +188,18 @@ static int msm_ofdata_to_platdata(struct udevice *dev)
return 0;
}
+static int msm_sdc_bind(struct udevice *dev)
+{
+ struct msm_sdhc_plat *plat = dev_get_platdata(dev);
+ int ret;
+
+ ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static const struct udevice_id msm_mmc_ids[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{ }
@@ -186,7 +210,10 @@ U_BOOT_DRIVER(msm_sdc_drv) = {
.id = UCLASS_MMC,
.of_match = msm_mmc_ids,
.ofdata_to_platdata = msm_ofdata_to_platdata,
+ .ops = &sdhci_ops,
+ .bind = msm_sdc_bind,
.probe = msm_sdc_probe,
.remove = msm_sdc_remove,
.priv_auto_alloc_size = sizeof(struct msm_sdhc),
+ .platdata_auto_alloc_size = sizeof(struct msm_sdhc_plat),
};
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index d41d60c..020a59b 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -7,8 +7,10 @@
#include <common.h>
#include <clk.h>
#include <dm.h>
+#include <dt-structs.h>
#include <dwmmc.h>
#include <errno.h>
+#include <mapmem.h>
#include <pwrseq.h>
#include <syscon.h>
#include <asm/gpio.h>
@@ -19,6 +21,9 @@
DECLARE_GLOBAL_DATA_PTR;
struct rockchip_mmc_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct dtd_rockchip_rk3288_dw_mshc dtplat;
+#endif
struct mmc_config cfg;
struct mmc mmc;
};
@@ -26,6 +31,9 @@ struct rockchip_mmc_plat {
struct rockchip_dwmmc_priv {
struct clk clk;
struct dwmci_host host;
+ int fifo_depth;
+ bool fifo_mode;
+ u32 minmax[2];
};
static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
@@ -45,6 +53,7 @@ static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
@@ -61,40 +70,54 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
else
host->dev_index = 1;
+ priv->fifo_depth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "fifo-depth", 0);
+ if (priv->fifo_depth < 0)
+ return -EINVAL;
+ priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+ "fifo-mode");
+ if (fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+ "clock-freq-min-max", priv->minmax, 2))
+ return -EINVAL;
+#endif
return 0;
}
static int rockchip_dwmmc_probe(struct udevice *dev)
{
-#ifdef CONFIG_BLK
struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
-#endif
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
struct udevice *pwr_dev __maybe_unused;
- u32 minmax[2];
int ret;
- int fifo_depth;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct dtd_rockchip_rk3288_dw_mshc *dtplat = &plat->dtplat;
+
+ host->name = dev->name;
+ host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
+ host->buswidth = dtplat->bus_width;
+ host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
+ host->priv = dev;
+ host->dev_index = 0;
+ priv->fifo_depth = dtplat->fifo_depth;
+ priv->fifo_mode = 0;
+ memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax));
+
+ ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
+ if (ret < 0)
+ return ret;
+#else
ret = clk_get_by_index(dev, 0, &priv->clk);
if (ret < 0)
return ret;
-
- if (fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
- "clock-freq-min-max", minmax, 2))
- return -EINVAL;
-
- fifo_depth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
- "fifo-depth", 0);
- if (fifo_depth < 0)
- return -EINVAL;
-
+#endif
host->fifoth_val = MSIZE(0x2) |
- RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2);
+ RX_WMARK(priv->fifo_depth / 2 - 1) |
+ TX_WMARK(priv->fifo_depth / 2);
- if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset, "fifo-mode"))
- host->fifo_mode = true;
+ host->fifo_mode = priv->fifo_mode;
#ifdef CONFIG_PWRSEQ
/* Enable power if needed */
@@ -106,33 +129,24 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
return ret;
}
#endif
-#ifdef CONFIG_BLK
dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
- minmax[1], minmax[0]);
+ priv->minmax[1], priv->minmax[0]);
host->mmc = &plat->mmc;
-#else
- ret = add_dwmci(host, minmax[1], minmax[0]);
- if (ret)
- return ret;
-
-#endif
host->mmc->priv = &priv->host;
host->mmc->dev = dev;
upriv->mmc = host->mmc;
- return 0;
+ return dwmci_probe(dev);
}
static int rockchip_dwmmc_bind(struct udevice *dev)
{
-#ifdef CONFIG_BLK
struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
int ret;
ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
if (ret)
return ret;
-#endif
return 0;
}
@@ -143,10 +157,11 @@ static const struct udevice_id rockchip_dwmmc_ids[] = {
};
U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
- .name = "rockchip_dwmmc",
+ .name = "rockchip_rk3288_dw_mshc",
.id = UCLASS_MMC,
.of_match = rockchip_dwmmc_ids,
.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
+ .ops = &dm_dwmci_ops,
.bind = rockchip_dwmmc_bind,
.probe = rockchip_dwmmc_probe,
.priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv),
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index 7da059c..5f1333b 100644
--- a/drivers/mmc/sandbox_mmc.c
+++ b/drivers/mmc/sandbox_mmc.c
@@ -25,7 +25,7 @@ struct sandbox_mmc_plat {
* This emulate an SD card version 2. Single-block reads result in zero data.
* Multiple-block reads return a test string.
*/
-static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
switch (cmd->cmdidx) {
@@ -85,25 +85,20 @@ static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
return 0;
}
-static void sandbox_mmc_set_ios(struct mmc *mmc)
-{
-}
-
-static int sandbox_mmc_init(struct mmc *mmc)
+static int sandbox_mmc_set_ios(struct udevice *dev)
{
return 0;
}
-static int sandbox_mmc_getcd(struct mmc *mmc)
+static int sandbox_mmc_get_cd(struct udevice *dev)
{
return 1;
}
-static const struct mmc_ops sandbox_mmc_ops = {
+static const struct dm_mmc_ops sandbox_mmc_ops = {
.send_cmd = sandbox_mmc_send_cmd,
.set_ios = sandbox_mmc_set_ios,
- .init = sandbox_mmc_init,
- .getcd = sandbox_mmc_getcd,
+ .get_cd = sandbox_mmc_get_cd,
};
int sandbox_mmc_probe(struct udevice *dev)
@@ -120,7 +115,6 @@ int sandbox_mmc_bind(struct udevice *dev)
int ret;
cfg->name = dev->name;
- cfg->ops = &sandbox_mmc_ops;
cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT;
cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
cfg->f_min = 1000000;
@@ -150,6 +144,7 @@ U_BOOT_DRIVER(mmc_sandbox) = {
.name = "mmc_sandbox",
.id = UCLASS_MMC,
.of_match = sandbox_mmc_ids,
+ .ops = &sandbox_mmc_ops,
.bind = sandbox_mmc_bind,
.unbind = sandbox_mmc_unbind,
.probe = sandbox_mmc_probe,
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 604f18d..de8d8ea 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -9,6 +9,7 @@
*/
#include <common.h>
+#include <errno.h>
#include <malloc.h>
#include <mmc.h>
#include <sdhci.h>
@@ -129,9 +130,17 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
#define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT 100
#define SDHCI_READ_STATUS_TIMEOUT 1000
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_send_command(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+#else
static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data)
+ struct mmc_data *data)
{
+#endif
struct sdhci_host *host = mmc->priv;
unsigned int stat = 0;
int ret = 0;
@@ -389,8 +398,14 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_set_ios(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
static void sdhci_set_ios(struct mmc *mmc)
{
+#endif
u32 ctrl;
struct sdhci_host *host = mmc->priv;
@@ -426,6 +441,9 @@ static void sdhci_set_ios(struct mmc *mmc)
ctrl &= ~SDHCI_CTRL_HISPD;
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+#ifdef CONFIG_DM_MMC_OPS
+ return 0;
+#endif
}
static int sdhci_init(struct mmc *mmc)
@@ -472,80 +490,110 @@ static int sdhci_init(struct mmc *mmc)
return 0;
}
+#ifdef CONFIG_DM_MMC_OPS
+int sdhci_probe(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return sdhci_init(mmc);
+}
+const struct dm_mmc_ops sdhci_ops = {
+ .send_cmd = sdhci_send_command,
+ .set_ios = sdhci_set_ios,
+};
+#else
static const struct mmc_ops sdhci_ops = {
.send_cmd = sdhci_send_command,
.set_ios = sdhci_set_ios,
.init = sdhci_init,
};
+#endif
-int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
+int sdhci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
+ uint caps, u32 max_clk, u32 min_clk, uint version,
+ uint quirks, uint host_caps)
{
- unsigned int caps;
-
- host->cfg.name = host->name;
- host->cfg.ops = &sdhci_ops;
-
- caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-#ifdef CONFIG_MMC_SDMA
- if (!(caps & SDHCI_CAN_DO_SDMA)) {
- printf("%s: Your controller doesn't support SDMA!!\n",
- __func__);
- return -1;
- }
+ cfg->name = name;
+#ifndef CONFIG_DM_MMC_OPS
+ cfg->ops = &sdhci_ops;
#endif
-
if (max_clk)
- host->cfg.f_max = max_clk;
+ cfg->f_max = max_clk;
else {
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
- host->cfg.f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
- >> SDHCI_CLOCK_BASE_SHIFT;
+ if (version >= SDHCI_SPEC_300)
+ cfg->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
+ SDHCI_CLOCK_BASE_SHIFT;
else
- host->cfg.f_max = (caps & SDHCI_CLOCK_BASE_MASK)
- >> SDHCI_CLOCK_BASE_SHIFT;
- host->cfg.f_max *= 1000000;
- }
- if (host->cfg.f_max == 0) {
- printf("%s: Hardware doesn't specify base clock frequency\n",
- __func__);
- return -1;
+ cfg->f_max = (caps & SDHCI_CLOCK_BASE_MASK) >>
+ SDHCI_CLOCK_BASE_SHIFT;
+ cfg->f_max *= 1000000;
}
+ if (cfg->f_max == 0)
+ return -EINVAL;
if (min_clk)
- host->cfg.f_min = min_clk;
+ cfg->f_min = min_clk;
else {
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
- host->cfg.f_min = host->cfg.f_max /
- SDHCI_MAX_DIV_SPEC_300;
+ if (version >= SDHCI_SPEC_300)
+ cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300;
else
- host->cfg.f_min = host->cfg.f_max /
- SDHCI_MAX_DIV_SPEC_200;
+ cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_200;
}
-
- host->cfg.voltages = 0;
+ cfg->voltages = 0;
if (caps & SDHCI_CAN_VDD_330)
- host->cfg.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
+ cfg->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
if (caps & SDHCI_CAN_VDD_300)
- host->cfg.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
+ cfg->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
if (caps & SDHCI_CAN_VDD_180)
- host->cfg.voltages |= MMC_VDD_165_195;
+ cfg->voltages |= MMC_VDD_165_195;
- 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_4BIT;
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
+ cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
+ if (version >= SDHCI_SPEC_300) {
if (caps & SDHCI_CAN_DO_8BIT)
- host->cfg.host_caps |= MMC_MODE_8BIT;
+ cfg->host_caps |= MMC_MODE_8BIT;
}
- if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)
- host->cfg.host_caps &= ~(MMC_MODE_HS | MMC_MODE_HS_52MHz);
+ if (quirks & SDHCI_QUIRK_NO_HISPD_BIT)
+ cfg->host_caps &= ~(MMC_MODE_HS | MMC_MODE_HS_52MHz);
- if (host->host_caps)
- host->cfg.host_caps |= host->host_caps;
+ if (host_caps)
+ cfg->host_caps |= host_caps;
- host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ return 0;
+}
+
+#ifdef CONFIG_BLK
+int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
+{
+ return mmc_bind(dev, mmc, cfg);
+}
+#else
+int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
+{
+ unsigned int caps;
+
+ caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+#ifdef CONFIG_MMC_SDMA
+ if (!(caps & SDHCI_CAN_DO_SDMA)) {
+ printf("%s: Your controller doesn't support SDMA!!\n",
+ __func__);
+ return -1;
+ }
+#endif
+
+ if (sdhci_setup_cfg(&host->cfg, host->name, host->bus_width, caps,
+ max_clk, min_clk, SDHCI_GET_VERSION(host),
+ host->quirks, host->host_caps)) {
+ printf("%s: Hardware doesn't specify base clock frequency\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
+ host->cfg.voltages |= host->voltages;
sdhci_reset(host, SDHCI_RESET_ALL);
@@ -557,3 +605,4 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
return 0;
}
+#endif