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_configeirik/updates-from-linux-fsl
parent
e9474770a8
commit
3b6bf66d98
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue