diff mbox

[U-Boot,3/4,v3] i.MX28: Fix ref_cpu clock setup

Message ID 1328540371-24305-1-git-send-email-robert@delien.nl
State Changes Requested
Headers show

Commit Message

Robert Deliƫn Feb. 6, 2012, 2:59 p.m. UTC
From: Robert Delien <robert@delien.nl>

Fixing erroneous 32-bit access to hw_clkctrl_frac0 and
hw_clkctrl_frac1 registers.

---
 arch/arm/cpu/arm926ejs/mx28/clock.c           |   70 ++++++++++---------------
 arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c    |   23 ++++-----
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |   47 ++++++-----------
 3 files changed, 54 insertions(+), 86 deletions(-)

Comments

Marek Vasut Feb. 6, 2012, 3:35 p.m. UTC | #1
> From: Robert Delien <robert@delien.nl>
> 
> Fixing erroneous 32-bit access to hw_clkctrl_frac0 and
> hw_clkctrl_frac1 registers.
> 
> ---
>  arch/arm/cpu/arm926ejs/mx28/clock.c           |   70
> ++++++++++--------------- arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c    | 
>  23 ++++-----
>  arch/arm/include/asm/arch-mx28/regs-clkctrl.h |   47 ++++++-----------
>  3 files changed, 54 insertions(+), 86 deletions(-)
> 
> diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c
> b/arch/arm/cpu/arm926ejs/mx28/clock.c index 9d3a018..c0eea9e 100644
> --- a/arch/arm/cpu/arm926ejs/mx28/clock.c
> +++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
> @@ -46,8 +46,8 @@ static uint32_t mx28_get_pclk(void)
>  	struct mx28_clkctrl_regs *clkctrl_regs =
>  		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> 
> -	uint32_t clkctrl, clkseq, clkfrac;
> -	uint32_t frac, div;
> +	uint32_t clkctrl, clkseq, div;
> +	uint8_t clkfrac, frac;
> 
>  	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
> 
> @@ -67,8 +67,8 @@ static uint32_t mx28_get_pclk(void)
>  	}
> 
>  	/* REF Path */
> -	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
> -	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
> +	clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
> +	frac = clkfrac & CLKCTRL_FRAC0_FRAC_MASK;
>  	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
>  	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
>  }
> @@ -96,8 +96,8 @@ static uint32_t mx28_get_emiclk(void)
>  	struct mx28_clkctrl_regs *clkctrl_regs =
>  		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> 
> -	uint32_t frac, div;
> -	uint32_t clkctrl, clkseq, clkfrac;
> +	uint32_t clkctrl, clkseq, div;
> +	uint8_t clkfrac, frac;
> 
>  	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
>  	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
> @@ -109,11 +109,9 @@ static uint32_t mx28_get_emiclk(void)
>  		return XTAL_FREQ_MHZ / div;
>  	}
> 
> -	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
> -
>  	/* REF Path */
> -	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
> -		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
> +	clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
> +	frac = clkfrac & CLKCTRL_FRAC0_FRAC_MASK;
>  	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
>  	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
>  }
> @@ -123,8 +121,8 @@ static uint32_t mx28_get_gpmiclk(void)
>  	struct mx28_clkctrl_regs *clkctrl_regs =
>  		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> 
> -	uint32_t frac, div;
> -	uint32_t clkctrl, clkseq, clkfrac;
> +	uint32_t clkctrl, clkseq, div;
> +	uint8_t clkfrac, frac;
> 
>  	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
>  	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
> @@ -135,11 +133,9 @@ static uint32_t mx28_get_gpmiclk(void)
>  		return XTAL_FREQ_MHZ / div;
>  	}
> 
> -	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
> -
>  	/* REF Path */
> -	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
> -		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
> +	clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI]);
> +	frac = clkfrac & CLKCTRL_FRAC1_FRAC_MASK;
>  	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
>  	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
>  }
> @@ -152,11 +148,12 @@ void mx28_set_ioclk(enum mxs_ioclock io, uint32_t
> freq) struct mx28_clkctrl_regs *clkctrl_regs =
>  		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
>  	uint32_t div;
> +	int io_reg;
> 
>  	if (freq == 0)
>  		return;
> 
> -	if (io > MXC_IOCLK1)
> +	if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1))
>  		return;
> 
>  	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
> @@ -167,23 +164,13 @@ void mx28_set_ioclk(enum mxs_ioclock io, uint32_t
> freq) if (div > 35)
>  		div = 35;
> 
> -	if (io == MXC_IOCLK0) {
> -		writel(CLKCTRL_FRAC0_CLKGATEIO0,
> -			&clkctrl_regs->hw_clkctrl_frac0_set);
> -		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
> -				CLKCTRL_FRAC0_IO0FRAC_MASK,
> -				div << CLKCTRL_FRAC0_IO0FRAC_OFFSET);
> -		writel(CLKCTRL_FRAC0_CLKGATEIO0,
> -			&clkctrl_regs->hw_clkctrl_frac0_clr);
> -	} else {
> -		writel(CLKCTRL_FRAC0_CLKGATEIO1,
> -			&clkctrl_regs->hw_clkctrl_frac0_set);
> -		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
> -				CLKCTRL_FRAC0_IO1FRAC_MASK,
> -				div << CLKCTRL_FRAC0_IO1FRAC_OFFSET);
> -		writel(CLKCTRL_FRAC0_CLKGATEIO1,
> -			&clkctrl_regs->hw_clkctrl_frac0_clr);
> -	}
> +	io_reg = CLKCTRL_FRAC0_IO0 - (io - MXC_IOCLK0);
> +	writeb(CLKCTRL_FRAC0_CLKGATE,
> +		&clkctrl_regs->hw_clkctrl_frac0_set[io_reg]);
> +	writeb(CLKCTRL_FRAC0_CLKGATE | (div & CLKCTRL_FRAC0_FRAC_MASK),
> +		&clkctrl_regs->hw_clkctrl_frac0[io_reg]);
> +	writeb(CLKCTRL_FRAC0_CLKGATE,
> +		&clkctrl_regs->hw_clkctrl_frac0_clr[io_reg]);
>  }
> 
>  /*
> @@ -193,19 +180,16 @@ static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
>  {
>  	struct mx28_clkctrl_regs *clkctrl_regs =
>  		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> -	uint32_t tmp, ret;
> +	uint8_t ret;
> +	int io_reg;
> 
> -	if (io > MXC_IOCLK1)
> +	if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1))
>  		return 0;
> 
> -	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
> +	io_reg = CLKCTRL_FRAC0_IO0 - (io - MXC_IOCLK0);
> 
> -	if (io == MXC_IOCLK0)
> -		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
> -			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
> -	else
> -		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
> -			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
> +	ret = readb(&clkctrl_regs->hw_clkctrl_frac0[io_reg]) &
> +		CLKCTRL_FRAC0_FRAC_MASK;
> 
>  	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
>  }
> diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c
> b/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c index 00493b8..9663836 100644
> --- a/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c
> +++ b/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c
> @@ -86,22 +86,20 @@ void mx28_mem_init_clock(void)
>  		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> 
>  	/* Gate EMI clock */
> -	writel(CLKCTRL_FRAC0_CLKGATEEMI,
> -		&clkctrl_regs->hw_clkctrl_frac0_set);
> +	writeb(CLKCTRL_FRAC0_CLKGATE,
> +		&clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
> 
> -	/* EMI = 205MHz */
> -	writel(CLKCTRL_FRAC0_EMIFRAC_MASK,
> -		&clkctrl_regs->hw_clkctrl_frac0_set);
> -	writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) &
> -		CLKCTRL_FRAC0_EMIFRAC_MASK,
> -		&clkctrl_regs->hw_clkctrl_frac0_clr);
> +	/* Set fractional divider for ref_emi to 480 * 18 / 21 = 411MHz */
> +	writeb(CLKCTRL_FRAC0_CLKGATE | (21 & CLKCTRL_FRAC0_FRAC_MASK),
> +		&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
> 
>  	/* Ungate EMI clock */
> -	writel(CLKCTRL_FRAC0_CLKGATEEMI,
> -		&clkctrl_regs->hw_clkctrl_frac0_clr);
> +	writeb(CLKCTRL_FRAC0_CLKGATE,
> +		&clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]);
> 
>  	early_delay(11000);
> 
> +	/* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */
>  	writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
>  		(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
>  		&clkctrl_regs->hw_clkctrl_emi);
> @@ -119,9 +117,8 @@ void mx28_mem_setup_cpu_and_hbus(void)
>  		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> 
>  	/* CPU = 454MHz and ungate CPU clock */
> -	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
> -		CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU,
> -		19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET);
> +	writeb(19 & CLKCTRL_FRAC0_FRAC_MASK,
> +		(uint8_t*)&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
> 
>  	/* Set CPU bypass */
>  	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
> diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
> b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h index 8e666ee..8576ec0
> 100644
> --- a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
> +++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
> @@ -56,8 +56,8 @@ struct mx28_clkctrl_regs {
> 
>  	uint32_t	reserved[16];
> 
> -	mx28_reg_32(hw_clkctrl_frac0)		/* 0x1b0 */
> -	mx28_reg_32(hw_clkctrl_frac1)		/* 0x1c0 */
> +	mx28_reg_8(hw_clkctrl_frac0)		/* 0x1b0 */
> +	mx28_reg_8(hw_clkctrl_frac1)		/* 0x1c0 */
>  	mx28_reg_32(hw_clkctrl_clkseq)		/* 0x1d0 */
>  	mx28_reg_32(hw_clkctrl_reset)		/* 0x1e0 */
>  	mx28_reg_32(hw_clkctrl_status)		/* 0x1f0 */
> @@ -248,35 +248,22 @@ struct mx28_clkctrl_regs {
>  #define	CLKCTRL_FLEXCAN_STOP_CAN1		(1 << 28)
>  #define	CLKCTRL_FLEXCAN_CAN1_STATUS		(1 << 27)
> 
> -#define	CLKCTRL_FRAC0_CLKGATEIO0		(1 << 31)
> -#define	CLKCTRL_FRAC0_IO0_STABLE		(1 << 30)
> -#define	CLKCTRL_FRAC0_IO0FRAC_MASK		(0x3f << 24)
> -#define	CLKCTRL_FRAC0_IO0FRAC_OFFSET		24
> -#define	CLKCTRL_FRAC0_CLKGATEIO1		(1 << 23)
> -#define	CLKCTRL_FRAC0_IO1_STABLE		(1 << 22)
> -#define	CLKCTRL_FRAC0_IO1FRAC_MASK		(0x3f << 16)
> -#define	CLKCTRL_FRAC0_IO1FRAC_OFFSET		16
> -#define	CLKCTRL_FRAC0_CLKGATEEMI		(1 << 15)
> -#define	CLKCTRL_FRAC0_EMI_STABLE		(1 << 14)
> -#define	CLKCTRL_FRAC0_EMIFRAC_MASK		(0x3f << 8)
> -#define	CLKCTRL_FRAC0_EMIFRAC_OFFSET		8
> -#define	CLKCTRL_FRAC0_CLKGATECPU		(1 << 7)
> -#define	CLKCTRL_FRAC0_CPU_STABLE		(1 << 6)
> -#define	CLKCTRL_FRAC0_CPUFRAC_MASK		0x3f
> -#define	CLKCTRL_FRAC0_CPUFRAC_OFFSET		0
> -
> -#define	CLKCTRL_FRAC1_CLKGATEGPMI		(1 << 23)
> -#define	CLKCTRL_FRAC1_GPMI_STABLE		(1 << 22)
> -#define	CLKCTRL_FRAC1_GPMIFRAC_MASK		(0x3f << 16)
> -#define	CLKCTRL_FRAC1_GPMIFRAC_OFFSET		16
> -#define	CLKCTRL_FRAC1_CLKGATEHSADC		(1 << 15)
> -#define	CLKCTRL_FRAC1_HSADC_STABLE		(1 << 14)
> -#define	CLKCTRL_FRAC1_HSADCFRAC_MASK		(0x3f << 8)
> -#define	CLKCTRL_FRAC1_HSADCFRAC_OFFSET		8
> -#define	CLKCTRL_FRAC1_CLKGATEPIX		(1 << 7)
> -#define	CLKCTRL_FRAC1_PIX_STABLE		(1 << 6)
> -#define	CLKCTRL_FRAC1_PIXFRAC_MASK		0x3f
> -#define	CLKCTRL_FRAC1_PIXFRAC_OFFSET		0
> +#define	CLKCTRL_FRAC0_CLKGATE			(1 << 7)
> +#define	CLKCTRL_FRAC0_STABLE			(1 << 6)
> +#define	CLKCTRL_FRAC0_FRAC_MASK			0x3f
> +#define	CLKCTRL_FRAC0_FRAC_OFFSET		0
> +#define	CLKCTRL_FRAC0_CPU			0
> +#define	CLKCTRL_FRAC0_EMI			1
> +#define	CLKCTRL_FRAC0_IO1			2
> +#define	CLKCTRL_FRAC0_IO0			3
> +
> +#define	CLKCTRL_FRAC1_CLKGATE			(1 << 7)
> +#define	CLKCTRL_FRAC1_STABLE			(1 << 6)
> +#define	CLKCTRL_FRAC1_FRAC_MASK			0x3f
> +#define	CLKCTRL_FRAC1_FRAC_OFFSET		0

Just replace this with simple CLKCTRL_FRAC_ and drop the CLKCTRL_FRAC0_ above 
too.

> +#define	CLKCTRL_FRAC1_PIX			0
> +#define	CLKCTRL_FRAC1_HSADC			1
> +#define	CLKCTRL_FRAC1_GPMI			2
> 
>  #define	CLKCTRL_CLKSEQ_BYPASS_CPU		(1 << 18)
>  #define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)
diff mbox

Patch

diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c
index 9d3a018..c0eea9e 100644
--- a/arch/arm/cpu/arm926ejs/mx28/clock.c
+++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
@@ -46,8 +46,8 @@  static uint32_t mx28_get_pclk(void)
 	struct mx28_clkctrl_regs *clkctrl_regs =
 		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
-	uint32_t clkctrl, clkseq, clkfrac;
-	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, div;
+	uint8_t clkfrac, frac;
 
 	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
 
@@ -67,8 +67,8 @@  static uint32_t mx28_get_pclk(void)
 	}
 
 	/* REF Path */
-	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
-	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
+	clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
+	frac = clkfrac & CLKCTRL_FRAC0_FRAC_MASK;
 	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
 	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
 }
@@ -96,8 +96,8 @@  static uint32_t mx28_get_emiclk(void)
 	struct mx28_clkctrl_regs *clkctrl_regs =
 		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
-	uint32_t frac, div;
-	uint32_t clkctrl, clkseq, clkfrac;
+	uint32_t clkctrl, clkseq, div;
+	uint8_t clkfrac, frac;
 
 	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
 	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
@@ -109,11 +109,9 @@  static uint32_t mx28_get_emiclk(void)
 		return XTAL_FREQ_MHZ / div;
 	}
 
-	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
-
 	/* REF Path */
-	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
-		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
+	clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
+	frac = clkfrac & CLKCTRL_FRAC0_FRAC_MASK;
 	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
 	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
 }
@@ -123,8 +121,8 @@  static uint32_t mx28_get_gpmiclk(void)
 	struct mx28_clkctrl_regs *clkctrl_regs =
 		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
-	uint32_t frac, div;
-	uint32_t clkctrl, clkseq, clkfrac;
+	uint32_t clkctrl, clkseq, div;
+	uint8_t clkfrac, frac;
 
 	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
 	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
@@ -135,11 +133,9 @@  static uint32_t mx28_get_gpmiclk(void)
 		return XTAL_FREQ_MHZ / div;
 	}
 
-	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
-
 	/* REF Path */
-	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
-		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
+	clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI]);
+	frac = clkfrac & CLKCTRL_FRAC1_FRAC_MASK;
 	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
 	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
 }
@@ -152,11 +148,12 @@  void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
 	struct mx28_clkctrl_regs *clkctrl_regs =
 		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
 	uint32_t div;
+	int io_reg;
 
 	if (freq == 0)
 		return;
 
-	if (io > MXC_IOCLK1)
+	if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1))
 		return;
 
 	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
@@ -167,23 +164,13 @@  void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
 	if (div > 35)
 		div = 35;
 
-	if (io == MXC_IOCLK0) {
-		writel(CLKCTRL_FRAC0_CLKGATEIO0,
-			&clkctrl_regs->hw_clkctrl_frac0_set);
-		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
-				CLKCTRL_FRAC0_IO0FRAC_MASK,
-				div << CLKCTRL_FRAC0_IO0FRAC_OFFSET);
-		writel(CLKCTRL_FRAC0_CLKGATEIO0,
-			&clkctrl_regs->hw_clkctrl_frac0_clr);
-	} else {
-		writel(CLKCTRL_FRAC0_CLKGATEIO1,
-			&clkctrl_regs->hw_clkctrl_frac0_set);
-		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
-				CLKCTRL_FRAC0_IO1FRAC_MASK,
-				div << CLKCTRL_FRAC0_IO1FRAC_OFFSET);
-		writel(CLKCTRL_FRAC0_CLKGATEIO1,
-			&clkctrl_regs->hw_clkctrl_frac0_clr);
-	}
+	io_reg = CLKCTRL_FRAC0_IO0 - (io - MXC_IOCLK0);
+	writeb(CLKCTRL_FRAC0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_set[io_reg]);
+	writeb(CLKCTRL_FRAC0_CLKGATE | (div & CLKCTRL_FRAC0_FRAC_MASK),
+		&clkctrl_regs->hw_clkctrl_frac0[io_reg]);
+	writeb(CLKCTRL_FRAC0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_clr[io_reg]);
 }
 
 /*
@@ -193,19 +180,16 @@  static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
 {
 	struct mx28_clkctrl_regs *clkctrl_regs =
 		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
-	uint32_t tmp, ret;
+	uint8_t ret;
+	int io_reg;
 
-	if (io > MXC_IOCLK1)
+	if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1))
 		return 0;
 
-	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
+	io_reg = CLKCTRL_FRAC0_IO0 - (io - MXC_IOCLK0);
 
-	if (io == MXC_IOCLK0)
-		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
-			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
-	else
-		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
-			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
+	ret = readb(&clkctrl_regs->hw_clkctrl_frac0[io_reg]) &
+		CLKCTRL_FRAC0_FRAC_MASK;
 
 	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
 }
diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c b/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c
index 00493b8..9663836 100644
--- a/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c
+++ b/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c
@@ -86,22 +86,20 @@  void mx28_mem_init_clock(void)
 		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
 	/* Gate EMI clock */
-	writel(CLKCTRL_FRAC0_CLKGATEEMI,
-		&clkctrl_regs->hw_clkctrl_frac0_set);
+	writeb(CLKCTRL_FRAC0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
 
-	/* EMI = 205MHz */
-	writel(CLKCTRL_FRAC0_EMIFRAC_MASK,
-		&clkctrl_regs->hw_clkctrl_frac0_set);
-	writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) &
-		CLKCTRL_FRAC0_EMIFRAC_MASK,
-		&clkctrl_regs->hw_clkctrl_frac0_clr);
+	/* Set fractional divider for ref_emi to 480 * 18 / 21 = 411MHz */
+	writeb(CLKCTRL_FRAC0_CLKGATE | (21 & CLKCTRL_FRAC0_FRAC_MASK),
+		&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
 
 	/* Ungate EMI clock */
-	writel(CLKCTRL_FRAC0_CLKGATEEMI,
-		&clkctrl_regs->hw_clkctrl_frac0_clr);
+	writeb(CLKCTRL_FRAC0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]);
 
 	early_delay(11000);
 
+	/* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */
 	writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
 		(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
 		&clkctrl_regs->hw_clkctrl_emi);
@@ -119,9 +117,8 @@  void mx28_mem_setup_cpu_and_hbus(void)
 		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
 	/* CPU = 454MHz and ungate CPU clock */
-	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
-		CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU,
-		19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET);
+	writeb(19 & CLKCTRL_FRAC0_FRAC_MASK,
+		(uint8_t*)&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
 
 	/* Set CPU bypass */
 	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
index 8e666ee..8576ec0 100644
--- a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
+++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
@@ -56,8 +56,8 @@  struct mx28_clkctrl_regs {
 
 	uint32_t	reserved[16];
 
-	mx28_reg_32(hw_clkctrl_frac0)		/* 0x1b0 */
-	mx28_reg_32(hw_clkctrl_frac1)		/* 0x1c0 */
+	mx28_reg_8(hw_clkctrl_frac0)		/* 0x1b0 */
+	mx28_reg_8(hw_clkctrl_frac1)		/* 0x1c0 */
 	mx28_reg_32(hw_clkctrl_clkseq)		/* 0x1d0 */
 	mx28_reg_32(hw_clkctrl_reset)		/* 0x1e0 */
 	mx28_reg_32(hw_clkctrl_status)		/* 0x1f0 */
@@ -248,35 +248,22 @@  struct mx28_clkctrl_regs {
 #define	CLKCTRL_FLEXCAN_STOP_CAN1		(1 << 28)
 #define	CLKCTRL_FLEXCAN_CAN1_STATUS		(1 << 27)
 
-#define	CLKCTRL_FRAC0_CLKGATEIO0		(1 << 31)
-#define	CLKCTRL_FRAC0_IO0_STABLE		(1 << 30)
-#define	CLKCTRL_FRAC0_IO0FRAC_MASK		(0x3f << 24)
-#define	CLKCTRL_FRAC0_IO0FRAC_OFFSET		24
-#define	CLKCTRL_FRAC0_CLKGATEIO1		(1 << 23)
-#define	CLKCTRL_FRAC0_IO1_STABLE		(1 << 22)
-#define	CLKCTRL_FRAC0_IO1FRAC_MASK		(0x3f << 16)
-#define	CLKCTRL_FRAC0_IO1FRAC_OFFSET		16
-#define	CLKCTRL_FRAC0_CLKGATEEMI		(1 << 15)
-#define	CLKCTRL_FRAC0_EMI_STABLE		(1 << 14)
-#define	CLKCTRL_FRAC0_EMIFRAC_MASK		(0x3f << 8)
-#define	CLKCTRL_FRAC0_EMIFRAC_OFFSET		8
-#define	CLKCTRL_FRAC0_CLKGATECPU		(1 << 7)
-#define	CLKCTRL_FRAC0_CPU_STABLE		(1 << 6)
-#define	CLKCTRL_FRAC0_CPUFRAC_MASK		0x3f
-#define	CLKCTRL_FRAC0_CPUFRAC_OFFSET		0
-
-#define	CLKCTRL_FRAC1_CLKGATEGPMI		(1 << 23)
-#define	CLKCTRL_FRAC1_GPMI_STABLE		(1 << 22)
-#define	CLKCTRL_FRAC1_GPMIFRAC_MASK		(0x3f << 16)
-#define	CLKCTRL_FRAC1_GPMIFRAC_OFFSET		16
-#define	CLKCTRL_FRAC1_CLKGATEHSADC		(1 << 15)
-#define	CLKCTRL_FRAC1_HSADC_STABLE		(1 << 14)
-#define	CLKCTRL_FRAC1_HSADCFRAC_MASK		(0x3f << 8)
-#define	CLKCTRL_FRAC1_HSADCFRAC_OFFSET		8
-#define	CLKCTRL_FRAC1_CLKGATEPIX		(1 << 7)
-#define	CLKCTRL_FRAC1_PIX_STABLE		(1 << 6)
-#define	CLKCTRL_FRAC1_PIXFRAC_MASK		0x3f
-#define	CLKCTRL_FRAC1_PIXFRAC_OFFSET		0
+#define	CLKCTRL_FRAC0_CLKGATE			(1 << 7)
+#define	CLKCTRL_FRAC0_STABLE			(1 << 6)
+#define	CLKCTRL_FRAC0_FRAC_MASK			0x3f
+#define	CLKCTRL_FRAC0_FRAC_OFFSET		0
+#define	CLKCTRL_FRAC0_CPU			0
+#define	CLKCTRL_FRAC0_EMI			1
+#define	CLKCTRL_FRAC0_IO1			2
+#define	CLKCTRL_FRAC0_IO0			3
+
+#define	CLKCTRL_FRAC1_CLKGATE			(1 << 7)
+#define	CLKCTRL_FRAC1_STABLE			(1 << 6)
+#define	CLKCTRL_FRAC1_FRAC_MASK			0x3f
+#define	CLKCTRL_FRAC1_FRAC_OFFSET		0
+#define	CLKCTRL_FRAC1_PIX			0
+#define	CLKCTRL_FRAC1_HSADC			1
+#define	CLKCTRL_FRAC1_GPMI			2
 
 #define	CLKCTRL_CLKSEQ_BYPASS_CPU		(1 << 18)
 #define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)