
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@marvell.com Michael Blostein <michaelbl@marvell.com
Reviewed-by: Ronen Shitrit rshitrit@marvell.com Signed-off-by: Prafulla Wadaskar prafulla@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@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@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@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@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@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@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@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@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@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@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@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@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