/** * mmc_set_data_timeout - set the timeout for a data command * @data: data phase for command * @card: the MMC card associated with the data transfer * * Computes the data timeout parameters according to the * correct algorithm given the card type. */ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) { unsigned int mult; /* * SDIO cards only define an upper 1 s limit on access. */ if (mmc_card_sdio(card)) { if (card->host->caps & MMC_CAP_ATHEROS_WIFI) data->timeout_ns = 2000000000; else data->timeout_ns = 1000000000; data->timeout_clks = 0; return; } /* * SD cards use a 100 multiplier rather than 10 */ mult = mmc_card_sd(card) ? 100 : 10; /* * Scale up the multiplier (and therefore the timeout) by * the r2w factor for writes. */ if (data->flags & MMC_DATA_WRITE) mult <<= card->csd.r2w_factor; data->timeout_ns = card->csd.tacc_ns * mult; data->timeout_clks = card->csd.tacc_clks * mult; /* * SD cards also have an upper limit on the timeout. */ if (mmc_card_sd(card)) { unsigned int timeout_us, limit_us; timeout_us = data->timeout_ns / 1000; timeout_us += data->timeout_clks * 1000 / (card->host->ios.clock / 1000); if (data->flags & MMC_DATA_WRITE) /* * The limit is really 250 ms, but that is * insufficient for some crappy cards. */ limit_us = 300000; else limit_us = 100000; /* * SDHC cards always use these fixed values. */ if (timeout_us > limit_us || mmc_card_blockaddr(card)) { data->timeout_ns = limit_us * 1000; data->timeout_clks = 0; } } /* * Some cards need very high timeouts if driven in SPI mode. * The worst observed timeout was 900ms after writing a * continuous stream of data until the internal logic * overflowed. */ if (mmc_host_is_spi(card->host)) { if (data->flags & MMC_DATA_WRITE) { if (data->timeout_ns < 1000000000) data->timeout_ns = 1000000000; /* 1s */ } else { if (data->timeout_ns < 100000000) data->timeout_ns = 100000000; /* 100ms */ } } }
/** * mmc_set_data_timeout - set the timeout for a data command * @data: data phase for command * @card: the MMC card associated with the data transfer * * Computes the data timeout parameters according to the * correct algorithm given the card type. */ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) { unsigned int mult; /* * SDIO cards only define an upper 1 s limit on access. */ if (mmc_card_sdio(card)) { data->timeout_ns = 1000000000; data->timeout_clks = 0; return; } /* * SD cards use a 100 multiplier rather than 10 */ mult = mmc_card_sd(card) ? 100 : 10; /* * Scale up the multiplier (and therefore the timeout) by * the r2w factor for writes. */ if (data->flags & MMC_DATA_WRITE) mult <<= card->csd.r2w_factor; data->timeout_ns = card->csd.tacc_ns * mult; data->timeout_clks = card->csd.tacc_clks * mult; /* * SD cards also have an upper limit on the timeout. */ if (mmc_card_sd(card)) { unsigned int timeout_us, limit_us; timeout_us = data->timeout_ns / 1000; timeout_us += data->timeout_clks * 1000 / (card->host->ios.clock / 1000); if (data->flags & MMC_DATA_WRITE) /* * The MMC spec "It is strongly recommended * for hosts to implement more than 500ms * timeout value even if the card indicates * the 250ms maximum busy length." Even the * previous value of 300ms is known to be * insufficient for some cards. */ limit_us = 3000000; else limit_us = 100000; /* * SDHC cards always use these fixed values. */ if (timeout_us > limit_us || mmc_card_blockaddr(card)) { data->timeout_ns = limit_us * 1000; data->timeout_clks = 0; } } /* * Some cards need very high timeouts if driven in SPI mode. * The worst observed timeout was 900ms after writing a * continuous stream of data until the internal logic * overflowed. */ if (mmc_host_is_spi(card->host)) { if (data->flags & MMC_DATA_WRITE) { if (data->timeout_ns < 1000000000) data->timeout_ns = 1000000000; /* 1s */ } else { if (data->timeout_ns < 100000000) data->timeout_ns = 100000000; /* 100ms */ } } }
/* * Decode extended CSD. */ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0; BUG_ON(!card); if (!ext_csd) return 0; /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; if (card->csd.structure == 3) { if (card->ext_csd.raw_ext_csd_structure > 2) { printk(KERN_ERR "%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), card->ext_csd.raw_ext_csd_structure); err = -EINVAL; goto out; } } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; if (card->ext_csd.rev > 6) { printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; goto out; } card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; card->ext_csd.raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3]; if (card->ext_csd.rev >= 2) { card->ext_csd.sectors = ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; /* Cards with density > 2GiB are sector addressed */ if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) mmc_card_set_blockaddr(card); } card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; break; case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; break; case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; break; case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; break; case EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 26000000; break; default: /* MMC v4 spec says this cannot happen */ printk(KERN_WARNING "%s: card is mmc v4 but doesn't " "support any high-speed modes.\n", mmc_hostname(card->host)); } card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.raw_erase_timeout_mult = ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.raw_hc_erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; if (card->ext_csd.rev >= 3) { u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG]; /* EXT_CSD value is in units of 10ms, but we store in ms */ card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME]; /* Sleep / awake timeout in 100ns units */ if (sa_shift > 0 && sa_shift <= 0x17) card->ext_csd.sa_timeout = 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.erase_group_def = ext_csd[EXT_CSD_ERASE_GROUP_DEF]; card->ext_csd.hc_erase_timeout = 300 * ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.hc_erase_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; card->ext_csd.rel_sectors = ext_csd[EXT_CSD_REL_WR_SEC_C]; /* * There are two boot regions of equal size, defined in * multiples of 128K. */ card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; } card->ext_csd.raw_hc_erase_gap_size = ext_csd[EXT_CSD_PARTITION_ATTRIBUTE]; card->ext_csd.raw_sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.raw_sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.raw_sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.raw_trim_mult = ext_csd[EXT_CSD_TRIM_MULT]; if (card->ext_csd.rev >= 4) { /* * Enhanced area feature support -- check whether the eMMC * card has the Enhanced area enabled. If so, export enhanced * area offset and size to user by adding sysfs interface. */ if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { u8 hc_erase_grp_sz = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; u8 hc_wp_grp_sz = ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; card->ext_csd.enhanced_area_en = 1; /* * calculate the enhanced data area offset, in bytes */ card->ext_csd.enhanced_area_offset = (ext_csd[139] << 24) + (ext_csd[138] << 16) + (ext_csd[137] << 8) + ext_csd[136]; if (mmc_card_blockaddr(card)) card->ext_csd.enhanced_area_offset <<= 9; /* * calculate the enhanced data area size, in kilobytes */ card->ext_csd.enhanced_area_size = (ext_csd[142] << 16) + (ext_csd[141] << 8) + ext_csd[140]; card->ext_csd.enhanced_area_size *= (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); card->ext_csd.enhanced_area_size <<= 9; } else { /* * If the enhanced area is not enabled, disable these * device attributes. */ card->ext_csd.enhanced_area_offset = -EINVAL; card->ext_csd.enhanced_area_size = -EINVAL; } card->ext_csd.sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.trim_timeout = 300 * ext_csd[EXT_CSD_TRIM_MULT]; } if (card->ext_csd.rev >= 5) card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM]; /* eMMC v4.5 or later */ if (card->ext_csd.rev >= 6) card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) card->erased_byte = 0xFF; else card->erased_byte = 0x0; out: return err; }
/* * Handle the detection and initialisation of a card. * * In the case of a resume, "oldcard" will contain the card * we're trying to reinitialise. */ static int mmc_init_card(struct mmc_host *host, u32 ocr, struct mmc_card *oldcard) { struct mmc_card *card; int err, ddr = 0; u32 cid[4]; unsigned int max_dtr; u32 rocr; u8 *ext_csd = NULL; BUG_ON(!host); WARN_ON(!host->claimed); /* * Since we're changing the OCR value, we seem to * need to tell some cards to go back to the idle * state. We wait 1ms to give cards time to * respond. */ mmc_go_idle(host); /* The extra bit indicates that we support high capacity */ err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr); if (err) goto err; /* * For SPI, enable CRC as appropriate. */ if (mmc_host_is_spi(host)) { err = mmc_spi_set_crc(host, use_spi_crc); if (err) goto err; } /* * Fetch CID from card. */ if (mmc_host_is_spi(host)) err = mmc_send_cid(host, cid); else err = mmc_all_send_cid(host, cid); if (err) goto err; if (oldcard) { if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { err = -ENOENT; goto err; } card = oldcard; } else { /* * Allocate card structure. */ card = mmc_alloc_card(host, &mmc_type); if (IS_ERR(card)) { err = PTR_ERR(card); goto err; } card->type = MMC_TYPE_MMC; card->rca = 1; memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); } /* * For native busses: set card RCA and quit open drain mode. */ if (!mmc_host_is_spi(host)) { err = mmc_set_relative_addr(card); if (err) goto free_card; mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } if (!oldcard) { /* * Fetch CSD from card. */ err = mmc_send_csd(card, card->raw_csd); if (err) goto free_card; err = mmc_decode_csd(card); if (err) goto free_card; err = mmc_decode_cid(card); if (err) goto free_card; } /* * Select card, as all following commands rely on that. */ if (!mmc_host_is_spi(host)) { err = mmc_select_card(card); if (err) goto free_card; } if (!oldcard) { /* * Fetch and process extended CSD. */ err = mmc_get_ext_csd(card, &ext_csd); if (err) goto free_card; err = mmc_read_ext_csd(card, ext_csd); if (err) goto free_card; /* If doing byte addressing, check if required to do sector * addressing. Handle the case of <2GB cards needing sector * addressing. See section 8.1 JEDEC Standard JED84-A441; * ocr register has bit 30 set for sector addressing. */ if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30))) mmc_card_set_blockaddr(card); /* Erase size depends on CSD and Extended CSD */ mmc_set_erase_size(card); if (card->ext_csd.sectors && (rocr & MMC_CARD_SECTOR_ADDR)) mmc_card_set_blockaddr(card); } /* * 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) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_ERASE_GROUP_DEF, 1, 0); if (err && err != -EBADMSG) goto free_card; if (err) { err = 0; /* * Just disable enhanced area off & sz * will try to enable ERASE_GROUP_DEF * during next time reinit */ card->ext_csd.enhanced_area_offset = -EINVAL; card->ext_csd.enhanced_area_size = -EINVAL; } else { card->ext_csd.erase_group_def = 1; /* * enable ERASE_GRP_DEF successfully. * This will affect the erase size, so * here need to reset erase size */ mmc_set_erase_size(card); } } /* * Ensure eMMC user default partition is enabled */ if (card->ext_csd.part_config & EXT_CSD_PART_CONFIG_ACC_MASK) { card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONFIG, card->ext_csd.part_config, card->ext_csd.part_time); if (err && err != -EBADMSG) goto free_card; } /* * 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 (err && err != -EBADMSG) goto free_card; if (err) { printk(KERN_WARNING "%s: switch to highspeed failed\n", mmc_hostname(card->host)); err = 0; } else { mmc_card_set_highspeed(card); mmc_set_timing(card->host, MMC_TIMING_MMC_HS); } } /* * Compute bus speed. */ max_dtr = (unsigned int)-1; if (mmc_card_highspeed(card)) { if (max_dtr > card->ext_csd.hs_max_dtr) max_dtr = card->ext_csd.hs_max_dtr; } else if (max_dtr > card->csd.max_dtr) { max_dtr = card->csd.max_dtr; } mmc_set_clock(host, max_dtr); /* * Indicate DDR mode (if supported). */ if (mmc_card_highspeed(card)) { if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) && ((host->caps & (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)) == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50))) ddr = MMC_1_8V_DDR_MODE; else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) && ((host->caps & (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)) == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50))) ddr = MMC_1_2V_DDR_MODE; } /* * Activate wide bus and DDR (if supported). */ if ((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 }, { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 }, { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 }, }; static unsigned bus_widths[] = { MMC_BUS_WIDTH_8, MMC_BUS_WIDTH_4, MMC_BUS_WIDTH_1 }; unsigned idx, bus_width = 0; if (host->caps & MMC_CAP_8_BIT_DATA) idx = 0; else idx = 1; for (; idx < ARRAY_SIZE(bus_widths); idx++) { bus_width = bus_widths[idx]; if (bus_width == MMC_BUS_WIDTH_1) ddr = 0; /* no DDR for 1-bit width */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx][0], 0); if (!err) { mmc_set_bus_width(card->host, bus_width); /* * If controller can't handle bus width test, * compare ext_csd previously read in 1 bit mode * against ext_csd at new bus width */ if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) err = mmc_compare_ext_csds(card, bus_width); else err = mmc_bus_test(card, bus_width); if (!err) break; } } if (!err && ddr) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx][1], 0); } if (err) { printk(KERN_WARNING "%s: switch to bus width %d ddr %d " "failed\n", mmc_hostname(card->host), 1 << bus_width, ddr); goto free_card; } else if (ddr) { /* * eMMC cards can support 3.3V to 1.2V i/o (vccq) * signaling. * * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq. * * 1.8V vccq at 3.3V core voltage (vcc) is not required * in the JEDEC spec for DDR. * * Do not force change in vccq since we are obviously * working and no change to vccq is needed. * * WARNING: eMMC rules are NOT the same as SD DDR */ if (ddr == MMC_1_2V_DDR_MODE) { err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0); if (err) goto err; } mmc_card_set_ddr_mode(card); mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50); mmc_set_bus_width(card->host, bus_width); } } if (!oldcard) host->card = card; mmc_free_ext_csd(ext_csd); return 0; free_card: if (!oldcard) mmc_remove_card(card); err: mmc_free_ext_csd(ext_csd); return err; }
/* * Register a new MMC card with the driver model. */ int mmc_add_card(struct mmc_card *card) { int ret; const char *type; const char *uhs_bus_speed_mode = ""; static const char *const uhs_speeds[] = { [UHS_SDR12_BUS_SPEED] = "SDR12 ", [UHS_SDR25_BUS_SPEED] = "SDR25 ", [UHS_SDR50_BUS_SPEED] = "SDR50 ", [UHS_SDR104_BUS_SPEED] = "SDR104 ", [UHS_DDR50_BUS_SPEED] = "DDR50 ", }; dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); switch (card->type) { case MMC_TYPE_MMC: type = "MMC"; break; case MMC_TYPE_SD: type = "SD"; if (mmc_card_blockaddr(card)) { if (mmc_card_ext_capacity(card)) type = "SDXC"; else type = "SDHC"; } break; case MMC_TYPE_SDIO: type = "SDIO"; break; case MMC_TYPE_SD_COMBO: type = "SD-combo"; if (mmc_card_blockaddr(card)) type = "SDHC-combo"; break; default: type = "?"; break; } if (mmc_card_uhs(card) && (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; if (mmc_host_is_spi(card->host)) { pr_info("%s: new %s%s%s card on SPI\n", mmc_hostname(card->host), mmc_card_highspeed(card) ? "high speed " : "", mmc_card_ddr_mode(card) ? "DDR " : "", type); } else { pr_info("%s: new %s%s%s%s%s card at address %04x\n", mmc_hostname(card->host), mmc_card_uhs(card) ? "ultra high speed " : (mmc_card_highspeed(card) ? "high speed " : ""), (mmc_card_hs200(card) ? "HS200 " : ""), mmc_card_ddr_mode(card) ? "DDR " : "", uhs_bus_speed_mode, type, card->rca); } #ifdef CONFIG_DEBUG_FS mmc_add_card_debugfs(card); #endif mmc_init_context_info(card->host); ret = device_add(&card->dev); if (ret) return ret; mmc_card_set_present(card); return 0; }
/* * Decode extended CSD. */ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0, idx; unsigned int part_size; u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0; BUG_ON(!card); if (!ext_csd) return 0; /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; if (card->csd.structure == 3) { if (card->ext_csd.raw_ext_csd_structure > 2) { pr_err("%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), card->ext_csd.raw_ext_csd_structure); err = -EINVAL; goto out; } } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; if (card->ext_csd.rev > 6) { printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; goto out; } card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; card->ext_csd.raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3]; if (card->ext_csd.rev >= 2) { card->ext_csd.sectors = ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; /* Cards with density > 2GiB are sector addressed */ if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) mmc_card_set_blockaddr(card); } card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; mmc_select_card_type(card); card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.raw_erase_timeout_mult = ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.raw_hc_erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; if (card->ext_csd.rev >= 3) { u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG]; /* EXT_CSD value is in units of 10ms, but we store in ms */ card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME]; /* Sleep / awake timeout in 100ns units */ if (sa_shift > 0 && sa_shift <= 0x17) card->ext_csd.sa_timeout = 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.erase_group_def = ext_csd[EXT_CSD_ERASE_GROUP_DEF]; card->ext_csd.hc_erase_timeout = 300 * ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.hc_erase_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; card->ext_csd.rel_sectors = ext_csd[EXT_CSD_REL_WR_SEC_C]; /* * There are two boot regions of equal size, defined in * multiples of 128K. */ if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host)) { for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) { part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; mmc_part_add(card, part_size, EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx, "boot%d", idx, true, MMC_BLK_DATA_AREA_BOOT); } } } card->ext_csd.raw_hc_erase_gap_size = ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; card->ext_csd.raw_sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.raw_sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.raw_sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.raw_trim_mult = ext_csd[EXT_CSD_TRIM_MULT]; if (card->ext_csd.rev >= 4) { /* * Enhanced area feature support -- check whether the eMMC * card has the Enhanced area enabled. If so, export enhanced * area offset and size to user by adding sysfs interface. */ card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { 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; /* * calculate the enhanced data area offset, in bytes */ card->ext_csd.enhanced_area_offset = (ext_csd[139] << 24) + (ext_csd[138] << 16) + (ext_csd[137] << 8) + ext_csd[136]; if (mmc_card_blockaddr(card)) card->ext_csd.enhanced_area_offset <<= 9; /* * calculate the enhanced data area size, in kilobytes */ card->ext_csd.enhanced_area_size = (ext_csd[142] << 16) + (ext_csd[141] << 8) + ext_csd[140]; card->ext_csd.enhanced_area_size *= (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); card->ext_csd.enhanced_area_size <<= 9; } else { /* * If the enhanced area is not enabled, disable these * device attributes. */ 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 = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.sec_feature_support = 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) { /* check whether the eMMC card support 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 && card->host->caps2 & MMC_CAP2_INIT_BKOPS) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN, 1, 0); if (err) pr_warning("%s: Enabling BKOPS failed\n", mmc_hostname(card->host)); else card->ext_csd.bkops_en = 1; } } /* 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]; } card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) card->erased_byte = 0xFF; 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]; } out: return err; }
/* * Decode extended CSD. */ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0; BUG_ON(!card); if (!ext_csd) return 0; /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; if (card->csd.structure == 3) { if (card->ext_csd.raw_ext_csd_structure > 2) { printk(KERN_ERR "%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), card->ext_csd.raw_ext_csd_structure); err = -EINVAL; #if defined(MMC_CHECK_EXT_CSD) /* For debugging about ext_csd register value */ mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_STRUCTURE); #endif goto out; } } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; /* eMMC 4.5 : ext_csd rev. is 6 * eMMC 5.0 : ext_csd rev. is 7 * It's temporary change. */ if (card->ext_csd.rev > 7) { printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; #if defined(MMC_CHECK_EXT_CSD) /* For debugging about ext_csd register value */ mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_REV); #endif goto out; } card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; card->ext_csd.raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3]; if (card->ext_csd.rev >= 2) { card->ext_csd.sectors = ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; /* Cards with density > 2GiB are sector addressed */ if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) mmc_card_set_blockaddr(card); } card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; if (card->host->caps2 & MMC_CAP2_HS200) { switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { case EXT_CSD_CARD_TYPE_SDR_ALL: case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V: case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V: case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52: card->ext_csd.hs_max_dtr = 200000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200; break; case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL: case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V: case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V: case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52: card->ext_csd.hs_max_dtr = 200000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V; break; case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL: case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V: case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V: case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52: card->ext_csd.hs_max_dtr = 200000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V; break; case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; break; case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; break; case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; break; case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; break; case EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 26000000; break; default: #if defined(MMC_CHECK_EXT_CSD) /* For debugging about ext_csd register value */ mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_CARD_TYPE); #endif /* MMC v4 spec says this cannot happen */ printk(KERN_WARNING "%s: card is mmc v4 but doesn't " "support any high-speed modes.\n", mmc_hostname(card->host)); #if defined(MMC_RETRY_READ_EXT_CSD) err = -EINVAL; goto out; #endif } } else { pr_debug("%s: Ignore device type HS200.\n", mmc_hostname(card->host)); switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_NO_HS200_MASK) { case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; break; case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; break; case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; break; case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; break; case EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 26000000; break; default: #if defined(MMC_CHECK_EXT_CSD) /* For debugging about ext_csd register value */ mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_CARD_TYPE); #endif /* MMC v4 spec says this cannot happen */ printk(KERN_WARNING "%s: card is mmc v4 but doesn't " "support any high-speed modes.\n", mmc_hostname(card->host)); #if defined(MMC_RETRY_READ_EXT_CSD) err = -EINVAL; goto out; #endif } } card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.raw_erase_timeout_mult = ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.raw_hc_erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; if (card->ext_csd.rev >= 3) { u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG]; card->ext_csd.boot_part_prot = ext_csd[EXT_CSD_BOOT_CONFIG_PROT]; /* EXT_CSD value is in units of 10ms, but we store in ms */ card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME]; /* Sleep / awake timeout in 100ns units */ if (sa_shift > 0 && sa_shift <= 0x17) card->ext_csd.sa_timeout = 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.erase_group_def = ext_csd[EXT_CSD_ERASE_GROUP_DEF]; card->ext_csd.hc_erase_timeout = 300 * ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.hc_erase_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; card->ext_csd.rel_sectors = ext_csd[EXT_CSD_REL_WR_SEC_C]; /* * There are two boot regions of equal size, defined in * multiples of 128K. */ card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; } card->ext_csd.raw_hc_erase_gap_size = ext_csd[EXT_CSD_PARTITION_ATTRIBUTE]; card->ext_csd.raw_sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.raw_sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.raw_sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.raw_trim_mult = ext_csd[EXT_CSD_TRIM_MULT]; card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if (card->ext_csd.rev >= 4) { /* * Enhanced area feature support -- check whether the eMMC * card has the Enhanced area enabled. If so, export enhanced * area offset and size to user by adding sysfs interface. */ if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { u8 hc_erase_grp_sz = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; u8 hc_wp_grp_sz = ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; card->ext_csd.enhanced_area_en = 1; /* * calculate the enhanced data area offset, in bytes */ card->ext_csd.enhanced_area_offset = (ext_csd[139] << 24) + (ext_csd[138] << 16) + (ext_csd[137] << 8) + ext_csd[136]; if (mmc_card_blockaddr(card)) card->ext_csd.enhanced_area_offset <<= 9; /* * calculate the enhanced data area size, in kilobytes */ card->ext_csd.enhanced_area_size = (ext_csd[142] << 16) + (ext_csd[141] << 8) + ext_csd[140]; card->ext_csd.enhanced_area_size *= (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); card->ext_csd.enhanced_area_size <<= 9; } else { /* * If the enhanced area is not enabled, disable these * device attributes. */ card->ext_csd.enhanced_area_offset = -EINVAL; card->ext_csd.enhanced_area_size = -EINVAL; } card->ext_csd.sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.trim_timeout = 300 * ext_csd[EXT_CSD_TRIM_MULT]; } if (card->ext_csd.rev >= 5) { /* enable discard feature if emmc is 4.41+ */ if ((ext_csd[EXT_CSD_VENDOR_SPECIFIC_FIELD + 0] & 0x1) && (card->cid.manfid == 0x15)) card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; /* 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]; } card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) card->erased_byte = 0xFF; 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; 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]; } out: return err; }
/* * Register a new MMC card with the driver model. */ int mmc_add_card(struct mmc_card *card) { int ret; const char *type; dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); card->removed = 0; switch (card->type) { case MMC_TYPE_MMC: type = "MMC"; break; case MMC_TYPE_SD: type = "SD"; if (mmc_card_blockaddr(card)) { if (mmc_card_ext_capacity(card)) type = "SDXC"; else type = "SDHC"; } break; case MMC_TYPE_SDIO: type = "SDIO"; break; case MMC_TYPE_SD_COMBO: type = "SD-combo"; if (mmc_card_blockaddr(card)) type = "SDHC-combo"; break; default: type = "?"; break; } if (mmc_host_is_spi(card->host)) { printk(KERN_INFO "%s: new %s%s%s card on SPI\n", mmc_hostname(card->host), mmc_card_highspeed(card) ? "high speed " : "", mmc_card_ddr_mode(card) ? "DDR " : "", type); } else { printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", mmc_hostname(card->host), mmc_sd_card_uhs(card) ? "ultra high speed " : (mmc_card_highspeed(card) ? "high speed " : ""), mmc_card_ddr_mode(card) ? "DDR " : "", type, card->rca); } #ifdef CONFIG_DEBUG_FS mmc_add_card_debugfs(card); #endif ret = device_add(&card->dev); if (ret) return ret; mmc_card_set_present(card); return 0; }
static int simple_sd_ioctl_single_rw(struct msdc_ioctl* msdc_ctl) { char l_buf[512]; struct scatterlist msdc_sg; struct mmc_data msdc_data; struct mmc_command msdc_cmd; struct mmc_request msdc_mrq; struct msdc_host *host_ctl; int ret = 0; host_ctl = mtk_msdc_host[msdc_ctl->host_num]; BUG_ON(!host_ctl); BUG_ON(!host_ctl->mmc); BUG_ON(!host_ctl->mmc->card); #ifdef MTK_MSDC_USE_CACHE if(msdc_ctl->iswrite && mmc_card_mmc(host_ctl->mmc->card) && (host_ctl->mmc->card->ext_csd.cache_ctrl & 0x1)) return simple_sd_ioctl_multi_rw(msdc_ctl); #endif mmc_claim_host(host_ctl->mmc); #if DEBUG_MMC_IOCTL printk("user want access %d partition\n",msdc_ctl->partition); #endif ret = mmc_send_ext_csd(host_ctl->mmc->card, l_buf); if (ret) { printk("mmc_send_ext_csd error, single rw\n"); goto single_end; } #ifdef MTK_EMMC_SUPPORT switch (msdc_ctl->partition){ case EMMC_PART_BOOT1: if (0x1 != (l_buf[179] & 0x7)){ /* change to access boot partition 1 */ l_buf[179] &= ~0x7; l_buf[179] |= 0x1; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; case EMMC_PART_BOOT2: if (0x2 != (l_buf[179] & 0x7)){ /* change to access boot partition 2 */ l_buf[179] &= ~0x7; l_buf[179] |= 0x2; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; default: /* make sure access partition is user data area */ if (0 != (l_buf[179] & 0x7)){ /* set back to access user area */ l_buf[179] &= ~0x7; l_buf[179] |= 0x0; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; } #endif if(msdc_ctl->total_size > 512){ msdc_ctl->result = -1; goto single_end; } #if DEBUG_MMC_IOCTL printk("start MSDC_SINGLE_READ_WRITE !!\n"); #endif memset(&msdc_data, 0, sizeof(struct mmc_data)); memset(&msdc_mrq, 0, sizeof(struct mmc_request)); memset(&msdc_cmd, 0, sizeof(struct mmc_command)); msdc_mrq.cmd = &msdc_cmd; msdc_mrq.data = &msdc_data; if(msdc_ctl->trans_type) dma_force[host_ctl->id] = FORCE_IN_DMA; else dma_force[host_ctl->id] = FORCE_IN_PIO; if (msdc_ctl->iswrite){ msdc_data.flags = MMC_DATA_WRITE; msdc_cmd.opcode = MMC_WRITE_BLOCK; msdc_data.blocks = msdc_ctl->total_size / 512; if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { if (copy_from_user(sg_msdc_multi_buffer, msdc_ctl->buffer, 512)){ dma_force[host_ctl->id] = FORCE_NOTHING; ret = -EFAULT; goto single_end; } } else { /* called from other kernel module */ memcpy(sg_msdc_multi_buffer, msdc_ctl->buffer, 512); } } else { msdc_data.flags = MMC_DATA_READ; msdc_cmd.opcode = MMC_READ_SINGLE_BLOCK; msdc_data.blocks = msdc_ctl->total_size / 512; memset(sg_msdc_multi_buffer, 0 , 512); } msdc_cmd.arg = msdc_ctl->address; if (!mmc_card_blockaddr(host_ctl->mmc->card)){ printk("the device is used byte address!\n"); msdc_cmd.arg <<= 9; } msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; msdc_data.stop = NULL; msdc_data.blksz = 512; msdc_data.sg = &msdc_sg; msdc_data.sg_len = 1; #if DEBUG_MMC_IOCTL printk("single block: ueser buf address is 0x%p!\n",msdc_ctl->buffer); #endif sg_init_one(&msdc_sg, sg_msdc_multi_buffer, msdc_ctl->total_size); mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card); mmc_wait_for_req(host_ctl->mmc, &msdc_mrq); if (!msdc_ctl->iswrite){ if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { if (copy_to_user(msdc_ctl->buffer,sg_msdc_multi_buffer,512)){ dma_force[host_ctl->id] = FORCE_NOTHING; ret = -EFAULT; goto single_end; } } else { /* called from other kernel module */ memcpy(msdc_ctl->buffer,sg_msdc_multi_buffer,512); } } if (msdc_ctl->partition){ ret = mmc_send_ext_csd(host_ctl->mmc->card,l_buf); if (ret) { printk("mmc_send_ext_csd error, single rw2\n"); goto single_end; } if (l_buf[179] & 0x7) { /* set back to access user area */ l_buf[179] &= ~0x7; l_buf[179] |= 0x0; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } } single_end: mmc_release_host(host_ctl->mmc); if (ret) { msdc_ctl->result = ret; } if (msdc_cmd.error) msdc_ctl->result= msdc_cmd.error; if (msdc_data.error) msdc_ctl->result= msdc_data.error; else msdc_ctl->result= 0; dma_force[host_ctl->id] = FORCE_NOTHING; return msdc_ctl->result; }
static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0, idx; unsigned int part_size; u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0; BUG_ON(!card); if (!ext_csd) return 0; card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; if (card->csd.structure == 3) { if (card->ext_csd.raw_ext_csd_structure > 2) { pr_err("%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), card->ext_csd.raw_ext_csd_structure); err = -EINVAL; goto out; } } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; if (card->ext_csd.rev > 7) { pr_err("%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; goto out; } mmc_fixup_device(card, mmc_fixups); card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; card->ext_csd.raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3]; if (card->ext_csd.rev >= 2) { card->ext_csd.sectors = ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) mmc_card_set_blockaddr(card); } card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; mmc_select_card_type(card); card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.raw_erase_timeout_mult = ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.raw_hc_erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; if (card->ext_csd.rev >= 3) { u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG]; card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME]; if (sa_shift > 0 && sa_shift <= 0x17) card->ext_csd.sa_timeout = 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.erase_group_def = ext_csd[EXT_CSD_ERASE_GROUP_DEF]; card->ext_csd.hc_erase_timeout = 300 * ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.hc_erase_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; card->ext_csd.rel_sectors = ext_csd[EXT_CSD_REL_WR_SEC_C]; if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host)) { for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) { part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; mmc_part_add(card, part_size, EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx, "boot%d", idx, true, MMC_BLK_DATA_AREA_BOOT); } } } card->ext_csd.raw_hc_erase_gap_size = ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; card->ext_csd.raw_sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.raw_sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.raw_sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.raw_trim_mult = ext_csd[EXT_CSD_TRIM_MULT]; if (card->ext_csd.rev >= 4) { card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { 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; card->ext_csd.enhanced_area_offset = (ext_csd[139] << 24) + (ext_csd[138] << 16) + (ext_csd[137] << 8) + ext_csd[136]; if (mmc_card_blockaddr(card)) card->ext_csd.enhanced_area_offset <<= 9; card->ext_csd.enhanced_area_size = (ext_csd[142] << 16) + (ext_csd[141] << 8) + ext_csd[140]; card->ext_csd.enhanced_area_size *= (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); card->ext_csd.enhanced_area_size <<= 9; } else { card->ext_csd.enhanced_area_offset = -EINVAL; card->ext_csd.enhanced_area_size = -EINVAL; } 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 = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.trim_timeout = 300 * ext_csd[EXT_CSD_TRIM_MULT]; 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 ((ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) && !(card->quirks & MMC_QUIRK_BROKEN_HPI)) { 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; card->ext_csd.out_of_int_time = ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10; } if ((ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) && card->ext_csd.hpi) { 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 && card->host->caps2 & MMC_CAP2_INIT_BKOPS) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN, 1, 0); if (err) pr_warn("%s: Enabling BKOPS failed\n", mmc_hostname(card->host)); else card->ext_csd.bkops_en = 1; } } pr_info("%s: BKOPS_EN bit = %d\n", mmc_hostname(card->host), card->ext_csd.bkops_en); 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]; card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT]; if (ext_csd[EXT_CSD_RPMB_MULT]) { 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]) card->erased_byte = 0xFF; else card->erased_byte = 0x0; 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]; } if (mmc_card_mmc(card)) { char *buf; int i, j; ssize_t n = 0; pr_info("%s: cid %08x%08x%08x%08x\n", mmc_hostname(card->host), card->raw_cid[0], card->raw_cid[1], card->raw_cid[2], card->raw_cid[3]); pr_info("%s: csd %08x%08x%08x%08x\n", mmc_hostname(card->host), card->raw_csd[0], card->raw_csd[1], card->raw_csd[2], card->raw_csd[3]); buf = kmalloc(512, GFP_KERNEL); if (buf) { for (i = 0; i < 32; i++) { for (j = 511 - (16 * i); j >= 496 - (16 * i); j--) n += sprintf(buf + n, "%02x", ext_csd[j]); n += sprintf(buf + n, "\n"); pr_info("%s: ext_csd %s", mmc_hostname(card->host), buf); n = 0; } } if (buf) kfree(buf); } out: return err; }
static int simple_sd_ioctl_multi_rw(struct msdc_ioctl* msdc_ctl) { char l_buf[512]; struct scatterlist msdc_sg; struct mmc_data msdc_data; struct mmc_command msdc_cmd; struct mmc_command msdc_stop; int ret = 0; #ifdef MTK_MSDC_USE_CMD23 struct mmc_command msdc_sbc; #endif struct mmc_request msdc_mrq; struct msdc_host *host_ctl; host_ctl = mtk_msdc_host[msdc_ctl->host_num]; BUG_ON(!host_ctl); BUG_ON(!host_ctl->mmc); BUG_ON(!host_ctl->mmc->card); mmc_claim_host(host_ctl->mmc); #if DEBUG_MMC_IOCTL printk("user want access %d partition\n",msdc_ctl->partition); #endif ret = mmc_send_ext_csd(host_ctl->mmc->card, l_buf); if (ret) { printk("mmc_send_ext_csd error, multi rw\n"); goto multi_end; } #ifdef MTK_EMMC_SUPPORT switch (msdc_ctl->partition){ case EMMC_PART_BOOT1: if (0x1 != (l_buf[179] & 0x7)){ /* change to access boot partition 1 */ l_buf[179] &= ~0x7; l_buf[179] |= 0x1; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; case EMMC_PART_BOOT2: if (0x2 != (l_buf[179] & 0x7)){ /* change to access boot partition 2 */ l_buf[179] &= ~0x7; l_buf[179] |= 0x2; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; default: /* make sure access partition is user data area */ if (0 != (l_buf[179] & 0x7)){ /* set back to access user area */ l_buf[179] &= ~0x7; l_buf[179] |= 0x0; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; } #endif if(msdc_ctl->total_size > 64*1024){ msdc_ctl->result = -1; goto multi_end; } memset(&msdc_data, 0, sizeof(struct mmc_data)); memset(&msdc_mrq, 0, sizeof(struct mmc_request)); memset(&msdc_cmd, 0, sizeof(struct mmc_command)); memset(&msdc_stop, 0, sizeof(struct mmc_command)); #ifdef MTK_MSDC_USE_CMD23 memset(&msdc_sbc, 0, sizeof(struct mmc_command)); #endif msdc_mrq.cmd = &msdc_cmd; msdc_mrq.data = &msdc_data; if(msdc_ctl->trans_type) dma_force[host_ctl->id] = FORCE_IN_DMA; else dma_force[host_ctl->id] = FORCE_IN_PIO; if (msdc_ctl->iswrite){ msdc_data.flags = MMC_DATA_WRITE; msdc_cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; msdc_data.blocks = msdc_ctl->total_size / 512; if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { if (copy_from_user(sg_msdc_multi_buffer, msdc_ctl->buffer, msdc_ctl->total_size)){ dma_force[host_ctl->id] = FORCE_NOTHING; ret = -EFAULT; goto multi_end; } } else { /* called from other kernel module */ memcpy(sg_msdc_multi_buffer, msdc_ctl->buffer, msdc_ctl->total_size); } } else { msdc_data.flags = MMC_DATA_READ; msdc_cmd.opcode = MMC_READ_MULTIPLE_BLOCK; msdc_data.blocks = msdc_ctl->total_size / 512; memset(sg_msdc_multi_buffer, 0 , msdc_ctl->total_size); } #ifdef MTK_MSDC_USE_CMD23 if ((mmc_card_mmc(host_ctl->mmc->card) || (mmc_card_sd(host_ctl->mmc->card) && host_ctl->mmc->card->scr.cmds & SD_SCR_CMD23_SUPPORT)) && !(host_ctl->mmc->card->quirks & MMC_QUIRK_BLK_NO_CMD23)){ msdc_mrq.sbc = &msdc_sbc; msdc_mrq.sbc->opcode = MMC_SET_BLOCK_COUNT; #ifdef MTK_MSDC_USE_CACHE /* if ioctl access cacheable partition data, there is on flush mechanism in msdc driver * so do reliable write .*/ if(mmc_card_mmc(host_ctl->mmc->card) && (host_ctl->mmc->card->ext_csd.cache_ctrl & 0x1) && (msdc_cmd.opcode == MMC_WRITE_MULTIPLE_BLOCK)) msdc_mrq.sbc->arg = msdc_data.blocks | (1<<31); else msdc_mrq.sbc->arg = msdc_data.blocks; #else msdc_mrq.sbc->arg = msdc_data.blocks; #endif msdc_mrq.sbc->flags = MMC_RSP_R1 | MMC_CMD_AC; } #endif msdc_cmd.arg = msdc_ctl->address; if (!mmc_card_blockaddr(host_ctl->mmc->card)){ printk("this device use byte address!!\n"); msdc_cmd.arg <<= 9; } msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; msdc_stop.opcode = MMC_STOP_TRANSMISSION; msdc_stop.arg = 0; msdc_stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; msdc_data.stop = &msdc_stop; msdc_data.blksz = 512; msdc_data.sg = &msdc_sg; msdc_data.sg_len = 1; #if DEBUG_MMC_IOCTL printk("total size is %d\n",msdc_ctl->total_size); #endif sg_init_one(&msdc_sg, sg_msdc_multi_buffer, msdc_ctl->total_size); mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card); mmc_wait_for_req(host_ctl->mmc, &msdc_mrq); if (!msdc_ctl->iswrite){ if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { if (copy_to_user(msdc_ctl->buffer, sg_msdc_multi_buffer, msdc_ctl->total_size)){ dma_force[host_ctl->id] = FORCE_NOTHING; ret = -EFAULT; goto multi_end; } } else { /* called from other kernel module */ memcpy(msdc_ctl->buffer, sg_msdc_multi_buffer, msdc_ctl->total_size); } } if (msdc_ctl->partition){ ret = mmc_send_ext_csd(host_ctl->mmc->card,l_buf); if (ret) { printk("mmc_send_ext_csd error, multi rw2\n"); goto multi_end; } if (l_buf[179] & 0x7) { /* set back to access user area */ l_buf[179] &= ~0x7; l_buf[179] |= 0x0; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } } multi_end: mmc_release_host(host_ctl->mmc); if (ret) { msdc_ctl->result = ret; } if (msdc_cmd.error) msdc_ctl->result = msdc_cmd.error; if (msdc_data.error){ msdc_ctl->result = msdc_data.error; } else { msdc_ctl->result = 0; } dma_force[host_ctl->id] = FORCE_NOTHING; return msdc_ctl->result; }
/* * Decode extended CSD. */ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0; BUG_ON(!card); if (!ext_csd) return 0; /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; if (card->csd.structure == 3) { if (card->ext_csd.raw_ext_csd_structure > 2) { printk(KERN_ERR "%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), card->ext_csd.raw_ext_csd_structure); err = -EINVAL; goto out; } } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; /* eMMC 4.5 : ext_csd rev. is 6 * eMMC 5.0 : ext_csd rev. is 7 * It's temporary change. */ if (card->ext_csd.rev > 7) { printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; goto out; } card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; card->ext_csd.raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3]; if (card->ext_csd.rev >= 2) { card->ext_csd.sectors = ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; /* Cards with density > 2GiB are sector addressed */ if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) mmc_card_set_blockaddr(card); } card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; mmc_select_card_type(card); card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.raw_erase_timeout_mult = ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.raw_hc_erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; if (card->ext_csd.rev >= 3) { u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG]; /* EXT_CSD value is in units of 10ms, but we store in ms */ card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME]; /* Sleep / awake timeout in 100ns units */ if (sa_shift > 0 && sa_shift <= 0x17) card->ext_csd.sa_timeout = 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.erase_group_def = ext_csd[EXT_CSD_ERASE_GROUP_DEF]; card->ext_csd.hc_erase_timeout = 300 * ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.hc_erase_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; card->ext_csd.rel_sectors = ext_csd[EXT_CSD_REL_WR_SEC_C]; /* * There are two boot regions of equal size, defined in * multiples of 128K. */ card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; } card->ext_csd.raw_hc_erase_gap_size = ext_csd[EXT_CSD_PARTITION_ATTRIBUTE]; card->ext_csd.raw_sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.raw_sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.raw_sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.raw_trim_mult = ext_csd[EXT_CSD_TRIM_MULT]; if (card->ext_csd.rev >= 4) { /* * Enhanced area feature support -- check whether the eMMC * card has the Enhanced area enabled. If so, export enhanced * area offset and size to user by adding sysfs interface. */ card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { u8 hc_erase_grp_sz = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; u8 hc_wp_grp_sz = ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; card->ext_csd.enhanced_area_en = 1; /* * calculate the enhanced data area offset, in bytes */ card->ext_csd.enhanced_area_offset = (ext_csd[139] << 24) + (ext_csd[138] << 16) + (ext_csd[137] << 8) + ext_csd[136]; if (mmc_card_blockaddr(card)) card->ext_csd.enhanced_area_offset <<= 9; /* * calculate the enhanced data area size, in kilobytes */ card->ext_csd.enhanced_area_size = (ext_csd[142] << 16) + (ext_csd[141] << 8) + ext_csd[140]; card->ext_csd.enhanced_area_size *= (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); card->ext_csd.enhanced_area_size <<= 9; } else { /* * If the enhanced area is not enabled, disable these * device attributes. */ card->ext_csd.enhanced_area_offset = -EINVAL; card->ext_csd.enhanced_area_size = -EINVAL; } card->ext_csd.sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.trim_timeout = 300 * ext_csd[EXT_CSD_TRIM_MULT]; } if (card->ext_csd.rev >= 5) card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM]; /* eMMC v4.5 or later */ if (card->ext_csd.rev >= 6) card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; else { /* * enable discard feature if emmc is 4.41+ Toshiba eMMC 19nm * Normally, emmc 4.5 use EXT_CSD[501] */ if ((ext_csd[501] & 0x3F) && (card->cid.manfid == 0x11)) card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; /* enable discard feature if emmc is 4.41+ moviNand (EXT_CSD_VENDOR_SPECIFIC_FIELD:64)*/ if ((ext_csd[64] & 0x1) && (card->cid.manfid == 0x15)) card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; } card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) card->erased_byte = 0xFF; else card->erased_byte = 0x0; out: return err; }
/* * Register a new MMC card with the driver model. */ int mmc_add_card(struct mmc_card *card) { int ret; const char *type; const char *uhs_bus_speed_mode = ""; static const char *const uhs_speeds[] = { [UHS_SDR12_BUS_SPEED] = "SDR12 ", [UHS_SDR25_BUS_SPEED] = "SDR25 ", [UHS_SDR50_BUS_SPEED] = "SDR50 ", [UHS_SDR104_BUS_SPEED] = "SDR104 ", [UHS_DDR50_BUS_SPEED] = "DDR50 ", }; dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); switch (card->type) { case MMC_TYPE_MMC: type = "MMC"; break; case MMC_TYPE_SD: type = "SD"; if (mmc_card_blockaddr(card)) { if (mmc_card_ext_capacity(card)) type = "SDXC"; else type = "SDHC"; } break; case MMC_TYPE_SDIO: type = "SDIO"; break; case MMC_TYPE_SD_COMBO: type = "SD-combo"; if (mmc_card_blockaddr(card)) type = "SDHC-combo"; break; default: type = "?"; break; } if (mmc_sd_card_uhs(card) && (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; if (mmc_host_is_spi(card->host)) { pr_info("%s: new %s%s%s card on SPI\n", mmc_hostname(card->host), mmc_card_highspeed(card) ? "high speed " : "", mmc_card_ddr_mode(card) ? "DDR " : "", type); } else { pr_info("%s: new %s%s%s%s%s%s card at address %04x\n", mmc_hostname(card->host), mmc_card_uhs(card) ? "ultra high speed " : (mmc_card_highspeed(card) ? "high speed " : ""), (mmc_card_hs400(card) ? "HS400 " : ""), (mmc_card_hs200(card) ? "HS200 " : ""), mmc_card_ddr_mode(card) ? "DDR " : "", uhs_bus_speed_mode, type, card->rca); } #ifdef CONFIG_MACH_LGE /* */ printk(KERN_INFO "[LGE][MMC][%-18s( )] mmc_hostname:%s, type:%s\n", __func__, mmc_hostname(card->host), type); #endif #ifdef CONFIG_DEBUG_FS mmc_add_card_debugfs(card); #endif mmc_init_context_info(card->host); if (mmc_use_core_runtime_pm(card->host)) { ret = pm_runtime_set_active(&card->dev); if (ret) pr_err("%s: %s: failed setting runtime active: ret: %d\n", mmc_hostname(card->host), __func__, ret); else if (!mmc_card_sdio(card)) pm_runtime_enable(&card->dev); } ret = device_add(&card->dev); #ifdef CONFIG_MACH_LGE /* */ if (ret) { printk(KERN_INFO "[LGE][MMC][%-18s( )] device_add & uevent posting fail!, ret:%d \n", __func__, ret); return ret; } else { printk(KERN_INFO "[LGE][MMC][%-18s( )] device_add & uevent posting complete!\n", __func__); } #else if (ret) return ret; #endif if (mmc_use_core_runtime_pm(card->host) && !mmc_card_sdio(card)) { card->rpm_attrib.show = show_rpm_delay; card->rpm_attrib.store = store_rpm_delay; sysfs_attr_init(&card->rpm_attrib.attr); card->rpm_attrib.attr.name = "runtime_pm_timeout"; card->rpm_attrib.attr.mode = S_IRUGO | S_IWUSR; ret = device_create_file(&card->dev, &card->rpm_attrib); if (ret) pr_err("%s: %s: creating runtime pm sysfs entry: failed: %d\n", mmc_hostname(card->host), __func__, ret); /* Default timeout is 10 seconds */ card->idle_timeout = RUNTIME_SUSPEND_DELAY_MS; } mmc_card_set_present(card); return 0; }
/* * Register a new MMC card with the driver model. */ int mmc_add_card(struct mmc_card *card) { int ret; const char *type; dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); switch (card->type) { case MMC_TYPE_MMC: type = "MMC"; break; case MMC_TYPE_SD: type = "SD"; if (mmc_card_blockaddr(card)) { if (mmc_card_ext_capacity(card)) type = "SDXC"; else type = "SDHC"; } break; case MMC_TYPE_SDIO: type = "SDIO"; break; case MMC_TYPE_SD_COMBO: type = "SD-combo"; if (mmc_card_blockaddr(card)) type = "SDHC-combo"; break; default: type = "?"; break; } if (mmc_host_is_spi(card->host)) { printk(KERN_INFO "%s: new %s%s%s card on SPI\n", mmc_hostname(card->host), mmc_card_highspeed(card) ? "high speed " : "", mmc_card_ddr_mode(card) ? "DDR " : "", type); } else { printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", mmc_hostname(card->host), mmc_sd_card_uhs(card) ? "ultra high speed " : (mmc_card_highspeed(card) ? "high speed " : ""), mmc_card_ddr_mode(card) ? "DDR " : "", type, card->rca); } #ifdef CONFIG_MACH_LGE /* LGE_CHANGE * MMC Driver update from G1TDR * 2012-01-14, [email protected] from G1TDR */ printk(KERN_INFO "[LGE][MMC][%-18s( )] mmc_hostname:%s, type:%s\n", __func__, mmc_hostname(card->host), type); #endif #ifdef CONFIG_DEBUG_FS mmc_add_card_debugfs(card); #endif ret = device_add(&card->dev); #ifdef CONFIG_MACH_LGE /* LGE_CHANGE * MMC Driver update from G1TDR * 2012-01-14, [email protected] from G1TDR */ if (ret) { printk(KERN_INFO "[LGE][MMC][%-18s( )] device_add & uevent posting fail!, ret:%d \n", __func__, ret); return ret; } else { printk(KERN_INFO "[LGE][MMC][%-18s( )] device_add & uevent posting complete!\n", __func__); } #else if (ret) return ret; #endif mmc_card_set_present(card); return 0; }
/* * Decode extended CSD. */ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0; BUG_ON(!card); if (!ext_csd) return 0; /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; if (card->csd.structure == 3) { if (card->ext_csd.raw_ext_csd_structure > 2) { printk(KERN_ERR "%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), card->ext_csd.raw_ext_csd_structure); err = -EINVAL; goto out; } } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; if (card->ext_csd.rev > 6) { printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; goto out; } card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; card->ext_csd.raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3]; if (card->ext_csd.rev >= 2) { card->ext_csd.sectors = ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; /* Cards with density > 2GiB are sector addressed */ if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) mmc_card_set_blockaddr(card); } card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; break; case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; break; case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; break; case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; break; case EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 26000000; break; default: /* MMC v4 spec says this cannot happen */ printk(KERN_WARNING "%s: card is mmc v4 but doesn't " "support any high-speed modes.\n", mmc_hostname(card->host)); } card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.raw_erase_timeout_mult = ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.raw_hc_erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; card->ext_csd.part_set_complete = ext_csd[EXT_CSD_PART_SET_COMPLETE]; if (card->ext_csd.rev >= 3) { u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG]; /* EXT_CSD value is in units of 10ms, but we store in ms */ card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME]; /* Sleep / awake timeout in 100ns units */ if (sa_shift > 0 && sa_shift <= 0x17) card->ext_csd.sa_timeout = 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.erase_group_def = ext_csd[EXT_CSD_ERASE_GROUP_DEF]; card->ext_csd.hc_erase_timeout = 300 * ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.hc_erase_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; card->ext_csd.rpmb_size = 128 * ext_csd[EXT_CSD_RPMB_SIZE_MULT]; card->ext_csd.rpmb_size <<= 2; /* Unit: half sector */ card->ext_csd.rel_sectors = ext_csd[EXT_CSD_REL_WR_SEC_C]; card->rpmb_max_w_blks = card->ext_csd.rel_sectors; if (card->rpmb_max_w_blks > RPMB_AVALIABLE_SECTORS) card->rpmb_max_w_blks = RPMB_AVALIABLE_SECTORS; card->rpmb_max_r_blks = RPMB_AVALIABLE_SECTORS; /* * There are two boot regions of equal size, defined in * multiples of 128K. */ card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; } card->ext_csd.raw_hc_erase_gap_size = ext_csd[EXT_CSD_PARTITION_ATTRIBUTE]; card->ext_csd.raw_sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.raw_sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.raw_sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.raw_trim_mult = ext_csd[EXT_CSD_TRIM_MULT]; card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if (card->ext_csd.rev >= 4) { /* * Enhanced area feature support -- check whether the eMMC * card has the Enhanced area enabled. If so, export enhanced * area offset and size to user by adding sysfs interface. */ if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { u8 hc_erase_grp_sz = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; u8 hc_wp_grp_sz = ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; card->ext_csd.enhanced_area_en = 1; /* * calculate the enhanced data area offset, in bytes */ card->ext_csd.enhanced_area_offset = (ext_csd[139] << 24) + (ext_csd[138] << 16) + (ext_csd[137] << 8) + ext_csd[136]; if (mmc_card_blockaddr(card)) card->ext_csd.enhanced_area_offset <<= 9; /* * calculate the enhanced data area size, in kilobytes */ card->ext_csd.enhanced_area_size = (ext_csd[142] << 16) + (ext_csd[141] << 8) + ext_csd[140]; card->ext_csd.enhanced_area_size *= (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); card->ext_csd.enhanced_area_size <<= 9; } else { /* * If the enhanced area is not enabled, disable these * device attributes. */ card->ext_csd.enhanced_area_offset = 0; card->ext_csd.enhanced_area_size = 0; } card->ext_csd.sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.sec_erase_mult = ext_csd[EXT_CSD_SEC_ERASE_MULT]; card->ext_csd.sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.trim_timeout = 300 * ext_csd[EXT_CSD_TRIM_MULT]; } 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]; } /* 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_set = ext_csd[EXT_CSD_WR_REL_SET]; 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]; } card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; if (card->ext_csd.rev >= 6) { /* eMMC v4.5 or later */ card->ext_csd.exception_events_ctrl = ext_csd[EXT_CSD_EXCEPTION_EVENTS_CTRL]; card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; card->ext_csd.power_off_longtime = 10 * ext_csd[EXT_CSD_POWER_OFF_LONG_TIME]; if ((ext_csd[EXT_CSD_DATA_SECTOR_SIZE] & 0x1) && (ext_csd[EXT_CSD_USE_NATIVE_SECTOR] & 0x1) && (ext_csd[EXT_CSD_NATIVE_SECTOR_SIZE] & 0x1) && (ext_csd[EXT_CSD_WR_REL_PARAM] & EXT_CSD_WR_REL_PARAM_EN)) { printk(KERN_INFO "%s: Large sector size enabled.\n", mmc_hostname(card->host)); card->ext_csd.large_sect_size_en = 1; } } if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) card->erased_byte = 0xFF; else card->erased_byte = 0x0; out: return err; }