mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
SD(io)/(e)MMC: update mmc flow, continue commit-sha19896ff517b38c2c2db17980a71dca8cd23fb8585
This commit is contained in:
@@ -2291,6 +2291,70 @@ int mmc_card_can_sleep(struct mmc_host *host)
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_card_can_sleep);
|
||||
|
||||
/*
|
||||
* Flush the cache to the non-volatile storage.
|
||||
*/
|
||||
int mmc_flush_cache(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
int err = 0;
|
||||
|
||||
if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
|
||||
return err;
|
||||
|
||||
if (mmc_card_mmc(card) &&
|
||||
(card->ext_csd.cache_size > 0) &&
|
||||
(card->ext_csd.cache_ctrl & 1)) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_FLUSH_CACHE, 1, 0);
|
||||
if (err)
|
||||
pr_err("%s: cache flush error %d\n",
|
||||
mmc_hostname(card->host), err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_flush_cache);
|
||||
|
||||
/*
|
||||
* Turn the cache ON/OFF.
|
||||
* Turning the cache OFF shall trigger flushing of the data
|
||||
* to the non-volatile storage.
|
||||
* This function should be called with host claimed
|
||||
*/
|
||||
int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
|
||||
{
|
||||
struct mmc_card *card = host->card;
|
||||
unsigned int timeout;
|
||||
int err = 0;
|
||||
|
||||
if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
|
||||
mmc_card_is_removable(host))
|
||||
return err;
|
||||
|
||||
if (card && mmc_card_mmc(card) &&
|
||||
(card->ext_csd.cache_size > 0)) {
|
||||
enable = !!enable;
|
||||
|
||||
if (card->ext_csd.cache_ctrl ^ enable) {
|
||||
timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_CACHE_CTRL, enable, timeout);
|
||||
if (err)
|
||||
pr_err("%s: cache %s error %d\n",
|
||||
mmc_hostname(card->host),
|
||||
enable ? "on" : "off",
|
||||
err);
|
||||
else
|
||||
card->ext_csd.cache_ctrl = enable;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_cache_ctrl);
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/**
|
||||
|
||||
1
drivers/mmc/core/core.h
Normal file → Executable file
1
drivers/mmc/core/core.h
Normal file → Executable file
@@ -24,6 +24,7 @@ struct mmc_bus_ops {
|
||||
int (*resume)(struct mmc_host *);
|
||||
int (*power_save)(struct mmc_host *);
|
||||
int (*power_restore)(struct mmc_host *);
|
||||
int (*alive)(struct mmc_host *);
|
||||
};
|
||||
|
||||
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "core.h"
|
||||
#include "bus.h"
|
||||
#include "host.h"
|
||||
#include "mmc_ops.h"
|
||||
#include "sd_ops.h"
|
||||
|
||||
@@ -95,6 +96,7 @@ static int mmc_decode_cid(struct mmc_card *card)
|
||||
card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
|
||||
card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
|
||||
card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
|
||||
card->cid.prv = UNSTUFF_BITS(resp, 48, 8);
|
||||
card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
|
||||
card->cid.month = UNSTUFF_BITS(resp, 12, 4);
|
||||
card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
|
||||
@@ -234,12 +236,44 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mmc_select_card_type(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
|
||||
u32 caps = host->caps, caps2 = host->caps2;
|
||||
unsigned int hs_max_dtr = 0;
|
||||
|
||||
if (card_type & EXT_CSD_CARD_TYPE_26)
|
||||
hs_max_dtr = MMC_HIGH_26_MAX_DTR;
|
||||
|
||||
if (caps & MMC_CAP_MMC_HIGHSPEED &&
|
||||
card_type & EXT_CSD_CARD_TYPE_52)
|
||||
hs_max_dtr = MMC_HIGH_52_MAX_DTR;
|
||||
|
||||
if ((caps & MMC_CAP_1_8V_DDR &&
|
||||
card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
|
||||
(caps & MMC_CAP_1_2V_DDR &&
|
||||
card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
|
||||
hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
|
||||
|
||||
if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
|
||||
card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
|
||||
(caps2 & MMC_CAP2_HS200_1_2V_SDR &&
|
||||
card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
|
||||
hs_max_dtr = MMC_HS200_MAX_DTR;
|
||||
|
||||
card->ext_csd.hs_max_dtr = hs_max_dtr;
|
||||
card->ext_csd.card_type = card_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode extended CSD.
|
||||
*/
|
||||
static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
|
||||
{
|
||||
int err = 0;
|
||||
int err = 0, idx;
|
||||
unsigned int part_size;
|
||||
u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0;
|
||||
|
||||
BUG_ON(!card);
|
||||
|
||||
@@ -397,6 +431,42 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
|
||||
card->ext_csd.enhanced_area_offset = -EINVAL;
|
||||
card->ext_csd.enhanced_area_size = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* General purpose partition feature support --
|
||||
* If ext_csd has the size of general purpose partitions,
|
||||
* set size, part_cfg, partition name in mmc_part.
|
||||
*/
|
||||
if (ext_csd[EXT_CSD_PARTITION_SUPPORT] &
|
||||
EXT_CSD_PART_SUPPORT_PART_EN) {
|
||||
if (card->ext_csd.enhanced_area_en != 1) {
|
||||
hc_erase_grp_sz =
|
||||
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
|
||||
hc_wp_grp_sz =
|
||||
ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
|
||||
|
||||
card->ext_csd.enhanced_area_en = 1;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) {
|
||||
if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] &&
|
||||
!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] &&
|
||||
!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2])
|
||||
continue;
|
||||
part_size =
|
||||
(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]
|
||||
<< 16) +
|
||||
(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1]
|
||||
<< 8) +
|
||||
ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3];
|
||||
part_size *= (size_t)(hc_erase_grp_sz *
|
||||
hc_wp_grp_sz);
|
||||
mmc_part_add(card, part_size << 19,
|
||||
EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
|
||||
"gp%d", idx, false,
|
||||
MMC_BLK_DATA_AREA_GP);
|
||||
}
|
||||
}
|
||||
card->ext_csd.sec_trim_mult =
|
||||
ext_csd[EXT_CSD_SEC_TRIM_MULT];
|
||||
card->ext_csd.sec_erase_mult =
|
||||
@@ -405,10 +475,57 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
|
||||
ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
|
||||
card->ext_csd.trim_timeout = 300 *
|
||||
ext_csd[EXT_CSD_TRIM_MULT];
|
||||
|
||||
/*
|
||||
* Note that the call to mmc_part_add above defaults to read
|
||||
* only. If this default assumption is changed, the call must
|
||||
* take into account the value of boot_locked below.
|
||||
*/
|
||||
card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP];
|
||||
card->ext_csd.boot_ro_lockable = true;
|
||||
}
|
||||
|
||||
if (card->ext_csd.rev >= 5)
|
||||
if (card->ext_csd.rev >= 5) {
|
||||
/* check whether the eMMC card supports BKOPS */
|
||||
if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
|
||||
card->ext_csd.bkops = 1;
|
||||
card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN];
|
||||
card->ext_csd.raw_bkops_status =
|
||||
ext_csd[EXT_CSD_BKOPS_STATUS];
|
||||
if (!card->ext_csd.bkops_en)
|
||||
pr_info("%s: BKOPS_EN bit is not set\n",
|
||||
mmc_hostname(card->host));
|
||||
}
|
||||
|
||||
/* check whether the eMMC card supports HPI */
|
||||
if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
|
||||
card->ext_csd.hpi = 1;
|
||||
if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
|
||||
card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
|
||||
else
|
||||
card->ext_csd.hpi_cmd = MMC_SEND_STATUS;
|
||||
/*
|
||||
* Indicate the maximum timeout to close
|
||||
* a command interrupted by HPI
|
||||
*/
|
||||
card->ext_csd.out_of_int_time =
|
||||
ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10;
|
||||
}
|
||||
|
||||
card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
|
||||
card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
|
||||
|
||||
/*
|
||||
* RPMB regions are defined in multiples of 128K.
|
||||
*/
|
||||
card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT];
|
||||
if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_cmd23(card->host)) {
|
||||
mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17,
|
||||
EXT_CSD_PART_CONFIG_ACC_RPMB,
|
||||
"rpmb", 0, false,
|
||||
MMC_BLK_DATA_AREA_RPMB);
|
||||
}
|
||||
}
|
||||
|
||||
card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
|
||||
if (ext_csd[EXT_CSD_ERASED_MEM_CONT])
|
||||
@@ -416,6 +533,43 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
|
||||
else
|
||||
card->erased_byte = 0x0;
|
||||
|
||||
/* eMMC v4.5 or later */
|
||||
if (card->ext_csd.rev >= 6) {
|
||||
card->ext_csd.feature_support |= MMC_DISCARD_FEATURE;
|
||||
|
||||
card->ext_csd.generic_cmd6_time = 10 *
|
||||
ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
|
||||
card->ext_csd.power_off_longtime = 10 *
|
||||
ext_csd[EXT_CSD_POWER_OFF_LONG_TIME];
|
||||
|
||||
card->ext_csd.cache_size =
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 0] << 0 |
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
|
||||
|
||||
if (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 1)
|
||||
card->ext_csd.data_sector_size = 4096;
|
||||
else
|
||||
card->ext_csd.data_sector_size = 512;
|
||||
|
||||
if ((ext_csd[EXT_CSD_DATA_TAG_SUPPORT] & 1) &&
|
||||
(ext_csd[EXT_CSD_TAG_UNIT_SIZE] <= 8)) {
|
||||
card->ext_csd.data_tag_unit_size =
|
||||
((unsigned int) 1 << ext_csd[EXT_CSD_TAG_UNIT_SIZE]) *
|
||||
(card->ext_csd.data_sector_size);
|
||||
} else {
|
||||
card->ext_csd.data_tag_unit_size = 0;
|
||||
}
|
||||
|
||||
card->ext_csd.max_packed_writes =
|
||||
ext_csd[EXT_CSD_MAX_PACKED_WRITES];
|
||||
card->ext_csd.max_packed_reads =
|
||||
ext_csd[EXT_CSD_MAX_PACKED_READS];
|
||||
} else {
|
||||
card->ext_csd.data_sector_size = 512;
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
@@ -510,10 +664,13 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
|
||||
MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
|
||||
MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
|
||||
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
|
||||
MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv);
|
||||
MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
|
||||
MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
|
||||
card->ext_csd.enhanced_area_offset);
|
||||
MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
|
||||
MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
|
||||
MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
|
||||
|
||||
static struct attribute *mmc_std_attrs[] = {
|
||||
&dev_attr_cid.attr,
|
||||
@@ -526,9 +683,12 @@ static struct attribute *mmc_std_attrs[] = {
|
||||
&dev_attr_manfid.attr,
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_oemid.attr,
|
||||
&dev_attr_prv.attr,
|
||||
&dev_attr_serial.attr,
|
||||
&dev_attr_enhanced_area_offset.attr,
|
||||
&dev_attr_enhanced_area_size.attr,
|
||||
&dev_attr_raw_rpmb_size_mult.attr,
|
||||
&dev_attr_rel_sectors.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -545,6 +705,166 @@ static struct device_type mmc_type = {
|
||||
.groups = mmc_attr_groups,
|
||||
};
|
||||
|
||||
/*
|
||||
* Select the PowerClass for the current bus width
|
||||
* If power class is defined for 4/8 bit bus in the
|
||||
* extended CSD register, select it by executing the
|
||||
* mmc_switch command.
|
||||
*/
|
||||
static int mmc_select_powerclass(struct mmc_card *card,
|
||||
unsigned int bus_width, u8 *ext_csd)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned int pwrclass_val;
|
||||
unsigned int index = 0;
|
||||
struct mmc_host *host;
|
||||
|
||||
BUG_ON(!card);
|
||||
|
||||
host = card->host;
|
||||
BUG_ON(!host);
|
||||
|
||||
if (ext_csd == NULL)
|
||||
return 0;
|
||||
|
||||
/* Power class selection is supported for versions >= 4.0 */
|
||||
if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
|
||||
return 0;
|
||||
|
||||
/* Power class values are defined only for 4/8 bit bus */
|
||||
if (bus_width == EXT_CSD_BUS_WIDTH_1)
|
||||
return 0;
|
||||
|
||||
switch (1 << host->ios.vdd) {
|
||||
case MMC_VDD_165_195:
|
||||
if (host->ios.clock <= 26000000)
|
||||
index = EXT_CSD_PWR_CL_26_195;
|
||||
else if (host->ios.clock <= 52000000)
|
||||
index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
|
||||
EXT_CSD_PWR_CL_52_195 :
|
||||
EXT_CSD_PWR_CL_DDR_52_195;
|
||||
else if (host->ios.clock <= 200000000)
|
||||
index = EXT_CSD_PWR_CL_200_195;
|
||||
break;
|
||||
case MMC_VDD_27_28:
|
||||
case MMC_VDD_28_29:
|
||||
case MMC_VDD_29_30:
|
||||
case MMC_VDD_30_31:
|
||||
case MMC_VDD_31_32:
|
||||
case MMC_VDD_32_33:
|
||||
case MMC_VDD_33_34:
|
||||
case MMC_VDD_34_35:
|
||||
case MMC_VDD_35_36:
|
||||
if (host->ios.clock <= 26000000)
|
||||
index = EXT_CSD_PWR_CL_26_360;
|
||||
else if (host->ios.clock <= 52000000)
|
||||
index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
|
||||
EXT_CSD_PWR_CL_52_360 :
|
||||
EXT_CSD_PWR_CL_DDR_52_360;
|
||||
else if (host->ios.clock <= 200000000)
|
||||
index = EXT_CSD_PWR_CL_200_360;
|
||||
break;
|
||||
default:
|
||||
pr_warning("%s: Voltage range not supported "
|
||||
"for power class.\n", mmc_hostname(host));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pwrclass_val = ext_csd[index];
|
||||
|
||||
if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8))
|
||||
pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >>
|
||||
EXT_CSD_PWR_CL_8BIT_SHIFT;
|
||||
else
|
||||
pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_4BIT_MASK) >>
|
||||
EXT_CSD_PWR_CL_4BIT_SHIFT;
|
||||
|
||||
/* If the power class is different from the default value */
|
||||
if (pwrclass_val > 0) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_POWER_CLASS,
|
||||
pwrclass_val,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Selects the desired buswidth and switch to the HS200 mode
|
||||
* if bus width set without error
|
||||
*/
|
||||
static int mmc_select_hs200(struct mmc_card *card)
|
||||
{
|
||||
int idx, err = -EINVAL;
|
||||
struct mmc_host *host;
|
||||
static unsigned ext_csd_bits[] = {
|
||||
EXT_CSD_BUS_WIDTH_4,
|
||||
EXT_CSD_BUS_WIDTH_8,
|
||||
};
|
||||
static unsigned bus_widths[] = {
|
||||
MMC_BUS_WIDTH_4,
|
||||
MMC_BUS_WIDTH_8,
|
||||
};
|
||||
|
||||
BUG_ON(!card);
|
||||
|
||||
host = card->host;
|
||||
|
||||
if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
|
||||
host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
|
||||
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120,0);
|
||||
|
||||
if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
|
||||
host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
|
||||
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,0);
|
||||
|
||||
/* If fails try again during next card power cycle */
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 1 : 0;
|
||||
|
||||
/*
|
||||
* Unlike SD, MMC cards dont have a configuration register to notify
|
||||
* supported bus width. So bus test command should be run to identify
|
||||
* the supported bus width or compare the ext csd values of current
|
||||
* bus width and ext csd values of 1 bit mode read earlier.
|
||||
*/
|
||||
for (; idx >= 0; idx--) {
|
||||
|
||||
/*
|
||||
* Host is capable of 8bit transfer, then switch
|
||||
* the device to work in 8bit transfer mode. If the
|
||||
* mmc switch command returns error then switch to
|
||||
* 4bit transfer mode. On success set the corresponding
|
||||
* bus width on the host.
|
||||
*/
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BUS_WIDTH,
|
||||
ext_csd_bits[idx],
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
if (err)
|
||||
continue;
|
||||
|
||||
mmc_set_bus_width(card->host, bus_widths[idx]);
|
||||
|
||||
if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
|
||||
err = mmc_compare_ext_csds(card, bus_widths[idx]);
|
||||
else
|
||||
err = mmc_bus_test(card, bus_widths[idx]);
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
|
||||
/* switch to HS200 mode if bus width set successfully */
|
||||
if (!err)
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_HS_TIMING, 2, 0);
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the detection and initialisation of a card.
|
||||
*
|
||||
@@ -564,6 +884,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
BUG_ON(!host);
|
||||
WARN_ON(!host->claimed);
|
||||
|
||||
/* Set correct bus mode for MMC before attempting init */
|
||||
if (!mmc_host_is_spi(host))
|
||||
mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
|
||||
|
||||
/*
|
||||
* Since we're changing the OCR value, we seem to
|
||||
* need to tell some cards to go back to the idle
|
||||
@@ -687,9 +1011,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
* If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
|
||||
* bit. This bit will be lost every time after a reset or power off.
|
||||
*/
|
||||
if (card->ext_csd.enhanced_area_en) {
|
||||
if (card->ext_csd.enhanced_area_en ||
|
||||
(card->ext_csd.rev >= 3 && (host->caps2 & MMC_CAP2_HC_ERASE_SZ))) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_ERASE_GROUP_DEF, 1, 0);
|
||||
EXT_CSD_ERASE_GROUP_DEF, 1,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
|
||||
if (err && err != -EBADMSG)
|
||||
goto free_card;
|
||||
@@ -726,13 +1052,40 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
goto free_card;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the host supports the power_off_notify capability then
|
||||
* set the notification byte in the ext_csd register of device
|
||||
*/
|
||||
if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) &&
|
||||
(card->ext_csd.rev >= 6)) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_POWER_OFF_NOTIFICATION,
|
||||
EXT_CSD_POWER_ON,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
if (err && err != -EBADMSG)
|
||||
goto free_card;
|
||||
|
||||
/*
|
||||
* The err can be -EBADMSG or 0,
|
||||
* so check for success and update the flag
|
||||
*/
|
||||
if (!err)
|
||||
card->ext_csd.power_off_notification = EXT_CSD_POWER_ON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Activate high speed (if supported)
|
||||
*/
|
||||
if ((card->ext_csd.hs_max_dtr != 0) &&
|
||||
(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_HS_TIMING, 1, 0);
|
||||
if (card->ext_csd.hs_max_dtr != 0) {
|
||||
err = 0;
|
||||
if (card->ext_csd.hs_max_dtr > 52000000 &&
|
||||
host->caps2 & MMC_CAP2_HS200)
|
||||
err = mmc_select_hs200(card);
|
||||
else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_HS_TIMING, 1,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
|
||||
if (err && err != -EBADMSG)
|
||||
goto free_card;
|
||||
|
||||
@@ -741,8 +1094,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
mmc_hostname(card->host));
|
||||
err = 0;
|
||||
} else {
|
||||
mmc_card_set_highspeed(card);
|
||||
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
|
||||
if (card->ext_csd.hs_max_dtr > 52000000 &&
|
||||
host->caps2 & MMC_CAP2_HS200) {
|
||||
mmc_card_set_hs200(card);
|
||||
mmc_set_timing(card->host,
|
||||
MMC_TIMING_MMC_HS200);
|
||||
} else {
|
||||
mmc_card_set_highspeed(card);
|
||||
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,6 +1114,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
if (mmc_card_highspeed(card)) {
|
||||
if (max_dtr > card->ext_csd.hs_max_dtr)
|
||||
max_dtr = card->ext_csd.hs_max_dtr;
|
||||
if (mmc_card_highspeed(card) && (max_dtr > 52000000))
|
||||
max_dtr = 52000000;
|
||||
} else if (max_dtr > card->csd.max_dtr) {
|
||||
if(!HOST_IS_EMMC(host)){
|
||||
//in order to expand the compatibility of card. Added by xbw@2011-03-21
|
||||
@@ -780,10 +1142,51 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
ddr = MMC_1_2V_DDR_MODE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate HS200 SDR mode (if supported).
|
||||
*/
|
||||
if (mmc_card_hs200(card)) {
|
||||
u32 ext_csd_bits;
|
||||
u32 bus_width = card->host->ios.bus_width;
|
||||
|
||||
/*
|
||||
* For devices supporting HS200 mode, the bus width has
|
||||
* to be set before executing the tuning function. If
|
||||
* set before tuning, then device will respond with CRC
|
||||
* errors for responses on CMD line. So for HS200 the
|
||||
* sequence will be
|
||||
* 1. set bus width 4bit / 8 bit (1 bit not supported)
|
||||
* 2. switch to HS200 mode
|
||||
* 3. set the clock to > 52Mhz <=200MHz and
|
||||
* 4. execute tuning for HS200
|
||||
*/
|
||||
if ((host->caps2 & MMC_CAP2_HS200) &&
|
||||
card->host->ops->execute_tuning) {
|
||||
mmc_host_clk_hold(card->host);
|
||||
err = card->host->ops->execute_tuning(card->host,
|
||||
MMC_SEND_TUNING_BLOCK_HS200);
|
||||
mmc_host_clk_release(card->host);
|
||||
}
|
||||
if (err) {
|
||||
pr_warning("%s: tuning execution failed\n",
|
||||
mmc_hostname(card->host));
|
||||
goto err;
|
||||
}
|
||||
|
||||
ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
|
||||
EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
|
||||
err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
|
||||
if (err)
|
||||
pr_warning("%s: power class selection to bus width %d"
|
||||
" failed\n", mmc_hostname(card->host),
|
||||
1 << bus_width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Activate wide bus and DDR (if supported).
|
||||
*/
|
||||
if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
|
||||
if (!mmc_card_hs200(card) &&
|
||||
(card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
|
||||
(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
|
||||
static unsigned ext_csd_bits[][2] = {
|
||||
{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
|
||||
@@ -805,10 +1208,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
bus_width = bus_widths[idx];
|
||||
if (bus_width == MMC_BUS_WIDTH_1)
|
||||
ddr = 0; /* no DDR for 1-bit width */
|
||||
err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
|
||||
ext_csd);
|
||||
if (err)
|
||||
pr_warning("%s: power class selection to "
|
||||
"bus width %d failed\n",
|
||||
mmc_hostname(card->host),
|
||||
1 << bus_width);
|
||||
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BUS_WIDTH,
|
||||
ext_csd_bits[idx][0],
|
||||
0);
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
if (!err) {
|
||||
mmc_set_bus_width(card->host, bus_width);
|
||||
|
||||
@@ -828,10 +1239,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
}
|
||||
|
||||
if (!err && ddr) {
|
||||
err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
|
||||
ext_csd);
|
||||
if (err)
|
||||
pr_warning("%s: power class selection to "
|
||||
"bus width %d ddr %d failed\n",
|
||||
mmc_hostname(card->host),
|
||||
1 << bus_width, ddr);
|
||||
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BUS_WIDTH,
|
||||
ext_csd_bits[idx][1],
|
||||
0);
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
}
|
||||
if (err) {
|
||||
printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
|
||||
@@ -865,6 +1284,72 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable HPI feature (if supported)
|
||||
*/
|
||||
if (card->ext_csd.hpi) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_HPI_MGMT, 1,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
if (err && err != -EBADMSG)
|
||||
goto free_card;
|
||||
if (err) {
|
||||
pr_warning("%s: Enabling HPI failed\n",
|
||||
mmc_hostname(card->host));
|
||||
err = 0;
|
||||
} else
|
||||
card->ext_csd.hpi_en = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If cache size is higher than 0, this indicates
|
||||
* the existence of cache and it can be turned on.
|
||||
*/
|
||||
if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
|
||||
card->ext_csd.cache_size > 0) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_CACHE_CTRL, 1,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
if (err && err != -EBADMSG)
|
||||
goto free_card;
|
||||
|
||||
/*
|
||||
* Only if no error, cache is turned on successfully.
|
||||
*/
|
||||
if (err) {
|
||||
pr_warning("%s: Cache is supported, "
|
||||
"but failed to turn on (%d)\n",
|
||||
mmc_hostname(card->host), err);
|
||||
card->ext_csd.cache_ctrl = 0;
|
||||
err = 0;
|
||||
} else {
|
||||
card->ext_csd.cache_ctrl = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The mandatory minimum values are defined for packed command.
|
||||
* read: 5, write: 3
|
||||
*/
|
||||
if (card->ext_csd.max_packed_writes >= 3 &&
|
||||
card->ext_csd.max_packed_reads >= 5 &&
|
||||
host->caps2 & MMC_CAP2_PACKED_CMD) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_EXP_EVENTS_CTRL,
|
||||
EXT_CSD_PACKED_EVENT_EN,
|
||||
card->ext_csd.generic_cmd6_time);
|
||||
if (err && err != -EBADMSG)
|
||||
goto free_card;
|
||||
if (err) {
|
||||
pr_warn("%s: Enabling packed event failed\n",
|
||||
mmc_hostname(card->host));
|
||||
card->ext_csd.packed_event_en = 0;
|
||||
err = 0;
|
||||
} else {
|
||||
card->ext_csd.packed_event_en = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!oldcard)
|
||||
host->card = card;
|
||||
|
||||
@@ -880,6 +1365,35 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mmc_can_poweroff_notify(const struct mmc_card *card)
|
||||
{
|
||||
return card &&
|
||||
mmc_card_mmc(card) &&
|
||||
(card->ext_csd.power_off_notification == EXT_CSD_POWER_ON);
|
||||
}
|
||||
|
||||
static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
|
||||
{
|
||||
unsigned int timeout = card->ext_csd.generic_cmd6_time;
|
||||
int err;
|
||||
|
||||
/* Use EXT_CSD_POWER_OFF_SHORT as default notification type. */
|
||||
if (notify_type == EXT_CSD_POWER_OFF_LONG)
|
||||
timeout = card->ext_csd.power_off_longtime;
|
||||
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_POWER_OFF_NOTIFICATION,
|
||||
notify_type, timeout);
|
||||
if (err)
|
||||
pr_err("%s: Power Off Notification timed out, %u\n",
|
||||
mmc_hostname(card->host), timeout);
|
||||
|
||||
/* Disable the power off notification after the switch operation. */
|
||||
card->ext_csd.power_off_notification = EXT_CSD_NO_POWER_NOTIFICATION;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Host is being removed. Free up the current card.
|
||||
*/
|
||||
@@ -892,6 +1406,14 @@ static void mmc_remove(struct mmc_host *host)
|
||||
host->card = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Card detection - card is alive.
|
||||
*/
|
||||
static int mmc_alive(struct mmc_host *host)
|
||||
{
|
||||
return mmc_send_status(host->card, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Card detection callback from host.
|
||||
*/
|
||||
@@ -924,18 +1446,31 @@ static void mmc_detect(struct mmc_host *host)
|
||||
/*
|
||||
* Suspend callback from host.
|
||||
*/
|
||||
extern int mmc_cache_ctrl(struct mmc_host *host, u8 enable);
|
||||
static int mmc_suspend(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
BUG_ON(!host);
|
||||
BUG_ON(!host->card);
|
||||
|
||||
mmc_claim_host(host);
|
||||
if (!mmc_host_is_spi(host))
|
||||
mmc_deselect_cards(host);
|
||||
host->card->state &= ~MMC_STATE_HIGHSPEED;
|
||||
mmc_release_host(host);
|
||||
|
||||
return 0;
|
||||
err = mmc_cache_ctrl(host, 0);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (mmc_can_poweroff_notify(host->card))
|
||||
err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
|
||||
else if (mmc_card_can_sleep(host))
|
||||
err = mmc_card_sleep(host);
|
||||
else if (!mmc_host_is_spi(host))
|
||||
err = mmc_deselect_cards(host);
|
||||
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
|
||||
|
||||
out:
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -962,7 +1497,7 @@ static int mmc_power_restore(struct mmc_host *host)
|
||||
{
|
||||
int ret;
|
||||
|
||||
host->card->state &= ~MMC_STATE_HIGHSPEED;
|
||||
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
|
||||
mmc_claim_host(host);
|
||||
ret = mmc_init_card(host, host->ocr, host->card);
|
||||
mmc_release_host(host);
|
||||
@@ -1008,6 +1543,7 @@ static const struct mmc_bus_ops mmc_ops = {
|
||||
.suspend = NULL,
|
||||
.resume = NULL,
|
||||
.power_restore = mmc_power_restore,
|
||||
.alive = mmc_alive,
|
||||
};
|
||||
|
||||
static const struct mmc_bus_ops mmc_ops_unsafe = {
|
||||
@@ -1018,6 +1554,7 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {
|
||||
.suspend = mmc_suspend,
|
||||
.resume = mmc_resume,
|
||||
.power_restore = mmc_power_restore,
|
||||
.alive = mmc_alive,
|
||||
};
|
||||
|
||||
static void mmc_attach_bus_ops(struct mmc_host *host)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
struct mmc_cid {
|
||||
unsigned int manfid;
|
||||
char prod_name[8];
|
||||
unsigned char prv;
|
||||
unsigned int serial;
|
||||
unsigned short oemid;
|
||||
unsigned short year;
|
||||
@@ -50,9 +51,21 @@ struct mmc_ext_csd {
|
||||
u8 rel_sectors;
|
||||
u8 rel_param;
|
||||
u8 part_config;
|
||||
u8 cache_ctrl;
|
||||
u8 rst_n_function;
|
||||
u8 max_packed_writes;
|
||||
u8 max_packed_reads;
|
||||
u8 packed_event_en;
|
||||
unsigned int part_time; /* Units: ms */
|
||||
unsigned int sa_timeout; /* Units: 100ns */
|
||||
unsigned int generic_cmd6_time; /* Units: 10ms */
|
||||
unsigned int power_off_longtime; /* Units: ms */
|
||||
u8 power_off_notification; /* state */
|
||||
unsigned int hs_max_dtr;
|
||||
#define MMC_HIGH_26_MAX_DTR 26000000
|
||||
#define MMC_HIGH_52_MAX_DTR 52000000
|
||||
#define MMC_HIGH_DDR_MAX_DTR 52000000
|
||||
#define MMC_HS200_MAX_DTR 200000000
|
||||
unsigned int sectors;
|
||||
unsigned int card_type;
|
||||
unsigned int hc_erase_size; /* In sectors */
|
||||
@@ -64,10 +77,23 @@ struct mmc_ext_csd {
|
||||
unsigned long long enhanced_area_offset; /* Units: Byte */
|
||||
unsigned int enhanced_area_size; /* Units: KB */
|
||||
unsigned int boot_size; /* in bytes */
|
||||
unsigned int cache_size; /* Units: KB */
|
||||
bool hpi_en; /* HPI enablebit */
|
||||
bool hpi; /* HPI support bit */
|
||||
unsigned int hpi_cmd; /* cmd used as HPI */
|
||||
bool bkops; /* background support bit */
|
||||
bool bkops_en; /* background enable bit */
|
||||
unsigned int data_sector_size; /* 512 bytes or 4KB */
|
||||
unsigned int data_tag_unit_size; /* DATA TAG UNIT size */
|
||||
unsigned int boot_ro_lock; /* ro lock support */
|
||||
bool boot_ro_lockable;
|
||||
u8 raw_exception_status; /* 54 */
|
||||
u8 raw_partition_support; /* 160 */
|
||||
u8 raw_rpmb_size_mult; /* 168 */
|
||||
u8 raw_erased_mem_count; /* 181 */
|
||||
u8 raw_ext_csd_structure; /* 194 */
|
||||
u8 raw_card_type; /* 196 */
|
||||
u8 out_of_int_time; /* 198 */
|
||||
u8 raw_s_a_timeout; /* 217 */
|
||||
u8 raw_hc_erase_gap_size; /* 221 */
|
||||
u8 raw_erase_timeout_mult; /* 223 */
|
||||
@@ -76,7 +102,11 @@ struct mmc_ext_csd {
|
||||
u8 raw_sec_erase_mult; /* 230 */
|
||||
u8 raw_sec_feature_support;/* 231 */
|
||||
u8 raw_trim_mult; /* 232 */
|
||||
u8 raw_bkops_status; /* 246 */
|
||||
u8 raw_sectors[4]; /* 212 - 4 bytes */
|
||||
|
||||
unsigned int feature_support;
|
||||
#define MMC_DISCARD_FEATURE BIT(0) /* CMD38 feature */
|
||||
};
|
||||
|
||||
struct sd_scr {
|
||||
@@ -126,6 +156,7 @@ struct sd_switch_caps {
|
||||
#define SD_SET_CURRENT_LIMIT_400 1
|
||||
#define SD_SET_CURRENT_LIMIT_600 2
|
||||
#define SD_SET_CURRENT_LIMIT_800 3
|
||||
#define SD_SET_CURRENT_NO_CHANGE (-1)
|
||||
|
||||
#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200)
|
||||
#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400)
|
||||
@@ -157,6 +188,30 @@ struct sdio_func_tuple;
|
||||
|
||||
#define SDIO_MAX_FUNCS 7
|
||||
|
||||
/* The number of MMC physical partitions. These consist of:
|
||||
* boot partitions (2), general purpose partitions (4) in MMC v4.4.
|
||||
*/
|
||||
#define MMC_NUM_BOOT_PARTITION 2
|
||||
#define MMC_NUM_GP_PARTITION 4
|
||||
#define MMC_NUM_PHY_PARTITION 6
|
||||
#define MAX_MMC_PART_NAME_LEN 20
|
||||
|
||||
/*
|
||||
* MMC Physical partitions
|
||||
*/
|
||||
struct mmc_part {
|
||||
unsigned int size; /* partition size (in bytes) */
|
||||
unsigned int part_cfg; /* partition type */
|
||||
char name[MAX_MMC_PART_NAME_LEN];
|
||||
bool force_ro; /* to make boot parts RO by default */
|
||||
unsigned int area_type;
|
||||
#define MMC_BLK_DATA_AREA_MAIN (1<<0)
|
||||
#define MMC_BLK_DATA_AREA_BOOT (1<<1)
|
||||
#define MMC_BLK_DATA_AREA_GP (1<<2)
|
||||
#define MMC_BLK_DATA_AREA_RPMB (1<<3)
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MMC device
|
||||
*/
|
||||
@@ -224,8 +279,31 @@ struct mmc_card {
|
||||
unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */
|
||||
|
||||
struct dentry *debugfs_root;
|
||||
struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
|
||||
unsigned int nr_parts;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function fill contents in mmc_part.
|
||||
*/
|
||||
static inline void mmc_part_add(struct mmc_card *card, unsigned int size,
|
||||
unsigned int part_cfg, char *name, int idx, bool ro,
|
||||
int area_type)
|
||||
{
|
||||
card->part[card->nr_parts].size = size;
|
||||
card->part[card->nr_parts].part_cfg = part_cfg;
|
||||
sprintf(card->part[card->nr_parts].name, name, idx);
|
||||
card->part[card->nr_parts].force_ro = ro;
|
||||
card->part[card->nr_parts].area_type = area_type;
|
||||
card->nr_parts++;
|
||||
}
|
||||
|
||||
static inline bool mmc_large_sector(struct mmc_card *card)
|
||||
{
|
||||
return card->ext_csd.data_sector_size == 4096;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The world is not perfect and supplies us with broken mmc/sdio devices.
|
||||
* For at least some of these bugs we need a work-around.
|
||||
@@ -319,6 +397,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
|
||||
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
|
||||
#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
|
||||
#define mmc_card_hs200(c) ((c)->state & MMC_STATE_HIGHSPEED_200)
|
||||
#define mmc_card_set_hs200(c) ((c)->state |= MMC_STATE_HIGHSPEED_200)
|
||||
#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
|
||||
#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
|
||||
#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
|
||||
|
||||
@@ -56,6 +56,7 @@ struct mmc_ios {
|
||||
#define MMC_TIMING_UHS_SDR50 3
|
||||
#define MMC_TIMING_UHS_SDR104 4
|
||||
#define MMC_TIMING_UHS_DDR50 5
|
||||
#define MMC_TIMING_MMC_HS200 8
|
||||
|
||||
unsigned char ddr; /* dual data rate used */
|
||||
|
||||
@@ -238,6 +239,28 @@ struct mmc_host {
|
||||
#define MMC_CAP_MAX_CURRENT_600 (1 << 28) /* Host max current limit is 600mA */
|
||||
#define MMC_CAP_MAX_CURRENT_800 (1 << 29) /* Host max current limit is 800mA */
|
||||
#define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */
|
||||
#define MMC_CAP_HW_RESET (1 << 31) /* Hardware reset */
|
||||
|
||||
u32 caps2; /* More host capabilities */
|
||||
#define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */
|
||||
#define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */
|
||||
#define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff supported */
|
||||
#define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */
|
||||
#define MMC_CAP2_NO_SLEEP_CMD (1 << 4) /* Don't allow sleep command */
|
||||
#define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */
|
||||
#define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */
|
||||
#define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \
|
||||
MMC_CAP2_HS200_1_2V_SDR)
|
||||
#define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */
|
||||
#define MMC_CAP2_DETECT_ON_ERR (1 << 8) /* On I/O err check card removal */
|
||||
#define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */
|
||||
#define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */
|
||||
#define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */
|
||||
#define MMC_CAP2_PACKED_RD (1 << 12) /* Allow packed read */
|
||||
#define MMC_CAP2_PACKED_WR (1 << 13) /* Allow packed write */
|
||||
#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
|
||||
MMC_CAP2_PACKED_WR)
|
||||
#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */
|
||||
|
||||
mmc_pm_flag_t pm_caps; /* supported pm features */
|
||||
|
||||
|
||||
68
include/linux/mmc/mmc.h
Normal file → Executable file
68
include/linux/mmc/mmc.h
Normal file → Executable file
@@ -51,6 +51,7 @@
|
||||
#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */
|
||||
#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */
|
||||
|
||||
/* class 3 */
|
||||
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
|
||||
@@ -269,19 +270,40 @@ struct _mmc_csd {
|
||||
/*
|
||||
* EXT_CSD fields
|
||||
*/
|
||||
|
||||
#define EXT_CSD_FLUSH_CACHE 32 /* W */
|
||||
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
|
||||
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
|
||||
#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */
|
||||
#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */
|
||||
#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */
|
||||
#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */
|
||||
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
|
||||
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
||||
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
|
||||
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
|
||||
#define EXT_CSD_HPI_MGMT 161 /* R/W */
|
||||
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
||||
#define EXT_CSD_BKOPS_EN 163 /* R/W */
|
||||
#define EXT_CSD_BKOPS_START 164 /* W */
|
||||
#define EXT_CSD_SANITIZE_START 165 /* W */
|
||||
#define EXT_CSD_WR_REL_PARAM 166 /* RO */
|
||||
#define EXT_CSD_RPMB_MULT 168 /* RO */
|
||||
#define EXT_CSD_BOOT_WP 173 /* R/W */
|
||||
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
|
||||
#define EXT_CSD_PART_CONFIG 179 /* R/W */
|
||||
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
|
||||
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
|
||||
#define EXT_CSD_HS_TIMING 185 /* R/W */
|
||||
#define EXT_CSD_POWER_CLASS 187 /* R/W */
|
||||
#define EXT_CSD_REV 192 /* RO */
|
||||
#define EXT_CSD_STRUCTURE 194 /* RO */
|
||||
#define EXT_CSD_CARD_TYPE 196 /* RO */
|
||||
#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */
|
||||
#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */
|
||||
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
|
||||
#define EXT_CSD_PWR_CL_26_195 201 /* RO */
|
||||
#define EXT_CSD_PWR_CL_52_360 202 /* RO */
|
||||
#define EXT_CSD_PWR_CL_26_360 203 /* RO */
|
||||
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
|
||||
#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
|
||||
#define EXT_CSD_REL_WR_SEC_C 222 /* RO */
|
||||
@@ -293,6 +315,20 @@ struct _mmc_csd {
|
||||
#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
|
||||
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
|
||||
#define EXT_CSD_TRIM_MULT 232 /* RO */
|
||||
#define EXT_CSD_PWR_CL_200_195 236 /* RO */
|
||||
#define EXT_CSD_PWR_CL_200_360 237 /* RO */
|
||||
#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */
|
||||
#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */
|
||||
#define EXT_CSD_BKOPS_STATUS 246 /* RO */
|
||||
#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
|
||||
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
|
||||
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
|
||||
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
|
||||
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
|
||||
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
|
||||
#define EXT_CSD_MAX_PACKED_READS 501 /* RO */
|
||||
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
|
||||
#define EXT_CSD_HPI_FEATURES 503 /* RO */
|
||||
|
||||
/*
|
||||
* EXT_CSD field definitions
|
||||
@@ -300,9 +336,18 @@ struct _mmc_csd {
|
||||
|
||||
#define EXT_CSD_WR_REL_PARAM_EN (1<<2)
|
||||
|
||||
#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40)
|
||||
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10)
|
||||
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04)
|
||||
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01)
|
||||
|
||||
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_BOOT1 (0x2)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
|
||||
|
||||
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
|
||||
|
||||
#define EXT_CSD_CMD_SET_NORMAL (1<<0)
|
||||
#define EXT_CSD_CMD_SET_SECURE (1<<1)
|
||||
@@ -310,13 +355,16 @@ struct _mmc_csd {
|
||||
|
||||
#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
|
||||
#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
|
||||
#define EXT_CSD_CARD_TYPE_MASK 0xF /* Mask out reserved bits */
|
||||
#define EXT_CSD_CARD_TYPE_MASK 0x3F /* Mask out reserved bits */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
|
||||
/* DDR mode @1.8V or 3V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
|
||||
/* DDR mode @1.2V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
|
||||
| EXT_CSD_CARD_TYPE_DDR_1_2V)
|
||||
#define EXT_CSD_CARD_TYPE_SDR_1_8V (1<<4) /* Card can run at 200MHz */
|
||||
#define EXT_CSD_CARD_TYPE_SDR_1_2V (1<<5) /* Card can run at 200MHz */
|
||||
/* SDR mode @1.2V I/O */
|
||||
|
||||
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
|
||||
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
|
||||
@@ -327,6 +375,22 @@ struct _mmc_csd {
|
||||
#define EXT_CSD_SEC_ER_EN BIT(0)
|
||||
#define EXT_CSD_SEC_BD_BLK_EN BIT(2)
|
||||
#define EXT_CSD_SEC_GB_CL_EN BIT(4)
|
||||
#define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */
|
||||
|
||||
#define EXT_CSD_RST_N_EN_MASK 0x3
|
||||
#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */
|
||||
|
||||
#define EXT_CSD_NO_POWER_NOTIFICATION 0
|
||||
#define EXT_CSD_POWER_ON 1
|
||||
#define EXT_CSD_POWER_OFF_SHORT 2
|
||||
#define EXT_CSD_POWER_OFF_LONG 3
|
||||
|
||||
#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */
|
||||
#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */
|
||||
#define EXT_CSD_PWR_CL_8BIT_SHIFT 4
|
||||
#define EXT_CSD_PWR_CL_4BIT_SHIFT 0
|
||||
|
||||
#define EXT_CSD_PACKED_EVENT_EN BIT(3)
|
||||
|
||||
/*
|
||||
* MMC_SWITCH access modes
|
||||
|
||||
Reference in New Issue
Block a user