Patchwork [U-Boot,v2,3/8] am33xx: NAND support

login
register
mail settings
Submitter Ilya Yanok
Date Nov. 6, 2012, 11:06 p.m.
Message ID <1352243195-64326-4-git-send-email-ilya.yanok@cogentembedded.com>
Download mbox | patch
Permalink /patch/197575/
State Accepted
Delegated to: Tom Rini
Headers show

Comments

Ilya Yanok - Nov. 6, 2012, 11:06 p.m.
TI AM33XX has the same GPMC controller as OMAP3 so we could just use the
existing omap_gpmc driver. This patch adds adds required
definitions/intialization.

Signed-off-by: Ilya Yanok <ilya.yanok@cogentembedded.com>

---
Changes in v2:
 - rebased on current master
 - clean up mem.c (remove unused stuff that was copied from OMAP3)
 - nand headers: remove unneeded stuff

 arch/arm/cpu/armv7/am33xx/Makefile           |    1 +
 arch/arm/cpu/armv7/am33xx/board.c            |    1 +
 arch/arm/cpu/armv7/am33xx/clock.c            |    5 ++
 arch/arm/cpu/armv7/am33xx/mem.c              |  101 ++++++++++++++++++++++
 arch/arm/include/asm/arch-am33xx/cpu.h       |   53 ++++++++++++
 arch/arm/include/asm/arch-am33xx/hardware.h  |    3 +
 arch/arm/include/asm/arch-am33xx/mem.h       |   83 ++++++++++++++++++
 arch/arm/include/asm/arch-am33xx/omap_gpmc.h |  120 ++++++++++++++++++++++++++
 arch/arm/include/asm/arch-am33xx/sys_proto.h |    3 +
 9 files changed, 370 insertions(+)
 create mode 100644 arch/arm/cpu/armv7/am33xx/mem.c
 create mode 100644 arch/arm/include/asm/arch-am33xx/mem.h
 create mode 100644 arch/arm/include/asm/arch-am33xx/omap_gpmc.h
Peter Korsgaard - Nov. 8, 2012, 9:33 a.m.
>>>>> "Ilya" == Ilya Yanok <ilya.yanok@cogentembedded.com> writes:

 Ilya> TI AM33XX has the same GPMC controller as OMAP3 so we could just use the
 Ilya> existing omap_gpmc driver. This patch adds adds required
 Ilya> definitions/intialization.

 Ilya> Signed-off-by: Ilya Yanok <ilya.yanok@cogentembedded.com>

..

 Ilya> +void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
 Ilya> +			u32 size)
 Ilya> +{
 Ilya> +	writel(0, &cs->config7);
 Ilya> +	sdelay(1000);
 Ilya> +	/* Delay for settling */

That comment should go above the delay.


 Ilya> +	writel(gpmc_config[0], &cs->config1);
 Ilya> +	writel(gpmc_config[1], &cs->config2);
 Ilya> +	writel(gpmc_config[2], &cs->config3);
 Ilya> +	writel(gpmc_config[3], &cs->config4);
 Ilya> +	writel(gpmc_config[4], &cs->config5);
 Ilya> +	writel(gpmc_config[5], &cs->config6);
 Ilya> +	/* Enable the config */
 Ilya> +	writel((((size & 0xF) << 8) | ((base >> 24) & 0x3F) |
 Ilya> +		(1 << 6)), &cs->config7);
 Ilya> +	sdelay(2000);

Any reason you now wait double as long?


 Ilya> +}
 Ilya> +
 Ilya> +/*****************************************************
 Ilya> + * gpmc_init(): init gpmc bus
 Ilya> + * Init GPMC for x16, MuxMode (SDRAM in x32).
 Ilya> + * This code can only be executed from SRAM or SDRAM.
 Ilya> + *****************************************************/
 Ilya> +void gpmc_init(void)
 Ilya> +{
 Ilya> +	/* putting a blanket check on GPMC based on ZeBu for now */
 Ilya> +	gpmc_cfg = (struct gpmc *)GPMC_BASE;
 Ilya> +
 Ilya> +#ifdef CONFIG_CMD_NAND
 Ilya> +	const u32 *gpmc_config = NULL;
 Ilya> +	u32 base = 0;
 Ilya> +	u32 size = 0;
 Ilya> +#endif
 Ilya> +	/* global settings */
 Ilya> +	writel(0x00000008, &gpmc_cfg->sysconfig);
 Ilya> +	writel(0x00000100, &gpmc_cfg->irqstatus);
 Ilya> +	writel(0x00000200, &gpmc_cfg->irqenable);
 Ilya> +	writel(0x00000012, &gpmc_cfg->config);
 Ilya> +	/*
 Ilya> +	 * Disable the GPMC0 config set by ROM code
 Ilya> +	 */
 Ilya> +	writel(0, &gpmc_cfg->cs[0].config7);
 Ilya> +	sdelay(1000);

Why? You already do this in enable_gpmc_cs_config().


 Ilya> +
 Ilya> +#ifdef CONFIG_CMD_NAND
 Ilya> +	gpmc_config = gpmc_m_nand;
 Ilya> +
 Ilya> +	base = PISMO1_NAND_BASE;
 Ilya> +	size = PISMO1_NAND_SIZE;
 Ilya> +	enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size);
 Ilya> +#endif
 Ilya> +}

 Ilya> +++ b/arch/arm/include/asm/arch-am33xx/mem.h
 Ilya> @@ -0,0 +1,83 @@
 Ilya> +/*
 Ilya> + * (C) Copyright 2006-2008
 Ilya> + * Texas Instruments, <www.ti.com>
 Ilya> + *
 Ilya> + * Author
 Ilya> + *		Mansoor Ahamed <mansoor.ahamed@ti.com>
 Ilya> + *
 Ilya> + * Initial Code from:
 Ilya> + *		Richard Woodruff <r-woodruff2@ti.com>
 Ilya> + *
 Ilya> + * See file CREDITS for list of people who contributed to this
 Ilya> + * project.
 Ilya> + *
 Ilya> + * This program is free software; you can redistribute it and/or
 Ilya> + * modify it under the terms of the GNU General Public License as
 Ilya> + * published by the Free Software Foundation; either version 2 of
 Ilya> + * the License, or (at your option) any later version.
 Ilya> + *
 Ilya> + * This program is distributed in the hope that it will be useful,
 Ilya> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 Ilya> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 Ilya> + * GNU General Public License for more details.
 Ilya> + *
 Ilya> + * You should have received a copy of the GNU General Public License
 Ilya> + * along with this program; if not, write to the Free Software
 Ilya> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 Ilya> + * MA 02111-1307 USA
 Ilya> + */
 Ilya> +
 Ilya> +#ifndef _MEM_H_
 Ilya> +#define _MEM_H_
 Ilya> +
 Ilya> +/*
 Ilya> + * GPMC settings -
 Ilya> + * Definitions is as per the following format
 Ilya> + * #define <PART>_GPMC_CONFIG<x> <value>
 Ilya> + * Where:
 Ilya> + * PART is the part name e.g. STNOR - Intel Strata Flash
 Ilya> + * x is GPMC config registers from 1 to 6 (there will be 6 macros)
 Ilya> + * Value is corresponding value
 Ilya> + *
 Ilya> + * For every valid PRCM configuration there should be only one definition of
 Ilya> + * the same. if values are independent of the board, this definition will be
 Ilya> + * present in this file if values are dependent on the board, then this should
 Ilya> + * go into corresponding mem-boardName.h file
 Ilya> + *
 Ilya> + * Currently valid part Names are (PART):
 Ilya> + * M_NAND - Micron NAND
 Ilya> + */
 Ilya> +#define GPMC_SIZE_256M		0x0
 Ilya> +#define GPMC_SIZE_128M		0x8
 Ilya> +#define GPMC_SIZE_64M		0xC
 Ilya> +#define GPMC_SIZE_32M		0xE
 Ilya> +#define GPMC_SIZE_16M		0xF
 Ilya> +
 Ilya> +#define M_NAND_GPMC_CONFIG1	0x00000800
 Ilya> +#define M_NAND_GPMC_CONFIG2	0x001e1e00
 Ilya> +#define M_NAND_GPMC_CONFIG3	0x001e1e00
 Ilya> +#define M_NAND_GPMC_CONFIG4	0x16051807
 Ilya> +#define M_NAND_GPMC_CONFIG5	0x00151e1e
 Ilya> +#define M_NAND_GPMC_CONFIG6	0x16000f80
 Ilya> +#define M_NAND_GPMC_CONFIG7	0x00000008

For what Micron part is this exactly? How about using the actual part
number in the define like we recently did for the DDR configuration?


 Ilya> +++ b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
 Ilya> @@ -0,0 +1,120 @@
 Ilya> +/*
 Ilya> + * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
 Ilya> + * Rohit Choraria <rohitkc@ti.com>
 Ilya> + *
 Ilya> + * See file CREDITS for list of people who contributed to this
 Ilya> + * project.
 Ilya> + *
 Ilya> + * This program is free software; you can redistribute it and/or
 Ilya> + * modify it under the terms of the GNU General Public License as
 Ilya> + * published by the Free Software Foundation; either version 2 of
 Ilya> + * the License, or (at your option) any later version.
 Ilya> + *
 Ilya> + * This program is distributed in the hope that it will be useful,
 Ilya> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 Ilya> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 Ilya> + * GNU General Public License for more details.
 Ilya> + *
 Ilya> + * You should have received a copy of the GNU General Public License
 Ilya> + * along with this program; if not, write to the Free Software
 Ilya> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 Ilya> + * MA 02111-1307 USA
 Ilya> + */
 Ilya> +#ifndef __ASM_ARCH_OMAP_GPMC_H
 Ilya> +#define __ASM_ARCH_OMAP_GPMC_H
 Ilya> +
 Ilya> +#define GPMC_BUF_EMPTY	0
 Ilya> +#define GPMC_BUF_FULL	1
 Ilya> +
 Ilya> +#define ECCCLEAR	(0x1 << 8)
 Ilya> +#define ECCRESULTREG1	(0x1 << 0)
 Ilya> +#define ECCSIZE512BYTE	0xFF
 Ilya> +#define ECCSIZE1	(ECCSIZE512BYTE << 22)
 Ilya> +#define ECCSIZE0	(ECCSIZE512BYTE << 12)
 Ilya> +#define ECCSIZE0SEL	(0x000 << 0)
 Ilya> +
 Ilya> +/* Generic ECC Layouts */
 Ilya> +/* Large Page x8 NAND device Layout */
 Ilya> +#ifdef GPMC_NAND_ECC_LP_x8_LAYOUT
 Ilya> +#define GPMC_NAND_HW_ECC_LAYOUT {\
 Ilya> +	.eccbytes = 12,\
 Ilya> +	.eccpos = {1, 2, 3, 4, 5, 6, 7, 8,\
 Ilya> +		9, 10, 11, 12},\
 Ilya> +	.oobfree = {\
 Ilya> +		{.offset = 13,\
 Ilya> +		 .length = 51 } } \
 Ilya> +}
 Ilya> +#endif
 Ilya> +
 Ilya> +/* Large Page x16 NAND device Layout */
 Ilya> +#ifdef GPMC_NAND_ECC_LP_x16_LAYOUT
 Ilya> +#define GPMC_NAND_HW_ECC_LAYOUT {\
 Ilya> +	.eccbytes = 12,\
 Ilya> +	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9,\
 Ilya> +		10, 11, 12, 13},\
 Ilya> +	.oobfree = {\
 Ilya> +		{.offset = 14,\
 Ilya> +		 .length = 50 } } \
 Ilya> +}
 Ilya> +#endif
 Ilya> +
 Ilya> +/* Small Page x8 NAND device Layout */
 Ilya> +#ifdef GPMC_NAND_ECC_SP_x8_LAYOUT
 Ilya> +#define GPMC_NAND_HW_ECC_LAYOUT {\
 Ilya> +	.eccbytes = 3,\
 Ilya> +	.eccpos = {1, 2, 3},\
 Ilya> +	.oobfree = {\
 Ilya> +		{.offset = 4,\
 Ilya> +		 .length = 12 } } \
 Ilya> +}
 Ilya> +#endif
 Ilya> +
 Ilya> +/* Small Page x16 NAND device Layout */
 Ilya> +#ifdef GPMC_NAND_ECC_SP_x16_LAYOUT
 Ilya> +#define GPMC_NAND_HW_ECC_LAYOUT {\
 Ilya> +	.eccbytes = 3,\
 Ilya> +	.eccpos = {2, 3, 4},\
 Ilya> +	.oobfree = {\
 Ilya> +		{.offset = 5,\
 Ilya> +		 .length = 11 } } \
 Ilya> +}
 Ilya> +#endif
 Ilya> +
 Ilya> +#define GPMC_NAND_HW_BCH4_ECC_LAYOUT {\
 Ilya> +	.eccbytes = 32,\
 Ilya> +	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
 Ilya> +				16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
 Ilya> +				28, 29, 30, 31, 32, 33},\
 Ilya> +	.oobfree = {\
 Ilya> +		{.offset = 34,\
 Ilya> +		 .length = 30 } } \
 Ilya> +}
 Ilya> +
 Ilya> +#define GPMC_NAND_HW_BCH8_ECC_LAYOUT {\
 Ilya> +	.eccbytes = 56,\
 Ilya> +	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
 Ilya> +				16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
 Ilya> +				28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\
 Ilya> +				40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\
 Ilya> +				52, 53, 54, 55, 56, 57},\
 Ilya> +	.oobfree = {\
 Ilya> +		{.offset = 58,\
 Ilya> +		 .length = 6 } } \
 Ilya> +}
 Ilya> +
 Ilya> +#define GPMC_NAND_HW_BCH16_ECC_LAYOUT {\
 Ilya> +	.eccbytes = 104,\
 Ilya> +	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
 Ilya> +				16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
 Ilya> +				28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\
 Ilya> +				40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\
 Ilya> +				52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\
 Ilya> +				64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,\
 Ilya> +				76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,\
 Ilya> +				88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\
 Ilya> +				100, 101, 102, 103, 104, 105},\
 Ilya> +	.oobfree = {\
 Ilya> +		{.offset = 106,\
 Ilya> +		 .length = 8 } } \
 Ilya> +}
 Ilya> +#endif /* __ASM_ARCH_OMAP_GPMC_H */


Do the non-BCH layouts make sense for am33xx? I've noticed that the TRM
shows the BCH8 format as 13 bytes/256 tightly packed instead of 14, but
that's wrong. I'll report it to the doc people.
Ilya Yanok - Nov. 15, 2012, 8:21 p.m.
Hi Peter,

On Thu, Nov 8, 2012 at 10:33 AM, Peter Korsgaard <jacmet@sunsite.dk> wrote:

>  Ilya> +void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs
> *cs, u32 base,
>  Ilya> +                        u32 size)
>  Ilya> +{
>  Ilya> +        writel(0, &cs->config7);
>  Ilya> +        sdelay(1000);
>  Ilya> +        /* Delay for settling */
>
> That comment should go above the delay.
>

Ok, will fix.


>   Ilya> +        writel(gpmc_config[0], &cs->config1);
>  Ilya> +        writel(gpmc_config[1], &cs->config2);
>  Ilya> +        writel(gpmc_config[2], &cs->config3);
>  Ilya> +        writel(gpmc_config[3], &cs->config4);
>  Ilya> +        writel(gpmc_config[4], &cs->config5);
>  Ilya> +        writel(gpmc_config[5], &cs->config6);
>  Ilya> +        /* Enable the config */
>  Ilya> +        writel((((size & 0xF) << 8) | ((base >> 24) & 0x3F) |
>  Ilya> +                (1 << 6)), &cs->config7);
>  Ilya> +        sdelay(2000);
>
> Any reason you now wait double as long?
>

No idea ;) To tell the truth I've taken all this code from omap3 as is.


>  Ilya> +}
>  Ilya> +
>  Ilya> +/*****************************************************
>  Ilya> + * gpmc_init(): init gpmc bus
>  Ilya> + * Init GPMC for x16, MuxMode (SDRAM in x32).
>  Ilya> + * This code can only be executed from SRAM or SDRAM.
>  Ilya> + *****************************************************/
>  Ilya> +void gpmc_init(void)
>  Ilya> +{
>  Ilya> +        /* putting a blanket check on GPMC based on ZeBu for now */
>  Ilya> +        gpmc_cfg = (struct gpmc *)GPMC_BASE;
>  Ilya> +
>  Ilya> +#ifdef CONFIG_CMD_NAND
>  Ilya> +        const u32 *gpmc_config = NULL;
>  Ilya> +        u32 base = 0;
>  Ilya> +        u32 size = 0;
>  Ilya> +#endif
>  Ilya> +        /* global settings */
>  Ilya> +        writel(0x00000008, &gpmc_cfg->sysconfig);
>  Ilya> +        writel(0x00000100, &gpmc_cfg->irqstatus);
>  Ilya> +        writel(0x00000200, &gpmc_cfg->irqenable);
>  Ilya> +        writel(0x00000012, &gpmc_cfg->config);
>  Ilya> +        /*
>  Ilya> +         * Disable the GPMC0 config set by ROM code
>  Ilya> +         */
>  Ilya> +        writel(0, &gpmc_cfg->cs[0].config7);
>  Ilya> +        sdelay(1000);
>
> Why? You already do this in enable_gpmc_cs_config().
>

Hm... Again, I'm not the one who written this code, I just stole it ;)
but probably the idea was to disable the config even in case of
CONFIG_CMD_NAND undefined...


>  Ilya> +
>  Ilya> +#ifdef CONFIG_CMD_NAND
>  Ilya> +        gpmc_config = gpmc_m_nand;
>  Ilya> +
>  Ilya> +        base = PISMO1_NAND_BASE;
>  Ilya> +        size = PISMO1_NAND_SIZE;
>  Ilya> +        enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base,
> size);
>  Ilya> +#endif
>  Ilya> +}
>
>  Ilya> +#define M_NAND_GPMC_CONFIG1     0x00000800
>  Ilya> +#define M_NAND_GPMC_CONFIG2     0x001e1e00
>  Ilya> +#define M_NAND_GPMC_CONFIG3     0x001e1e00
>  Ilya> +#define M_NAND_GPMC_CONFIG4     0x16051807
>  Ilya> +#define M_NAND_GPMC_CONFIG5     0x00151e1e
>  Ilya> +#define M_NAND_GPMC_CONFIG6     0x16000f80
>  Ilya> +#define M_NAND_GPMC_CONFIG7     0x00000008
>
> For what Micron part is this exactly? How about using the actual part
> number in the define like we recently did for the DDR configuration?
>

Ok, I'll try to figure that out from schematics.

Do the non-BCH layouts make sense for am33xx? I've noticed that the TRM
> shows the BCH8 format as 13 bytes/256 tightly packed instead of 14, but
> that's wrong. I'll report it to the doc people.
>

Hm. Non-BCH layouts was here because I initially planned to support nandecc
command to switch between supported ECC schemas... But as Tom requested to
remove it I guess we don't need these layouts any more...
Well, my idea was to make separate patches (one to just support existing
omap_gpmc driver on AM33xx and one to add BCH8 support) and this kinda
needs non-BCH layouts too... but I guess I should just squash the patches
into one.

Thanks for the review.

Regards, Ilya.
Peter Korsgaard - Nov. 15, 2012, 10:26 p.m.
>>>>> "Ilya" == Ilya Yanok <ilya.yanok@cogentembedded.com> writes:

Hi,

 Peter>     Why? You already do this in enable_gpmc_cs_config().

 Ilya> Hm... Again, I'm not the one who written this code, I just stole
 Ilya> it ;) but probably the idea was to disable the config even in
 Ilya> case of CONFIG_CMD_NAND undefined...

Why would you want to do that? I don't see a reason for touching the
GPMC if you're not going to use it.


 Ilya>      Ilya> +#define M_NAND_GPMC_CONFIG1     0x00000800
 Ilya>      Ilya> +#define M_NAND_GPMC_CONFIG2     0x001e1e00
 Ilya>      Ilya> +#define M_NAND_GPMC_CONFIG3     0x001e1e00
 Ilya>      Ilya> +#define M_NAND_GPMC_CONFIG4     0x16051807
 Ilya>      Ilya> +#define M_NAND_GPMC_CONFIG5     0x00151e1e
 Ilya>      Ilya> +#define M_NAND_GPMC_CONFIG6     0x16000f80
 Ilya>      Ilya> +#define M_NAND_GPMC_CONFIG7     0x00000008

 Peter>    For what Micron part is this exactly? How about using the actual part
 Peter>    number in the define like we recently did for the DDR configuration?


 Ilya> Ok, I'll try to figure that out from schematics.

Great, thanks. The choice of GPMC configuration values should also be
moved to board code, similar to how I did it for DDR.


 Peter>   Do the non-BCH layouts make sense for am33xx? I've noticed
 Peter>   that the TRM shows the BCH8 format as 13 bytes/256 tightly
 Peter>   packed instead of 14, but that's wrong. I'll report it to the
 Peter>   doc people.


 Ilya> Hm. Non-BCH layouts was here because I initially planned to
 Ilya> support nandecc command to switch between supported ECC
 Ilya> schemas... But as Tom requested to remove it I guess we don't
 Ilya> need these layouts any more...  Well, my idea was to make
 Ilya> separate patches (one to just support existing omap_gpmc driver
 Ilya> on AM33xx and one to add BCH8 support) and this kinda needs
 Ilya> non-BCH layouts too... but I guess I should just squash the
 Ilya> patches into one.

I don't think non-BCH makes much sense on am33xx considering the ROM
uses/requires BCH8.

 Ilya> Thanks for the review.

You're welcome.
Tom Rini - Nov. 21, 2012, 4:59 p.m.
On Thu, Nov 15, 2012 at 11:26:59PM +0100, Peter Korsgaard wrote:
>  Ilya> Hm. Non-BCH layouts was here because I initially planned to
>  Ilya> support nandecc command to switch between supported ECC
>  Ilya> schemas... But as Tom requested to remove it I guess we don't
>  Ilya> need these layouts any more...  Well, my idea was to make
>  Ilya> separate patches (one to just support existing omap_gpmc driver
>  Ilya> on AM33xx and one to add BCH8 support) and this kinda needs
>  Ilya> non-BCH layouts too... but I guess I should just squash the
>  Ilya> patches into one.
> 
> I don't think non-BCH makes much sense on am33xx considering the ROM
> uses/requires BCH8.

Long term (not today tho) we need to support BCH16 as well since the ROM
requires BCH16 on some parts and BCH8 on others.  We can cross that
bridge when we come to it, however.

Patch

diff --git a/arch/arm/cpu/armv7/am33xx/Makefile b/arch/arm/cpu/armv7/am33xx/Makefile
index 74875b3..f565357 100644
--- a/arch/arm/cpu/armv7/am33xx/Makefile
+++ b/arch/arm/cpu/armv7/am33xx/Makefile
@@ -18,6 +18,7 @@  LIB	= $(obj)lib$(SOC).o
 
 COBJS	+= clock.o
 COBJS	+= sys_info.o
+COBJS	+= mem.o
 COBJS	+= ddr.o
 COBJS	+= emif4.o
 COBJS	+= board.o
diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c
index e4c123c..c756c09 100644
--- a/arch/arm/cpu/armv7/am33xx/board.c
+++ b/arch/arm/cpu/armv7/am33xx/board.c
@@ -25,6 +25,7 @@ 
 #include <asm/arch/ddr_defs.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/mem.h>
 #include <asm/arch/mmc_host_def.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/io.h>
diff --git a/arch/arm/cpu/armv7/am33xx/clock.c b/arch/arm/cpu/armv7/am33xx/clock.c
index bc2abb6..6eb7d9f 100644
--- a/arch/arm/cpu/armv7/am33xx/clock.c
+++ b/arch/arm/cpu/armv7/am33xx/clock.c
@@ -150,6 +150,11 @@  static void enable_per_clocks(void)
 		;
 #endif /* CONFIG_SERIAL6 */
 
+	/* GPMC */
+	writel(PRCM_MOD_EN, &cmper->gpmcclkctrl);
+	while (readl(&cmper->gpmcclkctrl) != PRCM_MOD_EN)
+		;
+
 	/* MMC0*/
 	writel(PRCM_MOD_EN, &cmper->mmc0clkctrl);
 	while (readl(&cmper->mmc0clkctrl) != PRCM_MOD_EN)
diff --git a/arch/arm/cpu/armv7/am33xx/mem.c b/arch/arm/cpu/armv7/am33xx/mem.c
new file mode 100644
index 0000000..b8f54ab
--- /dev/null
+++ b/arch/arm/cpu/armv7/am33xx/mem.c
@@ -0,0 +1,101 @@ 
+/*
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *
+ * Author :
+ *     Mansoor Ahamed <mansoor.ahamed@ti.com>
+ *
+ * Initial Code from:
+ *     Manikandan Pillai <mani.pillai@ti.com>
+ *     Richard Woodruff <r-woodruff2@ti.com>
+ *     Syed Mohammed Khasim <khasim@ti.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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/mem.h>
+#include <asm/arch/sys_proto.h>
+#include <command.h>
+
+struct gpmc *gpmc_cfg;
+
+#if defined(CONFIG_CMD_NAND)
+static const u32 gpmc_m_nand[GPMC_MAX_REG] = {
+	M_NAND_GPMC_CONFIG1,
+	M_NAND_GPMC_CONFIG2,
+	M_NAND_GPMC_CONFIG3,
+	M_NAND_GPMC_CONFIG4,
+	M_NAND_GPMC_CONFIG5,
+	M_NAND_GPMC_CONFIG6, 0
+};
+#endif
+
+
+void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
+			u32 size)
+{
+	writel(0, &cs->config7);
+	sdelay(1000);
+	/* Delay for settling */
+	writel(gpmc_config[0], &cs->config1);
+	writel(gpmc_config[1], &cs->config2);
+	writel(gpmc_config[2], &cs->config3);
+	writel(gpmc_config[3], &cs->config4);
+	writel(gpmc_config[4], &cs->config5);
+	writel(gpmc_config[5], &cs->config6);
+	/* Enable the config */
+	writel((((size & 0xF) << 8) | ((base >> 24) & 0x3F) |
+		(1 << 6)), &cs->config7);
+	sdelay(2000);
+}
+
+/*****************************************************
+ * gpmc_init(): init gpmc bus
+ * Init GPMC for x16, MuxMode (SDRAM in x32).
+ * This code can only be executed from SRAM or SDRAM.
+ *****************************************************/
+void gpmc_init(void)
+{
+	/* putting a blanket check on GPMC based on ZeBu for now */
+	gpmc_cfg = (struct gpmc *)GPMC_BASE;
+
+#ifdef CONFIG_CMD_NAND
+	const u32 *gpmc_config = NULL;
+	u32 base = 0;
+	u32 size = 0;
+#endif
+	/* global settings */
+	writel(0x00000008, &gpmc_cfg->sysconfig);
+	writel(0x00000100, &gpmc_cfg->irqstatus);
+	writel(0x00000200, &gpmc_cfg->irqenable);
+	writel(0x00000012, &gpmc_cfg->config);
+	/*
+	 * Disable the GPMC0 config set by ROM code
+	 */
+	writel(0, &gpmc_cfg->cs[0].config7);
+	sdelay(1000);
+
+#ifdef CONFIG_CMD_NAND
+	gpmc_config = gpmc_m_nand;
+
+	base = PISMO1_NAND_BASE;
+	size = PISMO1_NAND_SIZE;
+	enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size);
+#endif
+}
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index 819fd2f..b91441f 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -60,6 +60,59 @@ 
 
 #ifndef __KERNEL_STRICT_NAMES
 #ifndef __ASSEMBLY__
+struct gpmc_cs {
+	u32 config1;		/* 0x00 */
+	u32 config2;		/* 0x04 */
+	u32 config3;		/* 0x08 */
+	u32 config4;		/* 0x0C */
+	u32 config5;		/* 0x10 */
+	u32 config6;		/* 0x14 */
+	u32 config7;		/* 0x18 */
+	u32 nand_cmd;		/* 0x1C */
+	u32 nand_adr;		/* 0x20 */
+	u32 nand_dat;		/* 0x24 */
+	u8 res[8];		/* blow up to 0x30 byte */
+};
+
+struct bch_res_0_3 {
+	u32 bch_result_x[4];
+};
+
+struct gpmc {
+	u8 res1[0x10];
+	u32 sysconfig;		/* 0x10 */
+	u8 res2[0x4];
+	u32 irqstatus;		/* 0x18 */
+	u32 irqenable;		/* 0x1C */
+	u8 res3[0x20];
+	u32 timeout_control;	/* 0x40 */
+	u8 res4[0xC];
+	u32 config;		/* 0x50 */
+	u32 status;		/* 0x54 */
+	u8 res5[0x8];		/* 0x58 */
+	struct gpmc_cs cs[8];	/* 0x60, 0x90, .. */
+	u8 res6[0x14];		/* 0x1E0 */
+	u32 ecc_config;		/* 0x1F4 */
+	u32 ecc_control;	/* 0x1F8 */
+	u32 ecc_size_config;	/* 0x1FC */
+	u32 ecc1_result;	/* 0x200 */
+	u32 ecc2_result;	/* 0x204 */
+	u32 ecc3_result;	/* 0x208 */
+	u32 ecc4_result;	/* 0x20C */
+	u32 ecc5_result;	/* 0x210 */
+	u32 ecc6_result;	/* 0x214 */
+	u32 ecc7_result;	/* 0x218 */
+	u32 ecc8_result;	/* 0x21C */
+	u32 ecc9_result;	/* 0x220 */
+	u8 res7[12];		/* 0x224 */
+	u32 testmomde_ctrl;	/* 0x230 */
+	u8 res8[12];		/* 0x234 */
+	struct bch_res_0_3 bch_result_0_3[2];	/* 0x240 */
+};
+
+/* Used for board specific gpmc initialization */
+extern struct gpmc *gpmc_cfg;
+
 /* Encapsulating core pll registers */
 struct cm_wkuppll {
 	unsigned int wkclkstctrl;	/* offset 0x00 */
diff --git a/arch/arm/include/asm/arch-am33xx/hardware.h b/arch/arm/include/asm/arch-am33xx/hardware.h
index 5bd4bc8..b3922d9 100644
--- a/arch/arm/include/asm/arch-am33xx/hardware.h
+++ b/arch/arm/include/asm/arch-am33xx/hardware.h
@@ -80,6 +80,9 @@ 
 #define DDRPHY_0_CONFIG_BASE		(CTRL_BASE + 0x1400)
 #define DDRPHY_CONFIG_BASE		DDRPHY_0_CONFIG_BASE
 
+/* GPMC Base address */
+#define GPMC_BASE			0x50000000
+
 /* CPSW Config space */
 #define AM335X_CPSW_BASE		0x4A100000
 #define AM335X_CPSW_MDIO_BASE		0x4A101000
diff --git a/arch/arm/include/asm/arch-am33xx/mem.h b/arch/arm/include/asm/arch-am33xx/mem.h
new file mode 100644
index 0000000..c3bf74e
--- /dev/null
+++ b/arch/arm/include/asm/arch-am33xx/mem.h
@@ -0,0 +1,83 @@ 
+/*
+ * (C) Copyright 2006-2008
+ * Texas Instruments, <www.ti.com>
+ *
+ * Author
+ *		Mansoor Ahamed <mansoor.ahamed@ti.com>
+ *
+ * Initial Code from:
+ *		Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * 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
+ */
+
+#ifndef _MEM_H_
+#define _MEM_H_
+
+/*
+ * GPMC settings -
+ * Definitions is as per the following format
+ * #define <PART>_GPMC_CONFIG<x> <value>
+ * Where:
+ * PART is the part name e.g. STNOR - Intel Strata Flash
+ * x is GPMC config registers from 1 to 6 (there will be 6 macros)
+ * Value is corresponding value
+ *
+ * For every valid PRCM configuration there should be only one definition of
+ * the same. if values are independent of the board, this definition will be
+ * present in this file if values are dependent on the board, then this should
+ * go into corresponding mem-boardName.h file
+ *
+ * Currently valid part Names are (PART):
+ * M_NAND - Micron NAND
+ */
+#define GPMC_SIZE_256M		0x0
+#define GPMC_SIZE_128M		0x8
+#define GPMC_SIZE_64M		0xC
+#define GPMC_SIZE_32M		0xE
+#define GPMC_SIZE_16M		0xF
+
+#define M_NAND_GPMC_CONFIG1	0x00000800
+#define M_NAND_GPMC_CONFIG2	0x001e1e00
+#define M_NAND_GPMC_CONFIG3	0x001e1e00
+#define M_NAND_GPMC_CONFIG4	0x16051807
+#define M_NAND_GPMC_CONFIG5	0x00151e1e
+#define M_NAND_GPMC_CONFIG6	0x16000f80
+#define M_NAND_GPMC_CONFIG7	0x00000008
+
+/* max number of GPMC Chip Selects */
+#define GPMC_MAX_CS		8
+/* max number of GPMC regs */
+#define GPMC_MAX_REG		7
+
+#define PISMO1_NOR		1
+#define PISMO1_NAND		2
+#define PISMO2_CS0		3
+#define PISMO2_CS1		4
+#define PISMO1_ONENAND		5
+#define DBG_MPDB		6
+#define PISMO2_NAND_CS0		7
+#define PISMO2_NAND_CS1		8
+
+/* make it readable for the gpmc_init */
+#define PISMO1_NOR_BASE	FLASH_BASE
+#define PISMO1_NAND_BASE	CONFIG_SYS_NAND_BASE
+#define PISMO1_NAND_SIZE	GPMC_SIZE_256M
+
+#endif /* endif _MEM_H_ */
diff --git a/arch/arm/include/asm/arch-am33xx/omap_gpmc.h b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
new file mode 100644
index 0000000..572f9d0
--- /dev/null
+++ b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
@@ -0,0 +1,120 @@ 
+/*
+ * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
+ * Rohit Choraria <rohitkc@ti.com>
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_OMAP_GPMC_H
+#define __ASM_ARCH_OMAP_GPMC_H
+
+#define GPMC_BUF_EMPTY	0
+#define GPMC_BUF_FULL	1
+
+#define ECCCLEAR	(0x1 << 8)
+#define ECCRESULTREG1	(0x1 << 0)
+#define ECCSIZE512BYTE	0xFF
+#define ECCSIZE1	(ECCSIZE512BYTE << 22)
+#define ECCSIZE0	(ECCSIZE512BYTE << 12)
+#define ECCSIZE0SEL	(0x000 << 0)
+
+/* Generic ECC Layouts */
+/* Large Page x8 NAND device Layout */
+#ifdef GPMC_NAND_ECC_LP_x8_LAYOUT
+#define GPMC_NAND_HW_ECC_LAYOUT {\
+	.eccbytes = 12,\
+	.eccpos = {1, 2, 3, 4, 5, 6, 7, 8,\
+		9, 10, 11, 12},\
+	.oobfree = {\
+		{.offset = 13,\
+		 .length = 51 } } \
+}
+#endif
+
+/* Large Page x16 NAND device Layout */
+#ifdef GPMC_NAND_ECC_LP_x16_LAYOUT
+#define GPMC_NAND_HW_ECC_LAYOUT {\
+	.eccbytes = 12,\
+	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9,\
+		10, 11, 12, 13},\
+	.oobfree = {\
+		{.offset = 14,\
+		 .length = 50 } } \
+}
+#endif
+
+/* Small Page x8 NAND device Layout */
+#ifdef GPMC_NAND_ECC_SP_x8_LAYOUT
+#define GPMC_NAND_HW_ECC_LAYOUT {\
+	.eccbytes = 3,\
+	.eccpos = {1, 2, 3},\
+	.oobfree = {\
+		{.offset = 4,\
+		 .length = 12 } } \
+}
+#endif
+
+/* Small Page x16 NAND device Layout */
+#ifdef GPMC_NAND_ECC_SP_x16_LAYOUT
+#define GPMC_NAND_HW_ECC_LAYOUT {\
+	.eccbytes = 3,\
+	.eccpos = {2, 3, 4},\
+	.oobfree = {\
+		{.offset = 5,\
+		 .length = 11 } } \
+}
+#endif
+
+#define GPMC_NAND_HW_BCH4_ECC_LAYOUT {\
+	.eccbytes = 32,\
+	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
+				16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
+				28, 29, 30, 31, 32, 33},\
+	.oobfree = {\
+		{.offset = 34,\
+		 .length = 30 } } \
+}
+
+#define GPMC_NAND_HW_BCH8_ECC_LAYOUT {\
+	.eccbytes = 56,\
+	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
+				16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
+				28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\
+				40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\
+				52, 53, 54, 55, 56, 57},\
+	.oobfree = {\
+		{.offset = 58,\
+		 .length = 6 } } \
+}
+
+#define GPMC_NAND_HW_BCH16_ECC_LAYOUT {\
+	.eccbytes = 104,\
+	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
+				16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
+				28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\
+				40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\
+				52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\
+				64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,\
+				76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,\
+				88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\
+				100, 101, 102, 103, 104, 105},\
+	.oobfree = {\
+		{.offset = 106,\
+		 .length = 8 } } \
+}
+#endif /* __ASM_ARCH_OMAP_GPMC_H */
diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
index 9cf35e0..588d8de 100644
--- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
@@ -33,4 +33,7 @@  u32 get_device_type(void);
 void setup_clocks_for_console(void);
 void ddr_pll_config(unsigned int ddrpll_M);
 
+void sdelay(unsigned long);
+void gpmc_init(void);
+void omap_nand_switch_ecc(int);
 #endif