tegra20: add clock_set_pllout function
Common practice on Tegra 2 boards is to use the pllp_out4 FO to generate the ULPI reference clock. For this to work we have to override the default hardware generated output divider. This function adds a clean way to do so. Signed-off-by: Lucas Stach <dev@lynxeye.de> Signed-off-by: Tom Warren <twarren@nvidia.com>
This commit is contained in:
parent
3f44e44f33
commit
65530a842e
@ -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
|
||||
|
@ -214,7 +214,7 @@ void wb_start(void)
|
||||
|
||||
reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE |
|
||||
PLLM_OUT1_RATIO_VAL_8;
|
||||
writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out);
|
||||
writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out[0]);
|
||||
|
||||
reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 |
|
||||
SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 |
|
||||
|
@ -27,8 +27,7 @@
|
||||
/* PLL registers - there are several PLLs in the clock controller */
|
||||
struct clk_pll {
|
||||
uint pll_base; /* the control register */
|
||||
uint pll_out; /* output control */
|
||||
uint reserved;
|
||||
uint pll_out[2]; /* output control */
|
||||
uint pll_misc; /* other misc things */
|
||||
};
|
||||
|
||||
@ -112,6 +111,14 @@ struct clk_rst_ctlr {
|
||||
#define PLL_DIVM_SHIFT 0
|
||||
#define PLL_DIVM_MASK (0x1f << PLL_DIVM_SHIFT)
|
||||
|
||||
/* CLK_RST_CONTROLLER_PLLx_OUTx_0 */
|
||||
#define PLL_OUT_RSTN (1 << 0)
|
||||
#define PLL_OUT_CLKEN (1 << 1)
|
||||
#define PLL_OUT_OVRRIDE (1 << 2)
|
||||
|
||||
#define PLL_OUT_RATIO_SHIFT 8
|
||||
#define PLL_OUT_RATIO_MASK (0xffU << PLL_OUT_RATIO_SHIFT)
|
||||
|
||||
/* CLK_RST_CONTROLLER_PLLx_MISC_0 */
|
||||
#define PLL_CPCON_SHIFT 8
|
||||
#define PLL_CPCON_MASK (15U << PLL_CPCON_SHIFT)
|
||||
|
@ -57,6 +57,18 @@ enum clock_osc_freq clock_get_osc_freq(void);
|
||||
unsigned long clock_start_pll(enum clock_id id, u32 divm, u32 divn,
|
||||
u32 divp, u32 cpcon, u32 lfcon);
|
||||
|
||||
/**
|
||||
* Set PLL output frequency
|
||||
*
|
||||
* @param clkid clock id
|
||||
* @param pllout pll output id
|
||||
* @param rate desired output rate
|
||||
*
|
||||
* @return 0 if ok, -1 on error (invalid clock id or no suitable divider)
|
||||
*/
|
||||
int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout,
|
||||
unsigned rate);
|
||||
|
||||
/**
|
||||
* Read low-level parameters of a PLL.
|
||||
*
|
||||
|
@ -176,6 +176,13 @@ enum periph_id {
|
||||
PERIPH_ID_NONE = -1,
|
||||
};
|
||||
|
||||
enum pll_out_id {
|
||||
PLL_OUT1,
|
||||
PLL_OUT2,
|
||||
PLL_OUT3,
|
||||
PLL_OUT4
|
||||
};
|
||||
|
||||
/* Converts a clock number to a clock register: 0=L, 1=H, 2=U */
|
||||
#define PERIPH_REG(id) ((id) >> 5)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user