[U-Boot] [PATCH 2/2] LPC2468 example board

Jean-Christophe PLAGNIOL-VILLARD
2009-07-18T16:16:34Z

On 15:54 Tue 28 Apr , Remco Poelstra wrote:
> Added example board for LPC2468 processor
>
> Signed-off-by: Remco Poelstra <remco.poelstra+u-boot@duran-audio.com
please split your patch
> ---
> From ab9ef1e9c2bd8f04612429461baa5c24dbc52266 Mon Sep 17 00:00:00 2001
> From: Remco Poelstra <remco.poelstra@duran-audio.com>
> Date: Tue, 28 Apr 2009 15:04:33 +0200
> Subject: [PATCH] Added example board for LPC2468 processor
>
> ---
> board/LPC2468/LPC2468.c | 65 +++++
> board/LPC2468/Makefile | 55 +++++
> board/LPC2468/config.mk | 29 +++
> board/LPC2468/flash.c | 255 +++++++++++++++++++
> board/LPC2468/lowlevel_init.c | 445 ++++++++++++++++++++++++++++++++++
> board/LPC2468/nand.c | 63 +++++
please add it in an other patch
and please store it in drivers/mtd/nand/
> board/LPC2468/u-boot.lds | 55 +++++
> include/asm-arm/arch-lpc24xx/immap.h | 142 ++++++++++-
> include/configs/LPC2468.h | 220 +++++++++++++++++
> 9 files changed, 1319 insertions(+), 10 deletions(-)
> create mode 100644 board/LPC2468/LPC2468.c
> create mode 100755 board/LPC2468/Makefile
> create mode 100755 board/LPC2468/config.mk
> create mode 100644 board/LPC2468/flash.c
> create mode 100644 board/LPC2468/lowlevel_init.c
> create mode 100755 board/LPC2468/nand.c
> create mode 100755 board/LPC2468/u-boot.lds
> create mode 100644 include/configs/LPC2468.h
>
> diff --git a/board/LPC2468/LPC2468.c b/board/LPC2468/LPC2468.c
> new file mode 100644
> index 0000000..498885f
> --- /dev/null
> +++ b/board/LPC2468/LPC2468.c
> @@ -0,0 +1,65 @@
> +/*
> + * (C) Copyright 2002
> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
> + * Marius Groeger <mgroeger@sysgo.de>
> + *
> + * (C) Copyright 2005 Rowel Atienza <rowel@diwalabs.com>
> + * Armadillo board HT1070
> + *
> + * 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 <clps7111.h>
> +
> +/* ------------------------------------------------------------------------- */
> +
> +/*
> + * Miscelaneous platform dependent initialisations
> + */
> +
> +int board_init (void)
> +{
> + DECLARE_GLOBAL_DATA_PTR;
> +
> + /* arch number MACH_TYPE_ARMADILLO - not official */
> + gd->bd->bi_arch_number = 1339;
please use proper CONFIG
> +
> + /* location of boot parameters */
> + gd->bd->bi_boot_params = 0xA0000100;
please use this style
CONFIG_RAM_BASE + 0x100
> +
> + return 0;
> +}
> +
> +int print_cpuinfo (void)
> +{
> + printf ("CPU: LPC2468 (ARM7tdmi-s from NXP)\n"
> + " running at 57.6 MHz (12 MHz crystal)\n");
is it possible to detect it?
> + return 0;
> +}
> +
> +int dram_init (void)
> +{
> + DECLARE_GLOBAL_DATA_PTR;
> +
> + gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
> + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
> +
> + return (0);
> +}
> diff --git a/board/LPC2468/Makefile b/board/LPC2468/Makefile
> new file mode 100755
> index 0000000..19a2cd7
> --- /dev/null
<snip>
> +TEXT_BASE = 0xA1f80000
> diff --git a/board/LPC2468/flash.c b/board/LPC2468/flash.c
> new file mode 100644
> index 0000000..9d61b43
> --- /dev/null
> +++ b/board/LPC2468/flash.c
Is your flash cfi compatible?
Stefan what do you think?
> @@ -0,0 +1,255 @@
> +/*
> + * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.com>
> + *
> + * (C) Copyright 2009 Duran Audio B.V. <www.duran-audio.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + *
> + * 18-03-2009 Updated for U-boot 2009.3
> + * by Remco Poelstra <remco.poelstra+u-boot@duran-audio.com>
> + */
> +

> diff --git a/board/LPC2468/lowlevel_init.c b/board/LPC2468/lowlevel_init.c
> new file mode 100644
> index 0000000..f7d7698
> --- /dev/null
> +++ b/board/LPC2468/lowlevel_init.c
> @@ -0,0 +1,445 @@
> +/*
> + * (C) Copyright 2006-2007 Embedded Artists AB <www.embeddedartists.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <config.h>
> +#include <version.h>
> +#include <exports.h>
> +#include <asm/arch/immap.h>
> +#include <asm/io.h>
I think a lot's of the inits done here are soc specific and not board specific
> +
> +/******************************************************************************
> + * Defines, macros, and typedefs
> + *****************************************************************************/
> +
> +#define USE_USB 1
> +
> +#define PLL_MValue (CONFIG_PLL_MVALUE-1)
> +#define PLL_NValue (CONFIG_PLL_NVALUE-1)
> +#define CCLKDivValue (CONFIG_PLL_CLKDIV-1)
> +#define USBCLKDivValue (CONFIG_PLL_USBCLKDIV-1)
> +
> +#define Fcco ((2*CONFIG_PLL_MVALUE*CONFIG_FOSC) / CONFIG_PLL_NVALUE)
> +#define Fcclk (Fcco / CONFIG_PLL_CLKDIV)
> +#define Fpclk (Fcclk / CONFIG_FPCLK_DIV)
> +#define MAM_SETTING 1 /* 0=disabled,
> + 1=partly enabled (enabled for code prefetch,
> + but not for data),
> + 2=fully enabled */
> +#define MEM_MAP 2 /*When executing from RAM, MAM_MAP should always be 2*/
> +#define SDRAM_BASE_ADDR 0xA0000000
> +#define FASTIO_BASE_ADDR 0x3FFF8000
please move thise configs to beter place
> +
> +/* Helper macros */
> +#define BFS32(reg,value) writel( (readl(reg)|=(value)) ,reg)
> +#define BFC32(reg,value) writel( (readl(reg)&=(~value)) ,reg)
> +
> +/*****************************************************************************
> + *
> + * Description:
> + * Delay execution by a specified number of milliseconds by using
> + * timer #1. A polled implementation.
> + *
> + * Params:
> + * [in] delayInMs - the number of milliseconds to delay.
> + *
> + ****************************************************************************/
> +void delayMs (unsigned short delayInMs)
> +{
> + timer_2468_t *timer=&(((immap_t *)CONFIG_SYS_IMMAP)->apb.timer1);
> + /*
> + * setup timer #1 for delay
> + */
> + writel (0x02, &(timer->tcr)); /*stop and reset timer */
> + writel (0x00, &(timer->pr)); /*set prescaler to zero */
> + writel (delayInMs * (Fpclk / 1000), &(timer->mr0));
> +
> + writel (0xff, &(timer->ir)); /*reset all interrrupt flags */
> + writel (0x04, &(timer->mcr)); /*stop timer on match */
> + writel (0x01, &(timer->tcr)); /*start timer */
> +
> + /*wait until delay time has elapsed */
> + while (readl (&(timer->tcr)) & 0x01) ;
> +
> +}
why do you need this and do not use the general timer implementation?
> +
> +/******************************************************************************
> +** Function name: GPIOinit
> +**
> +** Descriptions: Sets all GPIO ports to a known state
> +** parameters: None
> +** Returned value: None
could you describe what you do here?
maybe use gpio api to be more generic and understandable
> +**
> +******************************************************************************/
> +static void GPIOinit (void)
> +{
> + pin_connect_2468_t *pin_connect=
> + &(((immap_t *)CONFIG_SYS_IMMAP)->apb.pin_connect);
> + gpio_2468_t *gpio=
> + &(((immap_t *)CONFIG_SYS_IMMAP)->apb.gpio);
> + fastio_2468_t *fio=(fastio_2468_t *)FASTIO_BASE_ADDR;
> +
> + writel (0, &(pin_connect->pinsel0));
> + writel (0, &(pin_connect->pinsel1));
> + writel (0, &(pin_connect->pinsel2));
> + writel (0, &(pin_connect->pinsel3));
> + writel (0, &(pin_connect->pinsel4));
> + writel (0, &(pin_connect->pinsel5));
> + writel (0, &(pin_connect->pinsel6));
> + writel (0, &(pin_connect->pinsel7));
> + writel (0, &(pin_connect->pinsel8));
> + writel (0, &(pin_connect->pinsel9));
> + writel (0, &(pin_connect->pinsel10));
> +
> + writel (0, &(gpio->iodir0));
> + writel (0, &(gpio->iodir1));
> + writel (0xffffffff, &(gpio->ioset0));
> + writel (0xffffffff, &(gpio->ioset1));
> +
> + writel (0, &(fio->fio0dir));
> + writel (0, &(fio->fio1dir));
> + writel (0, &(fio->fio2dir));
> + writel (0, &(fio->fio3dir));
> + writel (0, &(fio->fio4dir));
> +
> + writel (0xffffffff, &(fio->fio0set));
> + writel (0xffffffff, &(fio->fio1set));
> + writel (0xffffffff, &(fio->fio2set));
> + writel (0, &(fio->fio3set));
> + writel (0xffffffff, &(fio->fio4set));
> +}
> +
> +/******************************************************************************
> +** Function name: VICinit
> +**
> +** Descriptions: Initialize the VIC to a known state
> +** parameters: None
> +** Returned value: None
why do you need this?
do you use the interrupt in update?
> +**
> +******************************************************************************/
> +static void VICinit (void)
please uppercase for macro
and lowercase for the rest
> +{
> + vic_2468_t *vic=&(((immap_t *)CONFIG_SYS_IMMAP)->ahb.vic);
> + /*initialize VIC */
> + writel (0xffffffff, &(vic->vicinenclr)); /* Disable ALL interrupts */
> + writel (0, &(vic->vicprotect)); /* Setup interrupt controller */
> + writel (0, &(vic->vicaddr));
> + writel (0, &(vic->vicintselect));
> + writel (0, &(vic->vicvectaddr0)); /* Set the vector address */
try to use array to simplify it
> + writel (0, &(vic->vicvectaddr1));
> + writel (0, &(vic->vicvectaddr2));
> + writel (0, &(vic->vicvectaddr3));
> + writel (0, &(vic->vicvectaddr4));
<snip>
> +void ConfigurePLL (void)
> +{
> + sys_con_2468_t *sys_con=&(((immap_t *)CONFIG_SYS_IMMAP)->apb.sys_con);
> +
> + volatile unsigned long MValue;
> + volatile unsigned long NValue;
please add an empty line
> + if (readl (&(sys_con->pllstat)) & (1 << 25)) {
> +
> + writel (1, &(sys_con->pllcon)); /* Enable PLL, disconnected */
> + writel (0xaa, &(sys_con->pllfeed));
> + writel (0x55, &(sys_con->pllfeed));
> + }
> +
> + writel (0, &(sys_con->pllcon)); /* Disable PLL, disconnected */
> + writel (0xaa, &(sys_con->pllfeed));
> + writel (0x55, &(sys_con->pllfeed));
> + BFS32 (&(sys_con->scs), 0x20); /* Enable main OSC */
> +
> + /* Wait until main OSC is usable */
> + while (!(readl (&(sys_con->scs)) & 0x40));
> +
> + /* select main OSC, 12MHz, as the PLL clock source */
> + writel (0x1, &(sys_con->clksrcsel));
> + writel (PLL_MValue | (PLL_NValue << 16), &(sys_con->pllcfg));
> + writel (0xaa, &(sys_con->pllfeed));
> + writel (0x55, &(sys_con->pllfeed));
> + writel (1, &(sys_con->pllcon)); /* Enable PLL, disconnected */
> + writel (0xaa, &(sys_con->pllfeed));
> + writel (0x55, &(sys_con->pllfeed));
> + writel (CCLKDivValue, &(sys_con->cclkcfg)); /*Set clock divider*/
> +
> +#if USE_USB
please use a CONFIG_CMD_USB or other related CONFIG
> + /* usbclk = 288 MHz/6 = 48 MHz */
> + writel (USBCLKDivValue, &(sys_con->usbclkcfg));
> +#endif
> +
> + /* Check lock bit status */
> + while (((readl (&(sys_con->pllstat)) & (1 << 26)) == 0));
> +
> + MValue = readl (&(sys_con->pllstat)) & 0x00007FFF;
> + NValue = (readl (&(sys_con->pllstat)) & 0x00FF0000) >> 16;
> +
> + while ((MValue != PLL_MValue) && (NValue != PLL_NValue)) ;
> +
> + writel (3, &(sys_con->pllcon)); /* enable and connect */
> + writel (0xaa, &(sys_con->pllfeed));
> + writel (0x55, &(sys_con->pllfeed));
> + /* Check connect bit status */
> + while (((readl (&(sys_con->pllstat)) & (1 << 25)) == 0));
> +}
> +
> +/****************************************************************************
> +** Function name: ConfigureEMC
> +**
> +** Descriptions: Configure EMC for external SDRAM, NAND and NOR FLASH
> +** parameters: None
> +** Returned value: None
> +**
> +****************************************************************************/
> +void ConfigureEMC (void)
> +{
> + ext_mem_2468_t *emc=&(((immap_t *)CONFIG_SYS_IMMAP)->ahb.ext_mem);
> + pin_connect_2468_t *pin_connect=
> + &(((immap_t *)CONFIG_SYS_IMMAP)->apb.pin_connect);
> + sys_con_2468_t *sys_con=&(((immap_t *)CONFIG_SYS_IMMAP)->apb.sys_con);
> +
> + volatile unsigned int i, dummy = dummy;
> +
> + writel (0x00000001, &(emc->control));
> + BFS32 (&(sys_con->pconp), 0x00000800); /* Turn on EMC PCLK */
> +
> + /* CS2 & CS3 not used PINSEL4 = 0x50000000; */
> + writel (0x05050555, &(pin_connect->pinsel5));
> + writel (0x55555555, &(pin_connect->pinsel6));
> + writel (0x55555555, &(pin_connect->pinsel8));
> + writel (0x50555555, &(pin_connect->pinsel9));
> +
> + /*all registers... */
> + writel (2, &(emc->dynrp)); /*>20ns = 2 clk */
> + writel (3, &(emc->dynras)); /*>45ns = 3 clk */
> + writel (7, &(emc->dynsrex)); /*>80-100ns = 6 clk */
> + writel (2, &(emc->dynapr));
> + writel (5, &(emc->dyndal)); /*2 clk */
> + writel (1, &(emc->dynwr)); /*2 clk */
> + writel (5, &(emc->dynrc)); /*>65ns = 4 clk */
> + writel (5, &(emc->dynrfc)); /*>80-100ns = 6 clk */
> + writel (7, &(emc->dynxsr)); /*>80-100ns = 6 clk */
> + writel (1, &(emc->dynrrd)); /*>15ns = 1-2 clk */
> + writel (2, &(emc->dynmrd)); /*2 clk */
> + writel (1, &(emc->dynreadconfig)); /*or 1,2,3 */
> + writel (0x00000303, &(emc->dynrascas0));
> + writel (0x00000680, &(emc->dynconfig0));
> +
> + /*wait 100mS */
> + delayMs (100);
> +
> + /*Send command: NOP */
> + writel (0x00000183, &(emc->dyncontrol));
> +
> + /*wait 200mS */
> + delayMs (200);
> +
> + /*Send command: PRECHARGE-ALL, shortest possible refresh period */
> + writel (0x00000103, &(emc->dyncontrol));
> + writel (0x00000002, &(emc->dynrefresh));
> +
> + /*wait 128 ABH clock cycles */
> + for (i = 0; i < 0x40; i++)
> + asm volatile (" nop");
> +
> + /*Set correct refresh period */
> + writel (28, &(emc->dynrefresh));
> +
> + /*Send command: MODE */
> + writel (0x00000083, &(emc->dyncontrol));
> +
> + /*Set mode register in SDRAM */
> + dummy = *((volatile unsigned int *)(SDRAM_BASE_ADDR | (0x33 << 12)));
> +
> + /*Send command: NORMAL */
> + writel (0x00000000, &(emc->dyncontrol));
> +
> + /*Enable buffer */
> + BFS32 (&(emc->dynconfig0), 0x00080000);
> +
> + /*initial system delay */
> + delayMs (1);
> +
> + writel (0x2, &(emc->statwaitwen0));
> + writel (0x2, &(emc->statwaitoen0));
> + writel (0x1f, &(emc->statwaitrd0));
> + writel (0x1f, &(emc->statwaitpage0));
> + writel (0x1f, &(emc->statwaitwr0));
> + writel (0xf, &(emc->statwaitturn0));
> + writel (0x00000081, &(emc->statconfig0));
> + writel (0x2, &(emc->statwaitwen1));
> + writel (0x2, &(emc->statwaitoen1));
> + writel (0x8, &(emc->statwaitrd1));
> + writel (0x1f, &(emc->statwaitpage1));
> + writel (0x8, &(emc->statwaitwr1));
> + writel (0xf, &(emc->statwaitturn1));
> + writel (0x00000080, &(emc->statconfig1));
> +}
> +
> +/*****************************************************************************
> + *
> + * Description:
> + * Initialize system functions and GPIO
> + *
> + ****************************************************************************/

> --- /dev/null
> +++ b/board/LPC2468/u-boot.lds
no need please remove
> @@ -0,0 +1,55 @@
> +/*
> + * (C) Copyright 2000
> + * 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
> + */
> +
<snip>
> +
> +#ifndef __CONFIG_H
> +#define __CONFIG_H
> +
> +#define CONFIG_LPC2468
> +
> +/*
> + * If we are developing, we might want to start armboot from ram
> + * so we MUST NOT initialize critical regs like mem-timing ...
> + */
> +#if 0
> +#define CONFIG_INIT_CRITICAL /* undef for developing */
> +#endif
please remove
> +
> +#undef CONFIG_SKIP_LOWLEVEL_INIT
> +
> +/*
> + * High Level Configuration Options
> + * (easy to change)
> + */
> +#define CONFIG_ARM7 1 /* This is a ARM7 CPU */
> +#define CONFIG_ARM_THUMB 1 /* this is an ARM720TDMI */
> +#undef CONFIG_ARM7_REVD /* disable ARM720 REV.D Workarounds */
> +
> +/* Clock settings */
> +
> +/* Crystal frequency */
> +#define CONFIG_FOSC 12000000
> +
> +/*
> + * Fcco = 2*M*Fosc / N
> + *
> + * Fcco = 288000000 -> M = 12, N = 1
> + *
> + * PLLCFG (MSEL) = (M-1)
> + * PLLCFG (NSEL) = (N-1)
> + */
> +#define CONFIG_PLL_MVALUE 12
> +#define CONFIG_PLL_NVALUE 1
> +
> +/*
> + * Fcclk = Fcco / CLKDIV
> + * CLKDIV must be an even number
> + *
> + * CCLKCFG = CLKDIV-1 (odd number must be written to register)
> + * CLKDIV = 4 -> Fcclk = 72 MHz (if Fcco = 288 MHz)
> + * CLKDIV = 6 -> Fcclk = 48 MHz (if Fcco = 288 MHz)
> + */
> +#define CONFIG_PLL_CLKDIV 4
> +
> +/*
> + * The USB clock must be 48 MHz
> + * Fusb = Fcco / USBCLKDIV
> + * USBCLKCFG = (USBCLKDIV-1)
> + */
> +#define CONFIG_PLL_USBCLKDIV 6
> +
> +/*
> + * Periperhal clock divider, i.e. Fpclk = Fcclk / divider
> + * Valid values are 1, 2, or 4
> + */
> +#define CONFIG_FPCLK_DIV 1
> +
> +#define CONFIG_USE_IRQ /* use irq for mci interface */
> +
> +/*
> + * Size of malloc() pool
> + */
> +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128*1024)
> +/* size in bytes reserved for initial data */
> +#define CONFIG_SYS_GBL_DATA_SIZE 128
> +
> +/*
> + * Hardware drivers
> + */
> +
> +/*
> + * select serial console configuration
> + */
> +#define CONFIG_LPC2468_SERIAL
> +#define CONFIG_SERIAL 1 /* we use Serial line 1 */
> +
> +#define CONFIG_LPC2468_ETH
> +
> +/* allow to overwrite serial and ethaddr */
> +#define CONFIG_ENV_OVERWRITE
> +
> +#define CONFIG_BAUDRATE 115200
> +
> +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT|CONFIG_BOOTP_BOOTFILESIZE)
> +
> +#include <config_cmd_default.h>
> +#undef CONFIG_CMD_NFS
> +#undef CONFIG_CMD_FPGA
> +#undef CONFIG_CMD_BOOTD
> +#define CONFIG_CMD_NAND
> +
> +#define CONFIG_BOOTARGS\
> + "root=/dev/ram initrd=0xa1800000,4000k console=ttyS0,115200N8"
> +
> +/*
> + * Miscellaneous configurable options
> + */
> +#define CFG_LONGHELP /*undef to save memory*/
it's not anymore CFG_ but CONFIG_SYS_
please rebase your patch against the Mainline

Best Regards,
J.