Logic unit: cpu/arm926ejs/at572d940hf Purpose: AT572D940HF-EB interrupts, reset and timer functions Author: Antnoio R. Costa <antonio.costa <at> atmel.com> Date : 11 Jun 2008
Status: - USB,MACB,MCI,DBGU,USARTS working - Introduced interrput handling on reset to work around a bug on SDRAM controller - Introduced a function to compute system frequency at run-time - Flashes initialised but not recognised - Environment is built-in and temporarly stored in SDRAM Signed-off-by: Antonio R. Costa <[EMAIL PROTECTED]> diff --git a/cpu/arm926ejs/at572d940hf/Makefile b/cpu/arm926ejs/at572d940hf/Makefile new file mode 100644 index 0000000..203abc2 --- /dev/null +++ b/cpu/arm926ejs/at572d940hf/Makefile @@ -0,0 +1,49 @@ +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd <at> denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS-y += ether.o +COBJS-y += timer.o +COBJS-$(CONFIG_HAS_DATAFLASH) +=spi.o +COBJS-y += usb.o +SOBJS = lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm926ejs/at572d940hf/config.mk b/cpu/arm926ejs/at572d940hf/config.mk new file mode 100644 index 0000000..ca2cae1 --- /dev/null +++ b/cpu/arm926ejs/at572d940hf/config.mk @@ -0,0 +1,2 @@ +PLATFORM_CPPFLAGS += -march=armv5te +PLATFORM_CPPFLAGS += $(call cc-option,-mtune=arm926ejs,) diff --git a/cpu/arm926ejs/at572d940hf/ether.c b/cpu/arm926ejs/at572d940hf/ether.c new file mode 100644 index 0000000..5b458f0 --- /dev/null +++ b/cpu/arm926ejs/at572d940hf/ether.c @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian.pop <at> leadtechdesign.com> + * Lead Tech Design <www.leadtechdesign.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/hardware.h> + +extern int macb_eth_initialize(int id, void *regs, unsigned int phy_addr); + +#if defined(CONFIG_MACB) && defined(CONFIG_CMD_NET) +void at572d940hf_eth_initialize(bd_t *bi) +{ + macb_eth_initialize(0, (void *)AT91_BASE_EMAC, 0x00); +} +#endif diff --git a/cpu/arm926ejs/at572d940hf/lowlevel_init.S b/cpu/arm926ejs/at572d940hf/lowlevel_init.S new file mode 100644 index 0000000..40a3f6a --- /dev/null +++ b/cpu/arm926ejs/at572d940hf/lowlevel_init.S @@ -0,0 +1,43 @@ +/* + * AT91CAP9/SAM9 setup stuff + * + * (C) Copyright 2007-2008 + * Stelian Pop <stelian.pop <at> leadtechdesign.com> + * Lead Tech Design <www.leadtechdesign.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + +.globl lowlevel_init +lowlevel_init: + + /* + * Clocks/SDRAM initialization is handled by at91bootstrap, + * no need to do it here... + */ + mov pc, lr + + .ltorg + +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/cpu/arm926ejs/at572d940hf/spi.c b/cpu/arm926ejs/at572d940hf/spi.c new file mode 100644 index 0000000..c9fe6d8 --- /dev/null +++ b/cpu/arm926ejs/at572d940hf/spi.c @@ -0,0 +1,157 @@ +/* + * Driver for ATMEL DataFlash support + * Author : Hamid Ikdoumi (Atmel) + * + * 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/hardware.h> +#include <asm/arch/gpio.h> +#include <asm/arch/io.h> +#include <asm/arch/at91_pio.h> +#include <asm/arch/at91_spi.h> + +#include <dataflash.h> + +#define AT91_SPI_PCS0_DATAFLASH_CARD 0xE /* Chip Select 0: NPCS0%1110 */ +#define AT91_SPI_PCS1_DATAFLASH_CARD 0xD /* Chip Select 0: NPCS0%1101 */ +#define AT91_SPI_PCS3_DATAFLASH_CARD 0x7 /* Chip Select 3: NPCS3%0111 */ + +void AT91F_SpiInit(void) +{ + /* Reset the SPI */ + writel(AT91_SPI_SWRST, AT91_BASE_SPI + AT91_SPI_CR); + + /* Configure SPI in Master Mode with No CS selected !!! */ + writel(AT91_SPI_MSTR | AT91_SPI_MODFDIS | AT91_SPI_PCS, + AT91_BASE_SPI + AT91_SPI_MR); + + /* Configure CS0 */ + writel(AT91_SPI_NCPHA | + (AT91_SPI_DLYBS & DATAFLASH_TCSS) | + (AT91_SPI_DLYBCT & DATAFLASH_TCHS) | + ((AT91_MASTER_CLOCK / AT91_SPI_CLK) << 8), + AT91_BASE_SPI + AT91_SPI_CSR(0)); + +#ifdef CFG_DATAFLASH_LOGIC_ADDR_CS1 + /* Configure CS1 */ + writel(AT91_SPI_NCPHA | + (AT91_SPI_DLYBS & DATAFLASH_TCSS) | + (AT91_SPI_DLYBCT & DATAFLASH_TCHS) | + ((AT91_MASTER_CLOCK / AT91_SPI_CLK) << 8), + AT91_BASE_SPI + AT91_SPI_CSR(1)); +#endif + +#ifdef CFG_DATAFLASH_LOGIC_ADDR_CS3 + /* Configure CS3 */ + writel(AT91_SPI_NCPHA | + (AT91_SPI_DLYBS & DATAFLASH_TCSS) | + (AT91_SPI_DLYBCT & DATAFLASH_TCHS) | + ((AT91_MASTER_CLOCK / AT91_SPI_CLK) << 8), + AT91_BASE_SPI + AT91_SPI_CSR(3)); +#endif + + /* SPI_Enable */ + writel(AT91_SPI_SPIEN, AT91_BASE_SPI + AT91_SPI_CR); + + while (!(readl(AT91_BASE_SPI + AT91_SPI_SR) & AT91_SPI_SPIENS)); + + /* + * Add tempo to get SPI in a safe state. + * Should not be needed for new silicon (Rev B) + */ + udelay(500000); + readl(AT91_BASE_SPI + AT91_SPI_SR); + readl(AT91_BASE_SPI + AT91_SPI_RDR); + +} + +void AT91F_SpiEnable(int cs) +{ + unsigned long mode; + + switch (cs) { + case 0: /* Configure SPI CS0 for Serial DataFlash AT45DBxx */ + mode = readl(AT91_BASE_SPI + AT91_SPI_MR); + mode &= 0xFFF0FFFF; + writel(mode | ((AT91_SPI_PCS0_DATAFLASH_CARD<<16) & AT91_SPI_PCS), + AT91_BASE_SPI + AT91_SPI_MR); + break; + case 1: /* Configure SPI CS1 for Serial DataFlash AT45DBxx */ + mode = readl(AT91_BASE_SPI + AT91_SPI_MR); + mode &= 0xFFF0FFFF; + writel(mode | ((AT91_SPI_PCS1_DATAFLASH_CARD<<16) & AT91_SPI_PCS), + AT91_BASE_SPI + AT91_SPI_MR); + break; + case 3: + mode = readl(AT91_BASE_SPI + AT91_SPI_MR); + mode &= 0xFFF0FFFF; + writel(mode | ((AT91_SPI_PCS3_DATAFLASH_CARD<<16) & AT91_SPI_PCS), + AT91_BASE_SPI + AT91_SPI_MR); + break; + } + + /* SPI_Enable */ + writel(AT91_SPI_SPIEN, AT91_BASE_SPI + AT91_SPI_CR); +} + +unsigned int AT91F_SpiWrite1(AT91PS_DataflashDesc pDesc); + +unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc) +{ + unsigned int timeout; + + pDesc->state = BUSY; + + writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS, AT91_BASE_SPI + AT91_SPI_PTCR); + + /* Initialize the Transmit and Receive Pointer */ + writel((unsigned int)pDesc->rx_cmd_pt, AT91_BASE_SPI + AT91_SPI_RPR); + writel((unsigned int)pDesc->tx_cmd_pt, AT91_BASE_SPI + AT91_SPI_TPR); + + /* Intialize the Transmit and Receive Counters */ + writel(pDesc->rx_cmd_size, AT91_BASE_SPI + AT91_SPI_RCR); + writel(pDesc->tx_cmd_size, AT91_BASE_SPI + AT91_SPI_TCR); + + if (pDesc->tx_data_size != 0) { + /* Initialize the Next Transmit and Next Receive Pointer */ + writel((unsigned int)pDesc->rx_data_pt, AT91_BASE_SPI + AT91_SPI_RNPR); + writel((unsigned int)pDesc->tx_data_pt, AT91_BASE_SPI + AT91_SPI_TNPR); + + /* Intialize the Next Transmit and Next Receive Counters */ + writel(pDesc->rx_data_size, AT91_BASE_SPI + AT91_SPI_RNCR); + writel(pDesc->tx_data_size, AT91_BASE_SPI + AT91_SPI_TNCR); + } + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked(); + timeout = 0; + + writel(AT91_SPI_TXTEN + AT91_SPI_RXTEN, AT91_BASE_SPI + AT91_SPI_PTCR); + while (!(readl(AT91_BASE_SPI + AT91_SPI_SR) & AT91_SPI_RXBUFF) && + ((timeout = get_timer_masked()) < CFG_SPI_WRITE_TOUT)); + writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS, AT91_BASE_SPI + AT91_SPI_PTCR); + pDesc->state = IDLE; + + if (timeout >= CFG_SPI_WRITE_TOUT) { + printf("Error Timeout\n\r"); + return DATAFLASH_ERROR; + } + + return DATAFLASH_OK; +} diff --git a/cpu/arm926ejs/at572d940hf/timer.c b/cpu/arm926ejs/at572d940hf/timer.c new file mode 100644 index 0000000..d81e867 --- /dev/null +++ b/cpu/arm926ejs/at572d940hf/timer.c @@ -0,0 +1,292 @@ +/* + * (C) Copyright 2007-2008 + * Stelian Pop <stelian.pop <at> leadtechdesign.com> + * Lead Tech Design <www.leadtechdesign.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 + */ + +/* + * Author: Antonio R. Costa + * based upon AT91 + */ + +#include <common.h> +#include <asm/errno.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at572d940hf.h> +#include <asm/arch/at572d940hf_mc.h> +#include <asm/arch/memory-map.h> +#include <asm/arch/at91_pit.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_rstc.h> +#include <asm/arch/timer.h> +#include <asm/arch/io.h> + +/* + * We're using the AT91CAP9/SAM9 PITC in 32 bit mode, by + * setting the 20 bit counter period to its maximum (0xfffff). + */ +#define TIMER_LOAD_VAL 0xfffff +#define READ_RESET_TIMER at91_sys_read(AT91_PIT_PIVR) +#define READ_TIMER at91_sys_read(AT91_PIT_PIIR) +#define TIMER_FREQ (AT91_MASTER_CLOCK << 4) +#define TICKS_TO_USEC(ticks) ((ticks) / 6) + +ulong get_timer_masked(void); +ulong resettime; + + +int sys_get_freq(unsigned long mode, unsigned long *pfreq) { + unsigned long mckr = (unsigned long) -1; + unsigned long clksrc=0; + unsigned long clkpre=0; + unsigned long clkdiv=0; + unsigned long main_clock=0; + unsigned long tmode = mode; + + + /*!This function checks for \c AT91_CLK_DELAY_CYCLES cycles if the main clock is ready. + * If it is not it exits with \c -EIO. + * Otherwise, assuming a slow clock of \c CFG_SLOW_CLK Hz (default 32768 Hz), it computes + * the number of main clock cycles occurring in 16 slow clock cycles. + * This number multiplied by (_GNAM_SLOW_CLK / 16) results in the + * actual frequency of the main clock. + */ + { + long tmp = AT91_CLK_DELAY_CYCLES; + while(!(at91_sys_read(AT91_CKGR_MCFR) & AT91_PMC_MAINRDY) && (tmp-- > 0)); + if(tmp <= 0) { + *pfreq = 0; + return -EIO; + } + } + + main_clock = (at91_sys_read(AT91_CKGR_MCFR) & AT91_PMC_MAINF) * (CFG_SLOW_CLK / 16); + + /*!Depending on the \c mode parameter, this function returns frequencies + * for the <b>slow clock</b>, <b>main clock</b>, \b PLLA, \b PLLB or <b>master clock</b>. + */ + + /*!In the last case the function reads the PMC to find which source + * has been selected for the master clock and perform the relevant + * computations. + */ + + if(AT91_SLOW_FREQ == mode) { + *pfreq = CFG_SLOW_CLK; + return 0; + } + + /* Little trick: master clock depends on another source, + * so here it checks for the selected source and + * change the mode param to the master clock source + */ + if((AT91_SYS_FREQ == mode) | (AT91_PROC_FREQ == mode)) { + mckr = at91_sys_read(AT91_PMC_MCKR); + clksrc = (mckr & AT91_PMC_CSS ) ; + clkpre = (mckr & AT91_PMC_PRES) >> 2; + clkdiv = (mckr & AT91_PMC_MDIV) >> 8; + tmode = clksrc; + } + + if(AT91_PMC_CSS_MAIN == tmode) + *pfreq = main_clock; + + if(AT91_PMC_CSS_PLLA == tmode) { + unsigned long pllar = at91_sys_read(AT91_CKGR_PLLAR); + unsigned long mula = (pllar & AT91_PMC_MUL) >> 16; + unsigned long diva = (pllar & AT91_PMC_DIV); + *pfreq = (diva != 0) ? ((main_clock / diva) * ++mula) : 0; + } + + if(AT91_PMC_CSS_PLLB == tmode) { + unsigned long pllbr = at91_sys_read(AT91_CKGR_PLLBR); + unsigned long mulb = (pllbr & AT91_PMC_MUL) >> 16; + unsigned long divb = (pllbr & AT91_PMC_DIV); + + *pfreq = (divb != 0) ? ((main_clock / divb) * ++mulb) : 0; + } + + /* If the mode selected is different of + * _GNAM_SYS_FREQ or AT91_PROC_FREQ + * all is done and frequency can be returned. + */ + if((AT91_SYS_FREQ != mode) & (AT91_PROC_FREQ != mode)) + return 0; + + /* Here it divides the frequency + * by the prescaler factor + */ + *pfreq = *pfreq >> clkpre; + + /* If the selected frequency is AT91_SYS_FREQ + * then it must be selected by the clkdiv factor + */ + if(AT91_SYS_FREQ == mode) + *pfreq = *pfreq >> clkdiv; + + return 0; +} + + +/* nothing really to do with interrupts, just starts up a counter. */ +int timer_init(void) +{ + /* + * Enable PITC Clock + * The clock is already enabled for system controller in boot + */ + at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_SYS); + + /* Enable PITC */ + at91_sys_write(AT91_PIT_MR, TIMER_LOAD_VAL | AT91_PIT_PITEN); + + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ + +static inline ulong get_timer_raw(void) +{ + ulong now = READ_TIMER; + + if (now >= resettime) + return now - resettime; + else + return 0xFFFFFFFFUL - (resettime - now) ; +} + +void reset_timer_masked(void) +{ + resettime = READ_TIMER; +} + +ulong get_timer_masked(void) +{ + return TICKS_TO_USEC(get_timer_raw()); + +} + +void udelay_masked(unsigned long usec) +{ + ulong tmp; + + tmp = get_timer(0); + while (get_timer(tmp) < usec) /* our timer works in usecs */ + ; /* NOP */ +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + ulong now = get_timer_masked(); + + if (now >= base) + return now - base; + else + return TICKS_TO_USEC(0xFFFFFFFFUL) - (base - now) ; +} + +void udelay(unsigned long usec) +{ + udelay_masked(usec); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + ulong tbclk; + + tbclk = CFG_HZ; + return tbclk; +} + +/* + * Reset the cpu by setting up the watchdog timer and let him time out. + */ +void reset_cpu(ulong ignored) +{ + //at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY | (0x3u << 8) | 0x01); + + /* + * ARC: + * This code must be executed in internal RAM + * cause the SDRAM is under reset + */ + + /* + * ARC: + * Reset SDRAM in safe way + */ + unsigned long reg = at91_sys_read(AT91_SDRAMC_LPR); + at91_sys_write(AT91_SDRAMC_LPR, reg | AT91_SDRAMC_LPCB_SELF_REFRESH); + at91_sys_write(AT91_SDRAMC_MR, AT91_SDRAMC_MODE_NORMAL); + *(volatile unsigned long *) AT572D940_SDRAM_BASE = 0x0; + + /* + * ARC + * Waits until the reset button has been released. + * Unusefull if checked previously. + */ + + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_EXTRST); + + + while(!(at91_sys_read(AT91_RSTC_SR) & (1<<16))); + + { + /* + * ARC: + * i should be register cause SDRAM has been reset + */ + volatile register unsigned int i = 1000000; + while(i-->0); + }; + + + /* this is the way Linux does it */ + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | + AT91_RSTC_PROCRST | +// AT91_RSTC_EXTRST + AT91_RSTC_PERRST); + return; + while (1); + /* Never reached */ +} diff --git a/cpu/arm926ejs/at572d940hf/usb.c b/cpu/arm926ejs/at572d940hf/usb.c new file mode 100644 index 0000000..d678897 --- /dev/null +++ b/cpu/arm926ejs/at572d940hf/usb.c @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2006 + * DENX Software Engineering <mk <at> 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> + +#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT) + +#include <asm/arch/hardware.h> +#include <asm/arch/io.h> +#include <asm/arch/at91_pmc.h> + +int usb_cpu_init(void) +{ + /* Enable USB host clock. */ + at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_UHP); + at91_sys_write(AT91_PMC_SCER, AT91_PMC_UHP); + + return 0; +} + +int usb_cpu_stop(void) +{ + /* Disable USB host clock. */ + at91_sys_write(AT91_PMC_PCDR, 1 << AT91_ID_UHP); + at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP); + return 0; +} + +int usb_cpu_init_fail(void) +{ + return usb_cpu_stop(); +} + +#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */ -- 1.5.4.3 ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ U-Boot-Users mailing list U-Boot-Users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/u-boot-users