diff mbox

[U-Boot,3/9] apf9328: Add Armadeus Project board APF9328

Message ID 20110810203315.21204.35859.stgit@shuttle2.etheralp.ch
State Changes Requested
Delegated to: Stefano Babic
Headers show

Commit Message

Eric Jarrige Aug. 10, 2011, 8:33 p.m. UTC
Add Armadeus Project board APF9328

Signed-off-by: Eric Jarrige <eric.jarrige@armadeus.org>
Signed-off-by: Nicolas Colombain <nicolas.colombain@armadeus.com>
---
 board/armadeus/apf9328/Makefile        |   51 +++
 board/armadeus/apf9328/apf9328.c       |   91 ++++++
 board/armadeus/apf9328/apf9328fpga.c   |   89 ++++++
 board/armadeus/apf9328/apf9328fpga.h   |   31 ++
 board/armadeus/apf9328/eeprom.c        |   88 ++++++
 board/armadeus/apf9328/fpga.c          |  121 ++++++++
 board/armadeus/apf9328/fpga.h          |   30 ++
 board/armadeus/apf9328/i2c.c           |  276 +++++++++++++++++++
 board/armadeus/apf9328/lowlevel_init.S |  469 ++++++++++++++++++++++++++++++++
 9 files changed, 1246 insertions(+), 0 deletions(-)
 create mode 100644 board/armadeus/apf9328/Makefile
 create mode 100644 board/armadeus/apf9328/apf9328.c
 create mode 100644 board/armadeus/apf9328/apf9328fpga.c
 create mode 100644 board/armadeus/apf9328/apf9328fpga.h
 create mode 100644 board/armadeus/apf9328/eeprom.c
 create mode 100644 board/armadeus/apf9328/fpga.c
 create mode 100644 board/armadeus/apf9328/fpga.h
 create mode 100644 board/armadeus/apf9328/i2c.c
 create mode 100644 board/armadeus/apf9328/lowlevel_init.S

Comments

Stefano Babic Aug. 11, 2011, 8:50 a.m. UTC | #1
On 08/10/2011 10:33 PM, Eric Jarrige wrote:
> Add Armadeus Project board APF9328
> 
> Signed-off-by: Eric Jarrige <eric.jarrige@armadeus.org>
> Signed-off-by: Nicolas Colombain <nicolas.colombain@armadeus.com>

Hi Eric,


> diff --git a/board/armadeus/apf9328/apf9328.c b/board/armadeus/apf9328/apf9328.c
> new file mode 100644
> index 0000000..2250221
> --- /dev/null
> +++ b/board/armadeus/apf9328/apf9328.c
> @@ -0,0 +1,91 @@
> +/*
> + * (C) Copyright 2005-2011
> + * Nicolas Colombin <thom25@users.sourceforge.net>
> + * Eric Jarrige <eric.jarrige@armadeus.org>
> + * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + *
> + */
> +
> +#include <common.h>
> +#include <asm/arch/imx-regs.h>
> +#include <flash.h>
> +#include <netdev.h>
> +#include "apf9328fpga.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int board_init(void)
> +{
> +	gd->bd->bi_arch_number = CONFIG_MACH_TYPE;

Is there no MACH_TYPE for this board ? It is uncommon for an ARM board.
Should this board run Linux ?

> +void dram_init_banksize(void)
> +{
> +#if (CONFIG_NR_DRAM_BANKS > 0)

I think you can get rid of this #ifdef, if you have no RAM at all you
cannot simply run u-boot.

> + * Miscellaneous intialization
> + */
> +int misc_init_r(void)
> +{
> +	char *s;
> +
> +#if (CONFIG_FPGA)
> +	apf9328_init_fpga();
> +#endif
> +
> +#if (CONFIG_DRIVER_DM9000)
> +	imx_gpio_mode(GPIO_PORTB | GPIO_DR | GPIO_IN | 14);

Is there a reason to put this code here and not in board_eth_init ? It
is related to Ethernet and I am supposing this setup should be done
before dm9000_initialize.

> +
> +void show_boot_progress(int status)
> +{
> +	return;
> +}

This function seems to me not very useful. Is it not better to drop it ?
It is not strictly required.
You set also #undef CONFIG_SHOW_BOOT_PROGRESS in the configuration file.


> +#if (CONFIG_FPGA)
> +DECLARE_GLOBAL_DATA_PTR;
> +/* Note that these are pointers to code that is in Flash.  They will be
> + * relocated at runtime.
> + * Spartan3 code is used to download our Spartan 3 :) code is compatible.
> + * Just take care about the file size
> +*/
> +Xilinx_Spartan3_Slave_Serial_fns fpga_fns = {
> +	fpga_pre_fn,
> +	fpga_pgm_fn,
> +	fpga_clk_fn,
> +	fpga_init_fn,
> +	fpga_done_fn,
> +	fpga_wr_fn,
> +};
> +
> +Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {

Do you have more as one FPGA on your board ? And if this is true, they
share the same firmware ? (I see only one CONFIG_FIRMWARE_ADDR..)

> +/*
> + * Initialize the fpga.  Return 1 on success, 0 on failure.
> + */
> +int apf9328_init_fpga(void)
> +{
> +	char *autoload = getenv("firmware_autoload");
> +	int i, lout = 1;
> +
> +	debug("%s:%d: Initialize FPGA interface (relocation offset= 0x%.8lx)\n",
> +		__func__, __LINE__, gd->reloc_off);
> +
> +	fpga_init();
> +
> +	for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
> +		debug("%s:%d: Adding fpga %d\n", __func__, __LINE__, i);
> +		fpga_add(fpga_xilinx, &fpga[i]);
> +	}
> +
> +	if ((autoload) && (0 == strcmp(autoload, "1"))) {
> +		if (FPGA_SUCCESS != fpga_load(0, (void *)CONFIG_FIRMWARE_ADDR,

I am confused...you add in the configuration file a variable
"firmware_addr=", and you set it as default to CONFIG_FIRMWARE_ADDR, but
you do not use this variable at all. Do you not shoul get the address
with getenv("firmware_addr") instead of the precompiled value ?

If you add some new CONFIG_ switches in U-Boot, you must document them
in the Readme file. However, CONFIG_FIRMWARE_* do not need to be global,
right ?

> +/*
> + * Spartan 3 FPGA configuration support for the APF9328 daughter board
> + */
> +
> +#include "fpga.h"
> +extern int apf9328_init_fpga(void);
> diff --git a/board/armadeus/apf9328/eeprom.c b/board/armadeus/apf9328/eeprom.c

It seems to much fo me to add a new file only for a single prototype.
and it is used only in apf9328fpga.c, as I can see.

> +
> +#include <common.h>
> +#include <command.h>
> +#include <dm9000.h>
> +
> +static int do_read_dm9000_eeprom(cmd_tbl_t *cmdtp, int flag, int argc,
> +				 char * const argv[])
> +{
> +	unsigned int i;
> +	u8 data[2];
> +
> +	for (i = 0; i < 0x40; i++) {
> +		if (!(i % 0x10))
> +			printf("\n%08x:", i);
> +		dm9000_read_srom_word(i, data);
> +		printf(" %02x%02x", data[1], data[0]);
> +	}

These functions can be factorized. I think the best place is inside the
DM9000 driver itself, removing them from board code.


> +#include <common.h>
> +
> +#if (CONFIG_FPGA)

#ifdef. We do not want to explicitely set the value for the CONFIG_
switches. It must be enough to use

#define CONFIG_FPGA

in your configuration file,

> +/*
> + * nitialize GPIO port B before download

Initialize

> +extern int fpga_pre_fn(int cookie);
> +extern int fpga_pgm_fn(int assert_pgm, int flush, int cookie);
> +extern int fpga_init_fn(int cookie);
> +extern int fpga_done_fn(int cookie);
> +extern int fpga_clk_fn(int assert_clk, int flush, int cookie);
> +extern int fpga_wr_fn(int assert_write, int flush, int cookie);

Maybe can you add here the prototy you set in apf9328.h ?

> diff --git a/board/armadeus/apf9328/i2c.c b/board/armadeus/apf9328/i2c.c

This is a I2C driver, and must be stored into drivers/i2c, not in board
directory. Please split your patch and push a separate patch only for
the I2C code, sending it to the I2C maintainer, too.

> +#include <common.h>
> +
> +#ifdef CONFIG_HARD_I2C
> +
> +#include <asm/io.h>
> +#include <asm/arch/imx-regs.h>
> +#include <i2c.h>
> +
> +/*-----------------------------------------------------------------------
> + * Definitions
> + */
> +
> +#define I2C_ACK		0	/* level to ack a byte */
> +#define I2C_NOACK	1	/* level to noack a byte */
> +
> +/*-----------------------------------------------------------------------
> + * Local functions
> + */
> +
> +/*-----------------------------------------------------------------------
> + * START: High -> Low on SDA while SCL is High
> + * after check for a bus free
> + */
> +static void imxi2c_send_start(void)
> +{
> +	while (I2SR & I2SR_IBB)
> +		udelay(1);

You are using the __REG macros, that are not allowed anymore in new
u-boot code. Instead of that, please add C structure and use general
accessors (writel, readl,...) to access to the registers. This comment
apply to the whole code here.


> diff --git a/board/armadeus/apf9328/lowlevel_init.S b/board/armadeus/apf9328/lowlevel_init.S
> new file mode 100644
> index 0000000..e4c6157
> --- /dev/null
> +++ b/board/armadeus/apf9328/lowlevel_init.S
> @@ -0,0 +1,469 @@
> +/*
> + * (C) Copyright 2005-2011 ej Armadeus Project <eric.jarrige@armadeus.org>
> + * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + *
> + */
> +
> +#include <config.h>
> +#include <version.h>
> +#include <asm/arch/imx-regs.h>
> +
> +.globl lowlevel_init
> +lowlevel_init:
> +/* Change PERCLK1DIV to 14 ie 14+1 */
> +	ldr		r0,	=PCDR
> +	ldr		r1,	=CONFIG_SYS_PCDR_VAL
> +	str		r1,	[r0]
> +
> +/* set MCU PLL Control Register 0 */
> +
> +	ldr		r0,	=MPCTL0
> +	ldr		r1,	=CONFIG_SYS_MPCTL0_VAL
> +	str		r1,	[r0]
> +
> +/* set MCU PLL Control Register 1 */
> +
> +	ldr		r0,	=MPCTL1
> +	ldr		r1,	=CONFIG_SYS_MPCTL1_VAL
> +	str		r1,	[r0]
> +
> +/* set mpll restart bit */
> +	ldr		r0, =CSCR
> +	ldr		r1, [r0]
> +	orr		r1,r1,#(1<<21)
> +	str		r1, [r0]
> +
> +	mov		r2,#0x10
> +1:
> +	mov		r3,#0x2000
> +2:
> +	subs	r3,r3,#1
> +	bne		2b
> +
> +	subs	r2,r2,#1
> +	bne		1b
> +
> +/* set System PLL Control Register 0 */
> +
> +	ldr		r0,	=SPCTL0
> +	ldr		r1,	=CONFIG_SYS_SPCTL0_VAL
> +	str		r1,	[r0]
> +
> +/* set System PLL Control Register 1 */
> +
> +	ldr		r0,	=SPCTL1
> +	ldr		r1,	=CONFIG_SYS_SPCTL1_VAL
> +	str		r1,	[r0]
> +
> +/* set spll restart bit */
> +	ldr		r0, =CSCR
> +	ldr		r1, [r0]
> +	orr		r1,r1,#(1<<22)
> +	str		r1, [r0]
> +
> +	mov		r2,#0x10
> +1:
> +	mov		r3,#0x2000
> +2:
> +	subs	r3,r3,#1
> +	bne		2b
> +
> +	subs	r2,r2,#1
> +	bne		1b
> +
> +	ldr		r0,	=CSCR
> +	ldr		r1,	=CONFIG_SYS_CSCR_VAL
> +	str		r1,	[r0]
> +
> +	ldr		r0,	=GPCR
> +	ldr		r1,	=CONFIG_SYS_GPCR_VAL
> +	str		r1,	[r0]
> +
> +/* I have now read the ARM920 DataSheet back-to-Back, and have stumbled upon
> + *this.....
> + *
> + * It would appear that from a Cold-Boot the ARM920T enters "FastBus" mode CP15
> + * register 1, this stops it using the output of the PLL and thus runs at the
> + * slow rate. Unless you place the Core into "Asynch" mode, the CPU will never
> + * use the value set in the CM_OSC registers...regardless of what you set it
> + * too!  Thus, although i thought i was running at 140MHz, i'm actually running
> + * at 40!..
> +
> + * Slapping this into my bootloader does the trick...
> +
> + * MRC p15,0,r0,c1,c0,0	 ; read core configuration register
> + * ORR r0,r0,#0xC0000000	; set asynchronous clocks and not fastbus mode
> + * MCR p15,0,r0,c1,c0,0	 ; write modified value to core configuration
> + * register
> + */
> +	MRC p15,0,r0,c1,c0,0
> +	ORR r0,r0,#0xC0000000
> +	MCR p15,0,r0,c1,c0,0
> +
> +/*	ldr		r0,	=GPR(0)

Do not add dead code, simply drop it.

However, this code is quite the same I can find on other IMX boards. Can
we factorize it and push it as common code ?

Best regards,
Stefano Babic
Eric Jarrige Aug. 11, 2011, 11:41 p.m. UTC | #2
Hi Stefano,

> On 08/10/2011 10:33 PM, Eric Jarrige wrote:
>> Add Armadeus Project board APF9328
>> 
>> Signed-off-by: Eric Jarrige <eric.jarrige@armadeus.org>
>> Signed-off-by: Nicolas Colombain <nicolas.colombain@armadeus.com>
> 
> Hi Eric,
> 
> 
>> diff --git a/board/armadeus/apf9328/apf9328.c b/board/armadeus/apf9328/apf9328.c
>> new file mode 100644
>> index 0000000..2250221
>> --- /dev/null
>> +++ b/board/armadeus/apf9328/apf9328.c
>> @@ -0,0 +1,91 @@
>> +/*
>> + * (C) Copyright 2005-2011
>> + * Nicolas Colombin <thom25@users.sourceforge.net>
>> + * Eric Jarrige <eric.jarrige@armadeus.org>
>> + * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation; either version 2 of
>> + * the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
>> + * MA 02111-1307 USA
>> + *
>> + */
>> +
>> +#include <common.h>
>> +#include <asm/arch/imx-regs.h>
>> +#include <flash.h>
>> +#include <netdev.h>
>> +#include "apf9328fpga.h"
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +int board_init(void)
>> +{
>> +	gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
> 
> Is there no MACH_TYPE for this board ? It is uncommon for an ARM board.
> Should this board run Linux ?
The MACH_TYPE for this board is 906. This board runs linux and the integration in linux is on going.
> 
>> +void dram_init_banksize(void)
>> +{
>> +#if (CONFIG_NR_DRAM_BANKS > 0)
> 
> I think you can get rid of this #ifdef, if you have no RAM at all you
> cannot simply run u-boot.
Good point. I will fix it.

> 
>> + * Miscellaneous intialization
>> + */
>> +int misc_init_r(void)
>> +{
>> +	char *s;
>> +
>> +#if (CONFIG_FPGA)
>> +	apf9328_init_fpga();
>> +#endif
>> +
>> +#if (CONFIG_DRIVER_DM9000)
>> +	imx_gpio_mode(GPIO_PORTB | GPIO_DR | GPIO_IN | 14);
> 
> Is there a reason to put this code here and not in board_eth_init ? It
> is related to Ethernet and I am supposing this setup should be done
> before dm9000_initialize.
The idea is to keep the configuration  of the CPU pins at one place and to keep the initialization of the ethernet controller in a separate function. 
Here this principle of segregation is not obvious as there is only one GPIO pin to configure.

 
> 
>> +
>> +void show_boot_progress(int status)
>> +{
>> +	return;
>> +}
> 
> This function seems to me not very useful. Is it not better to drop it ?
> It is not strictly required.
> You set also #undef CONFIG_SHOW_BOOT_PROGRESS in the configuration file.
Well I choosed to keep it in place in empty state to be the template for the final user to add their own debug method if needed.
If it is an issue I would prefer to define the CONFIG_SHOW_BOOT_PROGRESS in the configuration file than removing this empty show_boot_progress as the main purpose of the board is education and trainings on embedded developments.

> 
> 
>> +#if (CONFIG_FPGA)
>> +DECLARE_GLOBAL_DATA_PTR;
>> +/* Note that these are pointers to code that is in Flash.  They will be
>> + * relocated at runtime.
>> + * Spartan3 code is used to download our Spartan 3 :) code is compatible.
>> + * Just take care about the file size
>> +*/
>> +Xilinx_Spartan3_Slave_Serial_fns fpga_fns = {
>> +	fpga_pre_fn,
>> +	fpga_pgm_fn,
>> +	fpga_clk_fn,
>> +	fpga_init_fn,
>> +	fpga_done_fn,
>> +	fpga_wr_fn,
>> +};
>> +
>> +Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
> 
> Do you have more as one FPGA on your board ? And if this is true, they
> share the same firmware ? (I see only one CONFIG_FIRMWARE_ADDR..)
The APF9328 is a SOM therefore it possible to connect some other FPGA to the board. In such a situation the idea is to concatenate all the bitstream files in the firmware partition.
During the download process to the FPGAs the end of one FPGA download starts the download of the next one using the FPGA signal PRG_DONE.
So that it possible to have all firmware in only one partition and save memory space by using bitstream files.
To be honest I do not remember if someone use this feature on this board but that is . 

> 
>> +/*
>> + * Initialize the fpga.  Return 1 on success, 0 on failure.
>> + */
>> +int apf9328_init_fpga(void)
>> +{
>> +	char *autoload = getenv("firmware_autoload");
>> +	int i, lout = 1;
>> +
>> +	debug("%s:%d: Initialize FPGA interface (relocation offset= 0x%.8lx)\n",
>> +		__func__, __LINE__, gd->reloc_off);
>> +
>> +	fpga_init();
>> +
>> +	for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
>> +		debug("%s:%d: Adding fpga %d\n", __func__, __LINE__, i);
>> +		fpga_add(fpga_xilinx, &fpga[i]);
>> +	}
>> +
>> +	if ((autoload) && (0 == strcmp(autoload, "1"))) {
>> +		if (FPGA_SUCCESS != fpga_load(0, (void *)CONFIG_FIRMWARE_ADDR,
> 
> I am confused...you add in the configuration file a variable
> "firmware_addr=", and you set it as default to CONFIG_FIRMWARE_ADDR, but
> you do not use this variable at all. Do you not shoul get the address
> with getenv("firmware_addr") instead of the precompiled value ?

I use this variable in the script "flash_firmware" but it is a good point as I should
use getenv() instead of the CONFIG_FIRMWARE_ADDR.
I will do it. Thx

> 
> If you add some new CONFIG_ switches in U-Boot, you must document them
> in the Readme file. However, CONFIG_FIRMWARE_* do not need to be global,
> right ?
For the time being this switch applies to this board only. So I did not plan to document it in the README.
It is not clear for me if I should add a documentation in the README since this switch is only used in the APF9328 source files.

> 
>> +/*
>> + * Spartan 3 FPGA configuration support for the APF9328 daughter board
>> + */
>> +
>> +#include "fpga.h"
>> +extern int apf9328_init_fpga(void);
>> diff --git a/board/armadeus/apf9328/eeprom.c b/board/armadeus/apf9328/eeprom.c
> 
> It seems to much fo me to add a new file only for a single prototype.
> and it is used only in apf9328fpga.c, as I can see.

this file defines the public prototype of the function implemented in apf9328fpga.c and used in apf9328.c
I agree that it would not make sense to add a header file with prototypes never used anywhere else in the code.

> 
>> +
>> +#include <common.h>
>> +#include <command.h>
>> +#include <dm9000.h>
>> +
>> +static int do_read_dm9000_eeprom(cmd_tbl_t *cmdtp, int flag, int argc,
>> +				 char * const argv[])
>> +{
>> +	unsigned int i;
>> +	u8 data[2];
>> +
>> +	for (i = 0; i < 0x40; i++) {
>> +		if (!(i % 0x10))
>> +			printf("\n%08x:", i);
>> +		dm9000_read_srom_word(i, data);
>> +		printf(" %02x%02x", data[1], data[0]);
>> +	}
> 
> These functions can be factorized. I think the best place is inside the
> DM9000 driver itself, removing them from board code.

Good point. I will propose your recommendation as I am already pushing  a patch  for the DM9000

> 
> 
>> +#include <common.h>
>> +
>> +#if (CONFIG_FPGA)
> 
> #ifdef. We do not want to explicitely set the value for the CONFIG_
> switches. It must be enough to use
> 
> #define CONFIG_FPGA
> 
> in your configuration file,

I am fully in agrement with that. Thx

> 
>> +/*
>> + * nitialize GPIO port B before download
> 
> Initialize

Sure.

> 
>> +extern int fpga_pre_fn(int cookie);
>> +extern int fpga_pgm_fn(int assert_pgm, int flush, int cookie);
>> +extern int fpga_init_fn(int cookie);
>> +extern int fpga_done_fn(int cookie);
>> +extern int fpga_clk_fn(int assert_clk, int flush, int cookie);
>> +extern int fpga_wr_fn(int assert_write, int flush, int cookie);
> 
> Maybe can you add here the prototy you set in apf9328.h ?

Well, What do you think to add the prototype directly in apf9328.c: extern int apf9328_init_fpga(void);
This will avoid to expose the fpga_xx_fn to apf9328.c that does not care how the firmware is moved from CPU to FPGA
and therefore remove the very small apf9328_fpga.h

> 
>> diff --git a/board/armadeus/apf9328/i2c.c b/board/armadeus/apf9328/i2c.c
> 
> This is a I2C driver, and must be stored into drivers/i2c, not in board
> directory. Please split your patch and push a separate patch only for
> the I2C code, sending it to the I2C maintainer, too.

ok

> 
>> +#include <common.h>
>> +
>> +#ifdef CONFIG_HARD_I2C
>> +
>> +#include <asm/io.h>
>> +#include <asm/arch/imx-regs.h>
>> +#include <i2c.h>
>> +
>> +/*-----------------------------------------------------------------------
>> + * Definitions
>> + */
>> +
>> +#define I2C_ACK		0	/* level to ack a byte */
>> +#define I2C_NOACK	1	/* level to noack a byte */
>> +
>> +/*-----------------------------------------------------------------------
>> + * Local functions
>> + */
>> +
>> +/*-----------------------------------------------------------------------
>> + * START: High -> Low on SDA while SCL is High
>> + * after check for a bus free
>> + */
>> +static void imxi2c_send_start(void)
>> +{
>> +	while (I2SR & I2SR_IBB)
>> +		udelay(1);
> 
> You are using the __REG macros, that are not allowed anymore in new
> u-boot code. Instead of that, please add C structure and use general
> accessors (writel, readl,...) to access to the registers. This comment
> apply to the whole code here.
> 
> 
>> diff --git a/board/armadeus/apf9328/lowlevel_init.S b/board/armadeus/apf9328/lowlevel_init.S
>> new file mode 100644
>> index 0000000..e4c6157
>> --- /dev/null
>> +++ b/board/armadeus/apf9328/lowlevel_init.S
>> @@ -0,0 +1,469 @@
>> +/*
>> + * (C) Copyright 2005-2011 ej Armadeus Project <eric.jarrige@armadeus.org>
>> + * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version 2
>> + * of the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
>> + * 02111-1307, USA.
>> + *
>> + */
>> +
>> +#include <config.h>
>> +#include <version.h>
>> +#include <asm/arch/imx-regs.h>
>> +
>> +.globl lowlevel_init
>> +lowlevel_init:
>> +/* Change PERCLK1DIV to 14 ie 14+1 */
>> +	ldr		r0,	=PCDR
>> +	ldr		r1,	=CONFIG_SYS_PCDR_VAL
>> +	str		r1,	[r0]
>> +
>> +/* set MCU PLL Control Register 0 */
>> +
>> +	ldr		r0,	=MPCTL0
>> +	ldr		r1,	=CONFIG_SYS_MPCTL0_VAL
>> +	str		r1,	[r0]
>> +
>> +/* set MCU PLL Control Register 1 */
>> +
>> +	ldr		r0,	=MPCTL1
>> +	ldr		r1,	=CONFIG_SYS_MPCTL1_VAL
>> +	str		r1,	[r0]
>> +
>> +/* set mpll restart bit */
>> +	ldr		r0, =CSCR
>> +	ldr		r1, [r0]
>> +	orr		r1,r1,#(1<<21)
>> +	str		r1, [r0]
>> +
>> +	mov		r2,#0x10
>> +1:
>> +	mov		r3,#0x2000
>> +2:
>> +	subs	r3,r3,#1
>> +	bne		2b
>> +
>> +	subs	r2,r2,#1
>> +	bne		1b
>> +
>> +/* set System PLL Control Register 0 */
>> +
>> +	ldr		r0,	=SPCTL0
>> +	ldr		r1,	=CONFIG_SYS_SPCTL0_VAL
>> +	str		r1,	[r0]
>> +
>> +/* set System PLL Control Register 1 */
>> +
>> +	ldr		r0,	=SPCTL1
>> +	ldr		r1,	=CONFIG_SYS_SPCTL1_VAL
>> +	str		r1,	[r0]
>> +
>> +/* set spll restart bit */
>> +	ldr		r0, =CSCR
>> +	ldr		r1, [r0]
>> +	orr		r1,r1,#(1<<22)
>> +	str		r1, [r0]
>> +
>> +	mov		r2,#0x10
>> +1:
>> +	mov		r3,#0x2000
>> +2:
>> +	subs	r3,r3,#1
>> +	bne		2b
>> +
>> +	subs	r2,r2,#1
>> +	bne		1b
>> +
>> +	ldr		r0,	=CSCR
>> +	ldr		r1,	=CONFIG_SYS_CSCR_VAL
>> +	str		r1,	[r0]
>> +
>> +	ldr		r0,	=GPCR
>> +	ldr		r1,	=CONFIG_SYS_GPCR_VAL
>> +	str		r1,	[r0]
>> +
>> +/* I have now read the ARM920 DataSheet back-to-Back, and have stumbled upon
>> + *this.....
>> + *
>> + * It would appear that from a Cold-Boot the ARM920T enters "FastBus" mode CP15
>> + * register 1, this stops it using the output of the PLL and thus runs at the
>> + * slow rate. Unless you place the Core into "Asynch" mode, the CPU will never
>> + * use the value set in the CM_OSC registers...regardless of what you set it
>> + * too!  Thus, although i thought i was running at 140MHz, i'm actually running
>> + * at 40!..
>> +
>> + * Slapping this into my bootloader does the trick...
>> +
>> + * MRC p15,0,r0,c1,c0,0	 ; read core configuration register
>> + * ORR r0,r0,#0xC0000000	; set asynchronous clocks and not fastbus mode
>> + * MCR p15,0,r0,c1,c0,0	 ; write modified value to core configuration
>> + * register
>> + */
>> +	MRC p15,0,r0,c1,c0,0
>> +	ORR r0,r0,#0xC0000000
>> +	MCR p15,0,r0,c1,c0,0
>> +
>> +/*	ldr		r0,	=GPR(0)
> 
> Do not add dead code, simply drop it.

Sure.

> 
> However, this code is quite the same I can find on other IMX boards. Can
> we factorize it and push it as common code ?

The other boards use hardcoded values that are not compatible with the apf9328 board.
We do not use the same components and so cannot reuse or merge their code.
A factorization would require deep changes in the config files of every board.
For this old CPU there is no chance to convince the maintainers of the other boards to rework their implementation and specifically the boot code in assembly.

On the other hand I am working on some other ARM SOC more recent, so It may worth the pain to invest some effrot of  factorization on modern CPUs.
What is your opinion?

Thanks and best regards,
Eric
Stefano Babic Aug. 12, 2011, 6:49 a.m. UTC | #3
On 08/12/2011 01:41 AM, Eric Jarrige wrote:

Hi Eric,

>>> +int board_init(void) +{ +	gd->bd->bi_arch_number =
>>> CONFIG_MACH_TYPE;
>> 
>> Is there no MACH_TYPE for this board ? It is uncommon for an ARM
>> board. Should this board run Linux ?
> The MACH_TYPE for this board is 906. This board runs linux and the
> integration in linux is on going.

Ok, I have understood. The only thing you can directly set
MACH_TYPE_APF9328 here. IMHO it is more readable.

>>> +#if (CONFIG_DRIVER_DM9000) +	imx_gpio_mode(GPIO_PORTB | GPIO_DR
>>> | GPIO_IN | 14);
>> 
>> Is there a reason to put this code here and not in board_eth_init ?
>> It is related to Ethernet and I am supposing this setup should be
>> done before dm9000_initialize.
> The idea is to keep the configuration  of the CPU pins at one place
> and to keep the initialization of the ethernet controller in a
> separate function. Here this principle of segregation is not obvious
> as there is only one GPIO pin to configure.

Ok, understood. Maybe it is better to move this kind of initialization
adding a board_early_init_f() function (you need
CONFIG_BOARD_EARLY_INIT_F in your config). This assures that the gpio is
always set before the ethernet is initialized, as I suppose it must be.
Letting in the misc_init() works now, but the order could be changed in
future - the erarly entry point is thought for hardware initialization
before starting the drivers.

>> This function seems to me not very useful. Is it not better to drop
>> it ? It is not strictly required. You set also #undef
>> CONFIG_SHOW_BOOT_PROGRESS in the configuration file.
> Well I choosed to keep it in place in empty state to be the template
> for the final user to add their own debug method if needed. If it is
> an issue I would prefer to define the CONFIG_SHOW_BOOT_PROGRESS in
> the configuration file than removing this empty show_boot_progress as
> the main purpose of the board is education and trainings on embedded
> developments.

However, if the function is empty, the functionality is not shown - it
is quite dead code and does not teach very much. What about to add some
very simple code, as a print() or switching a led, for example, to
indicate which is the goal of the function ?

>> Do you have more as one FPGA on your board ? And if this is true,
>> they share the same firmware ? (I see only one
>> CONFIG_FIRMWARE_ADDR..)
> The APF9328 is a SOM therefore it possible to connect some other FPGA
> to the board. In such a situation the idea is to concatenate all the
> bitstream files in the firmware partition. During the download
> process to the FPGAs the end of one FPGA download starts the download
> of the next one using the FPGA signal PRG_DONE. So that it possible
> to have all firmware in only one partition and save memory space by
> using bitstream files. To be honest I do not remember if someone use
> this feature on this board but that is .

You are the best to say if it is work. Reading the code, I have expected
to see one fpga_load for each defined fpga structure, using offset
inside the loop to pass the correct start and length for each image.

Can you add a comment to explain the behavior and the fact the FPGAs are
concatenated ?


> For the time being this switch applies to this board only. So I did
> not plan to document it in the README. It is not clear for me if I
> should add a documentation in the README since this switch is only
> used in the APF9328 source files.

Then drop all this stuff from the configuration file and rename in a way
it is clear it is specific for your board only. You do not need to
document them in the README, because they are not general CONFIG_ switches.

> Well, What do you think to add the prototype directly in apf9328.c:
> extern int apf9328_init_fpga(void); This will avoid to expose the
> fpga_xx_fn to apf9328.c that does not care how the firmware is moved
> from CPU to FPGA and therefore remove the very small apf9328_fpga.h

Agree.

>> However, this code is quite the same I can find on other IMX
>> boards. Can we factorize it and push it as common code ?
> 
> The other boards use hardcoded values that are not compatible with
> the apf9328 board. We do not use the same components and so cannot
> reuse or merge their code. A factorization would require deep changes
> in the config files of every board. For this old CPU there is no
> chance to convince the maintainers of the other boards to rework
> their implementation and specifically the boot code in assembly.

This is right. These processors are obsolete, there are no more active
development for them. It is enough to see how many patches for theses
processors were sent to the list in the last years (only 1, to fix the
mx1ads board).

> 
> On the other hand I am working on some other ARM SOC more recent, so
> It may worth the pain to invest some effrot of  factorization on
> modern CPUs. What is your opinion?

Of course, this is a must and duplication of code must be avoided.
However, is there a chance to move your assembly file into
arch/arm/cpu/arm920t/imx/, making it available if someone else needs to
use these old-ancient processors ? We do not need to touch the other boards.

I see you load most values from the configuration file, and the code is
straightforward - storing these values into the registers. Any chance ?

Best regards,
Stefano Babic
Igor Grinberg Aug. 17, 2011, 7:31 a.m. UTC | #4
On 08/12/11 09:49, Stefano Babic wrote:
> On 08/12/2011 01:41 AM, Eric Jarrige wrote:
>
> Hi Eric,
>
>>>> +int board_init(void) +{ +	gd->bd->bi_arch_number =
>>>> CONFIG_MACH_TYPE;
>>> Is there no MACH_TYPE for this board ? It is uncommon for an ARM
>>> board. Should this board run Linux ?
>> The MACH_TYPE for this board is 906. This board runs linux and the
>> integration in linux is on going.
> Ok, I have understood. The only thing you can directly set
> MACH_TYPE_APF9328 here. IMHO it is more readable.

You should not do this here unless you support multiple mach types in a single file.
Please, see the CONFIG_MACH_TYPE in the U-Boot documentation (README file).
Eric Jarrige Aug. 17, 2011, 9:58 p.m. UTC | #5
Hi Higor, Hi Stefano,

On 17 août 2011, at 09:31, Igor Grinberg wrote:

> 
> On 08/12/11 09:49, Stefano Babic wrote:
>> On 08/12/2011 01:41 AM, Eric Jarrige wrote:
>> 
>> Hi Eric,
>> 
>>>>> +int board_init(void) +{ +	gd->bd->bi_arch_number =
>>>>> CONFIG_MACH_TYPE;
>>>> Is there no MACH_TYPE for this board ? It is uncommon for an ARM
>>>> board. Should this board run Linux ?
>>> The MACH_TYPE for this board is 906. This board runs linux and the
>>> integration in linux is on going.
>> Ok, I have understood. The only thing you can directly set
>> MACH_TYPE_APF9328 here. IMHO it is more readable.
> 
> You should not do this here unless you support multiple mach types in a single file.
> Please, see the CONFIG_MACH_TYPE in the U-Boot documentation (README file).

Here is the README sentence regarding CONFIG_MACH_TYPE:

> CONFIG_MACH_TYPE        [relevant for ARM only][mandatory]
>
> This setting is mandatory for all boards that have only one
> machine type and must be used to specify the machine type
> number as it appears in the ARM machine registry
> (see http://www.arm.linux.org.uk/developer/machines/).
> Only boards that have multiple machine types supported
> in a single configuration file and the machine type is
> runtime discoverable, do not have to use this setting.

My understanding is:
1) CONFIG_MACH_TYPE has to be defined in apf9328.h
2) as gd->bd->bi_arch_number is already initialize in board.c i should completely remove this second initialization from the apf9382.c

arch/arm/lib/board.c:
 262 void board_init_f(ulong bootflag)
 ..
 277 
 278 #ifdef CONFIG_MACH_TYPE
 279         gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
 280 #endif 

Please let me know if missed something.

Thx and best regards,
Eric
Igor Grinberg Aug. 18, 2011, 6:20 a.m. UTC | #6
On 08/18/11 00:58, Eric Jarrige wrote:
> Hi Higor, Hi Stefano,
>
> On 17 août 2011, at 09:31, Igor Grinberg wrote:
>
>> On 08/12/11 09:49, Stefano Babic wrote:
>>> On 08/12/2011 01:41 AM, Eric Jarrige wrote:
>>>
>>> Hi Eric,
>>>
>>>>>> +int board_init(void) +{ +	gd->bd->bi_arch_number =
>>>>>> CONFIG_MACH_TYPE;
>>>>> Is there no MACH_TYPE for this board ? It is uncommon for an ARM
>>>>> board. Should this board run Linux ?
>>>> The MACH_TYPE for this board is 906. This board runs linux and the
>>>> integration in linux is on going.
>>> Ok, I have understood. The only thing you can directly set
>>> MACH_TYPE_APF9328 here. IMHO it is more readable.
>> You should not do this here unless you support multiple mach types in a single file.
>> Please, see the CONFIG_MACH_TYPE in the U-Boot documentation (README file).
> Here is the README sentence regarding CONFIG_MACH_TYPE:
>
>> CONFIG_MACH_TYPE        [relevant for ARM only][mandatory]
>>
>> This setting is mandatory for all boards that have only one
>> machine type and must be used to specify the machine type
>> number as it appears in the ARM machine registry
>> (see http://www.arm.linux.org.uk/developer/machines/).
>> Only boards that have multiple machine types supported
>> in a single configuration file and the machine type is
>> runtime discoverable, do not have to use this setting.
> My understanding is:
> 1) CONFIG_MACH_TYPE has to be defined in apf9328.h
> 2) as gd->bd->bi_arch_number is already initialize in board.c i should completely remove this second initialization from the apf9382.c

Right. Just remove that line.
Stefano Babic Aug. 18, 2011, 8:51 a.m. UTC | #7
On 08/17/2011 11:58 PM, Eric Jarrige wrote:
> Hi Higor, Hi Stefano,
> 

Hi Eric,

> My understanding is:
> 1) CONFIG_MACH_TYPE has to be defined in apf9328.h
> 2) as gd->bd->bi_arch_number is already initialize in board.c i should completely remove this second initialization from the apf9382.c

You are right - drop only the line in apf9382.c

Best regards,
Stefano Babic
diff mbox

Patch

diff --git a/board/armadeus/apf9328/Makefile b/board/armadeus/apf9328/Makefile
new file mode 100644
index 0000000..0f097cd
--- /dev/null
+++ b/board/armadeus/apf9328/Makefile
@@ -0,0 +1,51 @@ 
+#
+# (C) Copyright 2000-2004
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= apf9328.o i2c.o apf9328fpga.o fpga.o eeprom.o
+SOBJS	:= lowlevel_init.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/armadeus/apf9328/apf9328.c b/board/armadeus/apf9328/apf9328.c
new file mode 100644
index 0000000..2250221
--- /dev/null
+++ b/board/armadeus/apf9328/apf9328.c
@@ -0,0 +1,91 @@ 
+/*
+ * (C) Copyright 2005-2011
+ * Nicolas Colombin <thom25@users.sourceforge.net>
+ * Eric Jarrige <eric.jarrige@armadeus.org>
+ * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/imx-regs.h>
+#include <flash.h>
+#include <netdev.h>
+#include "apf9328fpga.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+	gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
+	gd->bd->bi_boot_params = CONFIG_BOOT_PARAMS_ADDR;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	/* dram_init must store complete ramsize in gd->ram_size */
+	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_1_BASE,
+				    CONFIG_SYS_SDRAM_1_SIZE);
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+#if (CONFIG_NR_DRAM_BANKS > 0)
+	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_1_BASE;
+	gd->bd->bi_dram[0].size = CONFIG_SYS_SDRAM_1_SIZE;
+#endif
+}
+
+/*
+ * Miscellaneous intialization
+ */
+int misc_init_r(void)
+{
+	char *s;
+
+#if (CONFIG_FPGA)
+	apf9328_init_fpga();
+#endif
+
+#if (CONFIG_DRIVER_DM9000)
+	imx_gpio_mode(GPIO_PORTB | GPIO_DR | GPIO_IN | 14);
+#endif
+
+	/* detect compatibility issue of environment version */
+	s = getenv("env_version");
+	if ((NULL == s) || (0 != strcmp(s, CONFIG_ENV_VERSION))) {
+		printf("*** Warning - Environment version change suggests: "
+		       "run flash_reset_env; reset\n");
+	}
+
+	return 0;
+}
+
+void show_boot_progress(int status)
+{
+	return;
+}
+
+#ifdef CONFIG_DRIVER_DM9000
+int board_eth_init(bd_t *bis)
+{
+	return dm9000_initialize(bis);
+}
+#endif
diff --git a/board/armadeus/apf9328/apf9328fpga.c b/board/armadeus/apf9328/apf9328fpga.c
new file mode 100644
index 0000000..d64c0d4
--- /dev/null
+++ b/board/armadeus/apf9328/apf9328fpga.c
@@ -0,0 +1,89 @@ 
+/*
+ * (C) Copyright 2005-2011
+ * Nicolas Colombin <thom25@users.sourceforge.net>
+ * Eric Jarrige <eric.jarrige@armadeus.org>
+ *
+ * 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
+ *
+ */
+
+/*
+ * Spartan 3 FPGA configuration support for the APF9328 daughter board
+ */
+
+#include <common.h>
+#include <spartan3.h>
+#include <command.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include "apf9328fpga.h"
+
+#if (CONFIG_FPGA)
+DECLARE_GLOBAL_DATA_PTR;
+/* Note that these are pointers to code that is in Flash.  They will be
+ * relocated at runtime.
+ * Spartan3 code is used to download our Spartan 3 :) code is compatible.
+ * Just take care about the file size
+*/
+Xilinx_Spartan3_Slave_Serial_fns fpga_fns = {
+	fpga_pre_fn,
+	fpga_pgm_fn,
+	fpga_clk_fn,
+	fpga_init_fn,
+	fpga_done_fn,
+	fpga_wr_fn,
+};
+
+Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
+	{Xilinx_Spartan3,
+	 slave_serial,
+	 XILINX_XC3S400_SIZE,
+	 (void *)&fpga_fns,
+	 0}
+};
+
+/*
+ * Initialize the fpga.  Return 1 on success, 0 on failure.
+ */
+int apf9328_init_fpga(void)
+{
+	char *autoload = getenv("firmware_autoload");
+	int i, lout = 1;
+
+	debug("%s:%d: Initialize FPGA interface (relocation offset= 0x%.8lx)\n",
+		__func__, __LINE__, gd->reloc_off);
+
+	fpga_init();
+
+	for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
+		debug("%s:%d: Adding fpga %d\n", __func__, __LINE__, i);
+		fpga_add(fpga_xilinx, &fpga[i]);
+	}
+
+	if ((autoload) && (0 == strcmp(autoload, "1"))) {
+		if (FPGA_SUCCESS != fpga_load(0, (void *)CONFIG_FIRMWARE_ADDR,
+					      (size_t) CONFIG_FIRMWARE_LEN)) {
+			lout = 0;
+			printf("Firmware not loaded!\n");
+		}
+	}
+	return 1;
+}
+
+#endif /* CONFIG_FPGA */
diff --git a/board/armadeus/apf9328/apf9328fpga.h b/board/armadeus/apf9328/apf9328fpga.h
new file mode 100644
index 0000000..2a15443
--- /dev/null
+++ b/board/armadeus/apf9328/apf9328fpga.h
@@ -0,0 +1,31 @@ 
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.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
+ *
+ */
+
+/*
+ * Spartan 3 FPGA configuration support for the APF9328 daughter board
+ */
+
+#include "fpga.h"
+extern int apf9328_init_fpga(void);
diff --git a/board/armadeus/apf9328/eeprom.c b/board/armadeus/apf9328/eeprom.c
new file mode 100644
index 0000000..8f2ad9a
--- /dev/null
+++ b/board/armadeus/apf9328/eeprom.c
@@ -0,0 +1,88 @@ 
+/*
+ * (C) Copyright 2008-2011 Armadeus Project
+ * (C) Copyright 2007
+ * Stefano Babic, DENX Software Engineering, sbabic@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 <common.h>
+#include <command.h>
+#include <dm9000.h>
+
+static int do_read_dm9000_eeprom(cmd_tbl_t *cmdtp, int flag, int argc,
+				 char * const argv[])
+{
+	unsigned int i;
+	u8 data[2];
+
+	for (i = 0; i < 0x40; i++) {
+		if (!(i % 0x10))
+			printf("\n%08x:", i);
+		dm9000_read_srom_word(i, data);
+		printf(" %02x%02x", data[1], data[0]);
+	}
+	printf("\n");
+	return 0;
+}
+
+static int do_write_dm9000_eeprom(cmd_tbl_t *cmdtp, int flag, int argc,
+				  char * const argv[])
+{
+	unsigned long offset, value;
+
+	if (argc < 4) {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+
+	strict_strtoul(argv[2], 16, &offset);
+	strict_strtoul(argv[3], 16, &value);
+	if (offset > 0x40) {
+		printf("Wrong offset : 0x%lx\n", offset);
+		cmd_usage(cmdtp);
+		return 1;
+	}
+	dm9000_write_srom_word(offset, value);
+	return 0;
+}
+
+int do_dm9000_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	if (argc < 2) {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+
+	if (strcmp(argv[1], "read") == 0) {
+		return do_read_dm9000_eeprom(cmdtp, flag, argc, argv);
+	} else if (strcmp(argv[1], "write") == 0) {
+		return do_write_dm9000_eeprom(cmdtp, flag, argc, argv);
+	} else {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+}
+
+U_BOOT_CMD(dm9000ee, 4, 1, do_dm9000_eeprom,
+	   "Read/Write eeprom connected to Ethernet Controller",
+	   "\ndm9000ee write <word offset> <value> \n"
+	   "\tdm9000ee read \n"
+	   "\tword:\t\t00-02 : MAC Address\n"
+	   "\t\t\t03-07 : DM9000 Configuration\n" "\t\t\t08-63 : User data");
diff --git a/board/armadeus/apf9328/fpga.c b/board/armadeus/apf9328/fpga.c
new file mode 100644
index 0000000..ec4c251
--- /dev/null
+++ b/board/armadeus/apf9328/fpga.c
@@ -0,0 +1,121 @@ 
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.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>
+
+#if (CONFIG_FPGA)
+
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include <config.h>
+
+#define GPIO_PORT(x)  ((x >> 5) & 3)
+#define GPIO_SET(x)   (DR(GPIO_PORT(x)) |= (1<<(x & GPIO_PIN_MASK)))
+#define GPIO_CLEAR(x) (DR(GPIO_PORT(x)) &= ~(1<<(x & GPIO_PIN_MASK)))
+#define GPIO_WRITE(x, y) (y ? GPIO_SET(x) : GPIO_CLEAR(x))
+#define GPIO_READ(x)  ((SSR(GPIO_PORT(x)) & (1<<(x & GPIO_PIN_MASK))))
+
+/*
+ * Port bit numbers for the serial slave controls
+ */
+#define FPGA_INIT	CONFIG_SYS_FPGA_INIT
+#define FPGA_DONE	CONFIG_SYS_FPGA_DONE
+#define FPGA_DIN	CONFIG_SYS_FPGA_DATA
+#define FPGA_PROGRAM	CONFIG_SYS_FPGA_PRG
+#define FPGA_CLOCK	CONFIG_SYS_FPGA_CLK
+
+/* Note that these are pointers to code that is in Flash.  They will be
+ * relocated at runtime.
+ * Spartan2 code is used to download our Spartan 3 :) code is compatible.
+ * Just take care about the file size
+*/
+
+/*
+ * nitialize GPIO port B before download
+ */
+int fpga_pre_fn(int cookie)
+{
+	debug("%s:%d: FPGA PRE ", __func__, __LINE__);
+
+	/* Initialize GPIO pins */
+	imx_gpio_mode(FPGA_INIT | GPIO_DR | GPIO_IN);
+	imx_gpio_mode(FPGA_DONE | GPIO_DR | GPIO_IN);
+	imx_gpio_mode(FPGA_DIN | GPIO_DR | GPIO_OUT);
+	imx_gpio_mode(FPGA_PROGRAM | GPIO_DR | GPIO_OUT);
+	imx_gpio_mode(FPGA_CLOCK | GPIO_DR | GPIO_OUT);
+	return cookie;
+}
+
+/*
+ * Set the FPGA's active-low program line to the specified level
+ */
+int fpga_pgm_fn(int assert, int flush, int cookie)
+{
+	debug("%s:%d: FPGA PROGRAM %s", __func__, __LINE__,
+	       assert ? "high" : "low");
+	GPIO_WRITE(FPGA_PROGRAM, !assert);
+	return assert;
+}
+
+/*
+ * Set the FPGA's active-high clock line to the specified level
+ */
+int fpga_clk_fn(int assert_clk, int flush, int cookie)
+{
+	debug("%s:%d: FPGA CLOCK %s", __func__, __LINE__,
+	       assert_clk ? "high" : "low");
+	GPIO_WRITE(FPGA_CLOCK, assert_clk);
+	return assert_clk;
+}
+
+/*
+ * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
+ * asserted (low).
+ */
+int fpga_init_fn(int cookie)
+{
+	debug("%s:%d: INIT check... ", __func__, __LINE__);
+	return !GPIO_READ(FPGA_INIT);
+}
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int fpga_done_fn(int cookie)
+{
+	debug("%s:%d: DONE check... ", __func__, __LINE__);
+	return GPIO_READ(FPGA_DONE);
+}
+
+/*
+ * Set the FPGA's data line to the specified level
+ */
+int fpga_wr_fn(int assert_write, int flush, int cookie)
+{
+	debug("%s:%d: DATA write... ", __func__, __LINE__);
+	GPIO_WRITE(FPGA_DIN, assert_write);
+	return assert_write;
+}
+
+#endif /* CONFIG_FPGA */
diff --git a/board/armadeus/apf9328/fpga.h b/board/armadeus/apf9328/fpga.h
new file mode 100644
index 0000000..3b226d7
--- /dev/null
+++ b/board/armadeus/apf9328/fpga.h
@@ -0,0 +1,30 @@ 
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.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
+ *
+ */
+extern int fpga_pre_fn(int cookie);
+extern int fpga_pgm_fn(int assert_pgm, int flush, int cookie);
+extern int fpga_init_fn(int cookie);
+extern int fpga_done_fn(int cookie);
+extern int fpga_clk_fn(int assert_clk, int flush, int cookie);
+extern int fpga_wr_fn(int assert_write, int flush, int cookie);
diff --git a/board/armadeus/apf9328/i2c.c b/board/armadeus/apf9328/i2c.c
new file mode 100644
index 0000000..0ba0a8d
--- /dev/null
+++ b/board/armadeus/apf9328/i2c.c
@@ -0,0 +1,276 @@ 
+/*
+ * (C) Copyright 2005-2011 ej Armadeus Project <eric.jarrige@armadeus.org>
+ *
+ * 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>
+
+#ifdef CONFIG_HARD_I2C
+
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <i2c.h>
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+#define I2C_ACK		0	/* level to ack a byte */
+#define I2C_NOACK	1	/* level to noack a byte */
+
+/*-----------------------------------------------------------------------
+ * Local functions
+ */
+
+/*-----------------------------------------------------------------------
+ * START: High -> Low on SDA while SCL is High
+ * after check for a bus free
+ */
+static void imxi2c_send_start(void)
+{
+	while (I2SR & I2SR_IBB)
+		udelay(1);
+
+	I2CR |= I2CR_MSTA;
+	I2SR &= ~I2SR_IIF;
+}
+
+/*-----------------------------------------------------------------------
+ * STOP: Low -> High on SDA while SCL is High
+ * after the end of previous transfer
+ */
+static void imxi2c_send_stop(void)
+{
+	while (!(I2SR & I2SR_ICF))
+		udelay(1);
+
+	I2CR &= ~I2CR_MSTA;
+}
+
+/*-----------------------------------------------------------------------
+ * Send 8 bits and look for an acknowledgement.
+ */
+static int imxi2c_write_byte(uchar data)
+{
+	while (!(I2SR & I2SR_ICF))	/* Wait end of transfer */
+		udelay(1);
+
+	I2CR |= I2CR_MTX;
+	I2SR &= ~I2SR_IIF;
+	I2DR = data;
+
+	while (!(I2SR & I2SR_IIF))	/* checking IIF before ICF: FIXME */
+		udelay(1);
+
+	I2SR &= ~I2SR_IIF;
+
+	while (!(I2SR & I2SR_ICF))	/* Wait end of transfer */
+		udelay(1);
+
+	return I2SR & I2SR_RXAK;	/* not a nack is an ack */
+}
+
+/*-----------------------------------------------------------------------
+ * if ack == I2C_ACK, ACK the byte so can continue reading, else
+ * send I2C_NOACK to end the read.
+ */
+static uchar imxi2c_read_byte(int ack)
+{
+	int data;
+
+	while (!(I2SR & I2SR_ICF))
+		udelay(1);
+
+	I2CR &= ~I2CR_MTX;
+
+	if (ack)
+		I2CR |= I2CR_TXAK;
+	else
+		I2CR &= ~I2CR_TXAK;
+
+	data = I2DR;
+	return data;
+}
+
+/* ------------------------------------------------------------------------
+ * API Functions
+ * ------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------
+ * i2c_init compute the i2c divider to reach the requested speed
+ * see mxl reference manual
+ */
+void i2c_init(int speed, int slaveaddr)
+{
+	int hclk_dividers[] = {
+		30, 32, 36, 42, 48, 52, 60, 72,
+		80, 88, 104, 128, 144, 160, 192, 240,
+		288, 320, 384, 480, 576, 640, 768, 960,
+		1152, 1280, 1536, 1920, 2304, 2560, 3072, 3840,
+		22, 24, 26, 26, 32, 36, 40, 44,
+		48, 56, 64, 72, 80, 96, 112, 128,
+		160, 192, 224, 256, 320, 384, 448, 512,
+		640, 768, 896, 1024, 1280, 1536, 1792, 2048
+	};
+	int refDiv = get_HCLK() / speed;
+	int i, tmpIC;
+
+	imx_gpio_mode(PA15_PF_I2C_SDA);
+	imx_gpio_mode(PA16_PF_I2C_SCL);
+
+	tmpIC = (sizeof(hclk_dividers) / sizeof(int)) - 1;
+	for (i = tmpIC; i >= 0; i--) {
+		if ((hclk_dividers[i] >= refDiv)
+		    && (hclk_dividers[i] < hclk_dividers[tmpIC])) {
+			tmpIC = i;
+		}
+	}
+
+	IFDR = tmpIC;
+	IADR = slaveaddr << 1;
+
+	if (I2SR & I2SR_IBB)
+		imxi2c_send_stop();
+
+	I2CR |= I2CR_IEN;
+}
+
+/*-----------------------------------------------------------------------
+ * Probe to see if a chip is present. Also good for checking for the
+ * completion of EEPROM writes since the chip stops responding until
+ * the write completes (typically 10mSec).
+ * probe sends a read command to probe a an address
+ */
+int i2c_probe(uchar addr)
+{
+	int rc;
+
+	imxi2c_send_start();
+	rc = imxi2c_write_byte((addr << 1) | 0);
+	imxi2c_send_stop();
+
+	return rc ? 1 : 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Read bytes
+ */
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	int shift;
+	debug("i2c_read: chip %02X addr %02X alen %d buffer %p len %d\n",
+	       chip, addr, alen, buffer, len);
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+	/*
+	 * EEPROM chips that implement "address overflow" are ones
+	 * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
+	 * address and the extra bits end up in the "chip address"
+	 * bit slots. This makes a 24WC08 (1Kbyte) chip look like
+	 * four 256 byte chips.
+	 *
+	 * Note that we consider the length of the address field to
+	 * still be one byte because the extra address bits are
+	 * hidden in the chip address.
+	 */
+	chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+
+	debug("i2c_read: fix addr_overflow: chip %02X addr %02X\n",
+	       chip, addr);
+#endif
+
+	/*
+	 * Do the addressing portion of a write cycle to set the
+	 * chip's address pointer. If the address length is zero,
+	 * don't do the normal write cycle to set the address pointer,
+	 * there is no address pointer in this chip.
+	 */
+	imxi2c_send_start();
+	if (alen > 0) {
+		if (imxi2c_write_byte(chip << 1)) {	/* write cycle */
+			imxi2c_send_stop();
+			debug("i2c_read, no chip responded %02X\n", chip);
+			return 1;
+		}
+		shift = (alen - 1) * 8;
+		while (alen-- > 0) {
+			if (imxi2c_write_byte(addr >> shift)) {
+				debug("i2c_read, address not <ACK>ed\n");
+				return 1;
+			}
+			shift -= 8;
+		}
+
+		/* reportedly some chips need a full stop */
+		imxi2c_send_stop();
+		imxi2c_send_start();
+	}
+	/*
+	 * Send the chip address again, this time for a read cycle.
+	 * Then read the data. On the last byte, we do a NACK instead
+	 * of an ACK(len == 0) to terminate the read.
+	 */
+	imxi2c_write_byte((chip << 1) | 1);	/* read cycle */
+	imxi2c_read_byte(len <= 2);
+	while (len-- > 1)
+		*buffer++ = imxi2c_read_byte(len == 1);
+
+	imxi2c_send_stop();
+	*buffer++ = imxi2c_read_byte(0);
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Write bytes
+ */
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	int shift, failures = 0;
+
+	debug("i2c_write: chip %02X addr %02X alen %d buffer %p len %d\n",
+	       chip, addr, alen, buffer, len);
+
+	imxi2c_send_start();
+	if (imxi2c_write_byte(chip << 1)) {	/* write cycle */
+		imxi2c_send_stop();
+		debug("i2c_write, no chip responded %02X\n", chip);
+		return 1;
+	}
+	shift = (alen - 1) * 8;
+	while (alen-- > 0) {
+		if (imxi2c_write_byte(addr >> shift)) {
+			debug("i2c_write, address not <ACK>ed\n");
+			return 1;
+		}
+		shift -= 8;
+	}
+
+	while (len-- > 0) {
+		if (imxi2c_write_byte(*buffer++))
+			failures++;
+	}
+	imxi2c_send_stop();
+	return failures;
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/board/armadeus/apf9328/lowlevel_init.S b/board/armadeus/apf9328/lowlevel_init.S
new file mode 100644
index 0000000..e4c6157
--- /dev/null
+++ b/board/armadeus/apf9328/lowlevel_init.S
@@ -0,0 +1,469 @@ 
+/*
+ * (C) Copyright 2005-2011 ej Armadeus Project <eric.jarrige@armadeus.org>
+ * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+#include <version.h>
+#include <asm/arch/imx-regs.h>
+
+.globl lowlevel_init
+lowlevel_init:
+/* Change PERCLK1DIV to 14 ie 14+1 */
+	ldr		r0,	=PCDR
+	ldr		r1,	=CONFIG_SYS_PCDR_VAL
+	str		r1,	[r0]
+
+/* set MCU PLL Control Register 0 */
+
+	ldr		r0,	=MPCTL0
+	ldr		r1,	=CONFIG_SYS_MPCTL0_VAL
+	str		r1,	[r0]
+
+/* set MCU PLL Control Register 1 */
+
+	ldr		r0,	=MPCTL1
+	ldr		r1,	=CONFIG_SYS_MPCTL1_VAL
+	str		r1,	[r0]
+
+/* set mpll restart bit */
+	ldr		r0, =CSCR
+	ldr		r1, [r0]
+	orr		r1,r1,#(1<<21)
+	str		r1, [r0]
+
+	mov		r2,#0x10
+1:
+	mov		r3,#0x2000
+2:
+	subs	r3,r3,#1
+	bne		2b
+
+	subs	r2,r2,#1
+	bne		1b
+
+/* set System PLL Control Register 0 */
+
+	ldr		r0,	=SPCTL0
+	ldr		r1,	=CONFIG_SYS_SPCTL0_VAL
+	str		r1,	[r0]
+
+/* set System PLL Control Register 1 */
+
+	ldr		r0,	=SPCTL1
+	ldr		r1,	=CONFIG_SYS_SPCTL1_VAL
+	str		r1,	[r0]
+
+/* set spll restart bit */
+	ldr		r0, =CSCR
+	ldr		r1, [r0]
+	orr		r1,r1,#(1<<22)
+	str		r1, [r0]
+
+	mov		r2,#0x10
+1:
+	mov		r3,#0x2000
+2:
+	subs	r3,r3,#1
+	bne		2b
+
+	subs	r2,r2,#1
+	bne		1b
+
+	ldr		r0,	=CSCR
+	ldr		r1,	=CONFIG_SYS_CSCR_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GPCR
+	ldr		r1,	=CONFIG_SYS_GPCR_VAL
+	str		r1,	[r0]
+
+/* I have now read the ARM920 DataSheet back-to-Back, and have stumbled upon
+ *this.....
+ *
+ * It would appear that from a Cold-Boot the ARM920T enters "FastBus" mode CP15
+ * register 1, this stops it using the output of the PLL and thus runs at the
+ * slow rate. Unless you place the Core into "Asynch" mode, the CPU will never
+ * use the value set in the CM_OSC registers...regardless of what you set it
+ * too!  Thus, although i thought i was running at 140MHz, i'm actually running
+ * at 40!..
+
+ * Slapping this into my bootloader does the trick...
+
+ * MRC p15,0,r0,c1,c0,0	 ; read core configuration register
+ * ORR r0,r0,#0xC0000000	; set asynchronous clocks and not fastbus mode
+ * MCR p15,0,r0,c1,c0,0	 ; write modified value to core configuration
+ * register
+ */
+	MRC p15,0,r0,c1,c0,0
+	ORR r0,r0,#0xC0000000
+	MCR p15,0,r0,c1,c0,0
+
+/*	ldr		r0,	=GPR(0)
+	ldr		r1,	=CONFIG_SYS_GPR_A_VAL
+	str		r1,	[r0]
+*/
+
+	ldr		r0,	=DR(0)
+	ldr		r1,	=CONFIG_SYS_DR_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=OCR1(0)
+	ldr		r1,	=CONFIG_SYS_OCR1_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=OCR2(0)
+	ldr		r1,	=CONFIG_SYS_OCR2_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFA1(0)
+	ldr		r1,	=CONFIG_SYS_ICFA1_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFA2(0)
+	ldr		r1,	=CONFIG_SYS_ICFA2_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFB1(0)
+	ldr		r1,	=CONFIG_SYS_ICFB1_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFB2(0)
+	ldr		r1,	=CONFIG_SYS_ICFB2_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICR1(0)
+	ldr		r1,	=CONFIG_SYS_ICR1_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICR2(0)
+	ldr		r1,	=CONFIG_SYS_ICR2_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=IMR(0)
+	ldr		r1,	=CONFIG_SYS_IMR_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=DDIR(0)
+	ldr		r1,	=CONFIG_SYS_DDIR_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GPR(0)
+	ldr		r1,	=CONFIG_SYS_GPR_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=PUEN(0)
+	ldr		r1,	=CONFIG_SYS_PUEN_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GIUS(0)
+	ldr		r1,	=CONFIG_SYS_GIUS_A_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=DR(1)
+	ldr		r1,	=CONFIG_SYS_DR_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=OCR1(1)
+	ldr		r1,	=CONFIG_SYS_OCR1_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=OCR2(1)
+	ldr		r1,	=CONFIG_SYS_OCR2_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFA1(1)
+	ldr		r1,	=CONFIG_SYS_ICFA1_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFA2(1)
+	ldr		r1,	=CONFIG_SYS_ICFA2_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFB1(1)
+	ldr		r1,	=CONFIG_SYS_ICFB1_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFB2(1)
+	ldr		r1,	=CONFIG_SYS_ICFB2_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICR1(1)
+	ldr		r1,	=CONFIG_SYS_ICR1_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICR2(1)
+	ldr		r1,	=CONFIG_SYS_ICR2_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=IMR(1)
+	ldr		r1,	=CONFIG_SYS_IMR_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=DDIR(1)
+	ldr		r1,	=CONFIG_SYS_DDIR_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GPR(1)
+	ldr		r1,	=CONFIG_SYS_GPR_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=PUEN(1)
+	ldr		r1,	=CONFIG_SYS_PUEN_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GIUS(1)
+	ldr		r1,	=CONFIG_SYS_GIUS_B_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=DR(2)
+	ldr		r1,	=CONFIG_SYS_DR_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=OCR1(2)
+	ldr		r1,	=CONFIG_SYS_OCR1_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=OCR2(2)
+	ldr		r1,	=CONFIG_SYS_OCR2_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFA1(2)
+	ldr		r1,	=CONFIG_SYS_ICFA1_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFA2(2)
+	ldr		r1,	=CONFIG_SYS_ICFA2_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFB1(2)
+	ldr		r1,	=CONFIG_SYS_ICFB1_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFB2(2)
+	ldr		r1,	=CONFIG_SYS_ICFB2_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICR1(2)
+	ldr		r1,	=CONFIG_SYS_ICR1_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICR2(2)
+	ldr		r1,	=CONFIG_SYS_ICR2_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=IMR(2)
+	ldr		r1,	=CONFIG_SYS_IMR_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=DDIR(2)
+	ldr		r1,	=CONFIG_SYS_DDIR_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GPR(2)
+	ldr		r1,	=CONFIG_SYS_GPR_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=PUEN(2)
+	ldr		r1,	=CONFIG_SYS_PUEN_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GIUS(2)
+	ldr		r1,	=CONFIG_SYS_GIUS_C_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=DR(3)
+	ldr		r1,	=CONFIG_SYS_DR_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=OCR1(3)
+	ldr		r1,	=CONFIG_SYS_OCR1_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=OCR2(3)
+	ldr		r1,	=CONFIG_SYS_OCR2_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFA1(3)
+	ldr		r1,	=CONFIG_SYS_ICFA1_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFA2(3)
+	ldr		r1,	=CONFIG_SYS_ICFA2_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFB1(3)
+	ldr		r1,	=CONFIG_SYS_ICFB1_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICONFB2(3)
+	ldr		r1,	=CONFIG_SYS_ICFB2_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICR1(3)
+	ldr		r1,	=CONFIG_SYS_ICR1_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=ICR2(3)
+	ldr		r1,	=CONFIG_SYS_ICR2_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=IMR(3)
+	ldr		r1,	=CONFIG_SYS_IMR_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=DDIR(3)
+	ldr		r1,	=CONFIG_SYS_DDIR_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GPR(3)
+	ldr		r1,	=CONFIG_SYS_GPR_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=PUEN(3)
+	ldr		r1,	=CONFIG_SYS_PUEN_D_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=GIUS(3)
+	ldr		r1,	=CONFIG_SYS_GIUS_D_VAL
+	str		r1,	[r0]
+
+/* CS3 becomes CS3 by clearing reset default bit 1 in FMCR */
+
+	ldr		r0,	=FMCR
+	ldr		r1,	=CONFIG_SYS_FMCR_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS0U
+	ldr		r1,	=CONFIG_SYS_CS0U_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS0L
+	ldr		r1,	=CONFIG_SYS_CS0L_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS1U
+	ldr		r1,	=CONFIG_SYS_CS1U_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS1L
+	ldr		r1,	=CONFIG_SYS_CS1L_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS2U
+	ldr		r1,	=CONFIG_SYS_CS2U_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS2L
+	ldr		r1,	=CONFIG_SYS_CS2L_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS3U
+	ldr		r1,	=CONFIG_SYS_CS3U_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS3L
+	ldr		r1,	=CONFIG_SYS_CS3L_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS4U
+	ldr		r1,	=CONFIG_SYS_CS4U_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS4L
+	ldr		r1,	=CONFIG_SYS_CS4L_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS5U
+	ldr		r1,	=CONFIG_SYS_CS5U_VAL
+	str		r1,	[r0]
+
+	ldr		r0,	=CS5L
+	ldr		r1,	=CONFIG_SYS_CS5L_VAL
+	str		r1,	[r0]
+
+	adr	r0, sdramsetup	/* r0 <- current position of code */
+	/* test if we run from flash or RAM */
+	ldr	r1, =CONFIG_SYS_SDRAM_1_BASE
+	cmp	r1, r0		/* don't reloc during debug*/
+	bhi		sdramsetup
+	/* test if we run from flash or RAM */
+	ldr	r1, =CONFIG_SYS_FLASH_BASE
+	cmp	r0, r1		/* don't reloc during debug */
+	bmi		copy2ram
+
+/* SDRAM Setup */
+sdramsetup:
+	ldr		r0, =SDCTL0
+	ldr		r1, =CONFIG_SYS_PRECHARGE_CMD
+	str		r1,	[r0]
+
+	ldr		r1, =CONFIG_SYS_SDRAM_1_BASE			\
+				+CONFIG_SYS_SDRAM_PRECHARGE_ALL_VAL
+	ldr		r2,	[r1]
+
+	ldr		r1, =CONFIG_SYS_AUTOREFRESH_CMD
+	str		r1,	[r0]
+
+	ldr		r1, =CONFIG_SYS_SDRAM_1_BASE
+	ldr		r2,	[r1] /* Issue AutoRefresh Command */
+	ldr		r2,	[r1]
+	ldr		r2,	[r1]
+	ldr		r2,	[r1]
+	ldr		r2,	[r1]
+	ldr		r2,	[r1]
+	ldr		r2,	[r1]
+	ldr		r2,	[r1]
+
+	ldr		r1, =CONFIG_SYS_SET_MODE_REG_CMD
+	str		r1,	[r0]
+
+	ldr		r1, =CONFIG_SYS_SDRAM_1_BASE			\
+				+CONFIG_SYS_SDRAM_MODE_REGISTER_VAL
+	str		r2,	[r1]
+
+	ldr		r1, =CONFIG_SYS_NORMAL_RW_CMD
+	str		r1,	[r0]
+/* make U-Boot runnable form "almost" anywhere */
+/* but SYS_TEXT_BASE should be in RAM */
+copy2ram:		/* populate _TEXT_BASE with U-Boot from load addr */
+	ldr	r0, _start_adr
+	ldr	r1, _copy2ram
+	sub	r1, r1, r0
+	adr	r0, copy2ram
+	sub	r0, r0, r1
+	ldr	r1, =CONFIG_SYS_TEXT_BASE
+	cmp	r0, r1
+	beq	end_of_copy2ram		/* skip U-Boot copy */
+	ldr	r2, =CONFIG_SYS_MONITOR_LEN
+	add	r2, r2, r0		/* r2 <- source end address	    */
+
+copy_loop:
+	ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */
+	stmia	r1!, {r9-r10}		/* copy to   target address [r1]    */
+	cmp	r0, r2			/* until source end address [r2]    */
+	blo	copy_loop
+
+end_of_copy2ram:
+	mov	pc,lr
+
+_copy2ram:
+	.word copy2ram
+_start_adr:
+	.word _start