Message ID | 20110810203315.21204.35859.stgit@shuttle2.etheralp.ch |
---|---|
State | Changes Requested |
Delegated to: | Stefano Babic |
Headers | show |
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
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
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
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).
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
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.
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 --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