#include <config.h>
#include <common.h>
#include <command.h>
+#include <errno.h>
#include <mmc.h>
#include <part.h>
#include <malloc.h>
static struct list_head mmc_devices;
static int cur_dev_num = -1;
-int __weak board_mmc_getwp(struct mmc *mmc)
+__weak int board_mmc_getwp(struct mmc *mmc)
{
return -1;
}
return wp;
}
-int __board_mmc_getcd(struct mmc *mmc) {
+__weak int board_mmc_getcd(struct mmc *mmc)
+{
return -1;
}
-int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
- alias("__board_mmc_getcd")));
-
int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
int ret;
#endif
return TIMEOUT;
}
+ if (cmd.response[0] & MMC_STATUS_SWITCH_ERROR)
+ return SWITCH_ERR;
return 0;
}
{
struct mmc_cmd cmd;
+ if (mmc->card_caps & MMC_MODE_DDR_52MHz)
+ return 0;
+
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = len;
return 0;
}
-int mmc_send_op_cond(struct mmc *mmc)
+static int mmc_send_op_cond(struct mmc *mmc)
{
struct mmc_cmd cmd;
int err, i;
return IN_PROGRESS;
}
-int mmc_complete_op_cond(struct mmc *mmc)
+static int mmc_complete_op_cond(struct mmc *mmc)
{
struct mmc_cmd cmd;
int timeout = 1000;
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
if (err)
- return err;
+ return err == SWITCH_ERR ? 0 : err;
/* Now check to see that it worked */
err = mmc_send_ext_csd(mmc, ext_csd);
return 0;
/* High Speed is set, there are two types: 52MHz and 26MHz */
- if (cardtype & MMC_HS_52MHZ)
+ if (cardtype & EXT_CSD_CARD_TYPE_52) {
+ if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
+ mmc->card_caps |= MMC_MODE_DDR_52MHz;
mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
- else
+ } else {
mmc->card_caps |= MMC_MODE_HS;
+ }
return 0;
}
return 0;
}
+int mmc_select_hwpart(int dev_num, int hwpart)
+{
+ struct mmc *mmc = find_mmc_device(dev_num);
+ int ret;
+
+ if (!mmc)
+ return -ENODEV;
+
+ if (mmc->part_num == hwpart)
+ return 0;
+
+ if (mmc->part_config == MMCPART_NOAVAILABLE) {
+ printf("Card doesn't support part_switch\n");
+ return -EMEDIUMTYPE;
+ }
+
+ ret = mmc_switch_part(dev_num, hwpart);
+ if (ret)
+ return ret;
+
+ mmc->part_num = hwpart;
+
+ return 0;
+}
+
+
int mmc_switch_part(int dev_num, unsigned int part_num)
{
struct mmc *mmc = find_mmc_device(dev_num);
ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
(mmc->part_config & ~PART_ACCESS_MASK)
| (part_num & PART_ACCESS_MASK));
- if (ret)
- return ret;
- return mmc_set_capacity(mmc, part_num);
+ /*
+ * Set the capacity if the switch succeeded or was intended
+ * to return to representing the raw device.
+ */
+ if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0)))
+ ret = mmc_set_capacity(mmc, part_num);
+
+ return ret;
}
int mmc_getcd(struct mmc *mmc)
if (err)
return err;
+ else
+ ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
/* Read out group size from ext_csd */
mmc->erase_grp_size =
/* An array of possible bus widths in order of preference */
static unsigned ext_csd_bits[] = {
+ EXT_CSD_DDR_BUS_WIDTH_8,
+ EXT_CSD_DDR_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_8,
EXT_CSD_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_1,
/* An array to map CSD bus widths to host cap bits */
static unsigned ext_to_hostcaps[] = {
+ [EXT_CSD_DDR_BUS_WIDTH_4] = MMC_MODE_DDR_52MHz,
+ [EXT_CSD_DDR_BUS_WIDTH_8] = MMC_MODE_DDR_52MHz,
[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
};
/* An array to map chosen bus width to an integer */
static unsigned widths[] = {
- 8, 4, 1,
+ 8, 4, 8, 4, 1,
};
for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
mmc_set_bus_width(mmc, widths[idx]);
err = mmc_send_ext_csd(mmc, test_csd);
+ /* Only compare read only fields */
if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
== test_csd[EXT_CSD_PARTITIONING_SUPPORT]
- && ext_csd[EXT_CSD_ERASE_GROUP_DEF] \
- == test_csd[EXT_CSD_ERASE_GROUP_DEF] \
+ && ext_csd[EXT_CSD_HC_WP_GRP_SIZE] \
+ == test_csd[EXT_CSD_HC_WP_GRP_SIZE] \
&& ext_csd[EXT_CSD_REV] \
== test_csd[EXT_CSD_REV]
&& ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \
}
#endif
+/* board-specific MMC power initializations. */
+__weak void board_mmc_power_init(void)
+{
+}
+
int mmc_start_init(struct mmc *mmc)
{
int err;
if (mmc->has_init)
return 0;
+ board_mmc_power_init();
+
/* made sure it's not NULL earlier */
err = mmc->cfg->ops->init(mmc);
int mmc_init(struct mmc *mmc)
{
int err = IN_PROGRESS;
- unsigned start = get_timer(0);
+ unsigned start;
if (mmc->has_init)
return 0;
+
+ start = get_timer(0);
+
if (!mmc->init_in_progress)
err = mmc_start_init(mmc);
return 0;
}
-/*
- * CPU and board-specific MMC initializations. Aliased function
- * signals caller to move on
- */
-static int __def_mmc_init(bd_t *bis)
+/* CPU-specific MMC initializations */
+__weak int cpu_mmc_init(bd_t *bis)
{
return -1;
}
-int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
-int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
+/* board-specific MMC initializations. */
+__weak int board_mmc_init(bd_t *bis)
+{
+ return -1;
+}
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)