drivers/clk/rockchip/clk-pll.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/rockchip/clk-pll.c
Extension
.c
Size
35103 bytes
Lines
1207
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 rockchip_clk_pll {
	struct clk_hw		hw;

	struct clk_mux		pll_mux;
	const struct clk_ops	*pll_mux_ops;

	struct notifier_block	clk_nb;

	void __iomem		*reg_base;
	int			lock_offset;
	unsigned int		lock_shift;
	enum rockchip_pll_type	type;
	u8			flags;
	const struct rockchip_pll_rate_table *rate_table;
	unsigned int		rate_count;
	spinlock_t		*lock;

	struct rockchip_clk_provider *ctx;
};

#define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw)
#define to_rockchip_clk_pll_nb(nb) \
			container_of(nb, struct rockchip_clk_pll, clk_nb)

static const struct rockchip_pll_rate_table *rockchip_get_pll_settings(
			    struct rockchip_clk_pll *pll, unsigned long rate)
{
	const struct rockchip_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 int rockchip_pll_determine_rate(struct clk_hw *hw,
				       struct clk_rate_request *req)
{
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
	const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
	int i;

	/* Assuming rate_table is in descending order */
	for (i = 0; i < pll->rate_count; i++) {
		if (req->rate >= rate_table[i].rate) {
			req->rate = rate_table[i].rate;

			return 0;
		}
	}

	/* return minimum supported value */
	req->rate = rate_table[i - 1].rate;

	return 0;
}

/*
 * Wait for the pll to reach the locked state.
 * The calling set_rate function is responsible for making sure the
 * grf regmap is available.
 */
static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
{
	struct regmap *grf = pll->ctx->grf;
	unsigned int val;
	int ret;

	ret = regmap_read_poll_timeout(grf, pll->lock_offset, val,
				       val & BIT(pll->lock_shift), 0, 1000);
	if (ret)
		pr_err("%s: timeout waiting for pll to lock\n", __func__);

	return ret;
}

/*
 * PLL used in RK3036
 */

#define RK3036_PLLCON(i)			(i * 0x4)
#define RK3036_PLLCON0_FBDIV_MASK		0xfff
#define RK3036_PLLCON0_FBDIV_SHIFT		0
#define RK3036_PLLCON0_POSTDIV1_MASK		0x7
#define RK3036_PLLCON0_POSTDIV1_SHIFT		12
#define RK3036_PLLCON1_REFDIV_MASK		0x3f
#define RK3036_PLLCON1_REFDIV_SHIFT		0

Annotation

Implementation Notes