drivers/mmc/host/sdhci-esdhc-mcf.c

Source file repositories/reference/linux-study-clean/drivers/mmc/host/sdhci-esdhc-mcf.c

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sdhci-esdhc-mcf.c
Extension
.c
Size
12353 bytes
Lines
512
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pltfm_mcf_data {
	struct clk *clk_ipg;
	struct clk *clk_ahb;
	struct clk *clk_per;
	int aside;
	int current_bus_width;
};

static inline void esdhc_mcf_buffer_swap32(u32 *buf, int len)
{
	int i;
	u32 temp;

	len = (len + 3) >> 2;

	for (i = 0; i < len;  i++) {
		temp = swab32(*buf);
		*buf++ = temp;
	}
}

static inline void esdhc_clrset_be(struct sdhci_host *host,
				   u32 mask, u32 val, int reg)
{
	void __iomem *base = host->ioaddr + (reg & ~3);
	u8 shift = (reg & 3) << 3;

	mask <<= shift;
	val <<= shift;

	if (reg == SDHCI_HOST_CONTROL)
		val |= ESDHC_PROCTL_D3CD;

	writel((readl(base) & ~mask) | val, base);
}

/*
 * Note: mcf is big-endian, single bytes need to be accessed at big endian
 * offsets.
 */
static void esdhc_mcf_writeb_be(struct sdhci_host *host, u8 val, int reg)
{
	void __iomem *base = host->ioaddr + (reg & ~3);
	u8 shift = (reg & 3) << 3;
	u32 mask = ~(0xff << shift);

	if (reg == SDHCI_HOST_CONTROL) {
		u32 host_ctrl = ESDHC_DEFAULT_HOST_CONTROL;
		u8 dma_bits = (val & SDHCI_CTRL_DMA_MASK) >> 3;
		u8 tmp = readb(host->ioaddr + SDHCI_HOST_CONTROL + 1);

		tmp &= ~0x03;
		tmp |= dma_bits;

		/*
		 * Recomposition needed, restore always endianness and
		 * keep D3CD and AI, just setting bus width.
		 */
		host_ctrl |= val;
		host_ctrl |= (dma_bits << 8);
		writel(host_ctrl, host->ioaddr + SDHCI_HOST_CONTROL);

		return;
	}

	writel((readl(base) & mask) | (val << shift), base);
}

static void esdhc_mcf_writew_be(struct sdhci_host *host, u16 val, int reg)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct pltfm_mcf_data *mcf_data = sdhci_pltfm_priv(pltfm_host);
	void __iomem *base = host->ioaddr + (reg & ~3);
	u8 shift = (reg & 3) << 3;
	u32 mask = ~(0xffff << shift);

	switch (reg) {
	case SDHCI_TRANSFER_MODE:
		mcf_data->aside = val;
		return;
	case SDHCI_COMMAND:
		if (host->cmd->opcode == MMC_STOP_TRANSMISSION)
			val |= SDHCI_CMD_ABORTCMD;

		/*
		 * As for the fsl driver,
		 * we have to set the mode in a single write here.
		 */
		writel(val << 16 | mcf_data->aside,
		       host->ioaddr + SDHCI_TRANSFER_MODE);

Annotation

Implementation Notes