diff options
Diffstat (limited to 'arch/arm/cpu')
| -rw-r--r-- | arch/arm/cpu/arm926ejs/mxs/clock.c | 93 | 
1 files changed, 93 insertions, 0 deletions
| diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c b/arch/arm/cpu/arm926ejs/mxs/clock.c index 43e766334..f94107fc1 100644 --- a/arch/arm/cpu/arm926ejs/mxs/clock.c +++ b/arch/arm/cpu/arm926ejs/mxs/clock.c @@ -325,6 +325,99 @@ void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq)  		bus, tgtclk, freq);  } +void mxs_set_lcdclk(uint32_t freq) +{ +	struct mxs_clkctrl_regs *clkctrl_regs = +		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; +	uint32_t fp, x, k_rest, k_best, x_best, tk; +	int32_t k_best_l = 999, k_best_t = 0, x_best_l = 0xff, x_best_t = 0xff; + +	if (freq == 0) +		return; + +#if defined(CONFIG_MX23) +	writel(CLKCTRL_CLKSEQ_BYPASS_PIX, &clkctrl_regs->hw_clkctrl_clkseq_clr); +#elif defined(CONFIG_MX28) +	writel(CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF, &clkctrl_regs->hw_clkctrl_clkseq_clr); +#endif + +	/* +	 *             /               18 \     1       1 +	 * freq kHz = | 480000000 Hz * --  | * --- * ------ +	 *             \                x /     k     1000 +	 * +	 *      480000000 Hz   18 +	 *      ------------ * -- +	 *        freq kHz      x +	 * k = ------------------- +	 *             1000 +	 */ + +	fp = ((PLL_FREQ_KHZ * 1000) / freq) * 18; + +	for (x = 18; x <= 35; x++) { +		tk = fp / x; +		if ((tk / 1000 == 0) || (tk / 1000 > 255)) +			continue; + +		k_rest = tk % 1000; + +		if (k_rest < (k_best_l % 1000)) { +			k_best_l = tk; +			x_best_l = x; +		} + +		if (k_rest > (k_best_t % 1000)) { +			k_best_t = tk; +			x_best_t = x; +		} +	} + +	if (1000 - (k_best_t % 1000) > (k_best_l % 1000)) { +		k_best = k_best_l; +		x_best = x_best_l; +	} else { +		k_best = k_best_t; +		x_best = x_best_t; +	} + +	k_best /= 1000; + +#if defined(CONFIG_MX23) +	writeb(CLKCTRL_FRAC_CLKGATE, +		&clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_PIX]); +	writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK), +		&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_PIX]); +	writeb(CLKCTRL_FRAC_CLKGATE, +		&clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_PIX]); + +	writel(CLKCTRL_PIX_CLKGATE, +		&clkctrl_regs->hw_clkctrl_pix_set); +	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_pix, +			CLKCTRL_PIX_DIV_MASK | CLKCTRL_PIX_CLKGATE, +			k_best << CLKCTRL_PIX_DIV_OFFSET); + +	while (readl(&clkctrl_regs->hw_clkctrl_pix) & CLKCTRL_PIX_BUSY) +		; +#elif defined(CONFIG_MX28) +	writeb(CLKCTRL_FRAC_CLKGATE, +		&clkctrl_regs->hw_clkctrl_frac1_set[CLKCTRL_FRAC1_PIX]); +	writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK), +		&clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_PIX]); +	writeb(CLKCTRL_FRAC_CLKGATE, +		&clkctrl_regs->hw_clkctrl_frac1_clr[CLKCTRL_FRAC1_PIX]); + +	writel(CLKCTRL_DIS_LCDIF_CLKGATE, +		&clkctrl_regs->hw_clkctrl_lcdif_set); +	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_lcdif, +			CLKCTRL_DIS_LCDIF_DIV_MASK | CLKCTRL_DIS_LCDIF_CLKGATE, +			k_best << CLKCTRL_DIS_LCDIF_DIV_OFFSET); + +	while (readl(&clkctrl_regs->hw_clkctrl_lcdif) & CLKCTRL_DIS_LCDIF_BUSY) +		; +#endif +} +  uint32_t mxc_get_clock(enum mxc_clock clk)  {  	switch (clk) { |