Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f61b9fc2 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Sascha Hauer
Browse files

ARM: mxs/clock-mx28: fix up name##_set_rate



For the lcdif clock get_rate looks as follows:

	read div from HW_CLKCTRL_DIS_LCDIF.DIV
	return clk_get_rate(clk->parent) / div

with clk->parent being ref_pix_clk on my system.

ref_pix_clk's rate depends on HW_CLKCTRL_FRAC1.PIXFRAC.

The set_rate function for lcdif does:

	parent_rate = clk_get_rate(clk->parent);
	based on that calculate frac and div such that
	  parent_rate * 18 / frac / div is near the requested rate.
	HW_CLKCTRL_FRAC1.PIXFRAC is updated with frac
	HW_CLKCTRL_DIS_LCDIF.DIV is updated with div

For this calculation to be correct parent_rate needs to be
initialized not with the clock rate of lcdif's parent (i.e. ref_pix) but
that of its grandparent (i.e. ref_pix' parent == pll0_clk).

The obvious downside of this patch is that now set_rate(lcdif) changes
its parent's rate, too.  Still this is better than a wrong rate.

Acked-by: default avatarShawn Guo <shawn.guo@freescale.com>
LAKML-Reference: 20110225084950.GA13684@S2101-09.ap.freescale.net
Signed-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
parent 32a90b6e
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -295,11 +295,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
	unsigned long diff, parent_rate, calc_rate;			\
	unsigned long diff, parent_rate, calc_rate;			\
	int i;								\
	int i;								\
									\
									\
	parent_rate = clk_get_rate(clk->parent);			\
	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
	bm_busy = BM_CLKCTRL_##dr##_BUSY;				\
	bm_busy = BM_CLKCTRL_##dr##_BUSY;				\
									\
									\
	if (clk->parent == &ref_xtal_clk) {				\
	if (clk->parent == &ref_xtal_clk) {				\
		parent_rate = clk_get_rate(clk->parent);		\
		div = DIV_ROUND_UP(parent_rate, rate);			\
		div = DIV_ROUND_UP(parent_rate, rate);			\
		if (clk == &cpu_clk) {					\
		if (clk == &cpu_clk) {					\
			div_max = BM_CLKCTRL_CPU_DIV_XTAL >>		\
			div_max = BM_CLKCTRL_CPU_DIV_XTAL >>		\
@@ -309,6 +309,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
		if (div == 0 || div > div_max)				\
		if (div == 0 || div > div_max)				\
			return -EINVAL;					\
			return -EINVAL;					\
	} else {							\
	} else {							\
		/*							\
		 * hack alert: this block modifies clk->parent, too,	\
		 * so the base to use it the grand parent.		\
		 */							\
		parent_rate = clk_get_rate(clk->parent->parent);	\
		rate >>= PARENT_RATE_SHIFT;				\
		rate >>= PARENT_RATE_SHIFT;				\
		parent_rate >>= PARENT_RATE_SHIFT;			\
		parent_rate >>= PARENT_RATE_SHIFT;			\
		diff = parent_rate;					\
		diff = parent_rate;					\