Patchwork [U-Boot,01/31] iMX28: Initial support for iMX28 CPU

login
register
mail settings
Submitter Marek Vasut
Date Sept. 8, 2011, 8:42 p.m.
Message ID <1315514579-19215-2-git-send-email-marek.vasut@gmail.com>
Download mbox | patch
Permalink /patch/113952/
State Changes Requested
Headers show

Comments

Marek Vasut - Sept. 8, 2011, 8:42 p.m.
This patch supports:
- Timers
- Debug UART
- Clock

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +++
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  359 ++++++++++++++++++++++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  131 ++++++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  143 +++++++++
 arch/arm/include/asm/arch-mx28/clock.h        |   48 +++
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   33 ++
 arch/arm/include/asm/arch-mx28/mx28.h         |   30 ++
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  308 +++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  409 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  345 +++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  167 ++++++++++
 arch/arm/include/asm/arch-mx28/regs-uartdbg.h |  182 +++++++++++
 14 files changed, 2355 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/mx28.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-uartdbg.h
Stefano Babic - Sept. 9, 2011, 8:23 a.m.
On 09/08/2011 10:42 PM, Marek Vasut wrote:
> This patch supports:
> - Timers
> - Debug UART
> - Clock

Hi Marek,

a general remark. It seems to me that your patchset comes directly from
your development, as it looks like what I normally have when I develop a
new board ;-)

However, to put into mainline and to make review easier, because this is
a porting to a new SOC, I am expecting that all patches related to a new
file are squashed together. It makes no sense to have several patches
regarding, for example, m28evk.h, because this is a new file.

Another general remark here: we tend to have the same structure and the
same files for all IMX SOC. This means that all IMX SOC have a
imx-regs.h that contain the required register definitions (really a
subset what we have in kernel). Is it really necessary to split the
definitions in several small files ?

> 
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---
>  arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +++
>  arch/arm/cpu/arm926ejs/mx28/clock.c           |  359 ++++++++++++++++++++++
>  arch/arm/cpu/arm926ejs/mx28/mx28.c            |  131 ++++++++
>  arch/arm/cpu/arm926ejs/mx28/timer.c           |  143 +++++++++
>  arch/arm/include/asm/arch-mx28/clock.h        |   48 +++
>  arch/arm/include/asm/arch-mx28/imx-regs.h     |   33 ++
>  arch/arm/include/asm/arch-mx28/mx28.h         |   30 ++
>  arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++++++
>  arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  308 +++++++++++++++++++
>  arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++++
>  arch/arm/include/asm/arch-mx28/regs-power.h   |  409 +++++++++++++++++++++++++
>  arch/arm/include/asm/arch-mx28/regs-ssp.h     |  345 +++++++++++++++++++++
>  arch/arm/include/asm/arch-mx28/regs-timrot.h  |  167 ++++++++++
>  arch/arm/include/asm/arch-mx28/regs-uartdbg.h |  182 +++++++++++
>  14 files changed, 2355 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
>  create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
>  create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
>  create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
>  create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/mx28.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-uartdbg.h

regs-uartdbg.h is used only by the driver, right ? The driver should be
in the driver directory, and also its header. See drivers/serial/

> +
> +#include <common.h>
> +#include <asm/errno.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/regs-common.h>
> +#include <asm/arch/regs-base.h>
> +#include <asm/arch/regs-clkctrl.h>
> +#include <asm/arch/regs-ssp.h>

Again, regarding file splitting for register. If you prefer to have
several files, I think it is better that imx-regs.h include them. Then
we have still a common header imx-regs.h that contains all needed
register definitions. This is a better interface for a board maintainer.

> +
> +/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
> +#define	PLL_FREQ_KHZ	480000
> +#define	PLL_FREQ_COEF	18
> +/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
> +#define	XTAL_FREQ_KHZ	24000
> +
> +#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
> +#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
> +
> +uint32_t mx28_get_pclk(void)

This function must be static.

> +
> +uint32_t mx28_get_hclk(void)

Ditto. All *_get_some_clk are exported with mxc_get_clk(index_number)


> +
> +uint32_t mx28_get_emiclk(void)

Ditto

> +static inline void enable_gpmi_clk(void)
> +{

Is there a reason to have inline ? And this is called only once. Do we
have a enable_ without a disable_ function ? Your mx28_get_gpmiclk()
enables without the caller knows the gpmi clock. Strange for a pure
"get" function.

> +
> +uint32_t mx28_get_gpmiclk(void)

Also static.

> +/*
> + * Set IO clock frequency, in kHz
> + */
> +void mx28_set_ioclk(unsigned int io, uint32_t freq)
> +{

Please use an enum for io - it cannot assume any integer value,
something with GATE0 and GATE1 to be the call easier to understand.

> +
> +/*
> + * Get IO clock, returns IO clock in kHz
> + */
> +uint32_t mx28_get_ioclk(unsigned int io)

Static function. Do you think to export this function ? In this case,
you need to add enums for mxc_get_clk().

> +
> +/*
> + * Configure SSP clock frequency, in kHz
> + */
> +void mx28_set_sspclk(unsigned int ssp, uint32_t freq, int xtal)
> +{
> +	struct mx28_clkctrl_regs *clkctrl_regs =
> +		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> +	uint32_t clk, clkreg;
> +
> +	if (ssp > 3)
> +		return;

Maybe a define in imx-regs.h setting the max number of serial ports ?

> +
> +	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + (ssp * 0x10);

You have a pointer to a mx28_reg structure. Replace fixed offset with a
sizeof.

> +uint32_t mx28_get_sspclk(unsigned int ssp)
> +{

Static as other get functions.

> +uint32_t mxc_get_clock(enum mxc_clock clk)
> +{
> +	switch (clk) {
> +	case MXC_ARM_CLK:
> +		return mx28_get_pclk() * 1000000;
> +	case MXC_GPMI_CLK:
> +		return mx28_get_gpmiclk() * 1000000;
> +	case MXC_AHB_CLK:
> +	case MXC_IPG_CLK:
> +		return mx28_get_hclk() * 1000000;

Probably you need to add some new enums if you want to export all your
get functions, such as MXC_GET_UARTCLK for your mx28_get_sspclk (or new
enums if you think there new features).

> +
> +#include <common.h>
> +#include <asm/errno.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/regs-common.h>
> +#include <asm/arch/regs-base.h>
> +#include <asm/arch/regs-clkctrl.h>
> +#include <asm/arch/regs-power.h>
> +#include <asm/arch/mx28.h>

Same comment for register definitions splitting as before.

> +/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
> +inline void lowlevel_init(void) {}

Ok.

> +
> +void reset_cpu(ulong ignored) __attribute__((noreturn));
> +
> +void reset_cpu(ulong ignored)
> +{
> +	struct mx28_clkctrl_regs *clkctrl_regs =
> +		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> +	struct mx28_power_regs *power_regs =
> +		(struct mx28_power_regs *)MXS_POWER_BASE;
> +
> +	writel(0, &power_regs->hw_power_charge);
> +	writel(0, &power_regs->hw_power_minpwr);
> +	writel(CLKCTRL_RESET_DIG, &clkctrl_regs->hw_clkctrl_reset);
> +
> +	/* Endless loop, reset will exit from here */
> +	for (;;)
> +		;

To understand: does a reset mean on the i.MX28 a power off ? Do you turn
off the power ? If this is the case, some features are not possible (as
PRAM, for example) on this SOC.

> +int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout)
> +{
> +	while (--timeout) {
> +		if ((readl(&reg->reg) & mask) == mask)
> +			break;
> +		udelay(1);
> +	}
> +
> +	return !timeout;
> +}
> +
> +int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout)
> +{
> +	while (--timeout) {
> +		if ((readl(&reg->reg) & mask) == 0)
> +			break;
> +		udelay(1);
> +	}
> +
> +	return !timeout;
> +}
> +
> +int mx28_reset_block(struct mx28_register *reg)
> +{
> +	/* Clear SFTRST */
> +	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
> +
> +	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
> +		return 1;
> +
> +	/* Clear CLKGATE */
> +	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
> +
> +	/* Set SFTRST */
> +	writel(MX28_BLOCK_SFTRST, &reg->reg_set);
> +
> +	/* Wait for CLKGATE being set */
> +	if (mx28_wait_mask_set(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
> +		return 1;
> +
> +	/* Clear SFTRST */
> +	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
> +
> +	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
> +		return 1;
> +
> +	/* Clear CLKGATE */
> +	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
> +
> +	if (mx28_wait_mask_clr(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
> +		return 1;
> +
> +	return 0;
> +}
> +
> +#if defined(CONFIG_DISPLAY_CPUINFO)
> +int print_cpuinfo(void)
> +{
> +	printf("Freescale i.MX28 family\n");
> +	printf("CPU:   %3d MHz\n", mx28_get_pclk());
> +	printf("BUS:   %3d MHz\n", mx28_get_hclk());
> +	printf("EMI:   %3d MHz\n", mx28_get_emiclk());
> +	printf("GPMI:  %3d MHz\n", mx28_get_gpmiclk());
> +	return 0;
> +}

The function has the name "cpuinfo", but you print nothing about the
cpu. Instead of that, the clock's value are printed.

After some discussion we have this common statement for the i.MX SOCs:

- the print_cpuinfo gives the revision number and the reset cause
See all other i.MX implementations
- clocks are printed with a command, whose name *must* be (because we
use for PowerPC also) simply "clocks". This avoid too much printing at
the startup. See for example do_mx35_showclocks(), or the same for mx5.

Please follow this rule.

> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/regs-common.h>
> +#include <asm/arch/regs-base.h>
> +#include <asm/arch/regs-timrot.h>
> +#include <asm/arch/mx28.h>

Remark to check the register definitions. My idea is to have a simple
easy to understand interface to get the register definitions for a SOC,
and I would replace this stuff only with imx-regs.h. What do you think ?

> +ulong get_timer(ulong base)
> +{
> +	struct mx28_timrot_regs *timrot_regs =
> +		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
> +
> +	/* Current tick value */
> +	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
> +
> +	if (lastdec >= now) {
> +		/*
> +		 * normal mode (non roll)
> +		 * move stamp forward with absolut diff ticks
> +		 */
> +		timestamp += (lastdec - now);
> +	} else {
> +		/* we have rollover of decrementer */
> +		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
> +
> +	}
> +	lastdec = now;
> +
> +	return tick_to_time(timestamp) - base;
> +}

Not sure, but it seems to me this implementation does not follow the
last changes to this kind of interface. We should implement
get_timer_masked(), but then get_timer is simply:

ulong get_timer(ulong base)
{
        return get_timer_masked() - base;
}

as I see in most SOC. However, Heiko (in CC) knows more deeply this
stuff as me, and  he can better explain us if this implementation is
correct.

I know that other i.MX are look like your implementation, but they are
quite old...

> +
> +/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
> +#define	MX28_HW_DIGCTL_MICROSECONDS	0x8001c0c0
> +
> +void __udelay(unsigned long usec)
> +{
> +	uint32_t old, new, incr;
> +	uint32_t counter = 0;
> +
> +	old = readl(MX28_HW_DIGCTL_MICROSECONDS);
> +
> +	while (counter < usec) {
> +		new = readl(MX28_HW_DIGCTL_MICROSECONDS);
> +
> +		/* Check if the timer wrapped. */
> +		if (new < old) {
> +			incr = 0xffffffff - old;
> +			incr += new;
> +		} else {
> +			incr = new - old;
> +		}

The same for __udelay. I think there is a common agreement to it, and I
am expecting that the code to manage overflow is similar.

Should we export also a get_ticks() ?

> diff --git a/arch/arm/include/asm/arch-mx28/clock.h b/arch/arm/include/asm/arch-mx28/clock.h
> new file mode 100644
> index 0000000..5e13a51
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-mx28/clock.h
> @@ -0,0 +1,48 @@
> +/*
> + * Freescale i.MX28 Clock
> + *
> + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
> + * on behalf of DENX Software Engineering GmbH
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#ifndef __CLOCK_H__
> +#define __CLOCK_H__
> +
> +enum mxc_clock {
> +	MXC_ARM_CLK = 0,
> +	MXC_AHB_CLK,
> +	MXC_IPG_CLK,
> +	MXC_GPMI_CLK,
> +};
> +
> +uint32_t mxc_get_clock(enum mxc_clock clk);
> +uint32_t mx28_get_pclk(void);
> +uint32_t mx28_get_hclk(void);
> +uint32_t mx28_get_emiclk(void);
> +uint32_t mx28_get_gpmiclk(void);

wrong. You should export only mxc_get_clock.

> +
> +void mx28_set_ioclk(unsigned int io, uint32_t freq);
> +uint32_t mx28_get_ioclk(unsigned int io);

Ditto.

> diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
> new file mode 100644
> index 0000000..a082f1d
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
> @@ -0,0 +1,33 @@
> +/*
> + * Freescale i.MX28 Registers
> + *
> + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
> + * on behalf of DENX Software Engineering GmbH
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#ifndef __IMX_REGS_H__
> +#define __IMX_REGS_H__
> +
> +#include <asm/arch/regs-common.h>
> +#include <asm/arch/regs-base.h>
> +#include <asm/arch/regs-clkctrl.h>
> +#include <asm/arch/regs-ssp.h>
> +#include <asm/arch/regs-timrot.h>
> +#include <asm/arch/regs-uartdbg.h>
> +

Ok, I see. Then I do not understand why you include explicitely each
single file in the code instead of imx-regs.h only.


> diff --git a/arch/arm/include/asm/arch-mx28/mx28.h b/arch/arm/include/asm/arch-mx28/mx28.h
> new file mode 100644
> index 0000000..a262c05
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-mx28/mx28.h
> @@ -0,0 +1,30 @@
> +/*
> + * Freescale i.MX28 MX28 specific functions
> + *
> + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
> + * on behalf of DENX Software Engineering GmbH
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#ifndef __MX28_H__
> +#define __MX28_H__
> +
> +int mx28_reset_block(struct mx28_register *reg);
> +int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
> +int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
> +
> +#endif	/* __MX28_H__ */

Should be these function available also outside the SOC directory ? If
the answer is yes, the common name (copied from omap) for the header
file to add such prototypes is sys_proto.h

> diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
> new file mode 100644
> index 0000000..66d492f
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
> @@ -0,0 +1,308 @@
> +/*
> + * Freescale i.MX28 CLKCTRL Register Definitions
> + *
> + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
> + * on behalf of DENX Software Engineering GmbH
> + *
> + * Based on code from LTIB:
> + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
> + *
> + */
> +
> +#ifndef __REGS_CLKCTRL_H__
> +#define __REGS_CLKCTRL_H__
> +
> +struct mx28_clkctrl_regs {

I think you should protect with defined(__ASSEMBLY__). Register
definitions could be included by assembly file also - even if it is not
the case now with M28EVK, it could be in future.

> +	mx28_reg(hw_clkctrl_pll0ctrl0)		/* 0x00 */

This adds an implicit order to include your file. mx28_reg is not
defined here. regs-common.h must be included before this file. This is
pretty bad.

Best regards,
Stefano Babic
Heiko Schocher - Sept. 9, 2011, 8:54 a.m.
Hello Stefano,

Stefano Babic wrote:
> On 09/08/2011 10:42 PM, Marek Vasut wrote:
>> This patch supports:
>> - Timers
>> - Debug UART
>> - Clock
> 
> Hi Marek,
> 
> a general remark. It seems to me that your patchset comes directly from
> your development, as it looks like what I normally have when I develop a
> new board ;-)

I also tend to do such things ;-)

> However, to put into mainline and to make review easier, because this is
> a porting to a new SOC, I am expecting that all patches related to a new
> file are squashed together. It makes no sense to have several patches
> regarding, for example, m28evk.h, because this is a new file.

Yep, for new files, it makes sense to make only one patch.

> Another general remark here: we tend to have the same structure and the
> same files for all IMX SOC. This means that all IMX SOC have a
> imx-regs.h that contain the required register definitions (really a
> subset what we have in kernel). Is it really necessary to split the
> definitions in several small files ?

Hmm... is this really a good thing? If I look in the statistic
below, this results in a big (lines > 1000) file ... I don;t
like such big files, but this is just a personal taste ...

> 
>> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
>> Cc: Stefano Babic <sbabic@denx.de>
>> Cc: Wolfgang Denk <wd@denx.de>
>> Cc: Detlev Zundel <dzu@denx.de>
>> ---
>>  arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +++
>>  arch/arm/cpu/arm926ejs/mx28/clock.c           |  359 ++++++++++++++++++++++
>>  arch/arm/cpu/arm926ejs/mx28/mx28.c            |  131 ++++++++
>>  arch/arm/cpu/arm926ejs/mx28/timer.c           |  143 +++++++++
>>  arch/arm/include/asm/arch-mx28/clock.h        |   48 +++
>>  arch/arm/include/asm/arch-mx28/imx-regs.h     |   33 ++
>>  arch/arm/include/asm/arch-mx28/mx28.h         |   30 ++
>>  arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++++++
>>  arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  308 +++++++++++++++++++
>>  arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++++
>>  arch/arm/include/asm/arch-mx28/regs-power.h   |  409 +++++++++++++++++++++++++
>>  arch/arm/include/asm/arch-mx28/regs-ssp.h     |  345 +++++++++++++++++++++
>>  arch/arm/include/asm/arch-mx28/regs-timrot.h  |  167 ++++++++++
>>  arch/arm/include/asm/arch-mx28/regs-uartdbg.h |  182 +++++++++++

bye,
Heiko
Marek Vasut - Sept. 9, 2011, 10:12 a.m.
On Friday, September 09, 2011 10:23:09 AM Stefano Babic wrote:
> On 09/08/2011 10:42 PM, Marek Vasut wrote:
> > This patch supports:
> > - Timers
> > - Debug UART
> > - Clock
> 
> Hi Marek,
> 
> a general remark. It seems to me that your patchset comes directly from
> your development, as it looks like what I normally have when I develop a
> new board ;-)
> 
> However, to put into mainline and to make review easier, because this is
> a porting to a new SOC, I am expecting that all patches related to a new
> file are squashed together. It makes no sense to have several patches
> regarding, for example, m28evk.h, because this is a new file.

Done, I'll retest and send V2 of the series

> 
> Another general remark here: we tend to have the same structure and the
> same files for all IMX SOC. This means that all IMX SOC have a
> imx-regs.h that contain the required register definitions (really a
> subset what we have in kernel). Is it really necessary to split the
> definitions in several small files ?

Just like Heiko said ... it'd produce terribly big and messy file. I'd prefer to 
avoid that.

> 
> > Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> > Cc: Stefano Babic <sbabic@denx.de>
> > Cc: Wolfgang Denk <wd@denx.de>
> > Cc: Detlev Zundel <dzu@denx.de>
> > ---
> > 
> >  arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +++
> >  arch/arm/cpu/arm926ejs/mx28/clock.c           |  359
> >  ++++++++++++++++++++++ arch/arm/cpu/arm926ejs/mx28/mx28.c            | 
> >  131 ++++++++
> >  arch/arm/cpu/arm926ejs/mx28/timer.c           |  143 +++++++++
> >  arch/arm/include/asm/arch-mx28/clock.h        |   48 +++
> >  arch/arm/include/asm/arch-mx28/imx-regs.h     |   33 ++
> >  arch/arm/include/asm/arch-mx28/mx28.h         |   30 ++
> >  arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++++++
> >  arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  308 +++++++++++++++++++
> >  arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++++
> >  arch/arm/include/asm/arch-mx28/regs-power.h   |  409
> >  +++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/regs-ssp.h    
> >  |  345 +++++++++++++++++++++
> >  arch/arm/include/asm/arch-mx28/regs-timrot.h  |  167 ++++++++++
> >  arch/arm/include/asm/arch-mx28/regs-uartdbg.h |  182 +++++++++++ 14
> >  files changed, 2355 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
> >  create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
> >  create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
> >  create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
> >  create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/mx28.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-uartdbg.h
> 
> regs-uartdbg.h is used only by the driver, right ? The driver should be
> in the driver directory, and also its header. See drivers/serial/

Honestly, I need to check if the file is used at all. We replaced the original 
driver with pl011 driver.

> 
> > +
> > +#include <common.h>
> > +#include <asm/errno.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/clock.h>
> > +#include <asm/arch/regs-common.h>
> > +#include <asm/arch/regs-base.h>
> > +#include <asm/arch/regs-clkctrl.h>
> > +#include <asm/arch/regs-ssp.h>
> 
> Again, regarding file splitting for register. If you prefer to have
> several files, I think it is better that imx-regs.h include them. Then
> we have still a common header imx-regs.h that contains all needed
> register definitions. This is a better interface for a board maintainer.

Won't it make the compiler slower at compile time if it has to go through all of 
the included files instead of a subset ?

> 
> > +
> > +/* The PLL frequency is always 480MHz, see section 10.2 in iMX28
> > datasheet. */ +#define	PLL_FREQ_KHZ	480000
> > +#define	PLL_FREQ_COEF	18
> > +/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28
> > datasheet. */ +#define	XTAL_FREQ_KHZ	24000
> > +
> > +#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
> > +#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
> > +
> > +uint32_t mx28_get_pclk(void)
> 
> This function must be static.
> 

[...]
Fixed all the stuff

> > +/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
> > +inline void lowlevel_init(void) {}
> 
> Ok.
> 
> > +
> > +void reset_cpu(ulong ignored) __attribute__((noreturn));
> > +
> > +void reset_cpu(ulong ignored)
> > +{
> > +	struct mx28_clkctrl_regs *clkctrl_regs =
> > +		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
> > +	struct mx28_power_regs *power_regs =
> > +		(struct mx28_power_regs *)MXS_POWER_BASE;
> > +
> > +	writel(0, &power_regs->hw_power_charge);
> > +	writel(0, &power_regs->hw_power_minpwr);
> > +	writel(CLKCTRL_RESET_DIG, &clkctrl_regs->hw_clkctrl_reset);
> > +
> > +	/* Endless loop, reset will exit from here */
> > +	for (;;)
> > +		;
> 
> To understand: does a reset mean on the i.MX28 a power off ? Do you turn
> off the power ? If this is the case, some features are not possible (as
> PRAM, for example) on this SOC.

This should just reset the chip. No poweroff.

[...]

> 
> > +ulong get_timer(ulong base)
> > +{
> > +	struct mx28_timrot_regs *timrot_regs =
> > +		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
> > +
> > +	/* Current tick value */
> > +	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
> > +
> > +	if (lastdec >= now) {
> > +		/*
> > +		 * normal mode (non roll)
> > +		 * move stamp forward with absolut diff ticks
> > +		 */
> > +		timestamp += (lastdec - now);
> > +	} else {
> > +		/* we have rollover of decrementer */
> > +		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
> > +
> > +	}
> > +	lastdec = now;
> > +
> > +	return tick_to_time(timestamp) - base;
> > +}
> 
> Not sure, but it seems to me this implementation does not follow the
> last changes to this kind of interface. We should implement
> get_timer_masked(), but then get_timer is simply:
> 
> ulong get_timer(ulong base)
> {
>         return get_timer_masked() - base;
> }
> 
> as I see in most SOC. However, Heiko (in CC) knows more deeply this
> stuff as me, and  he can better explain us if this implementation is
> correct.
> 
> I know that other i.MX are look like your implementation, but they are
> quite old...

I'll probably wait for someone to clearly say how this should be to avoid 
reworking it for the fourth time.

[...]

> Best regards,
> Stefano Babic

Cheers
Stefano Babic - Sept. 9, 2011, 10:29 a.m.
On 09/09/2011 12:12 PM, Marek Vasut wrote:

>>
>> Another general remark here: we tend to have the same structure and the
>> same files for all IMX SOC. This means that all IMX SOC have a
>> imx-regs.h that contain the required register definitions (really a
>> subset what we have in kernel). Is it really necessary to split the
>> definitions in several small files ?
> 
> Just like Heiko said ... it'd produce terribly big and messy file. I'd prefer to 
> avoid that.

This is ok, and it is ok also that your imx-regs.h file contains only
the reg-specific include files. What is not ok, is that you do not use
imx-regs.h and you still includes each separate file. And as I see, they
must be included in a specific order.

This order must be defined only in imx-regs.h, as you have already done
and then each driver/board requires to include only imx-regs.h, without
having to care of the single files.

> Honestly, I need to check if the file is used at all. We replaced the original 
> driver with pl011 driver.

Ok

>> Again, regarding file splitting for register. If you prefer to have
>> several files, I think it is better that imx-regs.h include them. Then
>> we have still a common header imx-regs.h that contains all needed
>> register definitions. This is a better interface for a board maintainer.
> 
> Won't it make the compiler slower at compile time if it has to go through all of 
> the included files instead of a subset ?

Well, I do not know if on our Intel-PC this makes a so noticeable
difference ;-)

What I remark here, it is to have a clear and identical interface among
the several SOCs. This is not only easier for board developers, but also
removes some nasty #ifdef CONFIG_MX from the drivers.

>>
>> To understand: does a reset mean on the i.MX28 a power off ? Do you turn
>> off the power ? If this is the case, some features are not possible (as
>> PRAM, for example) on this SOC.
> 
> This should just reset the chip. No poweroff.

Ok - thanks for clarification.

> 
> I'll probably wait for someone to clearly say how this should be to avoid 
> reworking it for the fourth time.

Right.

Best regards,
Stefano Babic
Marek Vasut - Sept. 9, 2011, 10:50 a.m.
On Friday, September 09, 2011 12:29:01 PM Stefano Babic wrote:
> On 09/09/2011 12:12 PM, Marek Vasut wrote:
> >> Another general remark here: we tend to have the same structure and the
> >> same files for all IMX SOC. This means that all IMX SOC have a
> >> imx-regs.h that contain the required register definitions (really a
> >> subset what we have in kernel). Is it really necessary to split the
> >> definitions in several small files ?
> > 
> > Just like Heiko said ... it'd produce terribly big and messy file. I'd
> > prefer to avoid that.
> 
> This is ok, and it is ok also that your imx-regs.h file contains only
> the reg-specific include files. What is not ok, is that you do not use
> imx-regs.h and you still includes each separate file. And as I see, they
> must be included in a specific order.

I patched the reg definition files. This should be solved.
> 
> This order must be defined only in imx-regs.h, as you have already done
> and then each driver/board requires to include only imx-regs.h, without
> having to care of the single files.

Ok
> 
> > Honestly, I need to check if the file is used at all. We replaced the
> > original driver with pl011 driver.
> 
> Ok
> 
> >> Again, regarding file splitting for register. If you prefer to have
> >> several files, I think it is better that imx-regs.h include them. Then
> >> we have still a common header imx-regs.h that contains all needed
> >> register definitions. This is a better interface for a board maintainer.
> > 
> > Won't it make the compiler slower at compile time if it has to go through
> > all of the included files instead of a subset ?
> 
> Well, I do not know if on our Intel-PC this makes a so noticeable
> difference ;-)

It's a point-of-view question, really. But what about people compiling stuff on 
slower machines ?

> 
> What I remark here, it is to have a clear and identical interface among
> the several SOCs. This is not only easier for board developers, but also
> removes some nasty #ifdef CONFIG_MX from the drivers.

Yes, I understand. btw there's no CONFIG_MX stuff.

> 
> >> To understand: does a reset mean on the i.MX28 a power off ? Do you turn
> >> off the power ? If this is the case, some features are not possible (as
> >> PRAM, for example) on this SOC.
> > 
> > This should just reset the chip. No poweroff.
> 
> Ok - thanks for clarification.
> 
> > I'll probably wait for someone to clearly say how this should be to avoid
> > reworking it for the fourth time.
> 
> Right.
> 
> Best regards,
> Stefano Babic

Cheers
Stefano Babic - Sept. 9, 2011, 11:04 a.m.
On 09/09/2011 12:50 PM, Marek Vasut wrote:
>>
>> Well, I do not know if on our Intel-PC this makes a so noticeable
>> difference ;-)
> 
> It's a point-of-view question, really. But what about people compiling stuff on 
> slower machines ?

Yes, it is a point of view, and surely, compilation time is a drawback.

However, if I compare the advantages between clear interface and
compilation time, I choose the first one.

>> What I remark here, it is to have a clear and identical interface among
>> the several SOCs. This is not only easier for board developers, but also
>> removes some nasty #ifdef CONFIG_MX from the drivers.
> 
> Yes, I understand. btw there's no CONFIG_MX stuff.

Not yet, but only because you are adding a new SOC without using IMX
drivers. Things will be changed when the MX23 will be added. Or some
newer SOC of the mxs family will be added by Freescale.

Once we had only the MX31. Drivers were done only for this SOC. After
using the same driver with different SOCs, a lot of CONFIG_MX was added,
and most of code was really not readable - and it tooks time to remove
most of them.

Best regards,
Stefano Babic

Patch

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
new file mode 100644
index 0000000..98504f9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -0,0 +1,46 @@ 
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS	= clock.o mx28.o timer.o
+
+SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c
new file mode 100644
index 0000000..c81c305
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
@@ -0,0 +1,359 @@ 
+/*
+ * Freescale i.MX28 clock setup code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/regs-common.h>
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-ssp.h>
+
+/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+#define	PLL_FREQ_KHZ	480000
+#define	PLL_FREQ_COEF	18
+/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
+#define	XTAL_FREQ_KHZ	24000
+
+#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
+#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
+
+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;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl &
+		(CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
+		return 0;
+	}
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) {
+		div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >>
+			CLKCTRL_CPU_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
+	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+uint32_t mx28_get_hclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t div;
+	uint32_t clkctrl;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN)
+		return 0;
+
+	div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
+	return mx28_get_pclk() / div;
+}
+
+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;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) {
+		div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >>
+			CLKCTRL_EMI_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
+		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static inline void enable_gpmi_clk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Clear bypass bit */
+	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* Set GPMI clock to ref_gpmi / 12 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+}
+
+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;
+
+	/* Enable GPMI clock */
+	enable_gpmi_clk();
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) {
+		div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
+		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+/*
+ * Set IO clock frequency, in kHz
+ */
+void mx28_set_ioclk(unsigned int io, uint32_t freq)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t div;
+
+	if (freq == 0)
+		return;
+
+	if (io > 1)
+		return;
+
+	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
+
+	if (div < 18)
+		div = 18;
+
+	if (div > 35)
+		div = 35;
+
+	if (io == 0) {
+		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);
+	}
+}
+
+/*
+ * Get IO clock, returns IO clock in kHz
+ */
+uint32_t mx28_get_ioclk(unsigned int io)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t tmp, ret;
+
+	if (io > 1)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	if (io == 0)
+		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
+	else
+		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
+
+	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
+}
+
+/*
+ * Configure SSP clock frequency, in kHz
+ */
+void mx28_set_sspclk(unsigned int ssp, uint32_t freq, int xtal)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clk, clkreg;
+
+	if (ssp > 3)
+		return;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + (ssp * 0x10);
+
+	clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
+	while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
+		;
+
+	if (xtal)
+		clk = XTAL_FREQ_KHZ;
+	else
+		clk = mx28_get_ioclk(ssp >> 1);
+
+	if (freq > clk)
+		return;
+
+	/* Calculate the divider and cap it if necessary */
+	clk /= freq;
+	if (clk > CLKCTRL_SSP_DIV_MASK)
+		clk = CLKCTRL_SSP_DIV_MASK;
+
+	clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk);
+	while (readl(clkreg) & CLKCTRL_SSP_BUSY)
+		;
+
+	if (xtal)
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_set);
+	else
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+/*
+ * Return SSP frequency, in kHz
+ */
+uint32_t mx28_get_sspclk(unsigned int ssp)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clkreg;
+	uint32_t clk, tmp;
+
+	if (ssp > 3)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
+		return XTAL_FREQ_KHZ;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + (ssp * 0x10);
+
+	tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
+
+	if (tmp == 0)
+		return 0;
+
+	clk = mx28_get_ioclk(ssp >> 1);
+
+	return clk / tmp;
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz)
+ */
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+{
+	struct mx28_ssp_regs *ssp_regs;
+	const uint32_t sspclk = mx28_get_sspclk(bus);
+	uint32_t reg;
+	uint32_t divide, rate, tgtclk;
+
+	ssp_regs = (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	reg = SSP_TIMING_TIMEOUT_MASK |
+		(divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) |
+		((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET);
+	writel(reg, &ssp_regs->hw_ssp_timing);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+uint32_t mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mx28_get_pclk() * 1000000;
+	case MXC_GPMI_CLK:
+		return mx28_get_gpmiclk() * 1000000;
+	case MXC_AHB_CLK:
+	case MXC_IPG_CLK:
+		return mx28_get_hclk() * 1000000;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
new file mode 100644
index 0000000..e3df76b
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -0,0 +1,131 @@ 
+/*
+ * Freescale i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/regs-common.h>
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/mx28.h>
+
+/* 1 second delay should be plenty of time for block reset. */
+#define	RESET_MAX_TIMEOUT	1000000
+
+#define	MX28_BLOCK_SFTRST	(1 << 31)
+#define	MX28_BLOCK_CLKGATE	(1 << 30)
+
+/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel(0, &power_regs->hw_power_charge);
+	writel(0, &power_regs->hw_power_minpwr);
+	writel(CLKCTRL_RESET_DIG, &clkctrl_regs->hw_clkctrl_reset);
+
+	/* Endless loop, reset will exit from here */
+	for (;;)
+		;
+}
+
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == mask)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == 0)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_reset_block(struct mx28_register *reg)
+{
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	/* Set SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_set);
+
+	/* Wait for CLKGATE being set */
+	if (mx28_wait_mask_set(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	return 0;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	printf("Freescale i.MX28 family\n");
+	printf("CPU:   %3d MHz\n", mx28_get_pclk());
+	printf("BUS:   %3d MHz\n", mx28_get_hclk());
+	printf("EMI:   %3d MHz\n", mx28_get_emiclk());
+	printf("GPMI:  %3d MHz\n", mx28_get_gpmiclk());
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/mx28/timer.c b/arch/arm/cpu/arm926ejs/mx28/timer.c
new file mode 100644
index 0000000..548cfe3
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/timer.c
@@ -0,0 +1,143 @@ 
+/*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/regs-common.h>
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-timrot.h>
+#include <asm/arch/mx28.h>
+
+/* Maximum fixed count */
+#define TIMER_LOAD_VAL	0xffffffff
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->tbl)
+#define lastdec (gd->lastinc)
+
+/*
+ * This driver uses 1kHz clock source.
+ */
+#define	MX28_INCREMENTER_HZ		1000
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	return tick / (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	return time * (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+/* Calculate how many ticks happen in "us" microseconds */
+static inline unsigned long us_to_tick(unsigned long us)
+{
+	return (us * MX28_INCREMENTER_HZ) / 1000000;
+}
+
+int timer_init(void)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Reset Timers and Rotary Encoder module */
+	mx28_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+	/* Set fixed_count to 0 */
+	writel(0, &timrot_regs->hw_timrot_fixed_count0);
+
+	/* Set UPDATE bit and 1Khz frequency */
+	writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+		TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+		&timrot_regs->hw_timrot_timctrl0);
+
+	/* Set fixed_count to maximal value */
+	writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Current tick value */
+	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (lastdec - now);
+	} else {
+		/* we have rollover of decrementer */
+		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
+
+	}
+	lastdec = now;
+
+	return tick_to_time(timestamp) - base;
+}
+
+/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
+#define	MX28_HW_DIGCTL_MICROSECONDS	0x8001c0c0
+
+void __udelay(unsigned long usec)
+{
+	uint32_t old, new, incr;
+	uint32_t counter = 0;
+
+	old = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+	while (counter < usec) {
+		new = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+		/* Check if the timer wrapped. */
+		if (new < old) {
+			incr = 0xffffffff - old;
+			incr += new;
+		} else {
+			incr = new - old;
+		}
+
+		/*
+		 * Check if we are close to the maximum time and the counter
+		 * would wrap if incremented. If that's the case, break out
+		 * from the loop as the requested delay time passed.
+		 */
+		if (counter + incr < counter)
+			break;
+
+		counter += incr;
+		old = new;
+	}
+}
diff --git a/arch/arm/include/asm/arch-mx28/clock.h b/arch/arm/include/asm/arch-mx28/clock.h
new file mode 100644
index 0000000..5e13a51
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/clock.h
@@ -0,0 +1,48 @@ 
+/*
+ * Freescale i.MX28 Clock
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+enum mxc_clock {
+	MXC_ARM_CLK = 0,
+	MXC_AHB_CLK,
+	MXC_IPG_CLK,
+	MXC_GPMI_CLK,
+};
+
+uint32_t mxc_get_clock(enum mxc_clock clk);
+uint32_t mx28_get_pclk(void);
+uint32_t mx28_get_hclk(void);
+uint32_t mx28_get_emiclk(void);
+uint32_t mx28_get_gpmiclk(void);
+
+void mx28_set_ioclk(unsigned int io, uint32_t freq);
+uint32_t mx28_get_ioclk(unsigned int io);
+void mx28_set_sspclk(unsigned int ssp, uint32_t freq, int xtal);
+uint32_t mx28_get_sspclk(unsigned int ssp);
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq);
+
+/* Compatibility with the FEC Ethernet driver */
+#define	imx_get_fecclk()	(mx28_get_hclk() * 1000000)
+
+#endif	/* __CLOCK_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
new file mode 100644
index 0000000..a082f1d
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -0,0 +1,33 @@ 
+/*
+ * Freescale i.MX28 Registers
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __IMX_REGS_H__
+#define __IMX_REGS_H__
+
+#include <asm/arch/regs-common.h>
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-ssp.h>
+#include <asm/arch/regs-timrot.h>
+#include <asm/arch/regs-uartdbg.h>
+
+#endif	/* __IMX_REGS_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/mx28.h b/arch/arm/include/asm/arch-mx28/mx28.h
new file mode 100644
index 0000000..a262c05
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/mx28.h
@@ -0,0 +1,30 @@ 
+/*
+ * Freescale i.MX28 MX28 specific functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_H__
+#define __MX28_H__
+
+int mx28_reset_block(struct mx28_register *reg);
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
+
+#endif	/* __MX28_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-base.h b/arch/arm/include/asm/arch-mx28/regs-base.h
new file mode 100644
index 0000000..71e6b98
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-base.h
@@ -0,0 +1,88 @@ 
+/*
+ * Freescale i.MX28 Peripheral Base Addresses
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2008 Embedded Alley Solutions Inc.
+ *
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __REGS_BASE_H__
+#define __REGS_BASE_H__
+
+/*
+ * Register base address
+ */
+#define	MXS_ICOL_BASE		0x80000000
+#define	MXS_HSADC_BASE		0x80002000
+#define	MXS_APBH_BASE		0x80004000
+#define	MXS_PERFMON_BASE	0x80006000
+#define	MXS_BCH_BASE		0x8000A000
+#define	MXS_GPMI_BASE		0x8000C000
+#define	MXS_SSP0_BASE		0x80010000
+#define	MXS_SSP1_BASE		0x80012000
+#define	MXS_SSP2_BASE		0x80014000
+#define	MXS_SSP3_BASE		0x80016000
+#define	MXS_PINCTRL_BASE	0x80018000
+#define	MXS_DIGCTL_BASE		0x8001C000
+#define	MXS_ETM_BASE		0x80022000
+#define	MXS_APBX_BASE		0x80024000
+#define	MXS_DCP_BASE		0x80028000
+#define	MXS_PXP_BASE		0x8002A000
+#define	MXS_OCOTP_BASE		0x8002C000
+#define	MXS_AXI_AHB0_BASE	0x8002E000
+#define	MXS_LCDIF_BASE		0x80030000
+#define	MXS_CAN0_BASE		0x80032000
+#define	MXS_CAN1_BASE		0x80034000
+#define	MXS_SIMDBG_BASE		0x8003C000
+#define	MXS_SIMGPMISEL_BASE	0x8003C200
+#define	MXS_SIMSSPSEL_BASE	0x8003C300
+#define	MXS_SIMMEMSEL_BASE	0x8003C400
+#define	MXS_GPIOMON_BASE	0x8003C500
+#define	MXS_SIMENET_BASE	0x8003C700
+#define	MXS_ARMJTAG_BASE	0x8003C800
+#define	MXS_CLKCTRL_BASE	0x80040000
+#define	MXS_SAIF0_BASE		0x80042000
+#define	MXS_POWER_BASE		0x80044000
+#define	MXS_SAIF1_BASE		0x80046000
+#define	MXS_LRADC_BASE		0x80050000
+#define	MXS_SPDIF_BASE		0x80054000
+#define	MXS_RTC_BASE		0x80056000
+#define	MXS_I2C0_BASE		0x80058000
+#define	MXS_I2C1_BASE		0x8005A000
+#define	MXS_PWM_BASE		0x80064000
+#define	MXS_TIMROT_BASE		0x80068000
+#define	MXS_UARTAPP0_BASE	0x8006A000
+#define	MXS_UARTAPP1_BASE	0x8006C000
+#define	MXS_UARTAPP2_BASE	0x8006E000
+#define	MXS_UARTAPP3_BASE	0x80070000
+#define	MXS_UARTAPP4_BASE	0x80072000
+#define	MXS_UARTDBG_BASE	0x80074000
+#define	MXS_USBPHY0_BASE	0x8007C000
+#define	MXS_USBPHY1_BASE	0x8007E000
+#define	MXS_USBCTRL0_BASE	0x80080000
+#define	MXS_USBCTRL1_BASE	0x80090000
+#define	MXS_DFLPT_BASE		0x800C0000
+#define	MXS_DRAM_BASE		0x800E0000
+#define	MXS_ENET0_BASE		0x800F0000
+#define	MXS_ENET1_BASE		0x800F4000
+
+#endif /* __REGS_BASE_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
new file mode 100644
index 0000000..66d492f
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
@@ -0,0 +1,308 @@ 
+/*
+ * Freescale i.MX28 CLKCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __REGS_CLKCTRL_H__
+#define __REGS_CLKCTRL_H__
+
+struct mx28_clkctrl_regs {
+	mx28_reg(hw_clkctrl_pll0ctrl0)		/* 0x00 */
+	mx28_reg(hw_clkctrl_pll0ctrl1)		/* 0x10 */
+	mx28_reg(hw_clkctrl_pll1ctrl0)		/* 0x20 */
+	mx28_reg(hw_clkctrl_pll1ctrl1)		/* 0x30 */
+	mx28_reg(hw_clkctrl_pll2ctrl0)		/* 0x40 */
+	mx28_reg(hw_clkctrl_cpu)		/* 0x50 */
+	mx28_reg(hw_clkctrl_hbus)		/* 0x60 */
+	mx28_reg(hw_clkctrl_xbus)		/* 0x70 */
+	mx28_reg(hw_clkctrl_xtal)		/* 0x80 */
+	mx28_reg(hw_clkctrl_ssp0)		/* 0x90 */
+	mx28_reg(hw_clkctrl_ssp1)		/* 0xa0 */
+	mx28_reg(hw_clkctrl_ssp2)		/* 0xb0 */
+	mx28_reg(hw_clkctrl_ssp3)		/* 0xc0 */
+	mx28_reg(hw_clkctrl_gpmi)		/* 0xd0 */
+	mx28_reg(hw_clkctrl_spdif)		/* 0xe0 */
+	mx28_reg(hw_clkctrl_emi)		/* 0xf0 */
+	mx28_reg(hw_clkctrl_saif0)		/* 0x100 */
+	mx28_reg(hw_clkctrl_saif1)		/* 0x110 */
+	mx28_reg(hw_clkctrl_lcdif)		/* 0x120 */
+	mx28_reg(hw_clkctrl_etm)		/* 0x130 */
+	mx28_reg(hw_clkctrl_enet)		/* 0x140 */
+	mx28_reg(hw_clkctrl_hsadc)		/* 0x150 */
+	mx28_reg(hw_clkctrl_flexcan)		/* 0x160 */
+
+	uint32_t	reserved[16];
+
+	mx28_reg(hw_clkctrl_frac0)		/* 0x1b0 */
+	mx28_reg(hw_clkctrl_frac1)		/* 0x1c0 */
+	mx28_reg(hw_clkctrl_clkseq)		/* 0x1d0 */
+	mx28_reg(hw_clkctrl_reset)		/* 0x1e0 */
+	mx28_reg(hw_clkctrl_status)		/* 0x1f0 */
+	mx28_reg(hw_clkctrl_version)		/* 0x200 */
+};
+
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL0CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL0CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL0CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL1CTRL0_CLKGATEEMI		(1 << 31)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL1CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL1CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL1CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL2CTRL0_CLKGATE		(1 << 31)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	(1 << 26)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL2CTRL0_POWER			(1 << 23)
+
+#define	CLKCTRL_CPU_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_CPU_BUSY_REF_CPU		(1 << 28)
+#define	CLKCTRL_CPU_DIV_XTAL_FRAC_EN		(1 << 26)
+#define	CLKCTRL_CPU_DIV_XTAL_MASK		(0x3ff << 16)
+#define	CLKCTRL_CPU_DIV_XTAL_OFFSET		16
+#define	CLKCTRL_CPU_INTERRUPT_WAIT		(1 << 12)
+#define	CLKCTRL_CPU_DIV_CPU_FRAC_EN		(1 << 10)
+#define	CLKCTRL_CPU_DIV_CPU_MASK		0x3f
+#define	CLKCTRL_CPU_DIV_CPU_OFFSET		0
+
+#define	CLKCTRL_HBUS_ASM_BUSY			(1 << 31)
+#define	CLKCTRL_HBUS_DCP_AS_ENABLE		(1 << 30)
+#define	CLKCTRL_HBUS_PXP_AS_ENABLE		(1 << 29)
+#define	CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	(1 << 27)
+#define	CLKCTRL_HBUS_APBHDMA_AS_ENABLE		(1 << 26)
+#define	CLKCTRL_HBUS_APBXDMA_AS_ENABLE		(1 << 25)
+#define	CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	(1 << 24)
+#define	CLKCTRL_HBUS_TRAFFIC_AS_ENABLE		(1 << 23)
+#define	CLKCTRL_HBUS_CPU_DATA_AS_ENABLE		(1 << 22)
+#define	CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	(1 << 21)
+#define	CLKCTRL_HBUS_ASM_ENABLE			(1 << 20)
+#define	CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 19)
+#define	CLKCTRL_HBUS_SLOW_DIV_MASK		(0x7 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_OFFSET		16
+#define	CLKCTRL_HBUS_SLOW_DIV_BY1		(0x0 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY2		(0x1 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY4		(0x2 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY8		(0x3 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY16		(0x4 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY32		(0x5 << 16)
+#define	CLKCTRL_HBUS_DIV_FRAC_EN		(1 << 5)
+#define	CLKCTRL_HBUS_DIV_MASK			0x1f
+#define	CLKCTRL_HBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XBUS_BUSY			(1 << 31)
+#define	CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 11)
+#define	CLKCTRL_XBUS_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_XBUS_DIV_MASK			0x3ff
+#define	CLKCTRL_XBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XTAL_UART_CLK_GATE		(1 << 31)
+#define	CLKCTRL_XTAL_PWM_CLK24M_GATE		(1 << 29)
+#define	CLKCTRL_XTAL_TIMROT_CLK32K_GATE		(1 << 26)
+#define	CLKCTRL_XTAL_DIV_UART_MASK		0x3
+#define	CLKCTRL_XTAL_DIV_UART_OFFSET		0
+
+#define	CLKCTRL_SSP_CLKGATE			(1 << 31)
+#define	CLKCTRL_SSP_BUSY			(1 << 29)
+#define	CLKCTRL_SSP_DIV_FRAC_EN			(1 << 9)
+#define	CLKCTRL_SSP_DIV_MASK			0x1ff
+#define	CLKCTRL_SSP_DIV_OFFSET			0
+
+#define	CLKCTRL_GPMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_GPMI_BUSY			(1 << 29)
+#define	CLKCTRL_GPMI_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_GPMI_DIV_MASK			0x3ff
+#define	CLKCTRL_GPMI_DIV_OFFSET			0
+
+#define	CLKCTRL_SPDIF_CLKGATE			(1 << 31)
+
+#define	CLKCTRL_EMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_EMI_SYNC_MODE_EN		(1 << 30)
+#define	CLKCTRL_EMI_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_EMI_BUSY_REF_EMI		(1 << 28)
+#define	CLKCTRL_EMI_BUSY_REF_CPU		(1 << 27)
+#define	CLKCTRL_EMI_BUSY_SYNC_MODE		(1 << 26)
+#define	CLKCTRL_EMI_BUSY_DCC_RESYNC		(1 << 17)
+#define	CLKCTRL_EMI_DCC_RESYNC_ENABLE		(1 << 16)
+#define	CLKCTRL_EMI_DIV_XTAL_MASK		(0xf << 8)
+#define	CLKCTRL_EMI_DIV_XTAL_OFFSET		8
+#define	CLKCTRL_EMI_DIV_EMI_MASK		0x3f
+#define	CLKCTRL_EMI_DIV_EMI_OFFSET		0
+
+#define	CLKCTRL_SAIF0_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF0_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF0_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF0_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF0_DIV_OFFSET		0
+
+#define	CLKCTRL_SAIF1_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF1_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF1_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF1_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF1_DIV_OFFSET		0
+
+#define	CLKCTRL_DIS_LCDIF_CLKGATE		(1 << 31)
+#define	CLKCTRL_DIS_LCDIF_BUSY			(1 << 29)
+#define	CLKCTRL_DIS_LCDIF_DIV_FRAC_EN		(1 << 13)
+#define	CLKCTRL_DIS_LCDIF_DIV_MASK		0x1fff
+#define	CLKCTRL_DIS_LCDIF_DIV_OFFSET		0
+
+#define	CLKCTRL_ETM_CLKGATE			(1 << 31)
+#define	CLKCTRL_ETM_BUSY			(1 << 29)
+#define	CLKCTRL_ETM_DIV_FRAC_EN			(1 << 7)
+#define	CLKCTRL_ETM_DIV_MASK			0x7f
+#define	CLKCTRL_ETM_DIV_OFFSET			0
+
+#define	CLKCTRL_ENET_SLEEP			(1 << 31)
+#define	CLKCTRL_ENET_DISABLE			(1 << 30)
+#define	CLKCTRL_ENET_STATUS			(1 << 29)
+#define	CLKCTRL_ENET_BUSY_TIME			(1 << 27)
+#define	CLKCTRL_ENET_DIV_TIME_MASK		(0x3f << 21)
+#define	CLKCTRL_ENET_DIV_TIME_OFFSET		21
+#define	CLKCTRL_ENET_TIME_SEL_MASK		(0x3 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_OFFSET		19
+#define	CLKCTRL_ENET_TIME_SEL_XTAL		(0x0 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_PLL		(0x1 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_RMII_CLK		(0x2 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_UNDEFINED		(0x3 << 19)
+#define	CLKCTRL_ENET_CLK_OUT_EN			(1 << 18)
+#define	CLKCTRL_ENET_RESET_BY_SW_CHIP		(1 << 17)
+#define	CLKCTRL_ENET_RESET_BY_SW		(1 << 16)
+
+#define	CLKCTRL_HSADC_RESETB			(1 << 30)
+#define	CLKCTRL_HSADC_FREQDIV_MASK		(0x3 << 28)
+#define	CLKCTRL_HSADC_FREQDIV_OFFSET		28
+
+#define	CLKCTRL_FLEXCAN_STOP_CAN0		(1 << 30)
+#define	CLKCTRL_FLEXCAN_CAN0_STATUS		(1 << 29)
+#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_CLKSEQ_BYPASS_CPU		(1 << 18)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_BYPASS	(0x1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_PFD	(0x0 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_ETM		(1 << 8)
+#define	CLKCTRL_CLKSEQ_BYPASS_EMI		(1 << 7)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP3		(1 << 6)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP2		(1 << 5)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP1		(1 << 4)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP0		(1 << 3)
+#define	CLKCTRL_CLKSEQ_BYPASS_GPMI		(1 << 2)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF1		(1 << 1)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF0		(1 << 0)
+
+#define	CLKCTRL_RESET_WDOG_POR_DISABLE		(1 << 5)
+#define	CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	(1 << 4)
+#define	CLKCTRL_RESET_THERMAL_RESET_ENABLE	(1 << 3)
+#define	CLKCTRL_RESET_THERMAL_RESET_DEFAULT	(1 << 2)
+#define	CLKCTRL_RESET_CHIP			(1 << 1)
+#define	CLKCTRL_RESET_DIG			(1 << 0)
+
+#define	CLKCTRL_STATUS_CPU_LIMIT_MASK		(0x3 << 30)
+#define	CLKCTRL_STATUS_CPU_LIMIT_OFFSET		30
+
+#define	CLKCTRL_VERSION_MAJOR_MASK		(0xff << 24)
+#define	CLKCTRL_VERSION_MAJOR_OFFSET		24
+#define	CLKCTRL_VERSION_MINOR_MASK		(0xff << 16)
+#define	CLKCTRL_VERSION_MINOR_OFFSET		16
+#define	CLKCTRL_VERSION_STEP_MASK		0xffff
+#define	CLKCTRL_VERSION_STEP_OFFSET		0
+
+#endif /* __REGS_CLKCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-common.h b/arch/arm/include/asm/arch-mx28/regs-common.h
new file mode 100644
index 0000000..774cfa1
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-common.h
@@ -0,0 +1,66 @@ 
+/*
+ * Freescale i.MX28 Register Accessors
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __REGS_COMMON_H__
+#define __REGS_COMMON_H__
+
+/*
+ * The i.MX28 has interesting feature when it comes to register access. There
+ * are four kinds of access to one particular register. Those are:
+ *
+ * 1) Common read/write access. To use this mode, just write to the address of
+ *    the register.
+ * 2) Set bits only access. To set bits, write which bits you want to set to the
+ *    address of the register + 0x4.
+ * 3) Clear bits only access. To clear bits, write which bits you want to clear
+ *    to the address of the register + 0x8.
+ * 4) Toggle bits only access. To toggle bits, write which bits you want to
+ *    toggle to the address of the register + 0xc.
+ *
+ * IMPORTANT NOTE: Not all registers support accesses 2-4! Also, not all bits
+ * can be set/cleared by pure write as in access type 1, some need to be
+ * explicitly set/cleared by using access type 2-3.
+ *
+ * The following macros and structures allow the user to either access the
+ * register in all aforementioned modes (by accessing reg_name, reg_name_set,
+ * reg_name_clr, reg_name_tog) or pass the register structure further into
+ * various functions with correct type information (by accessing reg_name_reg).
+ *
+ */
+
+#define	__mx28_reg(name)		\
+	uint32_t name;			\
+	uint32_t name##_set;		\
+	uint32_t name##_clr;		\
+	uint32_t name##_tog;
+
+struct mx28_register {
+	__mx28_reg(reg)
+};
+
+#define	mx28_reg(name)					\
+	union {						\
+		struct { __mx28_reg(name) };		\
+		struct mx28_register name##_reg;	\
+	};
+
+#endif	/* __REGS_COMMON_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-power.h b/arch/arm/include/asm/arch-mx28/regs-power.h
new file mode 100644
index 0000000..a17514e
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-power.h
@@ -0,0 +1,409 @@ 
+/*
+ * Freescale i.MX28 Power Controller Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __REGS_POWER_H__
+#define __REGS_POWER_H__
+
+struct mx28_power_regs {
+	mx28_reg(hw_power_ctrl)
+	mx28_reg(hw_power_5vctrl)
+	mx28_reg(hw_power_minpwr)
+	mx28_reg(hw_power_charge)
+	uint32_t	hw_power_vdddctrl;
+	uint32_t	reserved_vddd[3];
+	uint32_t	hw_power_vddactrl;
+	uint32_t	reserved_vdda[3];
+	uint32_t	hw_power_vddioctrl;
+	uint32_t	reserved_vddio[3];
+	uint32_t	hw_power_vddmemctrl;
+	uint32_t	reserved_vddmem[3];
+	uint32_t	hw_power_dcdc4p2;
+	uint32_t	reserved_dcdc4p2[3];
+	uint32_t	hw_power_misc;
+	uint32_t	reserved_misc[3];
+	uint32_t	hw_power_dclimits;
+	uint32_t	reserved_dclimits[3];
+	mx28_reg(hw_power_loopctrl)
+	uint32_t	hw_power_sts;
+	uint32_t	reserved_sts[3];
+	mx28_reg(hw_power_speed)
+	uint32_t	hw_power_battmonitor;
+	uint32_t	reserved_battmonitor[3];
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_power_reset)
+	mx28_reg(hw_power_debug)
+	mx28_reg(hw_power_thermal)
+	mx28_reg(hw_power_usb1ctrl)
+	mx28_reg(hw_power_special)
+	mx28_reg(hw_power_version)
+	mx28_reg(hw_power_anaclkctrl)
+	mx28_reg(hw_power_refctrl)
+};
+
+#define	POWER_CTRL_PSWITCH_MID_TRAN			(1 << 27)
+#define	POWER_CTRL_DCDC4P2_BO_IRQ			(1 << 24)
+#define	POWER_CTRL_ENIRQ_DCDC4P2_BO			(1 << 23)
+#define	POWER_CTRL_VDD5V_DROOP_IRQ			(1 << 22)
+#define	POWER_CTRL_ENIRQ_VDD5V_DROOP			(1 << 21)
+#define	POWER_CTRL_PSWITCH_IRQ				(1 << 20)
+#define	POWER_CTRL_PSWITCH_IRQ_SRC			(1 << 19)
+#define	POWER_CTRL_POLARITY_PSWITCH			(1 << 18)
+#define	POWER_CTRL_ENIRQ_PSWITCH			(1 << 17)
+#define	POWER_CTRL_POLARITY_DC_OK			(1 << 16)
+#define	POWER_CTRL_DC_OK_IRQ				(1 << 15)
+#define	POWER_CTRL_ENIRQ_DC_OK				(1 << 14)
+#define	POWER_CTRL_BATT_BO_IRQ				(1 << 13)
+#define	POWER_CTRL_ENIRQ_BATT_BO			(1 << 12)
+#define	POWER_CTRL_VDDIO_BO_IRQ				(1 << 11)
+#define	POWER_CTRL_ENIRQ_VDDIO_BO			(1 << 10)
+#define	POWER_CTRL_VDDA_BO_IRQ				(1 << 9)
+#define	POWER_CTRL_ENIRQ_VDDA_BO			(1 << 8)
+#define	POWER_CTRL_VDDD_BO_IRQ				(1 << 7)
+#define	POWER_CTRL_ENIRQ_VDDD_BO			(1 << 6)
+#define	POWER_CTRL_POLARITY_VBUSVALID			(1 << 5)
+#define	POWER_CTRL_VBUS_VALID_IRQ			(1 << 4)
+#define	POWER_CTRL_ENIRQ_VBUS_VALID			(1 << 3)
+#define	POWER_CTRL_POLARITY_VDD5V_GT_VDDIO		(1 << 2)
+#define	POWER_CTRL_VDD5V_GT_VDDIO_IRQ			(1 << 1)
+#define	POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO			(1 << 0)
+
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_MASK		(0x3 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_OFFSET		30
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V3			(0x0 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V4			(0x1 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V5			(0x2 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V7			(0x3 << 30)
+#define	POWER_5VCTRL_HEADROOM_ADJ_MASK			(0x7 << 24)
+#define	POWER_5VCTRL_HEADROOM_ADJ_OFFSET		24
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_MASK		(0x3 << 20)
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET		20
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK		(0x3f << 12)
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET		12
+#define	POWER_5VCTRL_VBUSVALID_TRSH_MASK		(0x7 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_OFFSET		8
+#define	POWER_5VCTRL_VBUSVALID_TRSH_2V9			(0x0 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V0			(0x1 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V1			(0x2 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V2			(0x3 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V3			(0x4 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V4			(0x5 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V5			(0x6 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V6			(0x7 << 8)
+#define	POWER_5VCTRL_PWDN_5VBRNOUT			(1 << 7)
+#define	POWER_5VCTRL_ENABLE_LINREG_ILIMIT		(1 << 6)
+#define	POWER_5VCTRL_DCDC_XFER				(1 << 5)
+#define	POWER_5VCTRL_VBUSVALID_5VDETECT			(1 << 4)
+#define	POWER_5VCTRL_VBUSVALID_TO_B			(1 << 3)
+#define	POWER_5VCTRL_ILIMIT_EQ_ZERO			(1 << 2)
+#define	POWER_5VCTRL_PWRUP_VBUS_CMPS			(1 << 1)
+#define	POWER_5VCTRL_ENABLE_DCDC			(1 << 0)
+
+#define	POWER_MINPWR_LOWPWR_4P2				(1 << 14)
+#define	POWER_MINPWR_PWD_BO				(1 << 12)
+#define	POWER_MINPWR_USE_VDDXTAL_VBG			(1 << 11)
+#define	POWER_MINPWR_PWD_ANA_CMPS			(1 << 10)
+#define	POWER_MINPWR_ENABLE_OSC				(1 << 9)
+#define	POWER_MINPWR_SELECT_OSC				(1 << 8)
+#define	POWER_MINPWR_FBG_OFF				(1 << 7)
+#define	POWER_MINPWR_DOUBLE_FETS			(1 << 6)
+#define	POWER_MINPWR_HALFFETS				(1 << 5)
+#define	POWER_MINPWR_LESSANA_I				(1 << 4)
+#define	POWER_MINPWR_PWD_XTAL24				(1 << 3)
+#define	POWER_MINPWR_DC_STOPCLK				(1 << 2)
+#define	POWER_MINPWR_EN_DC_PFM				(1 << 1)
+#define	POWER_MINPWR_DC_HALFCLK				(1 << 0)
+
+#define	POWER_CHARGE_ADJ_VOLT_MASK			(0x7 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_OFFSET			24
+#define	POWER_CHARGE_ADJ_VOLT_M025P			(0x1 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P050P			(0x2 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M075P			(0x3 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P025P			(0x4 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M050P			(0x5 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P075P			(0x6 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M100P			(0x7 << 24)
+#define	POWER_CHARGE_ENABLE_LOAD			(1 << 22)
+#define	POWER_CHARGE_ENABLE_FAULT_DETECT		(1 << 20)
+#define	POWER_CHARGE_CHRG_STS_OFF			(1 << 19)
+#define	POWER_CHARGE_LIION_4P1				(1 << 18)
+#define	POWER_CHARGE_PWD_BATTCHRG			(1 << 16)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB1		(1 << 13)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB0		(1 << 12)
+#define	POWER_CHARGE_STOP_ILIMIT_MASK			(0xf << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_OFFSET			8
+#define	POWER_CHARGE_STOP_ILIMIT_10MA			(0x1 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_20MA			(0x2 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_50MA			(0x4 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_100MA			(0x8 << 8)
+#define	POWER_CHARGE_BATTCHRG_I_MASK			0x3f
+#define	POWER_CHARGE_BATTCHRG_I_OFFSET			0
+#define	POWER_CHARGE_BATTCHRG_I_10MA			0x01
+#define	POWER_CHARGE_BATTCHRG_I_20MA			0x02
+#define	POWER_CHARGE_BATTCHRG_I_50MA			0x04
+#define	POWER_CHARGE_BATTCHRG_I_100MA			0x08
+#define	POWER_CHARGE_BATTCHRG_I_200MA			0x10
+#define	POWER_CHARGE_BATTCHRG_I_400MA			0x20
+
+#define	POWER_VDDDCTRL_ADJTN_MASK			(0xf << 28)
+#define	POWER_VDDDCTRL_ADJTN_OFFSET			28
+#define	POWER_VDDDCTRL_PWDN_BRNOUT			(1 << 23)
+#define	POWER_VDDDCTRL_DISABLE_STEPPING			(1 << 22)
+#define	POWER_VDDDCTRL_ENABLE_LINREG			(1 << 21)
+#define	POWER_VDDDCTRL_DISABLE_FET			(1 << 20)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_MASK		(0x3 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_OFFSET		16
+#define	POWER_VDDDCTRL_LINREG_OFFSET_0STEPS		(0x0 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 16)
+#define	POWER_VDDDCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDDCTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDDCTRL_TRG_MASK				0x1f
+#define	POWER_VDDDCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDACTRL_PWDN_BRNOUT			(1 << 19)
+#define	POWER_VDDACTRL_DISABLE_STEPPING			(1 << 18)
+#define	POWER_VDDACTRL_ENABLE_LINREG			(1 << 17)
+#define	POWER_VDDACTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDACTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDACTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDACTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDACTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDACTRL_TRG_MASK				0x1f
+#define	POWER_VDDACTRL_TRG_OFFSET			0
+
+#define	POWER_VDDIOCTRL_ADJTN_MASK			(0xf << 20)
+#define	POWER_VDDIOCTRL_ADJTN_OFFSET			20
+#define	POWER_VDDIOCTRL_PWDN_BRNOUT			(1 << 18)
+#define	POWER_VDDIOCTRL_DISABLE_STEPPING		(1 << 17)
+#define	POWER_VDDIOCTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDIOCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDIOCTRL_BO_OFFSET_OFFSET		8
+#define	POWER_VDDIOCTRL_TRG_MASK			0x1f
+#define	POWER_VDDIOCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDMEMCTRL_PULLDOWN_ACTIVE		(1 << 10)
+#define	POWER_VDDMEMCTRL_ENABLE_ILIMIT			(1 << 9)
+#define	POWER_VDDMEMCTRL_ENABLE_LINREG			(1 << 8)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_MASK			(0x7 << 5)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_OFFSET		5
+#define	POWER_VDDMEMCTRL_TRG_MASK			0x1f
+#define	POWER_VDDMEMCTRL_TRG_OFFSET			0
+
+#define	POWER_DCDC4P2_DROPOUT_CTRL_MASK			(0xf << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_OFFSET		28
+#define	POWER_DCDC4P2_DROPOUT_CTRL_200MV		(0x3 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_100MV		(0x2 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_50MV			(0x1 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_25MV			(0x0 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2		(0x0 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2_LT_BATT	(0x1 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL		(0x2 << 28)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_MASK		(0x3 << 24)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_OFFSET		24
+#define	POWER_DCDC4P2_ENABLE_4P2			(1 << 23)
+#define	POWER_DCDC4P2_ENABLE_DCDC			(1 << 22)
+#define	POWER_DCDC4P2_HYST_DIR				(1 << 21)
+#define	POWER_DCDC4P2_HYST_THRESH			(1 << 20)
+#define	POWER_DCDC4P2_TRG_MASK				(0x7 << 16)
+#define	POWER_DCDC4P2_TRG_OFFSET			16
+#define	POWER_DCDC4P2_TRG_4V2				(0x0 << 16)
+#define	POWER_DCDC4P2_TRG_4V1				(0x1 << 16)
+#define	POWER_DCDC4P2_TRG_4V0				(0x2 << 16)
+#define	POWER_DCDC4P2_TRG_3V9				(0x3 << 16)
+#define	POWER_DCDC4P2_TRG_BATT				(0x4 << 16)
+#define	POWER_DCDC4P2_BO_MASK				(0x1f << 8)
+#define	POWER_DCDC4P2_BO_OFFSET				8
+#define	POWER_DCDC4P2_CMPTRIP_MASK			0x1f
+#define	POWER_DCDC4P2_CMPTRIP_OFFSET			0
+
+#define	POWER_MISC_FREQSEL_MASK				(0x7 << 4)
+#define	POWER_MISC_FREQSEL_OFFSET			4
+#define	POWER_MISC_FREQSEL_20MHZ			(0x1 << 4)
+#define	POWER_MISC_FREQSEL_24MHZ			(0x2 << 4)
+#define	POWER_MISC_FREQSEL_19MHZ			(0x3 << 4)
+#define	POWER_MISC_FREQSEL_14MHZ			(0x4 << 4)
+#define	POWER_MISC_FREQSEL_18MHZ			(0x5 << 4)
+#define	POWER_MISC_FREQSEL_21MHZ			(0x6 << 4)
+#define	POWER_MISC_FREQSEL_17MHZ			(0x7 << 4)
+#define	POWER_MISC_DISABLE_FET_BO_LOGIC			(1 << 3)
+#define	POWER_MISC_DELAY_TIMING				(1 << 2)
+#define	POWER_MISC_TEST					(1 << 1)
+#define	POWER_MISC_SEL_PLLCLK				(1 << 0)
+
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_MASK		(0x7f << 8)
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET		8
+#define	POWER_DCLIMITS_NEGLIMIT_MASK			0x7f
+#define	POWER_DCLIMITS_NETLIMIT_OFFSET			0
+
+#define	POWER_LOOPCTRL_TOGGLE_DIF			(1 << 20)
+#define	POWER_LOOPCTRL_HYST_SIGN			(1 << 19)
+#define	POWER_LOOPCTRL_EN_CM_HYST			(1 << 18)
+#define	POWER_LOOPCTRL_EN_DF_HYST			(1 << 17)
+#define	POWER_LOOPCTRL_CM_HYST_THRESH			(1 << 16)
+#define	POWER_LOOPCTRL_DF_HYST_THRESH			(1 << 15)
+#define	POWER_LOOPCTRL_RCSCALE_THRESH			(1 << 14)
+#define	POWER_LOOPCTRL_EN_RCSCALE_MASK			(0x3 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_OFFSET		12
+#define	POWER_LOOPCTRL_EN_RCSCALE_DIS			(0x0 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_2X			(0x1 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_4X			(0x2 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_8X			(0x3 << 12)
+#define	POWER_LOOPCTRL_DC_FF_MASK			(0x7 << 8)
+#define	POWER_LOOPCTRL_DC_FF_OFFSET			8
+#define	POWER_LOOPCTRL_DC_R_MASK			(0xf << 4)
+#define	POWER_LOOPCTRL_DC_R_OFFSET			4
+#define	POWER_LOOPCTRL_DC_C_MASK			0x3
+#define	POWER_LOOPCTRL_DC_C_OFFSET			0
+#define	POWER_LOOPCTRL_DC_C_MAX				0x0
+#define	POWER_LOOPCTRL_DC_C_2X				0x1
+#define	POWER_LOOPCTRL_DC_C_4X				0x2
+#define	POWER_LOOPCTRL_DC_C_MIN				0x3
+
+#define	POWER_STS_PWRUP_SOURCE_MASK			(0x3f << 24)
+#define	POWER_STS_PWRUP_SOURCE_OFFSET			24
+#define	POWER_STS_PWRUP_SOURCE_5V			(0x20 << 24)
+#define	POWER_STS_PWRUP_SOURCE_RTC			(0x10 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_HIGH		(0x02 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_MID		(0x01 << 24)
+#define	POWER_STS_PSWITCH_MASK				(0x3 << 20)
+#define	POWER_STS_PSWITCH_OFFSET			20
+#define	POWER_STS_THERMAL_WARNING			(1 << 19)
+#define	POWER_STS_VDDMEM_BO				(1 << 18)
+#define	POWER_STS_AVALID0_STATUS			(1 << 17)
+#define	POWER_STS_BVALID0_STATUS			(1 << 16)
+#define	POWER_STS_VBUSVALID0_STATUS			(1 << 15)
+#define	POWER_STS_SESSEND0_STATUS			(1 << 14)
+#define	POWER_STS_BATT_BO				(1 << 13)
+#define	POWER_STS_VDD5V_FAULT				(1 << 12)
+#define	POWER_STS_CHRGSTS				(1 << 11)
+#define	POWER_STS_DCDC_4P2_BO				(1 << 10)
+#define	POWER_STS_DC_OK					(1 << 9)
+#define	POWER_STS_VDDIO_BO				(1 << 8)
+#define	POWER_STS_VDDA_BO				(1 << 7)
+#define	POWER_STS_VDDD_BO				(1 << 6)
+#define	POWER_STS_VDD5V_GT_VDDIO			(1 << 5)
+#define	POWER_STS_VDD5V_DROOP				(1 << 4)
+#define	POWER_STS_AVALID0				(1 << 3)
+#define	POWER_STS_BVALID0				(1 << 2)
+#define	POWER_STS_VBUSVALID0				(1 << 1)
+#define	POWER_STS_SESSEND0				(1 << 0)
+
+#define	POWER_SPEED_STATUS_MASK				(0xffff << 8)
+#define	POWER_SPEED_STATUS_OFFSET			8
+#define	POWER_SPEED_STATUS_SEL_MASK			(0x3 << 6)
+#define	POWER_SPEED_STATUS_SEL_OFFSET			6
+#define	POWER_SPEED_STATUS_SEL_DCDC_STAT		(0x0 << 6)
+#define	POWER_SPEED_STATUS_SEL_CORE_STAT		(0x1 << 6)
+#define	POWER_SPEED_STATUS_SEL_ARM_STAT			(0x2 << 6)
+#define	POWER_SPEED_CTRL_MASK				0x3
+#define	POWER_SPEED_CTRL_OFFSET				0
+#define	POWER_SPEED_CTRL_SS_OFF				0x0
+#define	POWER_SPEED_CTRL_SS_ON				0x1
+#define	POWER_SPEED_CTRL_SS_ENABLE			0x3
+
+#define	POWER_BATTMONITOR_BATT_VAL_MASK			(0x3ff << 16)
+#define	POWER_BATTMONITOR_BATT_VAL_OFFSET		16
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT_5VDETECT_EN	(1 << 11)
+#define	POWER_BATTMONITOR_EN_BATADJ			(1 << 10)
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT		(1 << 9)
+#define	POWER_BATTMONITOR_BRWNOUT_PWD			(1 << 8)
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_MASK		0x1f
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET		0
+
+#define	POWER_RESET_UNLOCK_MASK				(0xffff << 16)
+#define	POWER_RESET_UNLOCK_OFFSET			16
+#define	POWER_RESET_UNLOCK_KEY				(0x3e77 << 16)
+#define	POWER_RESET_FASTFALL_PSWITCH_OFF		(1 << 2)
+#define	POWER_RESET_PWD_OFF				(1 << 1)
+#define	POWER_RESET_PWD					(1 << 0)
+
+#define	POWER_DEBUG_VBUSVALIDPIOLOCK			(1 << 3)
+#define	POWER_DEBUG_AVALIDPIOLOCK			(1 << 2)
+#define	POWER_DEBUG_BVALIDPIOLOCK			(1 << 1)
+#define	POWER_DEBUG_SESSENDPIOLOCK			(1 << 0)
+
+#define	POWER_THERMAL_TEST				(1 << 8)
+#define	POWER_THERMAL_PWD				(1 << 7)
+#define	POWER_THERMAL_LOW_POWER				(1 << 6)
+#define	POWER_THERMAL_OFFSET_ADJ_MASK			(0x3 << 4)
+#define	POWER_THERMAL_OFFSET_ADJ_OFFSET			4
+#define	POWER_THERMAL_OFFSET_ADJ_ENABLE			(1 << 3)
+#define	POWER_THERMAL_TEMP_THRESHOLD_MASK		0x7
+#define	POWER_THERMAL_TEMP_THRESHOLD_OFFSET		0
+
+#define	POWER_USB1CTRL_AVALID1				(1 << 3)
+#define	POWER_USB1CTRL_BVALID1				(1 << 2)
+#define	POWER_USB1CTRL_VBUSVALID1			(1 << 1)
+#define	POWER_USB1CTRL_SESSEND1				(1 << 0)
+
+#define	POWER_SPECIAL_TEST_MASK				0xffffffff
+#define	POWER_SPECIAL_TEST_OFFSET			0
+
+#define	POWER_VERSION_MAJOR_MASK			(0xff << 24)
+#define	POWER_VERSION_MAJOR_OFFSET			24
+#define	POWER_VERSION_MINOR_MASK			(0xff << 16)
+#define	POWER_VERSION_MINOR_OFFSET			16
+#define	POWER_VERSION_STEP_MASK				0xffff
+#define	POWER_VERSION_STEP_OFFSET			0
+
+#define	POWER_ANACLKCTRL_CLKGATE_0			(1 << 31)
+#define	POWER_ANACLKCTRL_OUTDIV_MASK			(0x7 << 28)
+#define	POWER_ANACLKCTRL_OUTDIV_OFFSET			28
+#define	POWER_ANACLKCTRL_INVERT_OUTCLK			(1 << 27)
+#define	POWER_ANACLKCTRL_CLKGATE_I			(1 << 26)
+#define	POWER_ANACLKCTRL_DITHER_OFF			(1 << 10)
+#define	POWER_ANACLKCTRL_SLOW_DITHER			(1 << 9)
+#define	POWER_ANACLKCTRL_INVERT_INCLK			(1 << 8)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_MASK		(0x3 << 4)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_OFFSET		4
+#define	POWER_ANACLKCTRL_INDIV_MASK			0x7
+#define	POWER_ANACLKCTRL_INDIV_OFFSET			0
+
+#define	POWER_REFCTRL_FASTSETTLING			(1 << 26)
+#define	POWER_REFCTRL_RAISE_REF				(1 << 25)
+#define	POWER_REFCTRL_XTAL_BGR_BIAS			(1 << 24)
+#define	POWER_REFCTRL_VBG_ADJ_MASK			(0x7 << 20)
+#define	POWER_REFCTRL_VBG_ADJ_OFFSET			20
+#define	POWER_REFCTRL_LOW_PWR				(1 << 19)
+#define	POWER_REFCTRL_BIAS_CTRL_MASK			(0x3 << 16)
+#define	POWER_REFCTRL_BIAS_CTRL_OFFSET			16
+#define	POWER_REFCTRL_VDDXTAL_TO_VDDD			(1 << 14)
+#define	POWER_REFCTRL_ADJ_ANA				(1 << 13)
+#define	POWER_REFCTRL_ADJ_VAG				(1 << 12)
+#define	POWER_REFCTRL_ANA_REFVAL_MASK			(0xf << 8)
+#define	POWER_REFCTRL_ANA_REFVAL_OFFSET			8
+#define	POWER_REFCTRL_VAG_VAL_MASK			(0xf << 4)
+#define	POWER_REFCTRL_VAG_VAL_OFFSET			4
+
+#endif	/* __REGS_POWER_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ssp.h b/arch/arm/include/asm/arch-mx28/regs-ssp.h
new file mode 100644
index 0000000..6a275c0
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ssp.h
@@ -0,0 +1,345 @@ 
+/*
+ * Freescale i.MX28 SSP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __REGS_SSP_H__
+#define __REGS_SSP_H__
+
+struct mx28_ssp_regs {
+	mx28_reg(hw_ssp_ctrl0)
+	mx28_reg(hw_ssp_cmd0)
+	mx28_reg(hw_ssp_cmd1)
+	mx28_reg(hw_ssp_xfer_size)
+	mx28_reg(hw_ssp_block_size)
+	mx28_reg(hw_ssp_compref)
+	mx28_reg(hw_ssp_compmask)
+	mx28_reg(hw_ssp_timing)
+	mx28_reg(hw_ssp_ctrl1)
+	mx28_reg(hw_ssp_data)
+	mx28_reg(hw_ssp_sdresp0)
+	mx28_reg(hw_ssp_sdresp1)
+	mx28_reg(hw_ssp_sdresp2)
+	mx28_reg(hw_ssp_sdresp3)
+	mx28_reg(hw_ssp_ddr_ctrl)
+	mx28_reg(hw_ssp_dll_ctrl)
+	mx28_reg(hw_ssp_status)
+	mx28_reg(hw_ssp_dll_sts)
+	mx28_reg(hw_ssp_debug)
+	mx28_reg(hw_ssp_version)
+};
+
+#define	SSP_CTRL0_SFTRST			(1 << 31)
+#define	SSP_CTRL0_CLKGATE			(1 << 30)
+#define	SSP_CTRL0_RUN				(1 << 29)
+#define	SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define	SSP_CTRL0_LOCK_CS			(1 << 27)
+#define	SSP_CTRL0_IGNORE_CRC			(1 << 26)
+#define	SSP_CTRL0_READ				(1 << 25)
+#define	SSP_CTRL0_DATA_XFER			(1 << 24)
+#define	SSP_CTRL0_BUS_WIDTH_MASK		(0x3 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_OFFSET		22
+#define	SSP_CTRL0_BUS_WIDTH_ONE_BIT		(0x0 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_FOUR_BIT		(0x1 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_EIGHT_BIT		(0x2 << 22)
+#define	SSP_CTRL0_WAIT_FOR_IRQ			(1 << 21)
+#define	SSP_CTRL0_WAIT_FOR_CMD			(1 << 20)
+#define	SSP_CTRL0_LONG_RESP			(1 << 19)
+#define	SSP_CTRL0_CHECK_RESP			(1 << 18)
+#define	SSP_CTRL0_GET_RESP			(1 << 17)
+#define	SSP_CTRL0_ENABLE			(1 << 16)
+
+#define	SSP_CMD0_SOFT_TERMINATE			(1 << 26)
+#define	SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define	SSP_CMD0_PRIM_BOOT_OP_EN		(1 << 24)
+#define	SSP_CMD0_BOOT_ACK_EN			(1 << 23)
+#define	SSP_CMD0_SLOW_CLKING_EN			(1 << 22)
+#define	SSP_CMD0_CONT_CLKING_EN			(1 << 21)
+#define	SSP_CMD0_APPEND_8CYC			(1 << 20)
+#define	SSP_CMD0_CMD_MASK			0xff
+#define	SSP_CMD0_CMD_OFFSET			0
+#define	SSP_CMD0_CMD_MMC_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_MMC_SEND_OP_COND		0x01
+#define	SSP_CMD0_CMD_MMC_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_MMC_SET_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_MMC_SET_DSR		0x04
+#define	SSP_CMD0_CMD_MMC_RESERVED_5		0x05
+#define	SSP_CMD0_CMD_MMC_SWITCH			0x06
+#define	SSP_CMD0_CMD_MMC_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_MMC_SEND_EXT_CSD		0x08
+#define	SSP_CMD0_CMD_MMC_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_MMC_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_MMC_READ_DAT_UNTIL_STOP	0x0b
+#define	SSP_CMD0_CMD_MMC_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_MMC_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_MMC_BUSTEST_R		0x0e
+#define	SSP_CMD0_CMD_MMC_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_MMC_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_MMC_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_MMC_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_MMC_BUSTEST_W		0x13
+#define	SSP_CMD0_CMD_MMC_WRITE_DAT_UNTIL_STOP	0x14
+#define	SSP_CMD0_CMD_MMC_SET_BLOCK_COUNT	0x17
+#define	SSP_CMD0_CMD_MMC_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_MMC_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CID		0x1a
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_MMC_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_MMC_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_MMC_SEND_WRITE_PROT	0x1e
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_END	0x24
+#define	SSP_CMD0_CMD_MMC_ERASE			0x26
+#define	SSP_CMD0_CMD_MMC_FAST_IO		0x27
+#define	SSP_CMD0_CMD_MMC_GO_IRQ_STATE		0x28
+#define	SSP_CMD0_CMD_MMC_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_MMC_APP_CMD		0x37
+#define	SSP_CMD0_CMD_MMC_GEN_CMD		0x38
+#define	SSP_CMD0_CMD_SD_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_SD_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_SD_SEND_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_SD_SET_DSR			0x04
+#define	SSP_CMD0_CMD_SD_IO_SEND_OP_COND		0x05
+#define	SSP_CMD0_CMD_SD_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_SD_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_SD_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_SD_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_SD_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_SD_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_SD_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_SD_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_SD_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_SD_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_SD_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_SD_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_SD_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_SD_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_SD_SEND_WRITE_PROT		0x1e
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_START	0x20
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_END	0x21
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_END		0x24
+#define	SSP_CMD0_CMD_SD_ERASE			0x26
+#define	SSP_CMD0_CMD_SD_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_SD_IO_RW_DIRECT		0x34
+#define	SSP_CMD0_CMD_SD_IO_RW_EXTENDED		0x35
+#define	SSP_CMD0_CMD_SD_APP_CMD			0x37
+#define	SSP_CMD0_CMD_SD_GEN_CMD			0x38
+
+#define	SSP_CMD1_CMD_ARG_MASK			0xffffffff
+#define	SSP_CMD1_CMD_ARG_OFFSET			0
+
+#define	SSP_XFER_SIZE_XFER_COUNT_MASK		0xffffffff
+#define	SSP_XFER_SIZE_XFER_COUNT_OFFSET		0
+
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_MASK		(0xffffff << 4)
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET	4
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_MASK		0xf
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET	0
+
+#define	SSP_COMPREF_REFERENCE_MASK		0xffffffff
+#define	SSP_COMPREF_REFERENCE_OFFSET		0
+
+#define	SSP_COMPMASK_MASK_MASK			0xffffffff
+#define	SSP_COMPMASK_MASK_OFFSET		0
+
+#define	SSP_TIMING_TIMEOUT_MASK			(0xffff << 16)
+#define	SSP_TIMING_TIMEOUT_OFFSET		16
+#define	SSP_TIMING_CLOCK_DIVIDE_MASK		(0xff << 8)
+#define	SSP_TIMING_CLOCK_DIVIDE_OFFSET		8
+#define	SSP_TIMING_CLOCK_RATE_MASK		0xff
+#define	SSP_TIMING_CLOCK_RATE_OFFSET		0
+
+#define	SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define	SSP_CTRL1_SDIO_IRQ_EN			(1 << 30)
+#define	SSP_CTRL1_RESP_ERR_IRQ			(1 << 29)
+#define	SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ_EN		(1 << 26)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ_EN		(1 << 24)
+#define	SSP_CTRL1_DATA_CRC_IRQ			(1 << 23)
+#define	SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define	SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define	SSP_CTRL1_FIFO_UNDERRUN_EN		(1 << 20)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ		(1 << 19)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ_EN		(1 << 18)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ_EN		(1 << 16)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ_EN		(1 << 14)
+#define	SSP_CTRL1_DMA_ENABLE			(1 << 13)
+#define	SSP_CTRL1_CEATA_CCS_ERR_EN		(1 << 12)
+#define	SSP_CTRL1_SLAVE_OUT_DISABLE		(1 << 11)
+#define	SSP_CTRL1_PHASE				(1 << 10)
+#define	SSP_CTRL1_POLARITY			(1 << 9)
+#define	SSP_CTRL1_SLAVE_MODE			(1 << 8)
+#define	SSP_CTRL1_WORD_LENGTH_MASK		(0xf << 4)
+#define	SSP_CTRL1_WORD_LENGTH_OFFSET		4
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED0		(0x0 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED1		(0x1 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED2		(0x2 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_FOUR_BITS		(0x3 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_EIGHT_BITS	(0x7 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_SIXTEEN_BITS	(0xf << 4)
+#define	SSP_CTRL1_SSP_MODE_MASK			0xf
+#define	SSP_CTRL1_SSP_MODE_OFFSET		0
+#define	SSP_CTRL1_SSP_MODE_SPI			0x0
+#define	SSP_CTRL1_SSP_MODE_SSI			0x1
+#define	SSP_CTRL1_SSP_MODE_SD_MMC		0x3
+#define	SSP_CTRL1_SSP_MODE_MS			0x4
+
+#define	SSP_DATA_DATA_MASK			0xffffffff
+#define	SSP_DATA_DATA_OFFSET			0
+
+#define	SSP_SDRESP0_RESP0_MASK			0xffffffff
+#define	SSP_SDRESP0_RESP0_OFFSET		0
+
+#define	SSP_SDRESP1_RESP1_MASK			0xffffffff
+#define	SSP_SDRESP1_RESP1_OFFSET		0
+
+#define	SSP_SDRESP2_RESP2_MASK			0xffffffff
+#define	SSP_SDRESP2_RESP2_OFFSET		0
+
+#define	SSP_SDRESP3_RESP3_MASK			0xffffffff
+#define	SSP_SDRESP3_RESP3_OFFSET		0
+
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_MASK	(0x3 << 30)
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_OFFSET	30
+#define	SSP_DDR_CTRL_NIBBLE_POS			(1 << 1)
+#define	SSP_DDR_CTRL_TXCLK_DELAY_TYPE		(1 << 0)
+
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_MASK	(0xf << 28)
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_OFFSET	28
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_MASK	(0xff << 20)
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_OFFSET	20
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_MASK	(0x3f << 10)
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_OFFSET	10
+#define	SSP_DLL_CTRL_SLV_OVERRIDE		(1 << 9)
+#define	SSP_DLL_CTRL_GATE_UPDATE		(1 << 7)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_MASK	(0xf << 3)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_OFFSET	3
+#define	SSP_DLL_CTRL_SLV_FORCE_UPD		(1 << 2)
+#define	SSP_DLL_CTRL_RESET			(1 << 1)
+#define	SSP_DLL_CTRL_ENABLE			(1 << 0)
+
+#define	SSP_STATUS_PRESENT			(1 << 31)
+#define	SSP_STATUS_MS_PRESENT			(1 << 30)
+#define	SSP_STATUS_SD_PRESENT			(1 << 29)
+#define	SSP_STATUS_CARD_DETECT			(1 << 28)
+#define	SSP_STATUS_DMABURST			(1 << 22)
+#define	SSP_STATUS_DMASENSE			(1 << 21)
+#define	SSP_STATUS_DMATERM			(1 << 20)
+#define	SSP_STATUS_DMAREQ			(1 << 19)
+#define	SSP_STATUS_DMAEND			(1 << 18)
+#define	SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define	SSP_STATUS_RESP_CRC_ERR			(1 << 16)
+#define	SSP_STATUS_RESP_ERR			(1 << 15)
+#define	SSP_STATUS_RESP_TIMEOUT			(1 << 14)
+#define	SSP_STATUS_DATA_CRC_ERR			(1 << 13)
+#define	SSP_STATUS_TIMEOUT			(1 << 12)
+#define	SSP_STATUS_RECV_TIMEOUT_STAT		(1 << 11)
+#define	SSP_STATUS_CEATA_CCS_ERR		(1 << 10)
+#define	SSP_STATUS_FIFO_OVRFLW			(1 << 9)
+#define	SSP_STATUS_FIFO_FULL			(1 << 8)
+#define	SSP_STATUS_FIFO_EMPTY			(1 << 5)
+#define	SSP_STATUS_FIFO_UNDRFLW			(1 << 4)
+#define	SSP_STATUS_CMD_BUSY			(1 << 3)
+#define	SSP_STATUS_DATA_BUSY			(1 << 2)
+#define	SSP_STATUS_BUSY				(1 << 0)
+
+#define	SSP_DLL_STS_REF_SEL_MASK		(0x3f << 8)
+#define	SSP_DLL_STS_REF_SEL_OFFSET		8
+#define	SSP_DLL_STS_SLV_SEL_MASK		(0x3f << 2)
+#define	SSP_DLL_STS_SLV_SEL_OFFSET		2
+#define	SSP_DLL_STS_REF_LOCK			(1 << 1)
+#define	SSP_DLL_STS_SLV_LOCK			(1 << 0)
+
+#define	SSP_DEBUG_DATACRC_ERR_MASK		(0xf << 28)
+#define	SSP_DEBUG_DATACRC_ERR_OFFSET		28
+#define	SSP_DEBUG_DATA_STALL			(1 << 27)
+#define	SSP_DEBUG_DAT_SM_MASK			(0x7 << 24)
+#define	SSP_DEBUG_DAT_SM_OFFSET			24
+#define	SSP_DEBUG_DAT_SM_DSM_IDLE		(0x0 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_WORD		(0x2 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC1		(0x3 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC2		(0x4 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_END		(0x5 << 24)
+#define	SSP_DEBUG_MSTK_SM_MASK			(0xf << 20)
+#define	SSP_DEBUG_MSTK_SM_OFFSET		20
+#define	SSP_DEBUG_MSTK_SM_MSTK_IDLE		(0x0 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CKON		(0x1 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS1		(0x2 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_TPC		(0x3 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS2		(0x4 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_HDSHK		(0x5 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS3		(0x6 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_RW		(0x7 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC1		(0x8 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC2		(0x9 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS0		(0xa << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END1		(0xb << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2W		(0xc << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2R		(0xd << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_DONE		(0xe << 20)
+#define	SSP_DEBUG_CMD_OE			(1 << 19)
+#define	SSP_DEBUG_DMA_SM_MASK			(0x7 << 16)
+#define	SSP_DEBUG_DMA_SM_OFFSET			16
+#define	SSP_DEBUG_DMA_SM_DMA_IDLE		(0x0 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAREQ		(0x1 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAACK		(0x2 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_STALL		(0x3 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_BUSY		(0x4 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DONE		(0x5 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_COUNT		(0x6 << 16)
+#define	SSP_DEBUG_MMC_SM_MASK			(0xf << 12)
+#define	SSP_DEBUG_MMC_SM_OFFSET			12
+#define	SSP_DEBUG_MMC_SM_MMC_IDLE		(0x0 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CMD		(0x1 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TRC		(0x2 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RESP		(0x3 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RPRX		(0x4 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TX			(0x5 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CTOK		(0x6 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RX			(0x7 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CCS		(0x8 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_PUP		(0x9 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_WAIT		(0xa << 12)
+#define	SSP_DEBUG_CMD_SM_MASK			(0x3 << 10)
+#define	SSP_DEBUG_CMD_SM_OFFSET			10
+#define	SSP_DEBUG_CMD_SM_CSM_IDLE		(0x0 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_INDEX		(0x1 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_ARG		(0x2 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_CRC		(0x3 << 10)
+#define	SSP_DEBUG_SSP_CMD			(1 << 9)
+#define	SSP_DEBUG_SSP_RESP			(1 << 8)
+#define	SSP_DEBUG_SSP_RXD_MASK			0xff
+#define	SSP_DEBUG_SSP_RXD_OFFSET		0
+
+#define	SSP_VERSION_MAJOR_MASK			(0xff << 24)
+#define	SSP_VERSION_MAJOR_OFFSET		24
+#define	SSP_VERSION_MINOR_MASK			(0xff << 16)
+#define	SSP_VERSION_MINOR_OFFSET		16
+#define	SSP_VERSION_STEP_MASK			0xffff
+#define	SSP_VERSION_STEP_OFFSET			0
+
+#endif /* __REGS_SSP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-timrot.h b/arch/arm/include/asm/arch-mx28/regs-timrot.h
new file mode 100644
index 0000000..27e511e
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-timrot.h
@@ -0,0 +1,167 @@ 
+/*
+ * Freescale i.MX28 TIMROT Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __REGS_TIMROT_H__
+#define __REGS_TIMROT_H__
+
+struct mx28_timrot_regs {
+	mx28_reg(hw_timrot_rotctrl)
+	mx28_reg(hw_timrot_rotcount)
+	mx28_reg(hw_timrot_timctrl0)
+	mx28_reg(hw_timrot_running_count0)
+	mx28_reg(hw_timrot_fixed_count0)
+	mx28_reg(hw_timrot_match_count0)
+	mx28_reg(hw_timrot_timctrl1)
+	mx28_reg(hw_timrot_running_count1)
+	mx28_reg(hw_timrot_fixed_count1)
+	mx28_reg(hw_timrot_match_count1)
+	mx28_reg(hw_timrot_timctrl2)
+	mx28_reg(hw_timrot_running_count2)
+	mx28_reg(hw_timrot_fixed_count2)
+	mx28_reg(hw_timrot_match_count2)
+	mx28_reg(hw_timrot_timctrl3)
+	mx28_reg(hw_timrot_running_count3)
+	mx28_reg(hw_timrot_fixed_count3)
+	mx28_reg(hw_timrot_match_count3)
+	mx28_reg(hw_timrot_version)
+};
+
+#define	TIMROT_ROTCTRL_SFTRST				(1 << 31)
+#define	TIMROT_ROTCTRL_CLKGATE				(1 << 30)
+#define	TIMROT_ROTCTRL_ROTARY_PRESENT			(1 << 29)
+#define	TIMROT_ROTCTRL_TIM3_PRESENT			(1 << 28)
+#define	TIMROT_ROTCTRL_TIM2_PRESENT			(1 << 27)
+#define	TIMROT_ROTCTRL_TIM1_PRESENT			(1 << 26)
+#define	TIMROT_ROTCTRL_TIM0_PRESENT			(1 << 25)
+#define	TIMROT_ROTCTRL_STATE_MASK			(0x7 << 22)
+#define	TIMROT_ROTCTRL_STATE_OFFSET			22
+#define	TIMROT_ROTCTRL_DIVIDER_MASK			(0x3f << 16)
+#define	TIMROT_ROTCTRL_DIVIDER_OFFSET			16
+#define	TIMROT_ROTCTRL_RELATIVE				(1 << 12)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_MASK			(0x3 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_OFFSET		10
+#define	TIMROT_ROTCTRL_OVERSAMPLE_8X			(0x0 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_4X			(0x1 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_2X			(0x2 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_1X			(0x3 << 10)
+#define	TIMROT_ROTCTRL_POLARITY_B			(1 << 9)
+#define	TIMROT_ROTCTRL_POLARITY_A			(1 << 8)
+#define	TIMROT_ROTCTRL_SELECT_B_MASK			(0xf << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_OFFSET			4
+#define	TIMROT_ROTCTRL_SELECT_B_NEVER_TICK		(0x0 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM0			(0x1 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM1			(0x2 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM2			(0x3 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM3			(0x4 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM4			(0x5 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM5			(0x6 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM6			(0x7 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM7			(0x8 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYA			(0x9 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYB			(0xa << 4)
+#define	TIMROT_ROTCTRL_SELECT_A_MASK			0xf
+#define	TIMROT_ROTCTRL_SELECT_A_OFFSET			0
+#define	TIMROT_ROTCTRL_SELECT_A_NEVER_TICK		0x0
+#define	TIMROT_ROTCTRL_SELECT_A_PWM0			0x1
+#define	TIMROT_ROTCTRL_SELECT_A_PWM1			0x2
+#define	TIMROT_ROTCTRL_SELECT_A_PWM2			0x3
+#define	TIMROT_ROTCTRL_SELECT_A_PWM3			0x4
+#define	TIMROT_ROTCTRL_SELECT_A_PWM4			0x5
+#define	TIMROT_ROTCTRL_SELECT_A_PWM5			0x6
+#define	TIMROT_ROTCTRL_SELECT_A_PWM6			0x7
+#define	TIMROT_ROTCTRL_SELECT_A_PWM7			0x8
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYA			0x9
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYB			0xa
+
+#define	TIMROT_ROTCOUNT_UPDOWN_MASK			0xffff
+#define	TIMROT_ROTCOUNT_UPDOWN_OFFSET			0
+
+#define	TIMROT_TIMCTRLn_IRQ				(1 << 15)
+#define	TIMROT_TIMCTRLn_IRQ_EN				(1 << 14)
+#define	TIMROT_TIMCTRLn_MATCH_MODE			(1 << 11)
+#define	TIMROT_TIMCTRLn_POLARITY			(1 << 8)
+#define	TIMROT_TIMCTRLn_UPDATE				(1 << 7)
+#define	TIMROT_TIMCTRLn_RELOAD				(1 << 6)
+#define	TIMROT_TIMCTRLn_PRESCALE_MASK			(0x3 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_OFFSET			4
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_1		(0x0 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_2		(0x1 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_4		(0x2 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_8		(0x3 << 4)
+#define	TIMROT_TIMCTRLn_SELECT_MASK			0xf
+#define	TIMROT_TIMCTRLn_SELECT_OFFSET			0
+#define	TIMROT_TIMCTRLn_SELECT_NEVER_TICK		0x0
+#define	TIMROT_TIMCTRLn_SELECT_PWM0			0x1
+#define	TIMROT_TIMCTRLn_SELECT_PWM1			0x2
+#define	TIMROT_TIMCTRLn_SELECT_PWM2			0x3
+#define	TIMROT_TIMCTRLn_SELECT_PWM3			0x4
+#define	TIMROT_TIMCTRLn_SELECT_PWM4			0x5
+#define	TIMROT_TIMCTRLn_SELECT_PWM5			0x6
+#define	TIMROT_TIMCTRLn_SELECT_PWM6			0x7
+#define	TIMROT_TIMCTRLn_SELECT_PWM7			0x8
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYA			0x9
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYB			0xa
+#define	TIMROT_TIMCTRLn_SELECT_32KHZ_XTAL		0xb
+#define	TIMROT_TIMCTRLn_SELECT_8KHZ_XTAL		0xc
+#define	TIMROT_TIMCTRLn_SELECT_4KHZ_XTAL		0xd
+#define	TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL		0xe
+#define	TIMROT_TIMCTRLn_SELECT_TICK_ALWAYS		0xf
+
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_MASK	0xffffffff
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET	0
+
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_MASK		0xffffffff
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_OFFSET		0
+
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_MASK		0xffffffff
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_OFFSET		0
+
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_MASK		(0xf << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_OFFSET		16
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_NEVER_TICK		(0x0 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM0		(0x1 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM1		(0x2 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM2		(0x3 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM3		(0x4 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM4		(0x5 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM5		(0x6 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM6		(0x7 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM7		(0x8 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYA		(0x9 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYB		(0xa << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_32KHZ_XTAL		(0xb << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_8KHZ_XTAL		(0xc << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_4KHZ_XTAL		(0xd << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_1KHZ_XTAL		(0xe << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_TICK_ALWAYS		(0xf << 16)
+#define	TIMROT_TIMCTRL3_DUTY_CYCLE			(1 << 9)
+
+#define	TIMROT_VERSION_MAJOR_MASK			(0xff << 24)
+#define	TIMROT_VERSION_MAJOR_OFFSET			24
+#define	TIMROT_VERSION_MINOR_MASK			(0xff << 16)
+#define	TIMROT_VERSION_MINOR_OFFSET			16
+#define	TIMROT_VERSION_STEP_MASK			0xffff
+#define	TIMROT_VERSION_STEP_OFFSET			0
+
+#endif /* __REGS_TIMROT_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-uartdbg.h b/arch/arm/include/asm/arch-mx28/regs-uartdbg.h
new file mode 100644
index 0000000..a2819e5
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-uartdbg.h
@@ -0,0 +1,182 @@ 
+/*
+ * Freescale i.MX28 UARTDBG Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __REGS_UARTDBG_H__
+#define __REGS_UARTDBG_H__
+
+struct mx28_uartdbg_regs {
+	uint32_t	hw_uartdbg_dr;		/* 0x00 */
+	uint32_t	hw_uartdbg_ecr;
+
+	uint32_t	reserved1[4];
+
+	uint32_t	hw_uartdbg_fr;
+
+	uint32_t	reserved2;
+
+	uint32_t	hw_uartdbg_ilpr;	/* 0x20 */
+	uint32_t	hw_uartdbg_ibrd;
+	uint32_t	hw_uartdbg_fbrd;
+	uint32_t	hw_uartdbg_lcr_h;
+	uint32_t	hw_uartdbg_cr;		/* 0x30 */
+	uint32_t	hw_uartdbg_ifls;
+	uint32_t	hw_uartdbg_imsc;
+	uint32_t	hw_uartdbg_ris;
+	uint32_t	hw_uartdbg_mis;		/* 0x40 */
+	uint32_t	hw_uartdbg_icr;
+	uint32_t	hw_uartdbg_dmacr;
+};
+
+#define	UARTDBG_DR_OE				(1 << 11)
+#define	UARTDBG_DR_BE				(1 << 10)
+#define	UARTDBG_DR_PE				(1 << 9)
+#define	UARTDBG_DR_FE				(1 << 8)
+#define	UARTDBG_DR_DATA_MASK			0xff
+#define	UARTDBG_DR_DATA_OFFSET			0
+
+#define	UARTDBG_RSR_ECR_EC_MASK			(0xf << 4)
+#define	UARTDBG_RSR_ECR_EC_OFFSET		4
+#define	UARTDBG_RSR_ECR_OE			(1 << 3)
+#define	UARTDBG_RSR_ECR_BE			(1 << 2)
+#define	UARTDBG_RSR_ECR_PE			(1 << 1)
+#define	UARTDBG_RSR_ECR_FE			(1 << 0)
+
+#define	UARTDBG_FR_RI				(1 << 8)
+#define	UARTDBG_FR_TXFE				(1 << 7)
+#define	UARTDBG_FR_RXFF				(1 << 6)
+#define	UARTDBG_FR_TXFF				(1 << 5)
+#define	UARTDBG_FR_RXFE				(1 << 4)
+#define	UARTDBG_FR_BUSY				(1 << 3)
+#define	UARTDBG_FR_DCD				(1 << 2)
+#define	UARTDBG_FR_DSR				(1 << 1)
+#define	UARTDBG_FR_CTS				(1 << 0)
+
+#define	UARTDBG_ILPR_ILPDVSR_MASK		0xff
+#define	UARTDBG_ILPR_ILPDVSR_OFFSET		0
+
+#define	UARTDBG_IBRD_BAUD_DIVINT_MASK		0xffff
+#define	UARTDBG_IBRD_BAUD_DIVINT_OFFSET		0
+
+#define	UARTDBG_FBRD_BAUD_DIVFRAC_MASK		0x3f
+#define	UARTDBG_FBRD_BAUD_DIVFRAC_OFFSET	0
+
+#define	UARTDBG_LCR_H_SPS			(1 << 7)
+#define	UARTDBG_LCR_H_WLEN_MASK			(0x3 << 5)
+#define	UARTDBG_LCR_H_WLEN_OFFSET		5
+#define	UARTDBG_LCR_H_FEN			(1 << 4)
+#define	UARTDBG_LCR_H_STP2			(1 << 3)
+#define	UARTDBG_LCR_H_EPS			(1 << 2)
+#define	UARTDBG_LCR_H_PEN			(1 << 1)
+#define	UARTDBG_LCR_H_BRK			(1 << 0)
+
+
+#define	UARTDBG_CR_CTSEN			(1 << 15)
+#define	UARTDBG_CR_RTSEN			(1 << 14)
+#define	UARTDBG_CR_OUT2				(1 << 13)
+#define	UARTDBG_CR_OUT1				(1 << 12)
+#define	UARTDBG_CR_RTS				(1 << 11)
+#define	UARTDBG_CR_DTR				(1 << 10)
+#define	UARTDBG_CR_RXE				(1 << 9)
+#define	UARTDBG_CR_TXE				(1 << 8)
+#define	UARTDBG_CR_LBE				(1 << 7)
+#define	UARTDBG_CR_RESERVED_MASK		(0xf << 3)
+#define	UARTDBG_CR_RESERVED_OFFSET		3
+#define	UARTDBG_CR_SIRLP			(1 << 2)
+#define	UARTDBG_CR_SIREN			(1 << 1)
+#define	UARTDBG_CR_UARTEN			(1 << 0)
+
+#define	UARTDBG_IFLS_RXIFLSEL_MASK		(0x7 << 3)
+#define	UARTDBG_IFLS_RXIFLSEL_OFFSET		3
+#define	UARTDBG_IFLS_RXIFLSEL_ONE_EIGHT		(0x0 << 3)
+#define	UARTDBG_IFLS_RXIFLSEL_ONE_QUARTER	(0x1 << 3)
+#define	UARTDBG_IFLS_RXIFLSEL_ONE_HALF		(0x2 << 3)
+#define	UARTDBG_IFLS_RXIFLSEL_THREE_QUARTERS	(0x3 << 3)
+#define	UARTDBG_IFLS_RXIFLSEL_SEVEN_EIGHTHS	(0x4 << 3)
+#define	UARTDBG_IFLS_RXIFLSEL_INVALID5		(0x5 << 3)
+#define	UARTDBG_IFLS_RXIFLSEL_INVALID6		(0x6 << 3)
+#define	UARTDBG_IFLS_RXIFLSEL_INVALID7		(0x7 << 3)
+#define	UARTDBG_IFLS_TXIFLSEL_MASK		0x7
+#define	UARTDBG_IFLS_TXIFLSEL_OFFSET		0
+#define	UARTDBG_IFLS_TXIFLSEL_ONE_EIGHT		0x0
+#define	UARTDBG_IFLS_TXIFLSEL_ONE_QUARTER	0x1
+#define	UARTDBG_IFLS_TXIFLSEL_ONE_HALF		0x2
+#define	UARTDBG_IFLS_TXIFLSEL_THREE_QUARTERS	0x3
+#define	UARTDBG_IFLS_TXIFLSEL_SEVEN_EIGHTHS	0x4
+#define	UARTDBG_IFLS_TXIFLSEL_INVALID5		0x5
+#define	UARTDBG_IFLS_TXIFLSEL_INVALID6		0x6
+#define	UARTDBG_IFLS_TXIFLSEL_INVALID7		0x7
+
+#define	UARTDBG_IMSC_OEIM			(1 << 10)
+#define	UARTDBG_IMSC_BEIM			(1 << 9)
+#define	UARTDBG_IMSC_PEIM			(1 << 8)
+#define	UARTDBG_IMSC_FEIM			(1 << 7)
+#define	UARTDBG_IMSC_RTIM			(1 << 6)
+#define	UARTDBG_IMSC_TXIM			(1 << 5)
+#define	UARTDBG_IMSC_RXIM			(1 << 4)
+#define	UARTDBG_IMSC_DSRMIM			(1 << 3)
+#define	UARTDBG_IMSC_DCDMIM			(1 << 2)
+#define	UARTDBG_IMSC_CTSMIM			(1 << 1)
+#define	UARTDBG_IMSC_RIMIM			(1 << 0)
+
+#define	UARTDBG_RIS_OERIS			(1 << 10)
+#define	UARTDBG_RIS_BERIS			(1 << 9)
+#define	UARTDBG_RIS_PERIS			(1 << 8)
+#define	UARTDBG_RIS_FERIS			(1 << 7)
+#define	UARTDBG_RIS_RTRIS			(1 << 6)
+#define	UARTDBG_RIS_TXRIS			(1 << 5)
+#define	UARTDBG_RIS_RXRIS			(1 << 4)
+#define	UARTDBG_RIS_DSRRMIS			(1 << 3)
+#define	UARTDBG_RIS_DCDRMIS			(1 << 2)
+#define	UARTDBG_RIS_CTSRMIS			(1 << 1)
+#define	UARTDBG_RIS_RIRMIS			(1 << 0)
+
+#define	UARTDBG_MIS_OEMIS			(1 << 10)
+#define	UARTDBG_MIS_BEMIS			(1 << 9)
+#define	UARTDBG_MIS_PEMIS			(1 << 8)
+#define	UARTDBG_MIS_FEMIS			(1 << 7)
+#define	UARTDBG_MIS_RTMIS			(1 << 6)
+#define	UARTDBG_MIS_TXMIS			(1 << 5)
+#define	UARTDBG_MIS_RXMIS			(1 << 4)
+#define	UARTDBG_MIS_DSRMMIS			(1 << 3)
+#define	UARTDBG_MIS_DCDMMIS			(1 << 2)
+#define	UARTDBG_MIS_CTSMMIS			(1 << 1)
+#define	UARTDBG_MIS_RIMMIS			(1 << 0)
+
+#define	UARTDBG_ICR_OEIC			(1 << 10)
+#define	UARTDBG_ICR_BEIC			(1 << 9)
+#define	UARTDBG_ICR_PEIC			(1 << 8)
+#define	UARTDBG_ICR_FEIC			(1 << 7)
+#define	UARTDBG_ICR_RTIC			(1 << 6)
+#define	UARTDBG_ICR_TXIC			(1 << 5)
+#define	UARTDBG_ICR_RXIC			(1 << 4)
+#define	UARTDBG_ICR_DSRMIC			(1 << 3)
+#define	UARTDBG_ICR_DCDMIC			(1 << 2)
+#define	UARTDBG_ICR_CTSMIC			(1 << 1)
+#define	UARTDBG_ICR_RIMIC			(1 << 0)
+
+#define	UARTDBG_DMACR_DMAONERR			(1 << 2)
+#define	UARTDBG_DMACR_TXDMAE			(1 << 1)
+#define	UARTDBG_DMACR_RXDMAE			(1 << 0)
+
+#endif /* __REGS_UARTDBG_H__ */