162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/drivers/mmc/sdio.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2006-2007 Pierre Ossman 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/err.h> 962306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1062306a36Sopenharmony_ci#include <linux/sysfs.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/mmc/host.h> 1362306a36Sopenharmony_ci#include <linux/mmc/card.h> 1462306a36Sopenharmony_ci#include <linux/mmc/mmc.h> 1562306a36Sopenharmony_ci#include <linux/mmc/sdio.h> 1662306a36Sopenharmony_ci#include <linux/mmc/sdio_func.h> 1762306a36Sopenharmony_ci#include <linux/mmc/sdio_ids.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "core.h" 2062306a36Sopenharmony_ci#include "card.h" 2162306a36Sopenharmony_ci#include "host.h" 2262306a36Sopenharmony_ci#include "bus.h" 2362306a36Sopenharmony_ci#include "quirks.h" 2462306a36Sopenharmony_ci#include "sd.h" 2562306a36Sopenharmony_ci#include "sdio_bus.h" 2662306a36Sopenharmony_ci#include "mmc_ops.h" 2762306a36Sopenharmony_ci#include "sd_ops.h" 2862306a36Sopenharmony_ci#include "sdio_ops.h" 2962306a36Sopenharmony_ci#include "sdio_cis.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciMMC_DEV_ATTR(vendor, "0x%04x\n", card->cis.vendor); 3262306a36Sopenharmony_ciMMC_DEV_ATTR(device, "0x%04x\n", card->cis.device); 3362306a36Sopenharmony_ciMMC_DEV_ATTR(revision, "%u.%u\n", card->major_rev, card->minor_rev); 3462306a36Sopenharmony_ciMMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); 3562306a36Sopenharmony_ciMMC_DEV_ATTR(rca, "0x%04x\n", card->rca); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define sdio_info_attr(num) \ 3862306a36Sopenharmony_cistatic ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf) \ 3962306a36Sopenharmony_ci{ \ 4062306a36Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); \ 4162306a36Sopenharmony_ci \ 4262306a36Sopenharmony_ci if (num > card->num_info) \ 4362306a36Sopenharmony_ci return -ENODATA; \ 4462306a36Sopenharmony_ci if (!card->info[num - 1][0]) \ 4562306a36Sopenharmony_ci return 0; \ 4662306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", card->info[num - 1]); \ 4762306a36Sopenharmony_ci} \ 4862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(info##num) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cisdio_info_attr(1); 5162306a36Sopenharmony_cisdio_info_attr(2); 5262306a36Sopenharmony_cisdio_info_attr(3); 5362306a36Sopenharmony_cisdio_info_attr(4); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic struct attribute *sdio_std_attrs[] = { 5662306a36Sopenharmony_ci &dev_attr_vendor.attr, 5762306a36Sopenharmony_ci &dev_attr_device.attr, 5862306a36Sopenharmony_ci &dev_attr_revision.attr, 5962306a36Sopenharmony_ci &dev_attr_info1.attr, 6062306a36Sopenharmony_ci &dev_attr_info2.attr, 6162306a36Sopenharmony_ci &dev_attr_info3.attr, 6262306a36Sopenharmony_ci &dev_attr_info4.attr, 6362306a36Sopenharmony_ci &dev_attr_ocr.attr, 6462306a36Sopenharmony_ci &dev_attr_rca.attr, 6562306a36Sopenharmony_ci NULL, 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ciATTRIBUTE_GROUPS(sdio_std); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic struct device_type sdio_type = { 7062306a36Sopenharmony_ci .groups = sdio_std_groups, 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic int sdio_read_fbr(struct sdio_func *func) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci int ret; 7662306a36Sopenharmony_ci unsigned char data; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (mmc_card_nonstd_func_interface(func->card)) { 7962306a36Sopenharmony_ci func->class = SDIO_CLASS_NONE; 8062306a36Sopenharmony_ci return 0; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci ret = mmc_io_rw_direct(func->card, 0, 0, 8462306a36Sopenharmony_ci SDIO_FBR_BASE(func->num) + SDIO_FBR_STD_IF, 0, &data); 8562306a36Sopenharmony_ci if (ret) 8662306a36Sopenharmony_ci goto out; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci data &= 0x0f; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (data == 0x0f) { 9162306a36Sopenharmony_ci ret = mmc_io_rw_direct(func->card, 0, 0, 9262306a36Sopenharmony_ci SDIO_FBR_BASE(func->num) + SDIO_FBR_STD_IF_EXT, 0, &data); 9362306a36Sopenharmony_ci if (ret) 9462306a36Sopenharmony_ci goto out; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci func->class = data; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciout: 10062306a36Sopenharmony_ci return ret; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic int sdio_init_func(struct mmc_card *card, unsigned int fn) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci int ret; 10662306a36Sopenharmony_ci struct sdio_func *func; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (WARN_ON(fn > SDIO_MAX_FUNCS)) 10962306a36Sopenharmony_ci return -EINVAL; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci func = sdio_alloc_func(card); 11262306a36Sopenharmony_ci if (IS_ERR(func)) 11362306a36Sopenharmony_ci return PTR_ERR(func); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci func->num = fn; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (!(card->quirks & MMC_QUIRK_NONSTD_SDIO)) { 11862306a36Sopenharmony_ci ret = sdio_read_fbr(func); 11962306a36Sopenharmony_ci if (ret) 12062306a36Sopenharmony_ci goto fail; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci ret = sdio_read_func_cis(func); 12362306a36Sopenharmony_ci if (ret) 12462306a36Sopenharmony_ci goto fail; 12562306a36Sopenharmony_ci } else { 12662306a36Sopenharmony_ci func->vendor = func->card->cis.vendor; 12762306a36Sopenharmony_ci func->device = func->card->cis.device; 12862306a36Sopenharmony_ci func->max_blksize = func->card->cis.blksize; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci card->sdio_func[fn - 1] = func; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci return 0; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cifail: 13662306a36Sopenharmony_ci /* 13762306a36Sopenharmony_ci * It is okay to remove the function here even though we hold 13862306a36Sopenharmony_ci * the host lock as we haven't registered the device yet. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ci sdio_remove_func(func); 14162306a36Sopenharmony_ci return ret; 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic int sdio_read_cccr(struct mmc_card *card, u32 ocr) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci int ret; 14762306a36Sopenharmony_ci int cccr_vsn; 14862306a36Sopenharmony_ci int uhs = ocr & R4_18V_PRESENT; 14962306a36Sopenharmony_ci unsigned char data; 15062306a36Sopenharmony_ci unsigned char speed; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CCCR, 0, &data); 15362306a36Sopenharmony_ci if (ret) 15462306a36Sopenharmony_ci goto out; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci cccr_vsn = data & 0x0f; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (cccr_vsn > SDIO_CCCR_REV_3_00) { 15962306a36Sopenharmony_ci pr_err("%s: unrecognised CCCR structure version %d\n", 16062306a36Sopenharmony_ci mmc_hostname(card->host), cccr_vsn); 16162306a36Sopenharmony_ci return -EINVAL; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci card->cccr.sdio_vsn = (data & 0xf0) >> 4; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CAPS, 0, &data); 16762306a36Sopenharmony_ci if (ret) 16862306a36Sopenharmony_ci goto out; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (data & SDIO_CCCR_CAP_SMB) 17162306a36Sopenharmony_ci card->cccr.multi_block = 1; 17262306a36Sopenharmony_ci if (data & SDIO_CCCR_CAP_LSC) 17362306a36Sopenharmony_ci card->cccr.low_speed = 1; 17462306a36Sopenharmony_ci if (data & SDIO_CCCR_CAP_4BLS) 17562306a36Sopenharmony_ci card->cccr.wide_bus = 1; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci if (cccr_vsn >= SDIO_CCCR_REV_1_10) { 17862306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_POWER, 0, &data); 17962306a36Sopenharmony_ci if (ret) 18062306a36Sopenharmony_ci goto out; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (data & SDIO_POWER_SMPC) 18362306a36Sopenharmony_ci card->cccr.high_power = 1; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (cccr_vsn >= SDIO_CCCR_REV_1_20) { 18762306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); 18862306a36Sopenharmony_ci if (ret) 18962306a36Sopenharmony_ci goto out; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci card->scr.sda_spec3 = 0; 19262306a36Sopenharmony_ci card->sw_caps.sd3_bus_mode = 0; 19362306a36Sopenharmony_ci card->sw_caps.sd3_drv_type = 0; 19462306a36Sopenharmony_ci if (cccr_vsn >= SDIO_CCCR_REV_3_00 && uhs) { 19562306a36Sopenharmony_ci card->scr.sda_spec3 = 1; 19662306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, 19762306a36Sopenharmony_ci SDIO_CCCR_UHS, 0, &data); 19862306a36Sopenharmony_ci if (ret) 19962306a36Sopenharmony_ci goto out; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (mmc_host_uhs(card->host)) { 20262306a36Sopenharmony_ci if (data & SDIO_UHS_DDR50) 20362306a36Sopenharmony_ci card->sw_caps.sd3_bus_mode 20462306a36Sopenharmony_ci |= SD_MODE_UHS_DDR50 | SD_MODE_UHS_SDR50 20562306a36Sopenharmony_ci | SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci if (data & SDIO_UHS_SDR50) 20862306a36Sopenharmony_ci card->sw_caps.sd3_bus_mode 20962306a36Sopenharmony_ci |= SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR25 21062306a36Sopenharmony_ci | SD_MODE_UHS_SDR12; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (data & SDIO_UHS_SDR104) 21362306a36Sopenharmony_ci card->sw_caps.sd3_bus_mode 21462306a36Sopenharmony_ci |= SD_MODE_UHS_SDR104 | SD_MODE_UHS_SDR50 21562306a36Sopenharmony_ci | SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, 21962306a36Sopenharmony_ci SDIO_CCCR_DRIVE_STRENGTH, 0, &data); 22062306a36Sopenharmony_ci if (ret) 22162306a36Sopenharmony_ci goto out; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (data & SDIO_DRIVE_SDTA) 22462306a36Sopenharmony_ci card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_A; 22562306a36Sopenharmony_ci if (data & SDIO_DRIVE_SDTC) 22662306a36Sopenharmony_ci card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_C; 22762306a36Sopenharmony_ci if (data & SDIO_DRIVE_SDTD) 22862306a36Sopenharmony_ci card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_D; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTERRUPT_EXT, 0, &data); 23162306a36Sopenharmony_ci if (ret) 23262306a36Sopenharmony_ci goto out; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (data & SDIO_INTERRUPT_EXT_SAI) { 23562306a36Sopenharmony_ci data |= SDIO_INTERRUPT_EXT_EAI; 23662306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_INTERRUPT_EXT, 23762306a36Sopenharmony_ci data, NULL); 23862306a36Sopenharmony_ci if (ret) 23962306a36Sopenharmony_ci goto out; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci card->cccr.enable_async_irq = 1; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci /* if no uhs mode ensure we check for high speed */ 24662306a36Sopenharmony_ci if (!card->sw_caps.sd3_bus_mode) { 24762306a36Sopenharmony_ci if (speed & SDIO_SPEED_SHS) { 24862306a36Sopenharmony_ci card->cccr.high_speed = 1; 24962306a36Sopenharmony_ci card->sw_caps.hs_max_dtr = 50000000; 25062306a36Sopenharmony_ci } else { 25162306a36Sopenharmony_ci card->cccr.high_speed = 0; 25262306a36Sopenharmony_ci card->sw_caps.hs_max_dtr = 25000000; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ciout: 25862306a36Sopenharmony_ci return ret; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic int sdio_enable_wide(struct mmc_card *card) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci int ret; 26462306a36Sopenharmony_ci u8 ctrl; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) 26762306a36Sopenharmony_ci return 0; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (card->cccr.low_speed && !card->cccr.wide_bus) 27062306a36Sopenharmony_ci return 0; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); 27362306a36Sopenharmony_ci if (ret) 27462306a36Sopenharmony_ci return ret; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if ((ctrl & SDIO_BUS_WIDTH_MASK) == SDIO_BUS_WIDTH_RESERVED) 27762306a36Sopenharmony_ci pr_warn("%s: SDIO_CCCR_IF is invalid: 0x%02x\n", 27862306a36Sopenharmony_ci mmc_hostname(card->host), ctrl); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* set as 4-bit bus width */ 28162306a36Sopenharmony_ci ctrl &= ~SDIO_BUS_WIDTH_MASK; 28262306a36Sopenharmony_ci ctrl |= SDIO_BUS_WIDTH_4BIT; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); 28562306a36Sopenharmony_ci if (ret) 28662306a36Sopenharmony_ci return ret; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci return 1; 28962306a36Sopenharmony_ci} 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci/* 29262306a36Sopenharmony_ci * If desired, disconnect the pull-up resistor on CD/DAT[3] (pin 1) 29362306a36Sopenharmony_ci * of the card. This may be required on certain setups of boards, 29462306a36Sopenharmony_ci * controllers and embedded sdio device which do not need the card's 29562306a36Sopenharmony_ci * pull-up. As a result, card detection is disabled and power is saved. 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_cistatic int sdio_disable_cd(struct mmc_card *card) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci int ret; 30062306a36Sopenharmony_ci u8 ctrl; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (!mmc_card_disable_cd(card)) 30362306a36Sopenharmony_ci return 0; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); 30662306a36Sopenharmony_ci if (ret) 30762306a36Sopenharmony_ci return ret; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci ctrl |= SDIO_BUS_CD_DISABLE; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci return mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci/* 31562306a36Sopenharmony_ci * Devices that remain active during a system suspend are 31662306a36Sopenharmony_ci * put back into 1-bit mode. 31762306a36Sopenharmony_ci */ 31862306a36Sopenharmony_cistatic int sdio_disable_wide(struct mmc_card *card) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci int ret; 32162306a36Sopenharmony_ci u8 ctrl; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) 32462306a36Sopenharmony_ci return 0; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (card->cccr.low_speed && !card->cccr.wide_bus) 32762306a36Sopenharmony_ci return 0; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); 33062306a36Sopenharmony_ci if (ret) 33162306a36Sopenharmony_ci return ret; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (!(ctrl & SDIO_BUS_WIDTH_4BIT)) 33462306a36Sopenharmony_ci return 0; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci ctrl &= ~SDIO_BUS_WIDTH_4BIT; 33762306a36Sopenharmony_ci ctrl |= SDIO_BUS_ASYNC_INT; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); 34062306a36Sopenharmony_ci if (ret) 34162306a36Sopenharmony_ci return ret; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return 0; 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic int sdio_disable_4bit_bus(struct mmc_card *card) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci int err; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci if (mmc_card_sdio(card)) 35362306a36Sopenharmony_ci goto out; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) 35662306a36Sopenharmony_ci return 0; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci if (!(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) 35962306a36Sopenharmony_ci return 0; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); 36262306a36Sopenharmony_ci if (err) 36362306a36Sopenharmony_ci return err; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ciout: 36662306a36Sopenharmony_ci return sdio_disable_wide(card); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cistatic int sdio_enable_4bit_bus(struct mmc_card *card) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci int err; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci err = sdio_enable_wide(card); 37562306a36Sopenharmony_ci if (err <= 0) 37662306a36Sopenharmony_ci return err; 37762306a36Sopenharmony_ci if (mmc_card_sdio(card)) 37862306a36Sopenharmony_ci goto out; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4) { 38162306a36Sopenharmony_ci err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); 38262306a36Sopenharmony_ci if (err) { 38362306a36Sopenharmony_ci sdio_disable_wide(card); 38462306a36Sopenharmony_ci return err; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ciout: 38862306a36Sopenharmony_ci mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci return 0; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci/* 39562306a36Sopenharmony_ci * Test if the card supports high-speed mode and, if so, switch to it. 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_cistatic int mmc_sdio_switch_hs(struct mmc_card *card, int enable) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci int ret; 40062306a36Sopenharmony_ci u8 speed; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) 40362306a36Sopenharmony_ci return 0; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (!card->cccr.high_speed) 40662306a36Sopenharmony_ci return 0; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); 40962306a36Sopenharmony_ci if (ret) 41062306a36Sopenharmony_ci return ret; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (enable) 41362306a36Sopenharmony_ci speed |= SDIO_SPEED_EHS; 41462306a36Sopenharmony_ci else 41562306a36Sopenharmony_ci speed &= ~SDIO_SPEED_EHS; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); 41862306a36Sopenharmony_ci if (ret) 41962306a36Sopenharmony_ci return ret; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci return 1; 42262306a36Sopenharmony_ci} 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci/* 42562306a36Sopenharmony_ci * Enable SDIO/combo card's high-speed mode. Return 0/1 if [not]supported. 42662306a36Sopenharmony_ci */ 42762306a36Sopenharmony_cistatic int sdio_enable_hs(struct mmc_card *card) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci int ret; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci ret = mmc_sdio_switch_hs(card, true); 43262306a36Sopenharmony_ci if (ret <= 0 || mmc_card_sdio(card)) 43362306a36Sopenharmony_ci return ret; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci ret = mmc_sd_switch_hs(card); 43662306a36Sopenharmony_ci if (ret <= 0) 43762306a36Sopenharmony_ci mmc_sdio_switch_hs(card, false); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci return ret; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic unsigned mmc_sdio_get_max_clock(struct mmc_card *card) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci unsigned max_dtr; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (mmc_card_hs(card)) { 44762306a36Sopenharmony_ci /* 44862306a36Sopenharmony_ci * The SDIO specification doesn't mention how 44962306a36Sopenharmony_ci * the CIS transfer speed register relates to 45062306a36Sopenharmony_ci * high-speed, but it seems that 50 MHz is 45162306a36Sopenharmony_ci * mandatory. 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci max_dtr = 50000000; 45462306a36Sopenharmony_ci } else { 45562306a36Sopenharmony_ci max_dtr = card->cis.max_dtr; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci if (mmc_card_sd_combo(card)) 45962306a36Sopenharmony_ci max_dtr = min(max_dtr, mmc_sd_get_max_clock(card)); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci return max_dtr; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic unsigned char host_drive_to_sdio_drive(int host_strength) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci switch (host_strength) { 46762306a36Sopenharmony_ci case MMC_SET_DRIVER_TYPE_A: 46862306a36Sopenharmony_ci return SDIO_DTSx_SET_TYPE_A; 46962306a36Sopenharmony_ci case MMC_SET_DRIVER_TYPE_B: 47062306a36Sopenharmony_ci return SDIO_DTSx_SET_TYPE_B; 47162306a36Sopenharmony_ci case MMC_SET_DRIVER_TYPE_C: 47262306a36Sopenharmony_ci return SDIO_DTSx_SET_TYPE_C; 47362306a36Sopenharmony_ci case MMC_SET_DRIVER_TYPE_D: 47462306a36Sopenharmony_ci return SDIO_DTSx_SET_TYPE_D; 47562306a36Sopenharmony_ci default: 47662306a36Sopenharmony_ci return SDIO_DTSx_SET_TYPE_B; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic void sdio_select_driver_type(struct mmc_card *card) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci int card_drv_type, drive_strength, drv_type; 48362306a36Sopenharmony_ci unsigned char card_strength; 48462306a36Sopenharmony_ci int err; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci card->drive_strength = 0; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci drive_strength = mmc_select_drive_strength(card, 49162306a36Sopenharmony_ci card->sw_caps.uhs_max_dtr, 49262306a36Sopenharmony_ci card_drv_type, &drv_type); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci if (drive_strength) { 49562306a36Sopenharmony_ci /* if error just use default for drive strength B */ 49662306a36Sopenharmony_ci err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0, 49762306a36Sopenharmony_ci &card_strength); 49862306a36Sopenharmony_ci if (err) 49962306a36Sopenharmony_ci return; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT); 50262306a36Sopenharmony_ci card_strength |= host_drive_to_sdio_drive(drive_strength); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* if error default to drive strength B */ 50562306a36Sopenharmony_ci err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH, 50662306a36Sopenharmony_ci card_strength, NULL); 50762306a36Sopenharmony_ci if (err) 50862306a36Sopenharmony_ci return; 50962306a36Sopenharmony_ci card->drive_strength = drive_strength; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci if (drv_type) 51362306a36Sopenharmony_ci mmc_set_driver_type(card->host, drv_type); 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic int sdio_set_bus_speed_mode(struct mmc_card *card) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci unsigned int bus_speed, timing; 52062306a36Sopenharmony_ci int err; 52162306a36Sopenharmony_ci unsigned char speed; 52262306a36Sopenharmony_ci unsigned int max_rate; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci /* 52562306a36Sopenharmony_ci * If the host doesn't support any of the UHS-I modes, fallback on 52662306a36Sopenharmony_ci * default speed. 52762306a36Sopenharmony_ci */ 52862306a36Sopenharmony_ci if (!mmc_host_uhs(card->host)) 52962306a36Sopenharmony_ci return 0; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci bus_speed = SDIO_SPEED_SDR12; 53262306a36Sopenharmony_ci timing = MMC_TIMING_UHS_SDR12; 53362306a36Sopenharmony_ci if ((card->host->caps & MMC_CAP_UHS_SDR104) && 53462306a36Sopenharmony_ci (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) { 53562306a36Sopenharmony_ci bus_speed = SDIO_SPEED_SDR104; 53662306a36Sopenharmony_ci timing = MMC_TIMING_UHS_SDR104; 53762306a36Sopenharmony_ci card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; 53862306a36Sopenharmony_ci card->sd_bus_speed = UHS_SDR104_BUS_SPEED; 53962306a36Sopenharmony_ci } else if ((card->host->caps & MMC_CAP_UHS_DDR50) && 54062306a36Sopenharmony_ci (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) { 54162306a36Sopenharmony_ci bus_speed = SDIO_SPEED_DDR50; 54262306a36Sopenharmony_ci timing = MMC_TIMING_UHS_DDR50; 54362306a36Sopenharmony_ci card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; 54462306a36Sopenharmony_ci card->sd_bus_speed = UHS_DDR50_BUS_SPEED; 54562306a36Sopenharmony_ci } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | 54662306a36Sopenharmony_ci MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode & 54762306a36Sopenharmony_ci SD_MODE_UHS_SDR50)) { 54862306a36Sopenharmony_ci bus_speed = SDIO_SPEED_SDR50; 54962306a36Sopenharmony_ci timing = MMC_TIMING_UHS_SDR50; 55062306a36Sopenharmony_ci card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; 55162306a36Sopenharmony_ci card->sd_bus_speed = UHS_SDR50_BUS_SPEED; 55262306a36Sopenharmony_ci } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | 55362306a36Sopenharmony_ci MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) && 55462306a36Sopenharmony_ci (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) { 55562306a36Sopenharmony_ci bus_speed = SDIO_SPEED_SDR25; 55662306a36Sopenharmony_ci timing = MMC_TIMING_UHS_SDR25; 55762306a36Sopenharmony_ci card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR; 55862306a36Sopenharmony_ci card->sd_bus_speed = UHS_SDR25_BUS_SPEED; 55962306a36Sopenharmony_ci } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | 56062306a36Sopenharmony_ci MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 | 56162306a36Sopenharmony_ci MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode & 56262306a36Sopenharmony_ci SD_MODE_UHS_SDR12)) { 56362306a36Sopenharmony_ci bus_speed = SDIO_SPEED_SDR12; 56462306a36Sopenharmony_ci timing = MMC_TIMING_UHS_SDR12; 56562306a36Sopenharmony_ci card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR; 56662306a36Sopenharmony_ci card->sd_bus_speed = UHS_SDR12_BUS_SPEED; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); 57062306a36Sopenharmony_ci if (err) 57162306a36Sopenharmony_ci return err; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci speed &= ~SDIO_SPEED_BSS_MASK; 57462306a36Sopenharmony_ci speed |= bus_speed; 57562306a36Sopenharmony_ci err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); 57662306a36Sopenharmony_ci if (err) 57762306a36Sopenharmony_ci return err; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci max_rate = min_not_zero(card->quirk_max_rate, 58062306a36Sopenharmony_ci card->sw_caps.uhs_max_dtr); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci mmc_set_timing(card->host, timing); 58362306a36Sopenharmony_ci mmc_set_clock(card->host, max_rate); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci return 0; 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci/* 58962306a36Sopenharmony_ci * UHS-I specific initialization procedure 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_cistatic int mmc_sdio_init_uhs_card(struct mmc_card *card) 59262306a36Sopenharmony_ci{ 59362306a36Sopenharmony_ci int err; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci if (!card->scr.sda_spec3) 59662306a36Sopenharmony_ci return 0; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* Switch to wider bus */ 59962306a36Sopenharmony_ci err = sdio_enable_4bit_bus(card); 60062306a36Sopenharmony_ci if (err) 60162306a36Sopenharmony_ci goto out; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* Set the driver strength for the card */ 60462306a36Sopenharmony_ci sdio_select_driver_type(card); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* Set bus speed mode of the card */ 60762306a36Sopenharmony_ci err = sdio_set_bus_speed_mode(card); 60862306a36Sopenharmony_ci if (err) 60962306a36Sopenharmony_ci goto out; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci /* 61262306a36Sopenharmony_ci * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and 61362306a36Sopenharmony_ci * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. 61462306a36Sopenharmony_ci */ 61562306a36Sopenharmony_ci if (!mmc_host_is_spi(card->host) && 61662306a36Sopenharmony_ci ((card->host->ios.timing == MMC_TIMING_UHS_SDR50) || 61762306a36Sopenharmony_ci (card->host->ios.timing == MMC_TIMING_UHS_SDR104))) 61862306a36Sopenharmony_ci err = mmc_execute_tuning(card); 61962306a36Sopenharmony_ciout: 62062306a36Sopenharmony_ci return err; 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_cistatic int mmc_sdio_pre_init(struct mmc_host *host, u32 ocr, 62462306a36Sopenharmony_ci struct mmc_card *card) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci if (card) 62762306a36Sopenharmony_ci mmc_remove_card(card); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci /* 63062306a36Sopenharmony_ci * Reset the card by performing the same steps that are taken by 63162306a36Sopenharmony_ci * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. 63262306a36Sopenharmony_ci * 63362306a36Sopenharmony_ci * sdio_reset() is technically not needed. Having just powered up the 63462306a36Sopenharmony_ci * hardware, it should already be in reset state. However, some 63562306a36Sopenharmony_ci * platforms (such as SD8686 on OLPC) do not instantly cut power, 63662306a36Sopenharmony_ci * meaning that a reset is required when restoring power soon after 63762306a36Sopenharmony_ci * powering off. It is harmless in other cases. 63862306a36Sopenharmony_ci * 63962306a36Sopenharmony_ci * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec, 64062306a36Sopenharmony_ci * is not necessary for non-removable cards. However, it is required 64162306a36Sopenharmony_ci * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and 64262306a36Sopenharmony_ci * harmless in other situations. 64362306a36Sopenharmony_ci * 64462306a36Sopenharmony_ci */ 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci sdio_reset(host); 64762306a36Sopenharmony_ci mmc_go_idle(host); 64862306a36Sopenharmony_ci mmc_send_if_cond(host, ocr); 64962306a36Sopenharmony_ci return mmc_send_io_op_cond(host, 0, NULL); 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci/* 65362306a36Sopenharmony_ci * Handle the detection and initialisation of a card. 65462306a36Sopenharmony_ci * 65562306a36Sopenharmony_ci * In the case of a resume, "oldcard" will contain the card 65662306a36Sopenharmony_ci * we're trying to reinitialise. 65762306a36Sopenharmony_ci */ 65862306a36Sopenharmony_cistatic int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, 65962306a36Sopenharmony_ci struct mmc_card *oldcard) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci struct mmc_card *card; 66262306a36Sopenharmony_ci int err; 66362306a36Sopenharmony_ci int retries = 10; 66462306a36Sopenharmony_ci u32 rocr = 0; 66562306a36Sopenharmony_ci u32 ocr_card = ocr; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci WARN_ON(!host->claimed); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci /* to query card if 1.8V signalling is supported */ 67062306a36Sopenharmony_ci if (mmc_host_uhs(host)) 67162306a36Sopenharmony_ci ocr |= R4_18V_PRESENT; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_citry_again: 67462306a36Sopenharmony_ci if (!retries) { 67562306a36Sopenharmony_ci pr_warn("%s: Skipping voltage switch\n", mmc_hostname(host)); 67662306a36Sopenharmony_ci ocr &= ~R4_18V_PRESENT; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci /* 68062306a36Sopenharmony_ci * Inform the card of the voltage 68162306a36Sopenharmony_ci */ 68262306a36Sopenharmony_ci err = mmc_send_io_op_cond(host, ocr, &rocr); 68362306a36Sopenharmony_ci if (err) 68462306a36Sopenharmony_ci return err; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci /* 68762306a36Sopenharmony_ci * For SPI, enable CRC as appropriate. 68862306a36Sopenharmony_ci */ 68962306a36Sopenharmony_ci if (mmc_host_is_spi(host)) { 69062306a36Sopenharmony_ci err = mmc_spi_set_crc(host, use_spi_crc); 69162306a36Sopenharmony_ci if (err) 69262306a36Sopenharmony_ci return err; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* 69662306a36Sopenharmony_ci * Allocate card structure. 69762306a36Sopenharmony_ci */ 69862306a36Sopenharmony_ci card = mmc_alloc_card(host, &sdio_type); 69962306a36Sopenharmony_ci if (IS_ERR(card)) 70062306a36Sopenharmony_ci return PTR_ERR(card); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci if ((rocr & R4_MEMORY_PRESENT) && 70362306a36Sopenharmony_ci mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) { 70462306a36Sopenharmony_ci card->type = MMC_TYPE_SD_COMBO; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci if (oldcard && (!mmc_card_sd_combo(oldcard) || 70762306a36Sopenharmony_ci memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) { 70862306a36Sopenharmony_ci err = -ENOENT; 70962306a36Sopenharmony_ci goto mismatch; 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci } else { 71262306a36Sopenharmony_ci card->type = MMC_TYPE_SDIO; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (oldcard && !mmc_card_sdio(oldcard)) { 71562306a36Sopenharmony_ci err = -ENOENT; 71662306a36Sopenharmony_ci goto mismatch; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci } 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci /* 72162306a36Sopenharmony_ci * Call the optional HC's init_card function to handle quirks. 72262306a36Sopenharmony_ci */ 72362306a36Sopenharmony_ci if (host->ops->init_card) 72462306a36Sopenharmony_ci host->ops->init_card(host, card); 72562306a36Sopenharmony_ci mmc_fixup_device(card, sdio_card_init_methods); 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci card->ocr = ocr_card; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* 73062306a36Sopenharmony_ci * If the host and card support UHS-I mode request the card 73162306a36Sopenharmony_ci * to switch to 1.8V signaling level. No 1.8v signalling if 73262306a36Sopenharmony_ci * UHS mode is not enabled to maintain compatibility and some 73362306a36Sopenharmony_ci * systems that claim 1.8v signalling in fact do not support 73462306a36Sopenharmony_ci * it. Per SDIO spec v3, section 3.1.2, if the voltage is already 73562306a36Sopenharmony_ci * 1.8v, the card sets S18A to 0 in the R4 response. So it will 73662306a36Sopenharmony_ci * fails to check rocr & R4_18V_PRESENT, but we still need to 73762306a36Sopenharmony_ci * try to init uhs card. sdio_read_cccr will take over this task 73862306a36Sopenharmony_ci * to make sure which speed mode should work. 73962306a36Sopenharmony_ci */ 74062306a36Sopenharmony_ci if (rocr & ocr & R4_18V_PRESENT) { 74162306a36Sopenharmony_ci err = mmc_set_uhs_voltage(host, ocr_card); 74262306a36Sopenharmony_ci if (err == -EAGAIN) { 74362306a36Sopenharmony_ci mmc_sdio_pre_init(host, ocr_card, card); 74462306a36Sopenharmony_ci retries--; 74562306a36Sopenharmony_ci goto try_again; 74662306a36Sopenharmony_ci } else if (err) { 74762306a36Sopenharmony_ci ocr &= ~R4_18V_PRESENT; 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci /* 75262306a36Sopenharmony_ci * For native busses: set card RCA and quit open drain mode. 75362306a36Sopenharmony_ci */ 75462306a36Sopenharmony_ci if (!mmc_host_is_spi(host)) { 75562306a36Sopenharmony_ci err = mmc_send_relative_addr(host, &card->rca); 75662306a36Sopenharmony_ci if (err) 75762306a36Sopenharmony_ci goto remove; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci /* 76062306a36Sopenharmony_ci * Update oldcard with the new RCA received from the SDIO 76162306a36Sopenharmony_ci * device -- we're doing this so that it's updated in the 76262306a36Sopenharmony_ci * "card" struct when oldcard overwrites that later. 76362306a36Sopenharmony_ci */ 76462306a36Sopenharmony_ci if (oldcard) 76562306a36Sopenharmony_ci oldcard->rca = card->rca; 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci /* 76962306a36Sopenharmony_ci * Read CSD, before selecting the card 77062306a36Sopenharmony_ci */ 77162306a36Sopenharmony_ci if (!oldcard && mmc_card_sd_combo(card)) { 77262306a36Sopenharmony_ci err = mmc_sd_get_csd(card); 77362306a36Sopenharmony_ci if (err) 77462306a36Sopenharmony_ci goto remove; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci mmc_decode_cid(card); 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci /* 78062306a36Sopenharmony_ci * Select card, as all following commands rely on that. 78162306a36Sopenharmony_ci */ 78262306a36Sopenharmony_ci if (!mmc_host_is_spi(host)) { 78362306a36Sopenharmony_ci err = mmc_select_card(card); 78462306a36Sopenharmony_ci if (err) 78562306a36Sopenharmony_ci goto remove; 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci if (card->quirks & MMC_QUIRK_NONSTD_SDIO) { 78962306a36Sopenharmony_ci /* 79062306a36Sopenharmony_ci * This is non-standard SDIO device, meaning it doesn't 79162306a36Sopenharmony_ci * have any CIA (Common I/O area) registers present. 79262306a36Sopenharmony_ci * It's host's responsibility to fill cccr and cis 79362306a36Sopenharmony_ci * structures in init_card(). 79462306a36Sopenharmony_ci */ 79562306a36Sopenharmony_ci mmc_set_clock(host, card->cis.max_dtr); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci if (card->cccr.high_speed) { 79862306a36Sopenharmony_ci mmc_set_timing(card->host, MMC_TIMING_SD_HS); 79962306a36Sopenharmony_ci } 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (oldcard) 80262306a36Sopenharmony_ci mmc_remove_card(card); 80362306a36Sopenharmony_ci else 80462306a36Sopenharmony_ci host->card = card; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci return 0; 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* 81062306a36Sopenharmony_ci * Read the common registers. Note that we should try to 81162306a36Sopenharmony_ci * validate whether UHS would work or not. 81262306a36Sopenharmony_ci */ 81362306a36Sopenharmony_ci err = sdio_read_cccr(card, ocr); 81462306a36Sopenharmony_ci if (err) { 81562306a36Sopenharmony_ci mmc_sdio_pre_init(host, ocr_card, card); 81662306a36Sopenharmony_ci if (ocr & R4_18V_PRESENT) { 81762306a36Sopenharmony_ci /* Retry init sequence, but without R4_18V_PRESENT. */ 81862306a36Sopenharmony_ci retries = 0; 81962306a36Sopenharmony_ci goto try_again; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci return err; 82262306a36Sopenharmony_ci } 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci /* 82562306a36Sopenharmony_ci * Read the common CIS tuples. 82662306a36Sopenharmony_ci */ 82762306a36Sopenharmony_ci err = sdio_read_common_cis(card); 82862306a36Sopenharmony_ci if (err) 82962306a36Sopenharmony_ci goto remove; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (oldcard) { 83262306a36Sopenharmony_ci if (card->cis.vendor == oldcard->cis.vendor && 83362306a36Sopenharmony_ci card->cis.device == oldcard->cis.device) { 83462306a36Sopenharmony_ci mmc_remove_card(card); 83562306a36Sopenharmony_ci card = oldcard; 83662306a36Sopenharmony_ci } else { 83762306a36Sopenharmony_ci err = -ENOENT; 83862306a36Sopenharmony_ci goto mismatch; 83962306a36Sopenharmony_ci } 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci mmc_fixup_device(card, sdio_fixup_methods); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci if (mmc_card_sd_combo(card)) { 84562306a36Sopenharmony_ci err = mmc_sd_setup_card(host, card, oldcard != NULL); 84662306a36Sopenharmony_ci /* handle as SDIO-only card if memory init failed */ 84762306a36Sopenharmony_ci if (err) { 84862306a36Sopenharmony_ci mmc_go_idle(host); 84962306a36Sopenharmony_ci if (mmc_host_is_spi(host)) 85062306a36Sopenharmony_ci /* should not fail, as it worked previously */ 85162306a36Sopenharmony_ci mmc_spi_set_crc(host, use_spi_crc); 85262306a36Sopenharmony_ci card->type = MMC_TYPE_SDIO; 85362306a36Sopenharmony_ci } else 85462306a36Sopenharmony_ci card->dev.type = &sd_type; 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci /* 85862306a36Sopenharmony_ci * If needed, disconnect card detection pull-up resistor. 85962306a36Sopenharmony_ci */ 86062306a36Sopenharmony_ci err = sdio_disable_cd(card); 86162306a36Sopenharmony_ci if (err) 86262306a36Sopenharmony_ci goto remove; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci /* Initialization sequence for UHS-I cards */ 86562306a36Sopenharmony_ci /* Only if card supports 1.8v and UHS signaling */ 86662306a36Sopenharmony_ci if ((ocr & R4_18V_PRESENT) && card->sw_caps.sd3_bus_mode) { 86762306a36Sopenharmony_ci err = mmc_sdio_init_uhs_card(card); 86862306a36Sopenharmony_ci if (err) 86962306a36Sopenharmony_ci goto remove; 87062306a36Sopenharmony_ci } else { 87162306a36Sopenharmony_ci /* 87262306a36Sopenharmony_ci * Switch to high-speed (if supported). 87362306a36Sopenharmony_ci */ 87462306a36Sopenharmony_ci err = sdio_enable_hs(card); 87562306a36Sopenharmony_ci if (err > 0) 87662306a36Sopenharmony_ci mmc_set_timing(card->host, MMC_TIMING_SD_HS); 87762306a36Sopenharmony_ci else if (err) 87862306a36Sopenharmony_ci goto remove; 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci /* 88162306a36Sopenharmony_ci * Change to the card's maximum speed. 88262306a36Sopenharmony_ci */ 88362306a36Sopenharmony_ci mmc_set_clock(host, mmc_sdio_get_max_clock(card)); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci /* 88662306a36Sopenharmony_ci * Switch to wider bus (if supported). 88762306a36Sopenharmony_ci */ 88862306a36Sopenharmony_ci err = sdio_enable_4bit_bus(card); 88962306a36Sopenharmony_ci if (err) 89062306a36Sopenharmony_ci goto remove; 89162306a36Sopenharmony_ci } 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci if (host->caps2 & MMC_CAP2_AVOID_3_3V && 89462306a36Sopenharmony_ci host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) { 89562306a36Sopenharmony_ci pr_err("%s: Host failed to negotiate down from 3.3V\n", 89662306a36Sopenharmony_ci mmc_hostname(host)); 89762306a36Sopenharmony_ci err = -EINVAL; 89862306a36Sopenharmony_ci goto remove; 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci host->card = card; 90262306a36Sopenharmony_ci return 0; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_cimismatch: 90562306a36Sopenharmony_ci pr_debug("%s: Perhaps the card was replaced\n", mmc_hostname(host)); 90662306a36Sopenharmony_ciremove: 90762306a36Sopenharmony_ci if (oldcard != card) 90862306a36Sopenharmony_ci mmc_remove_card(card); 90962306a36Sopenharmony_ci return err; 91062306a36Sopenharmony_ci} 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_cistatic int mmc_sdio_reinit_card(struct mmc_host *host) 91362306a36Sopenharmony_ci{ 91462306a36Sopenharmony_ci int ret; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci ret = mmc_sdio_pre_init(host, host->card->ocr, NULL); 91762306a36Sopenharmony_ci if (ret) 91862306a36Sopenharmony_ci return ret; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci return mmc_sdio_init_card(host, host->card->ocr, host->card); 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci/* 92462306a36Sopenharmony_ci * Host is being removed. Free up the current card. 92562306a36Sopenharmony_ci */ 92662306a36Sopenharmony_cistatic void mmc_sdio_remove(struct mmc_host *host) 92762306a36Sopenharmony_ci{ 92862306a36Sopenharmony_ci int i; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci for (i = 0;i < host->card->sdio_funcs;i++) { 93162306a36Sopenharmony_ci if (host->card->sdio_func[i]) { 93262306a36Sopenharmony_ci sdio_remove_func(host->card->sdio_func[i]); 93362306a36Sopenharmony_ci host->card->sdio_func[i] = NULL; 93462306a36Sopenharmony_ci } 93562306a36Sopenharmony_ci } 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci mmc_remove_card(host->card); 93862306a36Sopenharmony_ci host->card = NULL; 93962306a36Sopenharmony_ci} 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci/* 94262306a36Sopenharmony_ci * Card detection - card is alive. 94362306a36Sopenharmony_ci */ 94462306a36Sopenharmony_cistatic int mmc_sdio_alive(struct mmc_host *host) 94562306a36Sopenharmony_ci{ 94662306a36Sopenharmony_ci return mmc_select_card(host->card); 94762306a36Sopenharmony_ci} 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci/* 95062306a36Sopenharmony_ci * Card detection callback from host. 95162306a36Sopenharmony_ci */ 95262306a36Sopenharmony_cistatic void mmc_sdio_detect(struct mmc_host *host) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci int err; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci /* Make sure card is powered before detecting it */ 95762306a36Sopenharmony_ci if (host->caps & MMC_CAP_POWER_OFF_CARD) { 95862306a36Sopenharmony_ci err = pm_runtime_resume_and_get(&host->card->dev); 95962306a36Sopenharmony_ci if (err < 0) 96062306a36Sopenharmony_ci goto out; 96162306a36Sopenharmony_ci } 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci mmc_claim_host(host); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci /* 96662306a36Sopenharmony_ci * Just check if our card has been removed. 96762306a36Sopenharmony_ci */ 96862306a36Sopenharmony_ci err = _mmc_detect_card_removed(host); 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci mmc_release_host(host); 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci /* 97362306a36Sopenharmony_ci * Tell PM core it's OK to power off the card now. 97462306a36Sopenharmony_ci * 97562306a36Sopenharmony_ci * The _sync variant is used in order to ensure that the card 97662306a36Sopenharmony_ci * is left powered off in case an error occurred, and the card 97762306a36Sopenharmony_ci * is going to be removed. 97862306a36Sopenharmony_ci * 97962306a36Sopenharmony_ci * Since there is no specific reason to believe a new user 98062306a36Sopenharmony_ci * is about to show up at this point, the _sync variant is 98162306a36Sopenharmony_ci * desirable anyway. 98262306a36Sopenharmony_ci */ 98362306a36Sopenharmony_ci if (host->caps & MMC_CAP_POWER_OFF_CARD) 98462306a36Sopenharmony_ci pm_runtime_put_sync(&host->card->dev); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ciout: 98762306a36Sopenharmony_ci if (err) { 98862306a36Sopenharmony_ci mmc_sdio_remove(host); 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci mmc_claim_host(host); 99162306a36Sopenharmony_ci mmc_detach_bus(host); 99262306a36Sopenharmony_ci mmc_power_off(host); 99362306a36Sopenharmony_ci mmc_release_host(host); 99462306a36Sopenharmony_ci } 99562306a36Sopenharmony_ci} 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci/* 99862306a36Sopenharmony_ci * SDIO pre_suspend. We need to suspend all functions separately. 99962306a36Sopenharmony_ci * Therefore all registered functions must have drivers with suspend 100062306a36Sopenharmony_ci * and resume methods. Failing that we simply remove the whole card. 100162306a36Sopenharmony_ci */ 100262306a36Sopenharmony_cistatic int mmc_sdio_pre_suspend(struct mmc_host *host) 100362306a36Sopenharmony_ci{ 100462306a36Sopenharmony_ci int i; 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci for (i = 0; i < host->card->sdio_funcs; i++) { 100762306a36Sopenharmony_ci struct sdio_func *func = host->card->sdio_func[i]; 100862306a36Sopenharmony_ci if (func && sdio_func_present(func) && func->dev.driver) { 100962306a36Sopenharmony_ci const struct dev_pm_ops *pmops = func->dev.driver->pm; 101062306a36Sopenharmony_ci if (!pmops || !pmops->suspend || !pmops->resume) 101162306a36Sopenharmony_ci /* force removal of entire card in that case */ 101262306a36Sopenharmony_ci goto remove; 101362306a36Sopenharmony_ci } 101462306a36Sopenharmony_ci } 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci return 0; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ciremove: 101962306a36Sopenharmony_ci if (!mmc_card_is_removable(host)) { 102062306a36Sopenharmony_ci dev_warn(mmc_dev(host), 102162306a36Sopenharmony_ci "missing suspend/resume ops for non-removable SDIO card\n"); 102262306a36Sopenharmony_ci /* Don't remove a non-removable card - we can't re-detect it. */ 102362306a36Sopenharmony_ci return 0; 102462306a36Sopenharmony_ci } 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci /* Remove the SDIO card and let it be re-detected later on. */ 102762306a36Sopenharmony_ci mmc_sdio_remove(host); 102862306a36Sopenharmony_ci mmc_claim_host(host); 102962306a36Sopenharmony_ci mmc_detach_bus(host); 103062306a36Sopenharmony_ci mmc_power_off(host); 103162306a36Sopenharmony_ci mmc_release_host(host); 103262306a36Sopenharmony_ci host->pm_flags = 0; 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci return 0; 103562306a36Sopenharmony_ci} 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci/* 103862306a36Sopenharmony_ci * SDIO suspend. Suspend all functions separately. 103962306a36Sopenharmony_ci */ 104062306a36Sopenharmony_cistatic int mmc_sdio_suspend(struct mmc_host *host) 104162306a36Sopenharmony_ci{ 104262306a36Sopenharmony_ci WARN_ON(host->sdio_irqs && !mmc_card_keep_power(host)); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci /* Prevent processing of SDIO IRQs in suspended state. */ 104562306a36Sopenharmony_ci mmc_card_set_suspended(host->card); 104662306a36Sopenharmony_ci cancel_work_sync(&host->sdio_irq_work); 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci mmc_claim_host(host); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) 105162306a36Sopenharmony_ci sdio_disable_4bit_bus(host->card); 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci if (!mmc_card_keep_power(host)) { 105462306a36Sopenharmony_ci mmc_power_off(host); 105562306a36Sopenharmony_ci } else if (host->retune_period) { 105662306a36Sopenharmony_ci mmc_retune_timer_stop(host); 105762306a36Sopenharmony_ci mmc_retune_needed(host); 105862306a36Sopenharmony_ci } 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci mmc_release_host(host); 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci return 0; 106362306a36Sopenharmony_ci} 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_cistatic int mmc_sdio_resume(struct mmc_host *host) 106662306a36Sopenharmony_ci{ 106762306a36Sopenharmony_ci int err = 0; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci /* Basic card reinitialization. */ 107062306a36Sopenharmony_ci mmc_claim_host(host); 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci /* 107362306a36Sopenharmony_ci * Restore power and reinitialize the card when needed. Note that a 107462306a36Sopenharmony_ci * removable card is checked from a detect work later on in the resume 107562306a36Sopenharmony_ci * process. 107662306a36Sopenharmony_ci */ 107762306a36Sopenharmony_ci if (!mmc_card_keep_power(host)) { 107862306a36Sopenharmony_ci mmc_power_up(host, host->card->ocr); 107962306a36Sopenharmony_ci /* 108062306a36Sopenharmony_ci * Tell runtime PM core we just powered up the card, 108162306a36Sopenharmony_ci * since it still believes the card is powered off. 108262306a36Sopenharmony_ci * Note that currently runtime PM is only enabled 108362306a36Sopenharmony_ci * for SDIO cards that are MMC_CAP_POWER_OFF_CARD 108462306a36Sopenharmony_ci */ 108562306a36Sopenharmony_ci if (host->caps & MMC_CAP_POWER_OFF_CARD) { 108662306a36Sopenharmony_ci pm_runtime_disable(&host->card->dev); 108762306a36Sopenharmony_ci pm_runtime_set_active(&host->card->dev); 108862306a36Sopenharmony_ci pm_runtime_enable(&host->card->dev); 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci err = mmc_sdio_reinit_card(host); 109162306a36Sopenharmony_ci } else if (mmc_card_wake_sdio_irq(host)) { 109262306a36Sopenharmony_ci /* 109362306a36Sopenharmony_ci * We may have switched to 1-bit mode during suspend, 109462306a36Sopenharmony_ci * need to hold retuning, because tuning only supprt 109562306a36Sopenharmony_ci * 4-bit mode or 8 bit mode. 109662306a36Sopenharmony_ci */ 109762306a36Sopenharmony_ci mmc_retune_hold_now(host); 109862306a36Sopenharmony_ci err = sdio_enable_4bit_bus(host->card); 109962306a36Sopenharmony_ci mmc_retune_release(host); 110062306a36Sopenharmony_ci } 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci if (err) 110362306a36Sopenharmony_ci goto out; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci /* Allow SDIO IRQs to be processed again. */ 110662306a36Sopenharmony_ci mmc_card_clr_suspended(host->card); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci if (host->sdio_irqs) { 110962306a36Sopenharmony_ci if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) 111062306a36Sopenharmony_ci wake_up_process(host->sdio_irq_thread); 111162306a36Sopenharmony_ci else if (host->caps & MMC_CAP_SDIO_IRQ) 111262306a36Sopenharmony_ci schedule_work(&host->sdio_irq_work); 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ciout: 111662306a36Sopenharmony_ci mmc_release_host(host); 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci host->pm_flags &= ~MMC_PM_KEEP_POWER; 111962306a36Sopenharmony_ci return err; 112062306a36Sopenharmony_ci} 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_cistatic int mmc_sdio_runtime_suspend(struct mmc_host *host) 112362306a36Sopenharmony_ci{ 112462306a36Sopenharmony_ci /* No references to the card, cut the power to it. */ 112562306a36Sopenharmony_ci mmc_claim_host(host); 112662306a36Sopenharmony_ci mmc_power_off(host); 112762306a36Sopenharmony_ci mmc_release_host(host); 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci return 0; 113062306a36Sopenharmony_ci} 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_cistatic int mmc_sdio_runtime_resume(struct mmc_host *host) 113362306a36Sopenharmony_ci{ 113462306a36Sopenharmony_ci int ret; 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci /* Restore power and re-initialize. */ 113762306a36Sopenharmony_ci mmc_claim_host(host); 113862306a36Sopenharmony_ci mmc_power_up(host, host->card->ocr); 113962306a36Sopenharmony_ci ret = mmc_sdio_reinit_card(host); 114062306a36Sopenharmony_ci mmc_release_host(host); 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci return ret; 114362306a36Sopenharmony_ci} 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci/* 114662306a36Sopenharmony_ci * SDIO HW reset 114762306a36Sopenharmony_ci * 114862306a36Sopenharmony_ci * Returns 0 if the HW reset was executed synchronously, returns 1 if the HW 114962306a36Sopenharmony_ci * reset was asynchronously scheduled, else a negative error code. 115062306a36Sopenharmony_ci */ 115162306a36Sopenharmony_cistatic int mmc_sdio_hw_reset(struct mmc_host *host) 115262306a36Sopenharmony_ci{ 115362306a36Sopenharmony_ci struct mmc_card *card = host->card; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci /* 115662306a36Sopenharmony_ci * In case the card is shared among multiple func drivers, reset the 115762306a36Sopenharmony_ci * card through a rescan work. In this way it will be removed and 115862306a36Sopenharmony_ci * re-detected, thus all func drivers becomes informed about it. 115962306a36Sopenharmony_ci */ 116062306a36Sopenharmony_ci if (atomic_read(&card->sdio_funcs_probed) > 1) { 116162306a36Sopenharmony_ci if (mmc_card_removed(card)) 116262306a36Sopenharmony_ci return 1; 116362306a36Sopenharmony_ci host->rescan_entered = 0; 116462306a36Sopenharmony_ci mmc_card_set_removed(card); 116562306a36Sopenharmony_ci _mmc_detect_change(host, 0, false); 116662306a36Sopenharmony_ci return 1; 116762306a36Sopenharmony_ci } 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci /* 117062306a36Sopenharmony_ci * A single func driver has been probed, then let's skip the heavy 117162306a36Sopenharmony_ci * hotplug dance above and execute the reset immediately. 117262306a36Sopenharmony_ci */ 117362306a36Sopenharmony_ci mmc_power_cycle(host, card->ocr); 117462306a36Sopenharmony_ci return mmc_sdio_reinit_card(host); 117562306a36Sopenharmony_ci} 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_cistatic int mmc_sdio_sw_reset(struct mmc_host *host) 117862306a36Sopenharmony_ci{ 117962306a36Sopenharmony_ci mmc_set_clock(host, host->f_init); 118062306a36Sopenharmony_ci sdio_reset(host); 118162306a36Sopenharmony_ci mmc_go_idle(host); 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci mmc_set_initial_state(host); 118462306a36Sopenharmony_ci mmc_set_initial_signal_voltage(host); 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci return mmc_sdio_reinit_card(host); 118762306a36Sopenharmony_ci} 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_cistatic const struct mmc_bus_ops mmc_sdio_ops = { 119062306a36Sopenharmony_ci .remove = mmc_sdio_remove, 119162306a36Sopenharmony_ci .detect = mmc_sdio_detect, 119262306a36Sopenharmony_ci .pre_suspend = mmc_sdio_pre_suspend, 119362306a36Sopenharmony_ci .suspend = mmc_sdio_suspend, 119462306a36Sopenharmony_ci .resume = mmc_sdio_resume, 119562306a36Sopenharmony_ci .runtime_suspend = mmc_sdio_runtime_suspend, 119662306a36Sopenharmony_ci .runtime_resume = mmc_sdio_runtime_resume, 119762306a36Sopenharmony_ci .alive = mmc_sdio_alive, 119862306a36Sopenharmony_ci .hw_reset = mmc_sdio_hw_reset, 119962306a36Sopenharmony_ci .sw_reset = mmc_sdio_sw_reset, 120062306a36Sopenharmony_ci}; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci/* 120462306a36Sopenharmony_ci * Starting point for SDIO card init. 120562306a36Sopenharmony_ci */ 120662306a36Sopenharmony_ciint mmc_attach_sdio(struct mmc_host *host) 120762306a36Sopenharmony_ci{ 120862306a36Sopenharmony_ci int err, i, funcs; 120962306a36Sopenharmony_ci u32 ocr, rocr; 121062306a36Sopenharmony_ci struct mmc_card *card; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci WARN_ON(!host->claimed); 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci err = mmc_send_io_op_cond(host, 0, &ocr); 121562306a36Sopenharmony_ci if (err) 121662306a36Sopenharmony_ci return err; 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci mmc_attach_bus(host, &mmc_sdio_ops); 121962306a36Sopenharmony_ci if (host->ocr_avail_sdio) 122062306a36Sopenharmony_ci host->ocr_avail = host->ocr_avail_sdio; 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci rocr = mmc_select_voltage(host, ocr); 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci /* 122662306a36Sopenharmony_ci * Can we support the voltage(s) of the card(s)? 122762306a36Sopenharmony_ci */ 122862306a36Sopenharmony_ci if (!rocr) { 122962306a36Sopenharmony_ci err = -EINVAL; 123062306a36Sopenharmony_ci goto err; 123162306a36Sopenharmony_ci } 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci /* 123462306a36Sopenharmony_ci * Detect and init the card. 123562306a36Sopenharmony_ci */ 123662306a36Sopenharmony_ci err = mmc_sdio_init_card(host, rocr, NULL); 123762306a36Sopenharmony_ci if (err) 123862306a36Sopenharmony_ci goto err; 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci card = host->card; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci /* 124362306a36Sopenharmony_ci * Enable runtime PM only if supported by host+card+board 124462306a36Sopenharmony_ci */ 124562306a36Sopenharmony_ci if (host->caps & MMC_CAP_POWER_OFF_CARD) { 124662306a36Sopenharmony_ci /* 124762306a36Sopenharmony_ci * Do not allow runtime suspend until after SDIO function 124862306a36Sopenharmony_ci * devices are added. 124962306a36Sopenharmony_ci */ 125062306a36Sopenharmony_ci pm_runtime_get_noresume(&card->dev); 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci /* 125362306a36Sopenharmony_ci * Let runtime PM core know our card is active 125462306a36Sopenharmony_ci */ 125562306a36Sopenharmony_ci err = pm_runtime_set_active(&card->dev); 125662306a36Sopenharmony_ci if (err) 125762306a36Sopenharmony_ci goto remove; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci /* 126062306a36Sopenharmony_ci * Enable runtime PM for this card 126162306a36Sopenharmony_ci */ 126262306a36Sopenharmony_ci pm_runtime_enable(&card->dev); 126362306a36Sopenharmony_ci } 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci /* 126662306a36Sopenharmony_ci * The number of functions on the card is encoded inside 126762306a36Sopenharmony_ci * the ocr. 126862306a36Sopenharmony_ci */ 126962306a36Sopenharmony_ci funcs = (ocr & 0x70000000) >> 28; 127062306a36Sopenharmony_ci card->sdio_funcs = 0; 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci /* 127362306a36Sopenharmony_ci * Initialize (but don't add) all present functions. 127462306a36Sopenharmony_ci */ 127562306a36Sopenharmony_ci for (i = 0; i < funcs; i++, card->sdio_funcs++) { 127662306a36Sopenharmony_ci err = sdio_init_func(host->card, i + 1); 127762306a36Sopenharmony_ci if (err) 127862306a36Sopenharmony_ci goto remove; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci /* 128162306a36Sopenharmony_ci * Enable Runtime PM for this func (if supported) 128262306a36Sopenharmony_ci */ 128362306a36Sopenharmony_ci if (host->caps & MMC_CAP_POWER_OFF_CARD) 128462306a36Sopenharmony_ci pm_runtime_enable(&card->sdio_func[i]->dev); 128562306a36Sopenharmony_ci } 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci /* 128862306a36Sopenharmony_ci * First add the card to the driver model... 128962306a36Sopenharmony_ci */ 129062306a36Sopenharmony_ci mmc_release_host(host); 129162306a36Sopenharmony_ci err = mmc_add_card(host->card); 129262306a36Sopenharmony_ci if (err) 129362306a36Sopenharmony_ci goto remove_added; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci /* 129662306a36Sopenharmony_ci * ...then the SDIO functions. 129762306a36Sopenharmony_ci */ 129862306a36Sopenharmony_ci for (i = 0;i < funcs;i++) { 129962306a36Sopenharmony_ci err = sdio_add_func(host->card->sdio_func[i]); 130062306a36Sopenharmony_ci if (err) 130162306a36Sopenharmony_ci goto remove_added; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci if (host->caps & MMC_CAP_POWER_OFF_CARD) 130562306a36Sopenharmony_ci pm_runtime_put(&card->dev); 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci mmc_claim_host(host); 130862306a36Sopenharmony_ci return 0; 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ciremove: 131262306a36Sopenharmony_ci mmc_release_host(host); 131362306a36Sopenharmony_ciremove_added: 131462306a36Sopenharmony_ci /* 131562306a36Sopenharmony_ci * The devices are being deleted so it is not necessary to disable 131662306a36Sopenharmony_ci * runtime PM. Similarly we also don't pm_runtime_put() the SDIO card 131762306a36Sopenharmony_ci * because it needs to be active to remove any function devices that 131862306a36Sopenharmony_ci * were probed, and after that it gets deleted. 131962306a36Sopenharmony_ci */ 132062306a36Sopenharmony_ci mmc_sdio_remove(host); 132162306a36Sopenharmony_ci mmc_claim_host(host); 132262306a36Sopenharmony_cierr: 132362306a36Sopenharmony_ci mmc_detach_bus(host); 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci pr_err("%s: error %d whilst initialising SDIO card\n", 132662306a36Sopenharmony_ci mmc_hostname(host), err); 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci return err; 132962306a36Sopenharmony_ci} 133062306a36Sopenharmony_ci 1331