drivers/mmc/host/renesas_sdhi_core.c
Source file repositories/reference/linux-study-clean/drivers/mmc/host/renesas_sdhi_core.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mmc/host/renesas_sdhi_core.c- Extension
.c- Size
- 40928 bytes
- Lines
- 1365
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk.hlinux/delay.hlinux/iopoll.hlinux/kernel.hlinux/mmc/host.hlinux/mmc/mmc.hlinux/mmc/slot-gpio.hlinux/module.hlinux/mux/consumer.hlinux/pinctrl/consumer.hlinux/pinctrl/pinctrl-state.hlinux/platform_data/tmio.hlinux/platform_device.hlinux/pm_domain.hlinux/pm_runtime.hlinux/regulator/consumer.hlinux/regulator/driver.hlinux/regulator/of_regulator.hlinux/reset.hlinux/sh_dma.hlinux/slab.hrenesas_sdhi.htmio_mmc.h
Detected Declarations
function Copyrightfunction renesas_sdhi_clk_enablefunction renesas_sdhi_clk_updatefunction renesas_sdhi_set_clockfunction renesas_sdhi_clk_disablefunction renesas_sdhi_card_busyfunction renesas_sdhi_start_signal_voltage_switchfunction sd_scc_read32function sd_scc_write32function renesas_sdhi_init_tuningfunction renesas_sdhi_hs400_completefunction renesas_sdhi_disable_sccfunction sd_scc_tmpport_read32function sd_scc_tmpport_write32function renesas_sdhi_adjust_hs400_mode_enablefunction renesas_sdhi_adjust_hs400_mode_disablefunction renesas_sdhi_reset_hs400_modefunction renesas_sdhi_prepare_hs400_tuningfunction renesas_sdhi_scc_resetfunction renesas_sdhi_resetfunction renesas_sdhi_gen3_get_cyclesfunction renesas_sdhi_select_tuningfunction renesas_sdhi_execute_tuningfunction renesas_sdhi_manual_correctionfunction renesas_sdhi_auto_correctionfunction renesas_sdhi_check_scc_errorfunction renesas_sdhi_init_cardfunction renesas_sdhi_sdio_irqfunction renesas_sdhi_wait_idlefunction renesas_sdhi_write16_hookfunction renesas_sdhi_multi_io_quirkfunction renesas_sdhi_fixup_requestfunction renesas_sdhi_enable_dmafunction renesas_sdhi_regulator_disablefunction renesas_sdhi_regulator_enablefunction renesas_sdhi_regulator_is_enabledfunction renesas_sdhi_regulator_get_voltagefunction renesas_sdhi_regulator_set_voltagefunction renesas_sdhi_regulator_list_voltagefunction renesas_sdhi_probefunction renesas_sdhi_removefunction renesas_sdhi_suspendfunction renesas_sdhi_resumeexport renesas_sdhi_probeexport renesas_sdhi_removeexport renesas_sdhi_suspendexport renesas_sdhi_resume
Annotated Snippet
if (freq > new_upper_limit) {
/* Too fast; look for a slightly slower option */
freq = clk_round_rate(ref_clk, (new_clock << i) / 4 * 3);
if (freq > new_upper_limit)
continue;
}
diff = new_clock - (freq >> i);
if (diff <= diff_min) {
best_freq = freq;
diff_min = diff;
}
}
clk_set_rate(ref_clk, best_freq);
if (priv->clkh)
clk_set_rate(priv->clk, best_freq >> clkh_shift);
return clk_get_rate(priv->clk);
}
static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
unsigned int new_clock)
{
unsigned int clk_margin;
u32 clk = 0, clock;
sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
if (new_clock == 0) {
host->mmc->actual_clock = 0;
goto out;
}
host->mmc->actual_clock = renesas_sdhi_clk_update(host, new_clock);
clock = host->mmc->actual_clock / 512;
/*
* Add a margin of 1/1024 rate higher to the clock rate in order
* to avoid clk variable setting a value of 0 due to the margin
* provided for actual_clock in renesas_sdhi_clk_update().
*/
clk_margin = new_clock >> 10;
for (clk = 0x80000080; new_clock + clk_margin >= (clock << 1); clk >>= 1)
clock <<= 1;
/* 1/1 clock is option */
if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) && ((clk >> 22) & 0x1)) {
if (!(host->mmc->ios.timing == MMC_TIMING_MMC_HS400))
clk |= 0xff;
else
clk &= ~0xff;
}
clock = clk & CLK_CTL_DIV_MASK;
if (clock != CLK_CTL_DIV_MASK)
host->mmc->actual_clock /= (1 << (ffs(clock) + 1));
sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clock);
if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
usleep_range(10000, 11000);
sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
out:
/* HW engineers overrode docs: no sleep needed on R-Car2+ */
if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
usleep_range(10000, 11000);
}
static void renesas_sdhi_clk_disable(struct tmio_mmc_host *host)
{
struct renesas_sdhi *priv = host_to_priv(host);
clk_disable_unprepare(priv->clk_cd);
}
static int renesas_sdhi_card_busy(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
return !(sd_ctrl_read16_and_16_as_32(host, CTL_STATUS) &
TMIO_STAT_DAT0);
}
static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,
struct mmc_ios *ios)
Annotation
- Immediate include surface: `linux/clk.h`, `linux/delay.h`, `linux/iopoll.h`, `linux/kernel.h`, `linux/mmc/host.h`, `linux/mmc/mmc.h`, `linux/mmc/slot-gpio.h`, `linux/module.h`.
- Detected declarations: `function Copyright`, `function renesas_sdhi_clk_enable`, `function renesas_sdhi_clk_update`, `function renesas_sdhi_set_clock`, `function renesas_sdhi_clk_disable`, `function renesas_sdhi_card_busy`, `function renesas_sdhi_start_signal_voltage_switch`, `function sd_scc_read32`, `function sd_scc_write32`, `function renesas_sdhi_init_tuning`.
- Atlas domain: Driver Families / drivers/mmc.
- Implementation status: integration implementation candidate.
- 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.