drivers/mmc/host/sdhci-of-at91.c
Source file repositories/reference/linux-study-clean/drivers/mmc/host/sdhci-of-at91.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mmc/host/sdhci-of-at91.c- Extension
.c- Size
- 13802 bytes
- Lines
- 468
- Domain
- Driver Families
- Bucket
- drivers/mmc
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/clk.hlinux/delay.hlinux/err.hlinux/io.hlinux/iopoll.hlinux/kernel.hlinux/mmc/host.hlinux/mmc/slot-gpio.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pm.hlinux/pm_runtime.hsdhci-pltfm.h
Detected Declarations
struct sdhci_at91_soc_datastruct sdhci_at91_privfunction sdhci_at91_set_force_card_detectfunction sdhci_at91_set_clockfunction sdhci_at91_set_uhs_signalingfunction sdhci_at91_resetfunction sdhci_at91_set_clks_presetsfunction sdhci_at91_suspendfunction sdhci_at91_runtime_suspendfunction sdhci_at91_runtime_resumefunction sdhci_at91_probefunction sdhci_runtime_suspend_hostfunction sdhci_at91_remove
Annotated Snippet
struct sdhci_at91_soc_data {
const struct sdhci_pltfm_data *pdata;
bool baseclk_is_generated_internally;
unsigned int divider_for_baseclk;
};
struct sdhci_at91_priv {
const struct sdhci_at91_soc_data *soc_data;
struct clk *hclock;
struct clk *gck;
struct clk *mainck;
bool restore_needed;
bool cal_always_on;
};
static void sdhci_at91_set_force_card_detect(struct sdhci_host *host)
{
u8 mc1r;
mc1r = readb(host->ioaddr + SDMMC_MC1R);
mc1r |= SDMMC_MC1R_FCD;
writeb(mc1r, host->ioaddr + SDMMC_MC1R);
}
static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)
{
u16 clk;
host->mmc->actual_clock = 0;
/*
* There is no requirement to disable the internal clock before
* changing the SD clock configuration. Moreover, disabling the
* internal clock, changing the configuration and re-enabling the
* internal clock causes some bugs. It can prevent to get the internal
* clock stable flag ready and an unexpected switch to the base clock
* when using presets.
*/
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
clk &= SDHCI_CLOCK_INT_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
if (clock == 0)
return;
clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
clk |= SDHCI_CLOCK_INT_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
/* Wait max 20 ms */
if (read_poll_timeout(sdhci_readw, clk, (clk & SDHCI_CLOCK_INT_STABLE),
1000, 20000, false, host, SDHCI_CLOCK_CONTROL)) {
pr_err("%s: Internal clock never stabilised.\n",
mmc_hostname(host->mmc));
return;
}
clk |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
}
static void sdhci_at91_set_uhs_signaling(struct sdhci_host *host,
unsigned int timing)
{
u8 mc1r;
if (timing == MMC_TIMING_MMC_DDR52) {
mc1r = sdhci_readb(host, SDMMC_MC1R);
mc1r |= SDMMC_MC1R_DDR;
sdhci_writeb(host, mc1r, SDMMC_MC1R);
}
sdhci_set_uhs_signaling(host, timing);
}
static void sdhci_at91_reset(struct sdhci_host *host, u8 mask)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_at91_priv *priv = sdhci_pltfm_priv(pltfm_host);
unsigned int tmp;
sdhci_reset(host, mask);
if ((host->mmc->caps & MMC_CAP_NONREMOVABLE)
|| mmc_gpio_get_cd(host->mmc) >= 0)
sdhci_at91_set_force_card_detect(host);
if (priv->cal_always_on && (mask & SDHCI_RESET_ALL)) {
u32 calcr = sdhci_readl(host, SDMMC_CALCR);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/delay.h`, `linux/err.h`, `linux/io.h`, `linux/iopoll.h`, `linux/kernel.h`, `linux/mmc/host.h`.
- Detected declarations: `struct sdhci_at91_soc_data`, `struct sdhci_at91_priv`, `function sdhci_at91_set_force_card_detect`, `function sdhci_at91_set_clock`, `function sdhci_at91_set_uhs_signaling`, `function sdhci_at91_reset`, `function sdhci_at91_set_clks_presets`, `function sdhci_at91_suspend`, `function sdhci_at91_runtime_suspend`, `function sdhci_at91_runtime_resume`.
- Atlas domain: Driver Families / drivers/mmc.
- Implementation status: source implementation candidate.
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.