diff options
Diffstat (limited to 'arch/arm/cpu/tegra20-common/clock.c')
| -rw-r--r-- | arch/arm/cpu/tegra20-common/clock.c | 38 | 
1 files changed, 38 insertions, 0 deletions
diff --git a/arch/arm/cpu/tegra20-common/clock.c b/arch/arm/cpu/tegra20-common/clock.c index a670b0746..12987a689 100644 --- a/arch/arm/cpu/tegra20-common/clock.c +++ b/arch/arm/cpu/tegra20-common/clock.c @@ -396,6 +396,16 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {  	NONE(CRAM2),  }; +/* number of clock outputs of a PLL */ +static const u8 pll_num_clkouts[] = { +	1,	/* PLLC */ +	1,	/* PLLM */ +	4,	/* PLLP */ +	1,	/* PLLA */ +	0,	/* PLLU */ +	0,	/* PLLD */ +}; +  /*   * Get the oscillator frequency, from the corresponding hardware configuration   * field. @@ -604,6 +614,34 @@ unsigned long clock_get_periph_rate(enum periph_id periph_id,  		(readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);  } +int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout, unsigned rate) +{ +	struct clk_pll *pll = get_pll(clkid); +	int data = 0, div = 0, offset = 0; + +	if (!clock_id_is_pll(clkid)) +		return -1; + +	if (pllout + 1 > pll_num_clkouts[clkid]) +		return -1; + +	div = clk_get_divider(8, pll_rate[clkid], rate); + +	if (div < 0) +		return -1; + +	/* out2 and out4 are in the high part of the register */ +	if (pllout == PLL_OUT2 || pllout == PLL_OUT4) +		offset = 16; + +	data = (div << PLL_OUT_RATIO_SHIFT) | +			PLL_OUT_OVRRIDE | PLL_OUT_CLKEN | PLL_OUT_RSTN; +	clrsetbits_le32(&pll->pll_out[pllout >> 1], +			PLL_OUT_RATIO_MASK << offset, data << offset); + +	return 0; +} +  /**   * Find the best available 7.1 format divisor given a parent clock rate and   * required child clock rate. This function assumes that a second-stage  |