drivers/mmc/host/davinci_mmc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/davinci_mmc.c
Extension
.c
Size
38887 bytes
Lines
1395
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 mmc_davinci_host {
	struct mmc_command *cmd;
	struct mmc_data *data;
	struct mmc_host *mmc;
	struct clk *clk;
	unsigned int mmc_input_clk;
	void __iomem *base;
	struct resource *mem_res;
	int mmc_irq, sdio_irq;
	unsigned char bus_mode;

#define DAVINCI_MMC_DATADIR_NONE	0
#define DAVINCI_MMC_DATADIR_READ	1
#define DAVINCI_MMC_DATADIR_WRITE	2
	unsigned char data_dir;

	u32 bytes_left;

	struct dma_chan *dma_tx;
	struct dma_chan *dma_rx;
	bool use_dma;
	bool do_dma;
	bool sdio_int;
	bool active_request;

	/* For PIO we walk scatterlists one segment at a time. */
	struct sg_mapping_iter sg_miter;
	unsigned int		sg_len;

	/* Version of the MMC/SD controller */
	u8 version;
	/* for ns in one cycle calculation */
	unsigned ns_in_one_cycle;
	/* Number of sg segments */
	u8 nr_sg;
#ifdef CONFIG_CPU_FREQ
	struct notifier_block	freq_transition;
#endif
};

static irqreturn_t mmc_davinci_irq(int irq, void *dev_id);

/* PIO only */
static void davinci_fifo_data_trans(struct mmc_davinci_host *host,
					unsigned int n)
{
	struct sg_mapping_iter *sgm = &host->sg_miter;
	u8 *p;
	unsigned int i;

	/*
	 * By adjusting sgm->consumed this will give a pointer to the
	 * current index into the sgm.
	 */
	if (!sg_miter_next(sgm)) {
		dev_err(mmc_dev(host->mmc), "ran out of sglist prematurely\n");
		return;
	}
	p = sgm->addr;

	if (n > sgm->length)
		n = sgm->length;

	/* NOTE:  we never transfer more than rw_threshold bytes
	 * to/from the fifo here; there's no I/O overlap.
	 * This also assumes that access width( i.e. ACCWD) is 4 bytes
	 */
	if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
		for (i = 0; i < (n >> 2); i++) {
			writel(*((u32 *)p), host->base + DAVINCI_MMCDXR);
			p = p + 4;
		}
		if (n & 3) {
			iowrite8_rep(host->base + DAVINCI_MMCDXR, p, (n & 3));
			p = p + (n & 3);
		}
	} else {
		for (i = 0; i < (n >> 2); i++) {
			*((u32 *)p) = readl(host->base + DAVINCI_MMCDRR);
			p  = p + 4;
		}
		if (n & 3) {
			ioread8_rep(host->base + DAVINCI_MMCDRR, p, (n & 3));
			p = p + (n & 3);
		}
	}

	sgm->consumed = n;
	host->bytes_left -= n;
}

Annotation

Implementation Notes