drivers/mmc/host/sdhci-of-dwcmshc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sdhci-of-dwcmshc.c
Extension
.c
Size
81758 bytes
Lines
2647
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 rk35xx_priv {
	struct reset_control *reset;
	u8 txclk_tapnum;
};

struct eic7700_priv {
	struct reset_control *reset;
	unsigned int drive_impedance;
};

struct k230_priv  {
	/* Canaan k230 specific */
	struct regmap *hi_sys_regmap;
};

#define DWCMSHC_MAX_OTHER_CLKS 3

struct dwcmshc_priv {
	struct clk	*bus_clk;
	int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA1 reg */
	int vendor_specific_area2; /* P_VENDOR_SPECIFIC_AREA2 reg */

	int num_other_clks;
	struct clk_bulk_data other_clks[DWCMSHC_MAX_OTHER_CLKS];

	const struct dwcmshc_pltfm_data *dwcmshc_pdata;
	void *priv; /* pointer to SoC private stuff */
	u16 delay_line;
	u16 flags;
};

struct dwcmshc_pltfm_data {
	const struct sdhci_pltfm_data pdata;
	const struct cqhci_host_ops *cqhci_host_ops;
	int (*init)(struct device *dev, struct sdhci_host *host, struct dwcmshc_priv *dwc_priv);
	void (*postinit)(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv);
};

struct k230_pltfm_data {
	struct dwcmshc_pltfm_data dwcmshc_pdata;
	bool is_emmc;
	u32 ctrl_reg;
	u32 vol_stable_bit;
	u32 write_prot_bit;
};

struct rockchip_pltfm_data {
	struct dwcmshc_pltfm_data dwcmshc_pdata;
	/*
	 * The controller hardware has two known revisions documented internally:
	 * - Revision 0: Exclusively used by RK3566 and RK3568 SoCs.
	 * - Revision 1: Implemented in all other Rockchip SoCs, including RK3576, RK3588, etc.
	 */
	int revision;
};

static void dwcmshc_enable_card_clk(struct sdhci_host *host)
{
	u16 ctrl;

	ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
	if ((ctrl & SDHCI_CLOCK_INT_EN) && !(ctrl & SDHCI_CLOCK_CARD_EN)) {
		ctrl |= SDHCI_CLOCK_CARD_EN;
		sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL);
	}
}

static int dwcmshc_get_enable_other_clks(struct device *dev,
					 struct dwcmshc_priv *priv,
					 int num_clks,
					 const char * const clk_ids[])
{
	int err;

	if (num_clks > DWCMSHC_MAX_OTHER_CLKS)
		return -EINVAL;

	for (int i = 0; i < num_clks; i++)
		priv->other_clks[i].id = clk_ids[i];

	err = devm_clk_bulk_get_optional(dev, num_clks, priv->other_clks);
	if (err) {
		dev_err(dev, "failed to get clocks %d\n", err);
		return err;
	}

	err = clk_bulk_prepare_enable(num_clks, priv->other_clks);
	if (err)
		dev_err(dev, "failed to enable clocks %d\n", err);

Annotation

Implementation Notes