drivers/mmc/host/sdhci-iproc.c
Source file repositories/reference/linux-study-clean/drivers/mmc/host/sdhci-iproc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mmc/host/sdhci-iproc.c- Extension
.c- Size
- 12689 bytes
- Lines
- 425
- 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/acpi.hlinux/delay.hlinux/module.hlinux/mmc/host.hlinux/of.hlinux/platform_device.hsdhci-pltfm.h
Detected Declarations
struct sdhci_iproc_datastruct sdhci_iproc_hostfunction sdhci_iproc_readlfunction sdhci_iproc_readwfunction sdhci_iproc_readbfunction sdhci_iproc_writelfunction otherfunction sdhci_iproc_writebfunction sdhci_iproc_get_max_clockfunction sdhci_iproc_bcm2711_get_min_clockfunction sdhci_iproc_probefunction sdhci_iproc_shutdown
Annotated Snippet
struct sdhci_iproc_data {
const struct sdhci_pltfm_data *pdata;
u32 caps;
u32 caps1;
u32 mmc_caps;
bool missing_caps;
};
struct sdhci_iproc_host {
const struct sdhci_iproc_data *data;
u32 shadow_cmd;
u32 shadow_blk;
bool is_cmd_shadowed;
bool is_blk_shadowed;
};
#define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)
static inline u32 sdhci_iproc_readl(struct sdhci_host *host, int reg)
{
u32 val = readl(host->ioaddr + reg);
pr_debug("%s: readl [0x%02x] 0x%08x\n",
mmc_hostname(host->mmc), reg, val);
return val;
}
static u16 sdhci_iproc_readw(struct sdhci_host *host, int reg)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_iproc_host *iproc_host = sdhci_pltfm_priv(pltfm_host);
u32 val;
u16 word;
if ((reg == SDHCI_TRANSFER_MODE) && iproc_host->is_cmd_shadowed) {
/* Get the saved transfer mode */
val = iproc_host->shadow_cmd;
} else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) &&
iproc_host->is_blk_shadowed) {
/* Get the saved block info */
val = iproc_host->shadow_blk;
} else {
val = sdhci_iproc_readl(host, (reg & ~3));
}
word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff;
return word;
}
static u8 sdhci_iproc_readb(struct sdhci_host *host, int reg)
{
u32 val = sdhci_iproc_readl(host, (reg & ~3));
u8 byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff;
return byte;
}
static inline void sdhci_iproc_writel(struct sdhci_host *host, u32 val, int reg)
{
pr_debug("%s: writel [0x%02x] 0x%08x\n",
mmc_hostname(host->mmc), reg, val);
writel(val, host->ioaddr + reg);
if (host->clock <= 400000) {
/* Round up to micro-second four SD clock delay */
if (host->clock)
udelay((4 * 1000000 + host->clock - 1) / host->clock);
else
udelay(10);
}
}
/*
* The Arasan has a bugette whereby it may lose the content of successive
* writes to the same register that are within two SD-card clock cycles of
* each other (a clock domain crossing problem). The data
* register does not have this problem, which is just as well - otherwise we'd
* have to nobble the DMA engine too.
*
* This wouldn't be a problem with the code except that we can only write the
* controller with 32-bit writes. So two different 16-bit registers are
* written back to back creates the problem.
*
* In reality, this only happens when SDHCI_BLOCK_SIZE and SDHCI_BLOCK_COUNT
* are written followed by SDHCI_TRANSFER_MODE and SDHCI_COMMAND.
* The BLOCK_SIZE and BLOCK_COUNT are meaningless until a command issued so
* the work around can be further optimized. We can keep shadow values of
* BLOCK_SIZE, BLOCK_COUNT, and TRANSFER_MODE until a COMMAND is issued.
* Then, write the BLOCK_SIZE+BLOCK_COUNT in a single 32-bit write followed
* by the TRANSFER+COMMAND in another 32-bit write.
*/
Annotation
- Immediate include surface: `linux/acpi.h`, `linux/delay.h`, `linux/module.h`, `linux/mmc/host.h`, `linux/of.h`, `linux/platform_device.h`, `sdhci-pltfm.h`.
- Detected declarations: `struct sdhci_iproc_data`, `struct sdhci_iproc_host`, `function sdhci_iproc_readl`, `function sdhci_iproc_readw`, `function sdhci_iproc_readb`, `function sdhci_iproc_writel`, `function other`, `function sdhci_iproc_writeb`, `function sdhci_iproc_get_max_clock`, `function sdhci_iproc_bcm2711_get_min_clock`.
- 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.