drivers/mmc/host/sdhci-brcmstb.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sdhci-brcmstb.c
Extension
.c
Size
20296 bytes
Lines
698
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 sdhci_brcmstb_saved_regs {
	u32 sd_pin_sel;
	u32 phy_sw_mode0_rxctrl;
	u32 max_50mhz_mode;
	u32 boot_main_ctl;
};

struct brcmstb_match_priv {
	void (*cfginit)(struct sdhci_host *host);
	void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
	void (*save_restore_regs)(struct mmc_host *mmc, int save);
	struct sdhci_ops *ops;
	const unsigned int flags;
};

struct sdhci_brcmstb_priv {
	void __iomem *cfg_regs;
	void __iomem *boot_regs;
	struct sdhci_brcmstb_saved_regs saved_regs;
	unsigned int flags;
	struct clk *base_clk;
	u32 base_freq_hz;
	const struct brcmstb_match_priv *match_priv;
};

static void sdhci_brcmstb_save_regs(struct mmc_host *mmc, enum cfg_core_ver ver)
{
	struct sdhci_host *host = mmc_priv(mmc);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
	struct sdhci_brcmstb_saved_regs *sr = &priv->saved_regs;
	void __iomem *cr = priv->cfg_regs;
	bool is_emmc = mmc->caps & MMC_CAP_NONREMOVABLE;

	if (is_emmc && priv->boot_regs)
		sr->boot_main_ctl = readl(priv->boot_regs + SDIO_BOOT_MAIN_CTL);

	if (ver == SDIO_CFG_CORE_V1) {
		sr->sd_pin_sel = readl(cr + SDIO_CFG_V1_SD_PIN_SEL);
		return;
	}

	sr->sd_pin_sel = readl(cr + SDIO_CFG_SD_PIN_SEL);
	sr->phy_sw_mode0_rxctrl = readl(cr + SDIO_CFG_PHY_SW_MODE_0_RX_CTRL);
	sr->max_50mhz_mode = readl(cr + SDIO_CFG_MAX_50MHZ_MODE);
}

static void sdhci_brcmstb_restore_regs(struct mmc_host *mmc, enum cfg_core_ver ver)
{
	struct sdhci_host *host = mmc_priv(mmc);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
	struct sdhci_brcmstb_saved_regs *sr = &priv->saved_regs;
	void __iomem *cr = priv->cfg_regs;
	bool is_emmc = mmc->caps & MMC_CAP_NONREMOVABLE;

	if (is_emmc && priv->boot_regs)
		writel(sr->boot_main_ctl, priv->boot_regs + SDIO_BOOT_MAIN_CTL);

	if (ver == SDIO_CFG_CORE_V1) {
		writel(sr->sd_pin_sel, cr + SDIO_CFG_V1_SD_PIN_SEL);
		return;
	}

	writel(sr->sd_pin_sel, cr + SDIO_CFG_SD_PIN_SEL);
	writel(sr->phy_sw_mode0_rxctrl, cr + SDIO_CFG_PHY_SW_MODE_0_RX_CTRL);
	writel(sr->max_50mhz_mode, cr + SDIO_CFG_MAX_50MHZ_MODE);
}

static void sdhci_brcmstb_save_restore_regs_v1(struct mmc_host *mmc, int save)
{
	if (save)
		sdhci_brcmstb_save_regs(mmc, SDIO_CFG_CORE_V1);
	else
		sdhci_brcmstb_restore_regs(mmc, SDIO_CFG_CORE_V1);
}

static void sdhci_brcmstb_save_restore_regs_v2(struct mmc_host *mmc, int save)
{
	if (save)
		sdhci_brcmstb_save_regs(mmc, SDIO_CFG_CORE_V2);
	else
		sdhci_brcmstb_restore_regs(mmc, SDIO_CFG_CORE_V2);
}

static inline void enable_clock_gating(struct sdhci_host *host)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
	u32 reg;

Annotation

Implementation Notes