drivers/clk/visconti/pll.c

Source file repositories/reference/linux-study-clean/drivers/clk/visconti/pll.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/visconti/pll.c
Extension
.c
Size
8821 bytes
Lines
346
Domain
Driver Families
Bucket
drivers/clk
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 visconti_pll {
	struct clk_hw	hw;
	void __iomem	*pll_base;
	spinlock_t	*lock;
	unsigned long flags;
	const struct visconti_pll_rate_table *rate_table;
	size_t rate_count;
	struct visconti_pll_provider *ctx;
};

#define PLL_CONF_REG		0x0000
#define PLL_CTRL_REG		0x0004
#define PLL_FRACMODE_REG	0x0010
#define PLL_INTIN_REG		0x0014
#define PLL_FRACIN_REG		0x0018
#define PLL_REFDIV_REG		0x001c
#define PLL_POSTDIV_REG		0x0020

#define PLL_CONFIG_SEL		BIT(0)
#define PLL_PLLEN		BIT(4)
#define PLL_BYPASS		BIT(16)
#define PLL_INTIN_MASK		GENMASK(11, 0)
#define PLL_FRACIN_MASK		GENMASK(23, 0)
#define PLL_REFDIV_MASK		GENMASK(5, 0)
#define PLL_POSTDIV_MASK	GENMASK(2, 0)

#define PLL0_FRACMODE_DACEN	BIT(4)
#define PLL0_FRACMODE_DSMEN	BIT(0)

#define PLL_CREATE_FRACMODE(table) (table->dacen << 4 | table->dsmen)
#define PLL_CREATE_OSTDIV(table) (table->postdiv2 << 4 | table->postdiv1)

static inline struct visconti_pll *to_visconti_pll(struct clk_hw *hw)
{
	return container_of(hw, struct visconti_pll, hw);
}

static void visconti_pll_get_params(struct visconti_pll *pll,
				    struct visconti_pll_rate_table *rate_table)
{
	u32 postdiv, val;

	val = readl(pll->pll_base + PLL_FRACMODE_REG);

	rate_table->dacen = FIELD_GET(PLL0_FRACMODE_DACEN, val);
	rate_table->dsmen = FIELD_GET(PLL0_FRACMODE_DSMEN, val);

	rate_table->fracin = readl(pll->pll_base + PLL_FRACIN_REG) & PLL_FRACIN_MASK;
	rate_table->intin = readl(pll->pll_base + PLL_INTIN_REG) & PLL_INTIN_MASK;
	rate_table->refdiv = readl(pll->pll_base + PLL_REFDIV_REG) & PLL_REFDIV_MASK;

	postdiv = readl(pll->pll_base + PLL_POSTDIV_REG);
	rate_table->postdiv1 = postdiv & PLL_POSTDIV_MASK;
	rate_table->postdiv2 = (postdiv >> 4) & PLL_POSTDIV_MASK;
}

static const struct visconti_pll_rate_table *visconti_get_pll_settings(struct visconti_pll *pll,
								       unsigned long rate)
{
	const struct visconti_pll_rate_table *rate_table = pll->rate_table;
	int i;

	for (i = 0; i < pll->rate_count; i++)
		if (rate == rate_table[i].rate)
			return &rate_table[i];

	return NULL;
}

static unsigned long visconti_get_pll_rate_from_data(struct visconti_pll *pll,
						     const struct visconti_pll_rate_table *rate)
{
	const struct visconti_pll_rate_table *rate_table = pll->rate_table;
	int i;

	for (i = 0; i < pll->rate_count; i++)
		if (memcmp(&rate_table[i].dacen, &rate->dacen,
			sizeof(*rate) - sizeof(unsigned long)) == 0)
			return rate_table[i].rate;

	/* set default */
	return rate_table[0].rate;
}

static int visconti_pll_determine_rate(struct clk_hw *hw,
				       struct clk_rate_request *req)
{
	struct visconti_pll *pll = to_visconti_pll(hw);
	const struct visconti_pll_rate_table *rate_table = pll->rate_table;
	int i;

Annotation

Implementation Notes