drivers/mmc/host/mmci_stm32_sdmmc.c
Source file repositories/reference/linux-study-clean/drivers/mmc/host/mmci_stm32_sdmmc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mmc/host/mmci_stm32_sdmmc.c- Extension
.c- Size
- 19168 bytes
- Lines
- 750
- 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.
- 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.
- 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/bitfield.hlinux/delay.hlinux/dma-mapping.hlinux/iopoll.hlinux/mmc/host.hlinux/mmc/card.hlinux/of_address.hlinux/reset.hlinux/scatterlist.hmmci.h
Detected Declarations
struct sdmmc_lli_descstruct sdmmc_idmastruct sdmmc_dlybstruct sdmmc_tuning_opsstruct sdmmc_dlybfunction sdmmc_idma_validate_datafunction _sdmmc_idma_prep_datafunction sdmmc_idma_prep_datafunction sdmmc_idma_unprep_datafunction sdmmc_idma_setupfunction sdmmc_idma_startfunction for_each_sgfunction sdmmc_idma_errorfunction sdmmc_idma_finalizefunction mmci_sdmmc_set_clkregfunction sdmmc_dlyb_mp15_input_ckfunction mmci_sdmmc_set_pwrregfunction sdmmc_get_dctrl_cfgfunction sdmmc_busy_completefunction sdmmc_dlyb_mp15_enablefunction sdmmc_dlyb_mp15_set_cfgfunction sdmmc_dlyb_mp15_preparefunction sdmmc_dlyb_mp25_enablefunction sdmmc_dlyb_mp25_set_cfgfunction sdmmc_dlyb_mp25_preparefunction sdmmc_dlyb_phase_tuningfunction sdmmc_execute_tuningfunction sdmmc_pre_sig_volt_vswitchfunction sdmmc_post_sig_volt_switchfunction sdmmc_variant_init
Annotated Snippet
struct sdmmc_lli_desc {
u32 idmalar;
u32 idmabase;
u32 idmasize;
};
struct sdmmc_idma {
dma_addr_t sg_dma;
void *sg_cpu;
dma_addr_t bounce_dma_addr;
void *bounce_buf;
bool use_bounce_buffer;
};
struct sdmmc_dlyb;
struct sdmmc_tuning_ops {
int (*dlyb_enable)(struct sdmmc_dlyb *dlyb);
void (*set_input_ck)(struct sdmmc_dlyb *dlyb);
int (*tuning_prepare)(struct mmci_host *host);
int (*set_cfg)(struct sdmmc_dlyb *dlyb, int unit __maybe_unused,
int phase, bool sampler __maybe_unused);
};
struct sdmmc_dlyb {
void __iomem *base;
u32 unit;
u32 max;
struct sdmmc_tuning_ops *ops;
};
static int sdmmc_idma_validate_data(struct mmci_host *host,
struct mmc_data *data)
{
struct sdmmc_idma *idma = host->dma_priv;
struct device *dev = mmc_dev(host->mmc);
struct scatterlist *sg;
int i;
/*
* idma has constraints on idmabase & idmasize for each element
* excepted the last element which has no constraint on idmasize
*/
idma->use_bounce_buffer = false;
for_each_sg(data->sg, sg, data->sg_len - 1, i) {
if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
!IS_ALIGNED(sg->length,
host->variant->stm32_idmabsize_align)) {
dev_dbg(mmc_dev(host->mmc),
"unaligned scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length);
goto use_bounce_buffer;
}
}
if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
dev_dbg(mmc_dev(host->mmc),
"unaligned last scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length);
goto use_bounce_buffer;
}
return 0;
use_bounce_buffer:
if (!idma->bounce_buf) {
idma->bounce_buf = dmam_alloc_coherent(dev,
host->mmc->max_req_size,
&idma->bounce_dma_addr,
GFP_KERNEL);
if (!idma->bounce_buf) {
dev_err(dev, "Unable to map allocate DMA bounce buffer.\n");
return -ENOMEM;
}
}
idma->use_bounce_buffer = true;
return 0;
}
static int _sdmmc_idma_prep_data(struct mmci_host *host,
struct mmc_data *data)
{
struct sdmmc_idma *idma = host->dma_priv;
if (idma->use_bounce_buffer) {
if (data->flags & MMC_DATA_WRITE) {
unsigned int xfer_bytes = data->blksz * data->blocks;
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/delay.h`, `linux/dma-mapping.h`, `linux/iopoll.h`, `linux/mmc/host.h`, `linux/mmc/card.h`, `linux/of_address.h`, `linux/reset.h`.
- Detected declarations: `struct sdmmc_lli_desc`, `struct sdmmc_idma`, `struct sdmmc_dlyb`, `struct sdmmc_tuning_ops`, `struct sdmmc_dlyb`, `function sdmmc_idma_validate_data`, `function _sdmmc_idma_prep_data`, `function sdmmc_idma_prep_data`, `function sdmmc_idma_unprep_data`, `function sdmmc_idma_setup`.
- Atlas domain: Driver Families / drivers/mmc.
- Implementation status: source 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.