drivers/clk/spear/clk-vco-pll.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/spear/clk-vco-pll.c
Extension
.c
Size
8846 bytes
Lines
364
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

if (drate < rate) {
			/* previous clock was best */
			if (*index) {
				rate = prev_rate;
				*prate = vco_prev_rate;
				(*index)--;
			}
			break;
		}
	}

	return rate;
}

static int clk_pll_determine_rate(struct clk_hw *hw,
				  struct clk_rate_request *req)
{
	int unused;

	req->rate = clk_pll_round_rate_index(hw, req->rate,
					     &req->best_parent_rate, &unused);

	return 0;
}

static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long
		parent_rate)
{
	struct clk_pll *pll = to_clk_pll(hw);
	unsigned long flags = 0;
	unsigned int p;

	if (pll->vco->lock)
		spin_lock_irqsave(pll->vco->lock, flags);

	p = readl_relaxed(pll->vco->cfg_reg);

	if (pll->vco->lock)
		spin_unlock_irqrestore(pll->vco->lock, flags);

	p = (p >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK;

	return parent_rate / (1 << p);
}

static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
				unsigned long prate)
{
	struct clk_pll *pll = to_clk_pll(hw);
	struct pll_rate_tbl *rtbl = pll->vco->rtbl;
	unsigned long flags = 0, val;
	int i = 0;

	clk_pll_round_rate_index(hw, drate, NULL, &i);

	if (pll->vco->lock)
		spin_lock_irqsave(pll->vco->lock, flags);

	val = readl_relaxed(pll->vco->cfg_reg);
	val &= ~(PLL_DIV_P_MASK << PLL_DIV_P_SHIFT);
	val |= (rtbl[i].p & PLL_DIV_P_MASK) << PLL_DIV_P_SHIFT;
	writel_relaxed(val, pll->vco->cfg_reg);

	if (pll->vco->lock)
		spin_unlock_irqrestore(pll->vco->lock, flags);

	return 0;
}

static const struct clk_ops clk_pll_ops = {
	.recalc_rate = clk_pll_recalc_rate,
	.determine_rate = clk_pll_determine_rate,
	.set_rate = clk_pll_set_rate,
};

static inline unsigned long vco_calc_rate(struct clk_hw *hw,
		unsigned long prate, int index)
{
	struct clk_vco *vco = to_clk_vco(hw);

	return pll_calc_rate(vco->rtbl, prate, index, NULL);
}

static int clk_vco_determine_rate(struct clk_hw *hw,
				  struct clk_rate_request *req)
{
	struct clk_vco *vco = to_clk_vco(hw);
	int unused;

	req->rate = clk_round_rate_index(hw, req->rate, req->best_parent_rate,

Annotation

Implementation Notes