drivers/clk/pistachio/clk-pll.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/pistachio/clk-pll.c
Extension
.c
Size
14124 bytes
Lines
515
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 pistachio_clk_pll {
	struct clk_hw hw;
	void __iomem *base;
	struct pistachio_pll_rate_table *rates;
	unsigned int nr_rates;
};

static inline u32 pll_readl(struct pistachio_clk_pll *pll, u32 reg)
{
	return readl(pll->base + reg);
}

static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg)
{
	writel(val, pll->base + reg);
}

static inline void pll_lock(struct pistachio_clk_pll *pll)
{
	while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
		cpu_relax();
}

static inline u64 do_div_round_closest(u64 dividend, u64 divisor)
{
	dividend += divisor / 2;
	return div64_u64(dividend, divisor);
}

static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw)
{
	return container_of(hw, struct pistachio_clk_pll, hw);
}

static inline enum pll_mode pll_frac_get_mode(struct clk_hw *hw)
{
	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
	u32 val;

	val = pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_DSMPD;
	return val ? PLL_MODE_INT : PLL_MODE_FRAC;
}

static inline void pll_frac_set_mode(struct clk_hw *hw, enum pll_mode mode)
{
	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
	u32 val;

	val = pll_readl(pll, PLL_CTRL3);
	if (mode == PLL_MODE_INT)
		val |= PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD;
	else
		val &= ~(PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD);

	pll_writel(pll, val, PLL_CTRL3);
}

static struct pistachio_pll_rate_table *
pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref,
	       unsigned long fout)
{
	unsigned int i;

	for (i = 0; i < pll->nr_rates; i++) {
		if (pll->rates[i].fref == fref && pll->rates[i].fout == fout)
			return &pll->rates[i];
	}

	return NULL;
}

static int pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
	unsigned int i;

	for (i = 0; i < pll->nr_rates; i++) {
		if (i > 0 && pll->rates[i].fref == req->best_parent_rate &&
		    pll->rates[i].fout <= req->rate) {
			req->rate = pll->rates[i - 1].fout;

			return 0;
		}
	}

	req->rate = pll->rates[0].fout;

	return 0;
}

Annotation

Implementation Notes