drivers/mmc/host/sdhci-s3c.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sdhci-s3c.c
Extension
.c
Size
20515 bytes
Lines
777
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_s3c {
	struct sdhci_host	*host;
	struct platform_device	*pdev;
	struct resource		*ioarea;
	struct s3c_sdhci_platdata *pdata;
	int			cur_clk;
	int			ext_cd_irq;

	struct clk		*clk_io;
	struct clk		*clk_bus[MAX_BUS_CLK];
	unsigned long		clk_rates[MAX_BUS_CLK];

	bool			no_divider;
};

/**
 * struct sdhci_s3c_drv_data - S3C SDHCI platform specific driver data
 * @sdhci_quirks: sdhci host specific quirks.
 * @no_divider: no or non-standard internal clock divider.
 * @ops: sdhci_ops to use for this variant
 *
 * Specifies platform specific configuration of sdhci controller.
 * Note: A structure for driver specific platform data is used for future
 * expansion of its usage.
 */
struct sdhci_s3c_drv_data {
	unsigned int		sdhci_quirks;
	bool			no_divider;
	const struct sdhci_ops	*ops;
};

static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
{
	return sdhci_priv(host);
}

/**
 * sdhci_s3c_get_max_clk - callback to get maximum clock frequency.
 * @host: The SDHCI host instance.
 *
 * Callback to return the maximum clock rate acheivable by the controller.
*/
static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
{
	struct sdhci_s3c *ourhost = to_s3c(host);
	unsigned long rate, max = 0;
	int src;

	for (src = 0; src < MAX_BUS_CLK; src++) {
		rate = ourhost->clk_rates[src];
		if (rate > max)
			max = rate;
	}

	return max;
}

/**
 * sdhci_s3c_consider_clock - consider one the bus clocks for current setting
 * @ourhost: Our SDHCI instance.
 * @src: The source clock index.
 * @wanted: The clock frequency wanted.
 */
static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
					     unsigned int src,
					     unsigned int wanted)
{
	unsigned long rate;
	struct clk *clksrc = ourhost->clk_bus[src];
	int shift;

	if (IS_ERR(clksrc))
		return UINT_MAX;

	/*
	 * If controller uses a non-standard clock division, find the best clock
	 * speed possible with selected clock source and skip the division.
	 */
	if (ourhost->no_divider) {
		rate = clk_round_rate(clksrc, wanted);
		return wanted - rate;
	}

	rate = ourhost->clk_rates[src];

	for (shift = 0; shift <= 8; ++shift) {
		if ((rate >> shift) <= wanted)
			break;
	}

Annotation

Implementation Notes