drivers/mmc/host/sdhci-pci-arasan.c

Source file repositories/reference/linux-study-clean/drivers/mmc/host/sdhci-pci-arasan.c

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sdhci-pci-arasan.c
Extension
.c
Size
8525 bytes
Lines
332
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 arasan_host {
	u32 chg_clk;
};

static int arasan_phy_addr_poll(struct sdhci_host *host, u32 offset, u32 mask)
{
	ktime_t timeout = ktime_add_us(ktime_get(), 100);
	bool failed;
	u8 val = 0;

	while (1) {
		failed = ktime_after(ktime_get(), timeout);
		val = sdhci_readw(host, PHY_ADDR_REG);
		if (!(val & mask))
			return 0;
		if (failed)
			return -EBUSY;
	}
}

static int arasan_phy_write(struct sdhci_host *host, u8 data, u8 offset)
{
	sdhci_writew(host, data, PHY_DAT_REG);
	sdhci_writew(host, (PHY_WRITE | offset), PHY_ADDR_REG);
	return arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY);
}

static int arasan_phy_read(struct sdhci_host *host, u8 offset, u8 *data)
{
	int ret;

	sdhci_writew(host, 0, PHY_DAT_REG);
	sdhci_writew(host, offset, PHY_ADDR_REG);
	ret = arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY);

	/* Masking valid data bits */
	*data = sdhci_readw(host, PHY_DAT_REG) & DATA_MASK;
	return ret;
}

static int arasan_phy_sts_poll(struct sdhci_host *host, u32 offset, u32 mask)
{
	int ret;
	ktime_t timeout = ktime_add_us(ktime_get(), 100);
	bool failed;
	u8 val = 0;

	while (1) {
		failed = ktime_after(ktime_get(), timeout);
		ret = arasan_phy_read(host, offset, &val);
		if (ret)
			return -EBUSY;
		else if (val & mask)
			return 0;
		if (failed)
			return -EBUSY;
	}
}

/* Initialize the Arasan PHY */
static int arasan_phy_init(struct sdhci_host *host)
{
	int ret;
	u8 val;

	/* Program IOPADs and wait for calibration to be done */
	if (arasan_phy_read(host, IPAD_CTRL1, &val) ||
	    arasan_phy_write(host, val | RETB_ENBL | PDB_ENBL, IPAD_CTRL1) ||
	    arasan_phy_read(host, IPAD_CTRL2, &val) ||
	    arasan_phy_write(host, val | RTRIM_EN, IPAD_CTRL2))
		return -EBUSY;
	ret = arasan_phy_sts_poll(host, IPAD_STS, CALDONE_MASK);
	if (ret)
		return -EBUSY;

	/* Program CMD/Data lines */
	if (arasan_phy_read(host, IOREN_CTRL1, &val) ||
	    arasan_phy_write(host, val | REN_CMND | REN_STRB, IOREN_CTRL1) ||
	    arasan_phy_read(host, IOPU_CTRL1, &val) ||
	    arasan_phy_write(host, val | PU_CMD, IOPU_CTRL1) ||
	    arasan_phy_read(host, CMD_CTRL, &val) ||
	    arasan_phy_write(host, val | PDB_CMND, CMD_CTRL) ||
	    arasan_phy_read(host, IOREN_CTRL2, &val) ||
	    arasan_phy_write(host, val | REN_DATA, IOREN_CTRL2) ||
	    arasan_phy_read(host, IOPU_CTRL2, &val) ||
	    arasan_phy_write(host, val | PU_DAT, IOPU_CTRL2) ||
	    arasan_phy_read(host, DATA_CTRL, &val) ||
	    arasan_phy_write(host, val | PDB_DATA, DATA_CTRL) ||
	    arasan_phy_read(host, STRB_CTRL, &val) ||
	    arasan_phy_write(host, val | PDB_STRB, STRB_CTRL) ||

Annotation

Implementation Notes