drivers/clk/tegra/clk-pll.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/tegra/clk-pll.c
Extension
.c
Size
71683 bytes
Lines
2741
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 utmi_clk_param {
	/* Oscillator Frequency in Hz */
	u32 osc_frequency;
	/* UTMIP PLL Enable Delay Count  */
	u8 enable_delay_count;
	/* UTMIP PLL Stable count */
	u8 stable_count;
	/*  UTMIP PLL Active delay count */
	u8 active_delay_count;
	/* UTMIP PLL Xtal frequency count */
	u8 xtal_freq_count;
};

static const struct utmi_clk_param utmi_parameters[] = {
	{
		.osc_frequency = 13000000, .enable_delay_count = 0x02,
		.stable_count = 0x33, .active_delay_count = 0x05,
		.xtal_freq_count = 0x7f
	}, {
		.osc_frequency = 19200000, .enable_delay_count = 0x03,
		.stable_count = 0x4b, .active_delay_count = 0x06,
		.xtal_freq_count = 0xbb
	}, {
		.osc_frequency = 12000000, .enable_delay_count = 0x02,
		.stable_count = 0x2f, .active_delay_count = 0x04,
		.xtal_freq_count = 0x76
	}, {
		.osc_frequency = 26000000, .enable_delay_count = 0x04,
		.stable_count = 0x66, .active_delay_count = 0x09,
		.xtal_freq_count = 0xfe
	}, {
		.osc_frequency = 16800000, .enable_delay_count = 0x03,
		.stable_count = 0x41, .active_delay_count = 0x0a,
		.xtal_freq_count = 0xa4
	}, {
		.osc_frequency = 38400000, .enable_delay_count = 0x0,
		.stable_count = 0x0, .active_delay_count = 0x6,
		.xtal_freq_count = 0x80
	},
};

static int clk_pllu_enable(struct clk_hw *hw)
{
	struct tegra_clk_pll *pll = to_clk_pll(hw);
	struct clk_hw *pll_ref = clk_hw_get_parent(hw);
	struct clk_hw *osc = clk_hw_get_parent(pll_ref);
	const struct utmi_clk_param *params = NULL;
	unsigned long flags = 0, input_rate;
	unsigned int i;
	int ret = 0;
	u32 value;

	if (!osc) {
		pr_err("%s: failed to get OSC clock\n", __func__);
		return -EINVAL;
	}

	input_rate = clk_hw_get_rate(osc);

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

	if (!clk_pll_is_enabled(hw))
		_clk_pll_enable(hw);

	ret = clk_pll_wait_for_lock(pll);
	if (ret < 0)
		goto out;

	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
		if (input_rate == utmi_parameters[i].osc_frequency) {
			params = &utmi_parameters[i];
			break;
		}
	}

	if (!params) {
		pr_err("%s: unexpected input rate %lu Hz\n", __func__,
		       input_rate);
		ret = -EINVAL;
		goto out;
	}

	value = pll_readl_base(pll);
	value &= ~PLLU_BASE_OVERRIDE;
	pll_writel_base(value, pll);

	value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
	/* Program UTMIP PLL stable and active counts */
	value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);

Annotation

Implementation Notes