drivers/mmc/host/sdhci-uhs2.c
Source file repositories/reference/linux-study-clean/drivers/mmc/host/sdhci-uhs2.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mmc/host/sdhci-uhs2.c- Extension
.c- Size
- 35119 bytes
- Lines
- 1241
- Domain
- Driver Families
- Bucket
- drivers/mmc
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/delay.hlinux/module.hlinux/iopoll.hlinux/bitfield.hlinux/regulator/consumer.hlinux/mmc/mmc.hlinux/mmc/host.hsdhci.hsdhci-uhs2.h
Detected Declarations
function Copyrightfunction uhs2_dev_cmdfunction mmc_opt_regulator_set_ocrfunction sdhci_uhs2_resetfunction sdhci_uhs2_reset_cmd_datafunction sdhci_uhs2_set_powerfunction sdhci_calc_timeout_uhs2function __sdhci_uhs2_set_timeoutfunction sdhci_uhs2_set_timeoutfunction sdhci_uhs2_clear_set_irqsfunction __sdhci_uhs2_set_iosfunction sdhci_uhs2_set_iosfunction sdhci_uhs2_interface_detectfunction sdhci_uhs2_initfunction sdhci_uhs2_do_detect_initfunction sdhci_uhs2_disable_clkfunction sdhci_uhs2_enable_clkfunction sdhci_uhs2_set_configfunction sdhci_uhs2_check_dormantfunction sdhci_uhs2_controlfunction sdhci_uhs2_prepare_datafunction sdhci_uhs2_finish_datafunction sdhci_uhs2_set_transfer_modefunction __sdhci_uhs2_send_commandfunction sdhci_uhs2_send_commandfunction sdhci_uhs2_send_command_retryfunction __sdhci_uhs2_finish_commandfunction sdhci_uhs2_finish_commandfunction sdhci_uhs2_requestfunction sdhci_uhs2_needs_resetfunction sdhci_uhs2_request_donefunction sdhci_uhs2_complete_workfunction __sdhci_uhs2_irqfunction sdhci_uhs2_irqfunction sdhci_uhs2_thread_irqfunction sdhci_uhs2_host_ops_initfunction __sdhci_uhs2_add_host_v4function __sdhci_uhs2_remove_hostfunction sdhci_uhs2_add_hostfunction sdhci_uhs2_remove_hostexport sdhci_uhs2_dump_regsexport sdhci_uhs2_resetexport sdhci_uhs2_set_powerexport sdhci_uhs2_set_timeoutexport sdhci_uhs2_clear_set_irqsexport sdhci_uhs2_irqexport sdhci_uhs2_add_hostexport sdhci_uhs2_remove_host
Annotated Snippet
if (ios->power_mode == MMC_POWER_OFF) {
mmc_opt_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
mmc_regulator_set_vqmmc2(mmc, ios);
}
return -1;
}
sdhci_set_ios_common(mmc, ios);
__sdhci_uhs2_set_ios(mmc, ios);
return 0;
}
static int sdhci_uhs2_interface_detect(struct sdhci_host *host)
{
u32 val;
if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_IF_DETECT),
100, UHS2_INTERFACE_DETECT_TIMEOUT_100MS, true,
host, SDHCI_PRESENT_STATE)) {
pr_debug("%s: not detect UHS2 interface in 100ms.\n", mmc_hostname(host->mmc));
sdhci_dbg_dumpregs(host, "UHS2 interface detect timeout in 100ms");
return -EIO;
}
/* Enable UHS2 error interrupts */
sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, SDHCI_UHS2_INT_ERROR_MASK);
if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_LANE_SYNC),
100, UHS2_LANE_SYNC_TIMEOUT_150MS, true, host, SDHCI_PRESENT_STATE)) {
pr_debug("%s: UHS2 Lane sync fail in 150ms.\n", mmc_hostname(host->mmc));
sdhci_dbg_dumpregs(host, "UHS2 Lane sync fail in 150ms");
return -EIO;
}
DBG("%s: UHS2 Lane synchronized in UHS2 mode, PHY is initialized.\n",
mmc_hostname(host->mmc));
return 0;
}
static int sdhci_uhs2_init(struct sdhci_host *host)
{
u16 caps_ptr = 0;
u32 caps_gen = 0;
u32 caps_phy = 0;
u32 caps_tran[2] = {0, 0};
struct mmc_host *mmc = host->mmc;
caps_ptr = sdhci_readw(host, SDHCI_UHS2_CAPS_PTR);
if (caps_ptr < 0x100 || caps_ptr > 0x1FF) {
pr_err("%s: SDHCI_UHS2_CAPS_PTR(%d) is wrong.\n",
mmc_hostname(mmc), caps_ptr);
return -ENODEV;
}
caps_gen = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_OFFSET);
caps_phy = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_PHY_OFFSET);
caps_tran[0] = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_TRAN_OFFSET);
caps_tran[1] = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_TRAN_1_OFFSET);
/* General Caps */
mmc->uhs2_caps.dap = caps_gen & SDHCI_UHS2_CAPS_DAP_MASK;
mmc->uhs2_caps.gap = FIELD_GET(SDHCI_UHS2_CAPS_GAP_MASK, caps_gen);
mmc->uhs2_caps.n_lanes = FIELD_GET(SDHCI_UHS2_CAPS_LANE_MASK, caps_gen);
mmc->uhs2_caps.addr64 = (caps_gen & SDHCI_UHS2_CAPS_ADDR_64) ? 1 : 0;
mmc->uhs2_caps.card_type = FIELD_GET(SDHCI_UHS2_CAPS_DEV_TYPE_MASK, caps_gen);
/* PHY Caps */
mmc->uhs2_caps.phy_rev = caps_phy & SDHCI_UHS2_CAPS_PHY_REV_MASK;
mmc->uhs2_caps.speed_range = FIELD_GET(SDHCI_UHS2_CAPS_PHY_RANGE_MASK, caps_phy);
mmc->uhs2_caps.n_lss_sync = FIELD_GET(SDHCI_UHS2_CAPS_PHY_N_LSS_SYN_MASK, caps_phy);
mmc->uhs2_caps.n_lss_dir = FIELD_GET(SDHCI_UHS2_CAPS_PHY_N_LSS_DIR_MASK, caps_phy);
if (mmc->uhs2_caps.n_lss_sync == 0)
mmc->uhs2_caps.n_lss_sync = 16 << 2;
else
mmc->uhs2_caps.n_lss_sync <<= 2;
if (mmc->uhs2_caps.n_lss_dir == 0)
mmc->uhs2_caps.n_lss_dir = 16 << 3;
else
mmc->uhs2_caps.n_lss_dir <<= 3;
/* LINK/TRAN Caps */
mmc->uhs2_caps.link_rev = caps_tran[0] & SDHCI_UHS2_CAPS_TRAN_LINK_REV_MASK;
mmc->uhs2_caps.n_fcu = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_N_FCU_MASK, caps_tran[0]);
if (mmc->uhs2_caps.n_fcu == 0)
mmc->uhs2_caps.n_fcu = 256;
mmc->uhs2_caps.host_type = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_HOST_TYPE_MASK, caps_tran[0]);
mmc->uhs2_caps.maxblk_len = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_BLK_LEN_MASK, caps_tran[0]);
mmc->uhs2_caps.n_data_gap = caps_tran[1] & SDHCI_UHS2_CAPS_TRAN_1_N_DATA_GAP_MASK;
Annotation
- Immediate include surface: `linux/delay.h`, `linux/module.h`, `linux/iopoll.h`, `linux/bitfield.h`, `linux/regulator/consumer.h`, `linux/mmc/mmc.h`, `linux/mmc/host.h`, `sdhci.h`.
- Detected declarations: `function Copyright`, `function uhs2_dev_cmd`, `function mmc_opt_regulator_set_ocr`, `function sdhci_uhs2_reset`, `function sdhci_uhs2_reset_cmd_data`, `function sdhci_uhs2_set_power`, `function sdhci_calc_timeout_uhs2`, `function __sdhci_uhs2_set_timeout`, `function sdhci_uhs2_set_timeout`, `function sdhci_uhs2_clear_set_irqs`.
- Atlas domain: Driver Families / drivers/mmc.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.