func = sdio_alloc_func(card); if (IS_ERR(func)) return PTR_ERR(func);
func->num = fn;
if (!(card->quirks & MMC_QUIRK_NONSTD_SDIO)) {
ret = sdio_read_fbr(func); if (ret) goto fail;
ret = sdio_read_func_cis(func); if (ret) goto fail;
} else {
func->vendor = func->card->cis.vendor;
func->device = func->card->cis.device;
func->max_blksize = func->card->cis.blksize;
}
card->sdio_func[fn - 1] = func;
return 0;
fail: /* * It is okay to remove the function here even though we hold * the host lock as we haven't registered the device yet.
*/
sdio_remove_func(func); return ret;
}
staticint sdio_read_cccr(struct mmc_card *card, u32 ocr)
{ int ret; int cccr_vsn; int uhs = ocr & R4_18V_PRESENT; unsignedchar data; unsignedchar speed;
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CCCR, 0, &data); if (ret) goto out;
cccr_vsn = data & 0x0f;
if (cccr_vsn > SDIO_CCCR_REV_3_00) {
pr_err("%s: unrecognised CCCR structure version %d\n",
mmc_hostname(card->host), cccr_vsn); return -EINVAL;
}
card->cccr.sdio_vsn = (data & 0xf0) >> 4;
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CAPS, 0, &data); if (ret) goto out;
if (data & SDIO_CCCR_CAP_SMB)
card->cccr.multi_block = 1; if (data & SDIO_CCCR_CAP_LSC)
card->cccr.low_speed = 1; if (data & SDIO_CCCR_CAP_4BLS)
card->cccr.wide_bus = 1;
if (cccr_vsn >= SDIO_CCCR_REV_1_10) {
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_POWER, 0, &data); if (ret) goto out;
if (data & SDIO_POWER_SMPC)
card->cccr.high_power = 1;
}
if (cccr_vsn >= SDIO_CCCR_REV_1_20) {
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); if (ret) goto out;
ret = mmc_io_rw_direct(card, 0, 0,
SDIO_CCCR_DRIVE_STRENGTH, 0, &data); if (ret) goto out;
if (data & SDIO_DRIVE_SDTA)
card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_A; if (data & SDIO_DRIVE_SDTC)
card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_C; if (data & SDIO_DRIVE_SDTD)
card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_D;
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTERRUPT_EXT, 0, &data); if (ret) goto out;
if (data & SDIO_INTERRUPT_EXT_SAI) {
data |= SDIO_INTERRUPT_EXT_EAI;
ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_INTERRUPT_EXT,
data, NULL); if (ret) goto out;
card->cccr.enable_async_irq = 1;
}
}
/* if no uhs mode ensure we check for high speed */ if (!card->sw_caps.sd3_bus_mode) { if (speed & SDIO_SPEED_SHS) {
card->cccr.high_speed = 1;
card->sw_caps.hs_max_dtr = 50000000;
} else {
card->cccr.high_speed = 0;
card->sw_caps.hs_max_dtr = 25000000;
}
}
}
out: return ret;
}
staticint sdio_enable_wide(struct mmc_card *card)
{ int ret;
u8 ctrl;
if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) return 0;
if (card->cccr.low_speed && !card->cccr.wide_bus) return 0;
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); if (ret) return ret;
if ((ctrl & SDIO_BUS_WIDTH_MASK) == SDIO_BUS_WIDTH_RESERVED)
pr_warn("%s: SDIO_CCCR_IF is invalid: 0x%02x\n",
mmc_hostname(card->host), ctrl);
/* set as 4-bit bus width */
ctrl &= ~SDIO_BUS_WIDTH_MASK;
ctrl |= SDIO_BUS_WIDTH_4BIT;
ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); if (ret) return ret;
return 1;
}
/* * If desired, disconnect the pull-up resistor on CD/DAT[3] (pin 1) * of the card. This may be required on certain setups of boards, * controllers and embedded sdio device which do not need the card's * pull-up. As a result, card detection is disabled and power is saved.
*/ staticint sdio_disable_cd(struct mmc_card *card)
{ int ret;
u8 ctrl;
if (!mmc_card_disable_cd(card)) return 0;
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); if (ret) return ret;
/* * Devices that remain active during a system suspend are * put back into 1-bit mode.
*/ staticint sdio_disable_wide(struct mmc_card *card)
{ int ret;
u8 ctrl;
if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) return 0;
if (card->cccr.low_speed && !card->cccr.wide_bus) return 0;
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); if (ret) return ret;
ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); if (ret) return ret;
mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1);
return 0;
}
staticint sdio_disable_4bit_bus(struct mmc_card *card)
{ int err;
if (mmc_card_sdio(card)) goto out;
if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) return 0;
if (!(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) return 0;
err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); if (err) return err;
out: return sdio_disable_wide(card);
}
staticint sdio_enable_4bit_bus(struct mmc_card *card)
{ int err;
err = sdio_enable_wide(card); if (err <= 0) return err; if (mmc_card_sdio(card)) goto out;
if (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4) {
err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); if (err) {
sdio_disable_wide(card); return err;
}
}
out:
mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
return 0;
}
/* * Test if the card supports high-speed mode and, if so, switch to it.
*/ staticint mmc_sdio_switch_hs(struct mmc_card *card, int enable)
{ int ret;
u8 speed;
if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) return 0;
if (!card->cccr.high_speed) return 0;
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); if (ret) return ret;
if (enable)
speed |= SDIO_SPEED_EHS; else
speed &= ~SDIO_SPEED_EHS;
ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); if (ret) return ret;
return 1;
}
/* * Enable SDIO/combo card's high-speed mode. Return 0/1 if [not]supported.
*/ staticint sdio_enable_hs(struct mmc_card *card)
{ int ret;
ret = mmc_sdio_switch_hs(card, true); if (ret <= 0 || mmc_card_sdio(card)) return ret;
ret = mmc_sd_switch_hs(card); if (ret <= 0)
mmc_sdio_switch_hs(card, false);
if (mmc_card_hs(card)) { /* * The SDIO specification doesn't mention how * the CIS transfer speed register relates to * high-speed, but it seems that 50 MHz is * mandatory.
*/
max_dtr = 50000000;
} else {
max_dtr = card->cis.max_dtr;
}
if (mmc_card_sd_combo(card))
max_dtr = min(max_dtr, mmc_sd_get_max_clock(card));
if (drive_strength) { /* if error just use default for drive strength B */
err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0,
&card_strength); if (err) return;
/* * UHS-I specific initialization procedure
*/ staticint mmc_sdio_init_uhs_card(struct mmc_card *card)
{ int err;
if (!card->scr.sda_spec3) return 0;
/* Switch to wider bus */
err = sdio_enable_4bit_bus(card); if (err) goto out;
/* Set the driver strength for the card */
sdio_select_driver_type(card);
/* Set bus speed mode of the card */
err = sdio_set_bus_speed_mode(card); if (err) goto out;
/* * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104.
*/ if (!mmc_host_is_spi(card->host) &&
((card->host->ios.timing == MMC_TIMING_UHS_SDR50) ||
(card->host->ios.timing == MMC_TIMING_UHS_SDR104)))
err = mmc_execute_tuning(card);
out: return err;
}
/* * Reset the card by performing the same steps that are taken by * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. * * sdio_reset() is technically not needed. Having just powered up the * hardware, it should already be in reset state. However, some * platforms (such as SD8686 on OLPC) do not instantly cut power, * meaning that a reset is required when restoring power soon after * powering off. It is harmless in other cases. * * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec, * is not necessary for non-removable cards. However, it is required * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and * harmless in other situations. *
*/
/* * Handle the detection and initialisation of a card. * * In the case of a resume, "oldcard" will contain the card * we're trying to reinitialise.
*/ staticint mmc_sdio_init_card(struct mmc_host *host, u32 ocr, struct mmc_card *oldcard)
{ struct mmc_card *card; int err; int retries = 10;
u32 rocr = 0;
u32 ocr_card = ocr;
WARN_ON(!host->claimed);
/* to query card if 1.8V signalling is supported */ if (mmc_host_can_uhs(host))
ocr |= R4_18V_PRESENT;
try_again: if (!retries) {
pr_warn("%s: Skipping voltage switch\n", mmc_hostname(host));
ocr &= ~R4_18V_PRESENT;
}
/* * Inform the card of the voltage
*/
err = mmc_send_io_op_cond(host, ocr, &rocr); if (err) return err;
/* * For SPI, enable CRC as appropriate.
*/ if (mmc_host_is_spi(host)) {
err = mmc_spi_set_crc(host, use_spi_crc); if (err) return err;
}
/* * Call the optional HC's init_card function to handle quirks.
*/ if (host->ops->init_card)
host->ops->init_card(host, card);
mmc_fixup_device(card, sdio_card_init_methods);
card->ocr = ocr_card;
/* * If the host and card support UHS-I mode request the card * to switch to 1.8V signaling level. No 1.8v signalling if * UHS mode is not enabled to maintain compatibility and some * systems that claim 1.8v signalling in fact do not support * it. Per SDIO spec v3, section 3.1.2, if the voltage is already * 1.8v, the card sets S18A to 0 in the R4 response. So it will * fails to check rocr & R4_18V_PRESENT, but we still need to * try to init uhs card. sdio_read_cccr will take over this task * to make sure which speed mode should work.
*/ if (rocr & ocr & R4_18V_PRESENT) {
err = mmc_set_uhs_voltage(host, ocr_card); if (err == -EAGAIN) {
mmc_sdio_pre_init(host, ocr_card, card);
retries--; goto try_again;
} elseif (err) {
ocr &= ~R4_18V_PRESENT;
}
}
/* * For native busses: set card RCA and quit open drain mode.
*/ if (!mmc_host_is_spi(host)) {
err = mmc_send_relative_addr(host, &card->rca); if (err) goto remove;
/* * Update oldcard with the new RCA received from the SDIO * device -- we're doing this so that it's updated in the * "card" struct when oldcard overwrites that later.
*/ if (oldcard)
oldcard->rca = card->rca;
}
/* * Read CSD, before selecting the card
*/ if (!oldcard && mmc_card_sd_combo(card)) {
err = mmc_sd_get_csd(card, false); if (err) goto remove;
mmc_decode_cid(card);
}
/* * Select card, as all following commands rely on that.
*/ if (!mmc_host_is_spi(host)) {
err = mmc_select_card(card); if (err) goto remove;
}
if (card->quirks & MMC_QUIRK_NONSTD_SDIO) { /* * This is non-standard SDIO device, meaning it doesn't * have any CIA (Common I/O area) registers present. * It's host's responsibility to fill cccr and cis * structures in init_card().
*/
mmc_set_clock(host, card->cis.max_dtr);
if (card->cccr.high_speed) {
mmc_set_timing(card->host, MMC_TIMING_SD_HS);
}
if (oldcard)
mmc_remove_card(card); else
host->card = card;
return 0;
}
/* * Read the common registers. Note that we should try to * validate whether UHS would work or not.
*/
err = sdio_read_cccr(card, ocr); if (err) {
mmc_sdio_pre_init(host, ocr_card, card); if (ocr & R4_18V_PRESENT) { /* Retry init sequence, but without R4_18V_PRESENT. */
retries = 0; goto try_again;
} return err;
}
/* * Read the common CIS tuples.
*/
err = sdio_read_common_cis(card); if (err) goto remove;
if (mmc_card_sd_combo(card)) {
err = mmc_sd_setup_card(host, card, oldcard != NULL); /* handle as SDIO-only card if memory init failed */ if (err) {
mmc_go_idle(host); if (mmc_host_is_spi(host)) /* should not fail, as it worked previously */
mmc_spi_set_crc(host, use_spi_crc);
card->type = MMC_TYPE_SDIO;
} else
card->dev.type = &sd_type;
}
/* * If needed, disconnect card detection pull-up resistor.
*/
err = sdio_disable_cd(card); if (err) goto remove;
/* Initialization sequence for UHS-I cards */ /* Only if card supports 1.8v and UHS signaling */ if ((ocr & R4_18V_PRESENT) && card->sw_caps.sd3_bus_mode) {
err = mmc_sdio_init_uhs_card(card); if (err) goto remove;
} else { /* * Switch to high-speed (if supported).
*/
err = sdio_enable_hs(card); if (err > 0)
mmc_set_timing(card->host, MMC_TIMING_SD_HS); elseif (err) goto remove;
/* * Change to the card's maximum speed.
*/
mmc_set_clock(host, mmc_sdio_get_max_clock(card));
/* * Switch to wider bus (if supported).
*/
err = sdio_enable_4bit_bus(card); if (err) goto remove;
}
if (host->caps2 & MMC_CAP2_AVOID_3_3V &&
host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
pr_err("%s: Host failed to negotiate down from 3.3V\n",
mmc_hostname(host));
err = -EINVAL; goto remove;
}
host->card = card; return 0;
mismatch:
pr_debug("%s: Perhaps the card was replaced\n", mmc_hostname(host));
remove: if (oldcard != card)
mmc_remove_card(card); return err;
}
staticint mmc_sdio_reinit_card(struct mmc_host *host)
{ int ret;
ret = mmc_sdio_pre_init(host, host->card->ocr, NULL); if (ret) return ret;
/* * Card detection callback from host.
*/ staticvoid mmc_sdio_detect(struct mmc_host *host)
{ int err;
/* Make sure card is powered before detecting it */ if (host->caps & MMC_CAP_POWER_OFF_CARD) {
err = pm_runtime_resume_and_get(&host->card->dev); if (err < 0) goto out;
}
mmc_claim_host(host);
/* * Just check if our card has been removed.
*/
err = _mmc_detect_card_removed(host);
mmc_release_host(host);
/* * Tell PM core it's OK to power off the card now. * * The _sync variant is used in order to ensure that the card * is left powered off in case an error occurred, and the card * is going to be removed. * * Since there is no specific reason to believe a new user * is about to show up at this point, the _sync variant is * desirable anyway.
*/ if (host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_sync(&host->card->dev);
/* * SDIO pre_suspend. We need to suspend all functions separately. * Therefore all registered functions must have drivers with suspend * and resume methods. Failing that we simply remove the whole card.
*/ staticint mmc_sdio_pre_suspend(struct mmc_host *host)
{ int i;
for (i = 0; i < host->card->sdio_funcs; i++) { struct sdio_func *func = host->card->sdio_func[i]; if (func && sdio_func_present(func) && func->dev.driver) { conststruct dev_pm_ops *pmops = func->dev.driver->pm; if (!pmops || !pmops->suspend || !pmops->resume) /* force removal of entire card in that case */ goto remove;
}
}
return 0;
remove: if (!mmc_card_is_removable(host)) {
dev_warn(mmc_dev(host), "missing suspend/resume ops for non-removable SDIO card\n"); /* Don't remove a non-removable card - we can't re-detect it. */ return 0;
}
/* Remove the SDIO card and let it be re-detected later on. */
mmc_sdio_remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
mmc_power_off(host);
mmc_release_host(host);
host->pm_flags = 0;
/* * Restore power and reinitialize the card when needed. Note that a * removable card is checked from a detect work later on in the resume * process.
*/ if (!mmc_card_keep_power(host)) {
mmc_power_up(host, host->card->ocr); /* * Tell runtime PM core we just powered up the card, * since it still believes the card is powered off. * Note that currently runtime PM is only enabled * for SDIO cards that are MMC_CAP_POWER_OFF_CARD
*/ if (host->caps & MMC_CAP_POWER_OFF_CARD) {
pm_runtime_disable(&host->card->dev);
pm_runtime_set_active(&host->card->dev);
pm_runtime_enable(&host->card->dev);
}
err = mmc_sdio_reinit_card(host);
} elseif (mmc_card_wake_sdio_irq(host)) { /* * We may have switched to 1-bit mode during suspend, * need to hold retuning, because tuning only supprt * 4-bit mode or 8 bit mode.
*/
mmc_retune_hold_now(host);
err = sdio_enable_4bit_bus(host->card);
mmc_retune_release(host);
}
if (err) goto out;
/* Allow SDIO IRQs to be processed again. */
mmc_card_clr_suspended(host->card);
if (host->sdio_irqs) { if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD))
wake_up_process(host->sdio_irq_thread); elseif (host->caps & MMC_CAP_SDIO_IRQ)
schedule_work(&host->sdio_irq_work);
}
staticint mmc_sdio_runtime_suspend(struct mmc_host *host)
{ /* No references to the card, cut the power to it. */
mmc_claim_host(host);
mmc_power_off(host);
mmc_release_host(host);
return 0;
}
staticint mmc_sdio_runtime_resume(struct mmc_host *host)
{ int ret;
/* Restore power and re-initialize. */
mmc_claim_host(host);
mmc_power_up(host, host->card->ocr);
ret = mmc_sdio_reinit_card(host);
mmc_release_host(host);
return ret;
}
/* * SDIO HW reset * * Returns 0 if the HW reset was executed synchronously, returns 1 if the HW * reset was asynchronously scheduled, else a negative error code.
*/ staticint mmc_sdio_hw_reset(struct mmc_host *host)
{ struct mmc_card *card = host->card;
/* * In case the card is shared among multiple func drivers, reset the * card through a rescan work. In this way it will be removed and * re-detected, thus all func drivers becomes informed about it.
*/ if (atomic_read(&card->sdio_funcs_probed) > 1) { if (mmc_card_removed(card)) return 1;
host->rescan_entered = 0;
mmc_card_set_removed(card);
_mmc_detect_change(host, 0, false); return 1;
}
/* * A single func driver has been probed, then let's skip the heavy * hotplug dance above and execute the reset immediately.
*/
mmc_power_cycle(host, card->ocr); return mmc_sdio_reinit_card(host);
}
/* * Starting point for SDIO card init.
*/ int mmc_attach_sdio(struct mmc_host *host)
{ int err, i, funcs;
u32 ocr, rocr; struct mmc_card *card;
WARN_ON(!host->claimed);
err = mmc_send_io_op_cond(host, 0, &ocr); if (err) return err;
mmc_attach_bus(host, &mmc_sdio_ops); if (host->ocr_avail_sdio)
host->ocr_avail = host->ocr_avail_sdio;
rocr = mmc_select_voltage(host, ocr);
/* * Can we support the voltage(s) of the card(s)?
*/ if (!rocr) {
err = -EINVAL; goto err;
}
/* * Detect and init the card.
*/
err = mmc_sdio_init_card(host, rocr, NULL); if (err) goto err;
card = host->card;
/* * Enable runtime PM only if supported by host+card+board
*/ if (host->caps & MMC_CAP_POWER_OFF_CARD) { /* * Do not allow runtime suspend until after SDIO function * devices are added.
*/
pm_runtime_get_noresume(&card->dev);
/* * Let runtime PM core know our card is active
*/
err = pm_runtime_set_active(&card->dev); if (err) goto remove;
/* * Enable runtime PM for this card
*/
pm_runtime_enable(&card->dev);
}
/* * The number of functions on the card is encoded inside * the ocr.
*/
funcs = (ocr & 0x70000000) >> 28;
card->sdio_funcs = 0;
/* * Initialize (but don't add) all present functions.
*/ for (i = 0; i < funcs; i++, card->sdio_funcs++) {
err = sdio_init_func(host->card, i + 1); if (err) goto remove;
/* * Enable Runtime PM for this func (if supported)
*/ if (host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_enable(&card->sdio_func[i]->dev);
}
/* * First add the card to the driver model...
*/
mmc_release_host(host);
err = mmc_add_card(host->card); if (err) goto remove_added;
/* * ...then the SDIO functions.
*/ for (i = 0;i < funcs;i++) {
err = sdio_add_func(host->card->sdio_func[i]); if (err) goto remove_added;
}
if (host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put(&card->dev);
mmc_claim_host(host); return 0;
remove:
mmc_release_host(host);
remove_added: /* * The devices are being deleted so it is not necessary to disable * runtime PM. Similarly we also don't pm_runtime_put() the SDIO card * because it needs to be active to remove any function devices that * were probed, and after that it gets deleted.
*/
mmc_sdio_remove(host);
mmc_claim_host(host);
err:
mmc_detach_bus(host);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.