drivers/mmc/host/sdhci-milbeaut.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sdhci-milbeaut.c
Extension
.c
Size
9110 bytes
Lines
340
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 f_sdhost_priv {
	struct clk *clk_iface;
	struct clk *clk;
	struct device *dev;
	bool enable_cmd_dat_delay;
};

static void sdhci_milbeaut_soft_voltage_switch(struct sdhci_host *host)
{
	u32 ctrl = 0;

	usleep_range(2500, 3000);
	ctrl = sdhci_readl(host, F_SDH30_IO_CONTROL2);
	ctrl |= F_SDH30_CRES_O_DN;
	sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2);
	ctrl |= F_SDH30_MSEL_O_1_8;
	sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2);

	ctrl &= ~F_SDH30_CRES_O_DN;
	sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2);
	usleep_range(2500, 3000);

	ctrl = sdhci_readl(host, F_SDH30_TUNING_SETTING);
	ctrl |= F_SDH30_CMD_CHK_DIS;
	sdhci_writel(host, ctrl, F_SDH30_TUNING_SETTING);
}

static unsigned int sdhci_milbeaut_get_min_clock(struct sdhci_host *host)
{
	return F_SDH30_MIN_CLOCK;
}

static void sdhci_milbeaut_reset(struct sdhci_host *host, u8 mask)
{
	struct f_sdhost_priv *priv = sdhci_priv(host);
	u16 clk;
	u32 ctl;
	ktime_t timeout;

	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
	clk = (clk & ~SDHCI_CLOCK_CARD_EN) | SDHCI_CLOCK_INT_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	sdhci_reset(host, mask);

	clk |= SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	timeout = ktime_add_ms(ktime_get(), 10);
	while (1) {
		bool timedout = ktime_after(ktime_get(), timeout);

		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
		if (clk & SDHCI_CLOCK_INT_STABLE)
			break;
		if (timedout) {
			pr_err("%s: Internal clock never stabilised.\n",
				mmc_hostname(host->mmc));
			sdhci_dumpregs(host);
			return;
		}
		udelay(10);
	}

	if (priv->enable_cmd_dat_delay) {
		ctl = sdhci_readl(host, F_SDH30_ESD_CONTROL);
		ctl |= F_SDH30_CMD_DAT_DELAY;
		sdhci_writel(host, ctl, F_SDH30_ESD_CONTROL);
	}
}

static const struct sdhci_ops sdhci_milbeaut_ops = {
	.voltage_switch = sdhci_milbeaut_soft_voltage_switch,
	.get_min_clock = sdhci_milbeaut_get_min_clock,
	.reset = sdhci_milbeaut_reset,
	.set_clock = sdhci_set_clock,
	.set_bus_width = sdhci_set_bus_width,
	.set_uhs_signaling = sdhci_set_uhs_signaling,
	.set_power = sdhci_set_power_and_bus_voltage,
};

static void sdhci_milbeaut_bridge_reset(struct sdhci_host *host,
						int reset_flag)
{
	if (reset_flag)
		sdhci_writel(host, 0, MLB_SOFT_RESET);
	else
		sdhci_writel(host, MLB_SOFT_RESET_RSTX, MLB_SOFT_RESET);
}

Annotation

Implementation Notes