Patch series to add OMAP3 EVM support to Sakoman's u-boot Tree

85 views
Skip to first unread message

Pillai, Manikandan

unread,
Jul 17, 2008, 3:12:52 AM7/17/08
to discu...@beagleboard.org
Hi all,

I started working on getting OMAP3 EVM support on u-boot GIT, but later realized that similar development was on going for Beagle. I thought of working with you guys for getting EVM support on Sakoman's u-boot GIT branch and then do the additional cleanup and help in getting EVM and Beagle support on u-boot V1 GIT tree.

As part of my work, I am here by presenting a set of three patches that add EVM support to Sakoman's u-boot, kindly review the same and if no issues found I would request Sakoman to merge this onto his branch. Will continue my development on this branch further

Regards,
Mani

Dirk Behme

unread,
Jul 17, 2008, 10:50:46 AM7/17/08
to Pillai, Manikandan, Syed Mohammed, Khasim, beagl...@googlegroups.com
Pillai, Manikandan wrote:
> I started working on getting OMAP3 EVM support on u-boot GIT, but later realized that similar
> development was on going for Beagle. I thought of working with you guys for getting EVM
> support on Sakoman's u-boot GIT branch and then do the additional cleanup and help in
> getting EVM and Beagle support on u-boot V1 GIT tree.

This sounds really great! Yes, we really need some additional help for
cleanup. Maybe you already know the short status I wrote some days ago
about Sakoman's u-boot GIT branch:

http://groups.google.com/group/beagleboard/browse_thread/thread/0f1991bbc9318fe0#

For the archives: Sakoman's u-boot GIT we talk about here can be found at

http://www.sakoman.net/cgi-bin/gitweb.cgi?p=u-boot-omap3.git;a=summary

> As part of my work, I am here by presenting a set of three patches that add EVM support to Sakoman's u-boot, kindly review

I will do so, give me some days ;)

To answer some more points from today's IRC:

- Additional board support, e.g. Pandora: Yes, this is welcome. While
starting it will be some more work, but having e.g. three boards (e.g.
Beagle, EVM and Pandora) will really help us to identify common code
and let us optimize for future boards.

- Compiler: Yes, CSL 2008Q1 results in uboot I2C timeouts. So use
007Q3/Q1 for uboot. I observed this, too.

Mani and Khasim: At IRC it sounds like you are looking into this. If
you have an idea, please let us know.

> the same and if no issues found I would request Sakoman to merge this onto his branch. Will continue my development on this branch further

Many thanks for your patches

Dirk

sakoman

unread,
Jul 17, 2008, 6:43:21 PM7/17/08
to Beagle Board
Mani,

Thanks for the patches! Unfortunately I ran into a lot of the same
issues that Dirk did.

Could you run your patches through the kernel checkpatch script and
fix the things it complains about?

Passing checkpatch makes it much easier to ensure a clean merge on my
end. Otherwise I have to start doing hand edits and the odds of
messing something up increase ;-)

Thanks again!

Steve

Pillai, Manikandan

unread,
Jul 23, 2008, 11:33:07 PM7/23/08
to beagl...@googlegroups.com

Hi all,

 

I am re-sending the patch (1/3) for support of EVM boards. Since I had issues with earlier mail on the format, I am

sending this one as as attachments. I have run the checkpatch scripts and fixed the relevant warnings.

 

Pls let me know your comments. I will be sending the remaining two patches by today evening.

 

Regards

Mani

u-boot-omap3-p1.txt

Dirk Behme

unread,
Jul 24, 2008, 10:51:10 AM7/24/08
to beagl...@googlegroups.com
Hi Mani,

Pillai, Manikandan wrote:
> Hi all,
>
> I am re-sending the patch (1/3) for support of EVM boards. Since I had
> issues with earlier mail on the format, I am
>
> sending this one as as attachments.

Attachments are fine on this list, better than having reformats by
some mail tools. We are not uboot here ;)

>I have run the checkpatch scripts
> and fixed the relevant warnings.
>
> Pls let me know your comments. I will be sending the remaining two
> patches by today evening.

Many thanks!

As usual, give us some days to have a look.

Dirk

> ---------- Forwarded message ----------
> From: *sakoman* <sak...@gmail.com <mailto:sak...@gmail.com>>
> Date: Jul 18, 2008 4:13 AM
> Subject: [beagleboard] Re: Patch series to add OMAP3 EVM support to
> Sakoman's u-boot Tree
> To: Beagle Board <beagl...@googlegroups.com
> <mailto:beagl...@googlegroups.com>>
>
>
> Mani,
>
> Thanks for the patches! Unfortunately I ran into a lot of the same
> issues that Dirk did.
>
> Could you run your patches through the kernel checkpatch script and
> fix the things it complains about?
>
> Passing checkpatch makes it much easier to ensure a clean merge on my
> end. Otherwise I have to start doing hand edits and the odds of
> messing something up increase ;-)
>
> Thanks again!
>
> Steve
>
>
> On Jul 17, 12:12 am, "Pillai, Manikandan" <mani.pil...@ti.com

> <mailto:mani.pil...@ti.com>> wrote:
>> Hi all,
>>
>> I started working on getting OMAP3 EVM support on u-boot GIT, but
> later realized that similar development was on going for Beagle. I
> thought of working with you guys for getting EVM support on Sakoman's
> u-boot GIT branch and then do the additional cleanup and help in getting
> EVM and Beagle support on u-boot V1 GIT tree.
>>
>> As part of my work, I am here by presenting a set of three patches
> that add EVM support to Sakoman's u-boot, kindly review the same and if
> no issues found I would request Sakoman to merge this onto his branch.
> Will continue my development on this branch further
>>
>> Regards,
>> Mani
>
>
>
> >
>

> ------------------------------------------------------------------------
>
> From d8f34bafcf60e1e7a607033b682c08ef15d92267 Mon Sep 17 00:00:00 2001
> From: Manikandan Karunakaran Pillai <a0393249@gitsvr01.(none)>
> Date: Wed, 23 Jul 2008 15:06:44 +0530
> Subject: [PATCH] Files added to support Patch 1 for support to OMAP3EVM.
> Please enter the commit message for your changes.
>
>
> Signed-off-by: Manikandan Karunakaran Pillai <mani....@ti.com>
> ---
> Makefile | 3 +
> board/omap3evm/Makefile | 47 +++++
> board/omap3evm/clock.c | 313 ++++++++++++++++++++++++++++++
> board/omap3evm/config.mk | 17 ++
> board/omap3evm/lowlevel_init.S | 360 +++++++++++++++++++++++++++++++++++
> board/omap3evm/mem.c | 288 ++++++++++++++++++++++++++++
> board/omap3evm/nand.c | 408 ++++++++++++++++++++++++++++++++++++++++
> board/omap3evm/omap3evm.c | 389 ++++++++++++++++++++++++++++++++++++++
> board/omap3evm/sys_info.c | 312 ++++++++++++++++++++++++++++++
> board/omap3evm/syslib.c | 76 ++++++++
> board/omap3evm/u-boot.lds | 63 ++++++
> include/configs/omap3evm.h | 299 +++++++++++++++++++++++++++++
> 12 files changed, 2575 insertions(+), 0 deletions(-)
> create mode 100644 board/omap3evm/Makefile
> create mode 100644 board/omap3evm/clock.c
> create mode 100644 board/omap3evm/config.mk
> create mode 100644 board/omap3evm/lowlevel_init.S
> create mode 100644 board/omap3evm/mem.c
> create mode 100644 board/omap3evm/nand.c
> create mode 100644 board/omap3evm/omap3evm.c
> create mode 100644 board/omap3evm/sys_info.c
> create mode 100644 board/omap3evm/syslib.c
> create mode 100644 board/omap3evm/u-boot.lds
> create mode 100644 include/configs/omap3evm.h
>
> diff --git a/Makefile b/Makefile
> index e9bf61a..bc6da92 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -2570,6 +2570,9 @@ SMN42_config : unconfig
> omap3530beagle_config : unconfig
> @./mkconfig $(@:_config=) arm omap3 omap3530beagle
>
> +omap3evm_config : unconfig
> + @./mkconfig $(@:_config=) arm omap3 omap3evm
> +
> #########################################################################
> ## XScale Systems
> #########################################################################
> diff --git a/board/omap3evm/Makefile b/board/omap3evm/Makefile
> new file mode 100644
> index 0000000..e8b68dc
> --- /dev/null
> +++ b/board/omap3evm/Makefile
> @@ -0,0 +1,47 @@
> +#
> +# (C) Copyright 2000, 2001, 2002
> +# Wolfgang Denk, DENX Software Engineering, w...@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 = lib$(BOARD).a
> +
> +OBJS := omap3evm.o mem.o clock.o syslib.o sys_info.o nand.o
> +SOBJS := lowlevel_init.o
> +
> +$(LIB): $(OBJS) $(SOBJS)
> + $(AR) crv $@ $^
> +
> +clean:
> + rm -f $(SOBJS) $(OBJS)
> +
> +distclean: clean
> + rm -f $(LIB) core *.bak .depend
> +
> +#########################################################################
> +
> +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
> + $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
> +
> +-include .depend
> +
> +#########################################################################
> diff --git a/board/omap3evm/clock.c b/board/omap3evm/clock.c
> new file mode 100644
> index 0000000..9e97770
> --- /dev/null
> +++ b/board/omap3evm/clock.c
> @@ -0,0 +1,313 @@
> +/*
> + * (C) Copyright 2008
> + * Texas Instruments, <www.ti.com>
> + *
> + * Author :
> + * Manikandan Pillai <mani....@ti.com>
> + *
> + * Derived from Beagle Board and OMAP3 SDP code by
> + * Richard Woodruff <r-woo...@ti.com>
> + * Syed Mohammed Khasim <kha...@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/bits.h>
> +#include <asm/arch/clocks.h>
> +#include <asm/arch/clocks_omap3.h>
> +#include <asm/arch/mem.h>
> +#include <asm/arch/sys_proto.h>
> +#include <environment.h>
> +#include <command.h>
> +
> +/******************************************************************************
> + * get_sys_clk_speed() - determine reference oscillator speed
> + * based on known 32kHz clock and gptimer.
> + *****************************************************************************/
> +u32 get_osc_clk_speed(void)
> +{
> + u32 start, cstart, cend, cdiff, val;
> +
> + val = __raw_readl(PRM_CLKSRC_CTRL);
> +
> + /* If SYS_CLK is being divided by 2, remove for now */
> + val = (val & (~BIT7)) | BIT6;
> + __raw_writel(val, PRM_CLKSRC_CTRL);
> +
> + /* enable timer2 */
> + val = __raw_readl(CM_CLKSEL_WKUP) | BIT0;
> + __raw_writel(val, CM_CLKSEL_WKUP); /* select sys_clk for GPT1 */
> +
> + /* Enable I and F Clocks for GPT1 */
> + val = __raw_readl(CM_ICLKEN_WKUP) | BIT0 | BIT2;
> + __raw_writel(val, CM_ICLKEN_WKUP);
> + val = __raw_readl(CM_FCLKEN_WKUP) | BIT0;
> + __raw_writel(val, CM_FCLKEN_WKUP);
> +
> + __raw_writel(0, OMAP34XX_GPT1 + TLDR); /* start counting at 0 */
> + __raw_writel(GPT_EN, OMAP34XX_GPT1 + TCLR); /* enable clock */
> +
> + /* enable 32kHz source, determine sys_clk via gauging */
> + start = 20 + __raw_readl(S32K_CR); /* start time in 20 cycles */
> + while (__raw_readl(S32K_CR) < start) ; /* dead loop till start time */
> + /* get start sys_clk count */
> + cstart = __raw_readl(OMAP34XX_GPT1 + TCRR);
> + /* wait for 40 cycles */
> + while (__raw_readl(S32K_CR) < (start + 20)) ;
> + cend = __raw_readl(OMAP34XX_GPT1 + TCRR); /* get end sys_clk count */
> + cdiff = cend - cstart; /* get elapsed ticks */
> +
> + /* based on number of ticks assign speed */
> + if (cdiff > 19000)
> + return (S38_4M);
> + else if (cdiff > 15200)
> + return (S26M);
> + else if (cdiff > 13000)
> + return (S24M);
> + else if (cdiff > 9000)
> + return (S19_2M);
> + else if (cdiff > 7600)
> + return (S13M);
> + else
> + return (S12M);
> +}
> +
> +/******************************************************************************
> + * get_sys_clkin_sel() - returns the sys_clkin_sel field value based on
> + * input oscillator clock frequency.
> + *****************************************************************************/
> +void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel)
> +{
> + if (osc_clk == S38_4M)
> + *sys_clkin_sel = 4;
> + else if (osc_clk == S26M)
> + *sys_clkin_sel = 3;
> + else if (osc_clk == S19_2M)
> + *sys_clkin_sel = 2;
> + else if (osc_clk == S13M)
> + *sys_clkin_sel = 1;
> + else if (osc_clk == S12M)
> + *sys_clkin_sel = 0;
> +}
> +
> +/******************************************************************************
> + * prcm_init() - inits clocks for PRCM as defined in clocks.h
> + * called from SRAM, or Flash (using temp SRAM stack).
> + *****************************************************************************/
> +void prcm_init(void)
> +{
> + void (*f_lock_pll) (u32, u32, u32, u32);
> + int xip_safe, p0, p1, p2, p3;
> + u32 osc_clk = 0, sys_clkin_sel;
> + u32 clk_index, sil_index;
> + dpll_param *dpll_param_p;
> +
> + f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start +
> + SRAM_VECT_CODE);
> +
> + xip_safe = running_in_sram();
> +
> + /* Gauge the input clock speed and find out the sys_clkin_sel
> + * value corresponding to the input clock.
> + */
> + osc_clk = get_osc_clk_speed();
> + get_sys_clkin_sel(osc_clk, &sys_clkin_sel);
> +
> + sr32(PRM_CLKSEL, 0, 3, sys_clkin_sel); /* set input crystal speed */
> +
> + /* If the input clock is greater than 19.2M always divide/2 */
> + if (sys_clkin_sel > 2) {
> + sr32(PRM_CLKSRC_CTRL, 6, 2, 2); /* input clock divider */
> + clk_index = sys_clkin_sel / 2;
> + } else {
> + sr32(PRM_CLKSRC_CTRL, 6, 2, 1); /* input clock divider */
> + clk_index = sys_clkin_sel;
> + }
> +
> + /* The DPLL tables are defined according to sysclk value and
> + * silicon revision. The clk_index value will be used to get
> + * the values for that input sysclk from the DPLL param table
> + * and sil_index will get the values for that SysClk for the
> + * appropriate silicon rev.
> + */
> + sil_index = get_cpu_rev() - 1;
> + /* Unlock MPU DPLL (slows things down, and needed later) */
> + sr32(CM_CLKEN_PLL_MPU, 0, 3, PLL_LOW_POWER_BYPASS);
> + wait_on_value(BIT0, 0, CM_IDLEST_PLL_MPU, LDELAY);
> +
> + /* Getting the base address of Core DPLL param table */
> + dpll_param_p = (dpll_param *) get_core_dpll_param();
> + /* Moving it to the right sysclk and ES rev base */
> + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index;
> + if (xip_safe) {
> + /* CORE DPLL */
> + /* sr32(CM_CLKSEL2_EMU) set override to work when asleep */
> + sr32(CM_CLKEN_PLL, 0, 3, PLL_FAST_RELOCK_BYPASS);
> + wait_on_value(BIT0, 0, CM_IDLEST_CKGEN, LDELAY);
> + /* For OMAP3 ES1.0 Errata 1.50, default value directly doesnt
> + work. write another value and then default value. */
> + sr32(CM_CLKSEL1_EMU, 16, 5, CORE_M3X2 + 1); /* m3x2 */
> + sr32(CM_CLKSEL1_EMU, 16, 5, CORE_M3X2); /* m3x2 */
> + sr32(CM_CLKSEL1_PLL, 27, 2, dpll_param_p->m2); /* Set M2 */
> + sr32(CM_CLKSEL1_PLL, 16, 11, dpll_param_p->m); /* Set M */
> + sr32(CM_CLKSEL1_PLL, 8, 7, dpll_param_p->n); /* Set N */
> + sr32(CM_CLKSEL1_PLL, 6, 1, 0); /* 96M Src */
> + sr32(CM_CLKSEL_CORE, 8, 4, CORE_SSI_DIV); /* ssi */
> + sr32(CM_CLKSEL_CORE, 4, 2, CORE_FUSB_DIV); /* fsusb */
> + sr32(CM_CLKSEL_CORE, 2, 2, CORE_L4_DIV); /* l4 */
> + sr32(CM_CLKSEL_CORE, 0, 2, CORE_L3_DIV); /* l3 */
> + sr32(CM_CLKSEL_GFX, 0, 3, GFX_DIV); /* gfx */
> + sr32(CM_CLKSEL_WKUP, 1, 2, WKUP_RSM); /* reset mgr */
> + sr32(CM_CLKEN_PLL, 4, 4, dpll_param_p->fsel); /* FREQSEL */
> + sr32(CM_CLKEN_PLL, 0, 3, PLL_LOCK); /* lock mode */
> + wait_on_value(BIT0, 1, CM_IDLEST_CKGEN, LDELAY);
> + } else if (running_in_flash()) {
> + /* if running from flash, jump to small relocated code
> + area in SRAM. */
> + p0 = __raw_readl(CM_CLKEN_PLL);
> + sr32((u32) &p0, 0, 3, PLL_FAST_RELOCK_BYPASS);
> + sr32((u32) &p0, 4, 4, dpll_param_p->fsel); /* FREQSEL */
> +
> + p1 = __raw_readl(CM_CLKSEL1_PLL);
> + sr32((u32) &p1, 27, 2, dpll_param_p->m2); /* Set M2 */
> + sr32((u32) &p1, 16, 11, dpll_param_p->m); /* Set M */
> + sr32((u32) &p1, 8, 7, dpll_param_p->n); /* Set N */
> + sr32((u32) &p1, 6, 1, 0); /* set source for 96M */
> + p2 = __raw_readl(CM_CLKSEL_CORE);
> + sr32((u32) &p2, 8, 4, CORE_SSI_DIV); /* ssi */
> + sr32((u32) &p2, 4, 2, CORE_FUSB_DIV); /* fsusb */
> + sr32((u32) &p2, 2, 2, CORE_L4_DIV); /* l4 */
> + sr32((u32) &p2, 0, 2, CORE_L3_DIV); /* l3 */
> +
> + p3 = CM_IDLEST_CKGEN;
> +
> + (*f_lock_pll) (p0, p1, p2, p3);
> + }
> +
> + /* PER DPLL */
> + sr32(CM_CLKEN_PLL, 16, 3, PLL_STOP);
> + wait_on_value(BIT1, 0, CM_IDLEST_CKGEN, LDELAY);
> +
> + /* Getting the base address to PER DPLL param table */
> + /* Set N */
> + dpll_param_p = (dpll_param *) get_per_dpll_param();
> + /* Moving it to the right sysclk base */
> + dpll_param_p = dpll_param_p + clk_index;
> + /* Errata 1.50 Workaround for OMAP3 ES1.0 only */
> + /* If using default divisors, write default divisor + 1
> + and then the actual divisor value */
> + /* Need to change it to silicon and revision check */
> + if (1) {
> + sr32(CM_CLKSEL1_EMU, 24, 5, PER_M6X2 + 1); /* set M6 */
> + sr32(CM_CLKSEL1_EMU, 24, 5, PER_M6X2); /* set M6 */
> + sr32(CM_CLKSEL_CAM, 0, 5, PER_M5X2 + 1); /* set M5 */
> + sr32(CM_CLKSEL_CAM, 0, 5, PER_M5X2); /* set M5 */
> + sr32(CM_CLKSEL_DSS, 0, 5, PER_M4X2 + 1); /* set M4 */
> + sr32(CM_CLKSEL_DSS, 0, 5, PER_M4X2); /* set M4 */
> + sr32(CM_CLKSEL_DSS, 8, 5, PER_M3X2 + 1); /* set M3 */
> + sr32(CM_CLKSEL_DSS, 8, 5, PER_M3X2); /* set M3 */
> + sr32(CM_CLKSEL3_PLL, 0, 5, dpll_param_p->m2 + 1); /* set M2 */
> + sr32(CM_CLKSEL3_PLL, 0, 5, dpll_param_p->m2); /* set M2 */
> + } else {
> + sr32(CM_CLKSEL1_EMU, 24, 5, PER_M6X2); /* set M6 */
> + sr32(CM_CLKSEL_CAM, 0, 5, PER_M5X2); /* set M5 */
> + sr32(CM_CLKSEL_DSS, 0, 5, PER_M4X2); /* set M4 */
> + sr32(CM_CLKSEL_DSS, 8, 5, PER_M3X2); /* set M3 */
> + sr32(CM_CLKSEL3_PLL, 0, 5, dpll_param_p->m2); /* set M2 */
> + }
> + sr32(CM_CLKSEL2_PLL, 8, 11, dpll_param_p->m); /* set m */
> + sr32(CM_CLKSEL2_PLL, 0, 7, dpll_param_p->n); /* set n */
> + sr32(CM_CLKEN_PLL, 20, 4, dpll_param_p->fsel); /* FREQSEL */
> + sr32(CM_CLKEN_PLL, 16, 3, PLL_LOCK); /* lock mode */
> + wait_on_value(BIT1, 2, CM_IDLEST_CKGEN, LDELAY);
> +
> + /* Getting the base address to MPU DPLL param table */
> + dpll_param_p = (dpll_param *) get_mpu_dpll_param();
> + /* Moving it to the right sysclk and ES rev base */
> + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index;
> + /* MPU DPLL (unlocked already) */
> + sr32(CM_CLKSEL2_PLL_MPU, 0, 5, dpll_param_p->m2); /* Set M2 */
> + sr32(CM_CLKSEL1_PLL_MPU, 8, 11, dpll_param_p->m); /* Set M */
> + sr32(CM_CLKSEL1_PLL_MPU, 0, 7, dpll_param_p->n); /* Set N */
> + sr32(CM_CLKEN_PLL_MPU, 4, 4, dpll_param_p->fsel); /* FREQSEL */
> + sr32(CM_CLKEN_PLL_MPU, 0, 3, PLL_LOCK); /* lock mode */
> + wait_on_value(BIT0, 1, CM_IDLEST_PLL_MPU, LDELAY);
> +
> + /* Getting the base address to IVA DPLL param table */
> + dpll_param_p = (dpll_param *) get_iva_dpll_param();
> + /* Moving it to the right sysclk and ES rev base */
> + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index;
> + /* IVA DPLL (set to 12*20=240MHz) */
> + sr32(CM_CLKEN_PLL_IVA2, 0, 3, PLL_STOP);
> + wait_on_value(BIT0, 0, CM_IDLEST_PLL_IVA2, LDELAY);
> + sr32(CM_CLKSEL2_PLL_IVA2, 0, 5, dpll_param_p->m2); /* set M2 */
> + sr32(CM_CLKSEL1_PLL_IVA2, 8, 11, dpll_param_p->m); /* set M */
> + sr32(CM_CLKSEL1_PLL_IVA2, 0, 7, dpll_param_p->n); /* set N */
> + sr32(CM_CLKEN_PLL_IVA2, 4, 4, dpll_param_p->fsel); /* FREQSEL */
> + sr32(CM_CLKEN_PLL_IVA2, 0, 3, PLL_LOCK); /* lock mode */
> + wait_on_value(BIT0, 1, CM_IDLEST_PLL_IVA2, LDELAY);
> +
> + /* Set up GPTimers to sys_clk source only */
> + sr32(CM_CLKSEL_PER, 0, 8, 0xff);
> + sr32(CM_CLKSEL_WKUP, 0, 1, 1);
> +
> + sdelay(5000);
> +}
> +
> +/******************************************************************************
> + * peripheral_enable() - Enable the clks & power for perifs (GPT2, UART1,...)
> + *****************************************************************************/
> +void per_clocks_enable(void)
> +{
> + /* Enable GP2 timer. */
> + sr32(CM_CLKSEL_PER, 0, 1, 0x1); /* GPT2 = sys clk */
> + sr32(CM_ICLKEN_PER, 3, 1, 0x1); /* ICKen GPT2 */
> + sr32(CM_FCLKEN_PER, 3, 1, 0x1); /* FCKen GPT2 */
> +
> +#ifdef CFG_NS16550
> + /* Enable UART1 clocks */
> + sr32(CM_FCLKEN1_CORE, 13, 1, 0x1);
> + sr32(CM_ICLKEN1_CORE, 13, 1, 0x1);
> +
> + /* UART 3 Clocks */
> + sr32(CM_FCLKEN_PER, 11, 1, 0x1);
> + sr32(CM_ICLKEN_PER, 11, 1, 0x1);
> +#endif
> +#ifdef CONFIG_DRIVER_OMAP34XX_I2C
> + /* Turn on all 3 I2C clocks */
> + sr32(CM_FCLKEN1_CORE, 15, 3, 0x7);
> + sr32(CM_ICLKEN1_CORE, 15, 3, 0x7); /* I2C1,2,3 = on */
> +#endif
> + /* Enable the ICLK for 32K Sync Timer as its used in udelay */
> + sr32(CM_ICLKEN_WKUP, 2, 1, 0x1);
> +
> + sr32(CM_FCLKEN_IVA2, 0, 32, FCK_IVA2_ON);
> + sr32(CM_FCLKEN1_CORE, 0, 32, FCK_CORE1_ON);
> + sr32(CM_ICLKEN1_CORE, 0, 32, ICK_CORE1_ON);
> + sr32(CM_ICLKEN2_CORE, 0, 32, ICK_CORE2_ON);
> + sr32(CM_FCLKEN_WKUP, 0, 32, FCK_WKUP_ON);
> + sr32(CM_ICLKEN_WKUP, 0, 32, ICK_WKUP_ON);
> + sr32(CM_FCLKEN_DSS, 0, 32, FCK_DSS_ON);
> + sr32(CM_ICLKEN_DSS, 0, 32, ICK_DSS_ON);
> + sr32(CM_FCLKEN_CAM, 0, 32, FCK_CAM_ON);
> + sr32(CM_ICLKEN_CAM, 0, 32, ICK_CAM_ON);
> + sr32(CM_FCLKEN_PER, 0, 32, FCK_PER_ON);
> + sr32(CM_ICLKEN_PER, 0, 32, ICK_PER_ON);
> +
> + sdelay(1000);
> +}
> diff --git a/board/omap3evm/config.mk b/board/omap3evm/config.mk
> new file mode 100644
> index 0000000..9639c43
> --- /dev/null
> +++ b/board/omap3evm/config.mk
> @@ -0,0 +1,17 @@
> +#
> +# (C) Copyright 2006
> +# Texas Instruments, <www.ti.com>
> +#
> +# Begale Board uses OMAP3 (ARM-CortexA8) cpu
> +# see http://www.ti.com/ for more information on Texas Instruments
> +#
> +# Physical Address:
> +# 8000'0000 (bank0)
> +# A000/0000 (bank1)
> +# Linux-Kernel is expected to be at 8000'8000, entry 8000'8000
> +# (mem base + reserved)
> +
> +# For use with external or internal boots.
> +TEXT_BASE = 0x80e80000
> +
> +
> diff --git a/board/omap3evm/lowlevel_init.S b/board/omap3evm/lowlevel_init.S
> new file mode 100644
> index 0000000..1f9a0e9
> --- /dev/null
> +++ b/board/omap3evm/lowlevel_init.S
> @@ -0,0 +1,360 @@
> +/*
> + * Board specific setup info
> + *
> + * (C) Copyright 2008
> + * Texas Instruments, <www.ti.com>
> + *
> + * Initial Code by:
> + * Richard Woodruff <r-woo...@ti.com>
> + * Syed Mohammed Khasim <kha...@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
> + */
> +
> +#include <config.h>
> +#include <version.h>
> +#include <asm/arch/mem.h>
> +#include <asm/arch/clocks_omap3.h>
> +
> +_TEXT_BASE:
> + .word TEXT_BASE /* sdram load addr from config.mk */
> +
> +#if !defined(CFG_NAND_BOOT) && !defined(CFG_NAND_BOOT)
> +/**************************************************************************
> + * cpy_clk_code: relocates clock code into SRAM where its safer to execute
> + * R1 = SRAM destination address.
> + *************************************************************************/
> +.global cpy_clk_code
> + cpy_clk_code:
> + /* Copy DPLL code into SRAM */
> + adr r0, go_to_speed /* get addr of clock setting code */
> + mov r2, #384 /* r2 size to copy (div by 32 bytes) */
> + mov r1, r1 /* r1 <- dest address (passed in) */
> + add r2, r2, r0 /* r2 <- source end address */
> +next2:
> + ldmia r0!, {r3-r10} /* copy from source address [r0] */
> + stmia r1!, {r3-r10} /* copy to target address [r1] */
> + cmp r0, r2 /* until source end address [r2] */
> + bne next2
> + mov pc, lr /* back to caller */
> +
> +/* ***************************************************************************
> + * go_to_speed: -Moves to bypass, -Commits clock dividers, -puts dpll at speed
> + * -executed from SRAM.
> + * R0 = CM_CLKEN_PLL-bypass value
> + * R1 = CM_CLKSEL1_PLL-m, n, and divider values
> + * R2 = CM_CLKSEL_CORE-divider values
> + * R3 = CM_IDLEST_CKGEN - addr dpll lock wait
> + *
> + * Note: If core unlocks/relocks and SDRAM is running fast already it gets
> + * confused. A reset of the controller gets it back. Taking away its
> + * L3 when its not in self refresh seems bad for it. Normally, this
> + * code runs from flash before SDR is init so that should be ok.
> + ****************************************************************************/
> +.global go_to_speed
> + go_to_speed:
> + stmfd sp!, {r4-r6}
> +
> + /* move into fast relock bypass */
> + ldr r4, pll_ctl_add
> + str r0, [r4]
> +wait1:
> + ldr r5, [r3] /* get status */
> + and r5, r5, #0x1 /* isolate core status */
> + cmp r5, #0x1 /* still locked? */
> + beq wait1 /* if lock, loop */
> +
> + /* set new dpll dividers _after_ in bypass */
> + ldr r5, pll_div_add1
> + str r1, [r5] /* set m, n, m2 */
> + ldr r5, pll_div_add2
> + str r2, [r5] /* set l3/l4/.. dividers*/
> + ldr r5, pll_div_add3 /* wkup */
> + ldr r2, pll_div_val3 /* rsm val */
> + str r2, [r5]
> + ldr r5, pll_div_add4 /* gfx */
> + ldr r2, pll_div_val4
> + str r2, [r5]
> + ldr r5, pll_div_add5 /* emu */
> + ldr r2, pll_div_val5
> + str r2, [r5]
> +
> + /* now prepare GPMC (flash) for new dpll speed */
> + /* flash needs to be stable when we jump back to it */
> + ldr r5, flash_cfg3_addr
> + ldr r2, flash_cfg3_val
> + str r2, [r5]
> + ldr r5, flash_cfg4_addr
> + ldr r2, flash_cfg4_val
> + str r2, [r5]
> + ldr r5, flash_cfg5_addr
> + ldr r2, flash_cfg5_val
> + str r2, [r5]
> + ldr r5, flash_cfg1_addr
> + ldr r2, [r5]
> + orr r2, r2, #0x3 /* up gpmc divider */
> + str r2, [r5]
> +
> + /* lock DPLL3 and wait a bit */
> + orr r0, r0, #0x7 /* set up for lock mode */
> + str r0, [r4] /* lock */
> + nop /* ARM slow at this point working at sys_clk */
> + nop
> + nop
> + nop
> +wait2:
> + ldr r5, [r3] /* get status */
> + and r5, r5, #0x1 /* isolate core status */
> + cmp r5, #0x1 /* still locked? */
> + bne wait2 /* if lock, loop */
> + nop
> + nop
> + nop
> + nop
> + ldmfd sp!, {r4-r6}
> + mov pc, lr /* back to caller, locked */
> +
> +_go_to_speed: .word go_to_speed
> +
> +/* these constants need to be close for PIC code */
> +/* The Nor has to be in the Flash Base CS0 for this condition to happen */
> +flash_cfg1_addr:
> + .word (GPMC_CONFIG_CS0 + GPMC_CONFIG1)
> +flash_cfg3_addr:
> + .word (GPMC_CONFIG_CS0 + GPMC_CONFIG3)
> +flash_cfg3_val:
> + .word STNOR_GPMC_CONFIG3
> +flash_cfg4_addr:
> + .word (GPMC_CONFIG_CS0 + GPMC_CONFIG4)
> +flash_cfg4_val:
> + .word STNOR_GPMC_CONFIG4
> +flash_cfg5_val:
> + .word STNOR_GPMC_CONFIG5
> +flash_cfg5_addr:
> + .word (GPMC_CONFIG_CS0 + GPMC_CONFIG5)
> +pll_ctl_add:
> + .word CM_CLKEN_PLL
> +pll_div_add1:
> + .word CM_CLKSEL1_PLL
> +pll_div_add2:
> + .word CM_CLKSEL_CORE
> +pll_div_add3:
> + .word CM_CLKSEL_WKUP
> +pll_div_val3:
> + .word (WKUP_RSM << 1)
> +pll_div_add4:
> + .word CM_CLKSEL_GFX
> +pll_div_val4:
> + .word (GFX_DIV << 0)
> +pll_div_add5:
> + .word CM_CLKSEL1_EMU
> +pll_div_val5:
> + .word CLSEL1_EMU_VAL
> +
> +#endif
> +
> +.globl lowlevel_init
> +lowlevel_init:
> + ldr sp, SRAM_STACK
> + str ip, [sp] /* stash old link register */
> + mov ip, lr /* save link reg across call */
> + bl s_init /* go setup pll,mux,memory */
> + ldr ip, [sp] /* restore save ip */
> + mov lr, ip /* restore link reg */
> +
> + /* back to arch calling code */
> + mov pc, lr
> +
> + /* the literal pools origin */
> + .ltorg
> +
> +REG_CONTROL_STATUS:
> + .word CONTROL_STATUS
> +SRAM_STACK:
> + .word LOW_LEVEL_SRAM_STACK
> +
> +/* DPLL(1-4) PARAM TABLES */
> +/* Each of the tables has M, N, FREQSEL, M2 values defined for nominal
> + * OPP (1.2V). The fields are defined according to dpll_param struct(clock.c).
> + * The values are defined for all possible sysclk and for ES1 and ES2.
> + */
> +
> +mpu_dpll_param:
> +/* 12MHz */
> +/* ES1 */
> +.word 0x0FE,0x07,0x05,0x01
> +/* ES2 */
> +.word 0x0FA,0x05,0x07,0x01
> +/* 3410 */
> +.word 0x085,0x05,0x07,0x01
> +
> +/* 13MHz */
> +/* ES1 */
> +.word 0x17D,0x0C,0x03,0x01
> +/* ES2 */
> +.word 0x1F4,0x0C,0x03,0x01
> +/* 3410 */
> +.word 0x10A,0x0C,0x03,0x01
> +
> +/* 19.2MHz */
> +/* ES1 */
> +.word 0x179,0x12,0x04,0x01
> +/* ES2 */
> +.word 0x271,0x17,0x03,0x01
> +/* 3410 */
> +.word 0x14C,0x17,0x03,0x01
> +
> +/* 26MHz */
> +/* ES1 */
> +.word 0x17D,0x19,0x03,0x01
> +/* ES2 */
> +.word 0x0FA,0x0C,0x07,0x01
> +/* 3410 */
> +.word 0x085,0x0C,0x07,0x01
> +
> +/* 38.4MHz */
> +/* ES1 */
> +.word 0x1FA,0x32,0x03,0x01
> +/* ES2 */
> +.word 0x271,0x2F,0x03,0x01
> +/* 3410 */
> +.word 0x14C,0x2F,0x03,0x01
> +
> +
> +.globl get_mpu_dpll_param
> +get_mpu_dpll_param:
> + adr r0, mpu_dpll_param
> + mov pc, lr
> +
> +iva_dpll_param:
> +/* 12MHz */
> +/* ES1 */
> +.word 0x07D,0x05,0x07,0x01
> +/* ES2 */
> +.word 0x0B4,0x05,0x07,0x01
> +/* 3410 */
> +.word 0x085,0x05,0x07,0x01
> +
> +/* 13MHz */
> +/* ES1 */
> +.word 0x0FA,0x0C,0x03,0x01
> +/* ES2 */
> +.word 0x168,0x0C,0x03,0x01
> +/* 3410 */
> +.word 0x10A,0x0C,0x03,0x01
> +
> +/* 19.2MHz */
> +/* ES1 */
> +.word 0x082,0x09,0x07,0x01
> +/* ES2 */
> +.word 0x0E1,0x0B,0x06,0x01
> +/* 3410 */
> +.word 0x14C,0x17,0x03,0x01
> +
> +/* 26MHz */
> +/* ES1 */
> +.word 0x07D,0x0C,0x07,0x01
> +/* ES2 */
> +.word 0x0B4,0x0C,0x07,0x01
> +/* 3410 */
> +.word 0x085,0x0C,0x07,0x01
> +
> +/* 38.4MHz */
> +/* ES1 */
> +.word 0x13F,0x30,0x03,0x01
> +/* ES2 */
> +.word 0x0E1,0x17,0x06,0x01
> +/* 3410 */
> +.word 0x14C,0x2F,0x03,0x01
> +
> +
> +.globl get_iva_dpll_param
> +get_iva_dpll_param:
> + adr r0, iva_dpll_param
> + mov pc, lr
> +
> +/* Core DPLL targets for L3 at 166 & L133 */
> +core_dpll_param:
> +/* 12MHz */
> +/* ES1 */
> +.word M_12_ES1,M_12_ES1,FSL_12_ES1,M2_12_ES1
> +/* ES2 */
> +.word M_12,N_12,FSEL_12,M2_12
> +/* 3410 */
> +.word M_12,N_12,FSEL_12,M2_12
> +
> +/* 13MHz */
> +/* ES1 */
> +.word M_13_ES1,N_13_ES1,FSL_13_ES1,M2_13_ES1
> +/* ES2 */
> +.word M_13,N_13,FSEL_13,M2_13
> +/* 3410 */
> +.word M_13,N_13,FSEL_13,M2_13
> +
> +/* 19.2MHz */
> +/* ES1 */
> +.word M_19p2_ES1,N_19p2_ES1,FSL_19p2_ES1,M2_19p2_ES1
> +/* ES2 */
> +.word M_19p2,N_19p2,FSEL_19p2,M2_19p2
> +/* 3410 */
> +.word M_19p2,N_19p2,FSEL_19p2,M2_19p2
> +
> +/* 26MHz */
> +/* ES1 */
> +.word M_26_ES1,N_26_ES1,FSL_26_ES1,M2_26_ES1
> +/* ES2 */
> +.word M_26,N_26,FSEL_26,M2_26
> +/* 3410 */
> +.word M_26,N_26,FSEL_26,M2_26
> +
> +/* 38.4MHz */
> +/* ES1 */
> +.word M_38p4_ES1,N_38p4_ES1,FSL_38p4_ES1,M2_38p4_ES1
> +/* ES2 */
> +.word M_38p4,N_38p4,FSEL_38p4,M2_38p4
> +/* 3410 */
> +.word M_38p4,N_38p4,FSEL_38p4,M2_38p4
> +
> +.globl get_core_dpll_param
> +get_core_dpll_param:
> + adr r0, core_dpll_param
> + mov pc, lr
> +
> +/* PER DPLL values are same for both ES1 and ES2 */
> +per_dpll_param:
> +/* 12MHz */
> +.word 0xD8,0x05,0x07,0x09
> +
> +/* 13MHz */
> +.word 0x1B0,0x0C,0x03,0x09
> +
> +/* 19.2MHz */
> +.word 0xE1,0x09,0x07,0x09
> +
> +/* 26MHz */
> +.word 0xD8,0x0C,0x07,0x09
> +
> +/* 38.4MHz */
> +.word 0xE1,0x13,0x07,0x09
> +
> +.globl get_per_dpll_param
> +get_per_dpll_param:
> + adr r0, per_dpll_param
> + mov pc, lr
> +
> diff --git a/board/omap3evm/mem.c b/board/omap3evm/mem.c
> new file mode 100644
> index 0000000..f9e02bf
> --- /dev/null
> +++ b/board/omap3evm/mem.c
> @@ -0,0 +1,288 @@
> +/*
> + * (C) Copyright 2008
> + * Texas Instruments, <www.ti.com>
> + *
> + * Author :
> + * Manikandan Pillai <mani....@ti.com>
> + *
> + * Initial Code from:
> + * Richard Woodruff <r-woo...@ti.com>
> + * Syed Mohammed Khasim <kha...@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/bits.h>
> +#include <asm/arch/mem.h>
> +#include <asm/arch/sys_proto.h>
> +#include <command.h>
> +
> +/* Only One NAND allowed on board at a time.
> + * The GPMC CS Base for the same
> + */
> +unsigned int boot_flash_base;
> +unsigned int boot_flash_off;
> +unsigned int boot_flash_sec;
> +unsigned int boot_flash_type;
> +volatile unsigned int boot_flash_env_addr;
> +
> +/* help common/env_flash.c */
> +#ifdef ENV_IS_VARIABLE
> +
> +uchar(*boot_env_get_char_spec) (int index);
> +int (*boot_env_init) (void);
> +int (*boot_saveenv) (void);
> +void (*boot_env_relocate_spec) (void);
> +
> +/* 16 bit NAND */
> +uchar env_get_char_spec(int index);
> +int env_init(void);
> +int saveenv(void);
> +void env_relocate_spec(void);
> +extern char *env_name_spec;
> +
> +#if defined(CONFIG_CMD_NAND)
> +u8 is_nand;
> +#endif
> +
> +#if defined(CONFIG_CMD_ONENAND)
> +u8 is_onenand;
> +#endif
> +
> +#endif /* ENV_IS_VARIABLE */
> +
> +#if defined(CONFIG_CMD_NAND)
> +static 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
> +};
> +unsigned int nand_cs_base;
> +#endif
> +
> +#if defined(CONFIG_CMD_ONENAND)
> +static u32 gpmc_onenand[GPMC_MAX_REG] = {
> + ONENAND_GPMC_CONFIG1,
> + ONENAND_GPMC_CONFIG2,
> + ONENAND_GPMC_CONFIG3,
> + ONENAND_GPMC_CONFIG4,
> + ONENAND_GPMC_CONFIG5,
> + ONENAND_GPMC_CONFIG6, 0
> +};
> +unsigned int onenand_cs_base;
> +
> +#endif
> +
> +/**************************************************************************
> + * make_cs1_contiguous() - for es2 and above remap cs1 behind cs0 to allow
> + * command line mem=xyz use all memory with out discontinuous support
> + * compiled in. Could do it at the ATAG, but there really is two banks...
> + * Called as part of 2nd phase DDR init.
> + **************************************************************************/
> +void make_cs1_contiguous(void)
> +{
> + u32 size, a_add_low, a_add_high;
> +
> + size = get_sdr_cs_size(SDRC_CS0_OSET);
> + size /= SZ_32M; /* find size to offset CS1 */
> + a_add_high = (size & 3) << 8; /* set up low field */
> + a_add_low = (size & 0x3C) >> 2; /* set up high field */
> + __raw_writel((a_add_high | a_add_low), SDRC_CS_CFG);
> +
> +}
> +
> +/********************************************************
> + * mem_ok() - test used to see if timings are correct
> + * for a part. Helps in guessing which part
> + * we are currently using.
> + *******************************************************/
> +u32 mem_ok(void)
> +{
> + u32 val1, val2, addr;
> + u32 pattern = 0x12345678;
> +
> + addr = OMAP34XX_SDRC_CS0;
> +
> + __raw_writel(0x0, addr + 0x400); /* clear pos A */
> + __raw_writel(pattern, addr); /* pattern to pos B */
> + __raw_writel(0x0, addr + 4); /* remove pattern off the bus */
> + val1 = __raw_readl(addr + 0x400); /* get pos A value */
> + val2 = __raw_readl(addr); /* get val2 */
> +
> + if ((val1 != 0) || (val2 != pattern)) /* see if pos A value changed */
> + return (0);
> + else
> + return (1);
> +}
> +
> +/********************************************************
> + * sdrc_init() - init the sdrc chip selects CS0 and CS1
> + * - early init routines, called from flash or
> + * SRAM.
> + *******************************************************/
> +void sdrc_init(void)
> +{
> + /* only init up first bank here */
> + do_sdrc_init(SDRC_CS0_OSET, EARLY_INIT);
> +}
> +
> +/*************************************************************************
> + * do_sdrc_init(): initialize the SDRAM for use.
> + * -code sets up SDRAM basic SDRC timings for CS0
> + * -optimal settings can be placed here, or redone after i2c
> + * inspection of board info
> + *
> + * - code called ones in C-Stack only context for CS0 and a possible 2nd
> + * time depending on memory configuration from stack+global context
> + **************************************************************************/
> +
> +void do_sdrc_init(u32 offset, u32 early)
> +{
> +
> + /* reset sdrc controller */
> + __raw_writel(SOFTRESET, SDRC_SYSCONFIG);
> + wait_on_value(BIT0, BIT0, SDRC_STATUS, 12000000);
> + __raw_writel(0, SDRC_SYSCONFIG);
> +
> + /* setup sdrc to ball mux */
> + __raw_writel(SDP_SDRC_SHARING, SDRC_SHARING);
> +
> + /* SDRC_MCFG0 register */
> + (*(unsigned int *) 0x6D000080) = 0x02584099; /* from Micron */
> +
> + /* SDRC_RFR_CTRL0 register */
> + (*(unsigned int *) 0x6D0000a4) = 0x54601; /* for 166M */
> +
> + /* SDRC_ACTIM_CTRLA0 register */
> + (*(unsigned int *) 0x6D00009c) = 0xa29db4c6; /* for 166M */
> +
> + /* SDRC_ACTIM_CTRLB0 register */
> + (*(unsigned int *) 0x6D0000a0) = 0x12214; /* for 166M */
> +
> + /* Disble Power Down of CKE cuz of 1 CKE on combo part */
> + (*(unsigned int *) 0x6D000070) = 0x00000081;
> +
> + /* SDRC_Manual command register */
> + (*(unsigned int *) 0x6D0000a8) = 0x00000000; /* NOP command */
> + (*(unsigned int *) 0x6D0000a8) = 0x00000001; /* Precharge command */
> + (*(unsigned int *) 0x6D0000a8) = 0x00000002; /* Auto-refresh command */
> + (*(unsigned int *) 0x6D0000a8) = 0x00000002; /* Auto-refresh command */
> +
> + /* SDRC MR0 register */
> + (*(int *) 0x6D000084) = 0x00000032; /* Burst length = 4 */
> + /* CAS latency = 3, Write Burst = Read Burst Serial Mode */
> +
> + /* SDRC DLLA control register */
> + (*(unsigned int *) 0x6D000060) = 0x0000A;
> + sdelay(0x20000);
> +}
> +
> +void enable_gpmc_config(u32 *gpmc_config, u32 gpmc_base, u32 base, u32 size)
> +{
> + __raw_writel(0, GPMC_CONFIG7 + gpmc_base);
> + sdelay(1000);
> + /* Delay for settling */
> + __raw_writel(gpmc_config[0], GPMC_CONFIG1 + gpmc_base);
> + __raw_writel(gpmc_config[1], GPMC_CONFIG2 + gpmc_base);
> + __raw_writel(gpmc_config[2], GPMC_CONFIG3 + gpmc_base);
> + __raw_writel(gpmc_config[3], GPMC_CONFIG4 + gpmc_base);
> + __raw_writel(gpmc_config[4], GPMC_CONFIG5 + gpmc_base);
> + __raw_writel(gpmc_config[5], GPMC_CONFIG6 + gpmc_base);
> + /* Enable the config */
> + __raw_writel((((size & 0xF) << 8) | ((base >> 24) & 0x3F) |
> + (1 << 6)), GPMC_CONFIG7 + gpmc_base);
> + 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 */
> + u32 mux = 0, mwidth;
> + u32 *gpmc_config = NULL;
> + u32 gpmc_base = 0;
> + u32 base = 0;
> + u32 size = 0;
> + u32 f_off = CFG_MONITOR_LEN;
> + u32 f_sec = 0;
> + u32 config = 0;
> +
> + mux = BIT9;
> + mwidth = get_gpmc0_width();
> +
> + /* global settings */
> + __raw_writel(0x0, GPMC_IRQENABLE); /* isr's sources masked */
> + __raw_writel(0, GPMC_TIMEOUT_CONTROL); /* timeout disable */
> +
> + config = __raw_readl(GPMC_CONFIG);
> + config &= (~0xf00);
> + __raw_writel(config, GPMC_CONFIG);
> +
> + /* Disable the GPMC0 config set by ROM code
> + * It conflicts with our MPDB (both at 0x08000000)
> + */
> + __raw_writel(0, GPMC_CONFIG7 + GPMC_CONFIG_CS0);
> + sdelay(1000);
> +
> +#if defined(CONFIG_CMD_NAND)
> + /* CS 0 */
> + gpmc_config = gpmc_m_nand;
> + gpmc_base = GPMC_CONFIG_CS0 + (0 * GPMC_CONFIG_WIDTH);
> + base = PISMO1_NAND_BASE;
> + size = PISMO1_NAND_SIZE;
> + enable_gpmc_config(gpmc_config, gpmc_base, base, size);
> +
> + f_off = SMNAND_ENV_OFFSET;
> + f_sec = SZ_128K;
> + is_nand = 1;
> + nand_cs_base = gpmc_base;
> +#endif
> +
> +#if defined(CONFIG_CMD_ONENAND)
> + gpmc_config = gpmc_onenand;
> + gpmc_base = GPMC_CONFIG_CS0 + (0 * GPMC_CONFIG_WIDTH);
> + base = PISMO1_ONEN_BASE;
> + size = PISMO1_ONEN_SIZE;
> + enable_gpmc_config(gpmc_config, gpmc_base, base, size);
> +
> + f_off = (ONENAND_MAP + ONENAND_ENV_OFFSET);
> + f_sec = SZ_128K;
> + is_onenand = 1;
> + onenand_cs_base = gpmc_base;
> +#endif
> + /* env setup */
> + boot_flash_base = base;
> + boot_flash_off = f_off;
> + boot_flash_sec = f_sec;
> + boot_flash_env_addr = f_off;
> +
> +#ifdef ENV_IS_VARIABLE
> + boot_env_get_char_spec = env_get_char_spec;
> + boot_env_init = env_init;
> + boot_saveenv = saveenv;
> + boot_env_relocate_spec = env_relocate_spec;
> +#endif
> +
> +}
> diff --git a/board/omap3evm/nand.c b/board/omap3evm/nand.c
> new file mode 100644
> index 0000000..2f94684
> --- /dev/null
> +++ b/board/omap3evm/nand.c
> @@ -0,0 +1,408 @@
> +/*
> + * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
> + * Rohit Choraria <roh...@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
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/mem.h>
> +#include <linux/mtd/nand_ecc.h>
> +
> +#if defined(CONFIG_CMD_NAND)
> +
> +#include <nand.h>
> +
> +unsigned char cs;
> +volatile unsigned long gpmc_cs_base_add;
> +
> +#define GPMC_BUF_EMPTY 0
> +#define GPMC_BUF_FULL 1
> +
> +#define ECC_P1_128_E(val) ((val) & 0x000000FF) /* Bit 0 to 7 */
> +#define ECC_P512_2048_E(val) (((val) & 0x00000F00)>>8) /* Bit 8 to 11 */
> +#define ECC_P1_128_O(val) (((val) & 0x00FF0000)>>16) /* Bit 16 to Bit 23 */
> +#define ECC_P512_2048_O(val) (((val) & 0x0F000000)>>24) /* Bit 24 to Bit 27 */
> +
> +/*
> + * omap_nand_hwcontrol - Set the address pointers corretly for the
> + * following address/data/command operation
> + * @mtd: MTD device structure
> + * @ctrl: Says whether Address or Command or Data is following.
> + */
> +static void omap_nand_hwcontrol(struct mtd_info *mtd, int ctrl)
> +{
> + register struct nand_chip *this = mtd->priv;
> +
> + /* Point the IO_ADDR to DATA and ADDRESS registers instead
> + of chip address */
> + switch (ctrl) {
> + case NAND_CTL_SETCLE:
> + this->IO_ADDR_W = (void *) gpmc_cs_base_add + GPMC_NAND_CMD;
> + this->IO_ADDR_R = (void *) gpmc_cs_base_add + GPMC_NAND_DAT;
> + break;
> + case NAND_CTL_SETALE:
> + this->IO_ADDR_W = (void *) gpmc_cs_base_add + GPMC_NAND_ADR;
> + this->IO_ADDR_R = (void *) gpmc_cs_base_add + GPMC_NAND_DAT;
> + break;
> + case NAND_CTL_CLRCLE:
> + this->IO_ADDR_W = (void *) gpmc_cs_base_add + GPMC_NAND_DAT;
> + this->IO_ADDR_R = (void *) gpmc_cs_base_add + GPMC_NAND_DAT;
> + break;
> + case NAND_CTL_CLRALE:
> + this->IO_ADDR_W = (void *) gpmc_cs_base_add + GPMC_NAND_DAT;
> + this->IO_ADDR_R = (void *) gpmc_cs_base_add + GPMC_NAND_DAT;
> + break;
> + }
> +}
> +
> +/*
> + * omap_nand_wait - called primarily after a program/erase operation
> + * so that we access NAND again only after the device
> + * is ready again.
> + * @mtd: MTD device structure
> + * @chip: nand_chip structure
> + * @state: State from which wait function is being called i.e write/erase.
> + */
> +static int omap_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
> + int state)
> +{
> + register struct nand_chip *this = mtd->priv;
> + int status = 0;
> +
> + this->IO_ADDR_W = (void *) gpmc_cs_base_add + GPMC_NAND_CMD;
> + this->IO_ADDR_R = (void *) gpmc_cs_base_add + GPMC_NAND_DAT;
> + /* Send the status command and loop until the device is free */
> + while (!(status & 0x40)) {
> + __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
> + status = __raw_readb(this->IO_ADDR_R);
> + }
> + return status;
> +}
> +
> +#ifdef CFG_NAND_WIDTH_16
> +/*
> + * omap_nand_write_buf16 - [DEFAULT] write buffer to chip
> + * @mtd: MTD device structure
> + * @buf: data buffer
> + * @len: number of bytes to write
> + *
> + * Default write function for 16bit buswith
> + */
> +static void omap_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
> + int len)
> +{
> + int i;
> + struct nand_chip *this = mtd->priv;
> + u16 *p = (u16 *) buf;
> + len >>= 1;
> +
> + for (i = 0; i < len; i++) {
> + writew(p[i], this->IO_ADDR_W);
> + while (GPMC_BUF_EMPTY == (readl(GPMC_STATUS) & GPMC_BUF_FULL)) ;
> + }
> +}
> +
> +/*
> + * nand_read_buf16 - [DEFAULT] read chip data into buffer
> + * @mtd: MTD device structure
> + * @buf: buffer to store date
> + * @len: number of bytes to read
> + *
> + * Default read function for 16bit buswith
> + */
> +static void omap_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
> +{
> + int i;
> + struct nand_chip *this = mtd->priv;
> + u16 *p = (u16 *) buf;
> + len >>= 1;
> +
> + for (i = 0; i < len; i++)
> + p[i] = readw(this->IO_ADDR_R);
> +}
> +
> +#else
> +/*
> + * omap_nand_write_buf - write buffer to NAND controller
> + * @mtd: MTD device structure
> + * @buf: data buffer
> + * @len: number of bytes to write
> + *
> + */
> +static void omap_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
> + int len)
> +{
> + int i;
> + int j = 0;
> + struct nand_chip *chip = mtd->priv;
> +
> + for (i = 0; i < len; i++) {
> + writeb(buf[i], chip->IO_ADDR_W);
> + for (j = 0; j < 10; j++) ;
> + }
> +
> +}
> +
> +/*
> + * omap_nand_read_buf - read data from NAND controller into buffer
> + * @mtd: MTD device structure
> + * @buf: buffer to store date
> + * @len: number of bytes to read
> + *
> + */
> +static void omap_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
> +{
> + int i;
> + int j = 0;
> + struct nand_chip *chip = mtd->priv;
> +
> + for (i = 0; i < len; i++) {
> + buf[i] = readb(chip->IO_ADDR_R);
> + while (GPMC_BUF_EMPTY == (readl(GPMC_STATUS) & GPMC_BUF_FULL));
> + }
> +}
> +#endif /* CFG_NAND_WIDTH_16 */
> +
> +/*
> + * omap_hwecc_init - Initialize the Hardware ECC for NAND flash in
> + * GPMC controller
> + * @mtd: MTD device structure
> + *
> + */
> +static void omap_hwecc_init(struct nand_chip *chip)
> +{
> + unsigned long val = 0x0;
> +
> + /* Init ECC Control Register */
> + /* Clear all ECC | Enable Reg1 */
> + val = ((0x00000001 << 8) | 0x00000001);
> + __raw_writel(val, GPMC_BASE + GPMC_ECC_CONTROL);
> + __raw_writel(0x3fcff000, GPMC_BASE + GPMC_ECC_SIZE_CONFIG);
> +}
> +
> +/*
> + * omap_correct_data - Compares the ecc read from nand spare area with
> + * ECC registers values
> + * and corrects one bit error if it has occured
> + * @mtd: MTD device structure
> + * @dat: page data
> + * @read_ecc: ecc read from nand flash
> + * @calc_ecc: ecc read from ECC registers
> + */
> +static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
> + u_char *read_ecc, u_char *calc_ecc)
> +{
> + return 0;
> +}
> +
> +/*
> + * omap_calculate_ecc - Generate non-inverted ECC bytes.
> + *
> + * Using noninverted ECC can be considered ugly since writing a blank
> + * page ie. padding will clear the ECC bytes. This is no problem as
> + * long nobody is trying to write data on the seemingly unused page.
> + * Reading an erased page will produce an ECC mismatch between
> + * generated and read ECC bytes that has to be dealt with separately.
> + * @mtd: MTD structure
> + * @dat: unused
> + * @ecc_code: ecc_code buffer
> + */
> +static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
> + u_char *ecc_code)
> +{
> + unsigned long val = 0x0;
> + unsigned long reg;
> +
> + /* Start Reading from HW ECC1_Result = 0x200 */
> + reg = (unsigned long) (GPMC_BASE + GPMC_ECC1_RESULT);
> + val = __raw_readl(reg);
> +
> + *ecc_code++ = ECC_P1_128_E(val);
> + *ecc_code++ = ECC_P1_128_O(val);
> + *ecc_code++ = ECC_P512_2048_E(val) | ECC_P512_2048_O(val) << 4;
> +
> + return 0;
> +}
> +
> +/*
> + * omap_enable_ecc - This function enables the hardware ecc functionality
> + * @mtd: MTD device structure
> + * @mode: Read/Write mode
> + */
> +static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
> +{
> + struct nand_chip *chip = mtd->priv;
> + unsigned int val = __raw_readl(GPMC_BASE + GPMC_ECC_CONFIG);
> + unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
> +
> + switch (mode) {
> + case NAND_ECC_READ:
> + __raw_writel(0x101, GPMC_BASE + GPMC_ECC_CONTROL);
> + /* ECC col width | CS | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + case NAND_ECC_READSYN:
> + __raw_writel(0x100, GPMC_BASE + GPMC_ECC_CONTROL);
> + /* ECC col width | CS | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + case NAND_ECC_WRITE:
> + __raw_writel(0x101, GPMC_BASE + GPMC_ECC_CONTROL);
> + /* ECC col width | CS | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + default:
> + printf("Error: Unrecognized Mode[%d]!\n", mode);
> + break;
> + }
> +
> + __raw_writel(val, GPMC_BASE + GPMC_ECC_CONFIG);
> +}
> +
> +static struct nand_oobinfo hw_nand_oob_64 = {
> + .useecc = MTD_NANDECC_AUTOPLACE,
> + .eccbytes = 12,
> + .eccpos = {
> + 2, 3, 4, 5,
> + 6, 7, 8, 9,
> + 10, 11, 12, 13},
> + .oobfree = { {20, 50} } /* don't care */
> +};
> +
> +static struct nand_oobinfo sw_nand_oob_64 = {
> + .useecc = MTD_NANDECC_AUTOPLACE,
> + .eccbytes = 24,
> + .eccpos = {
> + 40, 41, 42, 43, 44, 45, 46, 47,
> + 48, 49, 50, 51, 52, 53, 54, 55,
> + 56, 57, 58, 59, 60, 61, 62, 63},
> + .oobfree = { {2, 38} }
> +};
> +
> +void omap_nand_switch_ecc(struct mtd_info *mtd, int hardware)
> +{
> + struct nand_chip *nand = mtd->priv;
> +
> + if (!hardware) {
> + nand->eccmode = NAND_ECC_SOFT;
> + nand->autooob = &sw_nand_oob_64;
> + nand->eccsize = 256; /* set default eccsize */
> + nand->eccbytes = 3;
> + nand->eccsteps = 8;
> + nand->enable_hwecc = 0;
> + nand->calculate_ecc = nand_calculate_ecc;
> + nand->correct_data = nand_correct_data;
> + } else {
> + nand->eccmode = NAND_ECC_HW3_512;
> + nand->autooob = &hw_nand_oob_64;
> + nand->eccsize = 512;
> + nand->eccbytes = 3;
> + nand->eccsteps = 4;
> + nand->enable_hwecc = omap_enable_hwecc;
> + nand->correct_data = omap_correct_data;
> + nand->calculate_ecc = omap_calculate_ecc;
> +
> + omap_hwecc_init(nand);
> + }
> +
> + mtd->eccsize = nand->eccsize;
> + nand->oobdirty = 1;
> +
> + if (nand->options & NAND_BUSWIDTH_16) {
> + mtd->oobavail = mtd->oobsize - (nand->autooob->eccbytes + 2);
> + if (nand->autooob->eccbytes & 0x01)
> + mtd->oobavail--;
> + } else
> + mtd->oobavail = mtd->oobsize - (nand->autooob->eccbytes + 1);
> +}
> +
> +/*
> + * Board-specific NAND initialization. The following members of the
> + * argument are board-specific (per include/linux/mtd/nand_new.h):
> + * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
> + * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
> + * - hwcontrol: hardwarespecific function for accesing control-lines
> + * - dev_ready: hardwarespecific function for accesing device ready/busy line
> + * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
> + * only be provided if a hardware ECC is available
> + * - eccmode: mode of ecc, see defines
> + * - chip_delay: chip dependent delay for transfering data from array to
> + * read regs (tR)
> + * - options: various chip options. They can partly be set to inform
> + * nand_scan about special functionality. See the defines for further
> + * explanation
> + * Members with a "?" were not set in the merged testing-NAND branch,
> + * so they are not set here either.
> + */
> +int board_nand_init(struct nand_chip *nand)
> +{
> + int gpmc_config = 0;
> + cs = 0;
> + while (cs <= GPMC_MAX_CS) {
> + /* Each GPMC set for a single CS is at offset 0x30 */
> + /* already remapped for us */
> + gpmc_cs_base_add = (GPMC_CONFIG_CS0 + (cs * 0x30));
> + /* xloader/Uboot would have written the NAND type for us
> + * NOTE: This is a temporary measure and cannot handle ONENAND.
> + * The proper way of doing this is to pass the setup of
> + * u-boot up to kernel using kernel params - something on
> + * the lines of machineID
> + */
> + /* Check if NAND type is set */
> + if ((__raw_readl(gpmc_cs_base_add + GPMC_CONFIG1) & 0xC00) ==
> + 0x800) {
> + /* Found it!! */
> + break;
> + }
> + cs++;
> + }
> + if (cs > GPMC_MAX_CS) {
> + printf("NAND: Unable to find NAND settings in " \
> + "GPMC Configuration - quitting\n");
> + }
> +
> + gpmc_config = __raw_readl(GPMC_CONFIG);
> + /* Disable Write protect */
> + gpmc_config |= 0x10;
> + __raw_writel(gpmc_config, GPMC_CONFIG);
> +
> + nand->IO_ADDR_R = (int *) gpmc_cs_base_add + GPMC_NAND_DAT;
> + nand->IO_ADDR_W = (int *) gpmc_cs_base_add + GPMC_NAND_CMD;
> +
> + nand->hwcontrol = omap_nand_hwcontrol;
> + nand->options = NAND_NO_PADDING | NAND_CACHEPRG | NAND_NO_AUTOINCR |
> + NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR;
> + nand->read_buf = omap_nand_read_buf;
> + nand->write_buf = omap_nand_write_buf;
> + nand->eccmode = NAND_ECC_SOFT;
> + /* if RDY/BSY line is connected to OMAP then use the omap ready
> + * function and the generic nand_wait function which reads the
> + * status register after monitoring the RDY/BSY line. Otherwise
> + * use a standard chip delay which is slightly more than tR
> + * (AC Timing) of the NAND device and read the status register
> + * until you get a failure or success
> + */
> + nand->waitfunc = omap_nand_wait;
> + nand->chip_delay = 50;
> +
> + return 0;
> +}
> +#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
> diff --git a/board/omap3evm/omap3evm.c b/board/omap3evm/omap3evm.c
> new file mode 100644
> index 0000000..a4b2dbe
> --- /dev/null
> +++ b/board/omap3evm/omap3evm.c
> @@ -0,0 +1,389 @@
> +/*
> + * (C) Copyright 2004-2008
> + * Texas Instruments, <www.ti.com>
> + *
> + * Author :
> + * Manikandan Pillai <mani....@ti.com>
> + *
> + * Derived from Beagle Board and 3430 SDP code by
> + * Richard Woodruff <r-woo...@ti.com>
> + * Syed Mohammed Khasim <kha...@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
> + */
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/bits.h>
> +#include <asm/arch/mux.h>
> +#include <asm/arch/sys_proto.h>
> +#include <asm/arch/mem.h>
> +#include <i2c.h>
> +#include <asm/mach-types.h>
> +
> +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && defined(CFG_NAND_LEGACY)
> +#include <linux/mtd/nand_legacy.h>
> +extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
> +#endif
> +
> +#define NOT_EARLY 0
> +
> +/* Permission values for registers -Full fledged permissions to all */
> +#define UNLOCK_1 0xFFFFFFFF
> +#define UNLOCK_2 0x00000000
> +#define UNLOCK_3 0x0000FFFF
> +
> +/******************************************************************************
> + * Routine: delay
> + * Description: spinning delay to use before udelay works
> + *****************************************************************************/
> +static inline void delay(unsigned long loops)
> +{
> + __asm__ volatile ("1:\n" "subs %0, %1, #1\n"
> + "bne 1b":"=r" (loops):"0"(loops));
> +}
> +
> +/******************************************************************************
> + * Routine: board_init
> + * Description: Early hardware init.
> + *****************************************************************************/
> +int board_init(void)
> +{
> + DECLARE_GLOBAL_DATA_PTR;
> +
> + gpmc_init(); /* in SRAM or SDRAM, finish GPMC */
> + /* board id for Linux */
> + gd->bd->bi_arch_number = MACH_TYPE_OMAP3EVM;
> + /* boot param addr */
> + gd->bd->bi_boot_params = (OMAP34XX_SDRC_CS0 + 0x100);
> +
> + return 0;
> +}
> +
> +/******************************************************************************
> + * Routine: secure_unlock
> + * Description: Setup security registers for access
> + * (GP Device only)
> + *****************************************************************************/
> +void secure_unlock_mem(void)
> +{
> + /* Protection Module Register Target APE (PM_RT) */
> + __raw_writel(UNLOCK_1, RT_REQ_INFO_PERMISSION_1);
> + __raw_writel(UNLOCK_1, RT_READ_PERMISSION_0);
> + __raw_writel(UNLOCK_1, RT_WRITE_PERMISSION_0);
> + __raw_writel(UNLOCK_2, RT_ADDR_MATCH_1);
> +
> + __raw_writel(UNLOCK_3, GPMC_REQ_INFO_PERMISSION_0);
> + __raw_writel(UNLOCK_3, GPMC_READ_PERMISSION_0);
> + __raw_writel(UNLOCK_3, GPMC_WRITE_PERMISSION_0);
> +
> + __raw_writel(UNLOCK_3, OCM_REQ_INFO_PERMISSION_0);
> + __raw_writel(UNLOCK_3, OCM_READ_PERMISSION_0);
> + __raw_writel(UNLOCK_3, OCM_WRITE_PERMISSION_0);
> + __raw_writel(UNLOCK_2, OCM_ADDR_MATCH_2);
> +
> + /* IVA Changes */
> + __raw_writel(UNLOCK_3, IVA2_REQ_INFO_PERMISSION_0);
> + __raw_writel(UNLOCK_3, IVA2_READ_PERMISSION_0);
> + __raw_writel(UNLOCK_3, IVA2_WRITE_PERMISSION_0);
> +
> + __raw_writel(UNLOCK_1, SMS_RG_ATT0); /* SDRC region 0 public */
> +}
> +
> +/******************************************************************************
> + * Routine: secureworld_exit()
> + * Description: If chip is EMU and boot type is external
> + * configure secure registers and exit secure world
> + * general use.
> + *****************************************************************************/
> +void secureworld_exit()
> +{
> + unsigned long i;
> +
> + /* configrue non-secure access control register */
> + __asm__ __volatile__("mrc p15, 0, %0, c1, c1, 2":"=r"(i));
> + /* enabling co-processor CP10 and CP11 accesses in NS world */
> + __asm__ __volatile__("orr %0, %0, #0xC00":"=r"(i));
> + /* allow allocation of locked TLBs and L2 lines in NS world */
> + /* allow use of PLE registers in NS world also */
> + __asm__ __volatile__("orr %0, %0, #0x70000":"=r"(i));
> + __asm__ __volatile__("mcr p15, 0, %0, c1, c1, 2":"=r"(i));
> +
> + /* Enable ASA in ACR register */
> + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i));
> + __asm__ __volatile__("orr %0, %0, #0x10":"=r"(i));
> + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i));
> +
> + /* Exiting secure world */
> + __asm__ __volatile__("mrc p15, 0, %0, c1, c1, 0":"=r"(i));
> + __asm__ __volatile__("orr %0, %0, #0x31":"=r"(i));
> + __asm__ __volatile__("mcr p15, 0, %0, c1, c1, 0":"=r"(i));
> +}
> +
> +/******************************************************************************
> + * Routine: setup_auxcr()
> + * Description: Write to AuxCR desired value using SMI.
> + * general use.
> + *****************************************************************************/
> +void setup_auxcr()
> +{
> + unsigned long i;
> + volatile unsigned int j;
> + /* Save r0, r12 and restore them after usage */
> + __asm__ __volatile__("mov %0, r12":"=r"(j));
> + __asm__ __volatile__("mov %0, r0":"=r"(i));
> +
> + /* GP Device ROM code API usage here */
> + /* r12 = AUXCR Write function and r0 value */
> + __asm__ __volatile__("mov r12, #0x3");
> + __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1");
> + /* Enabling ASA */
> + __asm__ __volatile__("orr r0, r0, #0x10");
> + /* SMI instruction to call ROM Code API */
> + __asm__ __volatile__(".word 0xE1600070");
> + __asm__ __volatile__("mov r0, %0":"=r"(i));
> + __asm__ __volatile__("mov r12, %0":"=r"(j));
> +}
> +
> +/******************************************************************************
> + * Routine: try_unlock_sram()
> + * Description: If chip is GP/EMU(special) type, unlock the SRAM for
> + * general use.
> + *****************************************************************************/
> +void try_unlock_memory()
> +{
> + int mode;
> + int in_sdram = running_in_sdram();
> +
> + /* if GP device unlock device SRAM for general use */
> + /* secure code breaks for Secure/Emulation device - HS/E/T */
> + mode = get_device_type();
> + if (mode == GP_DEVICE)
> + secure_unlock_mem();
> +
> + /* If device is EMU and boot is XIP external booting
> + * Unlock firewalls and disable L2 and put chip
> + * out of secure world
> + */
> + /* Assuming memories are unlocked by the demon who put us in SDRAM */
> + if ((mode <= EMU_DEVICE) && (get_boot_type() == 0x1F)
> + && (!in_sdram)) {
> + secure_unlock_mem();
> + secureworld_exit();
> + }
> +
> + return;
> +}
> +
> +/******************************************************************************
> + * Routine: s_init
> + * Description: Does early system init of muxing and clocks.
> + * - Called path is with SRAM stack.
> + *****************************************************************************/
> +void s_init(void)
> +{
> + int in_sdram = running_in_sdram();
> +
> + watchdog_init();
> +
> + try_unlock_memory();
> +
> + /* Right now flushing at low MPU speed.
> + Need to move after clock init */
> + v7_flush_dcache_all(get_device_type());
> +#ifndef CONFIG_ICACHE_OFF
> + icache_enable();
> +#endif
> +
> +#ifdef CONFIG_L2_OFF
> + l2cache_disable();
> +#else
> + l2cache_enable();
> +#endif
> + /* Writing to AuxCR in U-boot using SMI for GP DEV */
> + /* Currently SMI in Kernel on ES2 devices seems to have an isse
> + * Once that is resolved, we can postpone this config to kernel
> + */
> + if (get_device_type() == GP_DEVICE)
> + setup_auxcr();
> +
> + set_muxconf_regs();
> + delay(100);
> +
> + prcm_init();
> +
> + per_clocks_enable();
> +
> + if (!in_sdram)
> + sdrc_init();
> +}
> +
> +/******************************************************************************
> + * Routine: misc_init_r
> + * Description: Init ethernet (done here so udelay works)
> + *****************************************************************************/
> +int misc_init_r(void)
> +{
> +
> + unsigned char byte;
> +
> +#ifdef CONFIG_DRIVER_OMAP34XX_I2C
> + i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE);
> +#endif
> + byte = 0x20;
> + i2c_write(0x4B, 0x7A, 1, &byte, 1);
> + byte = 0x03;
> + i2c_write(0x4B, 0x7D, 1, &byte, 1);
> + byte = 0xE0;
> + i2c_write(0x4B, 0x8E, 1, &byte, 1);
> + byte = 0x05;
> + i2c_write(0x4B, 0x91, 1, &byte, 1);
> + byte = 0x20;
> + i2c_write(0x4B, 0x96, 1, &byte, 1);
> + byte = 0x03;
> + i2c_write(0x4B, 0x99, 1, &byte, 1);
> + byte = 0x33;
> + i2c_write(0x4A, 0xEE, 1, &byte, 1);
> +
> + *((uint *) 0x49058034) = 0xFFFFFAF9;
> + *((uint *) 0x49056034) = 0x0F9F0FFF;
> + *((uint *) 0x49058094) = 0x00000506;
> + *((uint *) 0x49056094) = 0xF060F000;
> +
> + /* set clksel_tv and clksel_dss1 to DPLL4 clock divided by 1 */
> + *((uint *) 0x48004E40) = 0x00001001;
> + return (0);
> +}
> +
> +
> +/******************************************************************************
> + * Routine: wait_for_command_complete
> + * Description: Wait for posting to finish on watchdog
> + *****************************************************************************/
> +void wait_for_command_complete(unsigned int wd_base)
> +{
> + int pending = 1;
> + do {
> + pending = __raw_readl(wd_base + WWPS);
> + } while (pending);
> +}
> +
> +/******************************************************************************
> + * Routine: watchdog_init
> + * Description: Shut down watch dogs
> + *****************************************************************************/
> +void watchdog_init(void)
> +{
> + /* There are 3 watch dogs WD1=Secure, WD2=MPU, WD3=IVA. WD1 is
> + * either taken care of by ROM (HS/EMU) or not accessible (GP).
> + * We need to take care of WD2-MPU or take a PRCM reset. WD3
> + * should not be running and does not generate a PRCM reset.
> + */
> +
> + sr32(CM_FCLKEN_WKUP, 5, 1, 1);
> + sr32(CM_ICLKEN_WKUP, 5, 1, 1);
> + wait_on_value(BIT5, 0x20, CM_IDLEST_WKUP, 5); /* some issue here */
> +
> + __raw_writel(WD_UNLOCK1, WD2_BASE + WSPR);
> + wait_for_command_complete(WD2_BASE);
> + __raw_writel(WD_UNLOCK2, WD2_BASE + WSPR);
> +}
> +
> +/******************************************************************************
> + * Routine: dram_init
> + * Description: sets uboots idea of sdram size
> + *****************************************************************************/
> +int dram_init(void)
> +{
> + DECLARE_GLOBAL_DATA_PTR;
> + unsigned int size0 = 0, size1 = 0;
> + u32 mtype, btype;
> +
> + btype = get_board_type();
> + mtype = get_mem_type();
> +
> + display_board_info(btype);
> +
> + /* If a second bank of DDR is attached to CS1 this is
> + * where it can be started. Early init code will init
> + * memory on CS0.
> + */
> + if ((mtype == DDR_COMBO) || (mtype == DDR_STACKED))
> + do_sdrc_init(SDRC_CS1_OSET, NOT_EARLY);
> +
> + size0 = get_sdr_cs_size(SDRC_CS0_OSET);
> + size1 = get_sdr_cs_size(SDRC_CS1_OSET);
> +
> + gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
> + gd->bd->bi_dram[0].size = size0;
> + gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + size0;
> + gd->bd->bi_dram[1].size = size1;
> +
> + return 0;
> +}
> +
> +/******************************************************************************
> + * Routine: set_muxconf_regs
> + * Description: Setting up the configuration Mux registers specific to the
> + * hardware. Many pins need to be moved from protect to primary
> + * mode.
> + *****************************************************************************/
> +void set_muxconf_regs(void)
> +{
> + MUX_DEFAULT_ES2();
> +}
> +
> +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && defined(CFG_NAND_LEGACY)
> +/******************************************************************************
> + * Routine: nand+_init
> + * Description: Set up nand for nand and jffs2 commands
> + *****************************************************************************/
> +void nand_init(void)
> +{
> + extern flash_info_t flash_info[];
> +
> + nand_probe(CFG_NAND_ADDR);
> + if (nand_dev_desc[0].ChipID != NAND_ChipID_UNKNOWN)
> + print_size(nand_dev_desc[0].totlen, "\n");
> +
> +#ifdef CFG_JFFS2_MEM_NAND
> + flash_info[CFG_JFFS2_FIRST_BANK].flash_id = nand_dev_desc[0].id;
> + /* only read kernel single meg partition */
> + flash_info[CFG_JFFS2_FIRST_BANK].size = 1024 * 1024 * 2;
> + /* 1024 blocks in 16meg chip (use less for raw/copied partition) */
> + flash_info[CFG_JFFS2_FIRST_BANK].sector_count = 1024;
> + /* ?, ram for now, open question, copy to RAM or adapt for NAND */
> + flash_info[CFG_JFFS2_FIRST_BANK].start[0] = 0x80200000;
> +#endif
> +}
> +#endif
> +
> +/******************************************************************************
> + * Dummy function to handle errors for EABI incompatibility
> + *****************************************************************************/
> +void raise(void)
> +{
> +}
> +
> +/******************************************************************************
> + * Dummy function to handle errors for EABI incompatibility
> + *****************************************************************************/
> +void abort(void)
> +{
> +}
> diff --git a/board/omap3evm/sys_info.c b/board/omap3evm/sys_info.c
> new file mode 100644
> index 0000000..a07e94b
> --- /dev/null
> +++ b/board/omap3evm/sys_info.c
> @@ -0,0 +1,312 @@
> +/*
> + * (C) Copyright 2008
> + * Texas Instruments, <www.ti.com>
> + *
> + * Author :
> + * Manikandan Pillai <mani....@ti.com>
> + *
> + * Derived from Beagle Board and 3430 SDP code by
> + * Richard Woodruff <r-woo...@ti.com>
> + * Syed Mohammed Khasim <kha...@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/bits.h>
> +#include <asm/arch/mem.h> /* get mem tables */
> +#include <asm/arch/sys_proto.h>
> +#include <i2c.h>
> +
> +/**************************************************************************
> + * get_gpmc0_type()
> + ***************************************************************************/
> +u32 get_gpmc0_type(void)
> +{
> + /* Default NAND */
> + return (2);
> +}
> +
> +/****************************************************
> + * get_cpu_type() - low level get cpu type
> + * - no C globals yet.
> + ****************************************************/
> +u32 get_cpu_type(void)
> +{
> + /* fixme, need to get register defines for OMAP3 */
> + return (CPU_3430);
> +}
> +
> +/******************************************
> + * get_cpu_rev(void) - extract version info
> + ******************************************/
> +u32 get_cpu_rev(void)
> +{
> + u32 cpuid = 0;
> + /* On ES1.0 the IDCODE register is not exposed on L4
> + * so using CPU ID to differentiate
> + * between ES2.0 and ES1.0.
> + */
> + __asm__ __volatile__("mrc p15, 0, %0, c0, c0, 0":"=r"(cpuid));
> + if ((cpuid & 0xf) == 0x0)
> + return CPU_3430_ES1;
> + else
> + return CPU_3430_ES2;
> +
> +}
> +
> +/****************************************************
> + * is_mem_sdr() - return 1 if mem type in use is SDR
> + ****************************************************/
> +u32 is_mem_sdr(void)
> +{
> + volatile u32 *burst = (volatile u32 *) (SDRC_MR_0 + SDRC_CS0_OSET);
> + if (*burst == SDP_SDRC_MR_0_SDR)
> + return (1);
> + return (0);
> +}
> +
> +/***********************************************************
> + * get_mem_type() - identify type of mDDR part used.
> + ***********************************************************/
> +u32 get_mem_type(void)
> +{
> + /* Current SDP3430 uses 2x16 MDDR Infenion parts */
> + return (DDR_DISCRETE);
> +}
> +
> +/***********************************************************************
> + * get_cs0_size() - get size of chip select 0/1
> + ************************************************************************/
> +u32 get_sdr_cs_size(u32 offset)
> +{
> + u32 size;
> +
> + /* get ram size field */
> + size = __raw_readl(SDRC_MCFG_0 + offset) >> 8;
> + size &= 0x3FF; /* remove unwanted bits */
> + size *= SZ_2M; /* find size in MB */
> + return (size);
> +}
> +
> +/***********************************************************************
> + * get_board_type() - get board type based on current production stats.
> + * - NOTE-1-: 2 I2C EEPROMs will someday be populated with proper info.
> + * when they are available we can get info from there. This should
> + * be correct of all known boards up until today.
> + * - NOTE-2- EEPROMs are populated but they are updated very slowly. To
> + * avoid waiting on them we will use ES version of the chip to get info.
> + * A later version of the FPGA migth solve their speed issue.
> + ************************************************************************/
> +u32 get_board_type(void)
> +{
> + if (get_cpu_rev() == CPU_3430_ES2)
> + return SDP_3430_V2;
> + else
> + return SDP_3430_V1;
> +}
> +
> +/******************************************************************
> + * get_sysboot_value() - get init word settings
> + ******************************************************************/
> +inline u32 get_sysboot_value(void)
> +{
> + return (0x0000003F & __raw_readl(CONTROL_STATUS));
> +}
> +
> +/***************************************************************************
> + * get_gpmc0_base() - Return current address hardware will be
> + * fetching from. The below effectively gives what is correct, its a bit
> + * mis-leading compared to the TRM. For the most general case the mask
> + * needs to be also taken into account this does work in practice.
> + * - for u-boot we currently map:
> + * -- 0 to nothing,
> + * -- 4 to flash
> + * -- 8 to enent
> + * -- c to wifi
> + ****************************************************************************/
> +u32 get_gpmc0_base(void)
> +{
> + u32 b;
> +
> + b = __raw_readl(GPMC_CONFIG_CS0 + GPMC_CONFIG7);
> + b &= 0x1F; /* keep base [5:0] */
> + b = b << 24; /* ret 0x0b000000 */
> + return (b);
> +}
> +
> +/*******************************************************************
> + * get_gpmc0_width() - See if bus is in x8 or x16 (mainly for nand)
> + *******************************************************************/
> +u32 get_gpmc0_width(void)
> +{
> + return (WIDTH_16BIT);
> +}
> +
> +/*************************************************************************
> + * get_board_rev() - setup to pass kernel board revision information
> + * returns:(bit[0-3] sub version, higher bit[7-4] is higher version)
> + *************************************************************************/
> +u32 get_board_rev(void)
> +{
> + return (0x20);
> +}
> +
> +/*********************************************************************
> + * display_board_info() - print banner with board info.
> + *********************************************************************/
> +void display_board_info(u32 btype)
> +{
> + char *bootmode[] = {
> + "NOR",
> + "ONND",
> + "NAND",
> + "P2a",
> + "NOR",
> + "NOR",
> + "P2a",
> + "P2b",
> + };
> + u32 brev = get_board_rev();
> + char cpu_3430s[] = "3530";
> + char db_ver[] = "0.0"; /* board type */
> + char mem_sdr[] = "mSDR"; /* memory type */
> + char mem_ddr[] = "LPDDR";
> + char t_tst[] = "TST"; /* security level */
> + char t_emu[] = "EMU";
> + char t_hs[] = "HS";
> + char t_gp[] = "GP";
> + char unk[] = "?";
> +#ifdef CONFIG_LED_INFO
> + char led_string[CONFIG_LED_LEN] = { 0 };
> +#endif
> + char p_l3[] = "165";
> + char p_cpu[] = "2";
> +
> + char *cpu_s, *db_s, *mem_s, *sec_s;
> + u32 cpu, rev, sec;
> +
> + rev = get_cpu_rev();
> + cpu = get_cpu_type();
> + sec = get_device_type();
> +
> + if (is_mem_sdr())
> + mem_s = mem_sdr;
> + else
> + mem_s = mem_ddr;
> +
> + cpu_s = cpu_3430s;
> +
> + db_s = db_ver;
> + db_s[0] += (brev >> 4) & 0xF;
> + db_s[2] += brev & 0xF;
> +
> + switch (sec) {
> + case TST_DEVICE:
> + sec_s = t_tst;
> + break;
> + case EMU_DEVICE:
> + sec_s = t_emu;
> + break;
> + case HS_DEVICE:
> + sec_s = t_hs;
> + break;
> + case GP_DEVICE:
> + sec_s = t_gp;
> + break;
> + default:
> + sec_s = unk;
> + }
> +
> + printf("OMAP%s-%s rev %d, CPU-OPP%s L3-%sMHz\n", cpu_s, sec_s, rev,
> + p_cpu, p_l3);
> + printf("OMAP3 EVM Board + %s/%s\n",
> + mem_s, bootmode[get_gpmc0_type()]);
> +
> +}
> +
> +/********************************************************
> + * get_base(); get upper addr of current execution
> + *******************************************************/
> +u32 get_base(void)
> +{
> + u32 val;
> +
> + __asm__ __volatile__("mov %0, pc \n":"=r"(val)::"memory");
> + val &= 0xF0000000;
> + val >>= 28;
> + return (val);
> +}
> +
> +/********************************************************
> + * running_in_flash() - tell if currently running in
> + * flash.
> + *******************************************************/
> +u32 running_in_flash(void)
> +{
> + if (get_base() < 4)
> + return (1); /* in flash */
> +
> + return (0); /* running in SRAM or SDRAM */
> +}
> +
> +/********************************************************
> + * running_in_sram() - tell if currently running in
> + * sram.
> + *******************************************************/
> +u32 running_in_sram(void)
> +{
> + if (get_base() == 4)
> + return (1); /* in SRAM */
> +
> + return (0); /* running in FLASH or SDRAM */
> +}
> +
> +/********************************************************
> + * running_in_sdram() - tell if currently running in
> + * flash.
> + *******************************************************/
> +u32 running_in_sdram(void)
> +{
> + if (get_base() > 4)
> + return (1); /* in sdram */
> +
> + return (0); /* running in SRAM or FLASH */
> +}
> +
> +/***************************************************************
> + * get_boot_type() - Is this an XIP type device or a stream one
> + * bits 4-0 specify type. Bit 5 sys mem/perif
> + ***************************************************************/
> +u32 get_boot_type(void)
> +{
> + u32 v;
> +
> + v = get_sysboot_value() & (BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
> + return v;
> +}
> +
> +/*************************************************************
> + * get_device_type(): tell if GP/HS/EMU/TST
> + *************************************************************/
> +u32 get_device_type(void)
> +{
> + int mode;
> +
> + mode = __raw_readl(CONTROL_STATUS) & (DEVICE_MASK);
> + return (mode >>= 8);
> +}
> diff --git a/board/omap3evm/syslib.c b/board/omap3evm/syslib.c
> new file mode 100644
> index 0000000..f161e93
> --- /dev/null
> +++ b/board/omap3evm/syslib.c
> @@ -0,0 +1,76 @@
> +/*
> + * (C) Copyright 2008
> + * Texas Instruments, <www.ti.com>
> + *
> + * Author :
> + * Manikandan Pillai <mani....@ti.com>
> + *
> + * Derived from Beagle Board and 3430 SDP code by
> + * Richard Woodruff <r-woo...@ti.com>
> + * Syed Mohammed Khasim <kha...@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/bits.h>
> +#include <asm/arch/mem.h>
> +#include <asm/arch/clocks.h>
> +#include <asm/arch/sys_proto.h>
> +
> +/************************************************************
> + * sdelay() - simple spin loop. Will be constant time as
> + * its generally used in bypass conditions only. This
> + * is necessary until timers are accessible.
> + *
> + * not inline to increase chances its in cache when called
> + *************************************************************/
> +void sdelay(unsigned long loops)
> +{
> + __asm__ volatile ("1:\n" "subs %0, %1, #1\n"
> + "bne 1b":"=r" (loops):"0"(loops));
> +}
> +
> +/*****************************************************************
> + * sr32 - clear & set a value in a bit range for a 32 bit address
> + *****************************************************************/
> +void sr32(u32 addr, u32 start_bit, u32 num_bits, u32 value)
> +{
> + u32 tmp, msk = 0;
> + msk = 1 << num_bits;
> + --msk;
> + tmp = __raw_readl(addr) & ~(msk << start_bit);
> + tmp |= value << start_bit;
> + __raw_writel(tmp, addr);
> +}
> +
> +/*********************************************************************
> + * wait_on_value() - common routine to allow waiting for changes in
> + * volatile regs.
> + *********************************************************************/
> +u32 wait_on_value(u32 read_bit_mask, u32 match_value, u32 read_addr, u32 bound)
> +{
> + u32 i = 0, val;
> + do {
> + ++i;
> + val = __raw_readl(read_addr) & read_bit_mask;
> + if (val == match_value)
> + return (1);
> + if (i == bound)
> + return (0);
> + } while (1);
> +}
> diff --git a/board/omap3evm/u-boot.lds b/board/omap3evm/u-boot.lds
> new file mode 100644
> index 0000000..72f15f6
> --- /dev/null
> +++ b/board/omap3evm/u-boot.lds
> @@ -0,0 +1,63 @@
> +/*
> + * January 2004 - Changed to support H4 device
> + * Copyright (c) 2004 Texas Instruments
> + *
> + * (C) Copyright 2002
> + * Gary Jennejohn, DENX Software Engineering, <g...@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
> + */
> +
> +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
> +OUTPUT_ARCH(arm)
> +ENTRY(_start)
> +SECTIONS
> +{
> + . = 0x00000000;
> +
> + . = ALIGN(4);
> + .text :
> + {
> + cpu/omap3/start.o (.text)
> + *(.text)
> + }
> +
> + . = ALIGN(4);
> + .rodata : { *(.rodata) }
> +
> + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
> + __exidx_start = .;
> + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
> + __exidx_end = .;
> +
> + . = ALIGN(4);
> + .data : { *(.data) }
> +
> + . = ALIGN(4);
> + .got : { *(.got) }
> +
> + __u_boot_cmd_start = .;
> + .u_boot_cmd : { *(.u_boot_cmd) }
> + __u_boot_cmd_end = .;
> +
> + . = ALIGN(4);
> + __bss_start = .;
> + .bss : { *(.bss) }
> + _end = .;
> +}
> diff --git a/include/configs/omap3evm.h b/include/configs/omap3evm.h
> new file mode 100644
> index 0000000..e808438
> --- /dev/null
> +++ b/include/configs/omap3evm.h
> @@ -0,0 +1,299 @@
> +/*
> + * (C) Copyright 2006-2008
> + * Texas Instruments.
> +
> + * Author :
> + * Manikandan Pillai <mani....@ti.com>
> + * Derived from Beagle Board and 3430 SDP code by
> + * Richard Woodruff <r-woo...@ti.com>
> + * Syed Mohammed Khasim <kha...@ti.com>
> + *
> + * Manikandan Pillai <mani....@ti.com>
> + *
> + * Configuration settings for the TI OMAP3 EVM board.
> + *
> + * 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 __CONFIG_H
> +#define __CONFIG_H
> +#include <asm/sizes.h>
> +
> +/*
> + * High Level Configuration Options
> + */
> +#define CONFIG_ARMCORTEXA8 1 /* This is an ARM V7 CPU core */
> +#define CONFIG_OMAP 1 /* in a TI OMAP core */
> +#define CONFIG_OMAP34XX 1 /* which is a 34XX */
> +#define CONFIG_OMAP3430 1 /* which is in a 3430 */
> +#define CONFIG_DOS_PARTITION 1
> +
> +#include <asm/arch/cpu.h> /* get chip and board defs */
> +#include <asm/arch/omap3.h>
> +
> +/* Clock Defines */
> +#define V_OSCK 26000000 /* Clock output from T2 */
> +#define V_SCLK (V_OSCK >> 1)
> +
> +#undef CONFIG_USE_IRQ /* no support for IRQs */
> +#define CONFIG_MISC_INIT_R
> +
> +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
> +#define CONFIG_SETUP_MEMORY_TAGS 1
> +#define CONFIG_INITRD_TAG 1
> +#define CONFIG_REVISION_TAG 1
> +
> +/*
> + * Size of malloc() pool
> + */
> +#define CFG_ENV_SIZE SZ_128K /* Total Size Environment Sector */
> +#define CFG_MALLOC_LEN (CFG_ENV_SIZE + SZ_128K)
> +#define CFG_GBL_DATA_SIZE 128 /* bytes reserved for initial data */
> +
> +/*
> + * Hardware drivers
> + */
> +
> +/*
> + * NS16550 Configuration
> + */
> +#define V_NS16550_CLK (48000000) /* 48MHz (APLL96/2) */
> +
> +#define CFG_NS16550
> +#define CFG_NS16550_SERIAL
> +#define CFG_NS16550_REG_SIZE (-4)
> +#define CFG_NS16550_CLK V_NS16550_CLK
> +
> +/*
> + * select serial console configuration
> + */
> +#define CONFIG_CONS_INDEX 1
> +#define CFG_NS16550_COM1 OMAP34XX_UART1
> +#define CONFIG_SERIAL1 1 /* UART1 on OMAP3 EVM */
> +
> +/* allow to overwrite serial and ethaddr */
> +#define CONFIG_ENV_OVERWRITE
> +#define CONFIG_BAUDRATE 115200
> +#define CFG_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600, 115200}
> +#define CONFIG_MMC 1
> +#define CFG_MMC_BASE 0xF0000000
> +#define CONFIG_DOS_PARTITION 1
> +
> +/* commands to include */
> +
> +#define CONFIG_CMD_EXT2 /* EXT2 Support */
> +#define CONFIG_CMD_FAT /* FAT support */
> +#define CONFIG_CMD_JFFS2 /* JFFS2 Support */
> +
> +#define CONFIG_CMD_I2C /* I2C serial bus support */
> +#define CONFIG_CMD_MMC /* MMC support */
> +#define CONFIG_CMD_ONENAND /* ONENAND support */
> +
> +#define CONFIG_CMD_AUTOSCRIPT /* autoscript support */
> +#define CONFIG_CMD_BDI /* bdinfo */
> +#define CONFIG_CMD_BOOTD /* bootd */
> +#define CONFIG_CMD_CONSOLE /* coninfo */
> +#define CONFIG_CMD_ECHO /* echo arguments */
> +#define CONFIG_CMD_ENV /* saveenv */
> +#define CONFIG_CMD_ITEST /* Integer (and string) test */
> +#define CONFIG_CMD_LOADB /* loadb */
> +#define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop mtest */
> +#define CONFIG_CMD_MISC /* misc functions like sleep etc*/
> +#define CONFIG_CMD_RUN /* run command in env variable */
> +
> +#define CFG_NO_FLASH
> +#define CFG_I2C_SPEED 100
> +#define CFG_I2C_SLAVE 1
> +#define CFG_I2C_BUS 0
> +#define CFG_I2C_BUS_SELECT 1
> +#define CONFIG_DRIVER_OMAP34XX_I2C 1
> +
> +/*
> + * Board NAND Info.
> + */
> +#define CFG_NAND_ADDR NAND_BASE /* physical address to access nand */
> +#define CFG_NAND_BASE NAND_BASE /* physical address to access nand at CS0 */
> +#define CFG_NAND_WIDTH_16
> +
> +#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
> +#define SECTORSIZE 512
> +
> +#define NAND_ALLOW_ERASE_ALL
> +#define ADDR_COLUMN 1
> +#define ADDR_PAGE 2
> +#define ADDR_COLUMN_PAGE 3
> +
> +#define NAND_ChipID_UNKNOWN 0x00
> +#define NAND_MAX_FLOORS 1
> +#define NAND_MAX_CHIPS 1
> +#define NAND_NO_RB 1
> +#define CFG_NAND_WP
> +
> +#define CONFIG_JFFS2_NAND
> +/* nand device jffs2 lives on */
> +#define CONFIG_JFFS2_DEV "nand0"
> +/* start of jffs2 partition */
> +#define CONFIG_JFFS2_PART_OFFSET 0x680000
> +#define CONFIG_JFFS2_PART_SIZE 0xf980000 /* size of jffs2 partition */
> +
> +/* Environment information */
> +#define CONFIG_BOOTDELAY 10
> +
> +#define CONFIG_BOOTCOMMAND "onenand read 80200000 280000 400000 ; \
> + bootm 80200000"
> +
> +#define CONFIG_BOOTARGS "setenv bootargs console=ttyS2,115200n8 noinitrd \
> + root=/dev/mtdblock4 rw rootfstype=jffs2"
> +
> +#define CONFIG_NETMASK 255.255.254.0
> +#define CONFIG_IPADDR 128.247.77.90
> +#define CONFIG_SERVERIP 128.247.77.158
> +#define CONFIG_BOOTFILE "uImage"
> +#define CONFIG_AUTO_COMPLETE 1
> +/*
> + * Miscellaneous configurable options
> + */
> +#define V_PROMPT "OMAP3_EVM # "
> +
> +#define CFG_LONGHELP /* undef to save memory */
> +#define CFG_PROMPT V_PROMPT
> +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
> +/* Print Buffer Size */
> +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)
> +#define CFG_MAXARGS 16 /* max number of command args */
> +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
> +
> +#define CFG_MEMTEST_START (OMAP34XX_SDRC_CS0) /* memtest works on */
> +#define CFG_MEMTEST_END (OMAP34XX_SDRC_CS0+0x01F00000) /* 31MB */
> +
> +#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
> +
> +#define CFG_LOAD_ADDR (OMAP34XX_SDRC_CS0) /* default load address */
> +
> +/* 2430 has 12 GP timers, they can be driven by the SysClk (12/13/19.2) or by
> + * 32KHz clk, or from external sig. This rate is divided by a local divisor.
> + */
> +#define V_PVT 7
> +
> +#define CFG_TIMERBASE OMAP34XX_GPT2
> +#define CFG_PVT V_PVT /* 2^(pvt+1) */
> +#define CFG_HZ ((V_SCLK)/(2 << CFG_PVT))
> +
> +/*-----------------------------------------------------------------------
> + * Stack sizes
> + *
> + * The stack sizes are set up in start.S using the settings below
> + */
> +#define CONFIG_STACKSIZE SZ_128K /* regular stack */
> +#ifdef CONFIG_USE_IRQ
> +#define CONFIG_STACKSIZE_IRQ SZ_4K /* IRQ stack */
> +#define CONFIG_STACKSIZE_FIQ SZ_4K /* FIQ stack */
> +#endif
> +
> +/*-----------------------------------------------------------------------
> + * Physical Memory Map
> + */
> +#define CONFIG_NR_DRAM_BANKS 2 /* CS1 may or may not be populated */
> +#define PHYS_SDRAM_1 OMAP34XX_SDRC_CS0
> +#define PHYS_SDRAM_1_SIZE SZ_32M /* at least 32 meg */
> +#define PHYS_SDRAM_2 OMAP34XX_SDRC_CS1
> +
> +/* SDRAM Bank Allocation method */
> +#define SDRC_R_B_C 1
> +
> +/*-----------------------------------------------------------------------
> + * FLASH and environment organization
> + */
> +
> +/* **** PISMO SUPPORT *** */
> +
> +/* Configure the PISMO */
> +#define PISMO1_NOR_SIZE_SDPV2 GPMC_SIZE_128M
> +#define PISMO1_NOR_SIZE GPMC_SIZE_64M
> +
> +#define PISMO1_NAND_SIZE GPMC_SIZE_128M
> +#define PISMO1_ONEN_SIZE GPMC_SIZE_128M
> +#define DBG_MPDB_SIZE GPMC_SIZE_16M
> +#define PISMO2_SIZE 0
> +
> +#define CFG_MAX_FLASH_SECT (520) /* max number of sectors on one chip */
> +#define CFG_MAX_FLASH_BANKS 2 /* max number of flash banks */
> +#define CFG_MONITOR_LEN SZ_256K /* Reserve 2 sectors */
> +
> +#define PHYS_FLASH_SIZE_SDPV2 SZ_128M
> +#define PHYS_FLASH_SIZE SZ_32M
> +
> +#define CFG_FLASH_BASE boot_flash_base
> +#define PHYS_FLASH_SECT_SIZE boot_flash_sec
> +/* Dummy declaration of flash banks to get compilation right */
> +#define CFG_FLASH_BANKS_LIST {0, 0}
> +
> +#define CFG_MONITOR_BASE CFG_FLASH_BASE /* Monitor at start of flash */
> +#define CFG_ONENAND_BASE ONENAND_MAP
> +
> +#define CFG_ENV_IS_IN_ONENAND 1
> +#define ONENAND_ENV_OFFSET 0x260000 /* environment starts here */
> +#define SMNAND_ENV_OFFSET 0x260000 /* environment starts here */
> +
> +#define CFG_ENV_SECT_SIZE boot_flash_sec
> +#define CFG_ENV_OFFSET boot_flash_off
> +#define CFG_ENV_ADDR boot_flash_env_addr
> +
> +/*-----------------------------------------------------------------------
> + * CFI FLASH driver setup
> + */
> +/* timeout values are in ticks */
> +#define CFG_FLASH_ERASE_TOUT (100*CFG_HZ) /* Timeout for Flash Erase */
> +#define CFG_FLASH_WRITE_TOUT (100*CFG_HZ) /* Timeout for Flash Write */
> +
> +/* Flash banks JFFS2 should use */
> +#define CFG_MAX_MTD_BANKS (CFG_MAX_FLASH_BANKS+CFG_MAX_NAND_DEVICE)
> +#define CFG_JFFS2_MEM_NAND
> +#define CFG_JFFS2_FIRST_BANK CFG_MAX_FLASH_BANKS /* use flash_info[2] */
> +#define CFG_JFFS2_NUM_BANKS 1
> +
> +#define ENV_IS_VARIABLE 1
> +
> +#ifndef __ASSEMBLY__
> +extern unsigned int nand_cs_base;
> +extern unsigned int boot_flash_base;
> +extern volatile unsigned int boot_flash_env_addr;
> +extern unsigned int boot_flash_off;
> +extern unsigned int boot_flash_sec;
> +extern unsigned int boot_flash_type;
> +#endif
> +
> +
> +#define WRITE_NAND_COMMAND(d, adr)\
> + __raw_writew(d, (nand_cs_base + GPMC_NAND_CMD))
> +#define WRITE_NAND_ADDRESS(d, adr)\
> + __raw_writew(d, (nand_cs_base + GPMC_NAND_ADR))
> +#define WRITE_NAND(d, adr) __raw_writew(d, (nand_cs_base + GPMC_NAND_DAT))
> +#define READ_NAND(adr) __raw_readw((nand_cs_base + GPMC_NAND_DAT))
> +
> +/* Other NAND Access APIs */
> +#define NAND_WP_OFF()\
> + do {*(volatile u32 *)(GPMC_CONFIG) |= 0x00000010; } while (0)
> +#define NAND_WP_ON()\
> + do {*(volatile u32 *)(GPMC_CONFIG) &= ~0x00000010; } while (0)
> +#define NAND_DISABLE_CE(nand)
> +#define NAND_ENABLE_CE(nand)
> +#define NAND_WAIT_READY(nand) udelay(10)
> +
> +#endif /* __CONFIG_H */

Pillai, Manikandan

unread,
Jul 25, 2008, 3:21:30 AM7/25/08
to beagl...@googlegroups.com
Hi all,

Pls find the Patch 2/3 for support of Ethernet on OMAP3EVM.
I have reused the existing 911x source code for supporting the Ethernet rather than adding a new file.

The tftp size has been changed back to 512 - After a tftp is done for the kernel
And/or filesystem the downloaded image does not work. (On diving more, I found that there are some memory corruptions at offsets of 0x4F8.)

Pls send me your comments.

Thanks and Regards
Mani

________________________________________
From: Pillai, Manikandan
Sent: Thursday, July 24, 2008 9:03 AM
To: 'beagl...@googlegroups.com'
Subject: RE: [beagleboard] Re: Patch series to add OMAP3 EVM support to Sakoman's u-boot Tree - Patch 1/3

Hi all,

I am re-sending the patch (1/3) for support of EVM boards. Since I had issues with earlier mail on the format, I am
sending this one as as attachments. I have run the checkpatch scripts and fixed the relevant warnings.

Pls let me know your comments. I will be sending the remaining two patches by today evening.

Regards
Mani

---------- Forwarded message ----------
From: sakoman <sak...@gmail.com>
Date: Jul 18, 2008 4:13 AM
Subject: [beagleboard] Re: Patch series to add OMAP3 EVM support to Sakoman's u-boot Tree
To: Beagle Board <beagl...@googlegroups.com>


u-boot-omap3-p2.txt

Pillai, Manikandan

unread,
Jul 25, 2008, 6:39:11 AM7/25/08
to beagl...@googlegroups.com
u-boot-omap3-p2.txt

Dirk Behme

unread,
Jul 25, 2008, 11:21:55 AM7/25/08
to Pillai, Manikandan, beagl...@googlegroups.com, Steve Sakoman
Hi Mani,

Pillai, Manikandan wrote:
> I am re-sending the patch (1/3) for support of EVM boards. Since I had
> issues with earlier mail on the format, I am
>
> sending this one as as attachments. I have run the checkpatch scripts
> and fixed the relevant warnings.

Thanks! There is a small pitfall, though. Kernel's checkpatch script
is a moving target. It may change from kernel version to kernel
version. Most probably this is the reason why I still get some
warnings with the checkpatch script from my 2.6.26-omap1 kernel. For
reference, I attach the result.

> Pls let me know your comments. I will be sending the remaining two
> patches by today evening.

> diff --git a/Makefile b/Makefile


> index e9bf61a..bc6da92 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -2570,6 +2570,9 @@ SMN42_config : unconfig
> omap3530beagle_config : unconfig
> @./mkconfig $(@:_config=) arm omap3 omap3530beagle
>
> +omap3evm_config : unconfig
> + @./mkconfig $(@:_config=) arm omap3 omap3evm
> +

Can you please use @$(MKCONFIG) here. Yes, we did it wrong for Beagle,
too.

> diff --git a/board/omap3evm/sys_info.c b/board/omap3evm/sys_info.c
> new file mode 100644
> index 0000000..a07e94b
> --- /dev/null
> +++ b/board/omap3evm/sys_info.c

> +/**************************************************************************


> + * get_gpmc0_type()
> + ***************************************************************************/
> +u32 get_gpmc0_type(void)
> +{
> + /* Default NAND */
> + return (2);
> +}

Here you should return 1 for OneNand. Thanks to Steve for this hint.

Regarding NAND driver there seems to be an issue with it. Steve reports:

"onenand doesn't work. detects the hw just fine, but erase read and
write silently fail unless you turn on mtd debugging. then there is
just enough delay that it starts to work."

Dirk

checkpatch_p1.txt

Dirk Behme

unread,
Jul 25, 2008, 11:39:32 AM7/25/08
to Pillai, Manikandan, beagl...@googlegroups.com
Hi Mani,

Pillai, Manikandan wrote:
> Pls find the Patch 2/3 for support of Ethernet on OMAP3EVM.

You sent this patch two times. I did a diff, both mails seem to
contain the same attachment. Is this correct or did you want to send
the third patch instead?

> I have reused the existing 911x source code for supporting the Ethernet rather than adding a new file.

Great! This makes the patch much smaller :)

> The tftp size has been changed back to 512 - After a tftp is done for the kernel
> And/or filesystem the downloaded image does not work. (On diving more, I found that there are some memory corruptions at offsets of 0x4F8.)

Keep us up to date regarding this.

> Pls send me your comments.

Same comment regarding checkpatch as for patch 1. See attachment. Yes,
I agree, volatile and extern warnings we can ignore for now, but maybe
you like to fix the other remaining warnings.

> ------------------------------------------------------------------------
>
> From dbe9edd3cf156743c504674962da12265e3434fb Mon Sep 17 00:00:00 2001
> From: Manikandan K Pillai <mani....@ti.com>
> Date: Fri, 25 Jul 2008 12:30:38 +0530
> Subject: [PATCH] Patch to put in NET support for OMAP3 EVM - DEV_a0393249_OMAP3EVM_NET_PATCH
>
>
> Signed-off-by: Manikandan K Pillai <mani....@ti.com>
...
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 84be288..00bcf29 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -66,6 +66,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
> COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
> COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
> COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
> +COBJS-$(CONFIG_DRIVER_SMC911X) += smc911x.o
>
> COBJS := $(COBJS-y)
> SRCS := $(COBJS:.o=.c)

This rejects for me as my Makefile has an additional sh_ether after
emaclite:

COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
COBJS-$(CONFIG_SH_ETHER) += sh_eth.o

Dirk

checkpatch_p2.txt

Dirk Behme

unread,
Jul 25, 2008, 11:45:07 AM7/25/08
to Pillai, Manikandan, beagl...@googlegroups.com, Steve Sakoman
Dirk Behme wrote:

>> +u32 get_gpmc0_type(void)
>> +{
>> + /* Default NAND */
>> + return (2);
>> +}
>
>
> Here you should return 1 for OneNand. Thanks to Steve for this hint.
>
> Regarding NAND driver there seems to be an issue with it. Steve reports:
>
> "onenand doesn't work. detects the hw just fine, but erase read and
> write silently fail unless you turn on mtd debugging. then there is just
> enough delay that it starts to work."

fyi, see IRC log

http://www.beagleboard.org/irclogs/index.php?date=2008-07-25#T15:32:50

for more details regarding this.

Dirk

Pillai, Manikandan

unread,
Jul 29, 2008, 7:12:49 AM7/29/08
to Dirk Behme, beagl...@googlegroups.com
Hi all,

Pls find attached Patch 2/2 for OMAP3EVM. This adds Ethernet support for OMAP3EVM.

Pls let me know your comments.

Regards
Mani

omap3evm_patch2.txt

Pillai, Manikandan

unread,
Jul 29, 2008, 7:11:15 AM7/29/08
to Dirk Behme, beagl...@googlegroups.com, Steve Sakoman
Hi all,

Hope to get it right this time. I am attaching patch (1/2) for OMAP3EVM support I have tried to fix the relevant comments.

This patch provides OMAP3EVM support on UBoot.


Regards
Mani

-----Original Message-----
From: Dirk Behme [mailto:dirk....@googlemail.com]
Sent: Friday, July 25, 2008 8:52 PM
To: Pillai, Manikandan

omap3evm_patch1.txt

Dirk Behme

unread,
Jul 29, 2008, 12:42:53 PM7/29/08
to Pillai, Manikandan, beagl...@googlegroups.com
Mani,

Pillai, Manikandan wrote:
> Hope to get it right this time.

Yes.

http://www.sakoman.net/cgi-bin/gitweb.cgi?p=u-boot-omap3.git;a=commit;h=9867aa192ea0ed0c797ea2a2b8c48ab919b80e4c

http://www.sakoman.net/cgi-bin/gitweb.cgi?p=u-boot-omap3.git;a=commit;h=b2980a3b0e5bcd6b3696e579e76eeb06276df79b

:)

Thanks for your help!

Hopfully you like to help with further uboot v1 clean up now to get it
upstream ready. If interested, maybe you like to have a look to (a) -
(h) at

http://groups.google.com/group/beagleboard/browse_thread/thread/0f1991bbc9318fe0#

Thanks

Dirk

Pillai, Manikandan

unread,
Aug 5, 2008, 12:59:03 AM8/5/08
to Dirk Behme, beagl...@googlegroups.com
Hi all,

Pls find attached the patch for I2C timeout errors.

I had initially thought the problem to be related to the compiler. Diving deep found that for some reason due to divide by 0, the compiler generates wrong values for writing to a register. This was happening because of I2C_SPEED being
passed as 100 rather than 100000 (for 100KB).

Pls review the patch and send me your comments. Meanwhile, I will get to some
of the cleanup activities.

Regards
Mani

-----Original Message-----
From: Dirk Behme [mailto:dirk....@googlemail.com]
Sent: Tuesday, July 29, 2008 10:13 PM
To: Pillai, Manikandan
Cc: beagl...@googlegroups.com

u-boot-i2c-p1.txt

Dirk Behme

unread,
Aug 5, 2008, 12:37:06 PM8/5/08
to Pillai, Manikandan, beagl...@googlegroups.com
Pillai, Manikandan wrote:
> Hi all,
>
> Pls find attached the patch for I2C timeout errors.

Many thanks! Will try it.

Dirk

> ------------------------------------------------------------------------
>
> From 0aa69f3767960a404d8c15b4dabf5e033014b67c Mon Sep 17 00:00:00 2001
> From: Manikandan Pillai <mani....@ti.com>
> Date: Tue, 5 Aug 2008 10:04:00 +0530
> Subject: [PATCH] Fix for uboot I2C timeouts with 2008Q1 compiler
>
>
> Signed-off-by: Manikandan Pillai <mani....@ti.com>
> ---
> include/configs/omap3evm.h | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/include/configs/omap3evm.h b/include/configs/omap3evm.h
> index dd30d76..53a65ba 100644
> --- a/include/configs/omap3evm.h
> +++ b/include/configs/omap3evm.h
> @@ -124,7 +124,7 @@
>
>
> #define CFG_NO_FLASH
> -#define CFG_I2C_SPEED 100
> +#define CFG_I2C_SPEED 100000
> #define CFG_I2C_SLAVE 1
> #define CFG_I2C_BUS 0
> #define CFG_I2C_BUS_SELECT 1

Pillai, Manikandan

unread,
Aug 6, 2008, 1:31:51 AM8/6/08
to Dirk Behme, beagl...@googlegroups.com

Hi all,

Pls find attached the patch(1/1) to fix issues regarding offset values to be given while using onenand command for read/write/erase ... operations.

Pls let me know your comments.

Regards

u-boot-onnd-p1.txt

Steve Sakoman

unread,
Aug 8, 2008, 12:01:50 AM8/8/08
to beagl...@googlegroups.com, Dirk Behme
Mani,

Thanks!

Pushed this evening -- also for overo and beagle

Steve

PS: x-load also had this issue, fixed there too

> From 0aa69f3767960a404d8c15b4dabf5e033014b67c Mon Sep 17 00:00:00 2001
> From: Manikandan Pillai <mani....@ti.com>
> Date: Tue, 5 Aug 2008 10:04:00 +0530
> Subject: [PATCH] Fix for uboot I2C timeouts with 2008Q1 compiler
>
>
> Signed-off-by: Manikandan Pillai <mani....@ti.com>
> ---
> include/configs/omap3evm.h | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/include/configs/omap3evm.h b/include/configs/omap3evm.h
> index dd30d76..53a65ba 100644
> --- a/include/configs/omap3evm.h
> +++ b/include/configs/omap3evm.h
> @@ -124,7 +124,7 @@
>
>
> #define CFG_NO_FLASH
> -#define CFG_I2C_SPEED 100
> +#define CFG_I2C_SPEED 100000
> #define CFG_I2C_SLAVE 1
> #define CFG_I2C_BUS 0
> #define CFG_I2C_BUS_SELECT 1

> --
> 1.5.6
>
>
>

Steve Sakoman

unread,
Aug 8, 2008, 12:14:53 AM8/8/08
to beagl...@googlegroups.com
Mani,

The patch, as written, will break overo! I want to be carefull to
keep evm, beagle, and overo working.

We should also probably separate this into two patches: one to fix the
offset bug for evm, beagle, and overo; and a second to add the
'onenand erase block' command.

Regards,

Steve

On Tue, Aug 5, 2008 at 10:31 PM, Pillai, Manikandan <mani....@ti.com> wrote:
>
> Hi all,
>
> Pls find attached the patch(1/1) to fix issues regarding offset values to be given while using onenand command for read/write/erase ... operations.
>
> Pls let me know your comments.
>
> Regards
> Mani
>
> -----Original Message-----
> From: Dirk Behme [mailto:dirk....@googlemail.com]
> Sent: Tuesday, August 05, 2008 10:07 PM
> To: Pillai, Manikandan
> Cc: beagl...@googlegroups.com
> Subject: Re: Patch to fix the UBoot I2C Timeout errors
>
> Pillai, Manikandan wrote:
>> Hi all,
>>
>> Pls find attached the patch for I2C timeout errors.
>
> Many thanks! Will try it.
>
> Dirk
>
>> I had initially thought the problem to be related to the compiler. Diving deep found that for some reason due to divide by 0, the compiler generates wrong values for writing to a register. This was happening because of I2C_SPEED being
>> passed as 100 rather than 100000 (for 100KB).
>>
>> Pls review the patch and send me your comments. Meanwhile, I will get to some
>> of the cleanup activities.
>>
>> Regards
>> Mani
>>
>
> >
>

> From 344c4a1b2c48c9fa9e622540250de9e0e8003eea Mon Sep 17 00:00:00 2001
> From: Manikandan Pillai <mani....@ti.com>
> Date: Wed, 6 Aug 2008 10:40:09 +0530
> Subject: [PATCH] Fix up for ONENAND flash offset for read/write operations


>
>
> Signed-off-by: Manikandan Pillai <mani....@ti.com>
> ---

> board/omap3evm/mem.c | 2 +-
> common/cmd_onenand.c | 48 +++++++++++++++++++++++++++---------------------
> common/env_onenand.c | 12 +++---------
> 3 files changed, 31 insertions(+), 31 deletions(-)
>
> diff --git a/board/omap3evm/mem.c b/board/omap3evm/mem.c
> index ba95317..0340aa5 100644
> --- a/board/omap3evm/mem.c
> +++ b/board/omap3evm/mem.c
> @@ -267,7 +267,7 @@ void gpmc_init(void)
> size = PISMO1_ONEN_SIZE;
> enable_gpmc_config(gpmc_config, gpmc_base, base, size);
>
> - f_off = (ONENAND_MAP + ONENAND_ENV_OFFSET);
> + f_off = ONENAND_ENV_OFFSET;
> f_sec = SZ_128K;
> is_onenand = 1;
> onenand_cs_base = gpmc_base;
> diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
> index 86a7420..2dfcd49 100644
> --- a/common/cmd_onenand.c
> +++ b/common/cmd_onenand.c
> @@ -32,8 +32,9 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
> case 1:
> printf("Usage:\n%s\n", cmdtp->usage);
> return 1;
> -
> + /* printf version info if no of arguments are not enough */
> case 2:
> + case 3:
> if (strncmp(argv[1], "open", 4) == 0) {
> onenand_init();
> return 0;
> @@ -47,8 +48,8 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
> struct erase_info instr = {
> .callback = NULL,
> };
> - ulong start, end;
> - ulong block;
> + ulong start = 0, end = 0;
> + ulong block = 0;
> char *endtail;
>
> if (strncmp(argv[2], "block", 5) == 0) {
> @@ -58,10 +59,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
> } else {
> start = simple_strtoul(argv[2], NULL, 10);
> end = simple_strtoul(argv[3], NULL, 10);
> -#ifndef CONFIG_OVERO
> - start -= (unsigned long)onenand_chip.base;
> - end -= (unsigned long)onenand_chip.base;
> -#endif
> start >>= onenand_chip.erase_shift;
> end >>= onenand_chip.erase_shift;
> /* Don't include the end block */
> @@ -87,14 +84,16 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
> }
>
> if (strncmp(argv[1], "read", 4) == 0) {
> + size_t len = 0, retlen = 0;
> ulong addr = simple_strtoul(argv[2], NULL, 16);
> ulong ofs = simple_strtoul(argv[3], NULL, 16);
> - size_t len = simple_strtoul(argv[4], NULL, 16);
> - size_t retlen = 0;
> int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
> -#ifndef CONFIG_OVERO
> - ofs -= (unsigned long)onenand_chip.base;
> -#endif
> +
> + if (argc >= 5)
> + len = simple_strtoul(argv[4], NULL, 16);
> + else
> + return 1;
> +
> if (oob)
> onenand_read_oob(&onenand_mtd, ofs, len,
> &retlen, (u_char *) addr);
> @@ -107,13 +106,14 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
> }
>
> if (strncmp(argv[1], "write", 5) == 0) {
> + size_t len = 0, retlen = 0;
> ulong addr = simple_strtoul(argv[2], NULL, 16);
> ulong ofs = simple_strtoul(argv[3], NULL, 16);
> - size_t len = simple_strtoul(argv[4], NULL, 16);
> - size_t retlen = 0;
> -#ifndef CONFIG_OVERO
> - ofs -= (unsigned long)onenand_chip.base;
> -#endif
> + if (argc >= 5)
> + len = simple_strtoul(argv[4], NULL, 16);
> + else
> + return 1;
> +
> onenand_write(&onenand_mtd, ofs, len, &retlen,
> (u_char *) addr);
> printf("Done\n");
> @@ -122,14 +122,19 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
> }
>
> if (strncmp(argv[1], "block", 5) == 0) {
> - ulong addr = simple_strtoul(argv[2], NULL, 16);
> - ulong block = simple_strtoul(argv[3], NULL, 10);
> - ulong page = simple_strtoul(argv[4], NULL, 10);
> - size_t len = simple_strtol(argv[5], NULL, 10);
> + ulong page = 0;
> + size_t len = 0;
> size_t retlen = 0;
> ulong ofs;
> + ulong addr = simple_strtoul(argv[2], NULL, 16);
> + ulong block = simple_strtoul(argv[3], NULL, 10);
> int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
>
> + if (argc >= 5)
> + page = simple_strtoul(argv[4], NULL, 10);
> + if (argc >= 6)
> + len = simple_strtol(argv[5], NULL, 10);
> +
> ofs = block << onenand_chip.erase_shift;
> if (page)
> ofs += page << onenand_chip.page_shift;
> @@ -163,6 +168,7 @@ U_BOOT_CMD(
> "onenand read[.oob] addr ofs len - read data at ofs with len to addr\n"
> "onenand write addr ofs len - write data at ofs with len from addr\n"
> "onenand erase saddr eaddr - erase block start addr to end addr\n"
> + "onenand erase block sblk-endblk - erase blocks sblk to endblk\n"
> "onenand block[.oob] addr block [page] [len] - "
> "read data with (block [, page]) to addr"
> );
> diff --git a/common/env_onenand.c b/common/env_onenand.c
> index 8b214e4..ecf93c4 100644
> --- a/common/env_onenand.c
> +++ b/common/env_onenand.c
> @@ -66,9 +66,7 @@ void env_relocate_spec(void)
> size_t retlen;
>
> env_addr = CFG_ENV_ADDR;
> -#ifndef CONFIG_OVERO
> - env_addr -= (unsigned long) onenand_chip.base;
> -#endif
> +
> /* Check OneNAND exist */
> if (onenand_mtd.oobblock)
> /* Ignore read fail */
> @@ -102,9 +100,7 @@ int saveenv(void)
>
> instr.len = CFG_ENV_SIZE;
> instr.addr = env_addr;
> -#ifndef CONFIG_OVERO
> - instr.addr -= (unsigned long)onenand_chip.base;
> -#endif
> +
> if (onenand_erase(&onenand_mtd, &instr)) {
> printf("OneNAND: erase failed at 0x%08lx\n", env_addr);
> return 1;
> @@ -113,9 +109,7 @@ int saveenv(void)
> /* update crc */
> env_ptr->crc =
> crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));
> -#ifndef CONFIG_OVERO
> - env_addr -= (unsigned long)onenand_chip.base;
> -#endif
> +
> if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.oobblock, &retlen,
> (u_char *) env_ptr)) {
> printf("OneNAND: write failed at 0x%08x\n", instr.addr);
> --
> 1.5.6
>
>
>

Steve Sakoman

unread,
Aug 8, 2008, 12:27:50 AM8/8/08
to beagl...@googlegroups.com
Oops! My mistake, it won't break overo. I should get some sleep :-)

It *might* break other machines that currently expect the offset to be
subtracted, so it could be an issue getting this patch accepted
upstream. That was the reason I originally structured the overo fix
the way that I did - the behaviour did not change for non-overo
machines.

That said, I suspect that users of other machines that include onenand
are also annoyed by this bizzare behavior. So we might get a welcome
reception if we propose a patch that fixes it for all machines that
use onenand.

Steve

Dirk Behme

unread,
Aug 10, 2008, 5:42:30 AM8/10/08
to Steve Sakoman, Pillai, Manikandan, beagl...@googlegroups.com
Steve, Mani,

Steve Sakoman wrote:
> Oops! My mistake, it won't break overo. I should get some sleep :-)
>
> It *might* break other machines that currently expect the offset to be
> subtracted, so it could be an issue getting this patch accepted
> upstream. That was the reason I originally structured the overo fix
> the way that I did - the behaviour did not change for non-overo
> machines.
>
> That said, I suspect that users of other machines that include onenand
> are also annoyed by this bizzare behavior. So we might get a welcome
> reception if we propose a patch that fixes it for all machines that
> use onenand.

I like to send something like in attachment as RFC to U-Boot list.

Do you like to have a look to it if I got it right? Do you like this?

Many thanks

Dirk

remove_onenand_base_address_offset.txt

Steve Sakoman

unread,
Aug 10, 2008, 10:53:17 AM8/10/08
to Dirk Behme, Pillai, Manikandan, beagl...@googlegroups.com
Dirk,

Looks good to me.

Steve

> To: u-b...@lists.denx.de, Kyungmin Park <kyungm...@samsung.com>
> Subject: [RFC][PATCH] OneNAND: Remove base address offset usage
>
> While locally preparing some U-Boot patches for ARM based OMAP3 boards, some
> using OneNAND and some using NAND, we found some differences in OneNAND and
> NAND command address handling.
>
> As this might confuse users (it already confused us), we like to align
> OneNAND
> and NAND address handling.
>
> The issue is that cmd_onenand.c subtracts the onenand base address from the
> addresses you type into the u-boot command line so, unlike nand, you can't
> use addresses relative to the start of the onenand part e.g. this won't
> work:
>
> onenand read 82000000 280000 400000
>
> you have to use:
>
> onenand read 82000000 20280000 400000
>
> Looking at recent git, the only board currently using OneNAND is Apollon,
> and
> for this the OneNAND base address is 0 (apollon.h)
>
> #define CFG_ONENAND_BASE 0x00000000
>
> so patch below won't break any existing boards and will align OneNAND and
> NAND
> handling on boards where OneNAND base address is != 0.
>
> Signed-off-by: Steve Sakoman <sak...@gmail.com>
> Signed-off-by: Manikandan Pillai <mani....@ti.com>
> Signed-off-by: Dirk Behme <dirk....@gmail.com>
>
>
> Index: foo/common/cmd_onenand.c
> ===================================================================
> --- foo.orig/common/cmd_onenand.c
> +++ foo/common/cmd_onenand.c
> @@ -58,8 +58,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int fl


> } else {
> start = simple_strtoul(argv[2], NULL, 10);
> end = simple_strtoul(argv[3], NULL, 10);

> - start -= (unsigned long)onenand_chip.base;
> - end -= (unsigned long)onenand_chip.base;
>

> start >>= onenand_chip.erase_shift;
> end >>= onenand_chip.erase_shift;

> @@ -92,8 +90,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int fl


> size_t retlen = 0;
> int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
>

> - ofs -= (unsigned long)onenand_chip.base;
> -

> if (oob)
> onenand_read_oob(&onenand_mtd, ofs, len,
> &retlen, (u_char *) addr);

> @@ -111,8 +107,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int fl


> size_t len = simple_strtoul(argv[4], NULL, 16);

> size_t retlen = 0;


>
> - ofs -= (unsigned long)onenand_chip.base;
> -

> onenand_write(&onenand_mtd, ofs, len, &retlen,
> (u_char *) addr);
> printf("Done\n");

> Index: foo/common/env_onenand.c
> ===================================================================
> --- foo.orig/common/env_onenand.c
> +++ foo/common/env_onenand.c
> @@ -66,7 +66,6 @@ void env_relocate_spec(void)


> size_t retlen;
>
> env_addr = CFG_ENV_ADDR;

> - env_addr -= (unsigned long) onenand_chip.base;
>

> /* Check OneNAND exist */
> if (onenand_mtd.oobblock)

> @@ -101,7 +100,6 @@ int saveenv(void)


>
> instr.len = CFG_ENV_SIZE;
> instr.addr = env_addr;

> - instr.addr -= (unsigned long)onenand_chip.base;

> if (onenand_erase(&onenand_mtd, &instr)) {
> printf("OneNAND: erase failed at 0x%08lx\n", env_addr);
> return 1;

> @@ -111,7 +109,6 @@ int saveenv(void)


> env_ptr->crc =
> crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));
>

> - env_addr -= (unsigned long)onenand_chip.base;

Steve Sakoman

unread,
Aug 11, 2008, 12:30:41 PM8/11/08
to Dirk Behme, Pillai, Manikandan, beagl...@googlegroups.com
Dirk,

I see the patch has already be accepted upstream. Good work!

You might also want to consider submitting this one:

http://www.sakoman.net/cgi-bin/gitweb.cgi?p=u-boot-omap3.git;a=commit;h=8406a19891788a3d86f6d20d6c3fa64e6db71616

I merged with upstream -- sadly one of the upstream commits (actually
a revert) broke the build. It introduces an extra #endif.

I'm testing a patch to fix this.

Thanks!

Steve

Dirk Behme

unread,
Aug 11, 2008, 2:33:20 PM8/11/08
to Steve Sakoman, beagl...@googlegroups.com
Steve,

Steve Sakoman wrote:
> Dirk,
>
> I see the patch has already be accepted upstream. Good work!
>
> You might also want to consider submitting this one:
>
> http://www.sakoman.net/cgi-bin/gitweb.cgi?p=u-boot-omap3.git;a=commit;h=8406a19891788a3d86f6d20d6c3fa64e6db71616

Done.

> I merged with upstream -- sadly one of the upstream commits (actually
> a revert) broke the build. It introduces an extra #endif.
>
> I'm testing a patch to fix this.

Sent this fix, too. And got immediately a response pointing to a
larger patch for this. I didn't follow this autostart discussion, but
seems that there is something additional broken. E.g. apollon build
stops with

bootm.c: In function 'do_bootm_linux':
bootm.c:140: error: 'bootm_headers_t' has no member named 'autostart'
bootm.c:160: error: 'bootm_headers_t' has no member named 'autostart'

Let us see which solution Wolfgang will take.

Many thanks

Dirk

Steve Sakoman

unread,
Aug 11, 2008, 2:48:02 PM8/11/08
to Dirk Behme, beagl...@googlegroups.com
> Sent this fix, too. And got immediately a response pointing to a larger
> patch for this. I didn't follow this autostart discussion, but seems that
> there is something additional broken. E.g. apollon build stops with
>
> bootm.c: In function 'do_bootm_linux':
> bootm.c:140: error: 'bootm_headers_t' has no member named 'autostart'
> bootm.c:160: error: 'bootm_headers_t' has no member named 'autostart'
>
> Let us see which solution Wolfgang will take.

Yes, I got the same error on overo and beagle. At that point I
decided to let Wolfgang fix it :-)

Steve

Dirk Behme

unread,
Aug 12, 2008, 10:44:46 AM8/12/08
to beagl...@googlegroups.com, Steve Sakoman
Dirk Behme wrote:
> Steve,
>
> Steve Sakoman wrote:
>
>> Dirk,
>>
>> I see the patch has already be accepted upstream. Good work!
>>
>> You might also want to consider submitting this one:
>>
>> http://www.sakoman.net/cgi-bin/gitweb.cgi?p=u-boot-omap3.git;a=commit;h=8406a19891788a3d86f6d20d6c3fa64e6db71616
>>
>
> Done.

Applied:

http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=commit;h=4d57b0fb2927d4f50d834884b4ec4a7ca01708b0

>> I merged with upstream -- sadly one of the upstream commits (actually
>> a revert) broke the build. It introduces an extra #endif.
>>
>> I'm testing a patch to fix this.
>
>
> Sent this fix, too. And got immediately a response pointing to a larger
> patch for this. I didn't follow this autostart discussion, but seems
> that there is something additional broken. E.g. apollon build stops with
>
> bootm.c: In function 'do_bootm_linux':
> bootm.c:140: error: 'bootm_headers_t' has no member named 'autostart'
> bootm.c:160: error: 'bootm_headers_t' has no member named 'autostart'
>
> Let us see which solution Wolfgang will take.

Kumar Gala's "Fix fallout from autostart revert" patch is applied,
too. Have to check if recent git compiles now.

Dirk

Reply all
Reply to author
Forward
0 new messages