[U-Boot] [PATCH v2] Marvell Kirkwood family SOC support

Prafulla Wadaskar prafulla at marvell.com
Tue Apr 14 19:26:31 CEST 2009


Hi all,

Any comments welcomed...
Or Shall I consider this patch is accepted ;-)
.....Shall I send it again ?

Regards..
Prafulla . .

> -----Original Message-----
> From: Prafulla Wadaskar [mailto:prafulla at marvell.com]
> Sent: Wednesday, April 08, 2009 5:33 PM
> To: u-boot at lists.denx.de
> Cc: Ronen Shitrit; Ashish Karkare; Prafulla Wadaskar
> Subject: [PATCH v2] Marvell Kirkwood family SOC support
>
> Kirkwood family controllers are highly integrated SOCs
> based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
>
> SOC versions supported:-
> 1) 88F6281-Z0       define CONFIG_KW88F6281_Z0
> 2) 88F6281-A0       define CONFIG_KW88F6281_A0
> 3) 88F6192-A0       define CONFIG_KW88F6192_A0
>
> Other supported features:-
> 1) get_random_hex() fucntion
> 2) SPI port controller driver
> 3) PCI Express port initialization
>
> Contributors:
> Yotam Admon <yotam at marvell.com>
> Michael Blostein <michaelbl at marvell.com
>
> Reviewed-by: Ronen Shitrit <rshitrit at marvell.com>
> Signed-off-by: Prafulla Wadaskar <prafulla at marvell.com>
> ---
> Changelog:
> v2: crated arch-kirkwood and moved some header files there
> renamed and moved spi.c to drivers/spi/
> renamed and moved serial.c to drivers/serial/
> doimage utility removed
> soc_init.S renamed as lowlevel_init.S
> debug prints removed
>
>  board/Marvell/include/core.h              |    4 +
>  cpu/arm926ejs/kirkwood/Makefile           |   50 ++++++
>  cpu/arm926ejs/kirkwood/config.mk          |   25 +++
>  cpu/arm926ejs/kirkwood/dram.c             |   55 +++++++
>  cpu/arm926ejs/kirkwood/kwcore.c           |  250
> +++++++++++++++++++++++++++++
>  cpu/arm926ejs/kirkwood/kwcore.h           |   47 ++++++
>  cpu/arm926ejs/kirkwood/lowlevel_init.S    |  183
> +++++++++++++++++++++
>  cpu/arm926ejs/kirkwood/timer.c            |  165 +++++++++++++++++++
>  drivers/serial/Makefile                   |    1 +
>  drivers/serial/kirkwood_serial.c          |  187
> +++++++++++++++++++++
>  drivers/spi/Makefile                      |    1 +
>  drivers/spi/kirkwood_spi.c                |  199
> +++++++++++++++++++++++
>  include/asm-arm/arch-kirkwood/kirkwood.h  |  142 ++++++++++++++++
>  include/asm-arm/arch-kirkwood/kw88f6192.h |   37 +++++
>  include/asm-arm/arch-kirkwood/kw88f6281.h |   43 +++++
>  include/asm-arm/config.h                  |    4 +
>  16 files changed, 1393 insertions(+), 0 deletions(-)
>  create mode 100644 cpu/arm926ejs/kirkwood/Makefile
>  create mode 100644 cpu/arm926ejs/kirkwood/config.mk
>  create mode 100644 cpu/arm926ejs/kirkwood/dram.c
>  create mode 100644 cpu/arm926ejs/kirkwood/kwcore.c
>  create mode 100644 cpu/arm926ejs/kirkwood/kwcore.h
>  create mode 100644 cpu/arm926ejs/kirkwood/lowlevel_init.S
>  create mode 100644 cpu/arm926ejs/kirkwood/timer.c
>  create mode 100644 drivers/serial/kirkwood_serial.c
>  create mode 100644 drivers/spi/kirkwood_spi.c
>  create mode 100644 include/asm-arm/arch-kirkwood/kirkwood.h
>  create mode 100644 include/asm-arm/arch-kirkwood/kw88f6192.h
>  create mode 100644 include/asm-arm/arch-kirkwood/kw88f6281.h
>
> diff --git a/board/Marvell/include/core.h
> b/board/Marvell/include/core.h
> index c413439..ecc4682 100644
> --- a/board/Marvell/include/core.h
> +++ b/board/Marvell/include/core.h
> @@ -12,9 +12,11 @@ space). The macros take care of Big/Little
> endian conversions.
>  #ifndef __INCcoreh
>  #define __INCcoreh
>
> +#ifndef CONFIG_KIRKWOOD
>  #include "mv_gen_reg.h"
>
>  extern unsigned int INTERNAL_REG_BASE_ADDR;
> +#endif /* CONFIG_KIRKWOOD */
>
>  /****************************************/
>  /*       GENERAL Definitions                 */
> @@ -91,10 +93,12 @@ extern unsigned int INTERNAL_REG_BASE_ADDR;
>  #define _1G          0x40000000
>  #define _2G          0x80000000
>
> +#ifndef __ASSEMBLY__
>  #ifndef      BOOL_WAS_DEFINED
>  #define BOOL_WAS_DEFINED
>  typedef enum _bool{false,true} bool;
>  #endif
> +#endif
>
>  /* Little to Big endian conversion macros */
>
> diff --git a/cpu/arm926ejs/kirkwood/Makefile
> b/cpu/arm926ejs/kirkwood/Makefile
> new file mode 100644
> index 0000000..c917f0d
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/Makefile
> @@ -0,0 +1,50 @@
> +#
> +# (C) Copyright 2009
> +# Marvell Semiconductor <www.marvell.com>
> +# Prafulla Wadaskar <prafulla at marvell.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., 51 Franklin Street, Fifth Floor, Boston,
> +# MA 02110-1301 USA
> +#
> +
> +include $(TOPDIR)/config.mk
> +
> +LIB  = $(obj)lib$(SOC).a
> +
> +COBJS-y      = dram.o
> +COBJS-y      += kwcore.o
> +COBJS-y      += timer.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/kirkwood/config.mk
> b/cpu/arm926ejs/kirkwood/config.mk
> new file mode 100644
> index 0000000..000eeb4
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/config.mk
> @@ -0,0 +1,25 @@
> +#
> +# (C) Copyright 2009
> +# Marvell Semiconductor <www.marvell.com>
> +# Prafulla Wadaskar <prafulla at marvell.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., 51 Franklin Street, Fifth Floor, Boston,
> +# MA 02110-1301 USA
> +#
> +
> +PLATFORM_CPPFLAGS += -march=armv5te
> diff --git a/cpu/arm926ejs/kirkwood/dram.c
> b/cpu/arm926ejs/kirkwood/dram.c
> new file mode 100644
> index 0000000..80e2b13
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/dram.c
> @@ -0,0 +1,55 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <config.h>
> +
> +/*
> + * kw_sdram_bar - reads SDRAM Base Address Register
> + */
> +u32 kw_sdram_bar(MEMORY_BANK bank)
> +{
> +     u32 result = 0;
> +     u32 enable = (0x01 & KW_REG_READ((0x1504 + bank * 8)));
> +
> +     if ((!enable) || (bank > BANK3))
> +             return 0;
> +
> +     result = KW_REG_READ((0x1500 + bank * 8));
> +     return result;
> +}
> +
> +/*
> + * kw_sdram_bs - reads SDRAM Bank size
> + */
> +u32 kw_sdram_bs(MEMORY_BANK bank)
> +{
> +     u32 result = 0;
> +     u32 enable = (0x01 & KW_REG_READ((0x1504 + bank * 8)));
> +
> +     if ((!enable) || (bank > BANK3))
> +             return 0;
> +     result = (0xff000000 & KW_REG_READ((0x1504 + bank * 8)));
> +     result += 0x01000000;
> +     return result;
> +}
> diff --git a/cpu/arm926ejs/kirkwood/kwcore.c
> b/cpu/arm926ejs/kirkwood/kwcore.c
> new file mode 100644
> index 0000000..2e887d5
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/kwcore.c
> @@ -0,0 +1,250 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <common.h>
> +#include <u-boot/md5.h>
> +
> +void reset_cpu(unsigned long ignored)
> +{
> +     KW_REG_BITS_SET(KW_REG_CPU_RSTOUTN_MASK, BIT2);
> +     KW_REG_BITS_SET(KW_REG_CPU_SYS_SOFT_RST, BIT0);
> +     while (1) ;
> +}
> +
> +/*
> + * Generates Ramdom hex number reading some time varient
> system registers
> + * and using md5 algorithm
> + */
> +unsigned char get_random_hex(void)
> +{
> +     int i;
> +     u32 inbuf[16];
> +     u8 outbuf[16];
> +
> +#if defined (CONFIG_KW88F6281_Z0)
> +     KW_REG_BITS_SET(0x1478, BIT7);
> +#elif defined (CONFIG_KW88F6281_A0) || defined (CONFIG_KW88F6192_A0)
> +     /*
> +      * in case of 88F6281/88F6192 A0,
> +      * BIT7 need to reset to generate random values in 0x1470
> +      */
> +     KW_REG_BITS_RESET(0x1478, BIT7);
> +#else
> +#error Undefined SOC Revision
> +#endif
> +     for (i = 0; i < 16; i++) {
> +             inbuf[i] = KW_REG_READ(0x1470);
> +     }
> +     md5((u8 *) inbuf, 64, outbuf);
> +     return outbuf[outbuf[7] % 0x0f];
> +}
> +
> +/*
> + * kw_window_ctrl_reg_init - Mbus-L to Mbus Bridge Registers init.
> + */
> +int kw_window_ctrl_reg_init(void)
> +{
> +     KW_REG_WRITE(KW_REG_WIN_CTRL(0), 0x0fffe841);
> +     KW_REG_WRITE(KW_REG_WIN_BASE(0), 0x90000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_LOW(0), 0x90000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_HIGH(0), 0x00000000);
> +
> +     KW_REG_WRITE(KW_REG_WIN_CTRL(1), 0x007f2f11);
> +     KW_REG_WRITE(KW_REG_WIN_BASE(1), 0xF9000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_LOW(1), 0xF9000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_HIGH(1), 0x00000000);
> +
> +     KW_REG_WRITE(KW_REG_WIN_CTRL(2), 0x00ffe041);
> +     KW_REG_WRITE(KW_REG_WIN_BASE(2), 0xF0000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_LOW(2), 0xC0000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_HIGH(2), 0x00000000);
> +
> +     KW_REG_WRITE(KW_REG_WIN_CTRL(3), 0x00ff1e11);
> +     KW_REG_WRITE(KW_REG_WIN_BASE(3), 0xF8000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_LOW(3), 0x00000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_HIGH(3), 0x00000000);
> +
> +     KW_REG_WRITE(KW_REG_WIN_CTRL(4), 0x00ff1d11);
> +     KW_REG_WRITE(KW_REG_WIN_BASE(4), 0xFF000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_LOW(4), 0x00000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_HIGH(4), 0x00000000);
> +
> +     KW_REG_WRITE(KW_REG_WIN_CTRL(5), 0x07ff1e10);
> +     KW_REG_WRITE(KW_REG_WIN_BASE(5), 0xE8000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_LOW(5), 0x00000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_HIGH(5), 0x00000000);
> +
> +     KW_REG_WRITE(KW_REG_WIN_CTRL(6), 0x07ff1d10);
> +     KW_REG_WRITE(KW_REG_WIN_BASE(6), 0xF0000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_LOW(6), 0x00000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_HIGH(6), 0x00000000);
> +
> +     KW_REG_WRITE(KW_REG_WIN_CTRL(7), 0x00000131);
> +     KW_REG_WRITE(KW_REG_WIN_BASE(7), 0xFB000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_LOW(7), 0x00000000);
> +     KW_REG_WRITE(KW_REG_WIN_REMAP_HIGH(7), 0x00000000);
> +
> +     return KW_OK;
> +}
> +
> +/*
> + * kw_gpio_init - Init gpios for default values
> + */
> +void kw_gpio_init(u32 gpp0_oe_val, u32 gpp1_oe_val, u32
> gpp0_oe, u32 gpp1_oe)
> +{
> +     /* Init GPIOS to default values as per board requirement */
> +     KW_REG_WRITE(KW_REG_GPP0_DATA_OUT, gpp0_oe_val);
> +     KW_REG_WRITE(KW_REG_GPP1_DATA_OUT, gpp1_oe_val);
> +     KW_REG_WRITE(KW_REG_GPP0_DATA_OUT_EN, gpp0_oe);
> +     KW_REG_WRITE(KW_REG_GPP1_DATA_OUT_EN, gpp1_oe);
> +}
> +
> +/*
> + * kw_mpp_control_init - initialize mpp for board specific
> functionality
> + */
> +int kw_mpp_control_init(u32 mpp0_7, u32 mpp8_15, u32
> mpp16_23, u32 mpp24_31,
> +                     u32 mpp32_39, u32 mpp40_47, u32 mpp48_55)
> +{
> +     /* program mpp registers */
> +     KW_REG_WRITE(KW_REG_MPP_CONTROL0, mpp0_7);
> +     KW_REG_WRITE(KW_REG_MPP_CONTROL1, mpp8_15);
> +     KW_REG_WRITE(KW_REG_MPP_CONTROL2, mpp16_23);
> +     KW_REG_WRITE(KW_REG_MPP_CONTROL3, mpp24_31);
> +     KW_REG_WRITE(KW_REG_MPP_CONTROL4, mpp32_39);
> +     KW_REG_WRITE(KW_REG_MPP_CONTROL5, mpp40_47);
> +     KW_REG_WRITE(KW_REG_MPP_CONTROL6, mpp48_55);
> +     return KW_OK;
> +}
> +
> +/*
> + * kw_misc_init_r - SOC specific misc init (mainly cache
> initialization)
> + */
> +int kw_misc_init_r(void)
> +{
> +     char *env;
> +     volatile unsigned int temp;
> +
> +     /*CPU streaming & write allocate */
> +     env = getenv("enaWrAllo");
> +     if (env && ((strcmp(env, "yes") == 0) || (strcmp(env,
> "Yes") == 0))) {
> +             __asm__ __volatile__("mrc p15, 1, %0, c15, c1,
> 0":"=r"(temp));
> +             temp |= BIT28;
> +             __asm__ __volatile__("mcr p15, 1, %0, c15, c1,
> 0"::"r"(temp));
> +
> +     } else {
> +             __asm__ __volatile__("mrc p15, 1, %0, c15, c1,
> 0":"=r"(temp));
> +             temp &= ~BIT28;
> +             __asm__ __volatile__("mcr p15, 1, %0, c15, c1,
> 0"::"r"(temp));
> +     }
> +
> +     env = getenv("enaCpuStream");
> +     if (!env || (strcmp(env, "no") == 0) || (strcmp(env,
> "No") == 0)) {
> +             __asm__ __volatile__("mrc p15, 1, %0, c15, c1,
> 0":"=r"(temp));
> +             temp &= ~BIT29;
> +             __asm__ __volatile__("mcr p15, 1, %0, c15, c1,
> 0"::"r"(temp));
> +     } else {
> +             __asm__ __volatile__("mrc p15, 1, %0, c15, c1,
> 0":"=r"(temp));
> +             temp |= BIT29;
> +             __asm__ __volatile__("mcr p15, 1, %0, c15, c1,
> 0"::"r"(temp));
> +     }
> +
> +     /* Verify write allocate and streaming */
> +     printf("\n");
> +     __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0":"=r"(temp));
> +     if (temp & BIT29)
> +             printf("Streaming enabled\n");
> +     else
> +             printf("Streaming disabled\n");
> +     if (temp & BIT28)
> +             printf("Write allocate enabled\n");
> +     else
> +             printf("Write allocate disabled\n");
> +
> +     /* DCache Pref  */
> +     env = getenv("enaDCPref");
> +     if (env && ((strcmp(env, "yes") == 0) || (strcmp(env,
> "Yes") == 0))) {
> +             temp = KW_REG_READ(KW_REG_CPU_CONFIG);
> +             temp |= BIT17; /* Set CCR_DCACH_PREF_BUF_ENABLE */
> +             KW_REG_WRITE(KW_REG_CPU_CONFIG, temp);
> +     }
> +
> +     if (env && ((strcmp(env, "no") == 0) || (strcmp(env,
> "No") == 0))) {
> +             temp = KW_REG_READ(KW_REG_CPU_CONFIG);
> +             temp &= ~BIT17; /* Reset CCR_DCACH_PREF_BUF_ENABLE */
> +             KW_REG_WRITE(KW_REG_CPU_CONFIG, temp);
> +     }
> +
> +     /* ICache Pref  */
> +     env = getenv("enaICPref");
> +     if (env && ((strcmp(env, "yes") == 0) || (strcmp(env,
> "Yes") == 0))) {
> +             temp = KW_REG_READ(KW_REG_CPU_CONFIG);
> +             temp |= BIT16; /* Set CCR_ICACH_PREF_BUF_ENABLE */
> +             KW_REG_WRITE(KW_REG_CPU_CONFIG, temp);
> +     }
> +
> +     if (env && ((strcmp(env, "no") == 0) || (strcmp(env,
> "No") == 0))) {
> +             temp = KW_REG_READ(KW_REG_CPU_CONFIG);
> +             temp &= ~BIT16; /* Reset CCR_ICACH_PREF_BUF_ENABLE */
> +             KW_REG_WRITE(KW_REG_CPU_CONFIG, temp);
> +     }
> +     /* Set L2C WT mode - Set bit 4 */
> +     temp = KW_REG_READ(KW_REG_CPU_L2_CONFIG);
> +     env = getenv("setL2CacheWT");
> +     if (!env || ((strcmp(env, "yes") == 0) || (strcmp(env,
> "Yes") == 0))) {
> +             temp |= BIT4;
> +     } else
> +             temp &= ~BIT4;
> +     KW_REG_WRITE(KW_REG_CPU_L2_CONFIG, temp);
> +
> +     /* L2Cache settings */
> +     asm("mrc p15, 1, %0, c15, c1, 0":"=r"(temp));
> +
> +     /* Disable L2C pre fetch - Set bit 24 */
> +     env = getenv("disL2Prefetch");
> +     if (env && ((strcmp(env, "no") == 0) || (strcmp(env,
> "No") == 0)))
> +             temp &= ~BIT24;
> +     else
> +             temp |= BIT24;
> +
> +     /* enable L2C - Set bit 22 */
> +     env = getenv("disL2Cache");
> +     if (!env || ((strcmp(env, "no") == 0) || (strcmp(env,
> "No") == 0)))
> +             temp |= BIT22;
> +     else
> +             temp &= ~BIT22;
> +
> +     asm("mcr p15, 1, %0, c15, c1, 0": :"r"(temp));
> +
> +     /* Enable i cache */
> +     asm("mrc p15, 0, %0, c1, c0, 0":"=r"(temp));
> +     temp |= BIT12;
> +     asm("mcr p15, 0, %0, c1, c0, 0": :"r"(temp));
> +     /* Change reset vector to address 0x0 */
> +     asm("mrc p15, 0, %0, c1, c0, 0":"=r"(temp));
> +     temp &= ~BIT13;
> +     asm("mcr p15, 0, %0, c1, c0, 0": :"r"(temp));
> +
> +     return (0);
> +}
> +
> diff --git a/cpu/arm926ejs/kirkwood/kwcore.h
> b/cpu/arm926ejs/kirkwood/kwcore.h
> new file mode 100644
> index 0000000..8d2a8cc
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/kwcore.h
> @@ -0,0 +1,47 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#ifndef _KWCORE_H
> +#define _KWCORE_H
> +
> +/*
> + * functions
> + */
> +#ifndef __ASSEMBLY__
> +void reset_cpu(unsigned long ignored);
> +unsigned char get_random_hex(void);
> +typedef enum _memory_bank { BANK0, BANK1, BANK2, BANK3 } MEMORY_BANK;
> +unsigned int kw_sdram_bar(MEMORY_BANK bank);
> +unsigned int kw_sdram_bs(MEMORY_BANK bank);
> +int kw_window_ctrl_reg_init(void);
> +void kw_gpio_init(unsigned int gpp0_oe_val, unsigned int gpp1_oe_val,
> +               unsigned int gpp0_oe, unsigned int gpp1_oe);
> +int kw_mpp_control_init(unsigned int mpp0_7, unsigned int mpp8_15,
> +                     unsigned int mpp16_23, unsigned int mpp24_31,
> +                     unsigned int mpp32_39, unsigned int mpp40_47,
> +                     unsigned int mpp48_55);
> +int kw_misc_init_r(void);
> +#endif                               /* __ASSEMBLY__ */
> +
> +#endif                               /* _KWCORE_H */
> diff --git a/cpu/arm926ejs/kirkwood/lowlevel_init.S
> b/cpu/arm926ejs/kirkwood/lowlevel_init.S
> new file mode 100644
> index 0000000..169e58b
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/lowlevel_init.S
> @@ -0,0 +1,183 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <config.h>
> +
> +#define CCR_CPU_2_MBUSL_TICK_DRV_OFFS                8
> +#define CCR_CPU_2_MBUSL_TICK_DRV_MASK                (0xF <<
> CCR_CPU_2_MBUSL_TICK_DRV_OFFS)
> +#define CCR_CPU_2_MBUSL_TICK_SMPL_OFFS               12
> +#define CCR_CPU_2_MBUSL_TICK_SMPL_MASK               (0xF <<
> CCR_CPU_2_MBUSL_TICK_SMPL_OFFS)
> +
> +#define MSAR_DDRCLCK_RTIO_OFFS                       5
> +#define MSAR_DDRCLCK_RTIO_MASK                       (0xF <<
> MSAR_DDRCLCK_RTIO_OFFS)
> +
> +/* Ratio options for CPU to DDR for 6281/6192/6180 */
> +#define CPU_2_DDR_CLK_1x2                    2
> +#define CPU_2_DDR_CLK_1x3                    4
> +#define CPU_2_DDR_CLK_1x4                    6
> +
> +/* Default values for CPU to Mbus-L DDR Interface Tick
> Driver and    */
> +/* CPU to Mbus-L Tick Sample fields in CPU config register
>       */
> +
> +#define TICK_DRV_1x1                         0
> +#define TICK_DRV_1x2                         0
> +#define TICK_DRV_1x3                         1
> +#define TICK_DRV_1x4                         2
> +#define TICK_SMPL_1x1                                0
> +#define TICK_SMPL_1x2                                1
> +#define TICK_SMPL_1x3                                2
> +#define TICK_SMPL_1x4                                3
> +#define CPU_2_MBUSL_DDR_CLK_1x2
>               \
> +              ((TICK_DRV_1x2  <<
> CCR_CPU_2_MBUSL_TICK_DRV_OFFS) |      \
> +               (TICK_SMPL_1x2 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS))
> +#define CPU_2_MBUSL_DDR_CLK_1x3
>               \
> +              ((TICK_DRV_1x3  <<
> CCR_CPU_2_MBUSL_TICK_DRV_OFFS) |      \
> +               (TICK_SMPL_1x3 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS))
> +#define CPU_2_MBUSL_DDR_CLK_1x4
>               \
> +              ((TICK_DRV_1x4  <<
> CCR_CPU_2_MBUSL_TICK_DRV_OFFS) |      \
> +               (TICK_SMPL_1x4 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS))
> +
> +
> +     .globl kw_cpu_if_pre_init
> +kw_cpu_if_pre_init:
> +
> +        mov     r11, LR              /* Save link register */
> +
> +        /*
> +      * Configures the I/O voltage of the pads connected to Egigabit
> +      * Ethernet interface to 1.8V
> +      * By defult it is set to 3.3V
> +      */
> +#ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8
> +        KW_REG_READ_ASM (r7, r5, KW_REG_MPP_OUT_DRV_REG)
> +        ldr    r5, =BIT7
> +        orr    r7, r7, r5       /* Set RGMII PADS Voltage to 1.8V */
> +        KW_REG_WRITE_ASM (r7, r5, KW_REG_MPP_OUT_DRV_REG)
> +#endif
> +        /*
> +      * Set egiga port0/1 in normal functional mode
> +      * This is required becasue on kirkwood by default
> ports are in reset mode
> +      * OS egiga driver may not have provision to set them
> in normal mode
> +      * and if u-boot is build without network support,
> network may fail at OS level
> +      */
> +#ifdef CONFIG_KIRKWOOD_EGIGA_INIT
> +        KW_REG_READ_ASM (r7, r5, KW_ETH_PORT_SERIAL_CONTROL1_REG(0))
> +        ldr    r5, =~(BIT4)
> +        and    r7, r7, r5       /* Clear PortReset Bit */
> +        KW_REG_WRITE_ASM (r7, r5, KW_ETH_PORT_SERIAL_CONTROL1_REG(0))
> +
> +        KW_REG_READ_ASM (r7, r5, KW_ETH_PORT_SERIAL_CONTROL1_REG(1))
> +        ldr    r5, =~(BIT4)
> +        and    r7, r7, r5       /* Clear PortReset Bit */
> +        KW_REG_WRITE_ASM (r7, r5, KW_ETH_PORT_SERIAL_CONTROL1_REG(1))
> +#endif
> +
> +     /*
> +      * Enable PCI Express Port0
> +      */
> +#ifdef CONFIG_KIRKWOOD_PCIE_INIT
> +        KW_REG_READ_ASM (r7, r5, KW_REG_CPU_CTRL_STAT)
> +        ldr    r5, =BIT0
> +        orr    r7, r7, r5       /* Set PEX0En Bit */
> +        KW_REG_WRITE_ASM (r7, r5, KW_REG_CPU_CTRL_STAT)
> +#endif
> +
> +#ifdef CONFIG_KW88F6281_Z0
> +        /* Get the "sample on reset" register */
> +     KW_REG_READ_ASM (r4, r5, KW_REG_MPP_SMPL_AT_RST)
> +        ldr    r5, =MSAR_DDRCLCK_RTIO_MASK
> +        and    r5, r4, r5
> +     mov    r5, r5, lsr #MSAR_DDRCLCK_RTIO_OFFS
> +
> +        ldr    r4, =CPU_2_MBUSL_DDR_CLK_1x2
> +        cmp    r5, #CPU_2_DDR_CLK_1x2
> +        beq    set_config_reg
> +
> +        ldr    r4, =CPU_2_MBUSL_DDR_CLK_1x3
> +        cmp    r5, #CPU_2_DDR_CLK_1x3
> +        beq    set_config_reg
> +
> +        ldr    r4, =CPU_2_MBUSL_DDR_CLK_1x4
> +        cmp    r5, #CPU_2_DDR_CLK_1x4
> +        beq    set_config_reg
> +
> +        ldr    r4, =0
> +
> +set_config_reg:
> +        /* Read CPU Config register */
> +        KW_REG_READ_ASM (r7, r5, KW_REG_CPU_CONFIG)
> +        ldr    r5, =~(CCR_CPU_2_MBUSL_TICK_DRV_MASK |
> CCR_CPU_2_MBUSL_TICK_SMPL_MASK)
> +        and    r7, r7, r5       /* Clear register fields */
> +        orr    r7, r7, r4       /* Set the values according
> to the findings */
> +        KW_REG_WRITE_ASM (r7, r5, KW_REG_CPU_CONFIG)
> +
> +done:
> +#endif
> +        mov     PC, r11         /* r11 is saved link register */
> +
> +     .globl kw_enable_invalidate_l2_cache
> +kw_enable_invalidate_l2_cache:
> +        mov     r11, LR      /* Save link register */
> +
> +     /* Enable L2 cache in write through mode */
> +     KW_REG_READ_ASM(r4, r1, KW_REG_CPU_L2_CONFIG)
> +     orr     r4, r4, #0x18
> +     KW_REG_WRITE_ASM(r4, r1, KW_REG_CPU_L2_CONFIG)
> +     /* Read operation to make sure the L2 bit is set */
> +     KW_REG_READ_ASM(r4, r1, KW_REG_CPU_L2_CONFIG)
> +
> +     /* invalidate L2 cache */
> +     mov     r0, #0
> +     mcr     p15, 1, r0, c15, c11, 0
> +
> +        mov     PC, r11         /* r11 is saved link register */
> +
> +        .globl lowlevel_init
> +lowlevel_init:
> +        /* Linux expects` the internal registers to be at
> 0xf1000000 */
> +        ldr r1, = KW_OFFSET_REG
> +        ldr r3, = KW_REGS_PHY_BASE
> +        str r3,[r1]
> +
> +        /* save Link Registers */
> +        mov r2, lr
> +
> +        /* Enable L2 cache in write through mode */
> +        bl kw_enable_invalidate_l2_cache
> +
> +#ifdef CONFIG_BOARD_LOWLEVEL_INIT
> +        /*
> +      * if Kirkwood is configured not to use its internal bootROM
> +      * This will be needed specially for DRAM configuration
> +      */
> +        bl board_lowlevel_init
> +#endif
> +
> +        /*
> +      * Initialize BUS-L to DDR configuration parameters
> +      * Must be done prior to DDR operation
> +      */
> +        bl kw_cpu_if_pre_init
> +        mov lr, r2
> +        mov pc, lr
> diff --git a/cpu/arm926ejs/kirkwood/timer.c
> b/cpu/arm926ejs/kirkwood/timer.c
> new file mode 100644
> index 0000000..4ab1a54
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/timer.c
> @@ -0,0 +1,165 @@
> +/*
> + * Copyright (C) Marvell International Ltd. and its affiliates
> + * Prafulla Wadaskar <prafulla at marvell.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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <common.h>
> +
> +#define UBOOT_CNTR   0       /* counter to use for uboot timer */
> +
> +/*
> + * ARM Timers Registers Map
> + */
> +#define CNTMR_CTRL_REG                       KW_REG_TMR_CTRL
> +#define CNTMR_RELOAD_REG(tmrNum)     (KW_REG_TMR_RELOAD + tmrNum*8)
> +#define CNTMR_VAL_REG(tmrNum)                (KW_REG_TMR_VAL
> + tmrNum*8)
> +
> +/*
> + * ARM Timers Control Register
> + * CPU_TIMERS_CTRL_REG (CTCR)
> + */
> +#define TIMER0_NUM                           0
> +#define TIMER1_NUM                           1
> +#define WATCHDOG_NUM                         2
> +
> +#define CTCR_ARM_TIMER_EN_OFFS(cntr)         (cntr * 2)
> +#define CTCR_ARM_TIMER_EN_MASK(cntr)         (1 <<
> CTCR_ARM_TIMER_EN_OFFS)
> +#define CTCR_ARM_TIMER_EN(cntr)                      (1 <<
> CTCR_ARM_TIMER_EN_OFFS(cntr))
> +#define CTCR_ARM_TIMER_DIS(cntr)             (0 <<
> CTCR_ARM_TIMER_EN_OFFS(cntr))
> +
> +#define CTCR_ARM_TIMER_AUTO_OFFS(cntr)       ((cntr * 2) + 1)
> +#define CTCR_ARM_TIMER_AUTO_MASK(cntr)       BIT1
> +#define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 <<
> CTCR_ARM_TIMER_AUTO_OFFS(cntr))
> +#define CTCR_ARM_TIMER_AUTO_DIS(cntr)        (0 <<
> CTCR_ARM_TIMER_AUTO_OFFS(cntr))
> +
> +/*
> + * ARM Timer\Watchdog Reload Register
> + * CNTMR_RELOAD_REG (TRR)
> + */
> +#define TRG_ARM_TIMER_REL_OFFS                       0
> +#define TRG_ARM_TIMER_REL_MASK                       0xffffffff
> +
> +/*
> + * ARM Timer\Watchdog Register
> + * CNTMR_VAL_REG (TVRG)
> + */
> +#define TVR_ARM_TIMER_OFFS                   0
> +#define TVR_ARM_TIMER_MASK                   0xffffffff
> +#define TVR_ARM_TIMER_MAX                    0xffffffff
> +#define TIMER_LOAD_VAL                               0xffffffff
> +
> +/* This enumerator describe counters\watchdog numbers       */
> +typedef enum _kwCntmrID {
> +     TIMER0 = 0,
> +     TIMER1,
> +     WATCHDOG
> +} KW_CNTMR_ID;
> +
> +#define READ_TIMER
> (KW_REG_READ(CNTMR_VAL_REG(UBOOT_CNTR))/(CONFIG_SYS_TCLK/1000))
> +
> +static ulong timestamp;
> +static ulong lastdec;
> +
> +void reset_timer_masked(void)
> +{
> +     /* reset time */
> +     lastdec = READ_TIMER;
> +     timestamp = 0;
> +}
> +
> +ulong get_timer_masked(void)
> +{
> +     ulong now = READ_TIMER;
> +
> +     if (lastdec >= now) {
> +             /* normal mode */
> +             timestamp += lastdec - now;
> +     } else {
> +             /* we have an overflow ... */
> +             timestamp +=
> +                 lastdec + (TIMER_LOAD_VAL /
> (CONFIG_SYS_TCLK / 1000)) - now;
> +     }
> +     lastdec = now;
> +
> +     return timestamp;
> +}
> +
> +void reset_timer(void)
> +{
> +     reset_timer_masked();
> +}
> +
> +ulong get_timer(ulong base)
> +{
> +     return get_timer_masked() - base;
> +}
> +
> +void set_timer(ulong t)
> +{
> +     timestamp = t;
> +}
> +
> +void udelay(unsigned long usec)
> +{
> +     uint current;
> +     ulong delayticks;
> +
> +     current = KW_REG_READ(CNTMR_VAL_REG(UBOOT_CNTR));
> +     delayticks = (usec * (CONFIG_SYS_TCLK / 1000000));
> +
> +     if (current < delayticks) {
> +             delayticks -= current;
> +             while (KW_REG_READ(CNTMR_VAL_REG(UBOOT_CNTR)) <
> current) ;
> +             while ((TIMER_LOAD_VAL - delayticks) <
> +                    KW_REG_READ(CNTMR_VAL_REG(UBOOT_CNTR))) ;
> +     } else {
> +             while (KW_REG_READ(CNTMR_VAL_REG(UBOOT_CNTR)) >
> +                    (current - delayticks)) ;
> +     }
> +}
> +
> +/*
> + * init the counter
> + */
> +int timer_init(void)
> +{
> +     unsigned int cntmrCtrl;
> +
> +     /* load value onto counter\timer */
> +     KW_REG_WRITE(CNTMR_RELOAD_REG(UBOOT_CNTR), TIMER_LOAD_VAL);
> +     KW_REG_WRITE(CNTMR_VAL_REG(UBOOT_CNTR), TIMER_LOAD_VAL);
> +
> +     /* set the counter to load in the first time */
> +     KW_REG_WRITE(CNTMR_VAL_REG(UBOOT_CNTR), TIMER_LOAD_VAL);
> +
> +     /* set control for timer \ cunter and enable */
> +     /* read control register */
> +     cntmrCtrl = KW_REG_READ(CNTMR_CTRL_REG);
> +     cntmrCtrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR);     /*
> enable cnt\timer */
> +     cntmrCtrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR);
> /* Auto mode */
> +
> +     KW_REG_WRITE(CNTMR_CTRL_REG, cntmrCtrl);
> +
> +     /* init the timestamp and lastdec value */
> +     reset_timer_masked();
> +
> +     return 0;
> +}
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index bb99a34..dd59ff8 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -28,6 +28,7 @@ LIB := $(obj)libserial.a
>  COBJS-$(CONFIG_ARM_DCC) += arm_dcc.o
>  COBJS-$(CONFIG_AT91RM9200_USART) += at91rm9200_usart.o
>  COBJS-$(CONFIG_ATMEL_USART) += atmel_usart.o
> +COBJS-$(CONFIG_KIRKWOOD) += kirkwood_serial.o
>  COBJS-$(CONFIG_MCFUART) += mcfuart.o
>  COBJS-$(CONFIG_NS9750_UART) += ns9750_serial.o
>  COBJS-$(CONFIG_SYS_NS16550) += ns16550.o
> diff --git a/drivers/serial/kirkwood_serial.c
> b/drivers/serial/kirkwood_serial.c
> new file mode 100644
> index 0000000..6422ab2
> --- /dev/null
> +++ b/drivers/serial/kirkwood_serial.c
> @@ -0,0 +1,187 @@
> +/*
> + * Copyright (C) Marvell International Ltd. and its affiliates
> + * Prafulla Wadaskar <prafulla at marvell.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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <common.h>
> +
> +/* registers feilds */
> +#define FCR_FIFO_EN          BIT0    /* fifo enable */
> +#define FCR_RXSR             BIT1    /* receiver soft reset */
> +#define FCR_TXSR             BIT2    /* transmitter soft reset */
> +#define MCR_RTS              BIT1    /* ready to send */
> +
> +#define LCR_WLS_OFFS         0
> +#define LCR_WLS_MASK                 0x3 << LCR_WLS_OFFS
> /* character length mask  */
> +#define LCR_WLS_5            0x0 << LCR_WLS_OFFS     /* 5
> bit character length */
> +#define LCR_WLS_6            0x1 << LCR_WLS_OFFS     /* 6
> bit character length */
> +#define LCR_WLS_7            0x2 << LCR_WLS_OFFS     /* 7
> bit character length */
> +#define LCR_WLS_8            0x3 << LCR_WLS_OFFS     /* 8
> bit character length */
> +#define LCR_STP_OFFS         2
> +#define LCR_1_STB                    0x0 << LCR_STP_OFFS
> /* Number of stop Bits */
> +#define LCR_2_STB                    0x1 << LCR_STP_OFFS
> /* Number of stop Bits */
> +#define LCR_PEN              0x8     /* Parity enable */
> +#define LCR_PS_OFFS          4
> +#define LCR_EPS              0x1 << LCR_PS_OFFS      /* Even
> Parity Select */
> +#define LCR_OPS              0x0 << LCR_PS_OFFS      /* Odd
> Parity Select */
> +#define LCR_SBRK_OFFS                0x6
> +#define LCR_SBRK             0x1 << LCR_SBRK_OFFS    /* Set Break */
> +#define LCR_DIVL_OFFS                7
> +#define LCR_DIVL_EN                  0x1 << LCR_DIVL_OFFS
> /* Divisior latch enable */
> +
> +#define LSR_DR               BIT0    /* Data ready */
> +#define LSR_OE               BIT1    /* Overrun */
> +#define LSR_PE               BIT2    /* Parity error */
> +#define LSR_FE               BIT3    /* Framing error */
> +#define LSR_BI               BIT4    /* Break */
> +#define LSR_THRE             BIT5    /* Xmit holding
> register empty */
> +#define LSR_TEMT             BIT6    /* Xmitter empty */
> +#define LSR_ERR              BIT7    /* Error */
> +
> +/* useful defaults for LCR*/
> +#define LCR_8N1              LCR_WLS_8 | LCR_1_STB
> +
> +/* This structure describes the registers offsets for one
> UART port/channel */
> +typedef struct kwUartPort {
> +     u8 rbr;                 /* 0 = 0-3 */
> +     u8 pad1[3];
> +     u8 ier;                 /* 1 = 4-7 */
> +     u8 pad2[3];
> +     u8 fcr;                 /* 2 = 8-b */
> +     u8 pad3[3];
> +     u8 lcr;                 /* 3 = c-f */
> +     u8 pad4[3];
> +     u8 mcr;                 /* 4 = 10-13 */
> +     u8 pad5[3];
> +     u8 lsr;                 /* 5 = 14-17 */
> +     u8 pad6[3];
> +     u8 msr;                 /* 6 =18-1b */
> +     u8 pad7[3];
> +     u8 scr;                 /* 7 =1c-1f */
> +     u8 pad8[3];
> +} kw_uart_port;
> +
> +/* aliases - for registers which has the same offsets */
> +#define thr rbr
> +#define iir fcr
> +#define dll rbr
> +#define dlm ier
> +
> +/* static variables */
> +#if defined (CONFIG_CONS_INDEX)      /* comes from board config */
> +#if (CONFIG_CONS_INDEX == 0 )
> +static volatile kw_uart_port *p_uart_port = (void
> *)KW_REGISTER(KW_UART0_BASE);
> +#elif (CONFIG_CONS_INDEX == 1 )
> +static volatile kw_uart_port *p_uart_port = (void
> *)KW_REGISTER(KW_UART1_BASE);
> +#endif
> +#else
> +#error CONFIG_CONS_INDEX not defined correctly
> +#endif
> +
> +#define CONFIG_KW_UART_PORTS { (void *)KW_UART0_BASE, \
> +                               (void *)KW_UART1_BASE }
> +
> +/*
> + * Serial init banner is kept simplest one
> + * if required can be created good one
> + */
> +int serial_init(void)
> +{
> +     serial_setbrg();
> +     printf
> +
> ("\n*************************************************************");
> +     return (0);
> +}
> +
> +void kwUartPutc(u8 c)
> +{
> +     while ((p_uart_port->lsr & LSR_THRE) == 0) ;
> +     p_uart_port->thr = c;
> +     return;
> +}
> +
> +void serial_putc(const char c)
> +{
> +     if (c == '\n')
> +             kwUartPutc('\r');
> +
> +     kwUartPutc(c);
> +}
> +
> +int serial_getc(void)
> +{
> +     while ((p_uart_port->lsr & LSR_DR) == 0) ;
> +     return (p_uart_port->rbr);
> +}
> +
> +int serial_tstc(void)
> +{
> +     return ((p_uart_port->lsr & LSR_DR) != 0);
> +}
> +
> +void serial_setbrg(void)
> +{
> +     DECLARE_GLOBAL_DATA_PTR;
> +
> +     int clock_divisor = (CONFIG_SYS_TCLK / 16) / gd->baudrate;
> +
> +     p_uart_port->ier = 0x00;
> +     p_uart_port->lcr = LCR_DIVL_EN; /* Access baud rate */
> +     p_uart_port->dll = clock_divisor & 0xff;        /* 9600 baud */
> +     p_uart_port->dlm = (clock_divisor >> 8) & 0xff;
> +     p_uart_port->lcr = LCR_8N1;     /* 8 data, 1 stop, no parity */
> +     /* Clear & enable FIFOs */
> +     p_uart_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR;
> +     return;
> +}
> +
> +void serial_puts(const char *s)
> +{
> +     while (*s) {
> +             serial_putc(*s++);
> +     }
> +}
> +
> +#ifdef CONFIG_CMD_KGDB
> +void kgdb_serial_init(void)
> +{
> +}
> +
> +void putDebugChar(int c)
> +{
> +     serial_putc(c);
> +}
> +
> +void putDebugStr(const char *str)
> +{
> +     serial_puts(str);
> +}
> +
> +int getDebugChar(void)
> +{
> +     return serial_getc();
> +}
> +
> +void kgdb_interruptible(int yes)
> +{
> +     return;
> +}
> +#endif /* CONFIG_CMD_KGDB */
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 1350f3e..7ffa47d 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -28,6 +28,7 @@ LIB := $(obj)libspi.a
>  COBJS-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>  COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>  COBJS-$(CONFIG_BFIN_SPI) += bfin_spi.o
> +COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>  COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
>  COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
>  COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
> diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
> new file mode 100644
> index 0000000..f0bc3a7
> --- /dev/null
> +++ b/drivers/spi/kirkwood_spi.c
> @@ -0,0 +1,199 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.com>
> + *
> + * Derived from drivers/spi/mpc8xxx_spi.c
> + *
> + * 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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <spi.h>
> +
> +/* SPI Registers on kirkwood SOC */
> +#define KW_REG_SPI_CTRL              (0x10600)
> +#define KW_REG_SPI_CONFIG    (0x10604)
> +#define KW_REG_SPI_DATA_OUT  (0x10608)
> +#define KW_REG_SPI_DATA_IN   (0x1060c)
> +#define KW_REG_SPI_IRQ_CAUSE (0x10610)
> +#define KW_REG_SPI_IRQ_MASK  (0x10614)
> +
> +#define KW_SPI_TIMEOUT               10000
> +
> +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> +                               unsigned int max_hz, unsigned
> int mode)
> +{
> +     struct spi_slave *slave;
> +     u32 data;
> +
> +     if (!spi_cs_is_valid(bus, cs))
> +             return NULL;
> +
> +     slave = malloc(sizeof(struct spi_slave));
> +     if (!slave)
> +             return NULL;
> +
> +     slave->bus = bus;
> +     slave->cs = cs;
> +
> +     KW_REG_WRITE(KW_REG_SPI_CTRL, 0x00000002);
> +     /* program spi clock prescaller using max_hz */
> +     data = ((CONFIG_SYS_TCLK / 2) / max_hz) & 0x0000000f;
> +     debug("data = 0x%08x \n", data);
> +     KW_REG_WRITE(KW_REG_SPI_CONFIG, 0x00000210 | data);
> +     KW_REG_WRITE(KW_REG_SPI_IRQ_CAUSE, 0x00000001);
> +     KW_REG_WRITE(KW_REG_SPI_IRQ_MASK, 0x00000000);
> +
> +     /* program mpp registers to select  SPI_CSn */
> +     if (cs)
> +             KW_REG_WRITE(KW_REG_MPP_CONTROL0,
> +                          ((KW_REG_READ(KW_REG_MPP_CONTROL0)
> & 0x0fffffff) |
> +                           0x20000000));
> +     else
> +             KW_REG_WRITE(KW_REG_MPP_CONTROL0,
> +                          ((KW_REG_READ(KW_REG_MPP_CONTROL0)
> & 0xfffffff0) |
> +                           0x00000002));
> +
> +     return slave;
> +}
> +
> +void spi_free_slave(struct spi_slave *slave)
> +{
> +     free(slave);
> +}
> +
> +int spi_claim_bus(struct spi_slave *slave)
> +{
> +     return 0;
> +}
> +
> +void spi_release_bus(struct spi_slave *slave)
> +{
> +}
> +
> +#ifndef CONFIG_SPI_CS_IS_VALID
> +/*
> + * you can define this function board specific
> + * define above CONFIG in board specific config file and
> + * provide the function in board specific src file
> + */
> +int spi_cs_is_valid(unsigned int bus, unsigned int cs)
> +{
> +     return (bus == 0 && (cs == 0 || cs == 1));
> +}
> +#endif
> +
> +void spi_cs_activate(struct spi_slave *slave)
> +{
> +     KW_REG_BITS_SET(KW_REG_SPI_CTRL, BIT0);
> +}
> +
> +void spi_cs_deactivate(struct spi_slave *slave)
> +{
> +     KW_REG_BITS_RESET(KW_REG_SPI_CTRL, BIT0);
> +}
> +
> +int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> const void *dout,
> +          void *din, unsigned long flags)
> +{
> +     unsigned int tmpdout, tmpdin;
> +     int tm, isRead = 0;
> +
> +     debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
> +                 slave->bus, slave->cs, dout, din, bitlen);
> +
> +     if (flags & SPI_XFER_BEGIN)
> +             spi_cs_activate(slave);
> +
> +     /*
> +      * handle data in 8-bit chunks
> +      * TBD: 2byte xfer mode to be enabled
> +      */
> +     while (bitlen > 4) {
> +             debug("loopstart bitlen %d\n", bitlen);
> +             tmpdout = 0;
> +             if (1) {        //bitlen <= 8) {
> +                     /*1 byte xfer mode */
> +                     KW_REG_BITS_RESET(KW_REG_SPI_CONFIG, BIT5);
> +                     /* Shift data so it's msb-justified */
> +                     if (dout) {
> +                             tmpdout = *(u32 *) dout & 0x0ff;
> +                     }
> +             } else {
> +                     /*2 byte xfer mode */
> +                     KW_REG_BITS_SET(KW_REG_SPI_CONFIG, BIT5);
> +                     /* Shift data so it's msb-justified */
> +                     if (dout) {
> +                             tmpdout = *(u32 *) dout & 0x0ffff;
> +                     }
> +             }
> +
> +             KW_REG_WRITE(KW_REG_SPI_IRQ_CAUSE, 0x0);
> /* clear bit */
> +             KW_REG_WRITE(KW_REG_SPI_DATA_OUT, tmpdout);
> /* Write the data out */
> +             debug("*** spi_xfer: ... %08x written, bitlen %d\n",
> +                         tmpdout, bitlen);
> +
> +             /*
> +              * Wait for SPI transmit to get out
> +              * or time out (1 second = 1000 ms)
> +              * The NE event must be read and cleared first
> +              */
> +             for (tm = 0, isRead = 0; tm < KW_SPI_TIMEOUT; ++tm) {
> +                     if (KW_REG_READ(KW_REG_SPI_IRQ_CAUSE)) {
> +                             isRead = 1;
> +                             tmpdin =
> KW_REG_READ(KW_REG_SPI_DATA_IN);
> +                             debug
> +                                 ("*** spi_xfer: din %08X
> ... %08x read\n",
> +                                  din, tmpdin);
> +
> +                             if (1) {        //bitlen <= 8) {
> +                                     if (din) {
> +                                             *((u8 *) din) =
> (u8) tmpdin;
> +                                             din += 1;
> +                                     }
> +                                     if (dout)
> +                                             dout += 1;
> +                                     bitlen -= 8;
> +                             } else {
> +                                     if (din) {
> +                                             *((u16 *) din)
> = (u16) tmpdin;
> +                                             din += 1;
> +                                     }
> +                                     if (dout)
> +                                             dout += 1;
> +                                     bitlen -= 16;
> +                             }
> +                     }
> +                     if (isRead)
> +                             break;
> +             }
> +             if (tm >= KW_SPI_TIMEOUT)
> +                     printf
> +                         ("*** spi_xfer: Time out during SPI
> transfer\n");
> +
> +             debug("loopend bitlen %d\n", bitlen);
> +     }
> +
> +     if (flags & SPI_XFER_END)
> +             spi_cs_deactivate(slave);
> +
> +     return 0;
> +}
> diff --git a/include/asm-arm/arch-kirkwood/kirkwood.h
> b/include/asm-arm/arch-kirkwood/kirkwood.h
> new file mode 100644
> index 0000000..67d94dc
> --- /dev/null
> +++ b/include/asm-arm/arch-kirkwood/kirkwood.h
> @@ -0,0 +1,142 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.com>
> + *
> + * Header file for the Marvell's Feroceon CPU core.
> + *
> + * 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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#ifndef _ASM_ARCH_KIRKWOOD_H
> +#define _ASM_ARCH_KIRKWOOD_H
> +
> +#ifndef __ASSEMBLY__
> +#include <asm-arm/types.h>
> +#endif /* __ASSEMBLY__ */
> +#include <../board/Marvell/include/core.h>
> +
> +#if defined (CONFIG_FEROCEON_88FR131) || defined
> (CONFIG_SHEEVA_88SV131)
> +#if defined (CONFIG_KIRKWOOD)
> +#include <../cpu/arm926ejs/kirkwood/kwcore.h>
> +
> +/* SOC specific definations */
> +#define INTREG_BASE                  0xd0000000
> +#define KW_REGISTER(x)                       (KW_REGS_PHY_BASE | x)
> +#define KW_OFFSET_REG                        (INTREG_BASE | 0x20080)
> +
> +#define KW_UART0_BASE                        (0x12000)
> /* UArt 0 */
> +#define KW_UART1_BASE                        (0x13000)
> /* UArt 1 */
> +
> +/* Controler environment registers offsets */
> +#define KW_REG_MPP_CONTROL0          (0x10000)
> +#define KW_REG_MPP_CONTROL1          (0x10004)
> +#define KW_REG_MPP_CONTROL2          (0x10008)
> +#define KW_REG_MPP_CONTROL3          (0x1000C)
> +#define KW_REG_MPP_CONTROL4          (0x10010)
> +#define KW_REG_MPP_CONTROL5          (0x10014)
> +#define KW_REG_MPP_CONTROL6          (0x10018)
> +#define KW_REG_MPP_SMPL_AT_RST               (0x10030)
> +#define KW_REG_CHIP_BOND             (0x10034)
> +#define KW_REG_MPP_OUT_DRV_REG               (0x100E0)
> +
> +#define KW_REG_GPP0_DATA_OUT         (0x10100)
> +#define KW_REG_GPP0_DATA_OUT_EN              (0x10104)
> +#define KW_REG_GPP0_BLINK_EN         (0x10108)
> +#define KW_REG_GPP0_DATA_IN_POL              (0x1010C)
> +#define KW_REG_GPP0_DATA_IN          (0x10110)
> +#define KW_REG_GPP0_INT_CAUSE                (0x10114)
> +#define KW_REG_GPP0_INT_MASK         (0x10118)
> +#define KW_REG_GPP0_INT_LVL          (0x1011c)
> +
> +#define KW_REG_GPP1_DATA_OUT         (0x10140)
> +#define KW_REG_GPP1_DATA_OUT_EN              (0x10144)
> +#define KW_REG_GPP1_BLINK_EN         (0x10148)
> +#define KW_REG_GPP1_DATA_IN_POL              (0x1014C)
> +#define KW_REG_GPP1_DATA_IN          (0x10150)
> +#define KW_REG_GPP1_INT_CAUSE                (0x10154)
> +#define KW_REG_GPP1_INT_MASK         (0x10158)
> +#define KW_REG_GPP1_INT_LVL          (0x1015c)
> +
> +#define KW_REG_NAND_READ_PARAM               (0x10418)
> +#define KW_REG_NAND_WRITE_PARAM              (0x1041c)
> +#define KW_REG_NAND_CTRL             (0x10470)
> +
> +#define KW_REG_WIN_CTRL(x)           (0x20000+(x*0x10))
> +#define KW_REG_WIN_BASE(x)           (0x20004+(x*0x10))
> +#define KW_REG_WIN_REMAP_LOW(x)              (0x20008+(x*0x10))
> +#define KW_REG_WIN_REMAP_HIGH(x)     (0x2000c+(x*0x10))
> +
> +#define KW_REG_CPU_CONFIG            (0x20100)
> +#define KW_REG_CPU_CTRL_STAT         (0x20104)
> +#define KW_REG_CPU_RSTOUTN_MASK              (0x20108)
> +#define KW_REG_CPU_SYS_SOFT_RST              (0x2010C)
> +#define KW_REG_CPU_AHB_MBUS_CAUSE_INT        (0x20110)
> +#define KW_REG_CPU_AHB_MBUS_MASK_INT (0x20114)
> +#define KW_REG_CPU_FTDLL_CONFIG              (0x20120)
> +#define KW_REG_CPU_L2_CONFIG         (0x20128)
> +#define KW_REG_L2_RAM_TIMING0                (0x20134)
> +#define KW_REG_L2_RAM_TIMING1                (0x20138)
> +
> +#define KW_REG_TMR_CTRL                      (0x20300)
> +#define KW_REG_TMR_RELOAD            (0x20310)
> +#define KW_REG_TMR_VAL                       (0x20314)
> +
> +/*
> + * Macros
> + * CPU architecture dependent I/O read/write
> + */
> +#define KW_REG_WRITE(addr, data)     \
> +    ((*((volatile unsigned int*)(KW_REGISTER(addr)))) \
> +              = ((unsigned int)WORD_SWAP((data))))
> +
> +#define KW_REG_READ(addr)            \
> +    WORD_SWAP(((*((volatile unsigned int*)(KW_REGISTER(addr))))))
> +
> +#define KW_REG_BITS_SET(adr, bits)   (KW_REG_WRITE(adr,
> KW_REG_READ(adr)\
> +                                     | ((unsigned
> int)WORD_SWAP(bits))))
> +
> +#define KW_REG_BITS_RESET(adr, bits) (KW_REG_WRITE(adr,
> KW_REG_READ(adr)\
> +                                     & ~((unsigned
> int)WORD_SWAP(bits))))
> +
> +#define KW_REG_READ_ASM(toReg, tmpReg, regOffs)      \
> +        ldr     tmpReg, =KW_REGISTER(regOffs);       \
> +        ldr     toReg, [tmpReg];                     \
> +                             /*WORD_SWAP_ASM(toReg,tmpReg) */
> +
> +#define KW_REG_WRITE_ASM(fromReg, tmpReg, regOffs)   \
> +        /*WORD_SWAP_ASM(fromReg,tmpReg)*/;           \
> +        ldr     tmpReg, =KW_REGISTER(regOffs);               \
> +        str     fromReg, [tmpReg]
> +
> +/*
> + * Error codes
> + */
> +#define KW_ERROR     (-1)
> +#define KW_OK                (0)
> +
> +#if defined (CONFIG_KW88F6281)
> +#include "kw88f6281.h"
> +#endif /* CONFIG_KW88F6281 */
> +#if defined (CONFIG_KW88F6192)
> +#include "kw88f6192.h"
> +#endif /* CONFIG_KW88F6192 */
> +#endif /* CONFIG_KIRKWOOD */
> +#endif /* CONFIG_FEROCEON_88FR131 */
> +#endif /* _ASM_ARCH_KIRKWOOD_H */
> diff --git a/include/asm-arm/arch-kirkwood/kw88f6192.h
> b/include/asm-arm/arch-kirkwood/kw88f6192.h
> new file mode 100644
> index 0000000..000fc16
> --- /dev/null
> +++ b/include/asm-arm/arch-kirkwood/kw88f6192.h
> @@ -0,0 +1,37 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.com>
> + *
> + * Header file for Feroceon CPU core 88FR131 Based KW88F6192 SOC.
> + *
> + * 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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#ifndef _CONFIG_KW88F6192_H
> +#define _CONFIG_KW88F6192_H
> +
> +/* SOC specific definations */
> +#define KW88F6192_REGS_PHYS_BASE     0xf1000000
> +#define KW_REGS_PHY_BASE             KW88F6192_REGS_PHYS_BASE
> +
> +/* TCLK Core Clock defination */
> +#define CONFIG_SYS_TCLK         166000000 /* 166MHz */
> +
> +#endif /* _CONFIG_KW88F6192_H */
> diff --git a/include/asm-arm/arch-kirkwood/kw88f6281.h
> b/include/asm-arm/arch-kirkwood/kw88f6281.h
> new file mode 100644
> index 0000000..45098fb
> --- /dev/null
> +++ b/include/asm-arm/arch-kirkwood/kw88f6281.h
> @@ -0,0 +1,43 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.com>
> + *
> + * Header file for Feroceon CPU core 88FR131 Based KW88F6281 SOC.
> + *
> + * 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., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#ifndef _ASM_ARCH_KW88F6281_H
> +#define _ASM_ARCH_KW88F6281_H
> +
> +/* SOC specific definations */
> +#define KW88F6281_REGS_PHYS_BASE     0xf1000000
> +#define KW_REGS_PHY_BASE             KW88F6281_REGS_PHYS_BASE
> +
> +/* TCLK Core Clock defination*/
> +#if defined (CONFIG_KW88F6281_Z0)
> +#define CONFIG_SYS_TCLK         166000000 /* 166MHz */
> +#elif defined (CONFIG_KW88F6281_A0)
> +#define CONFIG_SYS_TCLK         200000000 /* 200MHz */
> +#else
> +#error       "CONFIG_SYS_TCLK not defined"
> +#endif
> +
> +#endif /* _ASM_ARCH_KW88F6281_H */
> diff --git a/include/asm-arm/config.h b/include/asm-arm/config.h
> index 049c44e..5d52f15 100644
> --- a/include/asm-arm/config.h
> +++ b/include/asm-arm/config.h
> @@ -21,4 +21,8 @@
>  #ifndef _ASM_CONFIG_H_
>  #define _ASM_CONFIG_H_
>
> +#if defined (CONFIG_KIRKWOOD)
> +#include <asm-arm/arch-kirkwood/kirkwood.h>
> +#endif /* CONFIG_KIRKWOOD */
> +
>  #endif
> --
> 1.5.3.3
>
>


More information about the U-Boot mailing list