1
0
Fork 0

mmc: Try to bring up SD card

mmc

ENGR00285671 mmc: setup emmc boot partition configure methods

- Configure boot partition
Expose the interfaces that used to enable the configurations
of the boot mode of the eMMC cards.
usage how-to and examples:
Enable the boot partition 1 boot enabled.
"echo 8 > /sys/devices/soc0/soc.1/2100000.aips-bus/
219c000.usdhc/mmc_host/mmc2/mmc2\:0001/boot_config"

In order to make sure that the re-read the ext-csd of card
can be completed successfully, add the method to wait for
the finish of the busy state.

- setup boot_info message output
Output bit means of important esd_csd register

Read esd_csd info each time when cat boot_info
becasue user may change config affect esd_csd
value.

- Boot partition access howto:
About the details, please refer to the guidance of
Documentation/mmc/mmc-dev-parts.txt

To enable write access to /dev/mmcblkXbootY, disable the forced
read-only access with:
echo 0 > /sys/block/mmcblkXbootY/force_ro

To re-enable read-only access:
echo 1 > /sys/block/mmcblkXbootY/force_ro

NOTE:
- The definitions of the EXT_CSD_PART_CONFIG and EXT_CSD_BOOT_BUS_WIDTH
+------------------------------------------------------------+
| Bit7 | Bit6     | Bit5 Bit4 Bit3        | Bit2 Bit1 Bit0   |
|------|----------|-----------------------|------------------|
| X    | BOOT_ACK | BOOT_PARTITION_ENABLE | PARTITION_ACCESS |
+------------------------------------------------------------+
Bit7: Reserved
Bit6: always set to vaule '1' when boot_part is enabled
Bit[5:3]:
0x0 : Device not boot enabled (default)
0x1 : Boot partition 1 enabled for boot
0x2 : Boot partition 2 enabled for boot
0x7 : User area enabled for boot
Bit[2:0]:
0x0 : No access to boot partition (default)
0x1 : R/W boot partition 1
0x2 : R/W boot partition 2

+--------------------------------------------------------------------+
| Bit7 Bit6 Bit5 | Bit4 Bit3 | Bit2                 | Bit1 Bit0      |
|----------------|----------------------------------|----------------|
| X              | BOOT_MODE | RESET_BOOT_BUS_WIDTH | BOOT_BUS_WIDTH |
+--------------------------------------------------------------------+
Bit [4:3] : BOOT_MODE (non-volatile)
0x0 : Use single data rate + backward compatible timings in boot
operation (default)
0x1 : Use single data rate + high speed timings in boot operation mode
0x2 : Use dual data rate in boot operation
0x3 : Reserved
Bit [2]: RESET_BOOT_BUS_WIDTH (non-volatile)
0x0 : Reset bus width to x1, single data rate and backward compatible
timings after boot operation (default)
0x1 : Retain boot bus width and boot mode after boot operation
Bit[1:0] : BOOT_BUS_WIDTH (non-volatile)
0x0 : x1 (sdr) or x4 (ddr) bus width in boot operation mode (default)
0x1 : x4 (sdr/ddr) bus width in boot operation mode
0x2 : x8 (sdr/ddr) bus width in boot operation mode
0x3 : Reserved

- example of the boot_info:
boot_info:0x07;
  ALT_BOOT_MODE:1 - Supports alternate boot method
  DDR_BOOT_MODE:1 - Supports alternate dual data rate during boot
  HS_BOOTMODE:1 - Supports high speed timing during boot
boot_size:2048KB
  boot_partition:0x48;
  BOOT_ACK:1 - Boot acknowledge sent during boot operation
  BOOT_PARTITION-ENABLE: 1 - Boot partition 1 enabled
  PARTITION_ACCESS:0 - No access to boot partition
boot_bus:0x00
  BOOT_MODE:0 - Use single data rate + backward compatible timings
  in boot operation
  RESET_BOOT_BUS_WIDTH:0 - Reset bus width to x1, single data rate
  and backwardcompatible timings after boot operation
  BOOT_BUS_WIDTH:0 - x1 (sdr) or x4 (ddr) bus width in boot
  operation mode

Signed-off-by: Richard Zhu <r65037@freescale.com>

ENGR00323682 MMC: Fixed boot_config overwritten by switch partition

In MMC driver, two variables: boot_config and part_config  are used to
keep eCSD(179) PARTITION_CONFIG. The part_config is not updated when
set new boot_config, which causes the eCSD(179) is overwritten by
any following partition switching, so the new boot_config is lost.

Signed-off-by: Ye.Li <B37916@freescale.com>
(cherry picked from commit e66d21ade29855299ce048c97830a4bb79373761)

Port NXP boot_options patch to new mmc API

Set stricter permissions for boot_config
eirik/updates-from-linux-fsl
Lars Ivar Miljeteig 2018-05-08 12:37:03 +02:00 committed by Eirik Schultz
parent e9474770a8
commit 3b6bf66d98
No known key found for this signature in database
GPG Key ID: CA85F5BFB83767F3
5 changed files with 418 additions and 8 deletions

View File

@ -408,6 +408,10 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
}
card->ext_csd.strobe_support = ext_csd[EXT_CSD_STROBE_SUPPORT];
card->ext_csd.boot_info = ext_csd[EXT_CSD_BOOT_INFO];
card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT];
card->ext_csd.boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
mmc_select_card_type(card);
@ -733,6 +737,356 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
return err;
}
static ssize_t mmc_boot_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
char *boot_partition[8] = {
"Device not boot enabled",
"Boot partition 1 enabled",
"Boot partition 2 enabled",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"User area enabled for boot"};
char *bus_width[4] = {
"x1 (sdr) or x4 (ddr) bus width in boot operation mode",
"x4 (sdr/ddr) bus width in boot operation mode",
"x8 (sdr/ddr) bus width in boot operation mode",
"Reserved"};
char *boot_mode[4] = {
"Use single data rate + backward compatible timings in boot operation",
"Use single data rate + high speed timings in boot operation mode",
"Use dual data rate in boot operation",
"Reserved"};
int partition;
int width;
int mode;
int err;
u8 *ext_csd = NULL;
struct mmc_card *card = container_of(dev, struct mmc_card, dev);
/* read it again because user may change it */
mmc_claim_host(card->host);
err = mmc_get_ext_csd(card, &ext_csd);
mmc_release_host(card->host);
if (err || !ext_csd) {
pr_err("%s: failed to get ext_csd, err=%d\n",
mmc_hostname(card->host),
err);
return err;
}
kfree(ext_csd);
mmc_read_ext_csd(card);
partition = (card->ext_csd.part_config >> 3) & 0x7;
width = card->ext_csd.boot_bus_width & 0x3;
mode = (card->ext_csd.boot_bus_width >> 3) & 0x3;
return sprintf(buf,
"boot_info:0x%02x;\n"
" ALT_BOOT_MODE:%x - %s\n"
" DDR_BOOT_MODE:%x - %s\n"
" HS_BOOTMODE:%x - %s\n"
"boot_size:%04dKB\n"
"boot_partition:0x%02x;\n"
" BOOT_ACK:%x - %s\n"
" BOOT_PARTITION-ENABLE: %x - %s\n"
"boot_bus:0x%02x\n"
" BOOT_MODE:%x - %s\n"
" RESET_BOOT_BUS_WIDTH:%x - %s\n"
" BOOT_BUS_WIDTH:%x - %s\n",
card->ext_csd.boot_info,
!!(card->ext_csd.boot_info & 0x1),
(card->ext_csd.boot_info & 0x1) ?
"Supports alternate boot method" :
"Does not support alternate boot method",
!!(card->ext_csd.boot_info & 0x2),
(card->ext_csd.boot_info & 0x2) ?
"Supports alternate dual data rate during boot" :
"Does not support dual data rate during boot",
!!(card->ext_csd.boot_info & 0x4),
(card->ext_csd.boot_info & 0x4) ?
"Supports high speed timing during boot" :
"Does not support high speed timing during boot",
card->ext_csd.boot_size * 128,
card->ext_csd.part_config,
!!(card->ext_csd.part_config & 0x40),
(card->ext_csd.part_config & 0x40) ?
"Boot acknowledge sent during boot operation" :
"No boot acknowledge sent",
partition,
boot_partition[partition],
card->ext_csd.boot_bus_width,
mode,
boot_mode[mode],
!!(card->ext_csd.boot_bus_width & 0x4),
(card->ext_csd.boot_bus_width & 0x4) ?
"Retain boot bus width and boot mode after boot operation" :
"Reset bus width to x1, single data rate and backward"
"compatible timings after boot operation",
width,
bus_width[width]);
}
/* set up boot partitions */
static ssize_t
setup_boot_partitions(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int err, busy = 0;
u32 part;
u8 *ext_csd, boot_config;
struct mmc_command cmd;
struct mmc_card *card = container_of(dev, struct mmc_card, dev);
BUG_ON(!card);
sscanf(buf, "%d\n", &part);
if (card->csd.mmca_vsn < CSD_SPEC_VER_4) {
pr_err("%s: invalid mmc version" \
" mmc version is below version 4!)\n",
mmc_hostname(card->host));
return -EINVAL;
}
/* it's a normal SD/MMC but user request to configure boot partition */
if (card->ext_csd.boot_size <= 0) {
pr_err("%s: fail to send SWITCH command to card " \
"to update boot_config of the EXT_CSD!\n",
mmc_hostname(card->host));
return -EINVAL;
}
/*
* partition must be -
* 0 - user area
* 1 - boot partition 1
* 2 - boot partition 2
* DO NOT switch the partitions that used to be accessed
* in OS layer HERE
*/
if (part & EXT_CSD_BOOT_PARTITION_ACCESS_MASK) {
pr_err("%s: DO NOT switch the partitions that used to be\n" \
" accessed in OS layer HERE. please following the\n" \
" guidance of Documentation/mmc/mmc-dev-parts.txt.\n",
mmc_hostname(card->host));
return -EINVAL;
}
mmc_claim_host(card->host);
err = mmc_get_ext_csd(card, &ext_csd);
if (err) {
pr_err("%s: unable to read EXT_CSD.\n",
mmc_hostname(card->host));
goto err_rtn;
}
/* enable the boot partition in boot mode */
/* boot enable be -
* 0x00 - disable boot enable.
* 0x08 - boot partition 1 is enabled for boot.
* 0x10 - boot partition 2 is enabled for boot.
* 0x38 - User area is enabled for boot.
*/
switch (part & EXT_CSD_BOOT_PARTITION_ENABLE_MASK) {
case 0:
boot_config = (ext_csd[EXT_CSD_PART_CONFIG]
& ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK
& ~EXT_CSD_BOOT_ACK_ENABLE);
break;
case EXT_CSD_BOOT_PARTITION_PART1:
boot_config = ((ext_csd[EXT_CSD_PART_CONFIG]
& ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
| EXT_CSD_BOOT_PARTITION_PART1
| EXT_CSD_BOOT_ACK_ENABLE);
break;
case EXT_CSD_BOOT_PARTITION_PART2:
boot_config = ((ext_csd[EXT_CSD_PART_CONFIG]
& ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
| EXT_CSD_BOOT_PARTITION_PART2
| EXT_CSD_BOOT_ACK_ENABLE);
break;
case EXT_CSD_BOOT_PARTITION_ENABLE_MASK:
boot_config = ((ext_csd[EXT_CSD_PART_CONFIG]
| EXT_CSD_BOOT_PARTITION_ENABLE_MASK)
& ~EXT_CSD_BOOT_ACK_ENABLE);
break;
default:
pr_err("%s: wrong boot config parameter" \
" 00 (disable boot), 08 (enable boot1)," \
"16 (enable boot2), 56 (User area)\n",
mmc_hostname(card->host));
err = -EINVAL;
goto err_rtn;
}
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_PART_CONFIG, boot_config, card->ext_csd.part_time);
if (err) {
pr_err("%s: fail to send SWITCH command to card " \
"to update boot_config of the EXT_CSD!\n",
mmc_hostname(card->host));
goto err_rtn;
}
/* waiting for the card to finish the busy state */
do {
memset(&cmd, 0, sizeof(struct mmc_command));
cmd.opcode = MMC_SEND_STATUS;
cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err || busy > 100) {
pr_err("%s: failed to wait for" \
"the busy state to end.\n",
mmc_hostname(card->host));
break;
}
if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
pr_info("%s: card is in busy state" \
"pls wait for busy state to end.\n",
mmc_hostname(card->host));
}
busy++;
} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
/* Now check whether it works */
err = mmc_get_ext_csd(card, &ext_csd);
if (err) {
pr_err("%s: %d unable to re-read EXT_CSD.\n",
mmc_hostname(card->host), err);
goto err_rtn;
}
card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG];
err_rtn:
mmc_release_host(card->host);
if (err)
return err;
else
return count;
}
/* configure the boot bus */
static ssize_t
setup_boot_bus(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int err, busy = 0;
u32 boot_bus, new_bus;
u8 *ext_csd;
struct mmc_command cmd;
struct mmc_card *card = container_of(dev, struct mmc_card, dev);
BUG_ON(!card);
sscanf(buf, "%d\n", &boot_bus);
if (card->csd.mmca_vsn < CSD_SPEC_VER_4) {
pr_err("%s: invalid mmc version" \
" mmc version is below version 4!)\n",
mmc_hostname(card->host));
return -EINVAL;
}
/* it's a normal SD/MMC but user request to configure boot bus */
if (card->ext_csd.boot_size <= 0) {
pr_err("%s: this is a normal SD/MMC card" \
" but you request to configure boot bus !\n",
mmc_hostname(card->host));
return -EINVAL;
}
mmc_claim_host(card->host);
err = mmc_get_ext_csd(card, &ext_csd);
if (err) {
pr_err("%s: unable to read EXT_CSD.\n",
mmc_hostname(card->host));
goto err_rtn;
}
/* Configure the boot bus width when boot partition is enabled */
if (((boot_bus & EXT_CSD_BOOT_BUS_WIDTH_MODE_MASK) >> 3) > 2
|| (boot_bus & EXT_CSD_BOOT_BUS_WIDTH_WIDTH_MASK) > 2
|| (boot_bus & ~EXT_CSD_BOOT_BUS_WIDTH_MASK) > 0) {
pr_err("%s: Invalid inputs!\n",
mmc_hostname(card->host));
err = -EINVAL;
goto err_rtn;
}
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BOOT_BUS_WIDTH, boot_bus, card->ext_csd.part_time);
if (err) {
pr_err("%s: fail to send SWITCH command to card " \
"to update boot_config of the EXT_CSD!\n",
mmc_hostname(card->host));
goto err_rtn;
}
/* waiting for the card to finish the busy state */
do {
memset(&cmd, 0, sizeof(struct mmc_command));
cmd.opcode = MMC_SEND_STATUS;
cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err || busy > 100) {
pr_err("%s: failed to wait for" \
"the busy state to end.\n",
mmc_hostname(card->host));
break;
}
if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
pr_info("%s: card is in busy state" \
"pls wait for busy state to end.\n",
mmc_hostname(card->host));
}
busy++;
} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
/* Now check whether it works */
err = mmc_get_ext_csd(card, &ext_csd);
if (err) {
pr_err("%s: %d unable to re-read EXT_CSD.\n",
mmc_hostname(card->host), err);
goto err_rtn;
}
new_bus = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
if (boot_bus != new_bus) {
pr_err("%s: after SWITCH, current boot bus mode %d" \
" is not same as requested bus mode %d!\n",
mmc_hostname(card->host), new_bus, boot_bus);
goto err_rtn;
}
card->ext_csd.boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
err_rtn:
mmc_release_host(card->host);
if (err)
return err;
else
return count;
}
MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
card->raw_cid[2], card->raw_cid[3]);
MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
@ -753,6 +1107,9 @@ 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);
MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr);
DEVICE_ATTR(boot_info, S_IRUGO, mmc_boot_info_show, NULL);
DEVICE_ATTR(boot_config, S_IWUSR | S_IWGRP, NULL, setup_boot_partitions);
DEVICE_ATTR(boot_bus_config, S_IWUSR | S_IWGRP, NULL, setup_boot_bus);
static ssize_t mmc_fwrev_show(struct device *dev,
struct device_attribute *attr,
@ -806,6 +1163,9 @@ static struct attribute *mmc_std_attrs[] = {
&dev_attr_rel_sectors.attr,
&dev_attr_ocr.attr,
&dev_attr_dsr.attr,
&dev_attr_boot_info.attr,
&dev_attr_boot_config.attr,
&dev_attr_boot_bus_config.attr,
NULL,
};
ATTRIBUTE_GROUPS(mmc_std);
@ -1373,9 +1733,17 @@ static int mmc_select_hs200(struct mmc_card *card)
if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
if (err) {
printk("Unable to set MMC voltage to 1.2V\n");
}
if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
if (err) {
printk("Unable to set MMC voltage to 1.8V\n");
} else {
printk("Set MMC voltage to 1.8V\n");
}
/* If fails try again during next card power cycle */
if (err)
return err;
@ -1394,8 +1762,9 @@ static int mmc_select_hs200(struct mmc_card *card)
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
true, false, true);
if (err)
if (err) {
goto err;
}
old_timing = host->ios.timing;
mmc_set_timing(host, MMC_TIMING_MMC_HS200);

View File

@ -443,14 +443,18 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
int mmc_switch_status_error(struct mmc_host *host, u32 status)
{
if (mmc_host_is_spi(host)) {
if (status & R1_SPI_ILLEGAL_COMMAND)
if (status & R1_SPI_ILLEGAL_COMMAND) {
printk("Illegal SPI command!\n");
return -EBADMSG;
}
} else {
if (status & 0xFDFFA000)
if (status & 0xFDFFA000) {
pr_warn("%s: unexpected status %#x after switch\n",
mmc_hostname(host), status);
if (status & R1_SWITCH_ERROR)
}
if (status & R1_SWITCH_ERROR) {
return -EBADMSG;
}
}
return 0;
}

View File

@ -1240,8 +1240,10 @@ int mmc_attach_sd(struct mmc_host *host)
WARN_ON(!host->claimed);
err = mmc_send_app_op_cond(host, 0, &ocr);
if (err)
if (err) {
printk("unable to send app op cond\n");
return err;
}
mmc_attach_bus(host, &mmc_sd_ops);
if (host->ocr_avail_sd)
@ -1254,8 +1256,10 @@ int mmc_attach_sd(struct mmc_host *host)
mmc_go_idle(host);
err = mmc_spi_read_ocr(host, 0, &ocr);
if (err)
if (err) {
printk("unable to read spi ocr\n");
goto err;
}
}
rocr = mmc_select_voltage(host, ocr);
@ -1264,6 +1268,7 @@ int mmc_attach_sd(struct mmc_host *host)
* Can we support the voltage(s) of the card(s)?
*/
if (!rocr) {
printk("unable to get mmc voltage\n");
err = -EINVAL;
goto err;
}
@ -1272,13 +1277,17 @@ int mmc_attach_sd(struct mmc_host *host)
* Detect and init the card.
*/
err = mmc_sd_init_card(host, rocr, NULL);
if (err)
if (err) {
printk("unable to detect and/or init SD card\n");
goto err;
}
mmc_release_host(host);
err = mmc_add_card(host->card);
if (err)
if (err) {
printk("unable to claim mmc host\n");
goto remove_card;
}
mmc_claim_host(host);
return 0;

View File

@ -87,6 +87,7 @@ struct mmc_ext_csd {
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 */
unsigned int boot_size;
bool boot_ro_lockable;
bool ffu_capable; /* Firmware upgrade support */
#define MMC_FIRMWARE_LEN 8
@ -94,6 +95,7 @@ struct mmc_ext_csd {
u8 raw_exception_status; /* 54 */
u8 raw_partition_support; /* 160 */
u8 raw_rpmb_size_mult; /* 168 */
u8 boot_bus_width; /* 177 */
u8 raw_erased_mem_count; /* 181 */
u8 strobe_support; /* 184 */
u8 raw_ext_csd_structure; /* 194 */
@ -108,6 +110,7 @@ struct mmc_ext_csd {
u8 raw_hc_erase_gap_size; /* 221 */
u8 raw_erase_timeout_mult; /* 223 */
u8 raw_hc_erase_grp_size; /* 224 */
u8 boot_info; /* 228 */
u8 raw_sec_trim_mult; /* 229 */
u8 raw_sec_erase_mult; /* 230 */
u8 raw_sec_feature_support;/* 231 */

View File

@ -294,6 +294,7 @@ struct _mmc_csd {
#define EXT_CSD_FW_CONFIG 169 /* R/W */
#define EXT_CSD_BOOT_WP 173 /* R/W */
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
#define EXT_CSD_BOOT_BUS_WIDTH 177 /* 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 */
@ -317,6 +318,7 @@ struct _mmc_csd {
#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
#define EXT_CSD_BOOT_MULT 226 /* RO */
#define EXT_CSD_BOOT_INFO 228 /* RO, 1 bytes */
#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
@ -401,6 +403,29 @@ struct _mmc_csd {
#define EXT_CSD_SEC_GB_CL_EN BIT(4)
#define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */
#define EXT_CSD_BOOT_BUS_WIDTH_MASK (0x1F)
#define EXT_CSD_BOOT_BUS_WIDTH_MODE_MASK (0x3 << 3)
#define EXT_CSD_BOOT_BUS_WIDTH_MODE_SDR_NORMAL (0x0)
#define EXT_CSD_BOOT_BUS_WIDTH_MODE_SDR_HIGH (0x1)
#define EXT_CSD_BOOT_BUS_WIDTH_MODE_DDR (0x2)
#define EXT_CSD_BOOT_BUS_WIDTH_RST_WIDTH (1 << 2)
#define EXT_CSD_BOOT_BUS_WIDTH_WIDTH_MASK (0x3)
#define EXT_CSD_BOOT_BUS_WIDTH_1_SDR_4_DDR (0x0)
#define EXT_CSD_BOOT_BUS_WIDTH_4_SDR_4_DDR (0x1)
#define EXT_CSD_BOOT_BUS_WIDTH_8_SDR_8_DDR (0x2)
#define EXT_CSD_BOOT_ACK_ENABLE (0x1 << 6)
#define EXT_CSD_BOOT_PARTITION_ENABLE_MASK (0x7 << 3)
#define EXT_CSD_BOOT_PARTITION_DISABLE (0x0)
#define EXT_CSD_BOOT_PARTITION_PART1 (0x1 << 3)
#define EXT_CSD_BOOT_PARTITION_PART2 (0x2 << 3)
#define EXT_CSD_BOOT_PARTITION_USER (0x7 << 3)
#define EXT_CSD_BOOT_PARTITION_ACCESS_MASK (0x7)
#define EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE (0x0)
#define EXT_CSD_BOOT_PARTITION_ACCESS_PART1 (0x1)
#define EXT_CSD_BOOT_PARTITION_ACCESS_PART2 (0x2)
#define EXT_CSD_RST_N_EN_MASK 0x3
#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */