drivers/mmc/host/sdhci-pic32.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sdhci-pic32.c
Extension
.c
Size
6374 bytes
Lines
241
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 pic32_sdhci_priv {
	struct platform_device	*pdev;
	struct clk *sys_clk;
	struct clk *base_clk;
};

static unsigned int pic32_sdhci_get_max_clock(struct sdhci_host *host)
{
	struct pic32_sdhci_priv *sdhci_pdata = sdhci_priv(host);

	return clk_get_rate(sdhci_pdata->base_clk);
}

static void pic32_sdhci_set_bus_width(struct sdhci_host *host, int width)
{
	u8 ctrl;

	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
	if (width == MMC_BUS_WIDTH_8) {
		ctrl &= ~SDHCI_CTRL_4BITBUS;
		if (host->version >= SDHCI_SPEC_300)
			ctrl |= SDHCI_CTRL_8BITBUS;
	} else {
		if (host->version >= SDHCI_SPEC_300)
			ctrl &= ~SDHCI_CTRL_8BITBUS;
		if (width == MMC_BUS_WIDTH_4)
			ctrl |= SDHCI_CTRL_4BITBUS;
		else
			ctrl &= ~SDHCI_CTRL_4BITBUS;
	}

	/* CD select and test bits must be set for errata workaround. */
	ctrl &= ~SDHCI_CTRL_CDTLVL;
	ctrl |= SDHCI_CTRL_CDSSEL;
	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}

static unsigned int pic32_sdhci_get_ro(struct sdhci_host *host)
{
	/*
	 * The SDHCI_WRITE_PROTECT bit is unstable on current hardware so we
	 * can't depend on its value in any way.
	 */
	return 0;
}

static const struct sdhci_ops pic32_sdhci_ops = {
	.get_max_clock = pic32_sdhci_get_max_clock,
	.set_clock = sdhci_set_clock,
	.set_bus_width = pic32_sdhci_set_bus_width,
	.reset = sdhci_reset,
	.set_uhs_signaling = sdhci_set_uhs_signaling,
	.get_ro = pic32_sdhci_get_ro,
};

static const struct sdhci_pltfm_data sdhci_pic32_pdata = {
	.ops = &pic32_sdhci_ops,
	.quirks = SDHCI_QUIRK_NO_HISPD_BIT,
	.quirks2 = SDHCI_QUIRK2_NO_1_8_V,
};

static void pic32_sdhci_shared_bus(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	u32 bus = readl(host->ioaddr + SDH_SHARED_BUS_CTRL);
	u32 clk_pins = (bus & SDH_SHARED_BUS_NR_CLK_PINS_MASK) >> 0;
	u32 irq_pins = (bus & SDH_SHARED_BUS_NR_IRQ_PINS_MASK) >> 4;

	/* select first clock */
	if (clk_pins & 1)
		bus |= (1 << SDH_SHARED_BUS_CLK_PINS);

	/* select first interrupt */
	if (irq_pins & 1)
		bus |= (1 << SDH_SHARED_BUS_IRQ_PINS);

	writel(bus, host->ioaddr + SDH_SHARED_BUS_CTRL);
}

static void pic32_sdhci_probe_platform(struct platform_device *pdev,
				      struct pic32_sdhci_priv *pdata)
{
	u32 caps_slot_type;
	struct sdhci_host *host = platform_get_drvdata(pdev);

	/* Check card slot connected on shared bus. */
	host->caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
	caps_slot_type = (host->caps & SDH_CAPS_SDH_SLOT_TYPE_MASK) >> 30;
	if (caps_slot_type == SDH_SLOT_TYPE_SHARED_BUS)
		pic32_sdhci_shared_bus(pdev);

Annotation

Implementation Notes