drivers/mmc/host/sunxi-mmc.c

Source file repositories/reference/linux-study-clean/drivers/mmc/host/sunxi-mmc.c

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sunxi-mmc.c
Extension
.c
Size
42913 bytes
Lines
1554
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 sunxi_mmc_clk_delay {
	u32 output;
	u32 sample;
};

struct sunxi_idma_des {
	__le32 config;
	__le32 buf_size;
	__le32 buf_addr_ptr1;
	__le32 buf_addr_ptr2;
};

struct sunxi_mmc_cfg {
	u32 idma_des_size_bits;
	u32 idma_des_shift;
	const struct sunxi_mmc_clk_delay *clk_delays;

	/* does the IP block support autocalibration? */
	bool can_calibrate;

	/* Does DATA0 needs to be masked while the clock is updated */
	bool mask_data0;

	/*
	 * hardware only supports new timing mode, either due to lack of
	 * a mode switch in the clock controller, or the mmc controller
	 * is permanently configured in the new timing mode, without the
	 * NTSR mode switch.
	 */
	bool needs_new_timings;

	/* clock hardware can switch between old and new timing modes */
	bool ccu_has_timings_switch;
};

struct sunxi_mmc_host {
	struct device *dev;
	struct mmc_host	*mmc;
	struct reset_control *reset;
	const struct sunxi_mmc_cfg *cfg;

	/* IO mapping base */
	void __iomem	*reg_base;

	/* clock management */
	struct clk	*clk_ahb;
	struct clk	*clk_mmc;
	struct clk	*clk_sample;
	struct clk	*clk_output;

	/* irq */
	spinlock_t	lock;
	int		irq;
	u32		int_sum;
	u32		sdio_imask;

	/* dma */
	dma_addr_t	sg_dma;
	void		*sg_cpu;
	bool		wait_dma;

	struct mmc_request *mrq;
	struct mmc_request *manual_stop_mrq;
	int		ferror;

	/* vqmmc */
	bool		vqmmc_enabled;

	/* timings */
	bool		use_new_timings;
};

static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host)
{
	unsigned long expire = jiffies + msecs_to_jiffies(250);
	u32 rval;

	mmc_writel(host, REG_GCTRL, SDXC_HARDWARE_RESET);
	do {
		rval = mmc_readl(host, REG_GCTRL);
	} while (time_before(jiffies, expire) && (rval & SDXC_HARDWARE_RESET));

	if (rval & SDXC_HARDWARE_RESET) {
		dev_err(mmc_dev(host->mmc), "fatal err reset timeout\n");
		return -EIO;
	}

	return 0;
}

Annotation

Implementation Notes