[U-Boot] [PATCH] Marvell Feroceon-FR131/Sheeva-88SV131 cpu core support

This is ARM v5TE-compliant processor core with MMU and L1/L2 Cache
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com --- cpu/arm926ejs/start.S | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index ed4932a..08ec955 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -214,10 +214,15 @@ cpu_init_crit: * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 +#if defined (CONFIG_FEROCEON_88FR131) || defined (CONFIG_SHEEVA_88SV131) + bic r0, r0, #0x00000007 /* clear bits 2:0 (CAM) */ + orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ +#else bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ +#endif mcr p15, 0, r0, c1, c0, 0
/*

Dear Prafulla Wadaskar,
In message 1238798370-9245-1-git-send-email-prafulla@marvell.com you wrote:
This is ARM v5TE-compliant processor core with MMU and L1/L2 Cache
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com
cpu/arm926ejs/start.S | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index ed4932a..08ec955 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -214,10 +214,15 @@ cpu_init_crit: * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 +#if defined (CONFIG_FEROCEON_88FR131) || defined (CONFIG_SHEEVA_88SV131)
- bic r0, r0, #0x00000007 /* clear bits 2:0 (CAM) */
- orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
+#else bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ +#endif mcr p15, 0, r0, c1, c0, 0
Why is this special case needed?
Cannot you enable the IC, too?
Best regards,
Wolfgang Denk

From: prafulla_wadaskar prafulla@marvell.com
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) Doimage utility needed to create binaries with bootROM header 2) get_random_hex() fucntion 3) SPI port controller driver 4) PCI Express port initialization
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com --- board/Marvell/common/kw_lowlevel_init.S | 45 + board/Marvell/include/core.h | 4 + cpu/arm926ejs/kirkwood/Makefile | 52 + cpu/arm926ejs/kirkwood/bin_dep.sh | 50 + cpu/arm926ejs/kirkwood/config.mk | 25 + cpu/arm926ejs/kirkwood/doimage/Makefile | 112 ++ cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h | 88 ++ cpu/arm926ejs/kirkwood/doimage/doimage | Bin 0 -> 17712 bytes cpu/arm926ejs/kirkwood/doimage/doimage.c | 1341 ++++++++++++++++++++++++ cpu/arm926ejs/kirkwood/dram.c | 49 + cpu/arm926ejs/kirkwood/kw88f6192.h | 34 + cpu/arm926ejs/kirkwood/kw88f6281.h | 34 + cpu/arm926ejs/kirkwood/kwcore.c | 262 +++++ cpu/arm926ejs/kirkwood/kwcore.h | 141 +++ cpu/arm926ejs/kirkwood/serial.c | 187 ++++ cpu/arm926ejs/kirkwood/soc_init.S | 156 +++ cpu/arm926ejs/kirkwood/spi.c | 213 ++++ cpu/arm926ejs/kirkwood/timer.c | 165 +++ include/configs/kirkwood.h | 46 + 19 files changed, 3004 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/common/kw_lowlevel_init.S create mode 100644 cpu/arm926ejs/kirkwood/Makefile create mode 100755 cpu/arm926ejs/kirkwood/bin_dep.sh create mode 100644 cpu/arm926ejs/kirkwood/config.mk create mode 100644 cpu/arm926ejs/kirkwood/doimage/Makefile create mode 100644 cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h create mode 100755 cpu/arm926ejs/kirkwood/doimage/doimage create mode 100644 cpu/arm926ejs/kirkwood/doimage/doimage.c create mode 100644 cpu/arm926ejs/kirkwood/dram.c create mode 100644 cpu/arm926ejs/kirkwood/kw88f6192.h create mode 100644 cpu/arm926ejs/kirkwood/kw88f6281.h create mode 100644 cpu/arm926ejs/kirkwood/kwcore.c create mode 100644 cpu/arm926ejs/kirkwood/kwcore.h create mode 100644 cpu/arm926ejs/kirkwood/serial.c create mode 100644 cpu/arm926ejs/kirkwood/soc_init.S create mode 100644 cpu/arm926ejs/kirkwood/spi.c create mode 100644 cpu/arm926ejs/kirkwood/timer.c create mode 100644 include/configs/kirkwood.h
diff --git a/board/Marvell/common/kw_lowlevel_init.S b/board/Marvell/common/kw_lowlevel_init.S new file mode 100644 index 0000000..61453a7 --- /dev/null +++ b/board/Marvell/common/kw_lowlevel_init.S @@ -0,0 +1,45 @@ +/* + * (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 + */ + +#define KW_ASMLANGUAGE +#include <config.h> + +.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 + + /* 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/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..41ac8d7 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/Makefile @@ -0,0 +1,52 @@ +# +# (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 = timer.o +COBJS-y += serial.o +COBJS-y += kwcore.o +COBJS-y += dram.o +COBJS-$(CONFIG_KIRKWOOD_SPI) += spi.o + +SOBJS = soc_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/bin_dep.sh b/cpu/arm926ejs/kirkwood/bin_dep.sh new file mode 100755 index 0000000..1b36e91 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/bin_dep.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# (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 +# + +# Kirkwood SOC has BootROM +# On power on Reset BootROM will be executed if enabled +# BootROM looks for valid BootROM header and header extensions (optional) +# on the configured boot media to achieve sucessfull "boot from" operation +# +# This script builds/cleans doimage utility + +TOP_DIR=`pwd` +CUR_DIR=$2 +BIN_FILE=$TOP_DIR/$1 + +if [ "clean" == "$1" ]; then + # erase created doimage utility + rm -f $CUR_DIR/doimage/doimage + exit 0 +fi + +if [ ! -f $BIN_FILE ]; then + echo Error.. could not find $BIN_FILE + exit 1 +else + make -C $CUR_DIR/doimage + exit 0 +fi + 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/doimage/Makefile b/cpu/arm926ejs/kirkwood/doimage/Makefile new file mode 100644 index 0000000..219ae1e --- /dev/null +++ b/cpu/arm926ejs/kirkwood/doimage/Makefile @@ -0,0 +1,112 @@ +# +# (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 +# + +# Kirkwood SOC has BootROM +# On power on Reset BootROM will be executed if enabled +# BootROM looks for valid BootROM header and header extensions (optional) +# on the configured boot media to achieve sucessfull "boot from" operation +# +# This Makefile builds/cleans doimage utility + +BIN_FILES = doimage$(SFX) + +OBJ_LINKS = +OBJ_FILES = doimage.o + +LIBFDT_OBJ_FILES = + +#------------------------------------------------------------------------- + +HOSTARCH := $(shell uname -m | \ + sed -e s/i.86/i386/ \ + -e s/sun4u/sparc64/ \ + -e s/arm.*/arm/ \ + -e s/sa110/arm/ \ + -e s/powerpc/ppc/ \ + -e s/Power\ Macintosh/ppc/ \ + -e s/macppc/ppc/) + +HOSTOS := $(shell uname -s | tr A-Z a-z | \ + sed -e 's/(cygwin).*/cygwin/') + +TOOLSUBDIRS = + +# +# Everyone else +# +HOST_CFLAGS = -Wall -pedantic +HOST_LDFLAGS = +HOST_ENVIRO_CFLAGS = + +# +# Cygwin needs .exe files :-( +# +ifeq ($(HOSTOS),cygwin) +SFX = .exe +HOST_CFLAGS += -ansi +else +SFX = +endif + +# +# Include this after HOSTOS HOSTARCH check +# so that we can act intelligently. +# +include $(TOPDIR)/config.mk + +# now $(obj) is defined +SRCS := $(addprefix $(obj),$(OBJ_LINKS:.o=.c)) $(OBJ_FILES:.o=.c) +BINS := $(addprefix $(obj),$(BIN_FILES)) + +# +# Use native tools and options +# +CPPFLAGS = -idirafter $(SRCTREE)/include \ + -idirafter $(OBJTREE)/include2 \ + -idirafter $(OBJTREE)/include \ + -DTEXT_BASE=$(TEXT_BASE) -DUSE_HOSTCC +CFLAGS = $(HOST_CFLAGS) $(CPPFLAGS) -O + +# No -pedantic switch to avoid libfdt compilation warnings +FIT_CFLAGS = -Wall $(CPPFLAGS) -O + +AFLAGS = -D__ASSEMBLY__ $(CPPFLAGS) +CC = $(HOSTCC) +STRIP = $(HOSTSTRIP) +MAKEDEPEND = makedepend + +all: $(obj).depend $(BINS) + +$(obj)doimage$(SFX): $(obj)doimage.o + $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ + $(STRIP) $@ + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h b/cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h new file mode 100644 index 0000000..8782206 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h @@ -0,0 +1,88 @@ +/* + * (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 _INC_BOOTSTRAP__DEF_H +#define _INC_BOOTSTRAP__DEF_H + +#ifndef MV_ASMLANGUAGE +/* typedefs */ + +typedef char s8; +typedef unsigned char u8; + +typedef int s32; +typedef unsigned int u32; + +typedef short s16; +typedef unsigned short u16; + +typedef long s64; +typedef unsigned long u64; + +typedef struct BHR_t { + u8 blockID; /*0 */ + u8 nandEccMode; /*1 */ + u16 nandPageSize; /*2-3 */ + u32 blockSize; /*4-7 */ + u32 rsvd1; /*8-11 */ + u32 sourceAddr; /*12-15 */ + u32 destinationAddr; /*16-19 */ + u32 executionAddr; /*20-23 */ + u8 sataPioMode; /*24 */ + u8 rsvd3; /*25 */ + u16 ddrInitDelay; /*26-27 */ + u16 rsvd2; /*28-29 */ + u8 ext; /*30 */ + u8 checkSum; /*31 */ +} BHR_t, *pBHR_t; + +typedef struct ExtBHR_t { + u32 dramRegsOffs; /*0-3 */ + u32 rsrvd1; /*4-7 */ + u32 rsrvd2; /*8-11 */ + u32 rsrvd3; /*12-15 */ + u32 rsrvd4; /*16-19 */ + u32 rsrvd5; /*20-23 */ + u32 rsrvd6; /*24-27 */ + u16 rsrvd7; /*28-29 */ + u8 rsrvd8; /*30 */ + u8 checkSum; /*31 */ +} ExtBHR_t, *pExtBHR_t; + +#define BOOTROM_SIZE (12 * 1024) +#define HEADER_SIZE 512 +#define BHR_HDR_SIZE 0x20 +#define EXT_HEADER_SIZE (HEADER_SIZE - BHR_HDR_SIZE) + +/* Boot Type - block ID */ +#define IBR_HDR_I2C_ID 0x4D +#define IBR_HDR_SPI_ID 0x5A +#define IBR_HDR_NAND_ID 0x8B +#define IBR_HDR_SATA_ID 0x78 +#define IBR_HDR_PEX_ID 0x9C +#define IBR_HDR_UART_ID 0x69 +#define IBR_DEF_ATTRIB 0x00 + +#endif /* MV_ASMLANGUAGE */ +#endif /* _INC_BOOTSTRAP_H */ diff --git a/cpu/arm926ejs/kirkwood/doimage/doimage b/cpu/arm926ejs/kirkwood/doimage/doimage new file mode 100755 index 0000000000000000000000000000000000000000..9fee11740454ff880c081a64be0d692b1da4c19a GIT binary patch literal 17712 zcmcIse|%KcmA{h=Fd#ayQbf(l!zLA42nnP#P^kP$gccORAQmtT$%Gl3WMbxx1Q%-J zWR$m$X;~#*yJ8DU`*B;_;#LAEQxjlGw01XGYjJg3RMZ)RHtSDnquKBG-uEVNNWk`w zeSB{2Irp4<?m6e4d+vR2-s8^FC1oy`OW0SI$QH!5-{bZaqwb!oD8)h(9x+kmiYvr$ zG?7-^1RfOG0iA}S&5e>x8t~#~&`~Y{&O#bxv&f5mQR?Ri!NUF`N6}^5Z$U#@hYmYY zI4<c~s9M0^0vbyfa2C=z2FoJwFT&U?3xTuPv}LdBReiIC=sV>0u;hZqV$*K`9q6FT zmOr&7xPEF))s&iGU8J!f94eTm`a(5n+qKt~%f8f;eMX{C_81iUhV+Mi@$Rxm`Yxz` zCi&2W<y(JphjDNBc+xIMp?~O$rY~n*Mf?gBUX%V|TkfOZe679YT{Cw>xsStTTvILV z4%DARxz@sc7EZbLr2&{}A)J2l@3e5c{}KydfSU9tEWFL)|EYz)Y0;mx@KY9jgM}w8 ze4T|~jhgc6EWFIZ3oLw^g+FZJ)RX)H3lCZN0~TIk$$!Yg^DO%97QWG<f6Kx@wCIds zUf;9m_bOEU2sOtuE!>vZV&MoqN&l6F=UezB3;&CSuOR+kZV%`FVsV+A+xz$0xL0gJ z`^o>b@yo<K;HMn8sHoUb8>*`a>%IoPqCz0-Dj9AwM8)Fk(OMO(tB8dCRl?sG)J1iu z-d`u`BYK#BDg(X-Az4Iit*>6x`fI~}oh_jVc*()G%KA;By0Rt|_Jh=*haxqi)>l&# zswAhsp+VF}>e#(HT<NQ;hC<bi&;|lFHUxD)<TM29bhJaC4StA(kjmP6@KIMw@mgQ7 zPE<Ge{o>jsi{~$>m{w4fh6-Ua)-zWM|JwhuC8Yk^ZJD)8a&WC=F(t@CSr-R`7jl&y zx7u<fo+Vx)5!Vv<cQ_Ur{XPtfp8g*84<KNkhFvbi8sH-k59?S%tt!^w53t5W*09Fn ztY?kIt+O5>L?dgD5Sv+J!8frUg&f8D0wK1t9xcQ+*3fV}>x+cg!P+at{j6cgPSzI- zv5Pf=a1U!F&qr7zfjr9k^Fr)pJywXvSzju|0oLP$IK=ugA<B){qo+N|<1i(;3U(wb zza+%dM@0WuZUjev{wn;XKl<}&v0PcHll{2zX?cLORJX+GfdE~cYL_@Y5x__ywO8Ww zNI)aLOXBoQU?TDD5~qg(oaa=N#ObL(3GsS~(_?|T#Meojo(n7@zD(luU|<>Xxe})* z1FMJ^N}L`ItRt>ToSqHPpj3{;>ES><aUpSfI?zbG_fs_F)8m0A;wL3e&j+>=@0K`c zAh4ZyyTmyYf%}Q?l{jZ4u#5OEiF0NGj}YH3an4X+FYzXcbEX0Zh}TP;GZttkz7BZN z+qW36L{IfDyK#A-`<I}c#Ge~h2L8Cs?MeO;4DWB>j=5bCJ?&1Sk67J&WIOVwd0!uF zi9M$eOMU}Pt5!dKWV^g9-ljPo1h|M?b6_(z%qfld({Uy%zN&w>8|^cX+&(`3_!lWJ z+U|OoP5onHWU|N`lgEZpfGc{`y?X7Dxc)^EKg2X{#o6vA@W$Hp&(SUcU}UE|k8S<k zP=q>|OGlgK9&g*)9B*5e>qzvlE1Gge-t)E{fjlsnOFd@!XtOjY+ZF9_N8fVCp1bpX zNx5m|3c2w-NzqS@$Ddy#sD-!fuG84NjlWFlFnWJ?a-<ab@kNn050cO5l6@X=>BEmF zi%#@p9Zzz|k3EsoP{VNlQ?$d?{1@)Dk>^+6QXvOgxuW^B8%x|=JKBuo#A9dv+TU-u z^OBA5tXb+YIzBoc{d9!)Zb~*UDSD>))qXirN76IBrIp;~3U|?A)$DBa4AnS#sK%V3 z8pjOPIBuxMTt}nPF@2j<DtbhVzT=_h_mnY4KGesX*+pIXQu${(-trj7r*D(SMvu6o z@3<nb7+oKAHy@=dR^K8$gG_??L^c!2KA73LFweaU`xx44{vBbt6|o2S$7o8vtl$LU zZUw(U_^5*aO!$C;J&yr?RKXJn?^3WFX9ve|=gnffC4W1|+N^j^5Uy8n&aVJhDR>d# zRSIq)yhOo|5}vEzlZ1;EJmzu06BWFMaIS)P5YAEX3Bqm#=k5c{sfKO=!lxDdIN_5D zP7;1z!6j{gyDWafhZMY*@LmPKPk4`l3-<%QU%_h#Z&UDA!c7XEPoL-(58;4<50Gb# zf=?1&reN&=;DrjVCtRZ7M+r|>@J7nf6r5!H7zK|x2-u_G*@XK(mbUAJdlmdB;Zq7u z5<a2eaZdn#*3sUs;Du~|+|mAsg151Kr=xwlf~A}mM|-1!50Jmc(Y{W>|4dtM1pM@o z_>w#~l4<{KeMm7#BsVml-ipoKbQv)Qm3gzfv-C8=T6C7mY}y&)9wQrKvn?oIdfJE; z1BsU=jaUhREl2xgqC4mT>w7<oZ`t#h=e?gr6O`%lw(wlq8QTd&N!pW!9!W!tdqw4H zP|%??^lTd98dB8f)6j`D^fDkO!_L^rblaIU)R%_DCrV1{w>YvSzl3(gFFPhT{{?Qy z_O^*=a>4Ae-g_PZgSV}{KQC5;>>B;KG)Y+|?z}kpXB7&v>pXNt$}p!J`)KQjF>3A7 zFHSz=V9F&^TvAfkK=vSs4?39td<M=fKSiP0NHU%rXlUG+=Vlhp2F*BZmY!-V5g4P| z(d__8YV<5nmN+Os1VxRWWwde{QcvRSHb{rd99_PB9v$xdC_{%=RlG@O6sL7?Lx(O0 z<?^%+Zljd}koxLSI<z{vyoqtn<%hq1n4!Zhj&6I=?ISr0yxoKv^BlzcsCz2|p;=A` zSvq437V4jR80a9sxE%dgoJXe(nL0g#Ik)30cR(jB7U=YI2eF_1oH~J}Gsdu$I(ey+ zTvQA_-O=$FI$D+@Mj-Vj2l3xPv}^=1^)wdzAj__H@NWYDxx5|!Aj8|em`mHT`RJyi z&I1Kra8M?KqN2`Yv~r=RN{7<nVMmt_Fpg6P?tymXkIdAe#?kH9ASoT@LWkuJ${tXZ z4s(rGCXrMJ?g9q+VZ5WuZRgP;_I`#Rl9*N753|xbXwcz59TY9CgJ!fceWm6MrNaY` zE^lL;bNRuQsY8{cTN_ALJZLf=u5}Q90HPHSAR4Vqm8oAL!UlQcVn?sa^Jud1y$o;s zH|E>+#^eD_FajKsa1gx%nt*7uGLfey4W-FFj$SWfv~&67?RPUYS?1{W5V~1Df!CqQ zbO$j8qU941jaF_XsUIQe2KnR@OrmYv_2|Xq{52zS03B51<v{ca2h*3xBvVXI&$2<{ ze&OI0mbh#qb_n8{5^~$ybaB#fFueo|m8MNl&%7i)-(_Ss-Qg16*g`Dg%mKbLO70y^ zB~$d@o6;zwbsSQj8E4`%;<@-6{WvRfjkRziGj^ZE?U%7IZ#4HCgooha7BeDX^BEp6 ze)GTm{mC<!INJ%|fI^mEIm2IxCOC~AeX;^_^e-qt(=S&5m*#$lfRPZO#>ZLVR=D4k zXN9MB;M{T$TZ8B`j=lF2@4p=O-rL?8<DnRB;vgOph?2wJmc;`-esInn$eiNfwN{Ty z*(1R{+DL4}UvJx`-nL;sMCX}@BiDG_ZgK(rkwOcBW&z!$&<Q|sIvBPasM3WBRv&b^ zW<nL-h?y}Z68Ck(9#Wmk%(!a1fr1}ajYZzJ8z^{>Lazc!!9Pw5#^FFfE*?ula+Q=! zm7n+tIBd5Vf5>zUxWqv`eUXkS9O&~i_Mt$y^6Wlv#z3DwAj<tuJjOme&<)WC=^MJ? z4=12Y_8GAHAUeX4^E0e|LN!jYtbS6VS6Wsd0;=3e<)sBP59<x)J|%T59FtHzW_#OK z(u==N%Uek=K9!cYl3r|2%cB7Y@4+9)yDB*sp=QVJy?;g^Pjxgjqam8$@^DA8qp$2X z<<Vh6*UT;i>~II;DlmHYCzv;@jV*sPV?0S2rO%u4IAfHb=!}hq6by>(n(^xK-t!hG zBTl40FW!Zt<N!}+jM;_}n))rcj+Gv5j3ypMlh7|P_Yp86-8~~ZOS?H$11T&rO7&!` zB@LiO$4>8UiAZrTy9TJK^=gEmGA?>DCwj(pS%34Jd=}H(iHC>6NKkoWOLuC9;{8?z zZ+pH5)?t!UnrZ7gc4myaHe6)NJ>DqqPJIB)%(xV{v^(`CFc@cMi2Jbl4a#diCI#*z zuPyMBnbP=%3ry(^Xw);(ltUV&-QN9j7q2$Tk9phT+)TGF{f|_O8e(V05Dtw8L@Qk# z{>_F^Xty+@D;y)Wb2w%|gwzV!Nm1wx?OLU+<=xQ)r!<QhPtL73b{l-Df?>Ef#?`D2 za&B+z*L2baMtm=Nm|?epCo=!&F}5Vl)uW9EA4j91<HSEYFM0elo>sK$>x|8LZZk%9 z-UmFXTEAheL8}x(-XE*hV)7crdC69V=aGweOyOfBK07ZNk+?Uu0GefN0Y%Wxu?6Hl zi7lY3XJ8dAK}TgucI3{p%vkL))+TN3FHs|YN$Q!9+GE^LAPP1qJ)qay68FX)!?2&J z$6SXVM*$~&?+hsRD>Nv@vLfXswp8ig1#Sbkuh`PeR;j|6yyP8n$jJQ99PapA1JcVm z+`DfNG%Q3zXN=PY&D9gRcw!+|ySZ~8pUaxrv376EeU>-L!^!(@s=xo?F6_9`GyVE) zY+1uWhOr5q&<nbH=>KJKywVU%H-TyQDQ?t2o`8(m*Xi!rb&+w%Z5>E`$!eu4he`g_ z$s7lB=feGcm}b!f!TXu;Mf8{}`f0W|#s|zQVza$1OTfdC$uJODFDDUphaWzwbdG%4 z+$a60D=q(k!P8nk#<ARa?4Qhs67kp)$frR($%DdOB>5X~8AlKUvv*S{En3B<HF={= z6(*aN?9EOOlq=aZBl$F7v$YYjn?DwXLVRb2T4>pkDN=tlVX$3{+;^aTdYJzO0)mtg zqr8QA{6$hIhJ|@KXc$c@Y7c8mZSo{fy$Ky-?U?Uad!)cxj@Deg?exOWFiProNXMO$ zo1LRFFht}k3g(Z8sNM6CdQHS8>~Dl@85KR_NMU}rD7V;@=o}d$kz5k2VTa)vVA}b` z7}m-{kz1pQMexp$1134(2#S3c-ggctDQ~}FQKEB5@5hAWsn1XY9)XOW3+;T@G7A=) zF;0q6+GVyr3r9s?%`sZH1JK>aN?&!UNy^gm6yVmcP=L@sr+^XqNCkKz?r3S3JDT8e zRp|L<t30>9nyp`K#w6J8p44r`c&1e+Ti4Pqv%IS__P(_qKRleR7hCE;d21q1FeF}r zg=T4&(Gh(m`w0g7q-Ts)_H%VZbH;BkruzeM8L=)jbI#brnc-Te|1Jg9I<0$+QJBzZ z;t)snwtNB(a$bqKG54{N+4m+&J7zvec~5}@zYxH&vJVorT<;kxX#@D}NTt459Fj?c zRLc7ov@wHx6$zM6u$x~MP|fJ-NRAtM7}ZHnK7QE}BM*1HGH&EE#wF2CS98CZjnn!t z+#mGprHuPt#|q6&@VwOgn&6gvL~h9#%9Ms<*4?`qb+q{N;GTIxpWq0;JZJdr13mRW z_+8K15|L;B9Zg2;C``7F1WS|=w4WlMJ7qZ+I9;Zpj+Y)K={K-%Yw2qy4iEb%z!=UM zD|4Hr&l+VOv$WeN!%rp88)Z3W=?SB3j9L1!Q8vyjJ!zEXMiUG<OvPn#UU;7dWS2FF zoELfXW?(mZ3Mv@KFd6wnPQyuRXeEprVU3)+_=Ckfvvj)7o|G(bz`K|i{DJ@nPeX50 z+8=G78y}N^BK`3=J0l!D2A<5))Lf2Hx@Ru*Gh1nE^sr`@?lI%i?s<S8G3LYYM~(R~ ze6KMdhCgo1hv5f|`7r#DF&~Dv8}oBzpi+!Fr6n~^pn-|l0>zXcO?lMYy724iR1vTa zSO{`8JeSIDE`2ID{<Z%8uSs#7`E(x0nE5BclX@1v@H!Y~Gc@>%GKKsr7<z6RhyiO# zamYzW*Zx<X<D?T@#yBfDP8G&UZ&)`;ghy;_Wpd%U^ZM`(NU{X1oK|m3G4)bei54c9 zzwIN^Ll{(TBL~=PQn%|}JJG?5f}WcSmQLB79CR>io^aBt_q_s%N0c0+yW`CGj^vdt z)LE28PG%Hb$p;u~^6@$;X{AW_;PxQ70AoevSZ)r)%oMlT2ZoDdxOnb3#@AthN=#}L z9+#=qIShwQZY&Qn6LVE9Wg=4B%yFt38-oC(Yc7+0c<Y{{2d!K8jTb1u6UpsCnkG^6 zw)_`VvF_x(Ej%#Fb&%pu>*hXs)Y~@P_T2RxPL9E;{}D#yS)&Ix`qMC8&+k<SDM0xw z`l?G`5MPjG9GUbxBR4O(nM!uzuGLC;^c_X*IcZxf-PbB-60yo<d;&D@{^8MMS>FBa zwkGA&Bu;C2KK?v4>B;i8Tmh|np36`mTb~!lInh$!uMh?W&Kf>Hb9iaCJn3Tin@N)` zCUkJy3arj>#SSn<d)(fZe}zFkFJve%f(m$S1@0J9fjxgZkNu=s3fQCjGRz-K70cYw zV|>&jw~|clK7@p5k0<h!3Y=KK?xABVD7aPn5UatLRw4BR+_tNL!`;nvJQ6YY4H0nb z(7}kELWD5j9zmahh?J*|Ya~O`Vz@^Nl}BoQcA7KJ22SDUB=c#D`CDLqVr6-GxzYR4 zTSjlknemej8?7EpchB6FFS+yLReA0c7Y4AhUQ86A)w@5&>haOlMr<;G7k|#bFFnW} zFaDgQ&KPAg-mKN&Z8<Z5Z1h@7!yEem=h&X{>E-cnh$wq`#9jm~^;7&YRfM+YL9!X= zUvJxGa@J?=<Ct5@j1&1ykl%4;ggqzKGGgd2M*R9e;!N@qHkxR^C-R)xD%%n9NEm!N zF6liB&mkpFr_yV=nNkw69XE-#6w>jdx3}d%{x}t*qOR08`=PWvz8bM!2<nWv(T+i3 z7U!9Z_J(*_mT_#-3rt0w|HFwUkK)J5kU_>CH08~gDNh~_nfu~$@nQos6S5B??emae z%CWrr$4NKAFwsQ!cr)Ci+<<6YfF726a^Rl0bPr_OhLIk92P=LV@?lhp&g$7Y*ph7h zoAENYZOJFl)UxC(8@`ZfLwYMQmEExN269-_o&#T)aZa@BX(PU)4_HFBA#P-Zdt2Us zbH28Zr0*=YEbd5-&oEZ59XfC&L|evckv|NM1=3SjArPGrhS)e;U^*;@WeOY=7Nn>6 z4%uKCa+y%6j+Zi(;_|Uh+A=^%PsJg_snoo|0@c(ZR_ikbCghYlVwLosYX%F5$)JWt zQ!@p$%67++AwBwzTb~<^aWdSg4WHuv(D?+MuS7ESz?Hm-EacAo^nb&S?_f<kf=BMJ zQ5n8MzsQWsIED#Rz-#W4iep_&C8m6f7@t5)u7cFfjLC%jRodGcdjO7$CeGlm(C=tU z5Ec4uro6wQqXXzDZ<*Jc^2b7+AE_iCMU%euMF>_;_;JR@)-`ZmSPPQTY1#(~+>^*3 z0&p(jX4?XPSZ9)Vdq&A=lCKRZEnP^c8soTiF4jB;{j$8lLWtsdlw89Yd~RAsH1R$) zS5H0S56+fJgo|Ev!vhhJO?j_HVH86pE~oZs1!))0KBT-(yCr3)<dHstZ8`zAW2UWJ zrUTZ1=<1CZmmpPITc0{wQ9U}ZX{bTeDn{g_2N?r7kYdkHeKgTWWAzP|<1zOg)Pqkp zR+w^XT?u;6zO&$x;CL_nLA7N}QyUsxFhM#RYRWSzJn$N)PqxA@=Q<N^Lg#pHp&8?F z(RTODBl?x+x=*_hI`&L3<@+3_usxD-UVjVXqKTu@x{K5e4E0`tX6X&yc*=wQZnp4N zA>Hyl*_G2Q^l|Aq!?QOTEJ)h#u#5F9NuNovYtYg&wNu_F!9!SMGKc`BH2h|y&LgRf zAEm(`Lb`nUr1>acWx1Jeuf=_R*6V(J*KX}u@8{vYm*g!F*nGr)C6?Xk+~l8r506DP zMnGw=0w$IAc5La*GRu4M65*GN5K!?p>Vr4(c(2E8t8_F&mT$tj^ZLi)q&IU*Z{$zW zqq*`0Ix{zqI`Cb;C;8GoUQpaEYq)DPPJaE}W;X8)-;c^y2+8Mohw)jwf}30hU)+p0 z7h#rsub1N&6%-bV6_NV-P=oHT(pH2PXjT5(gO&d9EKO**miiiQ_t(^DB_(Au3QMMG zQ?z+Sg9t?>g(MUXCd`yQh9aD!$F!0nB`Om3ZSX^hDXX;l27g7puL|#DZ>R_d@9=9A z1OCQIV#>{0eJHFCMH*EZ!fV-eRb&VU*9U8YdXOfK61bNM`*feE164qbSdX`-BX|K^ zRM+^z0kJ+5(i=jxq8_B+v`YEzcR_(x7t#Y5UaJb#`3p2r7Oe4WSLcVXCPAwXMKIJT zQQFWDYS8dLcRgA2!&)`j>~_9CUYAK|5c!QZnQwe&QXycYFRWEI_<fw4QDURWFPye& z6#f>=za`dRkzd8Rw5O^n6s(2sv>QXA8try}LpT_!gEq_%!luoxjlgrEdL6Xz*R|C! z&);C<Yc(mLB3Neuc&A-k9q{|`%6bLhwL*+KOTZKjFR*Lt{TlqE(Fvgj)YTfq!aaE7 zeIsm}HA+mm(Gsa|s>keV8Yg27{l7-~e~sn;HJqO{n4dMA2q6Ot+yhsz+95~_hNYm% zay+Fxb>0}PsTrzoU1d$A%C9MlpmNP7ej71mp(V1)AJ(axawD-|osXW<;E}2ZU#&I~ zfQrFVtB=3YU&%hKBa#;Z+u#p}2lp8;!h#0ba<%lu)fyvMSwkggWnp8rbq!$`oLx7B z0?=DdgN$$5xxx|}4n-O&F$;sn=cKTY>L|aDU}%Q@l{)4&R6X?Anv!R^%^I~T82&aE zG#8@}oi`yG8suCJA!CppDkK;RLueDKuEr-9Qkx-U(c%n!eENVFppXiEUyamfU>vwd zOu313Td^@%r3W<5>7vqAYAMU6$#$rhOfH%+dHS@;Gm4R=mTLOOaIk_ao?SFwxH1@2 zz3P0mevAzTDnoTTzSam!O%_jEfY=D?T7!QB!WX8j-=qbmZj_(tSdlSMA^jkf!WutF zVMrl2X<REZdbu7mR`A!I7Serx+v<ev%VmIDc6_!GH9^EB*1232G=%<Jrg6%UmpAyW zd|l<QL>$*>Un!b4S({c^TrycJD3~-$yKdff3$<lTR?O?{yFm5zS5{WkhOkB_7R_1Y ztF1-&q2rw8D<*5x=Uj&*gO7oxEWut?<J&}c)FQ<*K0|d?VWc4hnO|GDeBM&&Vai<$ z=huT(W=3>aw)lD^DGqSEuO?U}!(hd{8|O)XVsBYwWe2InENziYezJ!>|Fa-gV1mF} zq|IWgu~N0nfim?^RErm>Xp$VjN;sSlNwND+%j~aj49Um|Pe!7l!c4kKg3=%D1KHRq z+R|rwrab24^XbC`sM)#{|BZc>CRW$<zJmOYwWDDPspX^8XS~{W4D3PRwX(fM&17@R zlnDuW%gR6*nOd9T%)x3-)Vlc_cC`UFj&hDC6M}Z0VYJoI#>(*64(WGwefF3c`!IZf z4eq=nIrWmM@NZR1!$M52LFj1j{TP!Q?)e6F@-ow$Z%8}!F_+1_fuYn<XqE;isYJ`v zRU5=vtZu_7UJjncb@*CNZgq%qf-+Qa?(x-Kjhx8TiS&RR%1&kJgO{%c=c1}j*zb^n zCTJlXbQ*$O&zq*!O}d8itNAINR_#L<wZ2tymd7?Q&&jXC*=zao>z5<RGZ67{ov*$C z=Rui_sPX#Xh7JA(=58FIs*s;`e;DU5T!E^Fg7x^0@7pVQ9-V`IIlob>4)c>dy#OaG zc}!K!l7F$xI|~B7%5R4wI6qkQ{HjT+b72V%g1F=na+ZcIWj=NWsKE1OIDJ0n<_QIT z+(%(nIPFVxz2=>N#`nD6b$i}N`Q;8(?!M3M*|mKDZ@Aa(sjz6|xfOj_=b*d+zAGJl z`@q}yJ-25x+V8sG?Ky>#^8>dhh`Pe62_FXh35sxKxrdGLjJjZS&e%&Y$34as*<Tw6 z#rT8s^LXEh4?j+!UWQu!GLG7H$8zD?>~UQ&+U?$ory}IXXM^H?@bUSBn0JvUmNoxE z!fY==*#=q=b(*#yI_z%uJ-n?ExaaD3)`a=61wS7Pd>$xH#M~bIj3^rMq09%L_J_9N z`(?`B8O3*ts1E_>M7)lIA9rLwd=4lt4zLXOqqK)FsnG^}N+|GopvZw-!o4kS55H~I zQ1DqHzUdbH@iWwpcBmGjF1@Jl0uJ!+zFKhWXLlNYx7#xo<%=jYP|8qNqEw^Yj&e83 z_fdX=(uQ&j<pq>CP(DN%j&IP%qI?l$21*&qN|b7p+fnXD;aK#keTi!qESRND#3$C1 zwBmxIf@#>z3%^=8bJ|z5iOaFf7GcH7_9@e+VT=C%;-3C@$^QT3rj-TZ0Ke|_trrFO zT-V=FFAA`1{RQ*pFP@_NHdxq(x=6wLNDv>k2dhK@u>fy43#vBNg*VlzT5nJk>#i*W zsQ|6PUqgNc)Ys@75Z@*j=>A6htp);82q$fyDDVd=s&TL4uRyLEz(fJh@L>$6s#_~T zgh*d)uoA<CAO?R5q--T;eHh%lpZ3@3cIbU(&9%c==US2fPXQ3F2m2z87u)bti{z94 zp8yCNaQouJG+q->Y`y^2XaIb9lA`|De9SR;4?Dzhxwf}~uMn`zC8){A@^uvINItIl zL*P4!!W@7~@-SzVp>W-kk2zu|5atH^A}_D&P_RbixLn(JVGz6!ksg=*SyrPk9}s3v zXa^tlbB+sC+=?<1g?!8@z2MUTJMG}&<ayiXV-CszLzl(Jd`DZ!w;6@HavbKs6X0Xs zvM=)S+K6KF^@6V#e7kHTK_ef_T@F6}Ul!XjImwA=v@ZIN*H#o;9&>IZjAb6TFMHhY zqJez0cL(@(fUlYcSeMQBec(2q{Qo83<e}v4aqx{xxIN?M2(ii*hT4|*3yY6)%*Sc` ze=+DU`?C4=p@HL)k00(fo`dg@gO4BRHi6HU0a6<70L;0dJmz%%e;Zv^8!E|1J)S|a z$6bQGX9)uLY<a}_Bf8DUJ!%>F>d|Ij<Y761V)M0wuN{2$T#?t7{YStYpZf6!jBfBv i25euN1-you^6ZOzV;l`OXpd?0ox%z2w2h#)`Th^~{+Sp6
literal 0 HcmV?d00001
diff --git a/cpu/arm926ejs/kirkwood/doimage/doimage.c b/cpu/arm926ejs/kirkwood/doimage/doimage.c new file mode 100644 index 0000000..0c484b2 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/doimage/doimage.c @@ -0,0 +1,1341 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Maen Suleiman maen@marvell.com + * Tawfik Bayouk tawfik@marvell.com + * + * Updated by + * 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 <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/mman.h> + +#define _HOST_COMPILER +#include "bootstrap_def.h" + +#ifndef O_BINARY /* should be define'd on __WIN32__ */ +#define O_BINARY 0 +#endif /* */ + +#define DOIMAGE_VERSION "1.00" +void print_usage(void); +int f_in = -1; +int f_out = -1; +int f_header = -1; +typedef enum { IMG_SATA, IMG_UART, IMG_FLASH, IMG_BOOTROM, IMG_NAND, IMG_HEX, + IMG_BIN, IMG_PEX, IMG_I2C +} IMG_TYPE; +typedef enum { HDR_IMG_ONE_FILE = 1, /* Create one file with header and image */ + HDR_IMG_TWO_FILES = 2, /* Create seperate header and image files */ + HDR_ONLY = 3, /* Create only header */ + IMG_ONLY = 4 /* Create only image */ +} HEADER_MODE; + +#define T_OPTION_MASK 0x1 /* image type */ +#define D_OPTION_MASK 0x2 /* image destination */ +#define E_OPTION_MASK 0x4 /* image execution address */ +#define S_OPTION_MASK 0x8 /* image source */ +#define R_OPTION_MASK 0x10 /* DRAM file */ +#define C_OPTION_MASK 0x20 /* NAND ECC mode */ +#define P_OPTION_MASK 0x40 /* NAND Page size */ +#define M_OPTION_MASK 0x80 /* TWSI serial init file */ +#define W_OPTION_MASK 0x100 /* HEX file width */ +#define H_OPTION_MASK 0x200 /* Header mode */ +#define X_OPTION_MASK 0x400 /* Pre padding */ +#define Y_OPTION_MASK 0x800 /* Post padding */ +#define I_OPTION_MASK 0x1000 /* SATA PIO mode */ +#define L_OPTION_MASK 0x2000 /* delay time in mseconds */ + +#define SATA_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|S_OPTION_MASK) +#define UART_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK) +#define FLASH_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK) +#define PEX_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK) +#define I2C_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|M_OPTION_MASK) +#define MAX_TWSI_HDR_SIZE (60*1024) /* MAX eeprom is 64K & leave 4K for image and header */ +#define BOOTROM_MUST_OPT (T_OPTION_MASK) + +#define NAND_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|P_OPTION_MASK) +#define HEX_MUST_OPT (T_OPTION_MASK|W_OPTION_MASK) +#define BIN_MUST_OPT (T_OPTION_MASK|W_OPTION_MASK) + +/* 8 bit checksum */ +u8 checksum8(void *start, u32 len, u8 csum) +{ + register u8 sum = csum; + volatile u8 *startp = (volatile u8 *)start; + + do { + sum += *startp; + startp++; + } while (--len); + return (sum); +} + +/* 32 bit checksum */ +u32 checksum32(void *start, u32 len, u32 csum) +{ + register u32 sum = csum; + volatile u32 *startp = (volatile u32 *)start; + int currLen = len; + + do { + sum += *(u32 *) startp; + startp++; + currLen -= 4; + } while (currLen > 0); + return (sum); +} + +void make_crc_table(u32 * crc_table) +{ + u32 c; + int n, k; + u32 poly; + + /* terms of polynomial defining this crc (except x^32): */ + static const u8 p[] = + { 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26 }; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p) / sizeof(u8); n++) + poly |= 1L << (31 - p[n]); + for (n = 0; n < 256; n++) { + c = (u32) n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } +} + +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); +u32 crc32(u32 crc, volatile u32 * buf, u32 len) +{ + u32 crc_table[256]; + + /* Create the CRC table */ + make_crc_table(crc_table); + crc = crc ^ 0xffffffffL; + while (len >= 8) { + DO8(buf); + len -= 8; + } + if (len) + do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} + +int main(int argc, char **argv) +{ + char *image_type = NULL; + IMG_TYPE img; + u32 image_dest = 0, image_exec = 0, header_size = + 0, image_source = 0, twsi_size = 0; + char *fname_in, *fname_out = NULL, *fname_hdr_out = NULL, *fname_romc = + NULL, *fname_dram = NULL, *fname_twsi = NULL; + u8 *ptr; + BHR_t hdr; + ExtBHR_t extHdr; + struct stat fs_stat; + char *buf_in = NULL; + int override[2]; + int err, size_written = 0; + char *tmpHeader = NULL; + char *tmpTwsi = NULL; + u32 opts = 0, required_opts = 0; + u32 chsum32 = 0; + u32 nandPageSize = 0, nandEccMode = 0, hex_width = + 0, header_mode = HDR_IMG_ONE_FILE, ms_delay = 0; + FILE *f_hex = NULL; + FILE *f_dram = NULL, *f_hex2 = NULL, *f_hex3 = NULL, *f_twsi = NULL; + u8 *hex8 = NULL, tmp8; + u16 *hex16 = NULL, tmp16; + u32 *hex32 = NULL, tmp32; + u32 lastDword = 0; + int i = 0; + u32 bytesToAlign = 0; + char **f_out_names[2]; + int pre_padding = 0, post_padding = 0, padding_size = 0; + +#define IMG_FILE_INDX 0 +#define HDR_FILE_INDX 1 + f_out_names[IMG_FILE_INDX] = &fname_out; + f_out_names[HDR_FILE_INDX] = &fname_hdr_out; + memset((void *)&hdr, 0, sizeof(BHR_t)); + memset((void *)&extHdr, 0, sizeof(ExtBHR_t)); + if (argc == 1) { + print_usage(); + exit(1); + } + while (--argc > 0 && **++argv == '-') { + while (*++*argv) { + switch (**argv) { + case 'T': /* image type */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + image_type = *++argv; + if (opts & T_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= T_OPTION_MASK; + break; + case 'D': /* image destination */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + image_dest = + strtoul(*++argv, (char **)&ptr, 16); + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & D_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= D_OPTION_MASK; + break; + case 'E': /* image execution */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + image_exec = + strtoul(*++argv, (char **)&ptr, 16); + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & E_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= E_OPTION_MASK; + break; + case 'X': /* Pre - Padding */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + padding_size = + strtoul(*++argv, (char **)&ptr, 16); + pre_padding = 1; + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & X_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= X_OPTION_MASK; + break; + case 'Y': /* Post - Padding */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + padding_size = + strtoul(*++argv, (char **)&ptr, 16); + post_padding = 1; + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & Y_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= Y_OPTION_MASK; + break; + case 'I': /* PIO */ + if (argc <= 0) { + print_usage(); + exit(1); + } + if (opts & I_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= I_OPTION_MASK; + break; + case 'S': /* starting sector */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + image_source = + strtoul(*++argv, (char **)&ptr, 16); + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & S_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= S_OPTION_MASK; + break; + case 'P': /* NAND Page Size */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + nandPageSize = + strtoul(*++argv, (char **)&ptr, 10); + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & P_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= P_OPTION_MASK; + break; + case 'C': /* NAND ECC mode */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + nandEccMode = + strtoul(*++argv, (char **)&ptr, 10); + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & C_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= C_OPTION_MASK; + break; + case 'L': /* Delay time */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + ms_delay = strtoul(*++argv, (char **)&ptr, 10); + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & L_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= L_OPTION_MASK; + break; + case 'W': /* HEX file width */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + hex_width = strtoul(*++argv, (char **)&ptr, 10); + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & W_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= W_OPTION_MASK; + break; + case 'H': /* Header file mode */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + header_mode = + strtoul(*++argv, (char **)&ptr, 10); + if (*ptr) { + print_usage(); + exit(1); + } + if (opts & H_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= H_OPTION_MASK; + break; + case 'R': /* dram file */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + fname_dram = *++argv; + if (opts & R_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= R_OPTION_MASK; + break; + case 'M': /* TWSI serial init file */ + if (--argc <= 0) { + print_usage(); + exit(1); + } + fname_twsi = *++argv; + if (opts & M_OPTION_MASK) { + print_usage(); + exit(1); + } + opts |= M_OPTION_MASK; + break; + } + } + } + + /* 2 sperate images is used with SATA only */ + if (header_mode == HDR_IMG_TWO_FILES) { + if (!(opts & S_OPTION_MASK)) { + fprintf(stderr, + "Error: -S option is missing\n\n\n\n\n"); + print_usage(); + exit(1); + } + } + + /* verify HEX file width selection to be valid */ + if (opts & W_OPTION_MASK) { + if ((hex_width != 8) && (hex_width != 16) && (hex_width != 32) + && (hex_width != 64)) { + print_usage(); + exit(1); + } + } + + /* get the minimum option set based on boot mode */ + if (opts & T_OPTION_MASK) { + if (strcmp(image_type, "sata") == 0) { + img = IMG_SATA; + required_opts = SATA_MUST_OPT; + } + + else if (strcmp(image_type, "nand") == 0) { + img = IMG_NAND; + required_opts = NAND_MUST_OPT; + } + + else if (strcmp(image_type, "hex") == 0) { + img = IMG_HEX; + required_opts = HEX_MUST_OPT; + } + + else if (strcmp(image_type, "bin") == 0) { + img = IMG_BIN; + required_opts = BIN_MUST_OPT; + } + + else if (strcmp(image_type, "uart") == 0) { + img = IMG_UART; + required_opts = UART_MUST_OPT; + } + + else if (strcmp(image_type, "flash") == 0) { + img = IMG_FLASH; + required_opts = FLASH_MUST_OPT; + } + + else if (strcmp(image_type, "bootrom") == 0) { + img = IMG_BOOTROM; + required_opts = BOOTROM_MUST_OPT; + } + + else if (strcmp(image_type, "pex") == 0) { + img = IMG_PEX; + required_opts = PEX_MUST_OPT; + } + + else if (strcmp(image_type, "i2c") == 0) { + img = IMG_I2C; + required_opts = I2C_MUST_OPT; + } + + else { + print_usage(); + exit(1); + } + } + + else { + print_usage(); + exit(1); + } + if (header_mode == IMG_ONLY) { + required_opts &= + ~(D_OPTION_MASK | E_OPTION_MASK | S_OPTION_MASK | + R_OPTION_MASK | P_OPTION_MASK); + } + if (required_opts != (opts & required_opts)) { + print_usage(); + exit(1); + } + hdr.ddrInitDelay = ms_delay; + hdr.destinationAddr = image_dest; + hdr.executionAddr = image_exec; + switch (img) { + case IMG_BOOTROM: + header_mode = IMG_ONLY; + break; + case IMG_HEX: + header_mode = IMG_ONLY; + break; + case IMG_BIN: + header_mode = IMG_ONLY; + break; + case IMG_SATA: + hdr.blockID = IBR_HDR_SATA_ID; + header_size = 512; + if (image_source) + hdr.sourceAddr = image_source; + + else + hdr.sourceAddr = 2; /* default */ + if (!(opts & H_OPTION_MASK)) { + header_mode = HDR_IMG_TWO_FILES /*HDR_ONLY */ ; + } + if (opts & I_OPTION_MASK) { + hdr.sataPioMode = 1; + } + break; + case IMG_UART: + hdr.blockID = IBR_HDR_UART_ID; + if (opts & R_OPTION_MASK) { + header_size = 512; + } else + header_size = 128; + hdr.sourceAddr = header_size; + break; + case IMG_FLASH: + hdr.blockID = IBR_HDR_SPI_ID; + if (opts & R_OPTION_MASK) { + header_size = 512; + } else + header_size = sizeof(BHR_t); + if ((image_source) && (image_source >= header_size)) { + hdr.sourceAddr = image_source; + } else { + hdr.sourceAddr = header_size; /* default */ + } + break; + case IMG_NAND: + hdr.blockID = IBR_HDR_NAND_ID; + if (opts & R_OPTION_MASK) { + header_size = 512; + } else + header_size = sizeof(BHR_t); + if ((image_source) && (image_source >= header_size)) { + hdr.sourceAddr = image_source; + } else { + hdr.sourceAddr = header_size; /* default */ + } + hdr.nandPageSize = (u16) nandPageSize; + hdr.nandEccMode = (u8) nandEccMode; + break; + case IMG_PEX: + hdr.blockID = IBR_HDR_PEX_ID; + if (opts & R_OPTION_MASK) { + header_size = 512; + } else + header_size = sizeof(BHR_t); + if ((image_source) && (image_source >= header_size)) { + hdr.sourceAddr = image_source; + } else { + hdr.sourceAddr = header_size; /* default */ + } + case IMG_I2C: + hdr.blockID = IBR_HDR_I2C_ID; + if (opts & R_OPTION_MASK) { + header_size = 512; + } else + header_size = sizeof(BHR_t); + if ((image_source) && (image_source >= header_size)) { + hdr.sourceAddr = image_source; + } else { + hdr.sourceAddr = header_size; /* default */ + } + } + if ((header_mode == HDR_IMG_TWO_FILES) + || ((header_mode == IMG_ONLY) && (img == IMG_BIN))) { + if (argc == 4) { /* In case ROMC is needed */ + fname_in = *argv++; + fname_out = *argv++; + fname_hdr_out = *argv++; + fname_romc = *argv++; + if ((0 == strcmp(fname_in, fname_out)) || + (0 == strcmp(fname_in, fname_hdr_out)) || + (0 == strcmp(fname_in, fname_romc)) || + (0 == strcmp(fname_out, fname_hdr_out)) || + (0 == strcmp(fname_out, fname_romc)) || + (0 == strcmp(fname_hdr_out, fname_romc))) { + fprintf(stderr, + "Error: Input and output images can't be the same\n"); + exit(1); + } + } + + else if (argc == 3) { + fname_in = *argv++; + fname_out = *argv++; + fname_hdr_out = *argv++; + if ((0 == strcmp(fname_in, fname_out)) || + (0 == strcmp(fname_in, fname_hdr_out)) || + (0 == strcmp(fname_out, fname_hdr_out))) { + fprintf(stderr, + "Error: Input and output images can't be the same\n"); + exit(1); + } + } + + else { + print_usage(); + exit(1); + } + } + + else { + if (argc == 2) { + fname_in = *argv++; + fname_out = *argv++; + if (0 == strcmp(fname_in, fname_out)) { + fprintf(stderr, + "Error: Input and output images can't be the same\n"); + exit(1); + } + } + + else { + print_usage(); + exit(1); + } + } + + /* check if the output image exist */ + i = 0; + + do { + if (*f_out_names[i]) { + f_out = open(*f_out_names[i], O_RDONLY | O_BINARY); + if (f_out != -1) { + char c; + close(f_out); + f_out = -1; + fprintf(stderr, + "File '%s' already exist! override (y/n)?", + *f_out_names[i]); + c = getc(stdin); + if ((c == 'N') || (c == 'n')) { + printf("exit.. nothing done. \n"); + exit(0); + } + + /* for the Enter */ + c = getc(stdin); + override[i] = 1; + } + + else { + override[i] = 0; + } + } + i++; + if (i == 2) + break; + } while (1); + if (header_mode != HDR_ONLY) { + + /* open input image */ + f_in = open(fname_in, O_RDONLY | O_BINARY); + if (f_in == -1) { + fprintf(stderr, "File '%s' not found \n", fname_in); + exit(0); + } + + /* get the size of the input image */ + err = fstat(f_in, &fs_stat); + if (0 != err) { + close(f_in); + fprintf(stderr, "fstat failed for file: '%s' err=%d\n", + fname_in, err); + exit(1); + } + if ((fs_stat.st_size > BOOTROM_SIZE) && (img == IMG_BOOTROM)) { + printf + ("ERROR : bootstrap.bin size is bigger than %d bytes \n", + BOOTROM_SIZE); + close(f_in); + exit(1); + } + + /* map the input image */ + buf_in = + mmap(0, fs_stat.st_size, PROT_READ, MAP_SHARED, f_in, 0); + if (!buf_in) { + fprintf(stderr, "Error mapping %s file \n", fname_in); + goto end; + } + } + + /* open the output image */ + if (override[IMG_FILE_INDX] == 0) { + f_out = + open(fname_out, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, + 0666); + } + + else + f_out = open(fname_out, O_RDWR | O_BINARY); + if (f_out == -1) { + fprintf(stderr, "Error openning %s file \n", fname_out); + } + if (header_mode == HDR_IMG_TWO_FILES) { + + /* open the output header file */ + if (override[HDR_FILE_INDX] == 0) { + f_header = + open(fname_hdr_out, + O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 0666); + } + + else + f_header = open(fname_hdr_out, O_RDWR | O_BINARY); + if (f_header == -1) { + fprintf(stderr, "Error openning %s file \n", + fname_hdr_out); + } + } + + /* Image Header */ + if (header_mode != IMG_ONLY) { + hdr.blockSize = fs_stat.st_size; + if (opts & R_OPTION_MASK) { + hdr.ext = 1; + } + + /* for FLASH\NAND , we have extra word for checksum */ + if ((img == IMG_FLASH) || (img == IMG_NAND) + || (img == IMG_SATA) || (img == IMG_PEX) + || (img == IMG_I2C)) { + + /*hdr.blockSize++; */ + hdr.blockSize += 4; + } + + /* in sata headers, blocksize is in sectors (512 byte) */ + if (img == IMG_SATA) { + + /*hdr.blockSize = (hdr.blockSize + 511) >> 9; */ + } + + /* Update Block size address */ + if (padding_size) { + + /* Align padding to 32 bit */ + if (padding_size & 0x3) { + padding_size += (4 - (padding_size & 0x3)); + } + hdr.blockSize += padding_size; + } + + /* Align size to 4 byte */ + if (hdr.blockSize & 0x3) { + printf("hdr.blockSize = 0x%x fs_stat.st_size = 0x%x\n", + (u32)hdr.blockSize, (u32)fs_stat.st_size); + bytesToAlign = (4 - (hdr.blockSize & 0x3)); + hdr.blockSize += bytesToAlign; + } + tmpTwsi = malloc(MAX_TWSI_HDR_SIZE); + memset(tmpTwsi, 0xFF, MAX_TWSI_HDR_SIZE); + if (opts & M_OPTION_MASK) { + if (fname_twsi) { + int i; + u32 *twsi_reg = (u32 *) tmpTwsi;; + f_twsi = fopen(fname_twsi, "r"); + if (f_twsi == NULL) { + fprintf(stderr, + "File '%s' not found \n", + fname_twsi); + exit(1); + } + for (i = 0; i < (MAX_TWSI_HDR_SIZE / 4); i++) { + if (EOF == + fscanf(f_twsi, "%x\n", twsi_reg)) + break; + + /* Swap Enianess */ + *twsi_reg = + (((*twsi_reg >> 24) & 0xFF) | + ((*twsi_reg >> 8) & 0xFF00) | + ((*twsi_reg << 8) & 0xFF0000) | + ((*twsi_reg << 24) & 0xFF000000)); + twsi_reg++; + } + fclose(f_twsi); + twsi_size = ((((i + 2) * 4) & ~0x1FF) + 0x200); /*size=512,1024,.. with at least 8 0xFF bytes */ + if ((write(f_out, tmpTwsi, twsi_size)) != + twsi_size) { + fprintf(stderr, + "Error writing %s file \n", + fname_out); + goto end; + } + } + } + tmpHeader = malloc(header_size); + memset(tmpHeader, 0, header_size); + hdr.checkSum = checksum8((void *)&hdr, sizeof(BHR_t), 0); + memcpy(tmpHeader, &hdr, sizeof(BHR_t)); + + /* Header extension */ + if (opts & R_OPTION_MASK) { + int dram_buf_size = 0; + + /* First we will take of DRAM */ + if (fname_dram) { + int i; + + /*u32 dram_reg[DRAM_REGS_NUM]; */ + u32 dram_reg[(512 >> 2)]; + f_dram = fopen(fname_dram, "r"); + if (f_dram == NULL) { + fprintf(stderr, + "File '%s' not found \n", + fname_dram); + exit(1); + } + + /*for (i=0; i< DRAM_REGS_NUM ; i++) */ + i = 0; + while (EOF != + fscanf(f_dram, "%x\n", &dram_reg[i++])) ; + fclose(f_dram); + + /*dram_buf_size = DRAM_REGS_NUM * 4; */ + dram_buf_size = (i - 1) * 4; + memcpy(tmpHeader + sizeof(BHR_t) + + sizeof(ExtBHR_t), dram_reg, + dram_buf_size); + extHdr.dramRegsOffs = + sizeof(BHR_t) + sizeof(ExtBHR_t); + } + memcpy(tmpHeader + sizeof(BHR_t), &extHdr, + sizeof(ExtBHR_t)); + *(u8 *) (tmpHeader + header_size - 1) = + checksum8((void *) (tmpHeader + sizeof(BHR_t)), + header_size - sizeof(BHR_t), (u8)0); + } + if (header_mode == HDR_IMG_TWO_FILES) { + + /* copy header to output image */ + size_written = write(f_header, tmpHeader, header_size); + if (size_written != header_size) { + fprintf(stderr, "Error writing %s file \n", + fname_hdr_out); + goto end; + } + fprintf(stdout, "%s was created \n", + *f_out_names[HDR_FILE_INDX]); + } + + else { + + /* copy header to output image */ + size_written = write(f_out, tmpHeader, header_size); + if (size_written != header_size) { + fprintf(stderr, "Error writing %s file \n", + fname_out); + goto end; + } + } + } + if (header_mode != HDR_ONLY) { + char *padding = NULL; + int new_file_size = 0; + if (img == IMG_BOOTROM) { + char *tmp1; + int tmpSize = BOOTROM_SIZE - sizeof(chsum32); + + /* PAD image with Zeros until BOOTROM_SIZE */ + tmp1 = malloc(tmpSize); + if (tmp1 == NULL) + goto end; + memcpy(tmp1, buf_in, fs_stat.st_size); + memset(tmp1 + fs_stat.st_size, 0, + tmpSize - fs_stat.st_size); + fs_stat.st_size = tmpSize; + + /* copy input image to output image */ + size_written = write(f_out, tmp1, fs_stat.st_size); + + /* calculate checsum */ + chsum32 = crc32(0, (u32 *) tmp1, (fs_stat.st_size / 4)); + printf("Image Chacksum (size = %d) = 0x%08x\n", + (int)fs_stat.st_size, chsum32); + fs_stat.st_size += sizeof(chsum32); + size_written += write(f_out, &chsum32, sizeof(chsum32)); + if (tmp1) + free(tmp1); + new_file_size = fs_stat.st_size; + } + + else if (img == IMG_HEX) { + char *tmp1 = NULL; + int hex_unaligned_len = 0; + int hex_len = fs_stat.st_size; + f_hex = fopen(fname_out, "w"); + if (f_hex == NULL) + goto end; + switch (hex_width) { + case 8: + hex8 = (u8 *) buf_in; + + do { + fprintf(f_hex, "%02X\n", *hex8); + hex8++; + size_written += 1; + hex_len--; + } while (hex_len); + break; + case 16: + hex16 = (u16 *) buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x1); + if (hex_unaligned_len) { + hex_len -= hex_unaligned_len; + hex_len += 2; + tmp1 = malloc(hex_len); + hex16 = (u16 *) tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + + do { + fprintf(f_hex, "%04X\n", *hex16++); + size_written += 2; + hex_len -= 2; + } while (hex_len); + break; + case 32: + hex32 = (u32 *)buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x3); + if (hex_unaligned_len) { + hex_len -= hex_unaligned_len; + hex_len += 4; + tmp1 = malloc(hex_len); + hex16 = (u16 *) tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + + do { + fprintf(f_hex, "%08X\n", (u32)*hex32++); + size_written += 4; + hex_len -= 4; + } while (hex_len); + break; + case 64: + hex32 = (u32 *)buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x7); + if (hex_unaligned_len) { + hex_len -= hex_unaligned_len; + hex_len += 8; + tmp1 = malloc(hex_len); + hex16 = (u16 *) tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + + do { + fprintf(f_hex, "%08X", (u32)*hex32++); + fprintf(f_hex, "%08X\n", (u32)*hex32++); + size_written += 8; + hex_len -= 8; + } while (hex_len); + break; + } + size_written = fs_stat.st_size; + if (tmp1) + free(tmp1); + fclose(f_hex); + new_file_size = fs_stat.st_size; + } + + else if (img == IMG_BIN) { + char *tmp1 = NULL; + int one_file_len; + int hex_len = fs_stat.st_size; + f_hex = fopen(fname_out, "w"); + if (f_hex == NULL) + goto end; + f_hex2 = fopen(fname_hdr_out, "w"); + if (f_hex2 == NULL) + goto end; + if (fname_romc) { + f_hex3 = fopen(fname_romc, "w"); + if (f_hex3 == NULL) + goto end; + one_file_len = (hex_len / 3); + } + + else { + one_file_len = hex_len * 0.5; + } + switch (hex_width) { + int hex_unaligned_len = 0; + case 8: + hex8 = (u8 *) buf_in; + + do { + tmp8 = *hex8; + if (hex_len > one_file_len) { + for (i = 0; i < hex_width; i++) { + fprintf(f_hex, "%d", + ((tmp8 & 0x80) + >> 7)); + tmp8 <<= 1; + } + fprintf(f_hex, "\n"); + } + + else { + for (i = 0; i < hex_width; i++) { + fprintf(f_hex2, "%d", + ((tmp8 & 0x80) + >> 7)); + tmp8 <<= 1; + } + fprintf(f_hex2, "\n"); + } + hex8++; + size_written += 1; + hex_len--; + } while (hex_len); + break; + case 16: + hex16 = (u16 *) buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x1); + if (hex_unaligned_len) { + hex_len -= hex_unaligned_len; + hex_len += 2; + tmp1 = malloc(hex_len); + hex16 = (u16 *) tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + + do { + tmp16 = *hex16; + for (i = 0; i < hex_width; i++) { + fprintf(f_hex, "%d", + ((tmp16 & 0x8000) >> + 15)); + tmp16 <<= 1; + } + fprintf(f_hex, "\n"); + hex16++; + size_written += 2; + hex_len -= 2; + } while (hex_len); + break; + case 32: + hex32 = (u32 *)buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x3); + if (hex_unaligned_len) { + hex_len -= hex_unaligned_len; + hex_len += 4; + tmp1 = malloc(hex_len); + hex16 = (u16 *) tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + + do { + tmp32 = *hex32; + if (fname_romc) { + if (hex_len > + (2 * one_file_len)) { + for (i = 0; + i < hex_width; + i++) { + fprintf(f_hex, + "%d", (int) + ((tmp32 + & + 0x80000000) + >> + 31)); + tmp32 <<= 1; + } + fprintf(f_hex, "\n"); + } + + else if (hex_len > one_file_len) { + for (i = 0; + i < hex_width; + i++) { + fprintf(f_hex2, + "%d", (int) + ((tmp32 + & + 0x80000000) + >> + 31)); + tmp32 <<= 1; + } + fprintf(f_hex2, "\n"); + } + + else { + for (i = 0; + i < hex_width; + i++) { + fprintf(f_hex3, + "%d", (int) + ((tmp32 + & + 0x80000000) + >> + 31)); + tmp32 <<= 1; + } + fprintf(f_hex3, "\n"); + } + } + + else { + if (hex_len > one_file_len) { + for (i = 0; + i < hex_width; + i++) { + fprintf(f_hex, + "%d", (int) + ((tmp32 + & + 0x80000000) + >> + 31)); + tmp32 <<= 1; + } + fprintf(f_hex, "\n"); + } + + else { + for (i = 0; + i < hex_width; + i++) { + fprintf(f_hex2, + "%d", (int) + ((tmp32 + & + 0x80000000) + >> + 31)); + tmp32 <<= 1; + } + fprintf(f_hex2, "\n"); + } + } + hex32++; + size_written += 4; + hex_len -= 4; + } while (hex_len); + break; + case 64: + fprintf(stderr, + "Error: 64 Bit is not supported for binary files\n\n\n\n\n"); + break; + } + size_written = fs_stat.st_size; + if (tmp1) + free(tmp1); + fclose(f_hex); + fclose(f_hex2); + new_file_size = fs_stat.st_size; + } + + else { + size_written = 0; + if ((pre_padding) && (padding_size)) { + padding = malloc(padding_size); + if (padding) { + new_file_size += padding_size; + memset((void *)padding, 0x5, + padding_size); + size_written += + write(f_out, padding, padding_size); + chsum32 = + checksum32( /*(u32) */ (void *) + padding, padding_size, + chsum32); + } + } + new_file_size += fs_stat.st_size; + + /* Calculate checksum */ + chsum32 = checksum32( /*(u32) */ (void *)buf_in, + (u32) ((u32) fs_stat.st_size - + bytesToAlign), chsum32); + if (bytesToAlign) { + memcpy(&lastDword, + (buf_in + + (fs_stat.st_size - bytesToAlign)), + bytesToAlign); + } + chsum32 = checksum32( /*(u32) */ (void *)&lastDword, 4, + chsum32); + + /* copy input image to output image */ + size_written += write(f_out, buf_in, fs_stat.st_size); + if (bytesToAlign) { + size_written += + write(f_out, &lastDword, bytesToAlign); + } + if ((post_padding) && (padding_size)) { + padding = malloc(padding_size); + if (padding) { + new_file_size += padding_size; + memset((void *)padding, 0xa, + padding_size); + size_written += + write(f_out, padding, padding_size); + chsum32 = + checksum32( /*(u32) */ (void *) + padding, padding_size, + chsum32); + } + } + + /* write checksum */ + size_written += write(f_out, &chsum32, sizeof(chsum32)); + new_file_size += 4; + } + if (size_written != new_file_size) { + fprintf(stderr, "Error writing %s file \n", fname_out); + goto end; + } + fprintf(stdout, "%s was created \n", + *f_out_names[IMG_FILE_INDX]); + } + end:if (tmpHeader) + free(tmpHeader); + + /* close handles */ + if (f_out != -1) + close(f_out); + if (f_header != -1) + close(f_header); + if (buf_in) + munmap((void *)buf_in, fs_stat.st_size); + if (f_in != -1) + close(f_in); + return 0; +} +void print_usage(void) +{ + printf("\n"); + printf("Marvell doimage Tool version %s\n", DOIMAGE_VERSION); + printf("Supported SoC devices: \n"); + printf(" Marvell 88F6082 - A1\n"); + printf(" Marvell 88F6180 - A0\n"); + printf(" Marvell 88F6192 - A0\n"); + printf(" Marvell 88F6190 - A0\n"); + printf(" Marvell 88F6281 - A0\n"); + printf("\n"); + printf("usage: \n"); + printf + ("doimage <must_options> [other_options] image_in image_out [header_out]\n"); + printf("\n<must_options> - can be one or more of the following:\n\n"); + printf("-T image_type: sata\uart\flash\bootrom\nand\hex\pex\n"); + printf(" if image_type is sata, the image_out will\n"); + printf(" include header only.\n"); + printf("-D image_dest: image destination in dram (in hex)\n"); + printf("-E image_exec: execution address in dram (in hex)\n"); + printf + (" if image_type is 'flash' and image_dest is 0xffffffff\n"); + printf(" then execution address on the flash\n"); + printf + ("-S image_source: if image_type is sata then the starting sector of\n"); + printf + (" the source image on the disk - mandatory for sata\n"); + printf + (" if image_type is flash\nand then the starting offset of\n"); + printf + (" the source image at the flash - optional for flash\nand\n"); + printf("-W hex_width : HEX file width, can be 8,16,32,64 \n"); + printf + ("-M twsi_file: ascii file name that contains the I2C init regs set by h/w.\n"); + printf(" this is used in i2c boot only\n"); + printf + ("\n<other_options> - optional and can be one or more of the following:\n\n"); + printf + ("-R dram_file: ascii file name that contains the list of dram regs\n"); + printf("-P nand_page_size (decimal 512, 2048, ..): NAND Page size\n"); + printf("-C nand_ecc_mode (1=Hamming, 2=RS, 3=None)\n"); + printf("-L delay in mili seconds before DRAM init\n"); + printf("-I copy image in PIO mode (valid for SATA only)\n"); + printf("-X pre_padding_size (hex)\n"); + printf("-Y post_padding_size (hex)\n"); + printf("-H header_mode: Header mode, can be:\n"); + printf + (" -H 1 :will create one file (image_out) for header and image\n"); + printf + (" -H 2 :will create two files, (image_out) for image , (header_out) for header\n"); + printf(" -H 3 :will create one file (image_out) for header only \n"); + printf(" -H 4 :will create one file (image_out) for image only \n"); + printf("\ncommand possibilities: \n\n"); + printf("doimage -T hex -W width image_in image_out\n"); + printf("doimage -T bootrom image_in image_out\n"); + printf("doimage -T sata -S sector -D image_dest -E image_exec\n"); + printf(" [other_options] image_in image_out header_out\n\n"); + printf("doimage -T flash -D image_dest -E image_exec [-S address]\n"); + printf(" [other_options] image_in image_out\n\n"); + printf("doimage -T pex -D image_dest -E image_exec \n"); + printf(" [other_options] image_in image_out\n\n"); + printf + ("doimage -T nand -D image_dest -E image_exec [-S address] -P page_size\n"); + printf(" [other_options] image_in image_out\n\n"); + printf("doimage -T uart -D image_dest -E image_exec\n"); + printf(" [other_options] image_in image_out\n\n"); + printf("doimage -T pex -D image_dest -E image_exec \n"); + printf(" [other_options] image_in image_out\n\n"); + printf + ("doimage -T i2c -D image_dest -E image_exec -M twsi_init_file\n"); + printf(" [other_options] image_in image_out\n\n"); + printf("\n\n\n"); +} diff --git a/cpu/arm926ejs/kirkwood/dram.c b/cpu/arm926ejs/kirkwood/dram.c new file mode 100644 index 0000000..41f1316 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/dram.c @@ -0,0 +1,49 @@ +/* + * (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> + +u32 kw_get_dram_bank_base_addr(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; +} + +u32 kw_get_dram_bank_size(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/kw88f6192.h b/cpu/arm926ejs/kirkwood/kw88f6192.h new file mode 100644 index 0000000..566c471 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kw88f6192.h @@ -0,0 +1,34 @@ +/* + * (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 + +#endif /* _CONFIG_KW88F6192_H */ diff --git a/cpu/arm926ejs/kirkwood/kw88f6281.h b/cpu/arm926ejs/kirkwood/kw88f6281.h new file mode 100644 index 0000000..3c0795a --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kw88f6281.h @@ -0,0 +1,34 @@ +/* + * (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 _CONFIG_KW88F6281_H +#define _CONFIG_KW88F6281_H + +/* SOC specific definations */ +#define KW88F6281_REGS_PHYS_BASE 0xf1000000 +#define KW_REGS_PHY_BASE KW88F6281_REGS_PHYS_BASE + +#endif /* _CONFIG_KW88F6281_H */ diff --git a/cpu/arm926ejs/kirkwood/kwcore.c b/cpu/arm926ejs/kirkwood/kwcore.c new file mode 100644 index 0000000..5085782 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.c @@ -0,0 +1,262 @@ +/* + * (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_DEBUG +#define KWCORE_DEBUG 0 +#endif +#define DEBUG_PRINT KWCORE_DEBUG + +#include <common.h> +#include <debug_prints.h> +#include <u-boot/md5.h> + +void reset_cpu(unsigned long ignored) +{ + debug_print_ftrace(); + 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]; + + debug_print_ftrace(); +#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) +{ + debug_print_ftrace(); + + 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) +{ + debug_print_ftrace(); + /* 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) +{ + debug_print_ftrace(); + /* 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; + + debug_print_ftrace(); + /*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) + info_print("Streaming enabled"); + else + info_print("Streaming disabled"); + if (temp & BIT28) + info_print("Write allocate enabled"); + else + info_print("Write allocate disabled"); + + /* 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..0ddc6a8 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.h @@ -0,0 +1,141 @@ +/* + * (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 _CONFIG_KWCORE_H +#define _CONFIG_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] + +/* + * 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_get_dram_bank_base_addr(MEMORY_BANK bank); +unsigned int kw_get_dram_bank_size(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 + +/* + * Error codes + */ +#define KW_ERROR (-1) +#define KW_OK (0) +#endif /* _CONFIG_KWCORE_H */ diff --git a/cpu/arm926ejs/kirkwood/serial.c b/cpu/arm926ejs/kirkwood/serial.c new file mode 100644 index 0000000..6422ab2 --- /dev/null +++ b/cpu/arm926ejs/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/cpu/arm926ejs/kirkwood/soc_init.S b/cpu/arm926ejs/kirkwood/soc_init.S new file mode 100644 index 0000000..e9701d2 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/soc_init.S @@ -0,0 +1,156 @@ +/* + * (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 */ + diff --git a/cpu/arm926ejs/kirkwood/spi.c b/cpu/arm926ejs/kirkwood/spi.c new file mode 100644 index 0000000..a334d95 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/spi.c @@ -0,0 +1,213 @@ +/* + * (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 + */ + +#ifndef KWSPI_DEBUG +#define KWSPI_DEBUG 0 +#endif +#define DEBUG_PRINT KWSPI_DEBUG + +#include <common.h> +#include <debug_prints.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; + + debug_print_ftrace(); + 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_print("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) +{ + debug_print_ftrace(); + free(slave); +} + +int spi_claim_bus(struct spi_slave *slave) +{ + debug_print_ftrace(); + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + debug_print_ftrace(); +} + +#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) +{ + debug_print_ftrace(); + return (bus == 0 && (cs == 0 || cs == 1)); +} +#endif + +void spi_cs_activate(struct spi_slave *slave) +{ + debug_print_ftrace(); + KW_REG_BITS_SET(KW_REG_SPI_CTRL, BIT0); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + debug_print_ftrace(); + 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_print_ftrace(); + debug_print("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_print("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_print("*** 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_print + ("*** 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) + error_print + ("*** spi_xfer: Time out during SPI transfer"); + + debug_print("loopend bitlen %d\n", bitlen); + } + + if (flags & SPI_XFER_END) + spi_cs_deactivate(slave); + + return 0; +} 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/include/configs/kirkwood.h b/include/configs/kirkwood.h new file mode 100644 index 0000000..eec04c2 --- /dev/null +++ b/include/configs/kirkwood.h @@ -0,0 +1,46 @@ +/* + * (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 _CONFIG_KIRKWOOD_H +#define _CONFIG_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> +#endif /* CONFIG_KIRKWOOD */ +#if defined (CONFIG_KW88F6281) +#include <../cpu/arm926ejs/kirkwood/kw88f6281.h> +#endif /* CONFIG_KW88F6281 */ +#if defined (CONFIG_KW88F6192) +#include <../cpu/arm926ejs/kirkwood/kw88f6192.h> +#endif /* CONFIG_KW88F6192 */ +#endif /* CONFIG_FEROCEON_88FR131 */ +#endif /* _CONFIG_KIRKWOOD_H */

Dear Prafulla Wadaskar,
In message 1238798370-9245-2-git-send-email-prafulla@marvell.com you wrote:
From: prafulla_wadaskar prafulla@marvell.com
Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:-
- 88F6281-Z0 define CONFIG_KW88F6281_Z0
- 88F6281-A0 define CONFIG_KW88F6281_A0
- 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:-
- Doimage utility needed to create binaries with bootROM header
- get_random_hex() fucntion
- SPI port controller driver
- PCI Express port initialization
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com
...
board/Marvell/common/kw_lowlevel_init.S | 45 + board/Marvell/include/core.h | 4 + cpu/arm926ejs/kirkwood/Makefile | 52 + cpu/arm926ejs/kirkwood/bin_dep.sh | 50 + cpu/arm926ejs/kirkwood/config.mk | 25 + cpu/arm926ejs/kirkwood/doimage/Makefile | 112 ++ cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h | 88 ++ cpu/arm926ejs/kirkwood/doimage/doimage | Bin 0 -> 17712 bytes
Never ever add binaries !!!
--- 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
Please get rid of these "cool" (actually stupid) macros.
+#ifndef __ASSEMBLY__ #ifndef BOOL_WAS_DEFINED #define BOOL_WAS_DEFINED typedef enum _bool{false,true} bool; #endif +#endif
/* Little to Big endian conversion macros */
Please also use standard macros here, and clean up these proprietary definitions.
diff --git a/cpu/arm926ejs/kirkwood/bin_dep.sh b/cpu/arm926ejs/kirkwood/bin_dep.sh new file mode 100755 index 0000000..1b36e91 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/bin_dep.sh
...
+TOP_DIR=`pwd` +CUR_DIR=$2 +BIN_FILE=$TOP_DIR/$1
+if [ "clean" == "$1" ]; then
- # erase created doimage utility
- rm -f $CUR_DIR/doimage/doimage
- exit 0
+fi
+if [ ! -f $BIN_FILE ]; then
- echo Error.. could not find $BIN_FILE
- exit 1
+else
- make -C $CUR_DIR/doimage
- exit 0
+fi
Please get rid of this. It doesn't for for out-of-tree builds anyway.
...
diff --git a/cpu/arm926ejs/kirkwood/doimage/Makefile b/cpu/arm926ejs/kirkwood/doimage/Makefile new file mode 100644 index 0000000..219ae1e --- /dev/null +++ b/cpu/arm926ejs/kirkwood/doimage/Makefile @@ -0,0 +1,112 @@
..
+BIN_FILES = doimage$(SFX)
+OBJ_LINKS = +OBJ_FILES = doimage.o
+LIBFDT_OBJ_FILES =
+#-------------------------------------------------------------------------
+HOSTARCH := $(shell uname -m | \
- sed -e s/i.86/i386/ \
-e s/sun4u/sparc64/ \
-e s/arm.*/arm/ \
-e s/sa110/arm/ \
-e s/powerpc/ppc/ \
-e s/Power\ Macintosh/ppc/ \
-e s/macppc/ppc/)
+HOSTOS := $(shell uname -s | tr A-Z a-z | \
- sed -e 's/(cygwin).*/cygwin/')
Why is this needed? You should get this from the top level Makefile.
+######################################################################### diff --git a/cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h b/cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h new file mode 100644 index 0000000..8782206 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h
Do you REEALLY need all this stuff?
Why? What is the rationale behind it?
Did I miss the documentation for it?
Apropos documentation... how about entries to the MAINTAINERS file, MAKEALL, etc. ?
...
+/* typedefs */
+typedef char s8; +typedef unsigned char u8;
+typedef int s32; +typedef unsigned int u32;
+typedef short s16; +typedef unsigned short u16;
+typedef long s64; +typedef unsigned long u64;
Why is theis needed? Please include the respexctive standard headers.
diff --git a/cpu/arm926ejs/kirkwood/doimage/doimage b/cpu/arm926ejs/kirkwood/doimage/doimage new file mode 100755 index 0000000000000000000000000000000000000000..9fee11740454ff880c081a64be0d692b1da4c19a GIT binary patch literal 17712 zcmcIse|%KcmA{h=Fd#ayQbf(l!zLA42nnP#P^kP$gccORAQmtT$%Gl3WMbxx1Q%-J zWR$m$X;~#*yJ8DU`*B;_;#LAEQxjlGw01XGYjJg3RMZ)RHtSDnquKBG-uEVNNWk`w zeSB{2Irp4<?m6e4d+vR2-s8^FC1oy`OW0SI$QH!5-{bZaqwb!oD8)h(9x+kmiYvr$
...
Never, never ever do this again.
diff --git a/cpu/arm926ejs/kirkwood/doimage/doimage.c b/cpu/arm926ejs/kirkwood/doimage/doimage.c new file mode 100644 index 0000000..0c484b2 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/doimage/doimage.c @@ -0,0 +1,1341 @@
Why is this needed?
...
+#define DOIMAGE_VERSION "1.00" +void print_usage(void); +int f_in = -1; +int f_out = -1; +int f_header = -1; +typedef enum { IMG_SATA, IMG_UART, IMG_FLASH, IMG_BOOTROM, IMG_NAND, IMG_HEX,
- IMG_BIN, IMG_PEX, IMG_I2C
+} IMG_TYPE; +typedef enum { HDR_IMG_ONE_FILE = 1, /* Create one file with header and image */
- HDR_IMG_TWO_FILES = 2, /* Create seperate header and image files */
- HDR_ONLY = 3, /* Create only header */
- IMG_ONLY = 4 /* Create only image */
+} HEADER_MODE;
Why do you have to reinvent your own image format here?
U-Boot already has a prtty powerful and flexible format - uns this. [Keep in mind that one day you want to add this to Linux, too. RMK will be much more draconic about such stuff than me.]
+/* 8 bit checksum */ +u8 checksum8(void *start, u32 len, u8 csum)
...
+/* 32 bit checksum */ +u32 checksum32(void *start, u32 len, u32 csum)
...
+void make_crc_table(u32 * crc_table)
No, no, no. You really re-invent all parts of the wheel.
Stop here. Don't. NAK.
...
+void print_usage(void) +{
- printf("\n");
- printf("Marvell doimage Tool version %s\n", DOIMAGE_VERSION);
- printf("Supported SoC devices: \n");
- printf(" Marvell 88F6082 - A1\n");
- printf(" Marvell 88F6180 - A0\n");
- printf(" Marvell 88F6192 - A0\n");
- printf(" Marvell 88F6190 - A0\n");
- printf(" Marvell 88F6281 - A0\n");
- printf("\n");
- printf("usage: \n");
- printf
("doimage <must_options> [other_options] image_in image_out [header_out]\n");
- printf("\n<must_options> - can be one or more of the following:\n\n");
- printf("-T image_type: sata\uart\flash\bootrom\nand\hex\pex\n");
- printf(" if image_type is sata, the image_out will\n");
- printf(" include header only.\n");
- printf("-D image_dest: image destination in dram (in hex)\n");
- printf("-E image_exec: execution address in dram (in hex)\n");
- printf
(" if image_type is 'flash' and image_dest is 0xffffffff\n");
- printf(" then execution address on the flash\n");
- printf
("-S image_source: if image_type is sata then the starting sector of\n");
- printf
(" the source image on the disk - mandatory for sata\n");
- printf
(" if image_type is flash\\nand then the starting offset of\n");
- printf
(" the source image at the flash - optional for flash\\nand\n");
- printf("-W hex_width : HEX file width, can be 8,16,32,64 \n");
- printf
("-M twsi_file: ascii file name that contains the I2C init regs set by h/w.\n");
- printf(" this is used in i2c boot only\n");
- printf
("\n<other_options> - optional and can be one or more of the following:\n\n");
- printf
("-R dram_file: ascii file name that contains the list of dram regs\n");
- printf("-P nand_page_size (decimal 512, 2048, ..): NAND Page size\n");
- printf("-C nand_ecc_mode (1=Hamming, 2=RS, 3=None)\n");
- printf("-L delay in mili seconds before DRAM init\n");
- printf("-I copy image in PIO mode (valid for SATA only)\n");
- printf("-X pre_padding_size (hex)\n");
- printf("-Y post_padding_size (hex)\n");
- printf("-H header_mode: Header mode, can be:\n");
- printf
(" -H 1 :will create one file (image_out) for header and image\n");
- printf
(" -H 2 :will create two files, (image_out) for image , (header_out) for header\n");
- printf(" -H 3 :will create one file (image_out) for header only \n");
- printf(" -H 4 :will create one file (image_out) for image only \n");
- printf("\ncommand possibilities: \n\n");
- printf("doimage -T hex -W width image_in image_out\n");
- printf("doimage -T bootrom image_in image_out\n");
- printf("doimage -T sata -S sector -D image_dest -E image_exec\n");
- printf(" [other_options] image_in image_out header_out\n\n");
- printf("doimage -T flash -D image_dest -E image_exec [-S address]\n");
- printf(" [other_options] image_in image_out\n\n");
- printf("doimage -T pex -D image_dest -E image_exec \n");
- printf(" [other_options] image_in image_out\n\n");
- printf
("doimage -T nand -D image_dest -E image_exec [-S address] -P page_size\n");
- printf(" [other_options] image_in image_out\n\n");
- printf("doimage -T uart -D image_dest -E image_exec\n");
- printf(" [other_options] image_in image_out\n\n");
- printf("doimage -T pex -D image_dest -E image_exec \n");
- printf(" [other_options] image_in image_out\n\n");
- printf
("doimage -T i2c -D image_dest -E image_exec -M twsi_init_file\n");
- printf(" [other_options] image_in image_out\n\n");
- printf("\n\n\n");
Instead of splitting this into a zillion or printf() statements (where puts() would be sifficient, too), just feed the text into one statement.
But anyway - I think you need to re-think this concept.
Such code has zero chance to go into mainline - not this image building code, and not the U-Boot implementation that obviusly requires that.
diff --git a/cpu/arm926ejs/kirkwood/dram.c b/cpu/arm926ejs/kirkwood/dram.c new file mode 100644 index 0000000..41f1316 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/dram.c
...
+u32 kw_get_dram_bank_base_addr(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));
Here and everywhere: do not access any device registers based on address plus offset. Provide proper C structures instead, and access the struct elements so the compiler can perform appropriate type checking.
And please do not re-invent your own private accessor macros / functions.
+u32 kw_get_dram_bank_size(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;
Consider to auto-size the RAM ionstead of using static information from some registers (which may or may not be correct).
+/*
- Generates Ramdom hex number reading some time varient system registers
- and using md5 algorithm
- */
+unsigned char get_random_hex(void) +{
You probably want to make this optional, so it can be omitted. Always requesting the full md5 code just to get some random numbers is a lot of overhead.
BTW - what do you need random numbers for in U-Boot? Nobody else needs this...
...
- return KW_OK;
Here and everywhere: please write readable code and avoid custom macros like these.
...
- debug_print_ftrace();
- /*CPU streaming & write allocate */
- env = getenv("enaWrAllo");
Documentation for all these variables missing.
Please use readable / writable variable names. CamelCase is strongly deprecated.
- /* Verify write allocate and streaming */
- printf("\n");
- __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0":"=r"(temp));
- if (temp & BIT29)
info_print("Streaming enabled");
- else
info_print("Streaming disabled");
- if (temp & BIT28)
info_print("Write allocate enabled");
- else
info_print("Write allocate disabled");
Yet another set of proprietary functions. Get rid of these!
diff --git a/cpu/arm926ejs/kirkwood/kwcore.h b/cpu/arm926ejs/kirkwood/kwcore.h new file mode 100644 index 0000000..0ddc6a8 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.h @@ -0,0 +1,141 @@
...
+/* 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)
...
Use C structures instead of offset tables!
+/*
- 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))))
Do not reinvent the wheel, do not pollute the code with tons of redundand proprietary versions of maros that exist elsewhere.
+#define KW_REG_READ_ASM(toReg, tmpReg, regOffs) \
ldr tmpReg, =KW_REGISTER(regOffs); \
ldr toReg, [tmpReg]; \
Indentation not by TAB. Please fix globally.
--- /dev/null +++ b/cpu/arm926ejs/kirkwood/serial.c
...
+/* 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;
NAK.
We will definiteli not accept yet another version of 16550 compatible UART register definitions. Please use the existing code (but wait until Detlev Zundel's cleanup patch from today has been applied).
...
diff --git a/cpu/arm926ejs/kirkwood/spi.c b/cpu/arm926ejs/kirkwood/spi.c new file mode 100644 index 0000000..a334d95 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/spi.c
...
- /*
* handle data in 8-bit chunks
* TBD: 2byte xfer mode to be enabled
*/
- while (bitlen > 4) {
debug_print("loopstart bitlen %d\n", bitlen);
tmpdout = 0;
if (1) { //bitlen <= 8) {
No C++ comments, please (fix globally).
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
...
+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;
Indentation not by TAB. Please check and fix globally.
diff --git a/include/configs/kirkwood.h b/include/configs/kirkwood.h new file mode 100644 index 0000000..eec04c2 --- /dev/null +++ b/include/configs/kirkwood.h @@ -0,0 +1,46 @@ +/*
- (C) Copyright 2009
- Marvell Semiconductor <www.marvell.com>
- Prafulla Wadaskar prafulla@marvell.com
- Header file for the Marvell's Feroceon CPU core.
NAK.
The include/configs/ directory is for board configuration files only.
CPU specific code has no place there.
Best regards,
Wolfgang Denk

From: prafulla_wadaskar prafulla@marvell.com
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com --- cpu/arm926ejs/kirkwood/Makefile | 1 + cpu/arm926ejs/kirkwood/egiga.c | 2169 +++++++++++++++++++++++++++++++++++ cpu/arm926ejs/kirkwood/egiga.h | 707 ++++++++++++ cpu/arm926ejs/kirkwood/egiga_regs.h | 161 +++ cpu/arm926ejs/kirkwood/kwcore.h | 2 + net/eth.c | 4 + 6 files changed, 3044 insertions(+), 0 deletions(-) create mode 100644 cpu/arm926ejs/kirkwood/egiga.c create mode 100644 cpu/arm926ejs/kirkwood/egiga.h create mode 100644 cpu/arm926ejs/kirkwood/egiga_regs.h
diff --git a/cpu/arm926ejs/kirkwood/Makefile b/cpu/arm926ejs/kirkwood/Makefile index 41ac8d7..3e20898 100644 --- a/cpu/arm926ejs/kirkwood/Makefile +++ b/cpu/arm926ejs/kirkwood/Makefile @@ -30,6 +30,7 @@ COBJS-y = timer.o COBJS-y += serial.o COBJS-y += kwcore.o COBJS-y += dram.o +COBJS-y += egiga.o COBJS-$(CONFIG_KIRKWOOD_SPI) += spi.o
SOBJS = soc_init.o diff --git a/cpu/arm926ejs/kirkwood/egiga.c b/cpu/arm926ejs/kirkwood/egiga.c new file mode 100644 index 0000000..609ee0c --- /dev/null +++ b/cpu/arm926ejs/kirkwood/egiga.c @@ -0,0 +1,2169 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Prafulla Wadaskar prafulla@marvell.com + * + * (C) Copyright 2003 + * Ingo Assmus ingo.assmus@keymile.com + * + * based on - Driver for MV64360X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 + */ + +/* + * mv_eth.c - header file for the polled mode GT ethernet driver + */ +#ifndef KWEGIGA_DEBUG +#define KWEGIGA_DEBUG 0 +#endif +#define DEBUG_PRINT KWEGIGA_DEBUG + +#include <common.h> +#include <net.h> +#include <malloc.h> +#include <debug_prints.h> +#include <../board/Marvell/common/ppc_error_no.h> + +#if defined (CONFIG_KIRKWOOD_EGIGA) + +/* In case SRAM is cache coherent or non-cacheable */ +#define CONFIG_NOT_COHERENT_CACHE +#define D_CACHE_FLUSH_LINE(addr, offset) ; +#define CPU_PIPE_FLUSH { __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop");} + +#include "egiga.h" + +/* PHY_BASE_ADR is board specific and can be configured */ +#if defined (CONFIG_PHY_BASE_ADR) +#define PHY_BASE_ADR CONFIG_PHY_BASE_ADR +#else +#define PHY_BASE_ADR 0x08 /* default phy base addr */ +#endif + +/************************************************************************* +* The first part is the high level driver of the gigE ethernet ports. * +*************************************************************************/ + +/* Definition for configuring driver */ +#undef UPDATE_STATS_BY_SOFTWARE + +/* Constants */ +#define MAGIC_ETH_RUNNING 8031971 +#define KW_INTERNAL_SRAM_SIZE _256K +#define EXTRA_BYTES 32 +#define WRAP ETH_HLEN + 2 + 4 + 16 +#define BUFFER_MTU dev->mtu + WRAP +#define INT_CAUSE_UNMASK_ALL 0x0007ffff +#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff +#ifdef KW_RX_FILL_ON_TASK +#define INT_CAUSE_MASK_ALL 0x00000000 +#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL +#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT +#endif + +/* + * PHY link detection and printing is not a dependency of egiga controller + * By default phy link is assumed to be UP + * if you want to detect link by querying phy then, + * configure CONFIG_PHY_LINK_DETECT in board header file + * and provide these functions in board specific code + */ +#ifndef CONFIG_PHY_LINK_DETECT +#define eth_phy_link_status(x) (TRUE) +#define egiga_print_phy_status(x) +#else +static bool eth_phy_link_status(ETH_PORT prt_num); +static void egiga_print_phy_status(struct eth_device *dev); +#endif + +/* + * eth_smi_reg_read - Read from ethernet phy register. + * + * INPUT: + * @phy_adr - Phy address. + * @reg_ofs - Phy register offset. + * + * This function reads ethernet phy register. + * REturns 16bit phy register value, or 0xffff on error + */ +int eth_smi_reg_read(u32 eth_port_num, u32 phy_adr, u32 reg_ofs, u16 * data) +{ + u32 smi_reg; + volatile u32 timeout; + + /* check parameters */ + if ((phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) { + error_print("Illegal PHY device address %d", phy_adr); + return -EFAULT; + } + if ((reg_ofs << KW_ETH_SMI_REG_ADDR_OFFS) & ~KW_ETH_SMI_REG_ADDR_MASK) { + error_print("Illegal PHY register offset %d", reg_ofs); + return -EFAULT; + } + + timeout = ETH_PHY_SMI_TIMEOUT; + /* wait till the SMI is not busy */ + do { + /* read smi register */ + smi_reg = KW_REG_READ(KW_ETH_SMI_REG(eth_port_num)); + if (timeout-- == 0) { + error_print("SMI busy timeout"); + return -EFAULT; + } + } while (smi_reg & ETH_PHY_SMI_BUSY_MASK); + + /* fill the phy address and regiser offset and read opcode */ + smi_reg = + (phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) | (reg_ofs << + KW_ETH_SMI_REG_ADDR_OFFS) + | ETH_PHY_SMI_OPCODE_READ; + + /* write the smi register */ + KW_REG_WRITE(KW_ETH_SMI_REG(eth_port_num), smi_reg); + + timeout = ETH_PHY_SMI_TIMEOUT; + + /*wait till readed value is ready */ + do { + /* read smi register */ + smi_reg = KW_REG_READ(KW_ETH_SMI_REG(eth_port_num)); + + if (timeout-- == 0) { + error_print("SMI read-valid timeout"); + return -EFAULT; + } + } while (!(smi_reg & ETH_PHY_SMI_READ_VALID_MASK)); + + /* Wait for the data to update in the SMI register */ + for (timeout = 0; timeout < ETH_PHY_SMI_TIMEOUT; timeout++) ; + + *data = + (u16) (KW_REG_READ(KW_ETH_SMI_REG(eth_port_num)) & + ETH_PHY_SMI_DATA_MASK); + + debug_print8("Reg(phyadr %d, off %d) Phy-value = %04x", phy_adr, + reg_ofs, *data); + + return 0; +} + +/* + * eth_smi_reg_write - Write to ethernet phy register. + * + * @phy_adr - Phy address. + * @reg_ofs - Phy register offset. + * @data - 16bit data. + * + * This function write to ethernet phy register. + * Returns 0 if write succeed, -EINVAL on bad parameters , MV_ERROR on error . + * -ETIME on timeout + */ +int eth_smi_reg_write(u32 eth_port_num, u32 phy_adr, u32 reg_ofs, u16 data) +{ + u32 smi_reg; + volatile u32 timeout; + + /* check parameters */ + if ((phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) { + error_print("Illegal phy address"); + return -EINVAL; + } + if ((reg_ofs << KW_ETH_SMI_REG_ADDR_OFFS) & ~KW_ETH_SMI_REG_ADDR_MASK) { + error_print("Illegal register offset"); + return -EINVAL; + } + + timeout = ETH_PHY_SMI_TIMEOUT; + + /* wait till the SMI is not busy */ + do { + /* read smi register */ + smi_reg = KW_REG_READ(KW_ETH_SMI_REG(eth_port_num)); + if (timeout-- == 0) { + error_print("SMI busy timeout"); + return -ETIME; + } + } while (smi_reg & ETH_PHY_SMI_BUSY_MASK); + + /* fill the phy address and regiser offset and write opcode and data */ + smi_reg = (data << ETH_PHY_SMI_DATA_OFFS); + smi_reg |= + (phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) | (reg_ofs << + KW_ETH_SMI_REG_ADDR_OFFS); + smi_reg &= ~ETH_PHY_SMI_OPCODE_READ; + + /* write the smi register */ + KW_REG_WRITE(KW_ETH_SMI_REG(eth_port_num), smi_reg); + + return 0; + +} + +static int egiga_free_tx_rings(struct eth_device *dev) +{ + u32 queue; + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + u32 port_num; + volatile ETH_TX_DESC *p_tx_curr_desc; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop Tx Queues */ + KW_REG_WRITE(KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00); + + /* Free TX rings */ + debug_print("Clearing previously allocated TX queues... "); + for (queue = 0; queue < KW_TX_QUEUE_NUM; queue++) { + /* Free on TX rings */ + for (p_tx_curr_desc = + ethernet_private->p_tx_desc_area_base[queue]; + ((u32)p_tx_curr_desc <= (u32) + ethernet_private->p_tx_desc_area_base[queue] + + ethernet_private->tx_desc_area_size[queue]); + p_tx_curr_desc = + (ETH_TX_DESC *) ((u32)p_tx_curr_desc + + TX_DESC_ALIGNED_SIZE)) { + /* this is inside for loop */ + if (p_tx_curr_desc->return_info != 0) { + p_tx_curr_desc->return_info = 0; + debug_print("freed"); + } + } + debug_print("Done"); + } + return 0; +} + +static int egiga_free_rx_rings(struct eth_device *dev) +{ + u32 queue; + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + u32 port_num; + volatile ETH_RX_DESC *p_rx_curr_desc; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + + /* Stop RX Queues */ + KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00); + + /* Free RX rings */ + debug_print("Clearing previously allocated RX queues... "); + for (queue = 0; queue < KW_RX_QUEUE_NUM; queue++) { + /* Free preallocated skb's on RX rings */ + for (p_rx_curr_desc = + ethernet_private->p_rx_desc_area_base[queue]; + (((u32)p_rx_curr_desc < + ((u32)ethernet_private-> + p_rx_desc_area_base[queue] + + ethernet_private->rx_desc_area_size[queue]))); + p_rx_curr_desc = + (ETH_RX_DESC *) ((u32)p_rx_curr_desc + + RX_DESC_ALIGNED_SIZE)) { + if (p_rx_curr_desc->return_info != 0) { + p_rx_curr_desc->return_info = 0; + debug_print("freed"); + } + } + debug_print("Done"); + } + return 0; +} + +static void eth_phy_set_addr(ETH_PORT eth_port_num, int phy_addr) +{ + KW_REG_WRITE(KW_ETH_PHY_ADDR_REG(eth_port_num), phy_addr); +} + +#ifdef UPDATE_STATS_BY_SOFTWARE +/********************************************************************** + * egiga_print_stat + * + * Update the statistics structure in the private data structure + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ + +static void egiga_print_stat(struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + struct net_device_stats *stats; + u32 port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + /* These are false updates */ + printf("\n### Network statistics: ###\n"); + printf("--------------------------\n"); + printf(" Packets received: %ld\n", stats->rx_packets); + printf(" Packets send: %ld\n", stats->tx_packets); + printf(" Received bytes: %ld\n", stats->rx_bytes); + printf(" Send bytes: %ld\n", stats->tx_bytes); + if (stats->rx_errors != 0) + printf(" Rx Errors: %ld\n", + stats->rx_errors); + if (stats->rx_dropped != 0) + printf(" Rx dropped (CRC Errors): %ld\n", + stats->rx_dropped); + if (stats->multicast != 0) + printf(" Rx mulicast frames: %ld\n", + stats->multicast); + if (stats->collisions != 0) + printf(" No. of collisions: %ld\n", + stats->collisions); + if (stats->rx_length_errors != 0) + printf(" Rx length errors: %ld\n", + stats->rx_length_errors); +} +#endif + +/* Helper function for egiga_stop */ +static int egiga_real_stop(struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + u32 port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + + egiga_free_tx_rings(dev); + egiga_free_rx_rings(dev); + + eth_port_reset(ethernet_private->port_num); + /* Disable ethernet port interrupts */ + KW_REG_WRITE(KW_ETH_INTERRUPT_CAUSE_REG(port_num), 0); + KW_REG_WRITE(KW_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); + /* Mask RX buffer and TX end interrupt */ + KW_REG_WRITE(KW_ETH_INTERRUPT_MASK_REG(port_num), 0); + /* Mask phy and link status changes interrupts */ + KW_REG_WRITE(KW_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0); + /* make sure CPU interrupts are disabled + KW_REG_BITS_RESET (KW_INTERRUPT0_MASK_HIGH(port_num), + BIT0 << port_num); + */ + + /* Print Network statistics */ +#ifdef UPDATE_STATS_BY_SOFTWARE + /* + * Print statistics (only if ethernet is running), + * then zero all the stats fields in memory + */ + if (port_private->eth_running == MAGIC_ETH_RUNNING) { + port_private->eth_running = 0; + egiga_print_stat(dev); + } + memset(port_private->stats, 0, sizeof(struct net_device_stats)); +#endif + debug_print("Ethernet stopped ... "); + return 0; +} + +/********************************************************************** + * kw_egiga_stop + * + * This function is used when closing the network device. + * It updates the hardware, + * release all memory that holds buffers and descriptors and release the IRQ. + * Input : a pointer to the device structure + * Output : zero if success , nonzero if fails + *********************************************************************/ + +int kw_egiga_stop(struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + u32 port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + + debug_print_ftrace(); + /* Disable all gigE address decoder */ + KW_REG_WRITE(KW_ETH_BASE_ADDR_ENABLE_REG(port_num), 0x3f); + egiga_real_stop(dev); + + return 0; +} + +/******************************************************************************* +* eth_clear_mib_counters - Clear all MIB counters +* +* DESCRIPTION: +* This function clears all MIB counters of a specific ethernet port. +* A read from the MIB counter will reset the counter. +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* +* OUTPUT: +* After reading all MIB counters, the counters resets. +* +* RETURN: +* MIB counter value. +* +*******************************************************************************/ +static void eth_clear_mib_counters(ETH_PORT eth_port_num) +{ + int i; + u32 dummy; + + /* Perform dummy reads from MIB counters */ + for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; + i += 4) + dummy = KW_REG_READ((KW_ETH_MIB_COUNTERS_BASE + (eth_port_num) + i)); + + return; +} + +/******************************************************************************* +* eth_read_mib_counter - Read a MIB counter +* +* DESCRIPTION: +* This function reads a MIB counter of a specific ethernet port. +* NOTE - If read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, then the +* following read must be from ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH +* register. The same applies for ETH_MIB_GOOD_OCTETS_SENT_LOW and +* ETH_MIB_GOOD_OCTETS_SENT_HIGH +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* u32 mib_offset MIB counter offset (use ETH_MIB_... macros). +* +* OUTPUT: +* After reading the MIB counter, the counter resets. +* +* RETURN: +* MIB counter value. +* +*******************************************************************************/ +u32 eth_read_mib_counter(ETH_PORT eth_port_num, + u32 mib_offset) +{ + return (KW_REG_READ((KW_ETH_MIB_COUNTERS_BASE(eth_port_num) + + mib_offset))); +} + + +/********************************************************************** + * egiga_update_stat + * + * Update the statistics structure in the private data structure + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + **********************************************************************/ + +static void egiga_update_stat(struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + struct net_device_stats *stats; + u32 port_num; + volatile u32 dummy; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + /* These are false updates */ + stats->rx_packets += (unsigned long) + eth_read_mib_counter(ethernet_private->port_num, + ETH_MIB_GOOD_FRAMES_RECEIVED); + stats->tx_packets += (unsigned long) + eth_read_mib_counter(ethernet_private->port_num, + ETH_MIB_GOOD_FRAMES_SENT); + stats->rx_bytes += (unsigned long) + eth_read_mib_counter(ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_RECEIVED_LOW); + /* + * Ideally this should be as follows - + * + * stats->rx_bytes += stats->rx_bytes + + * ((unsigned long) ethReadMibCounter (ethernet_private->port_num , + * ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH) << 32); + * + * But the unsigned long in PowerPC and MIPS are 32bit. So the next read + * is just a dummy read for proper work of the GigE port + */ + dummy = eth_read_mib_counter(ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH); + stats->tx_bytes += (unsigned long) + eth_read_mib_counter(ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_SENT_LOW); + dummy = eth_read_mib_counter(ethernet_private->port_num, + ETH_MIB_GOOD_OCTETS_SENT_HIGH); + stats->rx_errors += (unsigned long) + eth_read_mib_counter(ethernet_private->port_num, + ETH_MIB_MAC_RECEIVE_ERROR); + + /* Rx dropped is for received packet with CRC error */ + stats->rx_dropped += + (unsigned long)eth_read_mib_counter(ethernet_private-> + port_num, + ETH_MIB_BAD_CRC_EVENT); + stats->multicast += (unsigned long) + eth_read_mib_counter(ethernet_private->port_num, + ETH_MIB_MULTICAST_FRAMES_RECEIVED); + stats->collisions += + (unsigned long)eth_read_mib_counter(ethernet_private-> + port_num, + ETH_MIB_COLLISION) + + (unsigned long)eth_read_mib_counter(ethernet_private-> + port_num, + ETH_MIB_LATE_COLLISION); + /* detailed rx errors */ + stats->rx_length_errors += + (unsigned long)eth_read_mib_counter(ethernet_private-> + port_num, + ETH_MIB_UNDERSIZE_RECEIVED) + + + (unsigned long)eth_read_mib_counter(ethernet_private-> + port_num, + ETH_MIB_OVERSIZE_RECEIVED); + /* detailed tx errors */ +} + +/********************************************************************** + * egiga_get_stats + * + * Returns a pointer to the interface statistics. + * + * Input : dev - a pointer to the required interface + * + * Output : a pointer to the interface's statistics + **********************************************************************/ + +static struct net_device_stats *egiga_get_stats(struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + u32 port_num; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + + egiga_update_stat(dev); + + return port_private->stats; +} + +/************************************************************************* +* The second part is the low level driver of the gigE ethernet ports. * +*************************************************************************/ + +/* defines */ +/* SDMA command macros */ +#define ETH_ENABLE_TX_QUEUE(tx_queue, eth_port) \ + KW_REG_WRITE(KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), (1 << tx_queue)) + +#define CURR_RFD_GET(p_curr_desc, queue) \ + ((p_curr_desc) = p_eth_port_ctrl->p_rx_curr_desc_q[queue]) + +#define CURR_RFD_SET(p_curr_desc, queue) \ + (p_eth_port_ctrl->p_rx_curr_desc_q[queue] = (p_curr_desc)) + +#define USED_RFD_GET(p_used_desc, queue) \ + ((p_used_desc) = p_eth_port_ctrl->p_rx_used_desc_q[queue]) + +#define USED_RFD_SET(p_used_desc, queue)\ +(p_eth_port_ctrl->p_rx_used_desc_q[queue] = (p_used_desc)) + +#define CURR_TFD_GET(p_curr_desc, queue) \ + ((p_curr_desc) = p_eth_port_ctrl->p_tx_curr_desc_q[queue]) + +#define CURR_TFD_SET(p_curr_desc, queue) \ + (p_eth_port_ctrl->p_tx_curr_desc_q[queue] = (p_curr_desc)) + +#define USED_TFD_GET(p_used_desc, queue) \ + ((p_used_desc) = p_eth_port_ctrl->p_tx_used_desc_q[queue]) + +#define USED_TFD_SET(p_used_desc, queue) \ + (p_eth_port_ctrl->p_tx_used_desc_q[queue] = (p_used_desc)) + +#define FIRST_TFD_GET(p_first_desc, queue) \ + ((p_first_desc) = p_eth_port_ctrl->p_tx_first_desc_q[queue]) + +#define FIRST_TFD_SET(p_first_desc, queue) \ + (p_eth_port_ctrl->p_tx_first_desc_q[queue] = (p_first_desc)) + +/* Macros that save access to desc in order to find next desc pointer */ +#define RX_NEXT_DESC_PTR(p_rx_desc, queue) ( \ + ETH_RX_DESC*)(((((u32)p_rx_desc - \ + (u32)p_eth_port_ctrl->p_rx_desc_area_base[queue]) + \ + RX_DESC_ALIGNED_SIZE) % p_eth_port_ctrl->rx_desc_area_size[queue]) + \ + (u32)p_eth_port_ctrl->p_rx_desc_area_base[queue]) + +#define TX_NEXT_DESC_PTR(p_tx_desc, queue) ( \ + ETH_TX_DESC*)(((((u32)p_tx_desc - \ + (u32)p_eth_port_ctrl->p_tx_desc_area_base[queue]) + \ + TX_DESC_ALIGNED_SIZE) % p_eth_port_ctrl->tx_desc_area_size[queue]) + \ + (u32)p_eth_port_ctrl->p_tx_desc_area_base[queue]) + +/******************************************************************************* + * eth_set_access_control - Config address decode parameters for Ethernet unit + * + * DESCRIPTION: + * This function configures the address decode parameters for the Gigabit + * Ethernet Controller according the given parameters struct. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * ETH_WIN_PARAM *param Address decode parameter struct. + * + * OUTPUT: + * An access window is opened using the given access parameters. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_set_access_control(ETH_PORT eth_port_num, ETH_WIN_PARAM * param) +{ + u32 access_prot_reg; + + debug_print_ftrace(); + /* Set access control register */ + access_prot_reg = KW_REG_READ(KW_ETH_ACCESS_PROTECTION_REG + (eth_port_num)); + access_prot_reg &= (~(3 << (param->win * 2))); /* clear window permission */ + access_prot_reg |= (param->access_ctrl << (param->win * 2)); + KW_REG_WRITE(KW_ETH_ACCESS_PROTECTION_REG(eth_port_num), + access_prot_reg); + + /* Set window Size reg (SR) */ + KW_REG_WRITE((KW_ETH_SIZE_REG_0(eth_port_num) + + (ETH_SIZE_REG_GAP * param->win)), + (((param->size / 0x10000) - 1) << 16)); + + /* Set window Base address reg (BA) */ + KW_REG_WRITE((KW_ETH_BAR_0(eth_port_num) + (ETH_BAR_GAP * param->win)), + (param->target | param->attributes | param->base_addr)); + /* High address remap reg (HARR) */ + if (param->win < 4) + KW_REG_WRITE((KW_ETH_HIGH_ADDR_REMAP_REG_0(eth_port_num) + + (ETH_HIGH_ADDR_REMAP_REG_GAP * param->win)), + param->high_addr); + + /* Base address enable reg (BARER) */ + if (param->enable == 1) + KW_REG_BITS_RESET(KW_ETH_BASE_ADDR_ENABLE_REG(eth_port_num), + (1 << param->win)); + else + KW_REG_BITS_SET(KW_ETH_BASE_ADDR_ENABLE_REG(eth_port_num), + (1 << param->win)); +} + +static void eth_set_access_control_for_dram(u32 port_num) +{ + ETH_WIN_PARAM win_param; + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + /* Set access parameters for DRAM bank i */ + win_param.win = i; /* Use Ethernet window i */ + win_param.target = ETH_TARGET_DRAM; /* Window target - DDR */ + win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */ + win_param.high_addr = 0; + /* Get bank base */ + win_param.base_addr = kw_get_dram_bank_base_addr(i); + win_param.size = kw_get_dram_bank_size(i); /* Get bank size */ + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + switch(i) { + case 0: + /* Enable DRAM bank 0 */ + win_param.attributes = EBAR_ATTR_DRAM_CS0; + break; + case 1: + /* Enable DRAM bank 1 */ + win_param.attributes = EBAR_ATTR_DRAM_CS1; + break; + case 2: + /* Enable DRAM bank 2 */ + win_param.attributes = EBAR_ATTR_DRAM_CS2; + break; + case 3: + /* Enable DRAM bank 3 */ + win_param.attributes = EBAR_ATTR_DRAM_CS3; + break; + default: + /* invalide bank, disable access */ + win_param.enable = 0; + win_param.attributes = 0; + break; + } +#ifndef CONFIG_NOT_COHERENT_CACHE + win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB; +#endif + /* Set the access control for address window (EPAPR) READ & WRITE */ + eth_set_access_control(port_num, &win_param); + } +} + +/******************************************************************************* +* eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables +* +* DESCRIPTION: +* Go through all the DA filter tables (Unicast, Special Multicast & Other +* Multicast) and set each entry to 0. +* +* INPUT: +* ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. +* +* OUTPUT: +* Multicast and Unicast packets are rejected. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void eth_port_init_mac_tables(ETH_PORT eth_port_num) +{ + int table_index; + + /* Clear DA filter unicast table (Ex_dFUT) */ + for (table_index = 0; table_index <= 0xC; table_index += 4) + KW_REG_WRITE((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + table_index), 0); + + for (table_index = 0; table_index <= 0xFC; table_index += 4) { + /* Clear DA filter special multicast table (Ex_dFSMT) */ + KW_REG_WRITE((KW_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE + (eth_port_num) + table_index), 0); + /* Clear DA filter other multicast table (Ex_dFOMT) */ + KW_REG_WRITE((KW_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE + (eth_port_num) + table_index), 0); + } +} + +/******************************************************************************* +* eth_port_init - Initialize the Ethernet port driver +* +* DESCRIPTION: +* This function prepares the ethernet port to start its activity: +* 1) Completes the ethernet port driver struct initialization toward port +* start routine. +* 2) Resets the device to a quiescent state in case of warm reboot. +* 3) Enable SDMA access to all four DRAM banks as well as internal SRAM. +* 4) Clean MAC tables. The reset status of those tables is unknown. +* 5) Set PHY address. +* Note: Call this routine prior to eth_port_start routine and after setting +* user values in the user fields of Ethernet port control struct (i.e. +* port_phy_addr). +* +* INPUT: +* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct +* +* OUTPUT: +* See description. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void eth_port_init(ETH_PORT_INFO * p_eth_port_ctrl) +{ + int queue; + u32 port_num = p_eth_port_ctrl->port_num; + + p_eth_port_ctrl->port_config = PORT_CONFIG_VALUE; + p_eth_port_ctrl->port_config_extend = PORT_CONFIG_EXTEND_VALUE; + p_eth_port_ctrl->port_sdma_config = PORT_SDMA_CONFIG_VALUE; + p_eth_port_ctrl->port_serial_control = PORT_SERIAL_CONTROL_VALUE; + + p_eth_port_ctrl->port_rx_queue_command = 0; + p_eth_port_ctrl->port_tx_queue_command = 0; + + /* Stop RX Queues */ + KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00); + + /* Clear the ethernet port interrupts */ + KW_REG_WRITE(KW_ETH_INTERRUPT_CAUSE_REG(port_num), 0); + KW_REG_WRITE(KW_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); + + /* Unmask RX buffer and TX end interrupt */ + KW_REG_WRITE(KW_ETH_INTERRUPT_MASK_REG(port_num), INT_CAUSE_UNMASK_ALL); + + /* Unmask phy and link status changes interrupts */ + KW_REG_WRITE(KW_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), + INT_CAUSE_UNMASK_ALL_EXT); + + /* Zero out SW structs */ + for (queue = 0; queue < MAX_RX_QUEUE_NUM; queue++) { + CURR_RFD_SET((ETH_RX_DESC *) 0x00000000, queue); + USED_RFD_SET((ETH_RX_DESC *) 0x00000000, queue); + p_eth_port_ctrl->rx_resource_err[queue] = false; + } + + for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) { + CURR_TFD_SET((ETH_TX_DESC *) 0x00000000, queue); + USED_TFD_SET((ETH_TX_DESC *) 0x00000000, queue); + FIRST_TFD_SET((ETH_TX_DESC *) 0x00000000, queue); + p_eth_port_ctrl->tx_resource_err[queue] = false; + } + + eth_port_reset(port_num); + + eth_set_access_control_for_dram(port_num); + + eth_port_init_mac_tables(port_num); +} + + +/******************************************************************************* +* eth_port_start - Start the Ethernet port activity. +* +* DESCRIPTION: +* This routine prepares the Ethernet port for Rx and Tx activity: +* 1. Initialize Tx and Rx Current Descriptor Pointer for each queue that +* has been initialized a descriptor's ring (using kw_egiga_init_tx_desc_ring +* for Tx and kw_egiga_init_rx_desc_ring for Rx) +* 2. Initialize and enable the Ethernet configuration port by writing to +* the port's configuration and command registers. +* 3. Initialize and enable the SDMA by writing to the SDMA's +* configuration and command registers. +* After completing these steps, the ethernet port SDMA can starts to +* perform Rx and Tx activities. +* +* Note: Each Rx and Tx queue descriptor's list must be initialized prior +* to calling this function (use kw_egiga_init_tx_desc_ring for Tx queues and +* kw_egiga_init_rx_desc_ring for Rx queues). +* +* INPUT: +* ETH_PORT_INFO *p_eth_port_ctrl Ethernet port control struct +* +* OUTPUT: +* Ethernet port is ready to receive and transmit. +* +* RETURN: +* false if the port PHY is not up. +* true otherwise. +* +*******************************************************************************/ +static void eth_port_start(ETH_PORT_INFO * p_eth_port_ctrl) +{ + int queue; + volatile ETH_TX_DESC *p_tx_curr_desc; + volatile ETH_RX_DESC *p_rx_curr_desc; + ETH_PORT eth_port_num = p_eth_port_ctrl->port_num; + + /* Assignment of Tx CTRP of given queue */ + for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) { + CURR_TFD_GET(p_tx_curr_desc, queue); + KW_REG_WRITE((KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num) + + (4 * queue)), ((u32)p_tx_curr_desc)); + + } + + /* Assignment of Rx CRDB of given queue */ + for (queue = 0; queue < MAX_RX_QUEUE_NUM; queue++) { + CURR_RFD_GET(p_rx_curr_desc, queue); + KW_REG_WRITE((KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num) + + (4 * queue)), ((u32)p_rx_curr_desc)); + + if (p_rx_curr_desc != NULL) + /* Add the assigned Ethernet address to the port's address table */ + eth_port_uc_addr_set(p_eth_port_ctrl->port_num, + p_eth_port_ctrl->port_mac_addr, + queue); + } + + /* Assign port configuration and command. */ + KW_REG_WRITE(KW_ETH_PORT_CONFIG_REG(eth_port_num), + p_eth_port_ctrl->port_config); + + KW_REG_WRITE(KW_ETH_PORT_CONFIG_EXTEND_REG(eth_port_num), + p_eth_port_ctrl->port_config_extend); + + KW_REG_WRITE(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num), + p_eth_port_ctrl->port_serial_control); + + KW_REG_BITS_SET(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num), + ETH_SERIAL_PORT_ENABLE); + + /* Assign port SDMA configuration */ + KW_REG_WRITE(KW_ETH_SDMA_CONFIG_REG(eth_port_num), + p_eth_port_ctrl->port_sdma_config); + + KW_REG_WRITE(KW_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT + (eth_port_num), 0x3fffffff); + KW_REG_WRITE(KW_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG + (eth_port_num), 0x03fffcff); + /* Turn off the port/queue bandwidth limitation */ + KW_REG_WRITE(KW_ETH_MAXIMUM_TRANSMIT_UNIT(eth_port_num), 0x0); + + /* Enable port Rx. */ + KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num), + p_eth_port_ctrl->port_rx_queue_command); + + /* Set maximum receive buffer to 9700 bytes */ + KW_REG_WRITE(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num), + (0x5 << 17) | + (KW_REG_READ(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num)) + & 0xfff1ffff)); + + /* + * Set ethernet MTU for leaky bucket mechanism to 0 - this will + * disable the leaky bucket mechanism . + */ + KW_REG_WRITE(KW_ETH_MAXIMUM_TRANSMIT_UNIT(eth_port_num), 0); +} + +/******************************************************************************* +* eth_port_uc_addr - This function Set the port unicast address table +* +* DESCRIPTION: +* This function locates the proper entry in the Unicast table for the +* specified MAC nibble and sets its properties according to function +* parameters. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* u8 uc_nibble Unicast MAC Address last nibble. +* ETH_QUEUE queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* This function add/removes MAC addresses from the port unicast address +* table. +* +* RETURN: +* true is output succeeded. +* false if option parameter is invalid. +* +*******************************************************************************/ +static bool eth_port_uc_addr(ETH_PORT eth_port_num, + u8 uc_nibble, + ETH_QUEUE queue, int option) +{ + u32 unicast_reg; + u32 tbl_offset; + u32 reg_offset; + + /* Locate the Unicast table entry */ + uc_nibble = (0xf & uc_nibble); + tbl_offset = (uc_nibble / 4) * 4; /* Register offset from unicast table base */ + reg_offset = uc_nibble % 4; /* Entry offset within the above register */ + + switch (option) { + case REJECT_MAC_ADDR: + /* Clear accepts frame bit at specified unicast DA table entry */ + unicast_reg = + KW_REG_READ((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset)); + + unicast_reg &= (0xFF << (8 * reg_offset)); + + KW_REG_WRITE((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE(eth_port_num) + + tbl_offset), unicast_reg); + break; + + case ACCEPT_MAC_ADDR: + /* Set accepts frame bit at unicast DA filter table entry */ + unicast_reg = + KW_REG_READ((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + + tbl_offset)); + + unicast_reg &= (0xFF << (8 * reg_offset)); + unicast_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset)); + + KW_REG_WRITE((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE(eth_port_num) + + tbl_offset), unicast_reg); + + break; + + default: + return false; + } + return true; +} + +/******************************************************************************* +* eth_port_uc_addr_set - This function Set the port Unicast address. +* +* DESCRIPTION: +* This function Set the port Ethernet MAC address. +* +* INPUT: +* ETH_PORT eth_port_num Port number. +* char * p_addr Address to be set +* ETH_QUEUE queue Rx queue number for this MAC address. +* +* OUTPUT: +* Set MAC address low and high registers. also calls eth_port_uc_addr() +* To set the unicast table with the proper information. +* +* RETURN: +* N/A. +* +*******************************************************************************/ +static void eth_port_uc_addr_set(ETH_PORT eth_port_num, + u8 *p_addr, ETH_QUEUE queue) +{ + u32 mac_h; + u32 mac_l; + + mac_l = (p_addr[4] << 8) | (p_addr[5]); + mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | + (p_addr[2] << 8) | (p_addr[3] << 0); + + KW_REG_WRITE(KW_ETH_MAC_ADDR_LOW(eth_port_num), mac_l); + KW_REG_WRITE(KW_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h); + + /* Accept frames of this address */ + eth_port_uc_addr(eth_port_num, p_addr[5], queue, ACCEPT_MAC_ADDR); + + return; +} +/******************************************************************************* + * eth_port_reset - Reset Ethernet port + * + * DESCRIPTION: + * This routine resets the chip by aborting any SDMA engine activity and + * clearing the MIB counters. The Receiver and the Transmit unit are in + * idle state after this command is performed and the port is disabled. + * + * INPUT: + * ETH_PORT eth_port_num Ethernet Port number. See ETH_PORT enum. + * + * OUTPUT: + * Channel activity is halted. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_port_reset(ETH_PORT eth_port_num) +{ + u32 reg_data, i; + + /* Stop Tx port activity. Check port Tx activity. */ + reg_data = KW_REG_READ(KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port_num)); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + KW_REG_WRITE(KW_ETH_TRANSMIT_QUEUE_COMMAND_REG + (eth_port_num), (reg_data << 8)); + + /* Wait for all Tx activity to terminate. */ + do { + /* Check port cause register that all Tx queues are stopped */ + reg_data = + KW_REG_READ + (KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port_num)); + } + while (reg_data & 0xFF); + } + + /* Stop Rx port activity. Check port Rx activity. */ + reg_data = KW_REG_READ(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num)); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG + (eth_port_num), (reg_data << 8)); + + /* Wait for all Rx activity to terminate. */ + do { + /* Check port cause register that all Rx queues are stopped */ + reg_data = + KW_REG_READ + (KW_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num)); + } + while (reg_data & 0xFF); + } + + /* Clear all MIB counters */ + eth_clear_mib_counters(eth_port_num); + + /* Enable port in the Configuration Register */ + KW_REG_BITS_RESET(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num), + ETH_SERIAL_PORT_ENABLE); + /* Set port of active in the Configuration Register */ + KW_REG_BITS_RESET(KW_ETH_PORT_SERIAL_CONTROL1_REG(eth_port_num), BIT4); +#ifdef CONFIG_SYS_MII_MODE + /* Set MMI interface up */ + KW_REG_BITS_RESET(KW_ETH_PORT_SERIAL_CONTROL1_REG(eth_port_num), BIT3); +#endif + + for (i = 0; i < 4000; i++) ; + return; +} + +/******************************************************************************* + * kw_egiga_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory. + * + * DESCRIPTION: + * This function prepares a Rx chained list of descriptors and packet + * buffers in a form of a ring. The routine must be called after port + * initialization routine and before port start routine. + * The Ethernet SDMA engine uses CPU bus addresses to access the various + * devices in the system (i.e. DRAM). This function uses the ethernet + * struct 'virtual to physical' routine (set by the user) to set the ring + * with physical addresses. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * int rx_desc_num Number of Rx descriptors + * int rx_buff_size Size of Rx buffer + * u32 rx_desc_base_addr Rx descriptors memory area base addr. + * u32 rx_buff_base_addr Rx buffer memory area base addr. + * + * OUTPUT: + * The routine updates the Ethernet port control struct with information + * regarding the Rx descriptors and buffers. + * + * RETURN: + * false if the given descriptors memory area is not aligned according to + * Ethernet SDMA specifications. + * true otherwise. + * + *******************************************************************************/ +static bool kw_egiga_init_rx_desc_ring(ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE rx_queue, + int rx_desc_num, + int rx_buff_size, + u32 rx_desc_base_addr, + u32 rx_buff_base_addr) +{ + ETH_RX_DESC *p_rx_desc; + ETH_RX_DESC *p_rx_prev_desc; /* pointer to link with the last descriptor */ + u32 buffer_addr; + int ix; /* a counter */ + + p_rx_desc = (ETH_RX_DESC *) rx_desc_base_addr; + p_rx_prev_desc = p_rx_desc; + buffer_addr = rx_buff_base_addr; + + /* Rx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */ + if (rx_buff_base_addr & 0xF) + return false; + + /* Rx buffers are limited to 64K bytes and Minimum size is 8 bytes */ + if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE)) + return false; + + /* Rx buffers must be 64-bit aligned. */ + if ((rx_buff_base_addr + rx_buff_size) & 0x7) + return false; + + /* initialize the Rx descriptors ring */ + for (ix = 0; ix < rx_desc_num; ix++) { + p_rx_desc->buf_size = rx_buff_size; + p_rx_desc->byte_cnt = 0x0000; + p_rx_desc->cmd_sts = + ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT; + p_rx_desc->next_desc_ptr = + ((u32)p_rx_desc) + RX_DESC_ALIGNED_SIZE; + p_rx_desc->buf_ptr = buffer_addr; + p_rx_desc->return_info = 0x00000000; + D_CACHE_FLUSH_LINE(p_rx_desc, 0); + buffer_addr += rx_buff_size; + p_rx_prev_desc = p_rx_desc; + p_rx_desc = (ETH_RX_DESC *) + ((u32)p_rx_desc + RX_DESC_ALIGNED_SIZE); + } + + /* Closing Rx descriptors ring */ + p_rx_prev_desc->next_desc_ptr = (rx_desc_base_addr); + D_CACHE_FLUSH_LINE(p_rx_prev_desc, 0); + + /* Save Rx desc pointer to driver struct. */ + CURR_RFD_SET((ETH_RX_DESC *) rx_desc_base_addr, rx_queue); + USED_RFD_SET((ETH_RX_DESC *) rx_desc_base_addr, rx_queue); + + p_eth_port_ctrl->p_rx_desc_area_base[rx_queue] = + (ETH_RX_DESC *) rx_desc_base_addr; + p_eth_port_ctrl->rx_desc_area_size[rx_queue] = + rx_desc_num * RX_DESC_ALIGNED_SIZE; + + p_eth_port_ctrl->port_rx_queue_command |= (1 << rx_queue); + + return true; +} + +/******************************************************************************* + * kw_egiga_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory. + * + * DESCRIPTION: + * This function prepares a Tx chained list of descriptors and packet + * buffers in a form of a ring. The routine must be called after port + * initialization routine and before port start routine. + * The Ethernet SDMA engine uses CPU bus addresses to access the various + * devices in the system (i.e. DRAM). This function uses the ethernet + * struct 'virtual to physical' routine (set by the user) to set the ring + * with physical addresses. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * int tx_desc_num Number of Tx descriptors + * int tx_buff_size Size of Tx buffer + * u32 tx_desc_base_addr Tx descriptors memory area base addr. + * u32 tx_buff_base_addr Tx buffer memory area base addr. + * + * OUTPUT: + * The routine updates the Ethernet port control struct with information + * regarding the Tx descriptors and buffers. + * + * RETURN: + * false if the given descriptors memory area is not aligned according to + * Ethernet SDMA specifications. + * true otherwise. + * + *******************************************************************************/ +static bool kw_egiga_init_tx_desc_ring(ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE tx_queue, + int tx_desc_num, + int tx_buff_size, + u32 tx_desc_base_addr, + u32 tx_buff_base_addr) +{ + + ETH_TX_DESC *p_tx_desc; + ETH_TX_DESC *p_tx_prev_desc; + u32 buffer_addr; + int ix; /* a counter */ + + /* save the first desc pointer to link with the last descriptor */ + p_tx_desc = (ETH_TX_DESC *) tx_desc_base_addr; + p_tx_prev_desc = p_tx_desc; + buffer_addr = tx_buff_base_addr; + + /* Tx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */ + if (tx_buff_base_addr & 0xF) + return false; + + /* Tx buffers are limited to 64K bytes and Minimum size is 8 bytes */ + if ((tx_buff_size > TX_BUFFER_MAX_SIZE) + || (tx_buff_size < TX_BUFFER_MIN_SIZE)) + return false; + + /* Initialize the Tx descriptors ring */ + for (ix = 0; ix < tx_desc_num; ix++) { + p_tx_desc->byte_cnt = 0x0000; + p_tx_desc->l4i_chk = 0x0000; + p_tx_desc->cmd_sts = 0x00000000; + p_tx_desc->next_desc_ptr = + ((u32)p_tx_desc) + TX_DESC_ALIGNED_SIZE; + + p_tx_desc->buf_ptr = buffer_addr; + p_tx_desc->return_info = 0x00000000; + D_CACHE_FLUSH_LINE(p_tx_desc, 0); + buffer_addr += tx_buff_size; + p_tx_prev_desc = p_tx_desc; + p_tx_desc = (ETH_TX_DESC *) + ((u32)p_tx_desc + TX_DESC_ALIGNED_SIZE); + + } + /* Closing Tx descriptors ring */ + p_tx_prev_desc->next_desc_ptr = tx_desc_base_addr; + D_CACHE_FLUSH_LINE(p_tx_prev_desc, 0); + /* Set Tx desc pointer in driver struct. */ + CURR_TFD_SET((ETH_TX_DESC *) tx_desc_base_addr, tx_queue); + USED_TFD_SET((ETH_TX_DESC *) tx_desc_base_addr, tx_queue); + + /* Init Tx ring base and size parameters */ + p_eth_port_ctrl->p_tx_desc_area_base[tx_queue] = + (ETH_TX_DESC *) tx_desc_base_addr; + p_eth_port_ctrl->tx_desc_area_size[tx_queue] = + (tx_desc_num * TX_DESC_ALIGNED_SIZE); + + /* Add the queue to the list of Tx queues of this port */ + p_eth_port_ctrl->port_tx_queue_command |= (1 << tx_queue); + + return true; +} + +/******************************************************************************* + * eth_b_copy - Copy bytes from source to destination + * + * DESCRIPTION: + * This function supports the eight bytes limitation on Tx buffer size. + * The routine will zero eight bytes starting from the destination address + * followed by copying bytes from the source address to the destination. + * + * INPUT: + * u32 src_addr 32 bit source address. + * u32 dst_addr 32 bit destination address. + * int byte_count Number of bytes to copy. + * + * OUTPUT: + * See description. + * + * RETURN: + * None. + * + *******************************************************************************/ +static void eth_b_copy(u32 src_addr, u32 dst_addr, + int byte_count) +{ + /* Zero the dst_addr area */ + *(u32 *)dst_addr = 0x0; + + while (byte_count != 0) { + *(char *)dst_addr = *(char *)src_addr; + dst_addr++; + src_addr++; + byte_count--; + } +} + +/******************************************************************************* + * eth_port_send - Send an Ethernet packet + * + * DESCRIPTION: + * This routine send a given packet described by p_pktinfo parameter. It + * supports transmitting of a packet spaned over multiple buffers. The + * routine updates 'curr' and 'first' indexes according to the packet + * segment passed to the routine. In case the packet segment is first, + * the 'first' index is update. In any case, the 'curr' index is updated. + * If the routine get into Tx resource error it assigns 'curr' index as + * 'first'. This way the function can abort Tx process of multiple + * descriptors per packet. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Tx ring 'curr' and 'first' indexes are updated. + * + * RETURN: + * ETH_QUEUE_FULL in case of Tx resource error. + * ETH_ERROR in case the routine can not access Tx desc ring. + * ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_port_send(ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_TX_DESC *p_tx_desc_first; + volatile ETH_TX_DESC *p_tx_desc_curr; + volatile ETH_TX_DESC *p_tx_next_desc_curr; + volatile ETH_TX_DESC *p_tx_desc_used; + u32 command_status; + +#ifdef CONFIG_TX_PKT_DISPLAY + { + u16 pcnt = p_pkt_info->byte_cnt; + u8 *prndt = (char *)p_pkt_info->buf_ptr; + printf("cnt=%d ", pcnt); + while (pcnt) { + printf("%02x,", prndt[0]); + prndt++; + pcnt--; + } + printf(" pckend \n"); + + } +#endif + /* Do not process Tx ring in case of Tx ring resource error */ + if (p_eth_port_ctrl->tx_resource_err[tx_queue] == true) + return ETH_QUEUE_FULL; + + /* Get the Tx Desc ring indexes */ + CURR_TFD_GET(p_tx_desc_curr, tx_queue); + USED_TFD_GET(p_tx_desc_used, tx_queue); + + if (p_tx_desc_curr == NULL) + return ETH_ERROR; + + /* The following parameters are used to save readings from memory */ + p_tx_next_desc_curr = TX_NEXT_DESC_PTR(p_tx_desc_curr, tx_queue); + command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC; + + if (command_status & (ETH_TX_FIRST_DESC)) { + /* Update first desc */ + FIRST_TFD_SET(p_tx_desc_curr, tx_queue); + p_tx_desc_first = p_tx_desc_curr; + } else { + FIRST_TFD_GET(p_tx_desc_first, tx_queue); + command_status |= ETH_BUFFER_OWNED_BY_DMA; + } + + /* Buffers with a payload smaller than 8 bytes must be aligned to 64-bit */ + /* boundary. We use the memory allocated for Tx descriptor. This memory */ + /* located in TX_BUF_OFFSET_IN_DESC offset within the Tx descriptor. */ + if (p_pkt_info->byte_cnt <= 8) { + printf("You have failed in the < 8 bytes errata - fixme\n"); /* RABEEH - TBD */ + return ETH_ERROR; + + p_tx_desc_curr->buf_ptr = + (u32)p_tx_desc_curr + TX_BUF_OFFSET_IN_DESC; + eth_b_copy(p_pkt_info->buf_ptr, p_tx_desc_curr->buf_ptr, + p_pkt_info->byte_cnt); + } else + p_tx_desc_curr->buf_ptr = p_pkt_info->buf_ptr; + + p_tx_desc_curr->byte_cnt = p_pkt_info->byte_cnt; + p_tx_desc_curr->return_info = p_pkt_info->return_info; + + if (p_pkt_info->cmd_sts & (ETH_TX_LAST_DESC)) { + /* Set last desc with DMA ownership and interrupt enable. */ + p_tx_desc_curr->cmd_sts = command_status | + ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT; + + if (p_tx_desc_curr != p_tx_desc_first) + p_tx_desc_first->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA; + + /* Flush CPU pipe */ + + D_CACHE_FLUSH_LINE((u32)p_tx_desc_curr, 0); + D_CACHE_FLUSH_LINE((u32)p_tx_desc_first, 0); + CPU_PIPE_FLUSH; + + /* Apply send command */ + ETH_ENABLE_TX_QUEUE(tx_queue, p_eth_port_ctrl->port_num); + debug_print("packet xmitted"); + + /* Finish Tx packet. Update first desc in case of Tx resource error */ + p_tx_desc_first = p_tx_next_desc_curr; + FIRST_TFD_SET(p_tx_desc_first, tx_queue); + + } else { + p_tx_desc_curr->cmd_sts = command_status; + D_CACHE_FLUSH_LINE((u32)p_tx_desc_curr, 0); + } + + /* Check for ring index overlap in the Tx desc ring */ + if (p_tx_next_desc_curr == p_tx_desc_used) { + /* Update the current descriptor */ + CURR_TFD_SET(p_tx_desc_first, tx_queue); + + p_eth_port_ctrl->tx_resource_err[tx_queue] = true; + return ETH_QUEUE_LAST_RESOURCE; + } else { + /* Update the current descriptor */ + CURR_TFD_SET(p_tx_next_desc_curr, tx_queue); + return ETH_OK; + } +} + +/******************************************************************************* + * eth_tx_return_desc - Free all used Tx descriptors + * + * DESCRIPTION: + * This routine returns the transmitted packet information to the caller. + * It uses the 'first' index to support Tx desc return in case a transmit + * of a packet spanned over multiple buffer still in process. + * In case the Tx queue was in "resource error" condition, where there are + * no available Tx resources, the function resets the resource error flag. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE tx_queue Number of Tx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Tx ring 'first' and 'used' indexes are updated. + * + * RETURN: + * ETH_ERROR in case the routine can not access Tx desc ring. + * ETH_RETRY in case there is transmission in process. + * ETH_END_OF_JOB if the routine has nothing to release. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_tx_return_desc(ETH_PORT_INFO * + p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_TX_DESC *p_tx_desc_used = NULL; + volatile ETH_TX_DESC *p_tx_desc_first = NULL; + u32 command_status; + + /* Get the Tx Desc ring indexes */ + USED_TFD_GET(p_tx_desc_used, tx_queue); + FIRST_TFD_GET(p_tx_desc_first, tx_queue); + + /* Sanity check */ + if (p_tx_desc_used == NULL) + return ETH_ERROR; + + command_status = p_tx_desc_used->cmd_sts; + + /* Still transmitting... */ + if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { + D_CACHE_FLUSH_LINE((u32)p_tx_desc_used, 0); + return ETH_RETRY; + } + + /* Stop release. About to overlap the current available Tx descriptor */ + if ((p_tx_desc_used == p_tx_desc_first) && + (p_eth_port_ctrl->tx_resource_err[tx_queue] == false)) { + D_CACHE_FLUSH_LINE((u32)p_tx_desc_used, 0); + return ETH_END_OF_JOB; + } + + /* Pass the packet information to the caller */ + p_pkt_info->cmd_sts = command_status; + p_pkt_info->return_info = p_tx_desc_used->return_info; + p_tx_desc_used->return_info = 0; + + /* Update the next descriptor to release. */ + USED_TFD_SET(TX_NEXT_DESC_PTR(p_tx_desc_used, tx_queue), tx_queue); + + /* Any Tx return cancels the Tx resource error status */ + if (p_eth_port_ctrl->tx_resource_err[tx_queue] == true) + p_eth_port_ctrl->tx_resource_err[tx_queue] = false; + + D_CACHE_FLUSH_LINE((u32)p_tx_desc_used, 0); + + return ETH_OK; + +} + +/******************************************************************************* + * eth_port_receive - Get received information from Rx ring. + * + * DESCRIPTION: + * This routine returns the received data to the caller. There is no + * data copying during routine operation. All information is returned + * using pointer to packet information struct passed from the caller. + * If the routine exhausts Rx ring resources then the resource error flag + * is set. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * PKT_INFO *p_pkt_info User packet buffer. + * + * OUTPUT: + * Rx ring current and used indexes are updated. + * + * RETURN: + * ETH_ERROR in case the routine can not access Rx desc ring. + * ETH_QUEUE_FULL if Rx ring resources are exhausted. + * ETH_END_OF_JOB if there is no received data. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_port_receive(ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_RX_DESC *p_rx_curr_desc; + volatile ETH_RX_DESC *p_rx_next_curr_desc; + volatile ETH_RX_DESC *p_rx_used_desc; + u32 command_status; + + /* Do not process Rx ring in case of Rx ring resource error */ + if (p_eth_port_ctrl->rx_resource_err[rx_queue] == true) { + error_print("Rx Queue is full ..."); + return ETH_QUEUE_FULL; + } + + /* Get the Rx Desc ring 'curr and 'used' indexes */ + CURR_RFD_GET(p_rx_curr_desc, rx_queue); + USED_RFD_GET(p_rx_used_desc, rx_queue); + + /* Sanity check */ + if (p_rx_curr_desc == NULL) + return ETH_ERROR; + + /* The following parameters are used to save readings from memory */ + p_rx_next_curr_desc = RX_NEXT_DESC_PTR(p_rx_curr_desc, rx_queue); + command_status = p_rx_curr_desc->cmd_sts; + + /* Nothing to receive... */ + if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { + /*debug_print("Rx: command_status: %08x", command_status); */ + D_CACHE_FLUSH_LINE((u32)p_rx_curr_desc, 0); + /*debug_print("ETH_END_OF_JOB ..."); */ + return ETH_END_OF_JOB; + } + + p_pkt_info->byte_cnt = (p_rx_curr_desc->byte_cnt) - RX_BUF_OFFSET; + p_pkt_info->cmd_sts = command_status; + p_pkt_info->buf_ptr = (p_rx_curr_desc->buf_ptr) + RX_BUF_OFFSET; + p_pkt_info->return_info = p_rx_curr_desc->return_info; + p_pkt_info->l4i_chk = p_rx_curr_desc->buf_size; /* IP fragment indicator */ + + /* Clean the return info field to indicate that the packet has been */ + /* moved to the upper layers */ + p_rx_curr_desc->return_info = 0; + + /* Update 'curr' in data structure */ + CURR_RFD_SET(p_rx_next_curr_desc, rx_queue); + + /* Rx descriptors resource exhausted. Set the Rx ring resource error flag */ + if (p_rx_next_curr_desc == p_rx_used_desc) + p_eth_port_ctrl->rx_resource_err[rx_queue] = true; + + D_CACHE_FLUSH_LINE((u32)p_rx_curr_desc, 0); + CPU_PIPE_FLUSH; + return ETH_OK; +} + +/******************************************************************************* + * eth_rx_return_buff - Returns a Rx buffer back to the Rx ring. + * + * DESCRIPTION: + * This routine returns a Rx buffer back to the Rx ring. It retrieves the + * next 'used' descriptor and attached the returned buffer to it. + * In case the Rx ring was in "resource error" condition, where there are + * no available Rx resources, the function resets the resource error flag. + * + * INPUT: + * ETH_PORT_INFO *p_eth_port_ctrl Ethernet Port Control srtuct. + * ETH_QUEUE rx_queue Number of Rx queue. + * PKT_INFO *p_pkt_info Information on the returned buffer. + * + * OUTPUT: + * New available Rx resource in Rx descriptor ring. + * + * RETURN: + * ETH_ERROR in case the routine can not access Rx desc ring. + * ETH_OK otherwise. + * + *******************************************************************************/ +static ETH_FUNC_RET_STATUS eth_rx_return_buff(ETH_PORT_INFO * + p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO * p_pkt_info) +{ + volatile ETH_RX_DESC *p_used_rx_desc; /* Where to return Rx resource */ + + /* Get 'used' Rx descriptor */ + USED_RFD_GET(p_used_rx_desc, rx_queue); + + /* Sanity check */ + if (p_used_rx_desc == NULL) + return ETH_ERROR; + + p_used_rx_desc->buf_ptr = p_pkt_info->buf_ptr; + p_used_rx_desc->return_info = p_pkt_info->return_info; + p_used_rx_desc->byte_cnt = p_pkt_info->byte_cnt; + p_used_rx_desc->buf_size = KW_RX_BUFFER_SIZE; /* Reset Buffer size */ + + /* Flush the write pipe */ + CPU_PIPE_FLUSH; + + /* Return the descriptor to DMA ownership */ + p_used_rx_desc->cmd_sts = + ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT; + + /* Flush descriptor and CPU pipe */ + D_CACHE_FLUSH_LINE((u32)p_used_rx_desc, 0); + CPU_PIPE_FLUSH; + + /* Move the used descriptor pointer to the next descriptor */ + USED_RFD_SET(RX_NEXT_DESC_PTR(p_used_rx_desc, rx_queue), rx_queue); + + /* Any Rx return cancels the Rx resource error status */ + if (p_eth_port_ctrl->rx_resource_err[rx_queue] == true) + p_eth_port_ctrl->rx_resource_err[rx_queue] = false; + + return ETH_OK; +} + +/* + * helper function used for kirkwood_egiga_initialize + */ +void print_globals(struct eth_device *dev) +{ + debug_print("Ethernet PRINT_Globals-Debug function"); + debug_print("Base Address for ETH_PORT_INFO: %08x", + (u32)dev->priv); + debug_print("Base Address for egiga_priv: %08x", + (u32)&(((ETH_PORT_INFO *) dev->priv)->port_private)); + + debug_print + ("Base Address for TX-DESCs: %08x Number of allocated Buffers %d", + (u32)((ETH_PORT_INFO *) dev->priv)-> + p_tx_desc_area_base[0], KW_TX_QUEUE_SIZE); + debug_print + ("Base Address for RX-DESCs: %08x Number of allocated Buffers %d", + (u32)((ETH_PORT_INFO *) dev->priv)-> + p_rx_desc_area_base[0], KW_RX_QUEUE_SIZE); + debug_print("Base Address for RX-Buffer: %08x allocated Bytes %d", + (u32)((ETH_PORT_INFO *) dev->priv)-> + p_rx_buffer_base[0], + (KW_RX_QUEUE_SIZE * KW_RX_BUFFER_SIZE) + 32); + debug_print("Base Address for TX-Buffer: %08x allocated Bytes %d", + (u32)((ETH_PORT_INFO *) dev->priv)-> + p_tx_buffer_base[0], + (KW_TX_QUEUE_SIZE * KW_TX_BUFFER_SIZE) + 32); +} + + +/* + * u-boot entry functions + */ +static int kw_egiga_init(struct eth_device *dev) +{ + + u32 queue; + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + u32 port_num; + + debug_print_ftrace(); + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + /* ronen - when we update the MAC env params we only update dev->enetaddr + see ./net/eth.c eth_set_enetaddr() */ + memcpy(ethernet_private->port_mac_addr, dev->enetaddr, 6); + + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + + /* Activate the DMA channels etc */ + eth_port_init(ethernet_private); + + /* "Allocate" setup TX rings */ + + for (queue = 0; queue < KW_TX_QUEUE_NUM; queue++) { + u32 size; + + port_private->tx_ring_size[queue] = KW_TX_QUEUE_SIZE; + /*size = no of DESCs times DESC-size */ + size = + (port_private->tx_ring_size[queue] * TX_DESC_ALIGNED_SIZE); + ethernet_private->tx_desc_area_size[queue] = size; + + /* first clear desc area completely */ + memset((void *)ethernet_private->p_tx_desc_area_base[queue], + 0, ethernet_private->tx_desc_area_size[queue]); + + /* initialize tx desc ring with low level driver */ + if (kw_egiga_init_tx_desc_ring + (ethernet_private, ETH_Q0, + port_private->tx_ring_size[queue], + KW_TX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ , + (u32)ethernet_private-> + p_tx_desc_area_base[queue], + (u32)ethernet_private-> + p_tx_buffer_base[queue]) == false) + error_print("### initializing TX Ring"); + } + + /* "Allocate" setup RX rings */ + for (queue = 0; queue < KW_RX_QUEUE_NUM; queue++) { + u32 size; + + /* Meantime RX Ring are fixed - but must be configurable by user */ + port_private->rx_ring_size[queue] = KW_RX_QUEUE_SIZE; + size = (port_private->rx_ring_size[queue] * + RX_DESC_ALIGNED_SIZE); + ethernet_private->rx_desc_area_size[queue] = size; + + /* first clear desc area completely */ + memset((void *)ethernet_private->p_rx_desc_area_base[queue], + 0, ethernet_private->rx_desc_area_size[queue]); + if ((kw_egiga_init_rx_desc_ring + (ethernet_private, ETH_Q0, + port_private->rx_ring_size[queue], + KW_RX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ , + (u32)ethernet_private-> + p_rx_desc_area_base[queue], + (u32)ethernet_private-> + p_rx_buffer_base[queue])) == false) + error_print("### initializing RX Ring"); + } + + eth_port_start(ethernet_private); + + if (!eth_phy_link_status(port_num)) { + warn_print("No link on port %d", port_num); + return 0; + } else { + egiga_print_phy_status(port_num); + } + port_private->eth_running = MAGIC_ETH_RUNNING; + return 1; +} + +/********************************************************************** + * egiga_start_xmit + * + * This function is queues a packet in the Tx descriptor for + * required port. + * + * Input : skb - a pointer to socket buffer + * dev - a pointer to the required port + * + * Output : zero upon success + **********************************************************************/ + +int kw_egiga_xmit(struct eth_device *dev, volatile void *dataPtr, int dataSize) +{ + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + u32 port_num; + PKT_INFO pkt_info; + ETH_FUNC_RET_STATUS status; + struct net_device_stats *stats; + ETH_FUNC_RET_STATUS release_result; + + debug_print_ftrace(); + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + + stats = port_private->stats; + + /* Update packet info data structure */ + pkt_info.cmd_sts = ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC; /* first last */ + pkt_info.cmd_sts |= ETH_BUFFER_OWNED_BY_DMA; /* DMA owned */ + + pkt_info.byte_cnt = dataSize; + pkt_info.buf_ptr = (u32)dataPtr; + pkt_info.return_info = 0; + + status = eth_port_send(ethernet_private, ETH_Q0, &pkt_info); + if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) { + error_print("On transmitting packet .."); + if (status == ETH_QUEUE_FULL) + error_print("ETH Queue is full."); + if (status == ETH_QUEUE_LAST_RESOURCE) + error_print("ETH Queue: using last available resource."); + goto error; + } + + /* Update statistics and start of transmittion time */ + stats->tx_bytes += dataSize; + stats->tx_packets++; + + /* Check if packet(s) is(are) transmitted correctly (release everything) */ + do { + release_result = + eth_tx_return_desc(ethernet_private, ETH_Q0, &pkt_info); + switch (release_result) { + case ETH_OK: + debug_print("descriptor released"); + if (pkt_info.cmd_sts & BIT0) { + error_print("in TX"); + stats->tx_errors++; + + } + break; + case ETH_RETRY: + debug_print("transmission still in process"); + break; + + case ETH_ERROR: + error_print("routine can not access Tx desc ring"); + break; + + case ETH_END_OF_JOB: + debug_print("the routine has nothing to release"); + break; + default: /* should not happen */ + break; + } + } while (release_result == ETH_OK); + + return 0; /* success */ + error: + return 1; /* Failed - higher layers will free the skb */ +} + +/********************************************************************** + * kw_egiga_receive + * + * This function is forward packets that are received from the port's + * queues toward kernel core or FastRoute them to another interface. + * + * Input : dev - a pointer to the required interface + * max - maximum number to receive (0 means unlimted) + * + * Output : number of served packets + **********************************************************************/ + +int kw_egiga_receive(struct eth_device *dev) +{ + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + u32 port_num; + PKT_INFO pkt_info; + struct net_device_stats *stats; + + ethernet_private = (ETH_PORT_INFO *) dev->priv; + port_private = (struct egiga_priv *)ethernet_private->port_private; + port_num = port_private->port_num; + stats = port_private->stats; + + while ((eth_port_receive(ethernet_private, ETH_Q0, &pkt_info) == + ETH_OK)) { + + if (pkt_info.byte_cnt != 0) { + debug_print("%s: Received %d byte Packet @ 0x%x", + __FUNCTION__, pkt_info.byte_cnt, + pkt_info.buf_ptr); + } + /* Update statistics. Note byte count includes 4 byte CRC count */ + stats->rx_packets++; + stats->rx_bytes += pkt_info.byte_cnt; + + /* + * In case received a packet without first / last bits on OR the error + * summary bit is on, the packets needs to be dropeed. + */ + if (((pkt_info. + cmd_sts & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) != + (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) + || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) { + stats->rx_dropped++; + + printf + ("Received packet spread on multiple descriptors\n"); + + /* Is this caused by an error ? */ + if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY) { + stats->rx_errors++; + } + + /* free these descriptors again without forwarding them to the higher layers */ + pkt_info.buf_ptr &= ~0x7; /* realign buffer again */ + pkt_info.byte_cnt = 0x0000; /* Reset Byte count */ + + if (eth_rx_return_buff + (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) { + printf + ("Error while returning the RX Desc to Ring\n"); + } else { + debug_print("RX Desc returned to Ring"); + } + /* /free these descriptors again */ + } else { + + /* !!! call higher layer processing */ + debug_print("\nNow send it to upper layer protocols (NetReceive) ..."); + + /* let the upper layer handle the packet */ + NetReceive((uchar *) pkt_info.buf_ptr, + (int)pkt_info.byte_cnt); + + /* free descriptor */ + pkt_info.buf_ptr &= ~0x7; /* realign buffer again */ + pkt_info.byte_cnt = 0x0000; /* Reset Byte count */ + debug_print("RX: pkt_info.buf_ptr = %x", + pkt_info.buf_ptr); + if (eth_rx_return_buff + (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) { + error_print + ("while returning the RX Desc to Ring"); + } else { + debug_print("RX Desc returned to Ring"); + } + /* free descriptor code end */ + } + } + egiga_get_stats(dev); /* update statistics */ + return 1; +} + +/* + * Called from net/eth.c + */ +int kirkwood_egiga_initialize(bd_t * bis) +{ + struct eth_device *dev; + ETH_PORT_INFO *ethernet_private; + struct egiga_priv *port_private; + int devnum, x, temp; + char *s, *e, buf[64]; + u8 used_ports[MAX_ETH_DEVS] = CONFIG_KIRKWOOD_EGIGA_PORTS; + + debug_print_ftrace(); + for (devnum = 0; devnum < MAX_ETH_DEVS; devnum++) { + /*skip if port is configured not to use */ + if (used_ports[devnum] == FALSE) + continue; + + dev = calloc(sizeof(*dev), 1); + if (!dev) { + printf("%s: mv_enet%d allocation failure, %s\n", + __FUNCTION__, devnum, "eth_device structure"); + return -1; + } + + /* must be less than NAMESIZE (16) */ + sprintf(dev->name, "egiga%d", devnum); + + debug_print("Initializing %s", dev->name); + + /* Extract the MAC address from the environment */ + switch (devnum) { + case 0: + s = "ethaddr"; + break; + + case 1: + s = "eth1addr"; + break; + + default: /* this should never happen */ + printf("%s: Invalid device number %d\n", + __FUNCTION__, devnum); + return -1; + } + + e = getenv(s); + if (!e) { + /* Generate Ramdom MAC addresses if not set */ + sprintf(buf, "00:50:43:%02x:%02x:%02x", + get_random_hex(), get_random_hex(), + get_random_hex()); + setenv(s, buf); + } + + temp = getenv_r(s, buf, sizeof(buf)); + s = (temp > 0) ? buf : NULL; + + debug_print("Setting MAC %d to %s", devnum, s); + /* Assume port is pre-powered up */ + /* eth_port_power_up(devnum); */ + + for (x = 0; x < 6; ++x) { + dev->enetaddr[x] = s ? simple_strtoul(s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + /* set the MAC addr in the HW */ + eth_port_uc_addr_set(devnum, dev->enetaddr, 0); + + dev->init = (void *)kw_egiga_init; + dev->halt = (void *)kw_egiga_stop; + dev->send = (void *)kw_egiga_xmit; + dev->recv = (void *)kw_egiga_receive; + + ethernet_private = calloc(sizeof(*ethernet_private), 1); + dev->priv = (void *)ethernet_private; + + if (!ethernet_private) { + printf("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, + "Private Device Structure"); + free(dev); + return -1; + } + /* start with an zeroed ETH_PORT_INFO */ + memset(ethernet_private, 0, sizeof(ETH_PORT_INFO)); + memcpy(ethernet_private->port_mac_addr, dev->enetaddr, 6); + + /* set pointer to memory for stats data structure etc... */ + port_private = calloc(sizeof(*ethernet_private), 1); + ethernet_private->port_private = (void *)port_private; + if (!port_private) { + printf("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, + "Port Private Device Structure"); + + free(ethernet_private); + free(dev); + return -1; + } + + port_private->stats = + calloc(sizeof(struct net_device_stats), 1); + if (!port_private->stats) { + printf("%s: %s allocation failure, %s\n", + __FUNCTION__, dev->name, "Net stat Structure"); + + free(port_private); + free(ethernet_private); + free(dev); + return -1; + } + memset(ethernet_private->port_private, 0, + sizeof(struct egiga_priv)); + switch (devnum) { + case 0: + ethernet_private->port_num = ETH_0; + break; + case 1: + ethernet_private->port_num = ETH_1; + break; + default: + printf("Invalid device number %d\n", devnum); + break; + }; + + port_private->port_num = devnum; + /* + * Read MIB counter on the GT in order to reset them, + * then zero all the stats fields in memory + */ + egiga_update_stat(dev); + memset(port_private->stats, 0, sizeof(struct net_device_stats)); + + debug_print("Allocating descriptor and buffer rings"); + + ethernet_private->p_rx_desc_area_base[0] = + (ETH_RX_DESC *) memalign(16, + RX_DESC_ALIGNED_SIZE * + KW_RX_QUEUE_SIZE + 1); + ethernet_private->p_tx_desc_area_base[0] = + (ETH_TX_DESC *) memalign(16, + TX_DESC_ALIGNED_SIZE * + KW_TX_QUEUE_SIZE + 1); + + ethernet_private->p_rx_buffer_base[0] = + (char *)memalign(16, + KW_RX_QUEUE_SIZE * KW_TX_BUFFER_SIZE + 1); + ethernet_private->p_tx_buffer_base[0] = + (char *)memalign(16, + KW_RX_QUEUE_SIZE * KW_TX_BUFFER_SIZE + 1); + + /* DEBUG OUTPUT prints adresses of globals */ + print_globals(dev); + + eth_register(dev); + + /* Set phy address of the port */ + ethernet_private->port_phy_addr = + PHY_BASE_ADR + ethernet_private->port_num; + eth_phy_set_addr(ethernet_private->port_num, + ethernet_private->port_phy_addr); + + } + return 0; +} + +#endif /* CONFIG_KIRKWOOD_EGIGA */ diff --git a/cpu/arm926ejs/kirkwood/egiga.h b/cpu/arm926ejs/kirkwood/egiga.h new file mode 100644 index 0000000..83dc4b3 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/egiga.h @@ -0,0 +1,707 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Prafulla Wadaskar prafulla@marvell.com + * + * based on - Driver for MV64360X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 __EGIGA_H__ +#define __EGIGA_H__ + +#define MAX_ETH_DEVS 2 /*controller has two ports */ + +#include <asm/types.h> +#include <asm/byteorder.h> +#include <common.h> +#include <net.h> + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* Port attributes */ +/* Max queue number is 8 for controller but here configured 1 */ +#define MAX_RX_QUEUE_NUM 1 +#define MAX_TX_QUEUE_NUM 1 +/* Use one TX queue and one RX queue */ +#define KW_TX_QUEUE_NUM 1 +#define KW_RX_QUEUE_NUM 1 + +/* + * Number of RX / TX descriptors on RX / TX rings. + * Note that allocating RX descriptors is done by allocating the RX + * ring AND a preallocated RX buffers (skb's) for each descriptor. + * The TX descriptors only allocates the TX descriptors ring, + * with no pre allocated TX buffers (skb's are allocated by higher layers. + */ + +/* TX/RX parameters can be passed externally */ +#ifdef CONFIG_ETH_TXQUEUE_SIZE +#define KW_TX_QUEUE_SIZE CONFIG_ETH_TXQUEUE_SIZE +#else +#define KW_TX_QUEUE_SIZE 4 +#endif + +#ifdef CONFIG_ETH_RXQUEUE_SIZE +#define KW_RX_QUEUE_SIZE CONFIG_ETH_RXQUEUE_SIZE +#else +#define KW_RX_QUEUE_SIZE 4 +#endif + +#ifdef CONFIG_ETH_RXBUFFER_SIZE +#define KW_RX_BUFFER_SIZE CONFIG_ETH_RXBUFFER_SIZE +#else +#define KW_RX_BUFFER_SIZE 1600 +#endif + +#ifdef CONFIG_ETH_TXBUFFER_SIZE +#define KW_TX_BUFFER_SIZE CONFIG_ETH_TXBUFFER_SIZE +#else +#define KW_TX_BUFFER_SIZE 1600 +#endif + +#define RX_BUFFER_MAX_SIZE 0xFFFF +#define TX_BUFFER_MAX_SIZE 0xFFFF /* Buffers are limited to 64k */ +#define RX_BUFFER_MIN_SIZE 0x8 +#define TX_BUFFER_MIN_SIZE 0x8 + +/* + * Network device statistics. Akin to the 2.0 ether stats but + * with byte counters. + */ +struct net_device_stats { + u32 rx_packets; /* total packets received */ + u32 tx_packets; /* total packets transmitted */ + u32 rx_bytes; /* total bytes received */ + u32 tx_bytes; /* total bytes transmitted */ + u32 rx_errors; /* bad packets received */ + u32 tx_errors; /* packet transmit problems */ + u32 rx_dropped; /* no space in linux buffers */ + u32 tx_dropped; /* no space available in linux */ + u32 multicast; /* multicast packets received */ + u32 collisions; + /* detailed rx_errors: */ + u32 rx_length_errors; + u32 rx_over_errors; /* receiver ring buff overflow */ + u32 rx_crc_errors; /* recved pkt with crc error */ + u32 rx_frame_errors; /* recv'd frame alignment error */ + u32 rx_fifo_errors; /* recv'r fifo overrun */ + u32 rx_missed_errors; /* receiver missed packet */ + /* detailed tx_errors */ + u32 tx_aborted_errors; + u32 tx_carrier_errors; + u32 tx_fifo_errors; + u32 tx_heartbeat_errors; + u32 tx_window_errors; + /* for cslip etc */ + u32 rx_compressed; + u32 tx_compressed; +}; + +/* Private data structure used for ethernet device */ +struct egiga_priv { + u32 port_num; + struct net_device_stats *stats; + /* to buffer area aligned */ + char *p_eth_tx_buffer[KW_TX_QUEUE_SIZE + 1]; + char *p_eth_rx_buffer[KW_RX_QUEUE_SIZE + 1]; + /* Size of Tx Ring per queue */ + u32 tx_ring_size[MAX_TX_QUEUE_NUM]; + /* Size of Rx Ring per queue */ + u32 rx_ring_size[MAX_RX_QUEUE_NUM]; + /* Magic Number for Ethernet running */ + u32 eth_running; +}; + +/* + * The second part is the low level driver of the gigE ethernet ports. + */ + +/******************************************************************************** + * Header File for : network interface header + * + * DESCRIPTION: + * This header file contains macros typedefs and function declaration for + * the Marvell Gig Bit Ethernet Controller. + * + * DEPENDENCIES: + * None. + * + *******************************************************************************/ + +/* defines */ + +/* Default port configuration value */ +#define PORT_CONFIG_VALUE \ + ETH_UNICAST_NORMAL_MODE | \ + ETH_DEFAULT_RX_QUEUE_0 | \ + ETH_DEFAULT_RX_ARP_QUEUE_0 | \ + ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \ + ETH_RECEIVE_BC_IF_IP | \ + ETH_RECEIVE_BC_IF_ARP | \ + ETH_CAPTURE_TCP_FRAMES_DIS | \ + ETH_CAPTURE_UDP_FRAMES_DIS | \ + ETH_DEFAULT_RX_TCP_QUEUE_0 | \ + ETH_DEFAULT_RX_UDP_QUEUE_0 | \ + ETH_DEFAULT_RX_BPDU_QUEUE_0 + +/* Default port extend configuration value */ +#define PORT_CONFIG_EXTEND_VALUE \ + ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \ + ETH_PARTITION_DISABLE | \ + ETH_TX_CRC_GENERATION_ENABLE + +/* Default sdma control value */ +#ifdef CONFIG_NOT_COHERENT_CACHE +#define PORT_SDMA_CONFIG_VALUE \ + ETH_RX_BURST_SIZE_16_64BIT | \ + ETH_BLM_RX_NO_SWAP | \ + ETH_BLM_TX_NO_SWAP | \ + GT_ETH_IPG_INT_RX(0) | \ + ETH_TX_BURST_SIZE_16_64BIT; +#else +#define PORT_SDMA_CONFIG_VALUE \ + ETH_RX_BURST_SIZE_4_64BIT | \ + GT_ETH_IPG_INT_RX(0) | \ + ETH_TX_BURST_SIZE_4_64BIT; +#endif + +#define GT_ETH_IPG_INT_RX(value) \ + ((value & 0x3fff) << 8) + +/* Default port serial control value */ +#define PORT_SERIAL_CONTROL_VALUE_TMP \ + ETH_FORCE_LINK_PASS | \ + ETH_DISABLE_AUTO_NEG_FOR_DUPLX | \ + ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \ + ETH_ADV_NO_FLOW_CTRL | \ + ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \ + ETH_FORCE_BP_MODE_NO_JAM | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL | \ + ETH_DISABLE_AUTO_NEG_SPEED_GMII | \ + ETH_DTE_ADV_0 | \ + ETH_MIIPHY_MAC_MODE | \ + ETH_AUTO_NEG_NO_CHANGE | \ + ETH_MAX_RX_PACKET_1552BYTE | \ + ETH_CLR_EXT_LOOPBACK | \ + ETH_SET_FULL_DUPLEX_MODE | \ + ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX | \ + ETH_SET_MII_SPEED_TO_100 + +#ifdef CONFIG_SYS_MII_MODE +#define PORT_SERIAL_CONTROL_VALUE \ + PORT_SERIAL_CONTROL_VALUE_TMP | \ + ETH_SET_GMII_SPEED_TO_10_100 +#else +#define PORT_SERIAL_CONTROL_VALUE \ + PORT_SERIAL_CONTROL_VALUE_TMP | \ + ETH_SET_GMII_SPEED_TO_1000 +#endif + +/* Tx WRR confoguration macros */ +#define PORT_MAX_TRAN_UNIT 0x24 /* MTU register (default) 9KByte */ +#define PORT_MAX_TOKEN_BUCKET_SIZE 0x_fFFF /* PMTBS register (default) */ +#define PORT_TOKEN_RATE 1023 /* PTTBRC register (default) */ +/* MAC accepet/reject macros */ +#define ACCEPT_MAC_ADDR 0 +#define REJECT_MAC_ADDR 1 +/* Size of a Tx/Rx descriptor used in chain list data structure */ +#define RX_DESC_ALIGNED_SIZE 0x20 +#define TX_DESC_ALIGNED_SIZE 0x20 +/* An offest in Tx descriptors to store data for buffers less than 8 Bytes */ +#define TX_BUF_OFFSET_IN_DESC 0x18 +/* Buffer offset from buffer pointer */ +#define RX_BUF_OFFSET 0x2 +/* Gap define */ +#define ETH_BAR_GAP 0x8 +#define ETH_SIZE_REG_GAP 0x8 +#define ETH_HIGH_ADDR_REMAP_REG_GAP 0x4 +#define ETH_PORT_ACCESS_CTRL_GAP 0x4 +/* MIB Counters register definitions */ +#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0 +#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4 +#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8 +#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc +#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10 +#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14 +#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18 +#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c +#define ETH_MIB_FRAMES_64_OCTETS 0x20 +#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24 +#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28 +#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c +#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30 +#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34 +#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38 +#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c +#define ETH_MIB_GOOD_FRAMES_SENT 0x40 +#define ETH_MIB_EXCESSIVE_COLLISION 0x44 +#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48 +#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c +#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50 +#define ETH_MIB_FC_SENT 0x54 +#define ETH_MIB_GOOD_FC_RECEIVED 0x58 +#define ETH_MIB_BAD_FC_RECEIVED 0x5c +#define ETH_MIB_UNDERSIZE_RECEIVED 0x60 +#define ETH_MIB_FRAGMENTS_RECEIVED 0x64 +#define ETH_MIB_OVERSIZE_RECEIVED 0x68 +#define ETH_MIB_JABBER_RECEIVED 0x6c +#define ETH_MIB_MAC_RECEIVE_ERROR 0x70 +#define ETH_MIB_BAD_CRC_EVENT 0x74 +#define ETH_MIB_COLLISION 0x78 +#define ETH_MIB_LATE_COLLISION 0x7c + +/* Port serial status reg (PSR) */ +#define ETH_INTERFACE_GMII_MII 0 +#define ETH_INTERFACE_PCM BIT0 +#define ETH_LINK_IS_DOWN 0 +#define ETH_LINK_IS_UP BIT1 +#define ETH_PORT_AT_HALF_DUPLEX 0 +#define ETH_PORT_AT_FULL_DUPLEX BIT2 +#define ETH_RX_FLOW_CTRL_DISABLED 0 +#define ETH_RX_FLOW_CTRL_ENBALED BIT3 +#define ETH_GMII_SPEED_100_10 0 +#define ETH_GMII_SPEED_1000 BIT4 +#define ETH_MII_SPEED_10 0 +#define ETH_MII_SPEED_100 BIT5 +#define ETH_NO_TX 0 +#define ETH_TX_IN_PROGRESS BIT7 +#define ETH_BYPASS_NO_ACTIVE 0 +#define ETH_BYPASS_ACTIVE BIT8 +#define ETH_PORT_NOT_AT_PARTITION_STATE 0 +#define ETH_PORT_AT_PARTITION_STATE BIT9 +#define ETH_PORT_TX_FIFO_NOT_EMPTY 0 +#define ETH_PORT_TX_FIFO_EMPTY BIT10 + +/* These macros describes the Port configuration reg (Px_cR) bits */ +#define ETH_UNICAST_NORMAL_MODE 0 +#define ETH_UNICAST_PROMISCUOUS_MODE BIT0 +#define ETH_DEFAULT_RX_QUEUE_0 0 +#define ETH_DEFAULT_RX_QUEUE_1 BIT1 +#define ETH_DEFAULT_RX_QUEUE_2 BIT2 +#define ETH_DEFAULT_RX_QUEUE_3 (BIT2 | BIT1) +#define ETH_DEFAULT_RX_QUEUE_4 BIT3 +#define ETH_DEFAULT_RX_QUEUE_5 (BIT3 | BIT1) +#define ETH_DEFAULT_RX_QUEUE_6 (BIT3 | BIT2) +#define ETH_DEFAULT_RX_QUEUE_7 (BIT3 | BIT2 | BIT1) +#define ETH_DEFAULT_RX_ARP_QUEUE_0 0 +#define ETH_DEFAULT_RX_ARP_QUEUE_1 BIT4 +#define ETH_DEFAULT_RX_ARP_QUEUE_2 BIT5 +#define ETH_DEFAULT_RX_ARP_QUEUE_3 (BIT5 | BIT4) +#define ETH_DEFAULT_RX_ARP_QUEUE_4 BIT6 +#define ETH_DEFAULT_RX_ARP_QUEUE_5 (BIT6 | BIT4) +#define ETH_DEFAULT_RX_ARP_QUEUE_6 (BIT6 | BIT5) +#define ETH_DEFAULT_RX_ARP_QUEUE_7 (BIT6 | BIT5 | BIT4) +#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP 0 +#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP BIT7 +#define ETH_RECEIVE_BC_IF_IP 0 +#define ETH_REJECT_BC_IF_IP BIT8 +#define ETH_RECEIVE_BC_IF_ARP 0 +#define ETH_REJECT_BC_IF_ARP BIT9 +#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY BIT12 +#define ETH_CAPTURE_TCP_FRAMES_DIS 0 +#define ETH_CAPTURE_TCP_FRAMES_EN BIT14 +#define ETH_CAPTURE_UDP_FRAMES_DIS 0 +#define ETH_CAPTURE_UDP_FRAMES_EN BIT15 +#define ETH_DEFAULT_RX_TCP_QUEUE_0 0 +#define ETH_DEFAULT_RX_TCP_QUEUE_1 BIT16 +#define ETH_DEFAULT_RX_TCP_QUEUE_2 BIT17 +#define ETH_DEFAULT_RX_TCP_QUEUE_3 (BIT17 | BIT16) +#define ETH_DEFAULT_RX_TCP_QUEUE_4 BIT18 +#define ETH_DEFAULT_RX_TCP_QUEUE_5 (BIT18 | BIT16) +#define ETH_DEFAULT_RX_TCP_QUEUE_6 (BIT18 | BIT17) +#define ETH_DEFAULT_RX_TCP_QUEUE_7 (BIT18 | BIT17 | BIT16) +#define ETH_DEFAULT_RX_UDP_QUEUE_0 0 +#define ETH_DEFAULT_RX_UDP_QUEUE_1 BIT19 +#define ETH_DEFAULT_RX_UDP_QUEUE_2 BIT20 +#define ETH_DEFAULT_RX_UDP_QUEUE_3 (BIT20 | BIT19) +#define ETH_DEFAULT_RX_UDP_QUEUE_4 (BIT21 +#define ETH_DEFAULT_RX_UDP_QUEUE_5 (BIT21 | BIT19) +#define ETH_DEFAULT_RX_UDP_QUEUE_6 (BIT21 | BIT20) +#define ETH_DEFAULT_RX_UDP_QUEUE_7 (BIT21 | BIT20 | BIT19) +#define ETH_DEFAULT_RX_BPDU_QUEUE_0 0 +#define ETH_DEFAULT_RX_BPDU_QUEUE_1 BIT22 +#define ETH_DEFAULT_RX_BPDU_QUEUE_2 BIT23 +#define ETH_DEFAULT_RX_BPDU_QUEUE_3 (BIT23 | BIT22) +#define ETH_DEFAULT_RX_BPDU_QUEUE_4 BIT24 +#define ETH_DEFAULT_RX_BPDU_QUEUE_5 (BIT24 | BIT22) +#define ETH_DEFAULT_RX_BPDU_QUEUE_6 (BIT24 | BIT23) +#define ETH_DEFAULT_RX_BPDU_QUEUE_7 (BIT24 | BIT23 | BIT22) +#define ETH_DEFAULT_RX_TCP_CHKSUM_MODE BIT25 + +/* These macros describes the Port configuration extend reg (Px_cXR) bits*/ +#define ETH_CLASSIFY_EN BIT0 +#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL 0 +#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 BIT1 +#define ETH_PARTITION_DISABLE 0 +#define ETH_PARTITION_ENABLE BIT2 +#define ETH_TX_CRC_GENERATION_ENABLE 0 +#define ETH_TX_CRC_GENERATION_DISABLE BIT3 + +/* Tx/Rx queue command reg (RQCR/TQCR)*/ +#define ETH_QUEUE_0_ENABLE BIT0 +#define ETH_QUEUE_1_ENABLE BIT1 +#define ETH_QUEUE_2_ENABLE BIT2 +#define ETH_QUEUE_3_ENABLE BIT3 +#define ETH_QUEUE_4_ENABLE BIT4 +#define ETH_QUEUE_5_ENABLE BIT5 +#define ETH_QUEUE_6_ENABLE BIT6 +#define ETH_QUEUE_7_ENABLE BIT7 +#define ETH_QUEUE_0_DISABLE BIT8 +#define ETH_QUEUE_1_DISABLE BIT9 +#define ETH_QUEUE_2_DISABLE BIT10 +#define ETH_QUEUE_3_DISABLE BIT11 +#define ETH_QUEUE_4_DISABLE BIT12 +#define ETH_QUEUE_5_DISABLE BIT13 +#define ETH_QUEUE_6_DISABLE BIT14 +#define ETH_QUEUE_7_DISABLE BIT15 + +/* These macros describes the Port Sdma configuration reg (SDCR) bits */ +#define ETH_RIFB BIT0 +#define ETH_RX_BURST_SIZE_1_64BIT 0 +#define ETH_RX_BURST_SIZE_2_64BIT BIT1 +#define ETH_RX_BURST_SIZE_4_64BIT BIT2 +#define ETH_RX_BURST_SIZE_8_64BIT (BIT2 | BIT1) +#define ETH_RX_BURST_SIZE_16_64BIT BIT3 +#define ETH_BLM_RX_NO_SWAP BIT4 +#define ETH_BLM_RX_BYTE_SWAP 0 +#define ETH_BLM_TX_NO_SWAP BIT5 +#define ETH_BLM_TX_BYTE_SWAP 0 +#define ETH_DESCRIPTORS_BYTE_SWAP BIT6 +#define ETH_DESCRIPTORS_NO_SWAP 0 +#define ETH_TX_BURST_SIZE_1_64BIT 0 +#define ETH_TX_BURST_SIZE_2_64BIT BIT22 +#define ETH_TX_BURST_SIZE_4_64BIT BIT23 +#define ETH_TX_BURST_SIZE_8_64BIT (BIT23 | BIT22) +#define ETH_TX_BURST_SIZE_16_64BIT BIT24 + +/* These macros describes the Port serial control reg (PSCR) bits */ +#define ETH_SERIAL_PORT_DISABLE 0 +#define ETH_SERIAL_PORT_ENABLE BIT0 +#define ETH_FORCE_LINK_PASS BIT1 +#define ETH_DO_NOT_FORCE_LINK_PASS 0 +#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX 0 +#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX BIT2 +#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL 0 +#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL BIT3 +#define ETH_ADV_NO_FLOW_CTRL 0 +#define ETH_ADV_SYMMETRIC_FLOW_CTRL BIT4 +#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0 +#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS BIT5 +#define ETH_FORCE_BP_MODE_NO_JAM 0 +#define ETH_FORCE_BP_MODE_JAM_TX BIT7 +#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR BIT8 +#define ETH_FORCE_LINK_FAIL 0 +#define ETH_DO_NOT_FORCE_LINK_FAIL BIT10 +#define ETH_DISABLE_AUTO_NEG_SPEED_GMII BIT13 +#define ETH_ENABLE_AUTO_NEG_SPEED_GMII 0 +#define ETH_DTE_ADV_0 0 +#define ETH_DTE_ADV_1 BIT14 +#define ETH_MIIPHY_MAC_MODE 0 +#define ETH_MIIPHY_PHY_MODE BIT15 +#define ETH_AUTO_NEG_NO_CHANGE 0 +#define ETH_RESTART_AUTO_NEG BIT16 +#define ETH_MAX_RX_PACKET_1518BYTE 0 +#define ETH_MAX_RX_PACKET_1522BYTE BIT17 +#define ETH_MAX_RX_PACKET_1552BYTE BIT18 +#define ETH_MAX_RX_PACKET_9022BYTE (BIT18 | BIT17) +#define ETH_MAX_RX_PACKET_9192BYTE BIT19 +#define ETH_MAX_RX_PACKET_9700BYTE (BIT19 | BIT17) +#define ETH_SET_EXT_LOOPBACK BIT20 +#define ETH_CLR_EXT_LOOPBACK 0 +#define ETH_SET_FULL_DUPLEX_MODE BIT21 +#define ETH_SET_HALF_DUPLEX_MODE 0 +#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX BIT22 +#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0 +#define ETH_SET_GMII_SPEED_TO_10_100 0 +#define ETH_SET_GMII_SPEED_TO_1000 BIT23 +#define ETH_SET_MII_SPEED_TO_10 0 +#define ETH_SET_MII_SPEED_TO_100 BIT24 + +/* SMI register fields (KW_ETH_SMI_REG) */ +#define ETH_PHY_SMI_TIMEOUT 10000 +#define ETH_PHY_SMI_DATA_OFFS 0 /* Data */ +#define ETH_PHY_SMI_DATA_MASK (0xffff << ETH_PHY_SMI_DATA_OFFS) +#define ETH_PHY_SMI_DEV_ADDR_OFFS 16 /* PHY device address */ +#define ETH_PHY_SMI_DEV_ADDR_MASK (0x1f << ETH_PHY_SMI_DEV_ADDR_OFFS) +#define KW_ETH_SMI_REG_ADDR_OFFS 21 /* PHY device register address */ +#define KW_ETH_SMI_REG_ADDR_MASK (0x1f << KW_ETH_SMI_REG_ADDR_OFFS) +#define ETH_PHY_SMI_OPCODE_OFFS 26 /* Write/Read opcode */ +#define ETH_PHY_SMI_OPCODE_MASK (3 << ETH_PHY_SMI_OPCODE_OFFS) +#define ETH_PHY_SMI_OPCODE_WRITE (0 << ETH_PHY_SMI_OPCODE_OFFS) +#define ETH_PHY_SMI_OPCODE_READ (1 << ETH_PHY_SMI_OPCODE_OFFS) +#define ETH_PHY_SMI_READ_VALID_MASK BIT27 /* Read Valid */ +#define ETH_PHY_SMI_BUSY_MASK BIT28 /* Busy */ + +/* SDMA command status fields macros */ +/* Tx & Rx descriptors status */ +#define ETH_ERROR_SUMMARY (BIT0) + +/* Tx & Rx descriptors command */ +#define ETH_BUFFER_OWNED_BY_DMA (BIT31) + +/* Tx descriptors status */ +#define ETH_LC_ERROR (0 ) +#define ETH_UR_ERROR (BIT1 ) +#define ETH_RL_ERROR (BIT2 ) +#define ETH_LLC_SNAP_FORMAT (BIT9 ) + +/* Rx descriptors status */ +#define ETH_CRC_ERROR (0 ) +#define ETH_OVERRUN_ERROR (BIT1 ) +#define ETH_MAX_FRAME_LENGTH_ERROR (BIT2 ) +#define ETH_RESOURCE_ERROR ((BIT2 | BIT1)) +#define ETH_VLAN_TAGGED (BIT19) +#define ETH_BPDU_FRAME (BIT20) +#define ETH_TCP_FRAME_OVER_IP_V_4 (0 ) +#define ETH_UDP_FRAME_OVER_IP_V_4 (BIT21) +#define ETH_OTHER_FRAME_TYPE (BIT22) +#define ETH_LAYER_2_IS_ETH_V_2 (BIT23) +#define ETH_FRAME_TYPE_IP_V_4 (BIT24) +#define ETH_FRAME_HEADER_OK (BIT25) +#define ETH_RX_LAST_DESC (BIT26) +#define ETH_RX_FIRST_DESC (BIT27) +#define ETH_UNKNOWN_DESTINATION_ADDR (BIT28) +#define ETH_RX_ENABLE_INTERRUPT (BIT29) +#define ETH_LAYER_4_CHECKSUM_OK (BIT30) + +/* Rx descriptors byte count */ +#define ETH_FRAME_FRAGMENTED (BIT2) + +/* Tx descriptors command */ +#define ETH_LAYER_4_CHECKSUM_FIRST_DESC (BIT10) +#define ETH_FRAME_SET_TO_VLAN (BIT15) +#define ETH_TCP_FRAME (0 ) +#define ETH_UDP_FRAME (BIT16) +#define ETH_GEN_TCP_UDP_CHECKSUM (BIT17) +#define ETH_GEN_IP_V_4_CHECKSUM (BIT18) +#define ETH_ZERO_PADDING (BIT19) +#define ETH_TX_LAST_DESC (BIT20) +#define ETH_TX_FIRST_DESC (BIT21) +#define ETH_GEN_CRC (BIT22) +#define ETH_TX_ENABLE_INTERRUPT (BIT23) +#define ETH_AUTO_MODE (BIT30) + +/* Address decode parameters */ +/* Ethernet Base Address Register bits */ +#define EBAR_TARGET_DRAM 0x00000000 +#define EBAR_TARGET_DEVICE 0x00000001 +#define EBAR_TARGET_CBS 0x00000002 +#define EBAR_TARGET_PCI0 0x00000003 +#define EBAR_TARGET_PCI1 0x00000004 +#define EBAR_TARGET_CUNIT 0x00000005 +#define EBAR_TARGET_AUNIT 0x00000006 +#define EBAR_TARGET_GUNIT 0x00000007 + +/* Window attributes */ +#define EBAR_ATTR_DRAM_CS0 0x00000E00 +#define EBAR_ATTR_DRAM_CS1 0x00000D00 +#define EBAR_ATTR_DRAM_CS2 0x00000B00 +#define EBAR_ATTR_DRAM_CS3 0x00000700 + +/* DRAM Target interface */ +#define EBAR_ATTR_DRAM_NO_CACHE_COHERENCY 0x00000000 +#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WT 0x00001000 +#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WB 0x00002000 + +/* Device Bus Target interface */ +#define EBAR_ATTR_DEVICE_DEVCS0 0x00001E00 +#define EBAR_ATTR_DEVICE_DEVCS1 0x00001D00 +#define EBAR_ATTR_DEVICE_DEVCS2 0x00001B00 +#define EBAR_ATTR_DEVICE_DEVCS3 0x00001700 +#define EBAR_ATTR_DEVICE_BOOTCS3 0x00000F00 + +/* PCI Target interface */ +#define EBAR_ATTR_PCI_BYTE_SWAP 0x00000000 +#define EBAR_ATTR_PCI_NO_SWAP 0x00000100 +#define EBAR_ATTR_PCI_BYTE_WORD_SWAP 0x00000200 +#define EBAR_ATTR_PCI_WORD_SWAP 0x00000300 +#define EBAR_ATTR_PCI_NO_SNOOP_NOT_ASSERT 0x00000000 +#define EBAR_ATTR_PCI_NO_SNOOP_ASSERT 0x00000400 +#define EBAR_ATTR_PCI_IO_SPACE 0x00000000 +#define EBAR_ATTR_PCI_MEMORY_SPACE 0x00000800 +#define EBAR_ATTR_PCI_REQ64_FORCE 0x00000000 +#define EBAR_ATTR_PCI_REQ64_SIZE 0x00001000 + +/* Window access control */ +#define EWIN_ACCESS_NOT_ALLOWED 0 +#define EWIN_ACCESS_READ_ONLY BIT0 +#define EWIN_ACCESS_FULL (BIT1 | BIT0) + +/* typedefs */ + +typedef enum _eth_func_ret_status { + ETH_OK, /* Returned as expected. */ + ETH_ERROR, /* Fundamental error. */ + ETH_RETRY, /* Could not process request. Try later. */ + ETH_END_OF_JOB, /* Ring has nothing to process. */ + ETH_QUEUE_FULL, /* Ring resource error. */ + ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */ +} ETH_FUNC_RET_STATUS; + +typedef enum _eth_queue { + ETH_Q0 = 0, + ETH_Q1 = 1, + ETH_Q2 = 2, + ETH_Q3 = 3, + ETH_Q4 = 4, + ETH_Q5 = 5, + ETH_Q6 = 6, + ETH_Q7 = 7 +} ETH_QUEUE; + +typedef enum _addr_win { + ETH_WIN0, + ETH_WIN1, + ETH_WIN2, + ETH_WIN3, + ETH_WIN4, + ETH_WIN5 +} ETH_ADDR_WIN; + +typedef enum _eth_target { + ETH_TARGET_DRAM, + ETH_TARGET_DEVICE, + ETH_TARGET_CBS, + ETH_TARGET_PCI0, + ETH_TARGET_PCI1 +} ETH_TARGET; + +typedef struct _eth_rx_desc { + u32 cmd_sts; /* Descriptor command status */ + u16 buf_size; /* Buffer size */ + u16 byte_cnt; /* Descriptor buffer byte count */ + u32 buf_ptr; /* Descriptor buffer pointer */ + u32 next_desc_ptr; /* Next descriptor pointer */ + u32 return_info; /* User resource return information */ +} ETH_RX_DESC; + +typedef struct _eth_tx_desc { + u32 cmd_sts; /* Descriptor command status */ + u16 l4i_chk; /* CPU provided TCP Checksum */ + u16 byte_cnt; /* Descriptor buffer byte count */ + u32 buf_ptr; /* Descriptor buffer pointer */ + u32 next_desc_ptr; /* Next descriptor pointer */ + u32 return_info; /* User resource return information */ +} ETH_TX_DESC; + +/* + * Unified struct for Rx and Tx operations. The user is not required to + * be familier with neither Tx nor Rx descriptors. + */ +typedef struct _pkt_info { + u32 cmd_sts; /* Descriptor command status */ + u16 byte_cnt; /* Descriptor buffer byte count */ + u16 l4i_chk; /* Tx CPU provided TCP Checksum */ + u32 buf_ptr; /* Descriptor buffer pointer */ + u32 return_info; /* User resource return information */ +} PKT_INFO; + +typedef struct _eth_win_param { + ETH_ADDR_WIN win; /* Window number. See ETH_ADDR_WIN enum */ + ETH_TARGET target; /* System targets. See ETH_TARGET enum */ + u16 attributes; /* BAR attributes. See above macros */ + u32 base_addr; /* Window base address in u32 form */ + u32 high_addr; /* Window high address in u32 form */ + u32 size; /* Size in MBytes. Must be % 64Kbyte. */ + bool enable; /* Enable/disable access to the window. */ + u16 access_ctrl; /*Access ctrl register. see above macros */ +} ETH_WIN_PARAM; + +/* Ethernet port specific infomation */ +typedef struct _eth_port_ctrl { + ETH_PORT port_num; /* User Ethernet port number */ + int port_phy_addr; /* User phy address of Ethrnet port */ + u8 port_mac_addr[6]; /* User defined port MAC address. */ + u32 port_config; /* User port configuration value */ + u32 port_config_extend; /* User port config extend value */ + u32 port_sdma_config; /* User port SDMA config value */ + u32 port_serial_control; /* User port serial control value */ + u32 port_tx_queue_command; /* Port active Tx queues summary */ + u32 port_rx_queue_command; /* Port active Rx queues summary */ + + /* User function to cast virtual address to CPU bus address */ + u32 (*port_virt_to_phys) (u32 addr); + /* User scratch pad for user specific data structures */ + void *port_private; + + bool rx_resource_err[MAX_RX_QUEUE_NUM]; /* Rx ring resource err flag */ + bool tx_resource_err[MAX_TX_QUEUE_NUM]; /* Tx ring resource err flag */ + + /* Tx/Rx rings managment indexes fields. For driver use */ + + /* Next available Rx resource */ + volatile ETH_RX_DESC *p_rx_curr_desc_q[MAX_RX_QUEUE_NUM]; + /* Returning Rx resource */ + volatile ETH_RX_DESC *p_rx_used_desc_q[MAX_RX_QUEUE_NUM]; + + /* Next available Tx resource */ + volatile ETH_TX_DESC *p_tx_curr_desc_q[MAX_TX_QUEUE_NUM]; + /* Returning Tx resource */ + volatile ETH_TX_DESC *p_tx_used_desc_q[MAX_TX_QUEUE_NUM]; + /* An extra Tx index to support txmt of multiple buffs per packet */ + volatile ETH_TX_DESC *p_tx_first_desc_q[MAX_TX_QUEUE_NUM]; + + /* Tx/Rx rings size and base variables fields. For driver use */ + + volatile ETH_RX_DESC *p_rx_desc_area_base[MAX_RX_QUEUE_NUM]; + u32 rx_desc_area_size[MAX_RX_QUEUE_NUM]; + char *p_rx_buffer_base[MAX_RX_QUEUE_NUM]; + + volatile ETH_TX_DESC *p_tx_desc_area_base[MAX_TX_QUEUE_NUM]; + u32 tx_desc_area_size[MAX_TX_QUEUE_NUM]; + char *p_tx_buffer_base[MAX_TX_QUEUE_NUM]; + +} ETH_PORT_INFO; + + +/* Low level driver function calls */ +static void eth_clear_mib_counters(ETH_PORT eth_port_num); + +/* Port operation control routines */ +static void eth_port_init(ETH_PORT_INFO * p_eth_port_ctrl); +static void eth_port_reset(ETH_PORT eth_port_num); +static void eth_port_start(ETH_PORT_INFO * p_eth_port_ctrl); + +/* Port MAC address routines */ +static void eth_port_uc_addr_set(ETH_PORT eth_port_num, + u8 *p_addr, ETH_QUEUE queue); + +/* Port data flow control routines */ +static ETH_FUNC_RET_STATUS eth_port_send(ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO * p_pkt_info); +static ETH_FUNC_RET_STATUS eth_tx_return_desc(ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE tx_queue, + PKT_INFO * p_pkt_info); +static ETH_FUNC_RET_STATUS eth_port_receive(ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO * p_pkt_info); +static ETH_FUNC_RET_STATUS eth_rx_return_buff(ETH_PORT_INFO * p_eth_port_ctrl, + ETH_QUEUE rx_queue, + PKT_INFO * p_pkt_info); +#endif /* __EGIGA_H__ */ diff --git a/cpu/arm926ejs/kirkwood/egiga_regs.h b/cpu/arm926ejs/kirkwood/egiga_regs.h new file mode 100644 index 0000000..a24fa04 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/egiga_regs.h @@ -0,0 +1,161 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Prafulla Wadaskar prafulla@marvell.com + * + * (C) Copyright 2003 + * Ingo Assmus ingo.assmus@keymile.com + * + * based on - Driver for MV64360X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * 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 __EGIGA_REGS_H__ +#define __EGIGA_REGS_H__ + +/* + *Ethernet Controller Registers + */ +#define KW_ETH_PHY_ADDR_REG(port) (0x72000 + (port<<14)) +#define KW_ETH_SMI_REG(port) (0x72004 + (port<<14)) +#define KW_ETH_UNIT_DEFAULT_ADDR_REG(port) (0x72008 + (port<<14)) +#define KW_ETH_UNIT_DEFAULTID_REG(port) (0x7200c + (port<<14)) +#define KW_ETH_UNIT_INTERRUPT_CAUSE_REG(port) (0x72080 + (port<<14)) +#define KW_ETH_UNIT_INTERRUPT_MASK_REG(port) (0x72084 + (port<<14)) +#define KW_ETH_UNIT_ERROR_ADDR_REG(port) (0x72094 + (port<<14)) +#define KW_ETH_INTADR_ERROR_ADDR_REG(port) (0x72098 + (port<<14)) +#define KW_ETH_UNIT_CTRL_REG(port) (0x720b0 + (port<<14)) +#define KW_ETH_BAR_0(port) (0x72200 + (port<<14)) +#define KW_ETH_BAR_1(port) (0x72208 + (port<<14)) +#define KW_ETH_BAR_2(port) (0x72210 + (port<<14)) +#define KW_ETH_BAR_3(port) (0x72218 + (port<<14)) +#define KW_ETH_BAR_4(port) (0x72220 + (port<<14)) +#define KW_ETH_BAR_5(port) (0x72228 + (port<<14)) +#define KW_ETH_SIZE_REG_0(port) (0x72204 + (port<<14)) +#define KW_ETH_SIZE_REG_1(port) (0x7220c + (port<<14)) +#define KW_ETH_SIZE_REG_2(port) (0x72214 + (port<<14)) +#define KW_ETH_SIZE_REG_3(port) (0x7221c + (port<<14)) +#define KW_ETH_SIZE_REG_4(port) (0x72224 + (port<<14)) +#define KW_ETH_SIZE_REG_5(port) (0x7222c + (port<<14)) +#define KW_ETH_HIGH_ADDR_REMAP_REG_0(port) (0x72280 + (port<<14)) +#define KW_ETH_HIGH_ADDR_REMAP_REG_1(port) (0x72284 + (port<<14)) +#define KW_ETH_HIGH_ADDR_REMAP_REG_2(port) (0x72288 + (port<<14)) +#define KW_ETH_HIGH_ADDR_REMAP_REG_3(port) (0x7228c + (port<<14)) +#define KW_ETH_BASE_ADDR_ENABLE_REG(port) (0x72290 + (port<<14)) +#define KW_ETH_ACCESS_PROTECTION_REG(port) (0x72294 + (port<<14)) +#define KW_ETH_PORT_CONFIG_REG(port) (0x72400 + (port<<14)) +#define KW_ETH_PORT_CONFIG_EXTEND_REG(port) (0x72404 + (port<<14)) +#define KW_ETH_MII_SERIAL_PARAMETRS_REG(port) (0x72408 + (port<<14)) +#define KW_ETH_VLAN_ETHERTYPE_REG(port) (0x72410 + (port<<14)) +#define KW_ETH_MAC_ADDR_LOW(port) (0x72414 + (port<<14)) +#define KW_ETH_MAC_ADDR_HIGH(port) (0x72418 + (port<<14)) +#define KW_ETH_SDMA_CONFIG_REG(port) (0x7241c + (port<<14)) +#define KW_ETH_DSCP_0(port) (0x72420 + (port<<14)) +#define KW_ETH_DSCP_1(port) (0x72424 + (port<<14)) +#define KW_ETH_DSCP_2(port) (0x72428 + (port<<14)) +#define KW_ETH_DSCP_3(port) (0x7242c + (port<<14)) +#define KW_ETH_DSCP_4(port) (0x72430 + (port<<14)) +#define KW_ETH_DSCP_5(port) (0x72434 + (port<<14)) +#define KW_ETH_DSCP_6(port) (0x72438 + (port<<14)) +#define KW_ETH_PORT_SERIAL_CONTROL0_REG(port) (0x7243c + (port<<14)) +#define KW_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x72440 + (port<<14)) +#define KW_ETH_PORT_STATUS0_REG(port) (0x72444 + (port<<14)) +#define KW_ETH_PORT_SERIAL_CONTROL1_REG(port) (0x7244c + (port<<14)) +#define KW_ETH_PORT_STATUS1_REG(port) (0x72450 + (port<<14)) +#define KW_ETH_MARVELL_HEADER_REG(port) (0x72454 + (port<<14)) +#define KW_ETH_INTERRUPT_CAUSE_REG(port) (0x72460 + (port<<14)) +#define KW_ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x72464 + (port<<14)) +#define KW_ETH_INTERRUPT_MASK_REG(port) (0x72468 + (port<<14)) +#define KW_ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x7246c + (port<<14)) +#define KW_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x72474 + (port<<14)) +#define KW_ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x7247c + (port<<14)) +#define KW_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x72484 + (port<<14)) +#define KW_ETH_PORT_OVERRUN_FRM_COUNTER_REG(port) (0x72488 + (port<<14)) +#define KW_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x72494 + (port<<14)) +#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x7260c + (port<<14)) +#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x7261c + (port<<14)) +#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x7262c + (port<<14)) +#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x7263c + (port<<14)) +#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x7264c + (port<<14)) +#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x7265c + (port<<14)) +#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x7266c + (port<<14)) +#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x7267c + (port<<14)) +#define KW_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x72680 + (port<<14)) +#define KW_ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x72684 + (port<<14)) +#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x726c0 + (port<<14)) +#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x726c4 + (port<<14)) +#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x726c8 + (port<<14)) +#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x726cc + (port<<14)) +#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x726d0 + (port<<14)) +#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x726d4 + (port<<14)) +#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x726d8 + (port<<14)) +#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x726dc + (port<<14)) +#define KW_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x73400 + (port<<14)) +#define KW_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x73500 + (port<<14)) +#define KW_ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x73600 + (port<<14)) +#define KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x72448 + (port<<14)) +#define KW_ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x724dc + (port<<14)) +#define KW_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x724e0 + (port<<14)) +#define KW_ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x724e8 + (port<<14)) +#define KW_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x724ec + (port<<14)) +#define KW_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x72700 + (port<<14)) +#define KW_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x72710 + (port<<14)) +#define KW_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x72720 + (port<<14)) +#define KW_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x72730 + (port<<14)) +#define KW_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x72740 + (port<<14)) +#define KW_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x72750 + (port<<14)) +#define KW_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x72760 + (port<<14)) +#define KW_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x72770 + (port<<14)) +#define KW_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x72704 + (port<<14)) +#define KW_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x72714 + (port<<14)) +#define KW_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x72724 + (port<<14)) +#define KW_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x72734 + (port<<14)) +#define KW_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x72744 + (port<<14)) +#define KW_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x72754 + (port<<14)) +#define KW_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x72764 + (port<<14)) +#define KW_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x72774 + (port<<14)) +#define KW_ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x72708 + (port<<14)) +#define KW_ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x72718 + (port<<14)) +#define KW_ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x72728 + (port<<14)) +#define KW_ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x72738 + (port<<14)) +#define KW_ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x72748 + (port<<14)) +#define KW_ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x72758 + (port<<14)) +#define KW_ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x72768 + (port<<14)) +#define KW_ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x72778 + (port<<14)) +#define KW_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x72780 + (port<<14)) + +#define KW_ETH_MIB_COUNTERS_BASE(port) (0x73000 + (port<<14)) + +/* Type defs */ +#ifndef __ASSEMBLY__ +typedef enum _eth_port { + ETH_0 = 0, + ETH_1 = 1, +} ETH_PORT; /* SOC has two Gbe Ports */ + +/* smi register read/write function can be used by switch/phy */ +int eth_smi_reg_read(unsigned int eth_port_num, unsigned int phy_adr, + unsigned int reg_ofs, unsigned short *data); +int eth_smi_reg_write(unsigned int eth_port_num, unsigned int phy_adr, + unsigned int reg_ofs, unsigned short data); +#endif + +#endif /* __EGIGA_REGS_H__ */ diff --git a/cpu/arm926ejs/kirkwood/kwcore.h b/cpu/arm926ejs/kirkwood/kwcore.h index 0ddc6a8..50043d8 100644 --- a/cpu/arm926ejs/kirkwood/kwcore.h +++ b/cpu/arm926ejs/kirkwood/kwcore.h @@ -87,6 +87,8 @@ #define KW_REG_TMR_RELOAD (0x20310) #define KW_REG_TMR_VAL (0x20314)
+#include "egiga_regs.h" + /* * Macros * CPU architecture dependent I/O read/write diff --git a/net/eth.c b/net/eth.c index 4bbf84b..77fa8a5 100644 --- a/net/eth.c +++ b/net/eth.c @@ -73,6 +73,7 @@ int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));
extern int mv6436x_eth_initialize(bd_t *); extern int mv6446x_eth_initialize(bd_t *); +extern int kirkwood_egiga_initialize(bd_t*);
#ifdef CONFIG_API extern void (*push_packet)(volatile void *, int); @@ -205,6 +206,9 @@ int eth_initialize(bd_t *bis) #if defined(CONFIG_DB64460) || defined(CONFIG_P3Mx) mv6446x_eth_initialize(bis); #endif +#ifdef CONFIG_KIRKWOOD_EGIGA + kirkwood_egiga_initialize(bis); +#endif if (!eth_devices) { puts ("No ethernet found.\n"); show_boot_progress (-64);

On Friday 03 April 2009 18:39:28 Prafulla Wadaskar wrote:
--- a/net/eth.c +++ b/net/eth.c @@ -73,6 +73,7 @@ int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));
extern int mv6436x_eth_initialize(bd_t *); extern int mv6446x_eth_initialize(bd_t *); +extern int kirkwood_egiga_initialize(bd_t*);
#ifdef CONFIG_API extern void (*push_packet)(volatile void *, int); @@ -205,6 +206,9 @@ int eth_initialize(bd_t *bis) #if defined(CONFIG_DB64460) || defined(CONFIG_P3Mx) mv6446x_eth_initialize(bis); #endif +#ifdef CONFIG_KIRKWOOD_EGIGA
kirkwood_egiga_initialize(bis);
+#endif if (!eth_devices) { puts ("No ethernet found.\n"); show_boot_progress (-64);
this should be dying, not new additions. define board_eth_init() like everyone else now. -mike

Prafulla Wadaskar wrote:
From: prafulla_wadaskar prafulla@marvell.com
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com
<snip>
diff --git a/net/eth.c b/net/eth.c index 4bbf84b..77fa8a5 100644 --- a/net/eth.c +++ b/net/eth.c @@ -73,6 +73,7 @@ int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));
extern int mv6436x_eth_initialize(bd_t *); extern int mv6446x_eth_initialize(bd_t *); +extern int kirkwood_egiga_initialize(bd_t*);
#ifdef CONFIG_API extern void (*push_packet)(volatile void *, int); @@ -205,6 +206,9 @@ int eth_initialize(bd_t *bis) #if defined(CONFIG_DB64460) || defined(CONFIG_P3Mx) mv6446x_eth_initialize(bis); #endif +#ifdef CONFIG_KIRKWOOD_EGIGA
kirkwood_egiga_initialize(bis);
+#endif if (!eth_devices) { puts ("No ethernet found.\n"); show_boot_progress (-64);
I believe Mike mentioned this already, but you shouldn't be initializing your drivers here. You'll notice that this area of code is much smaller than it used to be, and the only drivers left are Marvell ones. I started cleaning them up, but the work was huge and lacking hardware I was nervous about breaking things. IIRC, the MV6436X and MV6446X drivers duplicate code > 99%.
regards, Ben

-----Original Message----- From: Ben Warren [mailto:biggerbadderben@gmail.com] Sent: Saturday, April 04, 2009 12:44 AM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ronen Shitrit Subject: Re: [U-Boot] [PATCH] Gbe Controller driver support for kirkwood SOCs
Prafulla Wadaskar wrote:
From: prafulla_wadaskar prafulla@marvell.com
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com
Reviewed by:
Ronen Shitrit rshitrit@marvell.com
<snip> > diff --git a/net/eth.c b/net/eth.c > index 4bbf84b..77fa8a5 100644 > --- a/net/eth.c > +++ b/net/eth.c > @@ -73,6 +73,7 @@ int board_eth_init(bd_t *bis) __attribute((weak, > alias("__def_eth_init"))); > > extern int mv6436x_eth_initialize(bd_t *); extern int > mv6446x_eth_initialize(bd_t *); > +extern int kirkwood_egiga_initialize(bd_t*); > > #ifdef CONFIG_API > extern void (*push_packet)(volatile void *, int); @@ -205,6 +206,9 @@ > int eth_initialize(bd_t *bis) #if defined(CONFIG_DB64460) || > defined(CONFIG_P3Mx) > mv6446x_eth_initialize(bis); > #endif > +#ifdef CONFIG_KIRKWOOD_EGIGA > + kirkwood_egiga_initialize(bis); #endif > if (!eth_devices) { > puts ("No ethernet found.\n"); > show_boot_progress (-64); > I believe Mike mentioned this already, but you shouldn't be initializing your drivers here. You'll notice that this area of code is much smaller than it used to be, and the only drivers left are Marvell ones. I started cleaning them up, but the work was huge and lacking hardware I was nervous about breaking things. IIRC, the MV6436X and MV6446X drivers duplicate code > 99%.
Hi Ben Neither I have all other hardware with me. While creating this driver I had this question in my mind But at safer side I decided not to broke other things...
It will be my pleasure to co-operate to sort this out..
Regards.. Prafulla ..
regards, Ben

Dear Prafulla Wadaskar,
In message 1238798370-9245-3-git-send-email-prafulla@marvell.com you wrote:
From: prafulla_wadaskar prafulla@marvell.com
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com
...
diff --git a/cpu/arm926ejs/kirkwood/Makefile b/cpu/arm926ejs/kirkwood/Makefile index 41ac8d7..3e20898 100644 --- a/cpu/arm926ejs/kirkwood/Makefile +++ b/cpu/arm926ejs/kirkwood/Makefile @@ -30,6 +30,7 @@ COBJS-y = timer.o COBJS-y += serial.o COBJS-y += kwcore.o COBJS-y += dram.o +COBJS-y += egiga.o
Please sort such lists.
...
+int eth_smi_reg_read(u32 eth_port_num, u32 phy_adr, u32 reg_ofs, u16 * data) +{
- u32 smi_reg;
- volatile u32 timeout;
- /* check parameters */
- if ((phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) {
Line too long. (Hint: consider using shorter names! :-)
...
- /* fill the phy address and regiser offset and read opcode */
- smi_reg =
(phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) | (reg_ofs <<
KW_ETH_SMI_REG_ADDR_OFFS)
| ETH_PHY_SMI_OPCODE_READ;
Please clean up indentation here.
...
+static int egiga_free_rx_rings(struct eth_device *dev) +{
- u32 queue;
- ETH_PORT_INFO *ethernet_private;
- struct egiga_priv *port_private;
- u32 port_num;
- volatile ETH_RX_DESC *p_rx_curr_desc;
- ethernet_private = (ETH_PORT_INFO *) dev->priv;
- port_private = (struct egiga_priv *)ethernet_private->port_private;
- port_num = port_private->port_num;
- /* Stop RX Queues */
- KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
- /* Free RX rings */
- debug_print("Clearing previously allocated RX queues... ");
- for (queue = 0; queue < KW_RX_QUEUE_NUM; queue++) {
/* Free preallocated skb's on RX rings */
for (p_rx_curr_desc =
ethernet_private->p_rx_desc_area_base[queue];
(((u32)p_rx_curr_desc <
((u32)ethernet_private->
p_rx_desc_area_base[queue] +
ethernet_private->rx_desc_area_size[queue])));
p_rx_curr_desc =
(ETH_RX_DESC *) ((u32)p_rx_curr_desc +
RX_DESC_ALIGNED_SIZE)) {
if (p_rx_curr_desc->return_info != 0) {
p_rx_curr_desc->return_info = 0;
debug_print("freed");
}
... and here. Such code is basicly unreadable.
...
+static ETH_FUNC_RET_STATUS eth_port_send(ETH_PORT_INFO * p_eth_port_ctrl,
ETH_QUEUE tx_queue,
PKT_INFO * p_pkt_info)
+{
- volatile ETH_TX_DESC *p_tx_desc_first;
- volatile ETH_TX_DESC *p_tx_desc_curr;
- volatile ETH_TX_DESC *p_tx_next_desc_curr;
- volatile ETH_TX_DESC *p_tx_desc_used;
- u32 command_status;
+#ifdef CONFIG_TX_PKT_DISPLAY
- {
u16 pcnt = p_pkt_info->byte_cnt;
u8 *prndt = (char *)p_pkt_info->buf_ptr;
printf("cnt=%d ", pcnt);
Blank line after declarations, please (check gloabally, please).
Also, pelase try to acoid such nested blocks with additional declarations.
while (pcnt) {
printf("%02x,", prndt[0]);
prndt++;
pcnt--;
}
printf(" pckend \n");
- }
+#endif
...
diff --git a/cpu/arm926ejs/kirkwood/egiga.h b/cpu/arm926ejs/kirkwood/egiga.h new file mode 100644 index 0000000..83dc4b3 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/egiga.h @@ -0,0 +1,707 @@
...
+#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif
Omit?
...
+struct net_device_stats {
- u32 rx_packets; /* total packets received */
- u32 tx_packets; /* total packets transmitted */
- u32 rx_bytes; /* total bytes received */
- u32 tx_bytes; /* total bytes transmitted */
- u32 rx_errors; /* bad packets received */
- u32 tx_errors; /* packet transmit problems */
- u32 rx_dropped; /* no space in linux buffers */
- u32 tx_dropped; /* no space available in linux */
- u32 multicast; /* multicast packets received */
- u32 collisions;
- /* detailed rx_errors: */
- u32 rx_length_errors;
- u32 rx_over_errors; /* receiver ring buff overflow */
- u32 rx_crc_errors; /* recved pkt with crc error */
- u32 rx_frame_errors; /* recv'd frame alignment error */
- u32 rx_fifo_errors; /* recv'r fifo overrun */
- u32 rx_missed_errors; /* receiver missed packet */
- /* detailed tx_errors */
- u32 tx_aborted_errors;
- u32 tx_carrier_errors;
- u32 tx_fifo_errors;
- u32 tx_heartbeat_errors;
- u32 tx_window_errors;
- /* for cslip etc */
- u32 rx_compressed;
- u32 tx_compressed;
+};
+/* Private data structure used for ethernet device */ +struct egiga_priv {
- u32 port_num;
- struct net_device_stats *stats;
- /* to buffer area aligned */
- char *p_eth_tx_buffer[KW_TX_QUEUE_SIZE + 1];
- char *p_eth_rx_buffer[KW_RX_QUEUE_SIZE + 1];
- /* Size of Tx Ring per queue */
- u32 tx_ring_size[MAX_TX_QUEUE_NUM];
- /* Size of Rx Ring per queue */
- u32 rx_ring_size[MAX_RX_QUEUE_NUM];
- /* Magic Number for Ethernet running */
- u32 eth_running;
+};
Please use TABs for vertical alignment to make the code readable.
...
+/* Gap define */ +#define ETH_BAR_GAP 0x8 +#define ETH_SIZE_REG_GAP 0x8 +#define ETH_HIGH_ADDR_REMAP_REG_GAP 0x4 +#define ETH_PORT_ACCESS_CTRL_GAP 0x4 +/* MIB Counters register definitions */ +#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0 +#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4 +#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8 +#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc +#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10 +#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14 +#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18 +#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c
... and so on:
Please use TABs for vertical alignment to make the code better readable.
This applies to the rest of file, too.
diff --git a/cpu/arm926ejs/kirkwood/egiga_regs.h b/cpu/arm926ejs/kirkwood/egiga_regs.h new file mode 100644 index 0000000..a24fa04 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/egiga_regs.h
...
+/*
- *Ethernet Controller Registers
- */
+#define KW_ETH_PHY_ADDR_REG(port) (0x72000 + (port<<14)) +#define KW_ETH_SMI_REG(port) (0x72004 + (port<<14)) +#define KW_ETH_UNIT_DEFAULT_ADDR_REG(port) (0x72008 + (port<<14)) +#define KW_ETH_UNIT_DEFAULTID_REG(port) (0x7200c + (port<<14)) +#define KW_ETH_UNIT_INTERRUPT_CAUSE_REG(port) (0x72080 + (port<<14)) +#define KW_ETH_UNIT_INTERRUPT_MASK_REG(port) (0x72084 + (port<<14))
...
Use C structures to describe the device layout, and you can get rid of this ugly code.
Best regards,
Wolfgang Denk

From: prafulla_wadaskar prafulla@marvell.com
Chips supprted:- 1. 88E61XX 6 port gbe swtich with 5 integrated PHYs 2. 88E6061 6 port fe swtich with 5 integrated PHYs 3. 88E1116 gbe transceiver
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com --- board/Marvell/common/mv88e1116.c | 72 +++++++ board/Marvell/common/mv88e60xx.c | 409 +++++++++++++++++++++++++++++++++++++ board/Marvell/common/mv88e61xx.c | 414 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 895 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/common/mv88e1116.c create mode 100644 board/Marvell/common/mv88e60xx.c create mode 100644 board/Marvell/common/mv88e61xx.c
diff --git a/board/Marvell/common/mv88e1116.c b/board/Marvell/common/mv88e1116.c new file mode 100644 index 0000000..87ec550 --- /dev/null +++ b/board/Marvell/common/mv88e1116.c @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Prafulla Wadaskar prafulla@marvell.com + * + * Contributors + * + * 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 MV88E1116_DEBUG +#define MV88E1116_DEBUG 0 +#endif +#define DEBUG_PRINT MV88E1116_DEBUG + +#include <common.h> +#include <debug_prints.h> +#include "../common/ppc_error_no.h" + +#if defined (CONFIG_PHY_88E1116) + +/* + * Marvell 88E1116 PHY initialization + */ +void mv_phy_88e1116_init(u32 eth_port_num) +{ + u16 reg; + u32 smi_dev_addr; + + debug_print_ftrace(); + smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(eth_port_num)); + + /* Leds link and activity */ + eth_smi_reg_write(eth_port_num, smi_dev_addr, 22, 0x3); + eth_smi_reg_read(eth_port_num, smi_dev_addr, 16, ®); + reg &= ~0xf; + reg |= 0x1; + eth_smi_reg_write(eth_port_num, smi_dev_addr, 16, reg); + eth_smi_reg_write(eth_port_num, smi_dev_addr, 22, 0x0); + + /* Set RGMII delay */ + eth_smi_reg_write(eth_port_num, smi_dev_addr, 22, 2); + eth_smi_reg_read(eth_port_num, smi_dev_addr, 21, ®); + reg |= (BIT5 | BIT4); + eth_smi_reg_write(eth_port_num, smi_dev_addr, 21, reg); + eth_smi_reg_write(eth_port_num, smi_dev_addr, 22, 0); + + /* reset the phy */ + eth_smi_reg_read(eth_port_num, smi_dev_addr, 0, ®); + reg |= BIT15; + eth_smi_reg_write(eth_port_num, smi_dev_addr, 0, reg); + + info_print("88E1116 Initialized"); +} + +#endif /* CONFIG_PHY_88E61XX */ diff --git a/board/Marvell/common/mv88e60xx.c b/board/Marvell/common/mv88e60xx.c new file mode 100644 index 0000000..6034f7b --- /dev/null +++ b/board/Marvell/common/mv88e60xx.c @@ -0,0 +1,409 @@ +/* + * (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 MV88E60XX_DEBUG +#define MV88E60XX_DEBUG 0 +#endif +#define DEBUG_PRINT MV88E60XX_DEBUG + +#include <common.h> +#include <debug_prints.h> +#include "../common/ppc_error_no.h" +#include <command.h> +#include <environment.h> +#include <watchdog.h> +#include <serial.h> +#include <linux/stddef.h> +#include <asm/byteorder.h> +#if defined(CONFIG_CMD_NET) +#include <net.h> +#endif + +#if defined (CONFIG_SWITCH_88E60XX) + +/* CPU port can be configured in board header file */ +#if defined (CONFIG_SWITCH_88E60XX_CPU_PORT) +#define MV88E60XX_CPU_PORT CONFIG_SWITCH_88E60XX_CPU_PORT +#else +#define MV88E60XX_CPU_PORT 0x5 +#endif +/* Enabled ports can be configured in board header file */ +#if defined (CONFIG_SWITCH_88E60XX_ENABLED_PORTS) +#define MV88E60XX_ENABLED_PORTS CONFIG_SWITCH_88E60XX_ENABLED_PORTS +#else +#define MV88E60XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \ + BIT3 | BIT4 | BIT5) +#endif + +#ifdef CONFIG_SWITCH_MV88E6061 +#define MV88E60XX_NAME "88E6061" +#else +#define MV88E60XX_NAME "88E60xx" +#endif +#define MV88E60XX_PHY_TIMEOUT 100000 +#define MV88E60XX_MAX_PORTS_NUM 0x6 + +#define MV88E60XX_PORT_STATUS_REG 0x1 +#define MV88E60XX_PORT_CONTROL_REG 0x4 +#define MV88E60XX_PORT_VMAP_REG 0x6 +#define MV88E60XX_PORT_VID_REG 0x7 + +#define MV88E60XX_PHY_SPEC_CONTROL_REG 0x10 +#define MV88E60XX_PHY_CONTROL_REG 0x00 + +#define MV88E60XX_PHY_OFFSET 0x10 +#define MV88E60XX_PORTS_OFFSET 0x18 +#define MV88E60XX_SMI_PHY_COMMAND 0x18 +#define MV88E60XX_SMI_PHY_DATA 0x19 +#define MV88E60XX_GLOBAL_2_REG_DEV_ADDR 0x1C + +#define MV88E60XX_PORT_STATUS_BIT_LINKUP BIT2 + +#define mv_sw_eth_phy_reg_write eth_smi_reg_write +#define mv_sw_eth_phy_reg_read eth_smi_reg_read + +static void mv_switch_88e60xx_vlan_init(u32 eth_port_num, + u32 switch_cpu_port, + u32 switch_max_ports_num, + u32 switch_ports_ofs, + u32 switch_enabled_ports_mask) +{ + u32 prt; + u16 reg; + + debug_print_ftrace(); + /* be sure all ports are disabled */ + for (prt = 0; prt < switch_max_ports_num; prt++) { + mv_sw_eth_phy_reg_read(eth_port_num, (switch_ports_ofs + prt), + MV88E60XX_PORT_CONTROL_REG, ®); + reg &= ~0x3; + mv_sw_eth_phy_reg_write(eth_port_num, (switch_ports_ofs + prt), + MV88E60XX_PORT_CONTROL_REG, reg); + } + /* Set CPU port VID to 0x1 */ + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + switch_cpu_port), + MV88E60XX_PORT_VID_REG, ®); + reg &= ~0xfff; + reg |= 0x1; + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + switch_cpu_port), + MV88E60XX_PORT_VID_REG, reg); + /* Setting Port default priority for all ports to zero */ + for (prt = 0; prt < switch_max_ports_num; prt++) { + mv_sw_eth_phy_reg_read(eth_port_num, (switch_ports_ofs + prt), + MV88E60XX_PORT_VID_REG, ®); + reg &= ~0xc000; + mv_sw_eth_phy_reg_write(eth_port_num, (switch_ports_ofs + prt), + MV88E60XX_PORT_VID_REG, reg); + } + /* Setting VID and VID map for all ports except CPU port */ + for (prt = 0; prt < switch_max_ports_num; prt++) { + /* only for enabled ports */ + if ((1 << prt) & switch_enabled_ports_mask) { + /* skip CPU port */ + if (prt == switch_cpu_port) + continue; + + /* + * set Ports VLAN Mapping. + * port prt <--> MV88E60XX_CPU_PORT VLAN #prt+1. + */ + + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + prt), + MV88E60XX_PORT_VID_REG, ®); + reg &= ~0x0fff; + reg |= (prt + 1); + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + prt), + MV88E60XX_PORT_VID_REG, reg); + + /* Set Vlan map table for all ports to send only to MV88E60XX_CPU_PORT */ + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + prt), + MV88E60XX_PORT_VMAP_REG, ®); + reg &= ~((1 << switch_max_ports_num) - 1); + reg |= (1 << switch_cpu_port); + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + prt), + MV88E60XX_PORT_VMAP_REG, reg); + } + } + /* Set Vlan map table for MV88E60XX_CPU_PORT to see all ports */ + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + switch_cpu_port), + MV88E60XX_PORT_VMAP_REG, ®); + reg &= ~((1 << switch_max_ports_num) - 1); + reg |= switch_enabled_ports_mask & ~(1 << switch_cpu_port); + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + switch_cpu_port), + MV88E60XX_PORT_VMAP_REG, reg); + + /*enable only appropriate ports to forwarding mode - and disable the others */ + for (prt = 0; prt < switch_max_ports_num; prt++) { + + if ((1 << prt) & switch_enabled_ports_mask) { + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + prt), + MV88E60XX_PORT_CONTROL_REG, + ®); + reg |= 0x3; + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + prt), + MV88E60XX_PORT_CONTROL_REG, + reg); + } else { + /* Disable port */ + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + prt), + MV88E60XX_PORT_CONTROL_REG, + ®); + reg &= ~0x3; + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + prt), + MV88E60XX_PORT_CONTROL_REG, + reg); + } + } +} + +/* + * Marvell 88E60XX Switch initialization + */ +int mv_switch_88e60xx_init(u32 eth_port_num) +{ + u32 prt; + u16 reg; + volatile u32 timeout; + + debug_print_ftrace(); + + /* Init vlan */ + mv_switch_88e60xx_vlan_init(eth_port_num, MV88E60XX_CPU_PORT, + MV88E60XX_MAX_PORTS_NUM, + MV88E60XX_PORTS_OFFSET, + MV88E60XX_ENABLED_PORTS); + for (prt = 0; prt < MV88E60XX_MAX_PORTS_NUM; prt++) { + if (prt != MV88E60XX_CPU_PORT) { + /*Enable Phy power up */ + mv_sw_eth_phy_reg_write(eth_port_num, + (MV88E60XX_PHY_OFFSET + prt), + MV88E60XX_PHY_CONTROL_REG, + 0xA100); + } + /*Enable port */ + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E60XX_PORTS_OFFSET + prt, 4, 0x17f); + } + /*Force CPU port to RGMII FDX 100Base */ + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E60XX_PORTS_OFFSET + MV88E60XX_CPU_PORT, 1, + 0x3d); + + info_print(MV88E60XX_NAME " Initialized"); + return 0; +} + +#if defined(CONFIG_CMD_SMIRW) +int smi_read_command(u32 smiaddr, u32 regaddr, u32 page) +{ + int prt = page; + u32 value; + + mv_sw_eth_phy_reg_read(0, smiaddr, regaddr, &value); + printf("smiread(smiaddr %x, regaddr %x, page %d)=%04x\n", smiaddr, + regaddr, page, (u16) value); + return 0; +} + +int smi_write_command(u32 smiaddr, u32 regaddr, u32 page, u32 value) +{ + int prt = page; + u32 page_backup = 0; + + mv_sw_eth_phy_reg_write(0, smiaddr, regaddr, value); + printf("smiwrite(smiaddr %x, regaddr %x, page %d) written =%04x\n", + smiaddr, regaddr, page, value); + return 0; +} + +/* + * "smi read [smiaddr] [regaddr] [page]\n" + * " - read smi register command\n" + * "smi write [smiaddr] [regaddr] [value] [page]\n" + * " - write <value> to <regaddr> register command\n" + */ +int do_smi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + u32 smiaddr = 0, regaddr = 0, value = 0, page = 0, size = 0; + char cmd = ' '; + + if (argc > 1) + cmd = argv[1][0]; + + switch (cmd) { + case 'r': /* read */ + if (argc > 2) + smiaddr = simple_strtoul(argv[2], NULL, 16); + if (argc > 3) + regaddr = simple_strtoul(argv[3], NULL, 16); + if (argc > 4) + page = simple_strtoul(argv[4], NULL, 16); + break; + case 'w': /* write */ + if (argc < 4) + goto usage; + smiaddr = simple_strtoul(argv[2], NULL, 16); + regaddr = simple_strtoul(argv[3], NULL, 16); + value = simple_strtoul(argv[4], NULL, 16); + if (argc > 5) + page = simple_strtoul(argv[5], NULL, 16); + break; + default: + usage: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + switch (argv[1][0]) { + case 'r': /* read */ + smi_read_command(smiaddr, regaddr, page); + return 0; + case 'w': /* write */ + smi_write_command(smiaddr, regaddr, page, value); + return 0; + } + return 1; +} + +U_BOOT_CMD(smi, CONFIG_SYS_MAXARGS, 1, do_smi, + "smi - isues read/write command on smi for switch registers\n", + "smi read [smiaddr] [regaddr] [page]\n" + " - read smi register command\n" + "smi write [smiaddr] [regaddr] [value] [page]\n" + " - write <value> to <regaddr> register command\n" + " - run the commands in the environment variable(s) 'var'\n"); + +#endif /* CONFIG_CMD_SMIRW */ + +#if defined(CONFIG_CMD_DUMP60XXPHY) +static void phy_busywait(u32 eth_port_num) +{ + u32 timeout; + u16 reg; + + timeout = MV88E60XX_PHY_TIMEOUT; + do { + mv_sw_eth_phy_reg_read(eth_port_num, + MV88E60XX_GLOBAL_2_REG_DEV_ADDR, + MV88E60XX_SMI_PHY_COMMAND, ®); + if (timeout-- == 0) { + error_print("SMI busy timeout"); + return -1; + } + } while (reg & BIT28); /* busy mask */ +} + +int do_dump60xxphy(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +#define SMI_CMD_BUSY_OFFSET 15 +#define SMI_CMD_MODE_OFFSET 12 +#define SMI_CMD_OP_OFFSET 10 +#define SMI_CMD_ADDR_OFFSET 5 + + int page, i, prt; + int eth_port_num = 0; + u32 reg; + + /* set page address to 3 */ + prt = 0; + for (page = 0; page < 7; page++) { + if (page == 1) + continue; + if (page == 4) + continue; + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E60XX_GLOBAL_2_REG_DEV_ADDR, + MV88E60XX_SMI_PHY_DATA, page); + + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E60XX_GLOBAL_2_REG_DEV_ADDR, + MV88E60XX_SMI_PHY_COMMAND, + (1 << SMI_CMD_BUSY_OFFSET | 1 << + SMI_CMD_MODE_OFFSET | 1 << + SMI_CMD_OP_OFFSET | prt << + SMI_CMD_ADDR_OFFSET | 22)); + + /* read and display phy registers */ + for (i = 0; i < 29; i++) { + if (page != 0) { + if (i < 16) + continue; + if (i == 22) + continue; + } + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E60XX_GLOBAL_2_REG_DEV_ADDR, + MV88E60XX_SMI_PHY_COMMAND, + (1 << SMI_CMD_BUSY_OFFSET | 1 << + SMI_CMD_MODE_OFFSET | 2 << + SMI_CMD_OP_OFFSET | prt << + SMI_CMD_ADDR_OFFSET | i)); + + phy_busywait(eth_port_num); + reg = 0x0; + mv_sw_eth_phy_reg_read(eth_port_num, + MV88E60XX_GLOBAL_2_REG_DEV_ADDR, + MV88E60XX_SMI_PHY_DATA, ®); + + printf("page %d reg %02d = %04x\n", page, i, (u16) reg); + } + } + + /* restore page address to zero */ + reg = 0; + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, MV88E60XX_GLOBAL_2_REG_DEV_ADDR, + MV88E60XX_SMI_PHY_DATA, reg); + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, MV88E60XX_GLOBAL_2_REG_DEV_ADDR, + MV88E60XX_SMI_PHY_COMMAND, + (1 << SMI_CMD_BUSY_OFFSET | 1 << + SMI_CMD_MODE_OFFSET | 1 << SMI_CMD_OP_OFFSET | + prt << SMI_CMD_ADDR_OFFSET | 22)); + + return 0; +} + +U_BOOT_CMD(dump60xxphy, CONFIG_SYS_MAXARGS, 1, do_dump60xxphy, + "dump60xxphy - dump 88360xx registers\n", + "var [...]\n" + " - run the commands in the environment variable(s) 'var'\n"); +#endif /* CONFIG_CMD_DUMP60XXPHY */ + +#endif /* CONFIG_SWITCH_88E60XX */ diff --git a/board/Marvell/common/mv88e61xx.c b/board/Marvell/common/mv88e61xx.c new file mode 100644 index 0000000..72a58eb --- /dev/null +++ b/board/Marvell/common/mv88e61xx.c @@ -0,0 +1,414 @@ +/* + * (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 MV88E61XX_DEBUG +#define MV88E61XX_DEBUG 0 +#endif +#define DEBUG_PRINT MV88E61XX_DEBUG + +#include <common.h> +#include <debug_prints.h> +#include "../common/ppc_error_no.h" +#include <command.h> +#include <environment.h> +#include <watchdog.h> +#include <serial.h> +#include <linux/stddef.h> +#include <asm/byteorder.h> +#if defined(CONFIG_CMD_NET) +#include <net.h> +#endif + +#if defined (CONFIG_SWITCH_88E61XX) + +/* CPU port can be configured in board header file */ +#if defined (CONFIG_SWITCH_88E61XX_CPU_PORT) +#define MV88E61XX_CPU_PORT CONFIG_SWITCH_88E61XX_CPU_PORT +#else +#define MV88E61XX_CPU_PORT 0x5 +#endif +/* Enabled ports can be configured in board header file */ +#if defined (CONFIG_SWITCH_88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_SWITCH_88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \ + BIT3 | BIT4 | BIT5) +#endif + +#define MV88E61XX_NAME "88E6165" +#define MV88E61XX_PHY_TIMEOUT 100000 +#define MV88E61XX_MAX_PORTS_NUM 0x6 + +#define MV88E61XX_PORT_STATUS_REG 0x1 +#define MV88E61XX_PORT_CONTROL_REG 0x4 +#define MV88E61XX_PORT_VMAP_REG 0x6 +#define MV88E61XX_PORT_VID_REG 0x7 + +#define MV88E61XX_PORTS_OFFSET 0x10 +#define MV88E61XX_SMI_PHY_COMMAND 0x18 +#define MV88E61XX_SMI_PHY_DATA 0x19 +#define MV88E61XX_GLOBAL_2_REG_DEV_ADDR 0x1C + +#define MV88E61XX_PORT_STATUS_BIT_LINKUP BIT2 + +/* Chip Address mode + * The Switch support two modes of operation + * 1. single chip mode and + * 2. Multi-chip mode + * Refer chip documentation for more details + * + * By default single chip mode is configured + * multichip mode operation can be configured in board header + */ +#ifndef CONFIG_SWITCH_88E61XX_MULTI_CHIP_ADDR_MODE +#define mv_sw_eth_phy_reg_write eth_smi_reg_write +#define mv_sw_eth_phy_reg_read eth_smi_reg_read +#else +void mv_sw_eth_phy_reg_write(u32 eth_port_num, u32 phy_adr, u32 reg_ofs, + u16 data) +{ + u16 reg; + u32 smi_dev_addr; + + smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(eth_port_num)); + do { + eth_smi_reg_read(eth_port_num, smi_dev_addr, 0x0, ®); + } while ((reg & BIT15)); + /* Poll till SMIBusy bit is clear */ + eth_smi_reg_write(eth_port_num, smi_dev_addr, 0x1, data); + /* Write data to Switch indirect data register */ + eth_smi_reg_write(eth_port_num, smi_dev_addr, 0x0, + reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15); + /* Write command to Switch indirect command register (write) */ +} + +void mv_sw_eth_phy_reg_read(u32 eth_port_num, u32 phy_adr, u32 reg_ofs, + u16 * data) +{ + u16 reg; + u32 smi_dev_addr; + + smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(eth_port_num)); + do { + eth_smi_reg_read(eth_port_num, smi_dev_addr, 0x0, ®); + } while ((reg & BIT15)); + /* Poll till SMIBusy bit is clear */ + eth_smi_reg_write(eth_port_num, smi_dev_addr, 0x0, + reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15); + /* Write command to Switch indirect command register (read) */ + do { + eth_smi_reg_read(eth_port_num, smi_dev_addr, 0x0, ®); + } while ((reg & BIT15)); + /* Poll till SMIBusy bit is clear */ + eth_smi_reg_read(eth_port_num, smi_dev_addr, 0x1, (u16 *) & data); + /* Read data from Switch indirect data register */ +} +#endif + +static void mv_switch_88e61xx_vlan_init(u32 eth_port_num, + u32 switch_cpu_port, + u32 switch_max_ports_num, + u32 switch_ports_ofs, + u32 switch_enabled_ports_mask) +{ + u32 prt; + u16 reg; + + debug_print_ftrace(); + /* be sure all ports are disabled */ + for (prt = 0; prt < switch_max_ports_num; prt++) { + mv_sw_eth_phy_reg_read(eth_port_num, (switch_ports_ofs + prt), + MV88E61XX_PORT_CONTROL_REG, ®); + reg &= ~0x3; + mv_sw_eth_phy_reg_write(eth_port_num, (switch_ports_ofs + prt), + MV88E61XX_PORT_CONTROL_REG, reg); + } + /* Set CPU port VID to 0x1 */ + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + switch_cpu_port), + MV88E61XX_PORT_VID_REG, ®); + reg &= ~0xfff; + reg |= 0x1; + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + switch_cpu_port), + MV88E61XX_PORT_VID_REG, reg); + + /* Setting Port default priority for all ports to zero */ + for (prt = 0; prt < switch_max_ports_num; prt++) { + mv_sw_eth_phy_reg_read(eth_port_num, (switch_ports_ofs + prt), + MV88E61XX_PORT_VID_REG, ®); + reg &= ~0xc000; + mv_sw_eth_phy_reg_write(eth_port_num, (switch_ports_ofs + prt), + MV88E61XX_PORT_VID_REG, reg); + } + /* Setting VID and VID map for all ports except CPU port */ + for (prt = 0; prt < switch_max_ports_num; prt++) { + /* only for enabled ports */ + if ((1 << prt) & switch_enabled_ports_mask) { + /* skip CPU port */ + if (prt == switch_cpu_port) + continue; + + /* + * set Ports VLAN Mapping. + * port prt <--> MV88E61XX_CPU_PORT VLAN #prt+1. + */ + + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + prt), + MV88E61XX_PORT_VID_REG, ®); + reg &= ~0x0fff; + reg |= (prt + 1); + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + prt), + MV88E61XX_PORT_VID_REG, reg); + + /* Set Vlan map table for all ports to send only to MV88E61XX_CPU_PORT */ + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + prt), + MV88E61XX_PORT_VMAP_REG, ®); + reg &= ~((1 << switch_max_ports_num) - 1); + reg |= (1 << switch_cpu_port); + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + prt), + MV88E61XX_PORT_VMAP_REG, reg); + } + } + /* Set Vlan map table for MV88E61XX_CPU_PORT to see all ports */ + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + switch_cpu_port), + MV88E61XX_PORT_VMAP_REG, ®); + reg &= ~((1 << switch_max_ports_num) - 1); + reg |= switch_enabled_ports_mask & ~(1 << switch_cpu_port); + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + switch_cpu_port), + MV88E61XX_PORT_VMAP_REG, reg); + + /*enable only appropriate ports to forwarding mode - and disable the others */ + for (prt = 0; prt < switch_max_ports_num; prt++) { + if ((1 << prt) & switch_enabled_ports_mask) { + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + prt), + MV88E61XX_PORT_CONTROL_REG, + ®); + reg |= 0x3; + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + prt), + MV88E61XX_PORT_CONTROL_REG, + reg); + } else { + /* Disable port */ + mv_sw_eth_phy_reg_read(eth_port_num, + (switch_ports_ofs + prt), + MV88E61XX_PORT_CONTROL_REG, + ®); + reg &= ~0x3; + mv_sw_eth_phy_reg_write(eth_port_num, + (switch_ports_ofs + prt), + MV88E61XX_PORT_CONTROL_REG, + reg); + } + } +} + +/* + * Marvell 88E61XX Switch initialization + */ +int mv_switch_88e61xx_init(u32 eth_port_num) +{ + u32 prt; + u16 reg; + volatile u32 timeout; + + debug_print_ftrace(); + /* Init vlan */ + mv_switch_88e61xx_vlan_init(eth_port_num, MV88E61XX_CPU_PORT, + MV88E61XX_MAX_PORTS_NUM, + MV88E61XX_PORTS_OFFSET, + MV88E61XX_ENABLED_PORTS); + + /* Enable RGMII delay on Tx and Rx for CPU port */ + mv_sw_eth_phy_reg_write(eth_port_num, 0x14, 0x1a, 0x81e7); + mv_sw_eth_phy_reg_read(eth_port_num, 0x15, 0x1a, ®); + mv_sw_eth_phy_reg_write(eth_port_num, 0x15, 0x1a, 0x18); + mv_sw_eth_phy_reg_write(eth_port_num, 0x14, 0x1a, 0xc1e7); + + for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) { + if (prt != MV88E61XX_CPU_PORT) { + /*Enable Phy power up */ + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_DATA, 0x3360); + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_COMMAND, + (0x9410 | (prt << 5))); + + /*Make sure SMIBusy bit cleared before another SMI operation can take place */ + timeout = MV88E61XX_PHY_TIMEOUT; + do { + mv_sw_eth_phy_reg_read(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_COMMAND, + ®); + if (timeout-- == 0) { + error_print("SMI busy timeout"); + return -1; + } + } while (reg & BIT28); /* busy mask */ + + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_DATA, 0x1140); + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_COMMAND, + (0x9400 | (prt << 5))); + + /*Make sure SMIBusy bit cleared before another SMI operation can take place */ + timeout = MV88E61XX_PHY_TIMEOUT; + do { + mv_sw_eth_phy_reg_read(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_COMMAND, + ®); + if (timeout-- == 0) { + error_print("SMI busy timeout"); + return -1; + } + } while (reg & BIT28); /* busy mask */ + } + + /*Enable port */ + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_PORTS_OFFSET + prt, 4, 0x7f); + } + /*Force CPU port to RGMII FDX 1000Base */ + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_PORTS_OFFSET + MV88E61XX_CPU_PORT, 1, + 0x3e); + + info_print(MV88E61XX_NAME " Initialized"); + return 0; +} + +#if defined(CONFIG_CMD_DUMP61XXPHY) +static void phy_busywait(u32 eth_port_num) +{ + u32 timeout; + u16 reg; + + timeout = MV88E61XX_PHY_TIMEOUT; + do { + mv_sw_eth_phy_reg_read(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_COMMAND, ®); + if (timeout-- == 0) { + error_print("SMI busy timeout"); + return -1; + } + } while (reg & BIT28); /* busy mask */ +} + +int do_dump61xxphy(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +#define SMI_CMD_BUSY_OFFSET 15 +#define SMI_CMD_MODE_OFFSET 12 +#define SMI_CMD_OP_OFFSET 10 +#define SMI_CMD_ADDR_OFFSET 5 + + int page, i, prt; + int eth_port_num = 0; + u32 reg; + + /* set page address to 3 */ + prt = 0; + for (page = 0; page < 7; page++) { + if (page == 1) + continue; + if (page == 4) + continue; + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_DATA, page); + + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_COMMAND, + (1 << SMI_CMD_BUSY_OFFSET | 1 << + SMI_CMD_MODE_OFFSET | 1 << + SMI_CMD_OP_OFFSET | prt << + SMI_CMD_ADDR_OFFSET | 22)); + + /* read and display phy registers */ + for (i = 0; i < 29; i++) { + if (page != 0) { + if (i < 16) + continue; + if (i == 22) + continue; + } + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_COMMAND, + (1 << SMI_CMD_BUSY_OFFSET | 1 << + SMI_CMD_MODE_OFFSET | 2 << + SMI_CMD_OP_OFFSET | prt << + SMI_CMD_ADDR_OFFSET | i)); + + phy_busywait(eth_port_num); + reg = 0x0; + mv_sw_eth_phy_reg_read(eth_port_num, + MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_DATA, ®); + + printf("page %d reg %02d = %04x\n", page, i, (u16) reg); + } + } + + /* restore page address to zero */ + reg = 0; + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_DATA, reg); + phy_busywait(eth_port_num); + mv_sw_eth_phy_reg_write(eth_port_num, MV88E61XX_GLOBAL_2_REG_DEV_ADDR, + MV88E61XX_SMI_PHY_COMMAND, + (1 << SMI_CMD_BUSY_OFFSET | 1 << + SMI_CMD_MODE_OFFSET | 1 << SMI_CMD_OP_OFFSET | + prt << SMI_CMD_ADDR_OFFSET | 22)); + + return 0; +} + +U_BOOT_CMD(dump61xxphy, CONFIG_SYS_MAXARGS, 1, do_dump61xxphy, + "dump61xxphy - dump 88361xx registers\n", + "var [...]\n" + " - run the commands in the environment variable(s) 'var'\n"); +#endif /* CONFIG_CMD_DUMP61XXPHY */ + +#endif /* CONFIG_SWITCH_88E61XX */

Hi Prafulla,
Prafulla Wadaskar wrote:
From: prafulla_wadaskar prafulla@marvell.com
Chips supprted:-
- 88E61XX 6 port gbe swtich with 5 integrated PHYs
- 88E6061 6 port fe swtich with 5 integrated PHYs
- 88E1116 gbe transceiver
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com
I'll review these changes, but as-is placing chip support in 'board/Marvell' is inappropriate. If they are pure ethernet devices they need to go in 'drivers/net'. We also need to move the Marvell system controller chips that are already in 'board/Marvell', but I'm not sure where they should go. As you see, there's a tremendous amount of redundancy there.
regards, Ben

Dear Prafulla Wadaskar,
In message 1238798370-9245-4-git-send-email-prafulla@marvell.com you wrote:
From: prafulla_wadaskar prafulla@marvell.com
Chips supprted:-
- 88E61XX 6 port gbe swtich with 5 integrated PHYs
- 88E6061 6 port fe swtich with 5 integrated PHYs
- 88E1116 gbe transceiver
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com
ben has already commented on the incorrect location of this code in the directory hierarchy. I will restrict my review to formal issues.
diff --git a/board/Marvell/common/mv88e1116.c b/board/Marvell/common/mv88e1116.c new file mode 100644 index 0000000..87ec550 --- /dev/null +++ b/board/Marvell/common/mv88e1116.c
...
+#ifndef MV88E1116_DEBUG +#define MV88E1116_DEBUG 0 +#endif +#define DEBUG_PRINT MV88E1116_DEBUG
+#include <common.h> +#include <debug_prints.h> +#include "../common/ppc_error_no.h"
See before (i. e. get rid of this stuff, here and everywhere else; it will make the code jkust simpler).
diff --git a/board/Marvell/common/mv88e60xx.c b/board/Marvell/common/mv88e60xx.c new file mode 100644 index 0000000..6034f7b --- /dev/null +++ b/board/Marvell/common/mv88e60xx.c
...
+static void mv_switch_88e60xx_vlan_init(u32 eth_port_num,
u32 switch_cpu_port,
u32 switch_max_ports_num,
u32 switch_ports_ofs,
u32 switch_enabled_ports_mask)
+{
- u32 prt;
- u16 reg;
- debug_print_ftrace();
- /* be sure all ports are disabled */
- for (prt = 0; prt < switch_max_ports_num; prt++) {
mv_sw_eth_phy_reg_read(eth_port_num, (switch_ports_ofs + prt),
MV88E60XX_PORT_CONTROL_REG, ®);
reg &= ~0x3;
mv_sw_eth_phy_reg_write(eth_port_num, (switch_ports_ofs + prt),
MV88E60XX_PORT_CONTROL_REG, reg);
Please read the CodingStyle document about resonable choice oif namess for functions, variables, etc. Names like mv_switch_88e60xx_vlan_init(), mv_sw_eth_phy_reg_read(), switch_max_ports_num, etc. are a pain to write, and a bigger pain to read. Please use SIMPLE, readable names.
...
+U_BOOT_CMD(smi, CONFIG_SYS_MAXARGS, 1, do_smi,
"smi - isues read/write command on smi for switch registers\n",
"smi read [smiaddr] [regaddr] [page]\n"
" - read smi register command\n"
"smi write [smiaddr] [regaddr] [value] [page]\n"
" - write <value> to <regaddr> register command\n"
" - run the commands in the environment variable(s) 'var'\n");
The definition of the U_BOOT_CMD macro has changed, please fix your
...
+U_BOOT_CMD(dump60xxphy, CONFIG_SYS_MAXARGS, 1, do_dump60xxphy,
"dump60xxphy - dump 88360xx registers\n",
"var [...]\n"
" - run the commands in the environment variable(s) 'var'\n");
+#endif /* CONFIG_CMD_DUMP60XXPHY */
Ditto.
Hm... if we the function of this is to "dump 88360xx registers", then why is the command name "dump60xxphy" ?
60xx != 88360xx ??
Ditto for the rest of the file.
Best regards,
Wolfgang Denk

Chips supprted:- 1. 88E6161 6 port gbe swtich with 5 integrated PHYs 2. 88E6165 6 port gbe swtich with 5 integrated PHYs Note: This driver is supported and tested against kirkwood egiga interface, other interfaces can be added
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: updated as per review comments by Wolfgand Denk removed other two drivers form earlier patch debug_prints removed driver moved to drivers/net/
drivers/net/Makefile | 1 + drivers/net/mv88e61xx.c | 291 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+), 0 deletions(-) create mode 100644 drivers/net/mv88e61xx.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f0c5654..7482327 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,6 +47,7 @@ COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_SWITCH_MV88E61XX) += mv88e61xx.o COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/mv88e61xx.c b/drivers/net/mv88e61xx.c new file mode 100644 index 0000000..8167919 --- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,291 @@ +/* + * (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> + +#if defined (CONFIG_SWITCH_MV88E61XX) + +/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \ + BIT3 | BIT4 | BIT5) +#endif + +#if defined (CONFIG_88E6161) +#define MV88E61XX_NAME "88E6161" +#elif defined (CONFIG_88E6165) +#define MV88E61XX_NAME "88E6165" +#else +#define MV88E61XX_NAME "88E61XX" +#endif + +#define MV88E61XX_PHY_TIMEOUT 100000 +#define MV88E61XX_MAX_PORTS_NUM 0x6 +/* CPU port can be configured in board header file */ +#if defined (CONFIG_MV88E61XX_CPU_PORT) +#define MV88E61XX_CPU_PORT CONFIG_MV88E61XX_CPU_PORT +#else +#define MV88E61XX_CPU_PORT 0x5 +#endif + +#define MV88E61XX_PRT_STS_REG 0x1 +#define MV88E61XX_PRT_CTRL_REG 0x4 +#define MV88E61XX_PRT_VMAP_REG 0x6 +#define MV88E61XX_PRT_VID_REG 0x7 + +#define MV88E61XX_PRT_OFST 0x10 +#define MV88E61XX_PHY_CMD 0x18 +#define MV88E61XX_PHY_DATA 0x19 +#define MV88E61XX_GLOBAL2_REG_DEVADR 0x1C + +#ifdef CONFIG_KIRKWOOD_EGIGA +#define smi_wr_reg eth_smi_reg_write +#define smi_rd_reg eth_smi_reg_read +#else /* add new interface above this */ +#error Unsupported interface +#endif + +/* Chip Address mode + * The Switch support two modes of operation + * 1. single chip mode and + * 2. Multi-chip mode + * Refer chip documentation for more details + * + * By default single chip mode is configured + * multichip mode operation can be configured in board header + */ +#ifndef CONFIG_MV88E61XX_MULTICHIP_ADRMODE +#define mv88e61xx_wr_phy smi_wr_reg +#define mv88e61xx_rd_phy smi_rd_reg +#else +void mv88e61xx_wr_phy(u32 port, u32 phy_adr, u32 reg_ofs, u16 data) +{ + u16 reg; + u32 smi_dev_addr; + + smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port)); + do { + smi_rd_reg(port, smi_dev_addr, 0x0, ®); + } while ((reg & BIT15)); + /* Poll till SMIBusy bit is clear */ + smi_wr_reg(port, smi_dev_addr, 0x1, data); + /* Write data to Switch indirect data register */ + smi_wr_reg(port, smi_dev_addr, 0x0, + reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15); + /* Write command to Switch indirect command register (write) */ +} + +void mv88e61xx_rd_phy(u32 port, u32 phy_adr, u32 reg_ofs, u16 * data) +{ + u16 reg; + u32 smi_dev_addr; + + smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port)); + do { + smi_rd_reg(port, smi_dev_addr, 0x0, ®); + } while ((reg & BIT15)); + /* Poll till SMIBusy bit is clear */ + smi_wr_reg(port, smi_dev_addr, 0x0, + reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15); + /* Write command to Switch indirect command register (read) */ + do { + smi_rd_reg(port, smi_dev_addr, 0x0, ®); + } while ((reg & BIT15)); + /* Poll till SMIBusy bit is clear */ + smi_rd_reg(port, smi_dev_addr, 0x1, (u16 *) & data); + /* Read data from Switch indirect data register */ +} +#endif /* CONFIG_MV88E61XX_MULTICHIP_ADRMODE */ + +static void mv88e61xx_vlaninit(u32 port, u32 cpu_port, u32 max_prtnum, + u32 ports_ofs, u32 port_mask) +{ + u32 prt; + u16 reg; + + /* be sure all ports are disabled */ + for (prt = 0; prt < max_prtnum; prt++) { + mv88e61xx_rd_phy(port, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG, + ®); + reg &= ~0x3; + mv88e61xx_wr_phy(port, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG, + reg); + } + /* Set CPU port VID to 0x1 */ + mv88e61xx_rd_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG, + ®); + reg &= ~0xfff; + reg |= 0x1; + mv88e61xx_wr_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG, + reg); + + /* Setting Port default priority for all ports to zero */ + for (prt = 0; prt < max_prtnum; prt++) { + mv88e61xx_rd_phy(port, ports_ofs + prt, MV88E61XX_PRT_VID_REG, + ®); + reg &= ~0xc000; + mv88e61xx_wr_phy(port, ports_ofs + prt, MV88E61XX_PRT_VID_REG, + reg); + } + /* Setting VID and VID map for all ports except CPU port */ + for (prt = 0; prt < max_prtnum; prt++) { + /* only for enabled ports */ + if ((1 << prt) & port_mask) { + /* skip CPU port */ + if (prt == cpu_port) + continue; + + /* + * set Ports VLAN Mapping. + * port prt <--> MV88E61XX_CPU_PORT VLAN #prt+1. + */ + + mv88e61xx_rd_phy(port, ports_ofs + prt, + MV88E61XX_PRT_VID_REG, ®); + reg &= ~0x0fff; + reg |= (prt + 1); + mv88e61xx_wr_phy(port, ports_ofs + prt, + MV88E61XX_PRT_VID_REG, reg); + + /* + * Set Vlan map table for all ports to send only to + * MV88E61XX_CPU_PORT + */ + mv88e61xx_rd_phy(port, ports_ofs + prt, + MV88E61XX_PRT_VMAP_REG, ®); + reg &= ~((1 << max_prtnum) - 1); + reg |= (1 << cpu_port); + mv88e61xx_wr_phy(port, ports_ofs + prt, + MV88E61XX_PRT_VMAP_REG, reg); + } + } + /* Set Vlan map table for MV88E61XX_CPU_PORT to see all ports */ + mv88e61xx_rd_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG, + ®); + reg &= ~((1 << max_prtnum) - 1); + reg |= port_mask & ~(1 << cpu_port); + mv88e61xx_wr_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG, + reg); + + /* + * enable only appropriate ports to forwarding mode + * and disable the others + */ + for (prt = 0; prt < max_prtnum; prt++) { + if ((1 << prt) & port_mask) { + mv88e61xx_rd_phy(port, ports_ofs + prt, + MV88E61XX_PRT_CTRL_REG, ®); + reg |= 0x3; + mv88e61xx_wr_phy(port, ports_ofs + prt, + MV88E61XX_PRT_CTRL_REG, reg); + } else { + /* Disable port */ + mv88e61xx_rd_phy(port, ports_ofs + prt, + MV88E61XX_PRT_CTRL_REG, ®); + reg &= ~0x3; + mv88e61xx_wr_phy(port, ports_ofs + prt, + MV88E61XX_PRT_CTRL_REG, reg); + } + } +} + +/* + * Marvell 88E61XX Switch initialization + */ +int mv_switch_88e61xx_init(u32 port) +{ + u32 prt; + u16 reg; + volatile u32 timeout; + + /* Init vlan */ + mv88e61xx_vlaninit(port, MV88E61XX_CPU_PORT, MV88E61XX_MAX_PORTS_NUM, + MV88E61XX_PRT_OFST, MV88E61XX_ENABLED_PORTS); + + /* Enable RGMII delay on Tx and Rx for CPU port */ + mv88e61xx_wr_phy(port, 0x14, 0x1a, 0x81e7); + mv88e61xx_rd_phy(port, 0x15, 0x1a, ®); + mv88e61xx_wr_phy(port, 0x15, 0x1a, 0x18); + mv88e61xx_wr_phy(port, 0x14, 0x1a, 0xc1e7); + + for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) { + if (prt != MV88E61XX_CPU_PORT) { + /*Enable Phy power up */ + mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_DATA, 0x3360); + mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_CMD, + (0x9410 | (prt << 5))); + + /* + * Make sure SMIBusy bit cleared before another + * SMI operation can take place + */ + timeout = MV88E61XX_PHY_TIMEOUT; + do { + mv88e61xx_rd_phy(port, + MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_CMD, ®); + if (timeout-- == 0) { + printf("SMI busy timeout\n"); + return -1; + } + } while (reg & BIT28); /* busy mask */ + + mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_DATA, 0x1140); + mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_CMD, + (0x9400 | (prt << 5))); + + /* + * Make sure SMIBusy bit cleared before another + * SMI operation can take place + */ + timeout = MV88E61XX_PHY_TIMEOUT; + do { + mv88e61xx_rd_phy(port, + MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_CMD, ®); + if (timeout-- == 0) { + printf("SMI busy timeout\n"); + return -1; + } + } while (reg & BIT28); /* busy mask */ + } + + /*Enable port */ + mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST + prt, 4, 0x7f); + } + /*Force CPU port to RGMII FDX 1000Base */ + mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST + MV88E61XX_CPU_PORT, 1, + 0x3e); + + printf(MV88E61XX_NAME " Initialized\n"); + return 0; +} + +#endif /* CONFIG_SWITCH_MV88E61XX */

On Wed, Apr 8, 2009 at 1:30 PM, Prafulla Wadaskar prafulla@marvell.com wrote:
Chips supprted:-
- 88E6161 6 port gbe swtich with 5 integrated PHYs
- 88E6165 6 port gbe swtich with 5 integrated PHYs
Note: This driver is supported and tested against kirkwood egiga interface, other interfaces can be added
We are going to be using this chip in a project, so I'm happy to see this code come by :-) A few comments sprinkled around below.
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: updated as per review comments by Wolfgand Denk
It's always good to spell the name of the guy with commit access right :-)
removed other two drivers form earlier patch debug_prints removed driver moved to drivers/net/
drivers/net/Makefile   |   1 +  drivers/net/mv88e61xx.c |  291 +++++++++++++++++++++++++++++++++++++++++++++++  2 files changed, 292 insertions(+), 0 deletions(-)  create mode 100644 drivers/net/mv88e61xx.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f0c5654..7482327 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,6 +47,7 @@ COBJS-$(CONFIG_MACB) += macb.o  COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o  COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o  COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_SWITCH_MV88E61XX) += mv88e61xx.o  COBJS-$(CONFIG_NATSEMI) += natsemi.o  COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o  COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/mv88e61xx.c b/drivers/net/mv88e61xx.c new file mode 100644 index 0000000..8167919 --- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,291 @@ +/*
- (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>
+#if defined (CONFIG_SWITCH_MV88E61XX)
+/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
- BIT3 | BIT4 | BIT5)
+#endif
+#if defined (CONFIG_88E6161) +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E6161" +#elif defined (CONFIG_88E6165) +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E6165" +#else +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E61XX" +#endif
+#define MV88E61XX_PHY_TIMEOUT Â Â Â Â Â 100000 +#define MV88E61XX_MAX_PORTS_NUM Â Â Â Â Â Â Â Â 0x6 +/* CPU port can be configured in board header file */ +#if defined (CONFIG_MV88E61XX_CPU_PORT) +#define MV88E61XX_CPU_PORT Â Â Â Â Â Â CONFIG_MV88E61XX_CPU_PORT +#else +#define MV88E61XX_CPU_PORT Â Â Â Â Â Â 0x5 +#endif
+#define MV88E61XX_PRT_STS_REG Â Â Â Â Â 0x1 +#define MV88E61XX_PRT_CTRL_REG Â Â Â Â 0x4 +#define MV88E61XX_PRT_VMAP_REG Â Â Â Â 0x6 +#define MV88E61XX_PRT_VID_REG Â Â Â Â Â 0x7
+#define MV88E61XX_PRT_OFST Â Â Â Â Â Â 0x10 +#define MV88E61XX_PHY_CMD Â Â Â Â Â Â Â 0x18 +#define MV88E61XX_PHY_DATA Â Â Â Â Â Â 0x19 +#define MV88E61XX_GLOBAL2_REG_DEVADR Â 0x1C
+#ifdef CONFIG_KIRKWOOD_EGIGA +#define smi_wr_reg   eth_smi_reg_write +#define smi_rd_reg   eth_smi_reg_read +#else /* add new interface above this */ +#error Unsupported interface +#endif
As far as I understand it, "SMI" for the 88E6161 is really just the physical MII layer with some changes in the register definitions. Would it not make more sense to use the existing u-boot miiphy code in common/miiphyutil.c to define the access functions? This allows for platform code to register mii access functions and gets platform specific stuff like this out of the driver.
+/* Chip Address mode
- The Switch support two modes of operation
- single chip mode and
- Multi-chip mode
- Refer chip documentation for more details
- By default single chip mode is configured
- multichip mode operation can be configured in board header
- */
+#ifndef CONFIG_MV88E61XX_MULTICHIP_ADRMODE +#define mv88e61xx_wr_phy smi_wr_reg +#define mv88e61xx_rd_phy smi_rd_reg +#else +void mv88e61xx_wr_phy(u32 port, u32 phy_adr, u32 reg_ofs, u16 data) +{
- u16 reg;
- u32 smi_dev_addr;
- smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port));
if CONFIG_MV88E61XX_MULTICHIP_ADRMODE is defined you're going to reference the KW_REG_READ and KW_ETH_PHY_ADDR_REG macros, which don't seem to be defined in this file. I'm assuming this is platform specific stuff.
- do {
- smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
- /* Poll till SMIBusy bit is clear */
How about a timeout here? I'm not a C style maven, but the extra () in the test could probably go away. Some constants for register names and bit functions would help as well. This code appears several times, so maybe could be factored out. Also the commenting style is a bit random through the file - sometimes the comment is before the action, other times afterwards.
- smi_wr_reg(port, smi_dev_addr, 0x1, data);
- /* Write data to Switch indirect data register */
- smi_wr_reg(port, smi_dev_addr, 0x0,
- reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
- /* Write command to Switch indirect command register (write) */
+}
+void mv88e61xx_rd_phy(u32 port, u32 phy_adr, u32 reg_ofs, u16 * data) +{
- u16 reg;
- u32 smi_dev_addr;
- smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port));
ditto above regarding the KW* macros
- do {
- smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
- /* Poll till SMIBusy bit is clear */
- smi_wr_reg(port, smi_dev_addr, 0x0,
- reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
- /* Write command to Switch indirect command register (read) */
- do {
- smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
- /* Poll till SMIBusy bit is clear */
- smi_rd_reg(port, smi_dev_addr, 0x1, (u16 *) & data);
- /* Read data from Switch indirect data register */
+} +#endif /* CONFIG_MV88E61XX_MULTICHIP_ADRMODE */
+static void mv88e61xx_vlaninit(u32 port, u32 cpu_port, u32 max_prtnum,
- u32 ports_ofs, u32 port_mask)
+{
- u32 prt;
- u16 reg;
- /* be sure all ports are disabled */
- for (prt = 0; prt < max_prtnum; prt++) {
- mv88e61xx_rd_phy(port, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG,
- ®);
- reg &= ~0x3;
- mv88e61xx_wr_phy(port, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG,
- reg);
- }
Would this code (and similar code below) work on the 88E6123 which (IIRC) only has ports 0, 1, and 5?
- /* Set CPU port VID to 0x1 */
- mv88e61xx_rd_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG,
- ®);
- reg &= ~0xfff;
- reg |= 0x1;
- mv88e61xx_wr_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG,
- reg);
- /* Setting  Port default priority for all ports to zero */
- for (prt = 0; prt < max_prtnum; prt++) {
- mv88e61xx_rd_phy(port, ports_ofs + prt, MV88E61XX_PRT_VID_REG,
- ®);
- reg &= ~0xc000;
- mv88e61xx_wr_phy(port, ports_ofs + prt, MV88E61XX_PRT_VID_REG,
- reg);
- }
- /* Setting VID and VID map for all ports except CPU port */
- for (prt = 0; prt < max_prtnum; prt++) {
- /* only for enabled ports */
- if ((1 << prt) & port_mask) {
- /* skip CPU port */
- if (prt == cpu_port)
- continue;
- /*
- * Â set Ports VLAN Mapping.
- * Â Â Â port prt <--> MV88E61XX_CPU_PORT VLAN #prt+1.
- */
- mv88e61xx_rd_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_VID_REG, ®);
- reg &= ~0x0fff;
- reg |= (prt + 1);
- mv88e61xx_wr_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_VID_REG, reg);
- /*
- * Set Vlan map table for all ports to send only to
- * MV88E61XX_CPU_PORT
- */
- mv88e61xx_rd_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_VMAP_REG, ®);
- reg &= ~((1 << max_prtnum) - 1);
- reg |= (1 << cpu_port);
- mv88e61xx_wr_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_VMAP_REG, reg);
- }
- }
- /* Set Vlan map table for MV88E61XX_CPU_PORT to see all ports */
- mv88e61xx_rd_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG,
- ®);
- reg &= ~((1 << max_prtnum) - 1);
- reg |= port_mask & ~(1 << cpu_port);
- mv88e61xx_wr_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG,
- reg);
- /*
- * enable only appropriate ports to forwarding mode
- * and disable the others
- */
- for (prt = 0; prt < max_prtnum; prt++) {
- if ((1 << prt) & port_mask) {
- mv88e61xx_rd_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_CTRL_REG, ®);
- reg |= 0x3;
- mv88e61xx_wr_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_CTRL_REG, reg);
- } else {
- /* Disable port */
- mv88e61xx_rd_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_CTRL_REG, ®);
- reg &= ~0x3;
- mv88e61xx_wr_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_CTRL_REG, reg);
- }
- }
+}
+/*
- Marvell 88E61XX Switch initialization
- */
+int mv_switch_88e61xx_init(u32 port) +{
- u32 prt;
- u16 reg;
- volatile u32 timeout;
- /* Init vlan */
- mv88e61xx_vlaninit(port, MV88E61XX_CPU_PORT, MV88E61XX_MAX_PORTS_NUM,
- MV88E61XX_PRT_OFST, MV88E61XX_ENABLED_PORTS);
- /* Enable RGMII delay on Tx and Rx for CPU port */
- mv88e61xx_wr_phy(port, 0x14, 0x1a, 0x81e7);
- mv88e61xx_rd_phy(port, 0x15, 0x1a, ®);
- mv88e61xx_wr_phy(port, 0x15, 0x1a, 0x18);
- mv88e61xx_wr_phy(port, 0x14, 0x1a, 0xc1e7);
^ -- lots of magic numbers above and below here -- v
In the middle of the above sequence you read the phy, but don't seem to do anything with 'reg'. Is this required?
What if I don't want RGMII delay as I'm using GMII on my platform?
- for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {
- if (prt != MV88E61XX_CPU_PORT) {
- /*Enable Phy power up */
- mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR,
- MV88E61XX_PHY_DATA, 0x3360);
- mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR,
- MV88E61XX_PHY_CMD,
- (0x9410 | (prt << 5)));
- /*
- * Make sure SMIBusy bit cleared before another
- * SMI operation can take place
- */
- timeout = MV88E61XX_PHY_TIMEOUT;
- do {
- mv88e61xx_rd_phy(port,
- MV88E61XX_GLOBAL2_REG_DEVADR,
- MV88E61XX_PHY_CMD, ®);
- if (timeout-- == 0) {
- printf("SMI busy timeout\n");
- return -1;
- }
- } while (reg & BIT28); Â /* busy mask */
- mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR,
- MV88E61XX_PHY_DATA, 0x1140);
- mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR,
- MV88E61XX_PHY_CMD,
- (0x9400 | (prt << 5)));
- /*
- * Make sure SMIBusy bit cleared before another
- * SMI operation can take place
- */
- timeout = MV88E61XX_PHY_TIMEOUT;
- do {
- mv88e61xx_rd_phy(port,
- MV88E61XX_GLOBAL2_REG_DEVADR,
- MV88E61XX_PHY_CMD, ®);
- if (timeout-- == 0) {
- printf("SMI busy timeout\n");
- return -1;
- }
- } while (reg & BIT28); Â /* busy mask */
replicated status polling code, might want to factor it out.
- }
- /*Enable port */
- mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST + prt, 4, 0x7f);
- }
- /*Force CPU port to RGMII FDX 1000Base */
- mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST + MV88E61XX_CPU_PORT, 1,
- 0x3e);
This last write seems very platform specific, for example in our case we want GMII, not RGMII. On another project we might want ports 4 & 5 to use the copper phy.
- printf(MV88E61XX_NAME " Initialized\n");
- return 0;
+}
+#endif /* CONFIG_SWITCH_MV88E61XX */
1.5.3.3
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Dear Andrew Dyer,
In message c166aa9f0904081532r7583585esc5cdcc384382d581@mail.gmail.com you wrote:
v2: updated as per review comments by Wolfgand Denk
It's always good to spell the name of the guy with commit access right :-)
He. I'm not Russell King.
Best regards,
Wolfgang Denk

-----Original Message----- From: Andrew Dyer [mailto:amdyer@gmail.com] Sent: Thursday, April 09, 2009 4:03 AM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v2] Marvell MV88E61XX Switch Driver support
On Wed, Apr 8, 2009 at 1:30 PM, Prafulla Wadaskar prafulla@marvell.com wrote:
Chips supprted:-
- 88E6161 6 port gbe swtich with 5 integrated PHYs 2.
88E6165 6 port
gbe swtich with 5 integrated PHYs Note: This driver is supported and tested against kirkwood egiga interface, other interfaces can be added
We are going to be using this chip in a project, so I'm happy to see this code come by :-) A few comments sprinkled around below.
Welcome...
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: updated as per review comments by Wolfgand Denk
It's always good to spell the name of the guy with commit access right :-)
removed other two drivers form earlier patch debug_prints removed driver moved to drivers/net/
drivers/net/Makefile | 1 + drivers/net/mv88e61xx.c | 291 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+), 0 deletions(-) create mode 100644 drivers/net/mv88e61xx.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f0c5654..7482327 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,6 +47,7 @@ COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_SWITCH_MV88E61XX) += mv88e61xx.o COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o
diff --git
a/drivers/net/mv88e61xx.c b/drivers/net/mv88e61xx.c new file mode 100644 index 0000000..8167919 --- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,291 @@ +/*
- (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>
+#if defined (CONFIG_SWITCH_MV88E61XX)
+/* Enabled ports can be enabled in board header file */
#if defined
+(CONFIG_MV88E61XX_ENABLED_PORTS) #define MV88E61XX_ENABLED_PORTS +CONFIG_MV88E61XX_ENABLED_PORTS #else #define
MV88E61XX_ENABLED_PORTS
+(BIT0 | BIT1 | BIT2 | \
BIT3 | BIT4 | BIT5) #endif
+#if defined (CONFIG_88E6161) +#define MV88E61XX_NAME "88E6161" +#elif defined (CONFIG_88E6165) +#define MV88E61XX_NAME "88E6165" +#else +#define MV88E61XX_NAME "88E61XX" +#endif
+#define MV88E61XX_PHY_TIMEOUT 100000 #define +MV88E61XX_MAX_PORTS_NUM 0x6 +/* CPU port can be configured in board header file */ #if defined +(CONFIG_MV88E61XX_CPU_PORT) #define MV88E61XX_CPU_PORT +CONFIG_MV88E61XX_CPU_PORT #else #define MV88E61XX_CPU_PORT
+0x5 #endif
+#define MV88E61XX_PRT_STS_REG 0x1 #define +MV88E61XX_PRT_CTRL_REG 0x4 #define
MV88E61XX_PRT_VMAP_REG
+0x6 #define MV88E61XX_PRT_VID_REG 0x7
+#define MV88E61XX_PRT_OFST 0x10 #define
MV88E61XX_PHY_CMD
+0x18 #define MV88E61XX_PHY_DATA 0x19 #define +MV88E61XX_GLOBAL2_REG_DEVADR 0x1C
+#ifdef CONFIG_KIRKWOOD_EGIGA +#define smi_wr_reg eth_smi_reg_write #define smi_rd_reg +eth_smi_reg_read #else /* add new interface above this */ #error +Unsupported interface #endif
As far as I understand it, "SMI" for the 88E6161 is really just the physical MII layer with some changes in the register definitions. Would it not make more sense to use the existing u-boot miiphy code in common/miiphyutil.c to define the access functions? This allows for platform code to register mii access functions and gets platform specific stuff like this out of the driver.
Thanks..miiphy is used for the same
+/* Chip Address mode
- The Switch support two modes of operation
- single chip mode and
- Multi-chip mode
- Refer chip documentation for more details
- By default single chip mode is configured
- multichip mode operation can be configured in board header */
+#ifndef CONFIG_MV88E61XX_MULTICHIP_ADRMODE +#define mv88e61xx_wr_phy smi_wr_reg +#define mv88e61xx_rd_phy smi_rd_reg +#else +void mv88e61xx_wr_phy(u32 port, u32 phy_adr, u32 reg_ofs,
u16 data) {
u16 reg;
u32 smi_dev_addr;
smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port));
if CONFIG_MV88E61XX_MULTICHIP_ADRMODE is defined you're going to reference the KW_REG_READ and KW_ETH_PHY_ADDR_REG macros, which don't seem to be defined in this file. I'm assuming this is platform specific stuff.
It is more egiga driver specific, you need to read phy address programmed for respective egga port on Gbe controller to establish communication, this settings is done in egiga driver, but there is no generic interface to read this To make it more generic I have used miiphy api i.e. miiphy_read(name, 0xEE, 0xEE, &mii_dev_adr); Values 0xEE are dummy to identify phy_address read.
Hope this will help, we can define special interface in future if this becomes generic usecase
do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
} while ((reg & BIT15));
/* Poll till SMIBusy bit is clear */
How about a timeout here? I'm not a C style maven, but the extra () in the test could probably go away. Some constants for register names and bit functions would help as well. This code appears several times, so maybe could be factored out. Also the commenting style is a bit random through the file - sometimes the comment is before the action, other times afterwards.
Corrected.... Code factored too..
smi_wr_reg(port, smi_dev_addr, 0x1, data);
/* Write data to Switch indirect data register */
smi_wr_reg(port, smi_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12
| BIT15);
/* Write command to Switch indirect command
register (write)
+*/ }
+void mv88e61xx_rd_phy(u32 port, u32 phy_adr, u32 reg_ofs,
u16 * data)
+{
u16 reg;
u32 smi_dev_addr;
smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port));
ditto above regarding the KW* macros
do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
} while ((reg & BIT15));
/* Poll till SMIBusy bit is clear */
smi_wr_reg(port, smi_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12
| BIT15);
/* Write command to Switch indirect command
register (read) */
do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
} while ((reg & BIT15));
/* Poll till SMIBusy bit is clear */
smi_rd_reg(port, smi_dev_addr, 0x1, (u16 *) & data);
/* Read data from Switch indirect data register */
} #endif /*
+CONFIG_MV88E61XX_MULTICHIP_ADRMODE */
+static void mv88e61xx_vlaninit(u32 port, u32 cpu_port, u32 +max_prtnum,
u32 ports_ofs, u32 port_mask) {
u32 prt;
u16 reg;
/* be sure all ports are disabled */
for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_CTRL_REG,
®);
reg &= ~0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_CTRL_REG,
reg);
}
Would this code (and similar code below) work on the 88E6123 which (IIRC) only has ports 0, 1, and 5?
It should.... I have added detection logic for 88E6123 too
/* Set CPU port VID to 0x1 */
mv88e61xx_rd_phy(port, (ports_ofs + cpu_port),
- MV88E61XX_PRT_VID_REG,
®);
reg &= ~0xfff;
reg |= 0x1;
mv88e61xx_wr_phy(port, (ports_ofs + cpu_port),
- MV88E61XX_PRT_VID_REG,
reg);
/* Setting Port default priority for all ports to zero */
for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_VID_REG,
®);
reg &= ~0xc000;
mv88e61xx_wr_phy(port, ports_ofs + prt,
- MV88E61XX_PRT_VID_REG,
reg);
}
/* Setting VID and VID map for all ports except CPU port */
for (prt = 0; prt < max_prtnum; prt++) {
/* only for enabled ports */
if ((1 << prt) & port_mask) {
/* skip CPU port */
if (prt == cpu_port)
continue;
/*
* set Ports VLAN Mapping.
* port prt <-->
MV88E61XX_CPU_PORT VLAN #prt+1.
*/
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, ®);
reg &= ~0x0fff;
reg |= (prt + 1);
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, reg);
/*
* Set Vlan map table for all ports to send
- only to
* MV88E61XX_CPU_PORT
*/
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG,
- ®);
reg &= ~((1 << max_prtnum) - 1);
reg |= (1 << cpu_port);
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, reg);
}
}
/* Set Vlan map table for MV88E61XX_CPU_PORT to see
all ports
- */
mv88e61xx_rd_phy(port, (ports_ofs + cpu_port),
- MV88E61XX_PRT_VMAP_REG,
®);
reg &= ~((1 << max_prtnum) - 1);
reg |= port_mask & ~(1 << cpu_port);
mv88e61xx_wr_phy(port, (ports_ofs + cpu_port),
- MV88E61XX_PRT_VMAP_REG,
reg);
/*
* enable only appropriate ports to forwarding mode
* and disable the others
*/
for (prt = 0; prt < max_prtnum; prt++) {
if ((1 << prt) & port_mask) {
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG,
+®);
reg |= 0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
} else {
/* Disable port */
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG,
+®);
reg &= ~0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
}
}
+}
+/*
- Marvell 88E61XX Switch initialization */ int
+mv_switch_88e61xx_init(u32 port) {
u32 prt;
u16 reg;
volatile u32 timeout;
/* Init vlan */
mv88e61xx_vlaninit(port, MV88E61XX_CPU_PORT,
- MV88E61XX_MAX_PORTS_NUM,
MV88E61XX_PRT_OFST,
- MV88E61XX_ENABLED_PORTS);
/* Enable RGMII delay on Tx and Rx for CPU port */
mv88e61xx_wr_phy(port, 0x14, 0x1a, 0x81e7);
mv88e61xx_rd_phy(port, 0x15, 0x1a, ®);
mv88e61xx_wr_phy(port, 0x15, 0x1a, 0x18);
mv88e61xx_wr_phy(port, 0x14, 0x1a, 0xc1e7);
^ -- lots of magic numbers above and below here -- v
In the middle of the above sequence you read the phy, but don't seem to do anything with 'reg'. Is this required?
I am sorry at this moment, I will replace them latter since I don't have enough data
What if I don't want RGMII delay as I'm using GMII on my platform?
For GMII/MII above settings not required... I have encapsulated them with CONFIG_SYS_RGMII_MODE
for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {
if (prt != MV88E61XX_CPU_PORT) {
/*Enable Phy power up */
mv88e61xx_wr_phy(port,
- MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x3360);
mv88e61xx_wr_phy(port,
- MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9410 | (prt << 5)));
/*
* Make sure SMIBusy bit cleared before
- another
* SMI operation can take place
*/
timeout = MV88E61XX_PHY_TIMEOUT;
do {
mv88e61xx_rd_phy(port,
- MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
- ®);
if (timeout-- == 0) {
printf("SMI busy
timeout\n");
return -1;
}
} while (reg & BIT28); /* busy mask */
mv88e61xx_wr_phy(port,
- MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x1140);
mv88e61xx_wr_phy(port,
- MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9400 | (prt << 5)));
/*
* Make sure SMIBusy bit cleared before
- another
* SMI operation can take place
*/
timeout = MV88E61XX_PHY_TIMEOUT;
do {
mv88e61xx_rd_phy(port,
- MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
- ®);
if (timeout-- == 0) {
printf("SMI busy
timeout\n");
return -1;
}
} while (reg & BIT28); /* busy mask */
replicated status polling code, might want to factor it out.
}
/*Enable port */
mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST + prt, 4,
- 0x7f);
}
/*Force CPU port to RGMII FDX 1000Base */
mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST +
- MV88E61XX_CPU_PORT, 1,
0x3e);
This last write seems very platform specific, for example in
These lines removed, by default switch detects speed normaly
our case we want GMII, not RGMII. On another project we might want ports 4 & 5 to use the copper phy.
In this case this driver many need updates, or we need to provide such interface. Any was current objective of this driver it to power up Phy and configure switch in managed mode. Also there are several h/s settings that go on the board which configures switch on power on Reset.
Thanks for feedback, I have updated the driver, will post v3 soon
Regards.. Prafulla . .
printf(MV88E61XX_NAME " Initialized\n");
return 0;
+}
+#endif /* CONFIG_SWITCH_MV88E61XX */
1.5.3.3
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
-- Hardware, n.: The parts of a computer system that can be kicked.

On Wed, Apr 8, 2009 at 1:30 PM, Prafulla Wadaskar prafulla@marvell.com wrote:
--- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,291 @@ +/*
- (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>
+#if defined (CONFIG_SWITCH_MV88E61XX)
+/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
- BIT3 | BIT4 | BIT5)
+#endif
+#if defined (CONFIG_88E6161) +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E6161" +#elif defined (CONFIG_88E6165) +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E6165" +#else +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E61XX" +#endif
Is this discoverable at runtime? What if there's a system that supports using multiple different types of MV88E61xx? I know it's a bit of a crazy idea, but board designers like to screw around with software developers like that.
+#define MV88E61XX_PHY_TIMEOUT Â Â Â Â Â 100000 +#define MV88E61XX_MAX_PORTS_NUM Â Â Â Â Â Â Â Â 0x6
Is this a limitation of the 88e61xx architecture, or just the max number on all of the currently shipping versions?
+#ifdef CONFIG_KIRKWOOD_EGIGA +#define smi_wr_reg   eth_smi_reg_write +#define smi_rd_reg   eth_smi_reg_read +#else /* add new interface above this */ +#error Unsupported interface +#endif
This sort of thing is discouraged. Why does this driver need to know about the ethernet controller? Perhaps function pointers are needed?
Andy

-----Original Message----- From: Andy Fleming [mailto:afleming@gmail.com] Sent: Thursday, April 09, 2009 4:43 AM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v2] Marvell MV88E61XX Switch Driver support
On Wed, Apr 8, 2009 at 1:30 PM, Prafulla Wadaskar prafulla@marvell.com wrote:
--- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,291 @@ +/*
- (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>
+#if defined (CONFIG_SWITCH_MV88E61XX)
+/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
- BIT3 | BIT4 | BIT5)
+#endif
+#if defined (CONFIG_88E6161) +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E6161" +#elif defined (CONFIG_88E6165) +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E6165" +#else +#define MV88E61XX_NAME Â Â Â Â Â Â Â Â "88E61XX" +#endif
Is this discoverable at runtime? What if there's a system that supports using multiple different types of MV88E61xx? I know it's a bit of a crazy idea, but board designers like to screw around with software developers like that.
Yes... I have done it, you will find it in PATCH v3
+#define MV88E61XX_PHY_TIMEOUT Â Â Â Â Â 100000 +#define MV88E61XX_MAX_PORTS_NUM Â Â Â Â Â Â Â Â 0x6
Is this a limitation of the 88e61xx architecture, or just the max number on all of the currently shipping versions?
No this represents how many maximum ports there are in 6161/6165 and those are 6
+#ifdef CONFIG_KIRKWOOD_EGIGA +#define smi_wr_reg   eth_smi_reg_write +#define smi_rd_reg   eth_smi_reg_read +#else /* add new interface above this */ +#error Unsupported interface +#endif
This sort of thing is discouraged. Why does this driver need to know about the ethernet controller? Perhaps function pointers are needed?
Yes this is removed and the interface is addressed through miiphy_read/write Thanks ... Regards.. Prafulla . .
Andy

Hi Prafulla, Prafulla Wadaskar wrote:
Chips supprted:-
- 88E6161 6 port gbe swtich with 5 integrated PHYs
- 88E6165 6 port gbe swtich with 5 integrated PHYs
Note: This driver is supported and tested against kirkwood egiga interface, other interfaces can be added
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: updated as per review comments by Wolfgand Denk removed other two drivers form earlier patch debug_prints removed driver moved to drivers/net/
drivers/net/Makefile | 1 + drivers/net/mv88e61xx.c | 291 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+), 0 deletions(-) create mode 100644 drivers/net/mv88e61xx.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f0c5654..7482327 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,6 +47,7 @@ COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_SWITCH_MV88E61XX) += mv88e61xx.o
Please change this to CONFIG_MV88E61XX_SWITCH
COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/mv88e61xx.c b/drivers/net/mv88e61xx.c new file mode 100644 index 0000000..8167919 --- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,291 @@ +/*
- (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>
+#if defined (CONFIG_SWITCH_MV88E61XX)
This is not needed - the makefile takes care of the conditional compilation
+/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
BIT3 | BIT4 | BIT5)
+#endif
+#if defined (CONFIG_88E6161) +#define MV88E61XX_NAME "88E6161" +#elif defined (CONFIG_88E6165) +#define MV88E61XX_NAME "88E6165" +#else +#define MV88E61XX_NAME "88E61XX" +#endif
There doesn't appear to be any code difference between the different chips. What's the point of differentiating them here? If it is meaningful, you should at least #warning if none of the known-about variants is mentioned.
+#define MV88E61XX_PHY_TIMEOUT 100000 +#define MV88E61XX_MAX_PORTS_NUM 0x6 +/* CPU port can be configured in board header file */ +#if defined (CONFIG_MV88E61XX_CPU_PORT) +#define MV88E61XX_CPU_PORT CONFIG_MV88E61XX_CPU_PORT +#else +#define MV88E61XX_CPU_PORT 0x5 +#endif
+#define MV88E61XX_PRT_STS_REG 0x1 +#define MV88E61XX_PRT_CTRL_REG 0x4 +#define MV88E61XX_PRT_VMAP_REG 0x6 +#define MV88E61XX_PRT_VID_REG 0x7
+#define MV88E61XX_PRT_OFST 0x10 +#define MV88E61XX_PHY_CMD 0x18 +#define MV88E61XX_PHY_DATA 0x19 +#define MV88E61XX_GLOBAL2_REG_DEVADR 0x1C
+#ifdef CONFIG_KIRKWOOD_EGIGA +#define smi_wr_reg eth_smi_reg_write +#define smi_rd_reg eth_smi_reg_read +#else /* add new interface above this */ +#error Unsupported interface +#endif
Please find a better way to do this. Board-specific code doesn't belong in a driver.
+/* Chip Address mode
- The Switch support two modes of operation
- single chip mode and
- Multi-chip mode
- Refer chip documentation for more details
- By default single chip mode is configured
- multichip mode operation can be configured in board header
- */
+#ifndef CONFIG_MV88E61XX_MULTICHIP_ADRMODE +#define mv88e61xx_wr_phy smi_wr_reg +#define mv88e61xx_rd_phy smi_rd_reg +#else +void mv88e61xx_wr_phy(u32 port, u32 phy_adr, u32 reg_ofs, u16 data)
If you're going to play games with macros & function names, please do it in a header file
+{
- u16 reg;
- u32 smi_dev_addr;
- smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port));
- do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
Is there any possibility this (and all the others) will become infinite loops?
- /* Poll till SMIBusy bit is clear */
- smi_wr_reg(port, smi_dev_addr, 0x1, data);
- /* Write data to Switch indirect data register */
- smi_wr_reg(port, smi_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
- /* Write command to Switch indirect command register (write) */
+}
+void mv88e61xx_rd_phy(u32 port, u32 phy_adr, u32 reg_ofs, u16 * data) +{
- u16 reg;
- u32 smi_dev_addr;
- smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port));
- do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
- /* Poll till SMIBusy bit is clear */
- smi_wr_reg(port, smi_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
- /* Write command to Switch indirect command register (read) */
- do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
- /* Poll till SMIBusy bit is clear */
- smi_rd_reg(port, smi_dev_addr, 0x1, (u16 *) & data);
- /* Read data from Switch indirect data register */
+} +#endif /* CONFIG_MV88E61XX_MULTICHIP_ADRMODE */
+static void mv88e61xx_vlaninit(u32 port, u32 cpu_port, u32 max_prtnum,
u32 ports_ofs, u32 port_mask)
+{
- u32 prt;
- u16 reg;
- /* be sure all ports are disabled */
- for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(port, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG,
®);
reg &= ~0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG,
reg);
- }
- /* Set CPU port VID to 0x1 */
- mv88e61xx_rd_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG,
®);
- reg &= ~0xfff;
- reg |= 0x1;
- mv88e61xx_wr_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG,
reg);
- /* Setting Port default priority for all ports to zero */
- for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(port, ports_ofs + prt, MV88E61XX_PRT_VID_REG,
®);
reg &= ~0xc000;
mv88e61xx_wr_phy(port, ports_ofs + prt, MV88E61XX_PRT_VID_REG,
reg);
- }
- /* Setting VID and VID map for all ports except CPU port */
- for (prt = 0; prt < max_prtnum; prt++) {
/* only for enabled ports */
if ((1 << prt) & port_mask) {
/* skip CPU port */
if (prt == cpu_port)
continue;
/*
* set Ports VLAN Mapping.
* port prt <--> MV88E61XX_CPU_PORT VLAN #prt+1.
*/
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, ®);
reg &= ~0x0fff;
reg |= (prt + 1);
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, reg);
/*
* Set Vlan map table for all ports to send only to
* MV88E61XX_CPU_PORT
*/
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, ®);
reg &= ~((1 << max_prtnum) - 1);
reg |= (1 << cpu_port);
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, reg);
}
- }
- /* Set Vlan map table for MV88E61XX_CPU_PORT to see all ports */
- mv88e61xx_rd_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG,
®);
- reg &= ~((1 << max_prtnum) - 1);
- reg |= port_mask & ~(1 << cpu_port);
- mv88e61xx_wr_phy(port, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG,
reg);
- /*
* enable only appropriate ports to forwarding mode
* and disable the others
*/
- for (prt = 0; prt < max_prtnum; prt++) {
if ((1 << prt) & port_mask) {
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, ®);
reg |= 0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
} else {
/* Disable port */
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, ®);
reg &= ~0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
}
- }
+}
+/*
- Marvell 88E61XX Switch initialization
- */
+int mv_switch_88e61xx_init(u32 port) +{
- u32 prt;
- u16 reg;
- volatile u32 timeout;
Why is this marked volatile?
- /* Init vlan */
- mv88e61xx_vlaninit(port, MV88E61XX_CPU_PORT, MV88E61XX_MAX_PORTS_NUM,
MV88E61XX_PRT_OFST, MV88E61XX_ENABLED_PORTS);
- /* Enable RGMII delay on Tx and Rx for CPU port */
- mv88e61xx_wr_phy(port, 0x14, 0x1a, 0x81e7);
- mv88e61xx_rd_phy(port, 0x15, 0x1a, ®);
- mv88e61xx_wr_phy(port, 0x15, 0x1a, 0x18);
- mv88e61xx_wr_phy(port, 0x14, 0x1a, 0xc1e7);
Please define these magic numbers somewhere
- for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {
if (prt != MV88E61XX_CPU_PORT) {
/*Enable Phy power up */
mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x3360);
mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9410 | (prt << 5)));
Same comment about magic numbers
/*
* Make sure SMIBusy bit cleared before another
* SMI operation can take place
*/
timeout = MV88E61XX_PHY_TIMEOUT;
do {
mv88e61xx_rd_phy(port,
MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD, ®);
if (timeout-- == 0) {
printf("SMI busy timeout\n");
return -1;
}
} while (reg & BIT28); /* busy mask */
mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x1140);
mv88e61xx_wr_phy(port, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9400 | (prt << 5)));
/*
* Make sure SMIBusy bit cleared before another
* SMI operation can take place
*/
timeout = MV88E61XX_PHY_TIMEOUT;
do {
mv88e61xx_rd_phy(port,
MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD, ®);
if (timeout-- == 0) {
printf("SMI busy timeout\n");
return -1;
}
} while (reg & BIT28); /* busy mask */
}
/*Enable port */
mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST + prt, 4, 0x7f);
- }
- /*Force CPU port to RGMII FDX 1000Base */
- mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST + MV88E61XX_CPU_PORT, 1,
0x3e);
Is RGMII the only mode this chip supports? If not, why are you forcing it so?
- printf(MV88E61XX_NAME " Initialized\n");
Shouldn't this message include the port number?
- return 0;
+}
+#endif /* CONFIG_SWITCH_MV88E61XX */

-----Original Message----- From: Ben Warren [mailto:biggerbadderben@gmail.com] Sent: Thursday, April 09, 2009 4:46 AM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v2] Marvell MV88E61XX Switch Driver support
Hi Prafulla, Prafulla Wadaskar wrote:
Chips supprted:-
- 88E6161 6 port gbe swtich with 5 integrated PHYs
- 88E6165 6 port gbe swtich with 5 integrated PHYs
Note: This driver is supported and tested against kirkwood egiga interface, other interfaces can be added
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: updated as per review comments by Wolfgand Denk removed other two drivers form earlier patch debug_prints removed driver moved to drivers/net/
drivers/net/Makefile | 1 + drivers/net/mv88e61xx.c | 291
+++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 292 insertions(+), 0 deletions(-) create mode 100644 drivers/net/mv88e61xx.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f0c5654..7482327 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,6 +47,7 @@ COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_SWITCH_MV88E61XX) += mv88e61xx.o
Please change this to CONFIG_MV88E61XX_SWITCH
Changed....
COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/mv88e61xx.c b/drivers/net/mv88e61xx.c new file mode 100644 index 0000000..8167919 --- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,291 @@ +/*
- (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>
+#if defined (CONFIG_SWITCH_MV88E61XX)
This is not needed - the makefile takes care of the conditional compilation
Removed...
+/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
BIT3 | BIT4 | BIT5)
+#endif
+#if defined (CONFIG_88E6161) +#define MV88E61XX_NAME "88E6161" +#elif defined (CONFIG_88E6165) +#define MV88E61XX_NAME "88E6165" +#else +#define MV88E61XX_NAME "88E61XX" +#endif
There doesn't appear to be any code difference between the different chips. What's the point of differentiating them here? If it is meaningful, you should at least #warning if none of the known-about variants is mentioned.
This part of code removed... Chip Id is read from PHY_Id reg and displayed now.
+#define MV88E61XX_PHY_TIMEOUT 100000 +#define MV88E61XX_MAX_PORTS_NUM 0x6 +/* CPU port can be configured in board header file */ +#if defined (CONFIG_MV88E61XX_CPU_PORT) +#define MV88E61XX_CPU_PORT CONFIG_MV88E61XX_CPU_PORT +#else +#define MV88E61XX_CPU_PORT 0x5 +#endif
+#define MV88E61XX_PRT_STS_REG 0x1 +#define MV88E61XX_PRT_CTRL_REG 0x4 +#define MV88E61XX_PRT_VMAP_REG 0x6 +#define MV88E61XX_PRT_VID_REG 0x7
+#define MV88E61XX_PRT_OFST 0x10 +#define MV88E61XX_PHY_CMD 0x18 +#define MV88E61XX_PHY_DATA 0x19 +#define MV88E61XX_GLOBAL2_REG_DEVADR 0x1C
+#ifdef CONFIG_KIRKWOOD_EGIGA +#define smi_wr_reg eth_smi_reg_write +#define smi_rd_reg eth_smi_reg_read +#else /* add new interface above this */ +#error Unsupported interface +#endif
Please find a better way to do this. Board-specific code doesn't belong in a driver.
this is now implemented using miiphy_read/write calls
+/* Chip Address mode
- The Switch support two modes of operation
- single chip mode and
- Multi-chip mode
- Refer chip documentation for more details
- By default single chip mode is configured
- multichip mode operation can be configured in board header
- */
+#ifndef CONFIG_MV88E61XX_MULTICHIP_ADRMODE +#define mv88e61xx_wr_phy smi_wr_reg +#define mv88e61xx_rd_phy smi_rd_reg +#else +void mv88e61xx_wr_phy(u32 port, u32 phy_adr, u32 reg_ofs, u16 data)
If you're going to play games with macros & function names, please do it in a header file
Void .. Removed....
+{
- u16 reg;
- u32 smi_dev_addr;
- smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port));
- do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
Is there any possibility this (and all the others) will become infinite loops?
No there is no such posibility, but at safer side I put there time out
- /* Poll till SMIBusy bit is clear */
- smi_wr_reg(port, smi_dev_addr, 0x1, data);
- /* Write data to Switch indirect data register */
- smi_wr_reg(port, smi_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
- /* Write command to Switch indirect command register (write) */
+}
+void mv88e61xx_rd_phy(u32 port, u32 phy_adr, u32 reg_ofs,
u16 * data)
+{
- u16 reg;
- u32 smi_dev_addr;
- smi_dev_addr = KW_REG_READ(KW_ETH_PHY_ADDR_REG(port));
- do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
- /* Poll till SMIBusy bit is clear */
- smi_wr_reg(port, smi_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
- /* Write command to Switch indirect command register (read) */
- do {
smi_rd_reg(port, smi_dev_addr, 0x0, ®);
- } while ((reg & BIT15));
- /* Poll till SMIBusy bit is clear */
- smi_rd_reg(port, smi_dev_addr, 0x1, (u16 *) & data);
- /* Read data from Switch indirect data register */
+} +#endif /* CONFIG_MV88E61XX_MULTICHIP_ADRMODE */
+static void mv88e61xx_vlaninit(u32 port, u32 cpu_port, u32
max_prtnum,
u32 ports_ofs, u32 port_mask)
+{
- u32 prt;
- u16 reg;
- /* be sure all ports are disabled */
- for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG,
®);
reg &= ~0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG,
reg);
- }
- /* Set CPU port VID to 0x1 */
- mv88e61xx_rd_phy(port, (ports_ofs + cpu_port),
MV88E61XX_PRT_VID_REG,
®);
- reg &= ~0xfff;
- reg |= 0x1;
- mv88e61xx_wr_phy(port, (ports_ofs + cpu_port),
MV88E61XX_PRT_VID_REG,
reg);
- /* Setting Port default priority for all ports to zero */
- for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VID_REG,
®);
reg &= ~0xc000;
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VID_REG,
reg);
- }
- /* Setting VID and VID map for all ports except CPU port */
- for (prt = 0; prt < max_prtnum; prt++) {
/* only for enabled ports */
if ((1 << prt) & port_mask) {
/* skip CPU port */
if (prt == cpu_port)
continue;
/*
* set Ports VLAN Mapping.
* port prt <-->
MV88E61XX_CPU_PORT VLAN #prt+1.
*/
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, ®);
reg &= ~0x0fff;
reg |= (prt + 1);
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, reg);
/*
* Set Vlan map table for all ports to
send only to
* MV88E61XX_CPU_PORT
*/
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, ®);
reg &= ~((1 << max_prtnum) - 1);
reg |= (1 << cpu_port);
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, reg);
}
- }
- /* Set Vlan map table for MV88E61XX_CPU_PORT to see all ports */
- mv88e61xx_rd_phy(port, (ports_ofs + cpu_port),
MV88E61XX_PRT_VMAP_REG,
®);
- reg &= ~((1 << max_prtnum) - 1);
- reg |= port_mask & ~(1 << cpu_port);
- mv88e61xx_wr_phy(port, (ports_ofs + cpu_port),
MV88E61XX_PRT_VMAP_REG,
reg);
- /*
* enable only appropriate ports to forwarding mode
* and disable the others
*/
- for (prt = 0; prt < max_prtnum; prt++) {
if ((1 << prt) & port_mask) {
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, ®);
reg |= 0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
} else {
/* Disable port */
mv88e61xx_rd_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, ®);
reg &= ~0x3;
mv88e61xx_wr_phy(port, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
}
- }
+}
+/*
- Marvell 88E61XX Switch initialization
- */
+int mv_switch_88e61xx_init(u32 port) +{
- u32 prt;
- u16 reg;
- volatile u32 timeout;
Why is this marked volatile?
Sorry .. Removed.....
- /* Init vlan */
- mv88e61xx_vlaninit(port, MV88E61XX_CPU_PORT,
MV88E61XX_MAX_PORTS_NUM,
MV88E61XX_PRT_OFST, MV88E61XX_ENABLED_PORTS);
- /* Enable RGMII delay on Tx and Rx for CPU port */
- mv88e61xx_wr_phy(port, 0x14, 0x1a, 0x81e7);
- mv88e61xx_rd_phy(port, 0x15, 0x1a, ®);
- mv88e61xx_wr_phy(port, 0x15, 0x1a, 0x18);
- mv88e61xx_wr_phy(port, 0x14, 0x1a, 0xc1e7);
Please define these magic numbers somewhere
I am sorry, At this moment I can't, since I do not have sufficient data. I got this info from h/w team, data sheets yet to update :-( I will do it latter..
- for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {
if (prt != MV88E61XX_CPU_PORT) {
/*Enable Phy power up */
mv88e61xx_wr_phy(port,
MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x3360);
mv88e61xx_wr_phy(port,
MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9410 | (prt << 5)));
Same comment about magic numbers
Put some comments there..
/*
* Make sure SMIBusy bit cleared before another
* SMI operation can take place
*/
timeout = MV88E61XX_PHY_TIMEOUT;
do {
mv88e61xx_rd_phy(port,
MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD, ®);
if (timeout-- == 0) {
printf("SMI busy timeout\n");
return -1;
}
} while (reg & BIT28); /* busy mask */
mv88e61xx_wr_phy(port,
MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x1140);
mv88e61xx_wr_phy(port,
MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9400 | (prt << 5)));
/*
* Make sure SMIBusy bit cleared before another
* SMI operation can take place
*/
timeout = MV88E61XX_PHY_TIMEOUT;
do {
mv88e61xx_rd_phy(port,
MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD, ®);
if (timeout-- == 0) {
printf("SMI busy timeout\n");
return -1;
}
} while (reg & BIT28); /* busy mask */
}
/*Enable port */
mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST +
prt, 4, 0x7f);
- }
- /*Force CPU port to RGMII FDX 1000Base */
- mv88e61xx_wr_phy(port, MV88E61XX_PRT_OFST +
MV88E61XX_CPU_PORT, 1,
0x3e);
Is RGMII the only mode this chip supports? If not, why are you forcing it so?
- printf(MV88E61XX_NAME " Initialized\n");
Shouldn't this message include the port number?
Added port name to the string
I am sending v3 patch for the same
Reagards..
Prafulla . .
- return 0;
+}
+#endif /* CONFIG_SWITCH_MV88E61XX */

Chips supported:- 1. 88E6161 6 port gbe swtich with 5 integrated PHYs 2. 88E6165 6 port gbe swtich with 5 integrated PHYs 2. 88E6132 3 port gbe swtich with 2 integrated PHYs
Note: This driver is supported and tested against kirkwood egiga interface
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: updated as per review comments for v1 removed other two drivers form earlier patch debug_prints removed driver moved to drivers/net/
v3: updated as per review comments for v2 miiphy interface used, platform specific dependency resolved Chip id detection and printing added common code forked out some cosmetic and magic number fixes
drivers/net/Makefile | 1 + drivers/net/mv88e61xx.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 300 insertions(+), 0 deletions(-) create mode 100644 drivers/net/mv88e61xx.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f0c5654..9e8787c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,6 +47,7 @@ COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/mv88e61xx.c b/drivers/net/mv88e61xx.c new file mode 100644 index 0000000..31a6fa6 --- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,299 @@ +/* + * (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 <miiphy.h> + +/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \ + BIT3 | BIT4 | BIT5) +#endif + +#define MV88E61XX_PHY_TIMEOUT 100000 +#define MV88E61XX_MAX_PORTS_NUM 0x6 + +/* CPU port can be configured in board header file */ +#if defined (CONFIG_MV88E61XX_CPU_PORT) +#define MV88E61XX_CPU_PORT CONFIG_MV88E61XX_CPU_PORT +#else +#define MV88E61XX_CPU_PORT 0x5 +#endif + +#define MV88E61XX_PRT_STS_REG 0x1 +#define MV88E61XX_PRT_CTRL_REG 0x4 +#define MV88E61XX_PRT_VMAP_REG 0x6 +#define MV88E61XX_PRT_VID_REG 0x7 + +#define MV88E61XX_PRT_OFST 0x10 +#define MV88E61XX_PHY_CMD 0x18 +#define MV88E61XX_PHY_DATA 0x19 +#define MV88E61XX_GLOBAL2_REG_DEVADR 0x1C + +/* Chip Address mode + * The Switch support two modes of operation + * 1. single chip mode and + * 2. Multi-chip mode + * Refer chip documentation for more details + * + * By default single chip mode is configured + * multichip mode operation can be configured in board header + */ +#ifndef CONFIG_MV88E61XX_MULTICHIP_ADRMODE +#define mv88e61xx_wr_phy miiphy_write +#define mv88e61xx_rd_phy miiphy_read +#else + +int mv88e61xx_busychk_multic(u32 devaddr) +{ + u32 reg = 0; + u32 timeout = MV88E61XX_PHY_TIMEOUT; + + /* Poll till SMIBusy bit is clear */ + do { + miiphy_read(name, devaddr, 0x0, ®); + if (timeout-- == 0) { + printf("SMI busy timeout\n"); + return -1; + } + } while (reg & BIT15); + return 0; +} + +void mv88e61xx_wr_phy(char *name, u32 phy_adr, u32 reg_ofs, u16 data) +{ + u16 reg; + u32 mii_dev_addr; + + /* command to read PHY dev address */ + miiphy_read(name, 0xEE, 0xEE, &mii_dev_addr); + mv88e61xx_busychk_multic(mii_dev_addr); + /* Write data to Switch indirect data register */ + miiphy_write(name, mii_dev_addr, 0x1, data); + /* Write command to Switch indirect command register (write) */ + miiphy_write(name, mii_dev_addr, 0x0, + reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15); +} + +void mv88e61xx_rd_phy(char *name, u32 phy_adr, u32 reg_ofs, u16 * data) +{ + u16 reg; + u32 mii_dev_addr; + + /* command to read PHY dev address */ + miiphy_read(name, 0xEE, 0xEE, &mii_dev_addr); + mv88e61xx_busychk_multic(mii_dev_addr); + /* Write command to Switch indirect command register (read) */ + miiphy_write(name, mii_dev_addr, 0x0, + reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15); + mv88e61xx_busychk_multic(mii_dev_addr); + /* Read data from Switch indirect data register */ + miiphy_read(name, mii_dev_addr, 0x1, (u16 *) & data); +} +#endif /* CONFIG_MV88E61XX_MULTICHIP_ADRMODE */ + +static void mv88e61xx_vlaninit(char *name, u32 cpu_port, u32 max_prtnum, + u32 ports_ofs, u32 port_mask) +{ + u32 prt; + u16 reg; + + /* be sure all ports are disabled */ + for (prt = 0; prt < max_prtnum; prt++) { + mv88e61xx_rd_phy(name, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG, + ®); + reg &= ~0x3; + mv88e61xx_wr_phy(name, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG, + reg); + } + /* Set CPU port VID to 0x1 */ + mv88e61xx_rd_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG, + ®); + reg &= ~0xfff; + reg |= 0x1; + mv88e61xx_wr_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG, + reg); + + /* Setting Port default priority for all ports to zero */ + for (prt = 0; prt < max_prtnum; prt++) { + mv88e61xx_rd_phy(name, ports_ofs + prt, MV88E61XX_PRT_VID_REG, + ®); + reg &= ~0xc000; + mv88e61xx_wr_phy(name, ports_ofs + prt, MV88E61XX_PRT_VID_REG, + reg); + } + /* Setting VID and VID map for all ports except CPU port */ + for (prt = 0; prt < max_prtnum; prt++) { + /* only for enabled ports */ + if ((1 << prt) & port_mask) { + /* skip CPU port */ + if (prt == cpu_port) + continue; + + /* + * set Ports VLAN Mapping. + * port prt <--> MV88E61XX_CPU_PORT VLAN #prt+1. + */ + + mv88e61xx_rd_phy(name, ports_ofs + prt, + MV88E61XX_PRT_VID_REG, ®); + reg &= ~0x0fff; + reg |= (prt + 1); + mv88e61xx_wr_phy(name, ports_ofs + prt, + MV88E61XX_PRT_VID_REG, reg); + + /* + * Set Vlan map table for all ports to send only to + * MV88E61XX_CPU_PORT + */ + mv88e61xx_rd_phy(name, ports_ofs + prt, + MV88E61XX_PRT_VMAP_REG, ®); + reg &= ~((1 << max_prtnum) - 1); + reg |= (1 << cpu_port); + mv88e61xx_wr_phy(name, ports_ofs + prt, + MV88E61XX_PRT_VMAP_REG, reg); + } + } + /* Set Vlan map table for MV88E61XX_CPU_PORT to see all ports */ + mv88e61xx_rd_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG, + ®); + reg &= ~((1 << max_prtnum) - 1); + reg |= port_mask & ~(1 << cpu_port); + mv88e61xx_wr_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG, + reg); + + /* + * enable only appropriate ports to forwarding mode + * and disable the others + */ + for (prt = 0; prt < max_prtnum; prt++) { + if ((1 << prt) & port_mask) { + mv88e61xx_rd_phy(name, ports_ofs + prt, + MV88E61XX_PRT_CTRL_REG, ®); + reg |= 0x3; + mv88e61xx_wr_phy(name, ports_ofs + prt, + MV88E61XX_PRT_CTRL_REG, reg); + } else { + /* Disable port */ + mv88e61xx_rd_phy(name, ports_ofs + prt, + MV88E61XX_PRT_CTRL_REG, ®); + reg &= ~0x3; + mv88e61xx_wr_phy(name, ports_ofs + prt, + MV88E61XX_PRT_CTRL_REG, reg); + } + } +} + +/* + * Make sure SMIBusy bit cleared before another + * SMI operation can take place + */ +int mv88361xx_busychk(char *name) +{ + u32 reg = 0; + u32 timeout = MV88E61XX_PHY_TIMEOUT; + do { + mv88e61xx_rd_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_CMD, ®); + if (timeout-- == 0) { + printf("SMI busy timeout\n"); + return -1; + } + } while (reg & BIT28); /* busy mask */ + return 0; +} + +/* + * Marvell 88E61XX Switch initialization + */ +int mv_switch_88e61xx_init(char *name) +{ + u32 prt; + u16 reg; + + if (miiphy_set_current_dev(name)) { + printf("%s failed\n", __FUNCTION__); + return -1; + } + + /* Init vlan */ + mv88e61xx_vlaninit(name, MV88E61XX_CPU_PORT, MV88E61XX_MAX_PORTS_NUM, + MV88E61XX_PRT_OFST, MV88E61XX_ENABLED_PORTS); + +#ifdef CONFIG_SYS_RGMII_MODE + /* Enable RGMII delay on Tx and Rx for CPU port */ + mv88e61xx_wr_phy(name, 0x14, 0x1a, 0x81e7); + mv88e61xx_rd_phy(name, 0x15, 0x1a, ®); + mv88e61xx_wr_phy(name, 0x15, 0x1a, 0x18); + mv88e61xx_wr_phy(name, 0x14, 0x1a, 0xc1e7); +#endif + + for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) { + if (prt != MV88E61XX_CPU_PORT) { + /* Write Copper Specific control reg1 (0x14) for- + * Enable Phy power up + * Energy Detect on (sense&Xmit NLP Periodically + * reset other settings default + */ + mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_DATA, 0x3360); + mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_CMD, + (0x9410 | (prt << 5))); + + if (mv88361xx_busychk(name)) + return -1; + + /* Write PHY ctrl reg (0x0) to apply + * Phy reset (BIT15=low) + * reset other default values + */ + mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_DATA, 0x1140); + mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR, + MV88E61XX_PHY_CMD, + (0x9400 | (prt << 5))); + + if (mv88361xx_busychk(name)) + return -1; + } + + /*Enable port */ + mv88e61xx_wr_phy(name, MV88E61XX_PRT_OFST + prt, 4, 0x7f); + } + + mv88e61xx_rd_phy(name, MV88E61XX_PRT_OFST, PHY_PHYIDR2, ®); + reg &= 0xfff0; + if (reg == 0x1610) + printf("88E6161"); + if (reg == 0x1650) + printf("88E6165"); + if (reg == 0x1210) + printf("88E6123"); + + printf(" Initialized on %s\n", name); + return 0; +}

On 22:31 Thu 09 Apr , Prafulla Wadaskar wrote:
Chips supported:-
- 88E6161 6 port gbe swtich with 5 integrated PHYs
- 88E6165 6 port gbe swtich with 5 integrated PHYs
- 88E6132 3 port gbe swtich with 2 integrated PHYs
Note: This driver is supported and tested against kirkwood egiga interface
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: updated as per review comments for v1 removed other two drivers form earlier patch debug_prints removed driver moved to drivers/net/
v3: updated as per review comments for v2 miiphy interface used, platform specific dependency resolved Chip id detection and printing added common code forked out some cosmetic and magic number fixes
drivers/net/Makefile | 1 + drivers/net/mv88e61xx.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++
the m88e61xx is a switch so have it in drivers/net/phy could make more sense
2 files changed, 300 insertions(+), 0 deletions(-) create mode 100644 drivers/net/mv88e61xx.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f0c5654..9e8787c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,6 +47,7 @@ COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/mv88e61xx.c b/drivers/net/mv88e61xx.c new file mode 100644 index 0000000..31a6fa6 --- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,299 @@ +/*
- (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 <miiphy.h>
+/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
BIT3 | BIT4 | BIT5)
please avoid this BITx macrot
+#endif
+#define MV88E61XX_PHY_TIMEOUT 100000 +#define MV88E61XX_MAX_PORTS_NUM 0x6
+/* CPU port can be configured in board header file */ +#if defined (CONFIG_MV88E61XX_CPU_PORT) +#define MV88E61XX_CPU_PORT CONFIG_MV88E61XX_CPU_PORT +#else +#define MV88E61XX_CPU_PORT 0x5 +#endif
this cpu port is normally configured by latch resistor you may could detect it
+#define MV88E61XX_PRT_STS_REG 0x1 +#define MV88E61XX_PRT_CTRL_REG 0x4 +#define MV88E61XX_PRT_VMAP_REG 0x6 +#define MV88E61XX_PRT_VID_REG 0x7
+#define MV88E61XX_PRT_OFST 0x10 +#define MV88E61XX_PHY_CMD 0x18 +#define MV88E61XX_PHY_DATA 0x19 +#define MV88E61XX_GLOBAL2_REG_DEVADR 0x1C
GLOBAL2_REGISTER will be better
+/* Chip Address mode
- The Switch support two modes of operation
- single chip mode and
- Multi-chip mode
- Refer chip documentation for more details
- By default single chip mode is configured
- multichip mode operation can be configured in board header
- */
+#ifndef CONFIG_MV88E61XX_MULTICHIP_ADRMODE +#define mv88e61xx_wr_phy miiphy_write +#define mv88e61xx_rd_phy miiphy_read +#else
+int mv88e61xx_busychk_multic(u32 devaddr) +{
- u32 reg = 0;
- u32 timeout = MV88E61XX_PHY_TIMEOUT;
- /* Poll till SMIBusy bit is clear */
- do {
miiphy_read(name, devaddr, 0x0, ®);
if (timeout-- == 0) {
printf("SMI busy timeout\n");
return -1;
}
- } while (reg & BIT15);
- return 0;
+}
+void mv88e61xx_wr_phy(char *name, u32 phy_adr, u32 reg_ofs, u16 data) +{
- u16 reg;
- u32 mii_dev_addr;
- /* command to read PHY dev address */
- miiphy_read(name, 0xEE, 0xEE, &mii_dev_addr);
- mv88e61xx_busychk_multic(mii_dev_addr);
- /* Write data to Switch indirect data register */
- miiphy_write(name, mii_dev_addr, 0x1, data);
- /* Write command to Switch indirect command register (write) */
- miiphy_write(name, mii_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
+}
+void mv88e61xx_rd_phy(char *name, u32 phy_adr, u32 reg_ofs, u16 * data) +{
- u16 reg;
- u32 mii_dev_addr;
- /* command to read PHY dev address */
- miiphy_read(name, 0xEE, 0xEE, &mii_dev_addr);
- mv88e61xx_busychk_multic(mii_dev_addr);
- /* Write command to Switch indirect command register (read) */
- miiphy_write(name, mii_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
- mv88e61xx_busychk_multic(mii_dev_addr);
- /* Read data from Switch indirect data register */
- miiphy_read(name, mii_dev_addr, 0x1, (u16 *) & data);
+} +#endif /* CONFIG_MV88E61XX_MULTICHIP_ADRMODE */
a doc explaining how to us it will be nice
+static void mv88e61xx_vlaninit(char *name, u32 cpu_port, u32 max_prtnum,
u32 ports_ofs, u32 port_mask)
+{
- u32 prt;
- u16 reg;
- /* be sure all ports are disabled */
- for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(name, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG,
®);
reg &= ~0x3;
mv88e61xx_wr_phy(name, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG,
reg);
- }
- /* Set CPU port VID to 0x1 */
- mv88e61xx_rd_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG,
®);
- reg &= ~0xfff;
- reg |= 0x1;
- mv88e61xx_wr_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG,
reg);
- /* Setting Port default priority for all ports to zero */
- for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(name, ports_ofs + prt, MV88E61XX_PRT_VID_REG,
®);
reg &= ~0xc000;
mv88e61xx_wr_phy(name, ports_ofs + prt, MV88E61XX_PRT_VID_REG,
reg);
- }
- /* Setting VID and VID map for all ports except CPU port */
- for (prt = 0; prt < max_prtnum; prt++) {
/* only for enabled ports */
if ((1 << prt) & port_mask) {
/* skip CPU port */
if (prt == cpu_port)
continue;
/*
* set Ports VLAN Mapping.
* port prt <--> MV88E61XX_CPU_PORT VLAN #prt+1.
*/
mv88e61xx_rd_phy(name, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, ®);
reg &= ~0x0fff;
reg |= (prt + 1);
mv88e61xx_wr_phy(name, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, reg);
/*
* Set Vlan map table for all ports to send only to
* MV88E61XX_CPU_PORT
*/
mv88e61xx_rd_phy(name, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, ®);
reg &= ~((1 << max_prtnum) - 1);
reg |= (1 << cpu_port);
mv88e61xx_wr_phy(name, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, reg);
}
- }
- /* Set Vlan map table for MV88E61XX_CPU_PORT to see all ports */
- mv88e61xx_rd_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG,
®);
- reg &= ~((1 << max_prtnum) - 1);
- reg |= port_mask & ~(1 << cpu_port);
- mv88e61xx_wr_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG,
reg);
- /*
* enable only appropriate ports to forwarding mode
* and disable the others
*/
- for (prt = 0; prt < max_prtnum; prt++) {
if ((1 << prt) & port_mask) {
mv88e61xx_rd_phy(name, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, ®);
reg |= 0x3;
mv88e61xx_wr_phy(name, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
} else {
/* Disable port */
mv88e61xx_rd_phy(name, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, ®);
reg &= ~0x3;
mv88e61xx_wr_phy(name, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
}
- }
+}
+/*
- Make sure SMIBusy bit cleared before another
- SMI operation can take place
- */
+int mv88361xx_busychk(char *name) +{
- u32 reg = 0;
- u32 timeout = MV88E61XX_PHY_TIMEOUT;
- do {
mv88e61xx_rd_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD, ®);
if (timeout-- == 0) {
printf("SMI busy timeout\n");
return -1;
}
- } while (reg & BIT28); /* busy mask */
- return 0;
+}
+/*
- Marvell 88E61XX Switch initialization
- */
+int mv_switch_88e61xx_init(char *name) +{
- u32 prt;
- u16 reg;
- if (miiphy_set_current_dev(name)) {
printf("%s failed\n", __FUNCTION__);
return -1;
- }
- /* Init vlan */
- mv88e61xx_vlaninit(name, MV88E61XX_CPU_PORT, MV88E61XX_MAX_PORTS_NUM,
MV88E61XX_PRT_OFST, MV88E61XX_ENABLED_PORTS);
this is board specific
+#ifdef CONFIG_SYS_RGMII_MODE
- /* Enable RGMII delay on Tx and Rx for CPU port */
- mv88e61xx_wr_phy(name, 0x14, 0x1a, 0x81e7);
- mv88e61xx_rd_phy(name, 0x15, 0x1a, ®);
- mv88e61xx_wr_phy(name, 0x15, 0x1a, 0x18);
- mv88e61xx_wr_phy(name, 0x14, 0x1a, 0xc1e7);
+#endif
this too
- for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {
if (prt != MV88E61XX_CPU_PORT) {
/* Write Copper Specific control reg1 (0x14) for-
* Enable Phy power up
* Energy Detect on (sense&Xmit NLP Periodically
* reset other settings default
*/
mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x3360);
mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9410 | (prt << 5)));
if (mv88361xx_busychk(name))
return -1;
/* Write PHY ctrl reg (0x0) to apply
* Phy reset (BIT15=low)
* reset other default values
*/
mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x1140);
mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9400 | (prt << 5)));
if (mv88361xx_busychk(name))
return -1;
}
/*Enable port */
mv88e61xx_wr_phy(name, MV88E61XX_PRT_OFST + prt, 4, 0x7f);
- }
this too
- mv88e61xx_rd_phy(name, MV88E61XX_PRT_OFST, PHY_PHYIDR2, ®);
- reg &= 0xfff0;
- if (reg == 0x1610)
printf("88E6161");
- if (reg == 0x1650)
printf("88E6165");
- if (reg == 0x1210)
printf("88E6123");
by detecting the switch model you will capable to identify the numbers of ports and their capability
- printf(" Initialized on %s\n", name);
- return 0;
+}
Best Regards, J.

Dear Jean,
Thanks for your comments Please see my inlined reply
________________________________________ From: Jean-Christophe PLAGNIOL-VILLARD [plagnioj@jcrosoft.com] Sent: Tuesday, April 14, 2009 3:49 AM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v3] Marvell MV88E61XX Switch Driver support
On 22:31 Thu 09 Apr , Prafulla Wadaskar wrote:
Chips supported:-
- 88E6161 6 port gbe swtich with 5 integrated PHYs
- 88E6165 6 port gbe swtich with 5 integrated PHYs
- 88E6132 3 port gbe swtich with 2 integrated PHYs
Note: This driver is supported and tested against kirkwood egiga interface
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: updated as per review comments for v1 removed other two drivers form earlier patch debug_prints removed driver moved to drivers/net/
v3: updated as per review comments for v2 miiphy interface used, platform specific dependency resolved Chip id detection and printing added common code forked out some cosmetic and magic number fixes
drivers/net/Makefile | 1 + drivers/net/mv88e61xx.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++
the m88e61xx is a switch so have it in drivers/net/phy could make more sense Prafulla: This driver represents the mv88e61xx chips which uses miiphy interface provided externally so I think drivers/net/ it correct place for it. drivers/net/phy/ generally has phy read/write modules code like bitbang mii interface.
2 files changed, 300 insertions(+), 0 deletions(-) create mode 100644 drivers/net/mv88e61xx.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f0c5654..9e8787c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,6 +47,7 @@ COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/mv88e61xx.c b/drivers/net/mv88e61xx.c new file mode 100644 index 0000000..31a6fa6 --- /dev/null +++ b/drivers/net/mv88e61xx.c @@ -0,0 +1,299 @@ +/*
- (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 <miiphy.h>
+/* Enabled ports can be enabled in board header file */ +#if defined (CONFIG_MV88E61XX_ENABLED_PORTS) +#define MV88E61XX_ENABLED_PORTS CONFIG_MV88E61XX_ENABLED_PORTS +#else +#define MV88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
BIT3 | BIT4 | BIT5)
please avoid this BITx macrot Prafulla: OK, I will hardcode this value, but in my view it looks better (readable) using these macros provided those are available on other platforms, mostly it should be, how about renaming them as PORTx ?
+#endif
+#define MV88E61XX_PHY_TIMEOUT 100000 +#define MV88E61XX_MAX_PORTS_NUM 0x6
+/* CPU port can be configured in board header file */ +#if defined (CONFIG_MV88E61XX_CPU_PORT) +#define MV88E61XX_CPU_PORT CONFIG_MV88E61XX_CPU_PORT +#else +#define MV88E61XX_CPU_PORT 0x5 +#endif
this cpu port is normally configured by latch resistor you may could detect it Prafulla: There are two ports on 6165/6161 and one port on 6123 which can be used for CPU interface, this is decided by board h/w. we offer this configuration to board header file, default value is port5 Prafulla: I could not find "latch register" in the switch documentation, can you pls explain this?
+#define MV88E61XX_PRT_STS_REG 0x1 +#define MV88E61XX_PRT_CTRL_REG 0x4 +#define MV88E61XX_PRT_VMAP_REG 0x6 +#define MV88E61XX_PRT_VID_REG 0x7
+#define MV88E61XX_PRT_OFST 0x10 +#define MV88E61XX_PHY_CMD 0x18 +#define MV88E61XX_PHY_DATA 0x19 +#define MV88E61XX_GLOBAL2_REG_DEVADR 0x1C
GLOBAL2_REGISTER will be better Prafulla: Actually I has used similar name earlier (v1) but wolfgang suggested to use smaller names so I trimmed them and others too, I am planning to trim it further to MV88E61XX_GLB2REG_DEVADR in next release
+/* Chip Address mode
- The Switch support two modes of operation
- single chip mode and
- Multi-chip mode
- Refer chip documentation for more details
- By default single chip mode is configured
- multichip mode operation can be configured in board header
- */
+#ifndef CONFIG_MV88E61XX_MULTICHIP_ADRMODE +#define mv88e61xx_wr_phy miiphy_write +#define mv88e61xx_rd_phy miiphy_read +#else
+int mv88e61xx_busychk_multic(u32 devaddr) +{
u32 reg = 0;
u32 timeout = MV88E61XX_PHY_TIMEOUT;
/* Poll till SMIBusy bit is clear */
do {
miiphy_read(name, devaddr, 0x0, ®);
if (timeout-- == 0) {
printf("SMI busy timeout\n");
return -1;
}
} while (reg & BIT15);
return 0;
+}
+void mv88e61xx_wr_phy(char *name, u32 phy_adr, u32 reg_ofs, u16 data) +{
u16 reg;
u32 mii_dev_addr;
/* command to read PHY dev address */
miiphy_read(name, 0xEE, 0xEE, &mii_dev_addr);
mv88e61xx_busychk_multic(mii_dev_addr);
/* Write data to Switch indirect data register */
miiphy_write(name, mii_dev_addr, 0x1, data);
/* Write command to Switch indirect command register (write) */
miiphy_write(name, mii_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
+}
+void mv88e61xx_rd_phy(char *name, u32 phy_adr, u32 reg_ofs, u16 * data) +{
u16 reg;
u32 mii_dev_addr;
/* command to read PHY dev address */
miiphy_read(name, 0xEE, 0xEE, &mii_dev_addr);
mv88e61xx_busychk_multic(mii_dev_addr);
/* Write command to Switch indirect command register (read) */
miiphy_write(name, mii_dev_addr, 0x0,
reg_ofs | (phy_adr << 5) | BIT10 | BIT12 | BIT15);
mv88e61xx_busychk_multic(mii_dev_addr);
/* Read data from Switch indirect data register */
miiphy_read(name, mii_dev_addr, 0x1, (u16 *) & data);
+} +#endif /* CONFIG_MV88E61XX_MULTICHIP_ADRMODE */
a doc explaining how to us it will be nice Prafulla: I can give here reference to the relevant chapter in data sheet
+static void mv88e61xx_vlaninit(char *name, u32 cpu_port, u32 max_prtnum,
u32 ports_ofs, u32 port_mask)
+{
u32 prt;
u16 reg;
/* be sure all ports are disabled */
for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(name, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG,
®);
reg &= ~0x3;
mv88e61xx_wr_phy(name, ports_ofs + prt, MV88E61XX_PRT_CTRL_REG,
reg);
}
/* Set CPU port VID to 0x1 */
mv88e61xx_rd_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG,
®);
reg &= ~0xfff;
reg |= 0x1;
mv88e61xx_wr_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VID_REG,
reg);
/* Setting Port default priority for all ports to zero */
for (prt = 0; prt < max_prtnum; prt++) {
mv88e61xx_rd_phy(name, ports_ofs + prt, MV88E61XX_PRT_VID_REG,
®);
reg &= ~0xc000;
mv88e61xx_wr_phy(name, ports_ofs + prt, MV88E61XX_PRT_VID_REG,
reg);
}
/* Setting VID and VID map for all ports except CPU port */
for (prt = 0; prt < max_prtnum; prt++) {
/* only for enabled ports */
if ((1 << prt) & port_mask) {
/* skip CPU port */
if (prt == cpu_port)
continue;
/*
* set Ports VLAN Mapping.
* port prt <--> MV88E61XX_CPU_PORT VLAN #prt+1.
*/
mv88e61xx_rd_phy(name, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, ®);
reg &= ~0x0fff;
reg |= (prt + 1);
mv88e61xx_wr_phy(name, ports_ofs + prt,
MV88E61XX_PRT_VID_REG, reg);
/*
* Set Vlan map table for all ports to send only to
* MV88E61XX_CPU_PORT
*/
mv88e61xx_rd_phy(name, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, ®);
reg &= ~((1 << max_prtnum) - 1);
reg |= (1 << cpu_port);
mv88e61xx_wr_phy(name, ports_ofs + prt,
MV88E61XX_PRT_VMAP_REG, reg);
}
}
/* Set Vlan map table for MV88E61XX_CPU_PORT to see all ports */
mv88e61xx_rd_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG,
®);
reg &= ~((1 << max_prtnum) - 1);
reg |= port_mask & ~(1 << cpu_port);
mv88e61xx_wr_phy(name, (ports_ofs + cpu_port), MV88E61XX_PRT_VMAP_REG,
reg);
/*
* enable only appropriate ports to forwarding mode
* and disable the others
*/
for (prt = 0; prt < max_prtnum; prt++) {
if ((1 << prt) & port_mask) {
mv88e61xx_rd_phy(name, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, ®);
reg |= 0x3;
mv88e61xx_wr_phy(name, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
} else {
/* Disable port */
mv88e61xx_rd_phy(name, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, ®);
reg &= ~0x3;
mv88e61xx_wr_phy(name, ports_ofs + prt,
MV88E61XX_PRT_CTRL_REG, reg);
}
}
+}
+/*
- Make sure SMIBusy bit cleared before another
- SMI operation can take place
- */
+int mv88361xx_busychk(char *name) +{
u32 reg = 0;
u32 timeout = MV88E61XX_PHY_TIMEOUT;
do {
mv88e61xx_rd_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD, ®);
if (timeout-- == 0) {
printf("SMI busy timeout\n");
return -1;
}
} while (reg & BIT28); /* busy mask */
return 0;
+}
+/*
- Marvell 88E61XX Switch initialization
- */
+int mv_switch_88e61xx_init(char *name) +{
u32 prt;
u16 reg;
if (miiphy_set_current_dev(name)) {
printf("%s failed\n", __FUNCTION__);
return -1;
}
/* Init vlan */
mv88e61xx_vlaninit(name, MV88E61XX_CPU_PORT, MV88E61XX_MAX_PORTS_NUM,
MV88E61XX_PRT_OFST, MV88E61XX_ENABLED_PORTS);
this is board specific Prafulla : the objective of this driver it to power up switch h/w to enable data path for Ethernet controller in switch managed mode (CPU <-> all other ports). Prafulla: I think this is the functionality specific
+#ifdef CONFIG_SYS_RGMII_MODE
/* Enable RGMII delay on Tx and Rx for CPU port */
mv88e61xx_wr_phy(name, 0x14, 0x1a, 0x81e7);
mv88e61xx_rd_phy(name, 0x15, 0x1a, ®);
mv88e61xx_wr_phy(name, 0x15, 0x1a, 0x18);
mv88e61xx_wr_phy(name, 0x14, 0x1a, 0xc1e7);
+#endif
this too Prafulla: this will be needed only if RGMII interface is used for this switch on any platform, so is needed here.
for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {
if (prt != MV88E61XX_CPU_PORT) {
/* Write Copper Specific control reg1 (0x14) for-
* Enable Phy power up
* Energy Detect on (sense&Xmit NLP Periodically
* reset other settings default
*/
mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x3360);
mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9410 | (prt << 5)));
if (mv88361xx_busychk(name))
return -1;
/* Write PHY ctrl reg (0x0) to apply
* Phy reset (BIT15=low)
* reset other default values
*/
mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_DATA, 0x1140);
mv88e61xx_wr_phy(name, MV88E61XX_GLOBAL2_REG_DEVADR,
MV88E61XX_PHY_CMD,
(0x9400 | (prt << 5)));
if (mv88361xx_busychk(name))
return -1;
}
/*Enable port */
mv88e61xx_wr_phy(name, MV88E61XX_PRT_OFST + prt, 4, 0x7f);
}
this too Prafulla : No :-) ... switch objective..., if I abstract your platform specific comments, there is nothing special in it to keep it in drivers/net/ Prafulla: so on any platform if this switch is used, this driver can be enabled, currently it provides copper specific init, can be extended further for fiber optics and other needs
mv88e61xx_rd_phy(name, MV88E61XX_PRT_OFST, PHY_PHYIDR2, ®);
reg &= 0xfff0;
if (reg == 0x1610)
printf("88E6161");
if (reg == 0x1650)
printf("88E6165");
if (reg == 0x1210)
printf("88E6123");
by detecting the switch model you will capable to identify the numbers of ports and their capability Prafulla: sure, but which port to be used will be again question to be asked to board header
printf(" Initialized on %s\n", name);
return 0;
+}
Best Regards, J.

Dear Jean
I have updated this driver with platform specific abstraction support, That satisfy most of your review feedback, also taken care of your other review comments I am sending patch v4 for the same
Regards.. Prafulla . .

Hi Prafulla,
We have a custom designed board with the M88E6185 and M88E6131 switch. The u-boot patches are very usefull, even though I already finished some code to initialize the switches.
In our application it's more easy to "fully" provision the switches when the linux kernel is up and running. So I wonder: Is "M88E61XX switch driver support" planned for the linux kernel ? In other words: is there any chance similar patches will be released for the linux kernel any time soon ?
--- N. van Bolhuis.

From: prafulla_wadaskar prafulla@marvell.com
This is Marvell's 88F6281_A0 based custom board developed for wireless access point product
This patch is tested for- 1. Boot from DRAM/SPI flash/NFS 2. File transfer using tftp and loadb 3. SPI flash read/write/erase 4. Booting Linux kernel and RFS from SPI flash
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com Tested by: Piyush Shah spiyush@marvell.com --- MAKEALL | 1 + Makefile | 3 + board/Marvell/mv88f6281gtw_ge/Makefile | 54 +++++++ board/Marvell/mv88f6281gtw_ge/bin_dep.sh | 74 +++++++++ board/Marvell/mv88f6281gtw_ge/config.mk | 25 +++ board/Marvell/mv88f6281gtw_ge/dramregs_333h.txt | 27 ++++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c | 135 ++++++++++++++++ board/Marvell/mv88f6281gtw_ge/u-boot.lds | 53 +++++++ include/configs/mv88f6281gtw_ge.h | 187 +++++++++++++++++++++++ 9 files changed, 559 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/mv88f6281gtw_ge/Makefile create mode 100755 board/Marvell/mv88f6281gtw_ge/bin_dep.sh create mode 100644 board/Marvell/mv88f6281gtw_ge/config.mk create mode 100644 board/Marvell/mv88f6281gtw_ge/dramregs_333h.txt create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c create mode 100644 board/Marvell/mv88f6281gtw_ge/u-boot.lds create mode 100644 include/configs/mv88f6281gtw_ge.h
diff --git a/MAKEALL b/MAKEALL index 854f303..de25165 100755 --- a/MAKEALL +++ b/MAKEALL @@ -506,6 +506,7 @@ LIST_ARM9=" \ lpd7a400 \ mx1ads \ mx1fs2 \ + mv88f6281gtw_ge \ netstar \ nmdk8815 \ omap1510inn \ diff --git a/Makefile b/Makefile index 8bf36ce..eb2fdfb 100644 --- a/Makefile +++ b/Makefile @@ -2564,6 +2564,9 @@ DB64360_config: unconfig DB64460_config: unconfig @$(MKCONFIG) DB64460 ppc 74xx_7xx db64460 Marvell
+mv88f6281gtw_ge_config: unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs $(@:_config=) Marvell kirkwood + ELPPC_config: unconfig @$(MKCONFIG) $(@:_config=) ppc 74xx_7xx elppc eltec
diff --git a/board/Marvell/mv88f6281gtw_ge/Makefile b/board/Marvell/mv88f6281gtw_ge/Makefile new file mode 100644 index 0000000..32acefc --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/Makefile @@ -0,0 +1,54 @@ +# +# (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$(BOARD).a + +COBJS := mv88f6281gtw_ge.o +COBJS += ../common/mv88e61xx.o + +SOBJS := ../common/kw_lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/Marvell/mv88f6281gtw_ge/bin_dep.sh b/board/Marvell/mv88f6281gtw_ge/bin_dep.sh new file mode 100755 index 0000000..5cb1e36 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/bin_dep.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# (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 +# + +# This script generates a binary to flash on NAND to achieve +# boot from NAND operation using doimage kirkwood SOC utility +# input file :u-boot.bin +# output file :u-boot-nand.bin + +CUR_DIR=$2 +TOP_DIR=`pwd` +BIN_FILE=$TOP_DIR/$1 + +DOIMAGE=$TOP_DIR/cpu/arm926ejs/kirkwood/doimage/doimage +#TEXT_BASE=`cat $CUR_DIR/config.mk | grep TEXT_BASE` +TEXT_BASE=`cat $CUR_DIR/config.mk | grep TEXT_BASE | sed 's/TEXT_BASE = //g'` +FLASH_BOOT="-T flash -D $TEXT_BASE -E $TEXT_BASE " +BOOT_FILE=$TOP_DIR/u-boot-spiflash.bin +DRAM_FILE=dramregs_333h.txt + +if [ "clean" == "$1" ]; then + # erase created binary if any + rm -f $BOOT_FILE + exit 0 +fi + + +if [ ! -f $BIN_FILE ]; then + echo Error.. could not find $BIN_FILE + exit 1 +fi + +if [ ! -f $DOIMAGE ]; then + echo Error.. could not find $DOIMAGE utility + exit 1 +else + cd $CUR_DIR + # erase previously created binary if any + rm -f $BOOT_FILE + + #generte boot file using doimage + echo $TEXT_BASE + echo "$DOIMAGE $FLASH_BOOT -R $DRAM_FILE $BIN_FILE $BOOT_FILE" + $DOIMAGE $FLASH_BOOT -R $DRAM_FILE $BIN_FILE $BOOT_FILE + + if [ -f $BOOT_FILE ]; then + echo + echo use $BOOT_FILE to program spi-flash at offset 0x0 + echo + fi + cd $TOP_DIR +fi +exit 0 diff --git a/board/Marvell/mv88f6281gtw_ge/config.mk b/board/Marvell/mv88f6281gtw_ge/config.mk new file mode 100644 index 0000000..fb29a1b --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/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 +# + +TEXT_BASE = 0x00600000 diff --git a/board/Marvell/mv88f6281gtw_ge/dramregs_333h.txt b/board/Marvell/mv88f6281gtw_ge/dramregs_333h.txt new file mode 100644 index 0000000..d40a9c7 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/dramregs_333h.txt @@ -0,0 +1,27 @@ +0xFFD01400 0x43000a00 +0xFFD01404 0x38543000 +0xFFD01408 0x2202433D +0xFFD0140C 0x0000002A +0xFFD01410 0x0000000D +0xFFD01414 0x00000000 +0xFFD01418 0x00000000 +0xFFD0141C 0x00000c52 +0xFFD01420 0x00000046 +0xFFD01424 0x0000F1FF +0xFFD01428 0x00085520 +0xFFD0147c 0x00008552 +0xFFD01508 0x00000000 +0xFFD01504 0x07FFFFF1 +0xFFD0150C 0x00000000 +0xFFD01514 0x00000000 +0xFFD0151C 0x00000000 +0xFFD01494 0x00010001 +0xFFD01498 0x00000000 +0xFFD0149C 0x0000E811 +0xFFD01480 0x00000001 +0xFFD20204 0x00000000 +0xFFD100E0 0x1B1B1B9B +0xFFD100D8 0x00000060 +0xFFD1007C 0x00000068 +0xFFD50430 0x00000008 +0x0 0x0 diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c new file mode 100644 index 0000000..b88fe3e --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c @@ -0,0 +1,135 @@ +/* + * (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 MV88F6281GTW_GE_DEBUG +#define MV88F6281GTW_GE_DEBUG 0 +#endif +#define DEBUG_PRINT MV88F6281GTW_GE_DEBUG + +#include <common.h> +#include <debug_prints.h> + +/* this line must be removed after this machine name gets mainlined in mach_types.h*/ +#define MACH_TYPE_MV88F6281GTW_GE 1932 + +DECLARE_GLOBAL_DATA_PTR; + +#define MV88F6281GTW_GE_OE_VAL_LOW (BIT20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH ((BIT6)|(BIT13)|(BIT16)|(BIT17)) +#define MV88F6281GTW_GE_OE_LOW (~((BIT7) | (BIT20) | (BIT21))) /*enable GLED,RLED */ +#define MV88F6281GTW_GE_OE_HIGH (~((BIT4)|(BIT6)|(BIT7)|(BIT12)|(BIT13)|(BIT16)|(BIT17))) + +/* + * Default values for MPP registers + */ +#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000 + +/* + * function definitations + */ +#ifdef CONFIG_SWITCH_88E61XX +extern int mv_switch_88e61xx_init(u32 eth_port_num); +#endif + +int board_init(void) +{ + unsigned int i; + + debug_print_ftrace(); + /* Board Parameters initializations */ + kw_window_ctrl_reg_init(); + kw_gpio_init(MV88F6281GTW_GE_OE_VAL_LOW, + MV88F6281GTW_GE_OE_VAL_HIGH, + MV88F6281GTW_GE_OE_LOW, + MV88F6281GTW_GE_OE_HIGH); + + kw_mpp_control_init(MV88F6281GTW_GE_MPP0_7, + MV88F6281GTW_GE_MPP8_15, + MV88F6281GTW_GE_MPP16_23, + MV88F6281GTW_GE_MPP24_31, + MV88F6281GTW_GE_MPP32_39, + MV88F6281GTW_GE_MPP40_47, + MV88F6281GTW_GE_MPP48_55); + + /* init serial */ + gd->baudrate = CONFIG_BAUDRATE; + gd->have_console = 1; + serial_init(); + /* + * arch number of USED SOC + */ + gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + /* relocate the exception vectors */ + /* U-Boot is running from DRAM at this stage */ + for (i = 0; i < 0x100; i += 4) { + *(unsigned int *)(0x0 + i) = *(unsigned int *)(TEXT_BASE + i); + } + return 0; +} + +int dram_init(void) +{ + int i; + + debug_print_ftrace(); + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = kw_get_dram_bank_base_addr(i); + gd->bd->bi_dram[i].size = kw_get_dram_bank_size(i); + } + return 0; +} + +int last_stage_init(void) +{ + debug_print_ftrace(); + return 0; +} + +#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent init */ +int misc_init_r(void) +{ + debug_print_ftrace(); + return kw_misc_init_r(); +} + +void reset_phy(void) +{ + debug_print_ftrace(); +#ifdef CONFIG_SWITCH_88E61XX + mv_switch_88e61xx_init(ETH_0); +#endif +} + +#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds new file mode 100644 index 0000000..0338757 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } + _end = .; +} + diff --git a/include/configs/mv88f6281gtw_ge.h b/include/configs/mv88f6281gtw_ge.h new file mode 100644 index 0000000..70e6dca --- /dev/null +++ b/include/configs/mv88f6281gtw_ge.h @@ -0,0 +1,187 @@ +/* + * (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 _CONFIG_MV88F6281GTW_GE_H +#define _CONFIG_MV88F6281GTW_GE_H + +/* + * Version number information + */ +#define CONFIG_IDENT_STRING "\nMarvell-MV88F6281GTW_GE-A0" + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* Basic Architecture */ +#define CONFIG_FEROCEON_88FR131 1 /* CPU Core subversion */ +#define LE 1 /* Specify LE/BE operation */ +#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */ +#define CONFIG_KW88F6281_A0 1 /* SOC Revision */ +#define CONFIG_MV88F6281GTW_GE_A0 1 /* Board Name */ + +#ifdef CONFIG_KIRKWOOD +#define CONFIG_MD5 /* get_random_hex on krikwood needs MD5 support */ +#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */ +#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE Port0 for kernel */ +#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to 1.8V */ +#endif + +/* + * Above definitions used in below file, do not change the sequence + */ +#include <configs/kirkwood.h> /* CPU specific information */ + +/* + * CLKs configurations + */ +#define CONFIG_SYS_HZ 1000 +#define CONFIG_SYS_TCLK 200000000 + +/* + * Serial Port configuration + * The following definitions let you select what serial you want to use + * for your console driver. + */ +#define CONFIG_KW_SERIAL +#define CONFIG_CONS_INDEX 0 /*Console on UART0 */ + +#define CONFIG_BAUDRATE 115200 /* console baudrate */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200,\ + 230400, 460800, 921600 } +/* auto boot */ +#define CONFIG_BOOTDELAY 3 /* default enable autoboot */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CONFIG_BOOTMAPSZ (8<<20) /* Initial Memmap for Linux */ +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS 1 /* enable memory tag */ + +#define CONFIG_SYS_PROMPT "Marvell>> " /* Command Prompt */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ + +sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buff */ +/* + * Commands configuration + */ +#define CONFIG_CMD_ENV +#define CONFIG_CMD_RUN +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_NET +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_AUTOSCRIPT +#define CONFIG_CMD_MEMORY +#define CONFIG_CMD_BOOTD +#define CONFIG_CMD_SAVEENV +#define CONFIG_CMD_SF + +/* + * Flash configuration + */ +#ifdef CONFIG_CMD_SF +#define CONFIG_SYS_NO_FLASH 1 /* Declare no NOR flash */ +#define CONFIG_SPI_FLASH 1 +#define CONFIG_HARD_SPI 1 +#define CONFIG_KIRKWOOD_SPI 1 +#define CONFIG_SPI_FLASH_MACRONIX 1 +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 +#define CONFIG_ENV_SPI_MAX_HZ 50000000 /*50Mhz */ +#endif + +/* + * Environment variables configurations + */ +#ifdef CONFIG_SPI_FLASH +#define CONFIG_ENV_IS_IN_SPI_FLASH 1 +#define CONFIG_ENV_SIZE _64K /* 1 spi flash block */ +#define CONFIG_ENV_SECT_SIZE _64K +#else +#define CONFIG_ENV_IS_NOWHERE 1 /* if env in SDRAM */ +#define CONFIG_ENV_SIZE _128K /* default 128k */ +#endif +#define CONFIG_ENV_ADDR _128K +#define CONFIG_ENV_OFFSET _128K /* env starts here + (can be relocated) */ +/* Default environment variables */ +#define CONFIG_BOOTCOMMAND "$(x_bootcmd_kernel); setenv bootargs $(x_bootargs) $(x_bootargs_root); bootm 0x6400000; " +#define CONFIG_EXTRA_ENV_SETTINGS \ + "x_bootargs=console=ttyS0,115200 mtdparts=spi0.0:512k(uboot),512k@512k(psm),2m@1m(kernel),13m@3m(rootfs)\0" \ + "x_bootcmd_kernel=cp.b 0xf8100000 0x6400000 0x200000\0" \ + "x_bootargs_root=root=/dev/mtdblock3 ro rootfstype=squashfs\0" + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN _4M +#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ + +/* + * Other required minimal configurations + */ +#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() */ +#define CONFIG_NR_DRAM_BANKS 4 +#define CONFIG_STACKSIZE _1M /* regular stack - up to 4M + (in case of exception) */ +#define CONFIG_SYS_LOAD_ADDR _8M /* default load address */ +#define CONFIG_SYS_MEMTEST_START _4M +#define CONFIG_SYS_MEMTEST_END (_8M -1) +#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Reset Vector Address */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ + +/* + * Ethernet Driver configuration + */ +#ifdef CONFIG_CMD_NET +#define CONFIG_NETCONSOLE /* include NetConsole support */ +#define CONFIG_NET_MULTI /* specify more that one ports available */ +#define CONFIG_KIRKWOOD_EGIGA /* Enable SOC specific Ethernet Gigabit + Controller Driver */ +#undef CONFIG_PHY_LINK_DETECT /* detect link always on */ + /*specify ports to be used */ +#define CONFIG_KIRKWOOD_EGIGA_PORTS {TRUE,FALSE} + /* phy base addr for multi-chip addressing */ +#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ +#endif /* CONFIG_CMD_NET */ + +/* + * Marvell 88Exxxx Switch configurations + */ +#define CONFIG_RESET_PHY_R 1 /* use reset_phy() to init phy/swtich */ +#define CONFIG_SWITCH_88E61XX /* Enable mv88e61xx switch driver */ +#define CONFIG_SWITCH_MV88E6165 /* Used Switch is 88E6165 */ +#define CONFIG_SWITCH_88E61XX_CPU_PORT 5 /* p5 of 88E6165 connceted to CPU */ +#define CONFIG_SWITCH_88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \ + BIT3 | BIT4 | BIT5) +#endif /* _CONFIG_MV88F6281GTW_GE_H */

Dear Prafulla Wadaskar,
In message 1238798370-9245-5-git-send-email-prafulla@marvell.com you wrote:
From: prafulla_wadaskar prafulla@marvell.com
This is Marvell's 88F6281_A0 based custom board developed for wireless access point product
This patch is tested for-
- Boot from DRAM/SPI flash/NFS
- File transfer using tftp and loadb
- SPI flash read/write/erase
- Booting Linux kernel and RFS from SPI flash
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com Tested by: Piyush Shah spiyush@marvell.com
...
--- a/MAKEALL +++ b/MAKEALL @@ -506,6 +506,7 @@ LIST_ARM9=" \ lpd7a400 \ mx1ads \ mx1fs2 \
- mv88f6281gtw_ge \ netstar \ nmdk8815 \ omap1510inn \
Please keep lists sorted.
diff --git a/Makefile b/Makefile index 8bf36ce..eb2fdfb 100644 --- a/Makefile +++ b/Makefile @@ -2564,6 +2564,9 @@ DB64360_config: unconfig DB64460_config: unconfig @$(MKCONFIG) DB64460 ppc 74xx_7xx db64460 Marvell
+mv88f6281gtw_ge_config: unconfig
- @$(MKCONFIG) $(@:_config=) arm arm926ejs $(@:_config=) Marvell kirkwood
ELPPC_config: unconfig @$(MKCONFIG) $(@:_config=) ppc 74xx_7xx elppc eltec
Please keep lists sorted.
diff --git a/board/Marvell/mv88f6281gtw_ge/bin_dep.sh b/board/Marvell/mv88f6281gtw_ge/bin_dep.sh new file mode 100755 index 0000000..5cb1e36 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/bin_dep.sh @@ -0,0 +1,74 @@
...
+CUR_DIR=$2 +TOP_DIR=`pwd` +BIN_FILE=$TOP_DIR/$1
+DOIMAGE=$TOP_DIR/cpu/arm926ejs/kirkwood/doimage/doimage
Please explain why this would be needed for?
Note that this most probably will not fork with out of tree builds.
...
diff --git a/board/Marvell/mv88f6281gtw_ge/dramregs_333h.txt b/board/Marvell/mv88f6281gtw_ge/dramregs_333h.txt new file mode 100644 index 0000000..d40a9c7 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/dramregs_333h.txt @@ -0,0 +1,27 @@ +0xFFD01400 0x43000a00 +0xFFD01404 0x38543000 +0xFFD01408 0x2202433D +0xFFD0140C 0x0000002A +0xFFD01410 0x0000000D +0xFFD01414 0x00000000 +0xFFD01418 0x00000000 +0xFFD0141C 0x00000c52 +0xFFD01420 0x00000046 +0xFFD01424 0x0000F1FF +0xFFD01428 0x00085520 +0xFFD0147c 0x00008552 +0xFFD01508 0x00000000 +0xFFD01504 0x07FFFFF1 +0xFFD0150C 0x00000000 +0xFFD01514 0x00000000 +0xFFD0151C 0x00000000 +0xFFD01494 0x00010001 +0xFFD01498 0x00000000 +0xFFD0149C 0x0000E811 +0xFFD01480 0x00000001 +0xFFD20204 0x00000000 +0xFFD100E0 0x1B1B1B9B +0xFFD100D8 0x00000060 +0xFFD1007C 0x00000068 +0xFFD50430 0x00000008 +0x0 0x0
What sort of file is this? Under which license is it?
diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c new file mode 100644 index 0000000..b88fe3e --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c @@ -0,0 +1,135 @@
...
+#ifndef MV88F6281GTW_GE_DEBUG +#define MV88F6281GTW_GE_DEBUG 0 +#endif +#define DEBUG_PRINT MV88F6281GTW_GE_DEBUG
Unused code? Delete!
+#include <common.h> +#include <debug_prints.h>
Non existent file included here.
+/* this line must be removed after this machine name gets mainlined in mach_types.h*/ +#define MACH_TYPE_MV88F6281GTW_GE 1932
Please first register the MACH ID, then fix this, then resubmit.
+DECLARE_GLOBAL_DATA_PTR;
+#define MV88F6281GTW_GE_OE_VAL_LOW (BIT20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH ((BIT6)|(BIT13)|(BIT16)|(BIT17)) +#define MV88F6281GTW_GE_OE_LOW (~((BIT7) | (BIT20) | (BIT21))) /*enable GLED,RLED */ +#define MV88F6281GTW_GE_OE_HIGH (~((BIT4)|(BIT6)|(BIT7)|(BIT12)|(BIT13)|(BIT16)|(BIT17)))
Lines too long (also check in all other files).
+/*
- Default values for MPP registers
- */
+#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000
+/*
- function definitations
- */
+#ifdef CONFIG_SWITCH_88E61XX +extern int mv_switch_88e61xx_init(u32 eth_port_num); +#endif
Do not use extern. Privde proper prototypes in the respective header files.
+int board_init(void) +{
...
- /* relocate the exception vectors */
- /* U-Boot is running from DRAM at this stage */
- for (i = 0; i < 0x100; i += 4) {
*(unsigned int *)(0x0 + i) = *(unsigned int *)(TEXT_BASE + i);
- }
Are you absolutely sure this code is correct?
+int dram_init(void) +{
- int i;
- debug_print_ftrace();
You probably want to get rid of these. I don't think we will accept this.
diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds new file mode 100644 index 0000000..0338757 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds @@ -0,0 +1,53 @@ +/*
- (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
- */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{
- . = _start;
- . = ALIGN(4);
- .text :
- {
cpu/arm926ejs/start.o (.text)
*(.text)
- }
- .rodata : { *(.rodata) }
- . = ALIGN(4);
- .data : { *(.data) }
- . = ALIGN(4);
- .got : { *(.got) }
- . = .;
- __u_boot_cmd_start = .;
- .u_boot_cmd : { *(.u_boot_cmd) }
- __u_boot_cmd_end = .;
- . = ALIGN(4);
- __bss_start = .;
- .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
- _end = .;
+}
diff --git a/include/configs/mv88f6281gtw_ge.h b/include/configs/mv88f6281gtw_ge.h new file mode 100644 index 0000000..70e6dca --- /dev/null +++ b/include/configs/mv88f6281gtw_ge.h
...
+/*
- Above definitions used in below file, do not change the sequence
- */
+#include <configs/kirkwood.h> /* CPU specific information */
include/configs/ is strictly for board specific information only; CPU specific data has no place there.
...
+#define CONFIG_BOOTMAPSZ (8<<20) /* Initial Memmap for Linux */ +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS 1 /* enable memory tag */
+#define CONFIG_SYS_PROMPT "Marvell>> " /* Command Prompt */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \
+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buff */
Lines too long, here and elsewhere. Please fix globally.
- Commands configuration
- */
+#define CONFIG_CMD_ENV +#define CONFIG_CMD_RUN +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_NET +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_AUTOSCRIPT
AUTOSCRIPT is deprecated. Please use SOURCE instead.
+#ifdef CONFIG_SPI_FLASH +#define CONFIG_ENV_IS_IN_SPI_FLASH 1 +#define CONFIG_ENV_SIZE _64K /* 1 spi flash block */ +#define CONFIG_ENV_SECT_SIZE _64K
Please use real numbers and get rid of such "cool" constants.
+/* Default environment variables */ +#define CONFIG_BOOTCOMMAND "$(x_bootcmd_kernel); setenv bootargs $(x_bootargs) $(x_bootargs_root); bootm 0x6400000; " +#define CONFIG_EXTRA_ENV_SETTINGS \
- "x_bootargs=console=ttyS0,115200 mtdparts=spi0.0:512k(uboot),512k@512k(psm),2m@1m(kernel),13m@3m(rootfs)\0" \
Lines WAY too long.
Best regards,
Wolfgang Denk

From: prafulla_wadaskar prafulla@marvell.com
This is Marvell's 88F6281_A0 based custom board developed for wireless access point product
This patch is tested for- 1. Boot from DRAM/SPI flash/NFS 2. File transfer using tftp and loadb 3. SPI flash read/write/erase 4. Booting Linux kernel and RFS from SPI flash Note: doImage utility needed to convert u-boot.bin to u-boot-spiflash.bin, DRAM configuration will be part of this utility
Reviewed-by: Ronen Shitrit rshitrit@marvell.com Signed-off-by: Prafulla Wadaskar prafulla@marvell.com --- Changelog v2: updated as per first review comments by Wolfgang Denk debug_prints updated to debug
MAKEALL | 1 + Makefile | 3 + board/Marvell/mv88f6281gtw_ge/Makefile | 52 +++++++ board/Marvell/mv88f6281gtw_ge/config.mk | 25 +++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c | 118 ++++++++++++++ board/Marvell/mv88f6281gtw_ge/u-boot.lds | 53 +++++++ include/configs/mv88f6281gtw_ge.h | 185 +++++++++++++++++++++++ 7 files changed, 437 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/mv88f6281gtw_ge/Makefile create mode 100644 board/Marvell/mv88f6281gtw_ge/config.mk create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c create mode 100644 board/Marvell/mv88f6281gtw_ge/u-boot.lds create mode 100644 include/configs/mv88f6281gtw_ge.h
diff --git a/MAKEALL b/MAKEALL index e4eb42b..1caf81d 100755 --- a/MAKEALL +++ b/MAKEALL @@ -504,6 +504,7 @@ LIST_ARM9=" \ cp946es \ cp966 \ lpd7a400 \ + mv88f6281gtw_ge \ mx1ads \ mx1fs2 \ netstar \ diff --git a/Makefile b/Makefile index d2c7c3f..709e4be 100644 --- a/Makefile +++ b/Makefile @@ -2792,6 +2792,9 @@ lpd7a400_config \ lpd7a404_config: unconfig @$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x
+mv88f6281gtw_ge_config: unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs $(@:_config=) Marvell kirkwood + mx1ads_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t mx1ads NULL imx
diff --git a/board/Marvell/mv88f6281gtw_ge/Makefile b/board/Marvell/mv88f6281gtw_ge/Makefile new file mode 100644 index 0000000..1b8cc6f --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/Makefile @@ -0,0 +1,52 @@ +# +# (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$(BOARD).a + +COBJS := mv88f6281gtw_ge.o +COBJS += ../common/mv88e61xx.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/Marvell/mv88f6281gtw_ge/config.mk b/board/Marvell/mv88f6281gtw_ge/config.mk new file mode 100644 index 0000000..fb29a1b --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/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 +# + +TEXT_BASE = 0x00600000 diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c new file mode 100644 index 0000000..617c87a --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c @@ -0,0 +1,118 @@ +/* + * (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> + +DECLARE_GLOBAL_DATA_PTR; + +#define MV88F6281GTW_GE_OE_LOW (~((BIT7) | (BIT20) \ + |(BIT21))) /*enable GLED,RLED */ +#define MV88F6281GTW_GE_OE_HIGH (~((BIT4)|(BIT6)|(BIT7)|(BIT12) \ + |(BIT13)|(BIT16)|(BIT17))) +#define MV88F6281GTW_GE_OE_VAL_LOW (BIT20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH ((BIT6)|(BIT13)|(BIT16)|(BIT17)) + +/* + * Default values for MPP registers + */ +#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000 + +/* + * function definitations + */ +#ifdef CONFIG_SWITCH_88E61XX +extern int mv_switch_88e61xx_init(u32 eth_port_num); +#endif + +int board_init(void) +{ + unsigned int i; + + /* Board Parameters initializations */ + kw_window_ctrl_reg_init(); + kw_gpio_init(MV88F6281GTW_GE_OE_VAL_LOW, + MV88F6281GTW_GE_OE_VAL_HIGH, + MV88F6281GTW_GE_OE_LOW, + MV88F6281GTW_GE_OE_HIGH); + + kw_mpp_control_init(MV88F6281GTW_GE_MPP0_7, + MV88F6281GTW_GE_MPP8_15, + MV88F6281GTW_GE_MPP16_23, + MV88F6281GTW_GE_MPP24_31, + MV88F6281GTW_GE_MPP32_39, + MV88F6281GTW_GE_MPP40_47, + MV88F6281GTW_GE_MPP48_55); + + /* init serial */ + gd->baudrate = CONFIG_BAUDRATE; + gd->have_console = 1; + serial_init(); + /* + * arch number of USED SOC + */ + gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + return 0; +} + +int dram_init(void) +{ + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = kw_sdram_bar(i); + gd->bd->bi_dram[i].size = kw_sdram_bs(i); + } + return 0; +} + +int last_stage_init(void) +{ + return 0; +} + +#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent init */ +int misc_init_r(void) +{ + return kw_misc_init_r(); +} + +void reset_phy(void) +{ +#ifdef CONFIG_SWITCH_88E61XX + mv_switch_88e61xx_init(ETH_0); +#endif +} + +#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds new file mode 100644 index 0000000..0338757 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } + _end = .; +} + diff --git a/include/configs/mv88f6281gtw_ge.h b/include/configs/mv88f6281gtw_ge.h new file mode 100644 index 0000000..7f2b325 --- /dev/null +++ b/include/configs/mv88f6281gtw_ge.h @@ -0,0 +1,185 @@ +/* + * (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 _CONFIG_MV88F6281GTW_GE_H +#define _CONFIG_MV88F6281GTW_GE_H + +/* + * Version number information + */ +#define CONFIG_IDENT_STRING "\nMarvell-MV88F6281GTW_GE-A0" + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* Basic Architecture */ +#define CONFIG_FEROCEON_88FR131 1 /* CPU Core subversion */ +#define LE 1 /* Specify LE/BE operation */ +#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */ +#define CONFIG_KW88F6281_A0 1 /* SOC Revision */ +#define CONFIG_MV88F6281GTW_GE_A0 1 /* Board Name */ + +#ifdef CONFIG_KIRKWOOD +#define CONFIG_MD5 /* get_random_hex on krikwood needs MD5 support */ +#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */ +#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE Port0 for kernel */ +#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to 1.8V */ +#endif + +/* + * CLKs configurations + */ +#define CONFIG_SYS_HZ 1000 + +/* + * Serial Port configuration + * The following definitions let you select what serial you want to use + * for your console driver. + */ +#define CONFIG_KW_SERIAL +#define CONFIG_CONS_INDEX 0 /*Console on UART0 */ + +#define CONFIG_BAUDRATE 115200 /* console baudrate */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \ + 115200,230400, 460800, 921600 } +/* auto boot */ +#define CONFIG_BOOTDELAY 3 /* default enable autoboot */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CONFIG_BOOTMAPSZ (8<<20) /* Initial Memmap for Linux */ +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS 1 /* enable memory tag */ + +#define CONFIG_SYS_PROMPT "Marvell>> " /* Command Prompt */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ + +sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buff */ +/* + * Commands configuration + */ +#define CONFIG_CMD_ENV +#define CONFIG_CMD_RUN +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_NET +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_AUTOSCRIPT +#define CONFIG_CMD_MEMORY +#define CONFIG_CMD_BOOTD +#define CONFIG_CMD_SAVEENV +#define CONFIG_CMD_SF + +/* + * Flash configuration + */ +#ifdef CONFIG_CMD_SF +#define CONFIG_SYS_NO_FLASH 1 /* Declare no NOR flash */ +#define CONFIG_SPI_FLASH 1 +#define CONFIG_HARD_SPI 1 +#define CONFIG_KIRKWOOD_SPI 1 +#define CONFIG_SPI_FLASH_MACRONIX 1 +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 +#define CONFIG_ENV_SPI_MAX_HZ 50000000 /*50Mhz */ +#endif + +/* + * Environment variables configurations + */ +#ifdef CONFIG_SPI_FLASH +#define CONFIG_ENV_IS_IN_SPI_FLASH 1 +#define CONFIG_ENV_SIZE 0x10000 /* spi flash block (64k) */ +#define CONFIG_ENV_SECT_SIZE 0x10000 /* _64K */ +#else +#define CONFIG_ENV_IS_NOWHERE 1 /* if env in SDRAM */ +#define CONFIG_ENV_SIZE 0x20000 /* default 128k */ +#endif +#define CONFIG_ENV_ADDR 0x20000 +#define CONFIG_ENV_OFFSET 0x20000 /* env starts here */ + +/* + * Default environment variables + */ +#define CONFIG_BOOTCOMMAND "$(x_bootcmd_kernel); setenv bootargs " \ + "$(x_bootargs) $(x_bootargs_root); bootm 0x6400000;" +#define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console=ttyS0,115200 " \ + "mtdparts=spi0.0:512k(uboot),512k@512k(psm),2m@1m(kernel),13m@3m(rootfs)\0" \ + "x_bootcmd_kernel=cp.b 0xf8100000 0x6400000 0x200000\0" \ + "x_bootargs_root=root=/dev/mtdblock3 ro rootfstype=squashfs\0" + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */ +/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128 + +/* + * Other required minimal configurations + */ +#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() */ +#define CONFIG_NR_DRAM_BANKS 4 +#define CONFIG_STACKSIZE 0x00100000 /* regular stack- 1M */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */ +#define CONFIG_SYS_MEMTEST_START 0x00400000 /* 4M */ +#define CONFIG_SYS_MEMTEST_END 0x007fffff /*(_8M -1) */ +#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ + +/* + * Ethernet Driver configuration + */ +#ifdef CONFIG_CMD_NET +#define CONFIG_NETCONSOLE /* include NetConsole support */ +#define CONFIG_NET_MULTI /* specify more that one ports available */ +#define CONFIG_KIRKWOOD_EGIGA /* Enable SOC specific Ethernet Gigabit + Controller Driver */ +#undef CONFIG_PHY_LINK_DETECT /* detect link always on */ + /* specify ports to be used */ +#define CONFIG_KIRKWOOD_EGIGA_PORTS {TRUE,FALSE} + /* phy base addr for multi-chip addressing */ +#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ +#endif /* CONFIG_CMD_NET */ + +/* + * Marvell 88Exxxx Switch configurations + */ +#define CONFIG_RESET_PHY_R /* use reset_phy() to init phy/swtich */ +#define CONFIG_SWITCH_88E61XX /* Enable mv88e61xx switch driver */ +#define CONFIG_SWITCH_MV88E6165 /* Used Switch is 88E6165 */ + /* p5 of 88E6165 connceted to CPU */ +#define CONFIG_SWITCH_88E61XX_CPU_PORT 5 +#define CONFIG_SWITCH_88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \ + BIT3 | BIT4 | BIT5) +#endif /* _CONFIG_MV88F6281GTW_GE_H */

On Wednesday 08 April 2009 12:18:11 Prafulla Wadaskar wrote:
From: prafulla_wadaskar prafulla@marvell.com
this part should be fixed as well -mike

Hi all,
This is much cleaner and smaller patch. Any comments or acceptance or flag to resend are welcomed.
Regards.. Prafulla . .
-----Original Message----- From: Prafulla Wadaskar [mailto:prafulla@marvell.com] Sent: Wednesday, April 08, 2009 9:48 PM To: u-boot@lists.denx.de Cc: Ronen Shitrit; Ashish Karkare; Prafulla Wadaskar Subject: [PATCH v2] Marvell MV88F6281GTW_GE Board support
From: prafulla_wadaskar prafulla@marvell.com
This is Marvell's 88F6281_A0 based custom board developed for wireless access point product
This patch is tested for-
- Boot from DRAM/SPI flash/NFS
- File transfer using tftp and loadb
- SPI flash read/write/erase
- Booting Linux kernel and RFS from SPI flash
Note: doImage utility needed to convert u-boot.bin to u-boot-spiflash.bin, DRAM configuration will be part of this utility
Reviewed-by: Ronen Shitrit rshitrit@marvell.com Signed-off-by: Prafulla Wadaskar prafulla@marvell.com
Changelog v2: updated as per first review comments by Wolfgang Denk debug_prints updated to debug
MAKEALL | 1 + Makefile | 3 + board/Marvell/mv88f6281gtw_ge/Makefile | 52 +++++++ board/Marvell/mv88f6281gtw_ge/config.mk | 25 +++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c | 118 ++++++++++++++ board/Marvell/mv88f6281gtw_ge/u-boot.lds | 53 +++++++ include/configs/mv88f6281gtw_ge.h | 185 +++++++++++++++++++++++ 7 files changed, 437 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/mv88f6281gtw_ge/Makefile create mode 100644 board/Marvell/mv88f6281gtw_ge/config.mk create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c create mode 100644 board/Marvell/mv88f6281gtw_ge/u-boot.lds create mode 100644 include/configs/mv88f6281gtw_ge.h
diff --git a/MAKEALL b/MAKEALL index e4eb42b..1caf81d 100755 --- a/MAKEALL +++ b/MAKEALL @@ -504,6 +504,7 @@ LIST_ARM9=" \ cp946es \ cp966 \ lpd7a400 \
mv88f6281gtw_ge \ mx1ads \ mx1fs2 \ netstar \
diff --git a/Makefile b/Makefile index d2c7c3f..709e4be 100644 --- a/Makefile +++ b/Makefile @@ -2792,6 +2792,9 @@ lpd7a400_config \ lpd7a404_config: unconfig @$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x
+mv88f6281gtw_ge_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm926ejs $(@:_config=)
Marvell kirkwood
mx1ads_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t mx1ads NULL imx
diff --git a/board/Marvell/mv88f6281gtw_ge/Makefile b/board/Marvell/mv88f6281gtw_ge/Makefile new file mode 100644 index 0000000..1b8cc6f --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/Makefile @@ -0,0 +1,52 @@ +# +# (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$(BOARD).a
+COBJS := mv88f6281gtw_ge.o +COBJS += ../common/mv88e61xx.o
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS))
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+clean:
rm -f $(SOBJS) $(OBJS)
+distclean: clean
rm -f $(LIB) core *.bak .depend
+############################################################# ############
+# defines $(obj).depend target +include $(SRCTREE)/rules.mk
+sinclude $(obj).depend
+############################################################# ############ diff --git a/board/Marvell/mv88f6281gtw_ge/config.mk b/board/Marvell/mv88f6281gtw_ge/config.mk new file mode 100644 index 0000000..fb29a1b --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/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 +#
+TEXT_BASE = 0x00600000 diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c new file mode 100644 index 0000000..617c87a --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c @@ -0,0 +1,118 @@ +/*
- (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>
+DECLARE_GLOBAL_DATA_PTR;
+#define MV88F6281GTW_GE_OE_LOW (~((BIT7) | (BIT20) \
|(BIT21))) /*enable
GLED,RLED */ +#define MV88F6281GTW_GE_OE_HIGH (~((BIT4)|(BIT6)|(BIT7)|(BIT12) \
|(BIT13)|(BIT16)|(BIT17)))
+#define MV88F6281GTW_GE_OE_VAL_LOW (BIT20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH ((BIT6)|(BIT13)|(BIT16)|(BIT17))
+/*
- Default values for MPP registers
- */
+#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000
+/*
- function definitations
- */
+#ifdef CONFIG_SWITCH_88E61XX +extern int mv_switch_88e61xx_init(u32 eth_port_num); +#endif
+int board_init(void) +{
unsigned int i;
/* Board Parameters initializations */
kw_window_ctrl_reg_init();
kw_gpio_init(MV88F6281GTW_GE_OE_VAL_LOW,
MV88F6281GTW_GE_OE_VAL_HIGH,
MV88F6281GTW_GE_OE_LOW,
MV88F6281GTW_GE_OE_HIGH);
kw_mpp_control_init(MV88F6281GTW_GE_MPP0_7,
MV88F6281GTW_GE_MPP8_15,
MV88F6281GTW_GE_MPP16_23,
MV88F6281GTW_GE_MPP24_31,
MV88F6281GTW_GE_MPP32_39,
MV88F6281GTW_GE_MPP40_47,
MV88F6281GTW_GE_MPP48_55);
/* init serial */
gd->baudrate = CONFIG_BAUDRATE;
gd->have_console = 1;
serial_init();
/*
* arch number of USED SOC
*/
gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x00000100;
return 0;
+}
+int dram_init(void) +{
int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
gd->bd->bi_dram[i].start = kw_sdram_bar(i);
gd->bd->bi_dram[i].size = kw_sdram_bs(i);
}
return 0;
+}
+int last_stage_init(void) +{
return 0;
+}
+#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent init */ +int misc_init_r(void) +{
return kw_misc_init_r();
+}
+void reset_phy(void) +{ +#ifdef CONFIG_SWITCH_88E61XX
mv_switch_88e61xx_init(ETH_0);
+#endif +}
+#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds new file mode 100644 index 0000000..0338757 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds @@ -0,0 +1,53 @@ +/*
- (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
- */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{
. = _start;
. = ALIGN(4);
.text :
{
cpu/arm926ejs/start.o (.text)
*(.text)
}
.rodata : { *(.rodata) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
_end = .;
+}
diff --git a/include/configs/mv88f6281gtw_ge.h b/include/configs/mv88f6281gtw_ge.h new file mode 100644 index 0000000..7f2b325 --- /dev/null +++ b/include/configs/mv88f6281gtw_ge.h @@ -0,0 +1,185 @@ +/*
- (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 _CONFIG_MV88F6281GTW_GE_H +#define _CONFIG_MV88F6281GTW_GE_H
+/*
- Version number information
- */
+#define CONFIG_IDENT_STRING "\nMarvell-MV88F6281GTW_GE-A0"
+/*
- High Level Configuration Options (easy to change)
- */
+#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* Basic Architecture */ +#define CONFIG_FEROCEON_88FR131 1 /* CPU Core subversion */ +#define LE 1 /* Specify LE/BE operation */ +#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */ +#define CONFIG_KW88F6281_A0 1 /* SOC Revision */ +#define CONFIG_MV88F6281GTW_GE_A0 1 /* Board Name */
+#ifdef CONFIG_KIRKWOOD +#define CONFIG_MD5 /* get_random_hex on krikwood needs MD5 support */ +#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */ +#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE Port0 for kernel */ +#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to 1.8V */ +#endif
+/*
- CLKs configurations
- */
+#define CONFIG_SYS_HZ 1000
+/*
- Serial Port configuration
- The following definitions let you select what serial you
want to use
- for your console driver.
- */
+#define CONFIG_KW_SERIAL +#define CONFIG_CONS_INDEX 0 /*Console on UART0 */
+#define CONFIG_BAUDRATE 115200 /* console baudrate */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \
115200,230400,
460800, 921600 } +/* auto boot */ +#define CONFIG_BOOTDELAY 3 /* default enable autoboot */
+/*
- For booting Linux, the board info and command line data
- have to be in the first 8 MB of memory, since this is
- the maximum mapped by the Linux kernel during initialization.
- */
+#define CONFIG_BOOTMAPSZ (8<<20) /* Initial Memmap for Linux */ +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS 1 /* enable memory tag */
+#define CONFIG_SYS_PROMPT "Marvell>> " /* Command Prompt */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \
+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buff */
+/*
- Commands configuration
- */
+#define CONFIG_CMD_ENV +#define CONFIG_CMD_RUN +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_NET +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_AUTOSCRIPT +#define CONFIG_CMD_MEMORY +#define CONFIG_CMD_BOOTD +#define CONFIG_CMD_SAVEENV +#define CONFIG_CMD_SF
+/*
- Flash configuration
- */
+#ifdef CONFIG_CMD_SF +#define CONFIG_SYS_NO_FLASH 1 /* Declare no NOR flash */ +#define CONFIG_SPI_FLASH 1 +#define CONFIG_HARD_SPI 1 +#define CONFIG_KIRKWOOD_SPI 1 +#define CONFIG_SPI_FLASH_MACRONIX 1 +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 +#define CONFIG_ENV_SPI_MAX_HZ 50000000 /*50Mhz */ +#endif
+/*
- Environment variables configurations
- */
+#ifdef CONFIG_SPI_FLASH +#define CONFIG_ENV_IS_IN_SPI_FLASH 1 +#define CONFIG_ENV_SIZE 0x10000 /* spi flash block (64k) */ +#define CONFIG_ENV_SECT_SIZE 0x10000 /* _64K */ +#else +#define CONFIG_ENV_IS_NOWHERE 1 /* if env in SDRAM */ +#define CONFIG_ENV_SIZE 0x20000 /* default 128k */ +#endif +#define CONFIG_ENV_ADDR 0x20000 +#define CONFIG_ENV_OFFSET 0x20000 /* env starts here */
+/*
- Default environment variables
- */
+#define CONFIG_BOOTCOMMAND "$(x_bootcmd_kernel); setenv bootargs " \
"$(x_bootargs) $(x_bootargs_root); bootm 0x6400000;"
+#define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console=ttyS0,115200 " \
"mtdparts=spi0.0:512k(uboot),512k@512k(psm),2m@1m(kernel),13m@ 3m(rootfs)\0" \
"x_bootcmd_kernel=cp.b 0xf8100000 0x6400000 0x200000\0" \
"x_bootargs_root=root=/dev/mtdblock3 ro rootfstype=squashfs\0"
+/*
- Size of malloc() pool
- */
+#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */ +/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128
+/*
- Other required minimal configurations
- */
+#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() */ +#define CONFIG_NR_DRAM_BANKS 4 +#define CONFIG_STACKSIZE 0x00100000 /* regular stack- 1M */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */ +#define CONFIG_SYS_MEMTEST_START 0x00400000 /* 4M */ +#define CONFIG_SYS_MEMTEST_END 0x007fffff /*(_8M -1) */ +#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
+/*
- Ethernet Driver configuration
- */
+#ifdef CONFIG_CMD_NET +#define CONFIG_NETCONSOLE /* include NetConsole support */ +#define CONFIG_NET_MULTI /* specify more that one ports available */ +#define CONFIG_KIRKWOOD_EGIGA /* Enable SOC specific Ethernet Gigabit
Controller Driver */
+#undef CONFIG_PHY_LINK_DETECT /* detect link always on */
/* specify ports to be used */
+#define CONFIG_KIRKWOOD_EGIGA_PORTS {TRUE,FALSE}
/* phy base addr for multi-chip
addressing */ +#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ +#endif /* CONFIG_CMD_NET */
+/*
- Marvell 88Exxxx Switch configurations
- */
+#define CONFIG_RESET_PHY_R /* use reset_phy() to init phy/swtich */ +#define CONFIG_SWITCH_88E61XX /* Enable mv88e61xx switch driver */ +#define CONFIG_SWITCH_MV88E6165 /* Used Switch is 88E6165 */
/* p5 of 88E6165 connceted to CPU */
+#define CONFIG_SWITCH_88E61XX_CPU_PORT 5 +#define CONFIG_SWITCH_88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
BIT3 | BIT4 | BIT5)
+#endif /* _CONFIG_MV88F6281GTW_GE_H */
1.5.3.3

On 21:48 Wed 08 Apr , Prafulla Wadaskar wrote:
From: prafulla_wadaskar prafulla@marvell.com
This is Marvell's 88F6281_A0 based custom board developed for wireless access point product
This patch is tested for-
- Boot from DRAM/SPI flash/NFS
- File transfer using tftp and loadb
- SPI flash read/write/erase
- Booting Linux kernel and RFS from SPI flash
Note: doImage utility needed to convert u-boot.bin to u-boot-spiflash.bin, DRAM configuration will be part of this utility
btw where is the spi driver?
Reviewed-by: Ronen Shitrit rshitrit@marvell.com Signed-off-by: Prafulla Wadaskar prafulla@marvell.com
Changelog v2: updated as per first review comments by Wolfgang Denk debug_prints updated to debug
MAKEALL | 1 + Makefile | 3 + board/Marvell/mv88f6281gtw_ge/Makefile | 52 +++++++ board/Marvell/mv88f6281gtw_ge/config.mk | 25 +++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c | 118 ++++++++++++++ board/Marvell/mv88f6281gtw_ge/u-boot.lds | 53 +++++++ include/configs/mv88f6281gtw_ge.h | 185 +++++++++++++++++++++++ 7 files changed, 437 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/mv88f6281gtw_ge/Makefile create mode 100644 board/Marvell/mv88f6281gtw_ge/config.mk create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c create mode 100644 board/Marvell/mv88f6281gtw_ge/u-boot.lds create mode 100644 include/configs/mv88f6281gtw_ge.h
diff --git a/MAKEALL b/MAKEALL index e4eb42b..1caf81d 100755 --- a/MAKEALL +++ b/MAKEALL @@ -504,6 +504,7 @@ LIST_ARM9=" \ cp946es \ cp966 \ lpd7a400 \
- mv88f6281gtw_ge \ mx1ads \ mx1fs2 \ netstar \
diff --git a/Makefile b/Makefile index d2c7c3f..709e4be 100644 --- a/Makefile
- 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>
+DECLARE_GLOBAL_DATA_PTR;
+#define MV88F6281GTW_GE_OE_LOW (~((BIT7) | (BIT20) \
|(BIT21))) /*enable GLED,RLED */
+#define MV88F6281GTW_GE_OE_HIGH (~((BIT4)|(BIT6)|(BIT7)|(BIT12) \
|(BIT13)|(BIT16)|(BIT17)))
+#define MV88F6281GTW_GE_OE_VAL_LOW (BIT20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH ((BIT6)|(BIT13)|(BIT16)|(BIT17))
plese remove the BITxx
+/*
- Default values for MPP registers
- */
+#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000
please move all this define to a header and if possible please use macro to describe the content
+/*
- function definitations
- */
+#ifdef CONFIG_SWITCH_88E61XX +extern int mv_switch_88e61xx_init(u32 eth_port_num); +#endif
please move it to a header
+int board_init(void) +{
- unsigned int i;
- /* Board Parameters initializations */
- kw_window_ctrl_reg_init();
- kw_gpio_init(MV88F6281GTW_GE_OE_VAL_LOW,
MV88F6281GTW_GE_OE_VAL_HIGH,
MV88F6281GTW_GE_OE_LOW,
MV88F6281GTW_GE_OE_HIGH);
- kw_mpp_control_init(MV88F6281GTW_GE_MPP0_7,
MV88F6281GTW_GE_MPP8_15,
MV88F6281GTW_GE_MPP16_23,
MV88F6281GTW_GE_MPP24_31,
MV88F6281GTW_GE_MPP32_39,
MV88F6281GTW_GE_MPP40_47,
MV88F6281GTW_GE_MPP48_55);
- /* init serial */
- gd->baudrate = CONFIG_BAUDRATE;
- gd->have_console = 1;
- serial_init();
no need please remove the serial init is done by the lib_arm/board.c
- /*
* arch number of USED SOC
*/
- gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE;
- /* adress of boot parameters */
- gd->bd->bi_boot_params = 0x00000100;
- return 0;
+}
+int dram_init(void) +{
- int i;
- for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
gd->bd->bi_dram[i].start = kw_sdram_bar(i);
gd->bd->bi_dram[i].size = kw_sdram_bs(i);
- }
- return 0;
+}
+int last_stage_init(void) +{
- return 0;
+}
+#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent init */ +int misc_init_r(void) +{
- return kw_misc_init_r();
+}
+void reset_phy(void) +{ +#ifdef CONFIG_SWITCH_88E61XX
- mv_switch_88e61xx_init(ETH_0);
+#endif +}
+#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
is it possible to have a shorter name for the board?
new file mode 100644 index 0000000..0338757 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
as all kirkwood will use the same lds please move it to soc cpu/.../kirlwood/
@@ -0,0 +1,53 @@ +/*
- (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
- */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{
- . = _start;
- . = ALIGN(4);
- .text :
- {
cpu/arm926ejs/start.o (.text)
*(.text)
- }
- .rodata : { *(.rodata) }
please replace by this .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
- . = ALIGN(4);
- .data : { *(.data) }
- . = ALIGN(4);
- .got : { *(.got) }
- . = .;
- __u_boot_cmd_start = .;
- .u_boot_cmd : { *(.u_boot_cmd) }
- __u_boot_cmd_end = .;
- . = ALIGN(4);
- __bss_start = .;
- .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
- _end = .;
+}
diff --git a/include/configs/mv88f6281gtw_ge.h b/include/configs/mv88f6281gtw_ge.h new file mode 100644 index 0000000..7f2b325 --- /dev/null +++ b/include/configs/mv88f6281gtw_ge.h @@ -0,0 +1,185 @@ +/*
- (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 _CONFIG_MV88F6281GTW_GE_H +#define _CONFIG_MV88F6281GTW_GE_H
+/*
- Version number information
- */
+#define CONFIG_IDENT_STRING "\nMarvell-MV88F6281GTW_GE-A0"
+/*
- High Level Configuration Options (easy to change)
- */
+#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* Basic Architecture */ +#define CONFIG_FEROCEON_88FR131 1 /* CPU Core subversion */ +#define LE 1 /* Specify LE/BE operation */
why?
+#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */ +#define CONFIG_KW88F6281_A0 1 /* SOC Revision */
is is not possible to detect it?
+#define CONFIG_MV88F6281GTW_GE_A0 1 /* Board Name */
+#ifdef CONFIG_KIRKWOOD +#define CONFIG_MD5 /* get_random_hex on krikwood needs MD5 support */ +#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */ +#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE Port0 for kernel */ +#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to 1.8V */ +#endif
+/*
- CLKs configurations
- */
+#define CONFIG_SYS_HZ 1000
+/*
- Serial Port configuration
- The following definitions let you select what serial you want to use
- for your console driver.
- */
+#define CONFIG_KW_SERIAL +#define CONFIG_CONS_INDEX 0 /*Console on UART0 */
+#define CONFIG_BAUDRATE 115200 /* console baudrate */
^^^^^^^^^ whitespace please remove
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \
115200,230400, 460800, 921600 }
+/* auto boot */ +#define CONFIG_BOOTDELAY 3 /* default enable autoboot */
+/*
- For booting Linux, the board info and command line data
- have to be in the first 8 MB of memory, since this is
- the maximum mapped by the Linux kernel during initialization.
- */
+#define CONFIG_BOOTMAPSZ (8<<20) /* Initial Memmap for Linux */ +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS 1 /* enable memory tag */
+#define CONFIG_SYS_PROMPT "Marvell>> " /* Command Prompt
why not Marvell> or a board name?
+#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \
+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buff */
please add space before and after '+'
+/*
- Commands configuration
- */
+#define CONFIG_CMD_ENV +#define CONFIG_CMD_RUN +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_NET +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_AUTOSCRIPT +#define CONFIG_CMD_MEMORY
- "x_bootcmd_kernel=cp.b 0xf8100000 0x6400000 0x200000\0" \
- "x_bootargs_root=root=/dev/mtdblock3 ro rootfstype=squashfs\0"
+/*
- Size of malloc() pool
- */
+#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */
4M?
+/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128
+/*
- Other required minimal configurations
- */
+#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() */ +#define CONFIG_NR_DRAM_BANKS 4
^ whitespace please remove
+#define CONFIG_STACKSIZE 0x00100000 /* regular stack- 1M */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */ +#define CONFIG_SYS_MEMTEST_START 0x00400000 /* 4M */ +#define CONFIG_SYS_MEMTEST_END 0x007fffff /*(_8M -1) */
_8M?
+#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
+/*
- Ethernet Driver configuration
- */
+#ifdef CONFIG_CMD_NET +#define CONFIG_NETCONSOLE /* include NetConsole support */
whitespace please remove
+#define CONFIG_NET_MULTI /* specify more that one ports available */ +#define CONFIG_KIRKWOOD_EGIGA /* Enable SOC specific Ethernet Gigabit
Controller Driver */
please use this style of multiple comment /* * */
+#undef CONFIG_PHY_LINK_DETECT /* detect link always on */
/* specify ports to be used */
+#define CONFIG_KIRKWOOD_EGIGA_PORTS {TRUE,FALSE}
/* phy base addr for multi-chip addressing */
+#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0
please remove the IP params
+#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ +#endif /* CONFIG_CMD_NET */
+/*
- Marvell 88Exxxx Switch configurations
- */
+#define CONFIG_RESET_PHY_R /* use reset_phy() to init phy/swtich */
whitespace please remove
+#define CONFIG_SWITCH_88E61XX /* Enable mv88e61xx switch driver */ +#define CONFIG_SWITCH_MV88E6165 /* Used Switch is 88E6165 */
/* p5 of 88E6165 connceted to CPU */
+#define CONFIG_SWITCH_88E61XX_CPU_PORT 5 +#define CONFIG_SWITCH_88E61XX_ENABLED_PORTS (BIT0 | BIT1 | BIT2 | \
BIT3 | BIT4 | BIT5)
please remobe this BITx
+#endif /* _CONFIG_MV88F6281GTW_GE_H */
Best Regards, J.

Hi Jean
Thanks for your comments, Please see my reply inlined...
-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Friday, April 17, 2009 1:15 PM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v2] Marvell MV88F6281GTW_GE Board support
On 21:48 Wed 08 Apr , Prafulla Wadaskar wrote:
From: prafulla_wadaskar prafulla@marvell.com
This is Marvell's 88F6281_A0 based custom board developed
for wireless
access point product
This patch is tested for-
- Boot from DRAM/SPI flash/NFS
- File transfer using tftp and loadb
- SPI flash read/write/erase
- Booting Linux kernel and RFS from SPI flash
Note: doImage utility needed to convert u-boot.bin to u-boot-spiflash.bin, DRAM configuration will be part of this utility
btw where is the spi driver?
Drivers/spi/kirkwood_spi.c through Kirkwood SOC support patch :-)
+#define MV88F6281GTW_GE_OE_HIGH
(~((BIT4)|(BIT6)|(BIT7)|(BIT12) \
|(BIT13)|(BIT16)|(BIT17)))
+#define MV88F6281GTW_GE_OE_VAL_LOW (BIT20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH
((BIT6)|(BIT13)|(BIT16)|(BIT17)) plese remove the BITxx
Okay....
+/*
- Default values for MPP registers
- */
+#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000
please move all this define to a header and if possible please use macro to describe the content
Okay I will creat and move them to header
- /* init serial */
- gd->baudrate = CONFIG_BAUDRATE;
- gd->have_console = 1;
- serial_init();
no need please remove the serial init is done by the lib_arm/board.c
Okay I will remove it
+#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
is it possible to have a shorter name for the board?
No Jean, not possible, kernel patches also represents the same name and machine is also register with the same name, pleas bear with this, thanks..
- .rodata : { *(.rodata) }
please replace by this .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
Okay I will do it
- . = ALIGN(4);
- .data : { *(.data) }
- . = ALIGN(4);
- .got : { *(.got) }
+/*
+#define CONFIG_FEROCEON_88FR131 1 /* CPU Core
subversion */
+#define LE 1 /* Specify LE/BE operation */
why?
Because SOC can be initialized to work in both the modes.
+#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */ +#define CONFIG_KW88F6281_A0 1 /* SOC Revision */
is is not possible to detect it?
I will try to detect it.
+#define CONFIG_BAUDRATE 115200 /* console baudrate */
^^^^^^^^^
whitespace please remove
You mean spaces and tabs combination, I wll remove them
+#define CONFIG_SYS_PROMPT "Marvell>> " /*
Command Prompt why not Marvell> or a board name?
This is to sync up with our current u-boot and the automation tools/documentation based on it Changing it to Marvell> is not a big deal but will involve lot of unwanted efforts.
+#define CONFIG_SYS_CBSIZE 1024 /* Console I/O
Buff Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \
+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buff */
please add space before and after '+'
Okay..
+#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */
4M?
What it should be?
+/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128
+/*
- Other required minimal configurations */
+#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() */ +#define CONFIG_NR_DRAM_BANKS 4
^
whitespace please remove
Okay..
+#define CONFIG_STACKSIZE 0x00100000 /* regular stack- 1M */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /*
default load adr- 8M */
+#define CONFIG_SYS_MEMTEST_START 0x00400000 /* 4M */ +#define CONFIG_SYS_MEMTEST_END 0x007fffff /*(_8M -1) */
_8M?
What it should be ?
- */
+#ifdef CONFIG_CMD_NET +#define CONFIG_NETCONSOLE /* include NetConsole support */
whitespace please remove
Okay ..
+#define CONFIG_NET_MULTI /* specify more that one ports
available */
+#define CONFIG_KIRKWOOD_EGIGA /* Enable SOC specific
Ethernet Gigabit
Controller Driver */
please use this style of multiple comment /*
*/
Okay..
+#undef CONFIG_PHY_LINK_DETECT /* detect link always on */
/* specify ports to be used */
+#define CONFIG_KIRKWOOD_EGIGA_PORTS {TRUE,FALSE}
/* phy base addr for multi-chip
addressing */
+#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0
please remove the IP params
Why ?
+#define CONFIG_ENV_OVERWRITE /* ethaddr can be
reprogrammed */
+#endif /* CONFIG_CMD_NET */
+/*
- Marvell 88Exxxx Switch configurations */
+#define CONFIG_RESET_PHY_R /* use reset_phy() to init
phy/swtich */ whitespace please remove
Okay..
+#define CONFIG_SWITCH_88E61XX /* Enable mv88e61xx
switch driver */
+#define CONFIG_SWITCH_MV88E6165 /* Used Switch is 88E6165 */
/* p5 of 88E6165 connceted to CPU */
+#define CONFIG_SWITCH_88E61XX_CPU_PORT 5 +#define CONFIG_SWITCH_88E61XX_ENABLED_PORTS (BIT0 |
BIT1 | BIT2 | \
BIT3 | BIT4 | BIT5)
please remobe this BITx
Okay..
+#endif /* _CONFIG_MV88F6281GTW_GE_H */
Best Regards, J.

+#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000
please move all this define to a header and if possible please use macro to describe the content
Okay I will creat and move them to header
- /* init serial */
- gd->baudrate = CONFIG_BAUDRATE;
- gd->have_console = 1;
- serial_init();
no need please remove the serial init is done by the lib_arm/board.c
Okay I will remove it
+#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
is it possible to have a shorter name for the board?
No Jean, not possible, kernel patches also represents the same name and machine is also register with the same name, pleas bear with this, thanks..
ok if possible next time try a shorter name
- .rodata : { *(.rodata) }
please replace by this .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
Okay I will do it
- . = ALIGN(4);
- .data : { *(.data) }
- . = ALIGN(4);
- .got : { *(.got) }
+/*
+#define CONFIG_FEROCEON_88FR131 1 /* CPU Core
subversion */
+#define LE 1 /* Specify LE/BE operation */
why?
Because SOC can be initialized to work in both the modes.
so the binary will be compile as LE or BE so __ARMEL__ or __ARMEB__ will be defined
+#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */ +#define CONFIG_KW88F6281_A0 1 /* SOC Revision */
is is not possible to detect it?
I will try to detect it.
+#define CONFIG_BAUDRATE 115200 /* console baudrate */
^^^^^^^^^
whitespace please remove
You mean spaces and tabs combination, I wll remove them
+#define CONFIG_SYS_PROMPT "Marvell>> " /*
Command Prompt why not Marvell> or a board name?
This is to sync up with our current u-boot and the automation tools/documentation based on it Changing it to Marvell> is not a big deal but will involve lot of unwanted efforts.
ok
+#define CONFIG_SYS_CBSIZE 1024 /* Console I/O
Buff Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \
+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buff */
please add space before and after '+'
Okay..
+#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */
4M?
What it should be?
just ask why do you need 4M of malloc?
+/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128
+/*
- Other required minimal configurations */
+#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() */ +#define CONFIG_NR_DRAM_BANKS 4
^
whitespace please remove
Okay..
+#define CONFIG_STACKSIZE 0x00100000 /* regular stack- 1M */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /*
default load adr- 8M */
+#define CONFIG_SYS_MEMTEST_START 0x00400000 /* 4M */ +#define CONFIG_SYS_MEMTEST_END 0x007fffff /*(_8M -1) */
_8M?
What it should be ?
8M maybe
- */
+#ifdef CONFIG_CMD_NET +#define CONFIG_NETCONSOLE /* include NetConsole support */
whitespace please remove
Okay ..
+#define CONFIG_NET_MULTI /* specify more that one ports
available */
+#define CONFIG_KIRKWOOD_EGIGA /* Enable SOC specific
Ethernet Gigabit
Controller Driver */
please use this style of multiple comment /*
*/
Okay..
+#undef CONFIG_PHY_LINK_DETECT /* detect link always on */
/* specify ports to be used */
+#define CONFIG_KIRKWOOD_EGIGA_PORTS {TRUE,FALSE}
/* phy base addr for multi-chip
addressing */
+#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0
please remove the IP params
Why ?
it's board instance specific
Best Regards, J.

+#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
is it possible to have a shorter name for the board?
No Jean, not possible, kernel patches also represents the
same name and machine is also register with the same name, pleas bear with this, thanks.. ok if possible next time try a shorter name
Sure... Except one more exception please "mv88f6192gtw_fe" This is next board whose kernel support and board name registry is already done in linux, this will be the next board support patch from me after getting this stuff in. For next upcomming boards I will keep in mind
+#define LE 1 /* Specify
LE/BE operation */
why?
Because SOC can be initialized to work in both the modes.
so the binary will be compile as LE or BE so __ARMEL__ or __ARMEB__ will be defined
Okay I will change accordingly
+#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */
4M?
What it should be?
just ask why do you need 4M of malloc?
In future to support all SOC drivers, I will keep it 4M if you agree
default load adr- 8M */
+#define CONFIG_SYS_MEMTEST_START 0x00400000 /* 4M */ +#define CONFIG_SYS_MEMTEST_END 0x007fffff /*(_8M -1) */
_8M?
What it should be ?
8M maybe
:-) I will keep it 8M at this moment
+#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0
please remove the IP params
Why ?
it's board instance specific
Okay I will remove them
Regards.. Prafulla . .

On 23:26 Sat 18 Apr , Prafulla Wadaskar wrote:
+#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
is it possible to have a shorter name for the board?
No Jean, not possible, kernel patches also represents the
same name and machine is also register with the same name, pleas bear with this, thanks.. ok if possible next time try a shorter name
Sure... Except one more exception please "mv88f6192gtw_fe" This is next board whose kernel support and board name registry is already done in linux, this will be the next board support patch from me after getting this stuff in. For next upcomming boards I will keep in mind
ok
+#define LE 1 /* Specify
LE/BE operation */
why?
Because SOC can be initialized to work in both the modes.
so the binary will be compile as LE or BE so __ARMEL__ or __ARMEB__ will be defined
Okay I will change accordingly
+#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */
4M?
What it should be?
just ask why do you need 4M of malloc?
In future to support all SOC drivers, I will keep it 4M if you agree
ok
Best Regards, J.

Hi Prafulla,
Prafulla Wadaskar wrote: <snip>
+#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0
please remove the IP params
Why ?
Because these values are only relevant to your lab network, not anybody else who's going to use your boards. Boards should start with a clean slate. This is a hard rule that we've been enforcing for a while now - no address or network parameter initializations in config files.
regards, Ben

+#define CONFIG_IPADDR 192.168.5.44 +#define CONFIG_SERVERIP 192.168.5.30 +#define CONFIG_NETMASK 255.255.255.0
please remove the IP params
Why ?
Because these values are only relevant to your lab network, not anybody else who's going to use your boards. Boards should start with a clean slate. This is a hard rule that we've been enforcing for a while now - no address or network parameter initializations in config files.
Thanks Ben for clarification.
Regards.. Prafulla . .

Hi,
Any updates with this switches support in uboot?
2009/4/3 Prafulla Wadaskar prafulla@marvell.com:
From: prafulla_wadaskar prafulla@marvell.com
Chips supprted:-
- 88E61XX 6 port gbe swtich with 5 integrated PHYs
- 88E6061 6 port fe swtich with 5 integrated PHYs
- 88E1116 gbe transceiver
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com

-----Original Message----- From: Sergey Nikulov [mailto:sergey.nikulov@gmail.com] Sent: Thursday, May 21, 2009 4:20 AM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ronen Shitrit Subject: Re: [U-Boot] [PATCH] Marvell 88EXXXX Switch/PHY init support
Hi,
Any updates with this switches support in uboot?
Hi Sergey You can find patch here. This will be merged soon http://git.denx.de/?p=u-boot/u-boot-net.git;a=commit;h=b67f915a20e7bcb020602...
There are few updates to it that will follow the same path http://lists.denx.de/pipermail/u-boot/2009-May/052905.html
Regards.. Prafulla . .

Well, actually I'm more interested in mv88e60xx.c support :)
From log I can see
" Marvell MV88E61XX Switch Driver support " are MV88E61XX and MV88E60XX the same?
Regards, Sergey
2009/5/20 Prafulla Wadaskar prafulla@marvell.com:
-----Original Message----- From: Sergey Nikulov [mailto:sergey.nikulov@gmail.com] Sent: Thursday, May 21, 2009 4:20 AM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ronen Shitrit Subject: Re: [U-Boot] [PATCH] Marvell 88EXXXX Switch/PHY init support
Hi,
Any updates with this switches support in uboot?
Hi Sergey You can find patch here. This will be merged soon http://git.denx.de/?p=u-boot/u-boot-net.git;a=commit;h=b67f915a20e7bcb020602...
There are few updates to it that will follow the same path http://lists.denx.de/pipermail/u-boot/2009-May/052905.html
Regards.. Prafulla . .

Well, actually I'm more interested in mv88e60xx.c support :)
BTW: Which specific chip support you are looking for? I will try if I can help you
From log I can see " Marvell MV88E61XX Switch Driver support " are MV88E61XX and MV88E60XX the same?
Not really...
Regards.. Prafulla . .

Hi,
I'll provide you two seperate comment one for the file location and global comment and an other for code review
On 04:09 Sat 04 Apr , Prafulla Wadaskar wrote:
From: prafulla_wadaskar prafulla@marvell.com
Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:-
- 88F6281-Z0 define CONFIG_KW88F6281_Z0
- 88F6281-A0 define CONFIG_KW88F6281_A0
- 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:-
- Doimage utility needed to create binaries with bootROM header
- get_random_hex() fucntion
- SPI port controller driver
- PCI Express port initialization
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com
board/Marvell/common/kw_lowlevel_init.S | 45 +
is this init are Marvell common or Kirkwood common?
board/Marvell/include/core.h | 4 + cpu/arm926ejs/kirkwood/Makefile | 52 + cpu/arm926ejs/kirkwood/bin_dep.sh | 50 +
what it this file?
cpu/arm926ejs/kirkwood/config.mk | 25 + cpu/arm926ejs/kirkwood/doimage/Makefile | 112 ++
tools must go to tools/
cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h | 88 ++ cpu/arm926ejs/kirkwood/doimage/doimage | Bin 0 -> 17712 bytes
please remove and a .gitignore entry for it
cpu/arm926ejs/kirkwood/doimage/doimage.c | 1341 ++++++++++++++++++++++++ cpu/arm926ejs/kirkwood/dram.c | 49 + cpu/arm926ejs/kirkwood/kw88f6192.h | 34 +
please move define to include/asm-arm/arch-<somthing> the same as linux
cpu/arm926ejs/kirkwood/kw88f6281.h | 34 + cpu/arm926ejs/kirkwood/kwcore.c | 262 +++++ cpu/arm926ejs/kirkwood/kwcore.h | 141 +++ cpu/arm926ejs/kirkwood/serial.c | 187 ++++
please move to drivers/serial/
cpu/arm926ejs/kirkwood/soc_init.S | 156 +++
please call it lowlevel_init.S
cpu/arm926ejs/kirkwood/spi.c | 213 ++++
please move to drivers/spi/
cpu/arm926ejs/kirkwood/timer.c | 165 +++ include/configs/kirkwood.h | 46 +
include/configs/ are only for boards config
Best Regards, J.

-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Saturday, April 04, 2009 9:55 PM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ronen Shitrit; Nicolas Pitre Subject: Re: [U-Boot] [PATCH] Marvell Kirkwood family SOC support
Hi,
I'll provide you two seperate comment one for the file location and global comment and an other for code review
On 04:09 Sat 04 Apr , Prafulla Wadaskar wrote:
From: prafulla_wadaskar prafulla@marvell.com
Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:-
- 88F6281-Z0 define CONFIG_KW88F6281_Z0
- 88F6281-A0 define CONFIG_KW88F6281_A0
- 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:-
- Doimage utility needed to create binaries with bootROM header
- get_random_hex() fucntion
- SPI port controller driver
- PCI Express port initialization
Contributors: Yotam Admon yotam@marvell.com Michael Blostein <michaelbl@marvell.com
Signed-off-by: prafulla_wadaskar prafulla@marvell.com
Reviewed by:
Ronen Shitrit rshitrit@marvell.com
board/Marvell/common/kw_lowlevel_init.S | 45 +
is this init are Marvell common or Kirkwood common?
This is Marvell common, this is board specific but since it is used for each supported board I have moved it to common folder.
board/Marvell/include/core.h | 4 + cpu/arm926ejs/kirkwood/Makefile | 52 + cpu/arm926ejs/kirkwood/bin_dep.sh | 50 +
what it this file?
This was supported file to build doImage form tools context Removed..
cpu/arm926ejs/kirkwood/config.mk | 25 + cpu/arm926ejs/kirkwood/doimage/Makefile | 112 ++
tools must go to tools/
Removed..
cpu/arm926ejs/kirkwood/doimage/bootstrap_def.h | 88 ++ cpu/arm926ejs/kirkwood/doimage/doimage | Bin 0 ->
17712 bytes please remove and a .gitignore entry for it
Removed..
cpu/arm926ejs/kirkwood/doimage/doimage.c | 1341
++++++++++++++++++++++++
cpu/arm926ejs/kirkwood/dram.c | 49 + cpu/arm926ejs/kirkwood/kw88f6192.h | 34 +
please move define to include/asm-arm/arch-<somthing> the same as linux
Moved...
cpu/arm926ejs/kirkwood/kw88f6281.h | 34 + cpu/arm926ejs/kirkwood/kwcore.c | 262 +++++ cpu/arm926ejs/kirkwood/kwcore.h | 141 +++ cpu/arm926ejs/kirkwood/serial.c | 187 ++++
please move to drivers/serial/
Moved...
cpu/arm926ejs/kirkwood/soc_init.S | 156 +++
please call it lowlevel_init.S
Renamed..
cpu/arm926ejs/kirkwood/spi.c | 213 ++++
please move to drivers/spi/
Moved...
cpu/arm926ejs/kirkwood/timer.c | 165 +++ include/configs/kirkwood.h | 46 +
include/configs/ are only for boards config
Moved this file to asm-arm/arch-kirkwood/
I am in process accumulating and testing changes I will send you updated patch (v2) for the same
Thanks....
Regards.. Prafulla . .
Best Regards, J.

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

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@marvell.com] Sent: Wednesday, April 08, 2009 5:33 PM To: u-boot@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:-
- 88F6281-Z0 define CONFIG_KW88F6281_Z0
- 88F6281-A0 define CONFIG_KW88F6281_A0
- 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:-
- get_random_hex() fucntion
- SPI port controller driver
- 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
1.5.3.3

On 17:33 Wed 08 Apr , Prafulla Wadaskar wrote:
Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:-
- 88F6281-Z0 define CONFIG_KW88F6281_Z0
- 88F6281-A0 define CONFIG_KW88F6281_A0
- 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:-
- get_random_hex() fucntion
- SPI port controller driver
- 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)));
please create macro for these registers please use readx/writex (madatory)
- 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);
plase use readx/writex everywhere
- 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)
could you detect it
- /*
* in case of 88F6281/88F6192 A0,
* BIT7 need to reset to generate random values in 0x1470
*/
- KW_REG_BITS_RESET(0x1478, BIT7);
please use macro everywhere instead of hardcode value
+#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) +{
coudl explain a few more what you do and try use macro instead of hardcode value
- 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));
please cp15 api (the same as the kernel) set_cr/get_cr
btw could explain why do you need to do it via env?
be aware that we have cache API
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));
- }
<snip>
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;
please do not use upper case
+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))
please move all this define to header corresponding of the functionallity/IP
- .globl kw_cpu_if_pre_init
+kw_cpu_if_pre_init:
do you really need to do this before relocation
mov r11, LR /* Save link register */
will you call a sub routine?
/*
* 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)
please remove thhis KW_RED_READ_ASM or do it via asm macro as we have done for sh2/3/4
- 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
please create a macro for this
mov PC, r11 /* r11 is saved link register */
.globl lowlevel_init
in this case call it arch_lowlevel_init
and update start.S to call it just be the lowlevel_init
which is board lowlevel init
+lowlevel_init:
if you have multple sub call use the stack will be beter
/* 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)
please no uppercase in the var name
+/*
- 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
please move all this define to a header
and nearly all precedent comment can be apply to the rest of the patch
Best Regards, J.

Hi Jean
Thanks for your review comments.
-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Friday, April 17, 2009 2:52 PM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v2] Marvell Kirkwood family SOC support
On 17:33 Wed 08 Apr , Prafulla Wadaskar wrote:
Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:-
- 88F6281-Z0 define CONFIG_KW88F6281_Z0
- 88F6281-A0 define CONFIG_KW88F6281_A0
- 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:-
- get_random_hex() fucntion
- SPI port controller driver
- PCI Express port initialization
+/*
- 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)));
please create macro for these registers
This will be taken care....
please use readx/writex (madatory)
You mean instead of KW_REG_READ to be used readx() ?
+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);
plase use readx/writex everywhere
Okay...
+#if defined (CONFIG_KW88F6281_Z0)
- KW_REG_BITS_SET(0x1478, BIT7);
+#elif defined (CONFIG_KW88F6281_A0) || defined
(CONFIG_KW88F6192_A0) could you detect it
I should be able to detect it, I will check and update the same
- /*
* in case of 88F6281/88F6192 A0,
* BIT7 need to reset to generate random values in 0x1470
*/
- KW_REG_BITS_RESET(0x1478, BIT7);
please use macro everywhere instead of hardcode value
Okay..
+/*
- kw_window_ctrl_reg_init - Mbus-L to Mbus Bridge Registers init.
- */
+int kw_window_ctrl_reg_init(void) +{
coudl explain a few more what you do and try use macro instead of hardcode value
Macros will be used.. I will put the explaination in the comment for this function
- 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);
+#ifndef __ASSEMBLY__ +void reset_cpu(unsigned long ignored); unsigned char +get_random_hex(void); typedef enum _memory_bank { BANK0, BANK1, +BANK2, BANK3 } MEMORY_BANK;
please do not use upper case
You mean MEMORY_BANK, right? I will change it
(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))
please move all this define to header corresponding of the functionallity/IP
I thought these are only settings limited to this file only, any way I will create and move them to header file
- .globl kw_cpu_if_pre_init
+kw_cpu_if_pre_init:
do you really need to do this before relocation
Yes..
mov r11, LR /* Save link register */
will you call a sub routine?
I will do it?
- .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)
please remove thhis KW_RED_READ_ASM or do it via asm macro as we have done for sh2/3/4
I will check this...
- /* invalidate L2 cache */
- mov r0, #0
- mcr p15, 1, r0, c15, c11, 0
please create a macro for this
Okay...
mov PC, r11 /* r11 is saved link register */
.globl lowlevel_init
in this case call it arch_lowlevel_init
and update start.S to call it just be the lowlevel_init
You mean to add support for arch_lowlevel_init, using some CONFIG_ option ?
which is board lowlevel init
+lowlevel_init:
if you have multple sub call use the stack will be beter
That's good idea, I will do it
+/*
- 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)
please no uppercase in the var name
Okay..
+/*
- 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
please move all this define to a header
Okay...
Thanks and regards.... Prafulla . .
and nearly all precedent comment can be apply to the rest of the patch
Best Regards, J.

On 23:44 Fri 17 Apr , Prafulla Wadaskar wrote:
Hi Jean
Thanks for your review comments.
-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Friday, April 17, 2009 2:52 PM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v2] Marvell Kirkwood family SOC support
On 17:33 Wed 08 Apr , Prafulla Wadaskar wrote:
Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:-
- 88F6281-Z0 define CONFIG_KW88F6281_Z0
- 88F6281-A0 define CONFIG_KW88F6281_A0
- 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:-
- get_random_hex() fucntion
- SPI port controller driver
- PCI Express port initialization
+/*
- 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)));
please create macro for these registers
This will be taken care....
please use readx/writex (madatory)
You mean instead of KW_REG_READ to be used readx() ?
readl I guess
take a look in include/arm-asm/io.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);
plase use readx/writex everywhere
Okay...
+#if defined (CONFIG_KW88F6281_Z0)
- KW_REG_BITS_SET(0x1478, BIT7);
+#elif defined (CONFIG_KW88F6281_A0) || defined
(CONFIG_KW88F6192_A0) could you detect it
I should be able to detect it, I will check and update the same
- /*
* in case of 88F6281/88F6192 A0,
* BIT7 need to reset to generate random values in 0x1470
*/
- KW_REG_BITS_RESET(0x1478, BIT7);
please use macro everywhere instead of hardcode value
Okay..
+/*
- kw_window_ctrl_reg_init - Mbus-L to Mbus Bridge Registers init.
- */
+int kw_window_ctrl_reg_init(void) +{
coudl explain a few more what you do and try use macro instead of hardcode value
Macros will be used.. I will put the explaination in the comment for this function
- 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);
+#ifndef __ASSEMBLY__ +void reset_cpu(unsigned long ignored); unsigned char +get_random_hex(void); typedef enum _memory_bank { BANK0, BANK1, +BANK2, BANK3 } MEMORY_BANK;
please do not use upper case
You mean MEMORY_BANK, right? I will change it
yes
(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))
please move all this define to header corresponding of the functionallity/IP
I thought these are only settings limited to this file only, any way I will create and move them to header file
- .globl kw_cpu_if_pre_init
+kw_cpu_if_pre_init:
do you really need to do this before relocation
Yes..
could add comment to explain why
mov r11, LR /* Save link register */
will you call a sub routine?
I will do it?
- .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)
please remove thhis KW_RED_READ_ASM or do it via asm macro as we have done for sh2/3/4
I will check this...
attached a first version of macro.h file for arm
- /* invalidate L2 cache */
- mov r0, #0
- mcr p15, 1, r0, c15, c11, 0
please create a macro for this
Okay...
mov PC, r11 /* r11 is saved link register */
.globl lowlevel_init
in this case call it arch_lowlevel_init
and update start.S to call it just be the lowlevel_init
You mean to add support for arch_lowlevel_init, using some CONFIG_ option ?
yes CONFIG_ARCH_LOWLEVEL_INIT
Best Regards, J.

- u32 enable = (0x01 & KW_REG_READ((0x1504 + bank * 8)));
please create macro for these registers
This will be taken care....
please use readx/writex (madatory)
You mean instead of KW_REG_READ to be used readx() ?
readl I guess
take a look in include/arm-asm/io.h
I understood... Thanks
- .globl kw_cpu_if_pre_init
+kw_cpu_if_pre_init:
do you really need to do this before relocation
Yes..
could add comment to explain why
Okay I will add..
please remove thhis KW_RED_READ_ASM or do it via asm macro as we have done for sh2/3/4
I will check this...
attached a first version of macro.h file for arm
Thanks ....
and update start.S to call it just be the lowlevel_init
You mean to add support for arch_lowlevel_init, using some
CONFIG_ option ? yes CONFIG_ARCH_LOWLEVEL_INIT
Okay, I will release a small separate patch for this because this will be generic to arm other SOCs too
Regards.. Prafulla . .
Best Regards, J.

Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:- 1) 88F6281-A0 define CONFIG_KW88F6281_A0 2) 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:- 1) get_random_hex() function 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 --- Change log: 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
v3: lowlevel_init.S converted to lowlevel_init.c removed BITxx macros, removed entire assembly code Added CONFIG_ARCH_LOWLEVE_INIT support for arm926ejs core updated as per review comments for v2
board/Marvell/include/core.h | 4 + cpu/arm926ejs/kirkwood/Makefile | 49 +++++ cpu/arm926ejs/kirkwood/config.mk | 25 +++ cpu/arm926ejs/kirkwood/dram.c | 57 ++++++ cpu/arm926ejs/kirkwood/kwcore.c | 304 +++++++++++++++++++++++++++++ cpu/arm926ejs/kirkwood/kwcore.h | 112 +++++++++++ cpu/arm926ejs/kirkwood/lowlevel_init.c | 93 +++++++++ cpu/arm926ejs/kirkwood/timer.c | 165 ++++++++++++++++ cpu/arm926ejs/start.S | 7 +- 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 | 140 +++++++++++++ include/asm-arm/arch-kirkwood/kw88f6192.h | 37 ++++ include/asm-arm/arch-kirkwood/kw88f6281.h | 37 ++++ include/asm-arm/config.h | 4 + 17 files changed, 1421 insertions(+), 1 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.c 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..9f9aed2 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/Makefile @@ -0,0 +1,49 @@ +# +# (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-$(CONFIG_ARCH_LOWLEVEL_INIT) += lowlevel_init.o +COBJS-y += timer.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..03f3277 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/dram.c @@ -0,0 +1,57 @@ +/* + * (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 KW_REG_CPUCS_WIN_BAR(x) (0x1500+ (x * 0x08)) +#define KW_REG_CPUCS_WIN_SZ(x) (0x1504+ (x * 0x08)) +/* + * kw_sdram_bar - reads SDRAM Base Address Register + */ +u32 kw_sdram_bar(enum memory_bank bank) +{ + u32 result = 0; + u32 enable = 0x01 & readl(KW_REG_CPUCS_WIN_SZ(bank)); + + if ((!enable) || (bank > BANK3)) + return 0; + + result = readl(KW_REG_CPUCS_WIN_BAR(bank)); + return result; +} + +/* + * kw_sdram_bs - reads SDRAM Bank size + */ +u32 kw_sdram_bs(enum memory_bank bank) +{ + u32 result = 0; + u32 enable = 0x01 & readl(KW_REG_CPUCS_WIN_SZ(bank)); + + if ((!enable) || (bank > BANK3)) + return 0; + result = 0xff000000 & readl(KW_REG_CPUCS_WIN_SZ(bank)); + result += 0x01000000; + return result; +} diff --git a/cpu/arm926ejs/kirkwood/kwcore.c b/cpu/arm926ejs/kirkwood/kwcore.c new file mode 100644 index 0000000..df57f4c --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.c @@ -0,0 +1,304 @@ +/* + * (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) +{ + writel_set_bits(KW_REG_CPU_RSTOUTN_MASK, 1<<2); + writel_set_bits(KW_REG_CPU_SYS_SOFT_RST, 1<<0); + 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]; + + /* + * in case of 88F6281/88F6192 A0, + * 1<<7 need to reset to generate random values in 0x1470 + * Soc reg offsets 0x1470 and 0x1478 are reserved regs and + * Does not have names at this moment (no errata available) + */ + writel_reset_bits(0x1478, 1<<7); + for (i = 0; i < 16; i++) { + inbuf[i] = readl(0x1470); + } + md5((u8 *) inbuf, 64, outbuf); + return outbuf[outbuf[7] % 0x0f]; +} + +/* + * Window Size + * Used with the Base register to set the address window size and location. + * Must be programmed from LSB to MSB as sequence of 1?EUR(tm)s followed by + * sequence of 0?EUR(tm)s. The number of 1?EUR(tm)s specifies the size of the window in + * 64 KByte granularity (e.g., a value of 0x00FF specifies 256 = 16 MByte). + * NOTE: A value of 0x0 specifies 64-KByte size. + */ +static unsigned int kw_winctrl_calcsize(unsigned int sizeval) +{ + int i; + unsigned int j = 0; + + for (i = 0; i < (sizeval / 0x10000); i++) { + j |= 1 << i; + } + return (0x0000ffff & j); +} + +/* prepares data to be loaded in win_Ctrl register */ +#define KWCPU_WIN_CTRL_DATA(size, target, attr, en) (en | target<<4 \ + | attr<<8 | kw_winctrl_calcsize(size)<<16) + +/* + * kw_window_ctrl_reg_init - Mbus-L to Mbus Bridge Registers init. + * + * Ref: Sec 25.1 and 25.3 of Datasheet + * The CPU interfaces with the device units over the Mbus-L to Mbus bridge. + * This bridge forwards CPU transactions to the device units over the Mbus, + * and forwards read responses back from the units to the CPU. + * + * NOTE: If the remap function for this register is not used, + * the <Remap> field in the Window0 Remap Low Register must be set to same + * value as the <Base> field in this register + */ +int kw_window_ctrl_reg_init(void) +{ + writel(KW_REG_WIN_CTRL(0), + KWCPU_WIN_CTRL_DATA(0xc0000, KWCPU_TARGET_PCIE, + KWCPU_ATTR_PCIE_MEM, KWCPU_WIN_ENABLE)); + + writel(KW_REG_WIN_BASE(0), 0x90000000); + writel(KW_REG_WIN_REMAP_LOW(0), 0x90000000); + writel(KW_REG_WIN_REMAP_HIGH(0), 0x00000000); + + writel(KW_REG_WIN_CTRL(1), + KWCPU_WIN_CTRL_DATA(0x70000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_NANDFLASH, KWCPU_WIN_ENABLE)); + writel(KW_REG_WIN_BASE(1), 0xF9000000); + writel(KW_REG_WIN_REMAP_LOW(1), 0xF9000000); + writel(KW_REG_WIN_REMAP_HIGH(1), 0x00000000); + + writel(KW_REG_WIN_CTRL(2), + KWCPU_WIN_CTRL_DATA(0x80000, KWCPU_TARGET_PCIE, + KWCPU_ATTR_PCIE_IO, KWCPU_WIN_ENABLE)); + writel(KW_REG_WIN_BASE(2), 0xF0000000); + writel(KW_REG_WIN_REMAP_LOW(2), 0xC0000000); + writel(KW_REG_WIN_REMAP_HIGH(2), 0x00000000); + + writel(KW_REG_WIN_CTRL(3), + KWCPU_WIN_CTRL_DATA(0x80000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_SPIFLASH, KWCPU_WIN_ENABLE)); + writel(KW_REG_WIN_BASE(3), 0xF8000000); + writel(KW_REG_WIN_REMAP_LOW(3), 0x00000000); + writel(KW_REG_WIN_REMAP_HIGH(3), 0x00000000); + + writel(KW_REG_WIN_CTRL(4), + KWCPU_WIN_CTRL_DATA(0x80000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_BOOTROM, KWCPU_WIN_ENABLE)); + writel(KW_REG_WIN_BASE(4), 0xFF000000); + writel(KW_REG_WIN_REMAP_LOW(4), 0x00000000); + writel(KW_REG_WIN_REMAP_HIGH(4), 0x00000000); + + writel(KW_REG_WIN_CTRL(5), + KWCPU_WIN_CTRL_DATA(0xb0000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_SPIFLASH, KWCPU_WIN_DISABLE)); + writel(KW_REG_WIN_BASE(5), 0xE8000000); + writel(KW_REG_WIN_REMAP_LOW(5), 0x00000000); + writel(KW_REG_WIN_REMAP_HIGH(5), 0x00000000); + + writel(KW_REG_WIN_CTRL(6), + KWCPU_WIN_CTRL_DATA(0xb0000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_BOOTROM, KWCPU_WIN_DISABLE)); + writel(KW_REG_WIN_BASE(6), 0xF0000000); + writel(KW_REG_WIN_REMAP_LOW(6), 0x00000000); + writel(KW_REG_WIN_REMAP_HIGH(6), 0x00000000); + + writel(KW_REG_WIN_CTRL(7), + KWCPU_WIN_CTRL_DATA(0x0, KWCPU_TARGET_SASRAM, KWCPU_ATTR_SASRAM, + KWCPU_WIN_ENABLE)); + writel(KW_REG_WIN_BASE(7), 0xFB000000); + writel(KW_REG_WIN_REMAP_LOW(7), 0x00000000); + writel(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 */ + writel(KW_REG_GPP0_DATA_OUT, gpp0_oe_val); + writel(KW_REG_GPP1_DATA_OUT, gpp1_oe_val); + writel(KW_REG_GPP0_DATA_OUT_EN, gpp0_oe); + writel(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 */ + writel(KW_REG_MPP_CONTROL0, mpp0_7); + writel(KW_REG_MPP_CONTROL1, mpp8_15); + writel(KW_REG_MPP_CONTROL2, mpp16_23); + writel(KW_REG_MPP_CONTROL3, mpp24_31); + writel(KW_REG_MPP_CONTROL4, mpp32_39); + writel(KW_REG_MPP_CONTROL5, mpp40_47); + writel(KW_REG_MPP_CONTROL6, mpp48_55); + return KW_OK; +} + +char *kwsoc_name(void) +{ + switch (readl(KW_REG_DEVICE_ID) & 0x03) { + case 1: + return ("88F6192_A0"); + break; + case 2: + return ("88F6281_A0"); + break; + default: + return ("Unknown"); + } +} + +/* + * kw_misc_init_r - SOC specific misc init (mainly cache initialization) + */ +int kw_misc_init_r(void) +{ + char *env; + volatile unsigned int temp; + + printf("SoC: %s\n", kwsoc_name()); + + /*CPU streaming & write allocate */ + env = getenv("enaWrAllo"); + temp = readfr_extra_feature_reg(); + if (env && ((strcmp(env, "yes") == 0) || (strcmp(env, "Yes") == 0))) + temp |= 1<<28; /*Enable wr alloc */ + else + temp &= ~1<<28; /*disable wr alloc */ + writefr_extra_feature_reg(temp); + + env = getenv("enaCpuStream"); + temp = readfr_extra_feature_reg(); + if (!env || (strcmp(env, "no") == 0) || (strcmp(env, "No") == 0)) + temp &= ~1<<29; /* streaming disabled */ + else + temp |= 1<<29; /*streaming enabled */ + writefr_extra_feature_reg(temp); + + /* Verify write allocate and streaming */ + printf("\n"); + temp = readfr_extra_feature_reg(); + if (temp & 1<<29) + printf("Streaming enabled\n"); + else + printf("Streaming disabled\n"); + if (temp & 1<<28) + 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 = readl(KW_REG_CPU_CONFIG); + temp |= 1<<17; /* Set CCR_DCACH_PREF_BUF_ENABLE */ + writel(KW_REG_CPU_CONFIG, temp); + } + + if (env && ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0))) { + temp = readl(KW_REG_CPU_CONFIG); + temp &= ~1<<17; /* Reset CCR_DCACH_PREF_BUF_ENABLE */ + writel(KW_REG_CPU_CONFIG, temp); + } + + /* ICache Pref */ + env = getenv("enaICPref"); + if (env && ((strcmp(env, "yes") == 0) || (strcmp(env, "Yes") == 0))) { + temp = readl(KW_REG_CPU_CONFIG); + temp |= 1<<16; /* Set CCR_ICACH_PREF_BUF_ENABLE */ + writel(KW_REG_CPU_CONFIG, temp); + } + + if (env && ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0))) { + temp = readl(KW_REG_CPU_CONFIG); + temp &= ~1<<16; /* Reset CCR_ICACH_PREF_BUF_ENABLE */ + writel(KW_REG_CPU_CONFIG, temp); + } + /* Set L2C WT mode - Set bit 4 */ + temp = readl(KW_REG_CPU_L2_CONFIG); + env = getenv("setL2CacheWT"); + if (!env || ((strcmp(env, "yes") == 0) || (strcmp(env, "Yes") == 0))) { + temp |= 1<<4; + } else + temp &= ~1<<4; + writel(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 &= ~1<<24; + else + temp |= 1<<24; + + /* enable L2C - Set bit 22 */ + env = getenv("disL2Cache"); + if (!env || ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0))) + temp |= 1<<22; + else + temp &= ~1<<22; + + asm("mcr p15, 1, %0, c15, c1, 0": :"r"(temp)); + + /* Enable i cache */ + asm("mrc p15, 0, %0, c1, c0, 0":"=r"(temp)); + temp |= 1<<12; + 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 &= ~1<<13; + 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..feec86b --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.h @@ -0,0 +1,112 @@ +/* + * (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 + +#include <asm/system.h> + +#ifndef __ASSEMBLY__ +enum memory_bank { + BANK0, + BANK1, + BANK2, + BANK3 +}; + +enum kwcpu_winen { + KWCPU_WIN_DISABLE, + KWCPU_WIN_ENABLE +}; + +enum kwcpu_target { + KWCPU_TARGET_RESERVED, + KWCPU_TARGET_MEMORY, + KWCPU_TARGET_1RESERVED, + KWCPU_TARGET_SASRAM, + KWCPU_TARGET_PCIE +}; + +enum kwcpu_attrib { + KWCPU_ATTR_SASRAM = 0x01, + KWCPU_ATTR_NANDFLASH = 0x2f, + KWCPU_ATTR_SPIFLASH = 0x1e, + KWCPU_ATTR_BOOTROM = 0x1d, + KWCPU_ATTR_PCIE_IO = 0xe0, + KWCPU_ATTR_PCIE_MEM = 0xe8 +}; + +/* + * read feroceon/sheeva core extra feature register + * using co-proc instruction + */ +static inline unsigned int readfr_extra_feature_reg(void) +{ + unsigned int val; + asm volatile ("mrc p15, 1, %0, c15, c1, 0 @ readfr exfr" + : "=r" (val) : : "cc"); + return val; +} + +/* + * write feroceon/sheeva core extra feature register + * using co-proc instruction + */ +static inline void writefr_extra_feature_reg(unsigned int val) +{ + asm volatile("mcr p15, 1, %0, c15, c1, 0 @ writefr exfr" + : : "r" (val) : "cc"); + isb(); +} + +/* + * Invalidate L2 Cache using co-proc instruction + */ +static inline void invalidate_l2_cache(void) +{ + unsigned int val=0; + + asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache" + : : "r" (val) : "cc"); + isb(); +} + +/* + * functions + */ +void reset_cpu(unsigned long ignored); +unsigned char get_random_hex(void); +unsigned int kw_sdram_bar(enum memory_bank bank); +unsigned int kw_sdram_bs(enum 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.c b/cpu/arm926ejs/kirkwood/lowlevel_init.c new file mode 100644 index 0000000..21bfc81 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/lowlevel_init.c @@ -0,0 +1,93 @@ +/* + * (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> + +void kw_cpu_if_pre_init(void) +{ + u32 reg; + +#ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8 + /* + * Configures the I/O voltage of the pads connected to Egigabit + * Ethernet interface to 1.8V + * By defult it is set to 3.3V + */ + reg = readl(KW_REG_MPP_OUT_DRV_REG); + reg |= 1 << 7; + writel(KW_REG_MPP_OUT_DRV_REG, ®); +#endif +#ifdef CONFIG_KIRKWOOD_EGIGA_INIT + /* + * 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 + */ + reg = readl((KW_EGIGA0_BASE + 0x44c)); /* PORT_SERIAL_CONTROL1_REG */ + reg &= ~(1 << 4); /* Clear PortReset Bit */ + writel((KW_EGIGA0_BASE + 0x44c), ®); /* PORT_SERIAL_CONTROL1_REG */ + reg = readl((KW_EGIGA1_BASE + 0x44c)); /* PORT_SERIAL_CONTROL1_REG */ + reg &= ~(1 << 4); /* Clear PortReset Bit */ + writel((KW_EGIGA1_BASE + 0x44c), ®); /* PORT_SERIAL_CONTROL1_REG */ +#endif +#ifdef CONFIG_KIRKWOOD_PCIE_INIT + /* + * Enable PCI Express Port0 + */ + reg = readl(KW_REG_CPU_CTRL_STAT); + reg |= 1 << 0; /* Set PEX0En Bit */ + writel(KW_REG_CPU_CTRL_STAT, ®); +#endif +} + +void kw_enable_invalidate_l2_cache(void) +{ + u32 reg; + + /* Enable L2 cache in write through mode */ + reg = readl(KW_REG_CPU_L2_CONFIG); + reg |= 0x18; + writel(KW_REG_CPU_L2_CONFIG, reg); + /* Read operation to make sure the L2 bit is set */ + reg = readl(KW_REG_CPU_L2_CONFIG); + + invalidate_l2_cache(); +} + +void arch_lowlevel_init(void) +{ + /* Linux expects` the internal registers to be at 0xf1000000 */ + writel(KW_REGS_PHY_BASE, KW_OFFSET_REG); + + /* Enable L2 cache in write through mode */ + kw_enable_invalidate_l2_cache(); + + /* + * kw_cpu_if_pre_init contains + * Initialize BUS-L to DDR configuration parameters + * so must be done prior to DDR operation + */ + kw_cpu_if_pre_init(); +} diff --git a/cpu/arm926ejs/kirkwood/timer.c b/cpu/arm926ejs/kirkwood/timer.c new file mode 100644 index 0000000..c6e1a26 --- /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) 1<<1 +#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 (readl(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 = readl(CNTMR_VAL_REG(UBOOT_CNTR)); + delayticks = (usec * (CONFIG_SYS_TCLK / 1000000)); + + if (current < delayticks) { + delayticks -= current; + while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) < current) ; + while ((TIMER_LOAD_VAL - delayticks) < + readl(CNTMR_VAL_REG(UBOOT_CNTR))) ; + } else { + while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) > + (current - delayticks)) ; + } +} + +/* + * init the counter + */ +int timer_init(void) +{ + unsigned int cntmrCtrl; + + /* load value onto counter\timer */ + writel(CNTMR_RELOAD_REG(UBOOT_CNTR), TIMER_LOAD_VAL); + writel(CNTMR_VAL_REG(UBOOT_CNTR), TIMER_LOAD_VAL); + + /* set the counter to load in the first time */ + writel(CNTMR_VAL_REG(UBOOT_CNTR), TIMER_LOAD_VAL); + + /* set control for timer \ cunter and enable */ + /* read control register */ + cntmrCtrl = readl(CNTMR_CTRL_REG); + cntmrCtrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR); /* enable cnt\timer */ + cntmrCtrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR); /* Auto mode */ + + writel(CNTMR_CTRL_REG, cntmrCtrl); + + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + return 0; +} diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index ed4932a..520dcef 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -201,7 +201,7 @@ _start_armboot: * ************************************************************************* */ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined (CONFIG_ARCH_LOWLEVEL_INIT) cpu_init_crit: /* * flush v4 I/D caches @@ -224,7 +224,12 @@ cpu_init_crit: * Go setup Memory and board specific bits prior to relocation. */ mov ip, lr /* perserve link reg across call */ +#ifdef CONFIG_ARCH_LOWLEVEL_INIT + bl arch_lowlevel_init /* go setup arch specific init */ +#endif /* CONFIG_ARCH_LOWLEVEL_INIT */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl lowlevel_init /* go setup pll,mux,memory */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ mov lr, ip /* restore link */ mov pc, lr /* back to my caller */ #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 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 1<<0 /* fifo enable */ +#define FCR_RXSR 1<<1 /* receiver soft reset */ +#define FCR_TXSR 1<<2 /* transmitter soft reset */ +#define MCR_RTS 1<<1 /* 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 1<<0 /* Data ready */ +#define LSR_OE 1<<1 /* Overrun */ +#define LSR_PE 1<<2 /* Parity error */ +#define LSR_FE 1<<3 /* Framing error */ +#define LSR_BI 1<<4 /* Break */ +#define LSR_THRE 1<<5 /* Xmit holding register empty */ +#define LSR_TEMT 1<<6 /* Xmitter empty */ +#define LSR_ERR 1<<7 /* 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..a884ac1 --- /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; + + writel(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); + writel(KW_REG_SPI_CONFIG, 0x00000210 | data); + writel(KW_REG_SPI_IRQ_CAUSE, 0x00000001); + writel(KW_REG_SPI_IRQ_MASK, 0x00000000); + + /* program mpp registers to select SPI_CSn */ + if (cs) + writel(KW_REG_MPP_CONTROL0, + ((readl(KW_REG_MPP_CONTROL0) & 0x0fffffff) | + 0x20000000)); + else + writel(KW_REG_MPP_CONTROL0, + ((readl(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) +{ + writel_set_bits(KW_REG_SPI_CTRL, 1<<0); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + writel_reset_bits(KW_REG_SPI_CTRL, 1<<0); +} + +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 */ + writel_reset_bits(KW_REG_SPI_CONFIG, 1<<5); + /* Shift data so it's msb-justified */ + if (dout) { + tmpdout = *(u32 *) dout & 0x0ff; + } + } else { + /*2 byte xfer mode */ + writel_set_bits(KW_REG_SPI_CONFIG, 1<<5); + /* Shift data so it's msb-justified */ + if (dout) { + tmpdout = *(u32 *) dout & 0x0ffff; + } + } + + writel(KW_REG_SPI_IRQ_CAUSE, 0x0); /* clear bit */ + writel(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 (readl(KW_REG_SPI_IRQ_CAUSE)) { + isRead = 1; + tmpdin = readl(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..f07aa64 --- /dev/null +++ b/include/asm-arm/arch-kirkwood/kirkwood.h @@ -0,0 +1,140 @@ +/* + * (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 + +#if defined (__ARMEL__) +#define LE +#else +#define BE +#endif /* __ARMEL__ */ + +#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_DEVICE_ID (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) + +#define KW_REG_PCIE_BASE (0x40000) + +/* + * Macros + * CPU architecture dependent I/O read/write + */ +#define writel(addr, data) \ + (*((volatile unsigned int*)(KW_REGISTER(addr))) \ + = (unsigned int)WORD_SWAP((data))) + +#define readl(addr) \ + (WORD_SWAP(*((volatile unsigned int*)(KW_REGISTER(addr))))) + +#define writel_set_bits(adr, bits) (writel(adr, readl(adr)\ + | ((unsigned int)WORD_SWAP(bits)))) + +#define writel_reset_bits(adr, bits) (writel(adr, readl(adr)\ + & ~((unsigned int)WORD_SWAP(bits)))) + +/* + * 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..270d931 --- /dev/null +++ b/include/asm-arm/arch-kirkwood/kw88f6281.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 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*/ +#define CONFIG_SYS_TCLK 200000000 /* 200MHz */ + +#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.4

On 07:16 Thu 23 Apr , Prafulla Wadaskar wrote:
Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:-
- 88F6281-A0 define CONFIG_KW88F6281_A0
- 88F6192-A0 define CONFIG_KW88F6192_A0
Other supported features:-
- get_random_hex() function
- SPI port controller driver
- 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
a general comment please sue tab for indentation not space
Change log: 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
v3: lowlevel_init.S converted to lowlevel_init.c removed BITxx macros, removed entire assembly code Added CONFIG_ARCH_LOWLEVE_INIT support for arm926ejs core updated as per review comments for v2
board/Marvell/include/core.h | 4 + cpu/arm926ejs/kirkwood/Makefile | 49 +++++ cpu/arm926ejs/kirkwood/config.mk | 25 +++ cpu/arm926ejs/kirkwood/dram.c | 57 ++++++ cpu/arm926ejs/kirkwood/kwcore.c | 304 +++++++++++++++++++++++++++++ cpu/arm926ejs/kirkwood/kwcore.h | 112 +++++++++++ cpu/arm926ejs/kirkwood/lowlevel_init.c | 93 +++++++++ cpu/arm926ejs/kirkwood/timer.c | 165 ++++++++++++++++ cpu/arm926ejs/start.S | 7 +- drivers/serial/kirkwood_serial.c | 187 ++++++++++++++++++ drivers/spi/Makefile | 1 + drivers/spi/kirkwood_spi.c | 199 +++++++++++++++++++ include/asm-arm/arch-kirkwood/kirkwood.h | 140 +++++++++++++ include/asm-arm/arch-kirkwood/kw88f6192.h | 37 ++++ include/asm-arm/arch-kirkwood/kw88f6281.h | 37 ++++
} else
temp &= ~1<<4;
writel(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");
sorry I've forget about it precedently btw please add a doc about all this env var
if (env && ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0)))
temp &= ~1<<24;
else
temp |= 1<<24;
/* enable L2C - Set bit 22 */
env = getenv("disL2Cache");
if (!env || ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0)))
temp |= 1<<22;
else
temp &= ~1<<22;
asm("mcr p15, 1, %0, c15, c1, 0": :"r"(temp));
please use set/get_cr
/* Enable i cache */
we have a cache management framework now please take a look on the lib_arm/cache-cp15.c
asm("mrc p15, 0, %0, c1, c0, 0":"=r"(temp));
temp |= 1<<12;
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 &= ~1<<13;
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..feec86b --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.h
asm volatile("mcr p15, 1, %0, c15, c1, 0 @ writefr exfr"
: : "r" (val) : "cc");
isb();
+}
+/*
- Invalidate L2 Cache using co-proc instruction
- */
+static inline void invalidate_l2_cache(void)
we need to have the same api for l2_cache management so please add it in include/asm-arm/cache.h
+{
unsigned int val=0;
asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache"
: : "r" (val) : "cc");
isb();
+}
+/*
- functions
- */
+void reset_cpu(unsigned long ignored); +unsigned char get_random_hex(void); +unsigned int kw_sdram_bar(enum memory_bank bank); +unsigned int kw_sdram_bs(enum 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.c b/cpu/arm926ejs/kirkwood/lowlevel_init.c new file mode 100644 index 0000000..21bfc81 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/lowlevel_init.c @@ -0,0 +1,93 @@ +/*
- (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
- */
I'm not a fan of c init but if you prefer ok
+#include <config.h>
+void kw_cpu_if_pre_init(void) +{
u32 reg;
+#ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8
/*
* Configures the I/O voltage of the pads connected to Egigabit
* Ethernet interface to 1.8V
* By defult it is set to 3.3V
*/
reg = readl(KW_REG_MPP_OUT_DRV_REG);
reg |= 1 << 7;
writel(KW_REG_MPP_OUT_DRV_REG, ®);
+#endif +#ifdef CONFIG_KIRKWOOD_EGIGA_INIT
/*
* 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
*/
reg = readl((KW_EGIGA0_BASE + 0x44c)); /* PORT_SERIAL_CONTROL1_REG */
reg &= ~(1 << 4); /* Clear PortReset Bit */
writel((KW_EGIGA0_BASE + 0x44c), ®); /* PORT_SERIAL_CONTROL1_REG */
* so must be done prior to DDR operation
*/
kw_cpu_if_pre_init();
+} diff --git a/cpu/arm926ejs/kirkwood/timer.c b/cpu/arm926ejs/kirkwood/timer.c new file mode 100644 index 0000000..c6e1a26 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/timer.c @@ -0,0 +1,165 @@
as I've ask for the ARM925T timer update please provice the precision and resolution on you timer in the code
+/*
- 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)
please add a space before and after the '*' and so on
+#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) 1<<1 +#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 {
please no Uppercase
TIMER0 = 0,
TIMER1,
WATCHDOG
+} KW_CNTMR_ID;
+#define READ_TIMER (readl(CNTMR_VAL_REG(UBOOT_CNTR))/(CONFIG_SYS_TCLK/1000))
please add a space before and after the '/'
+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 = readl(CNTMR_VAL_REG(UBOOT_CNTR));
+} diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index ed4932a..520dcef 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -201,7 +201,7 @@ _start_armboot:
*/ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined (CONFIG_ARCH_LOWLEVEL_INIT)
we will call the ARCH_LOWLEVEL_INIT only if we do not skip the the LOWLEVEL INIT
cpu_init_crit: /* * flush v4 I/D caches @@ -224,7 +224,12 @@ cpu_init_crit: * Go setup Memory and board specific bits prior to relocation. */ mov ip, lr /* perserve link reg across call */ +#ifdef CONFIG_ARCH_LOWLEVEL_INIT
bl arch_lowlevel_init /* go setup arch specific init */
+#endif /* CONFIG_ARCH_LOWLEVEL_INIT */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl lowlevel_init /* go setup pll,mux,memory */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ mov lr, ip /* restore link */ mov pc, lr /* back to my caller */ #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 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
please use the same CONFIG_ as the kernel
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 1<<0 /* fifo enable */ +#define FCR_RXSR 1<<1 /* receiver soft reset */ +#define FCR_TXSR 1<<2 /* transmitter soft reset */ +#define MCR_RTS 1<<1 /* 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 1<<0 /* Data ready */ +#define LSR_OE 1<<1 /* Overrun */ +#define LSR_PE 1<<2 /* Parity error */ +#define LSR_FE 1<<3 /* Framing error */ +#define LSR_BI 1<<4 /* Break */ +#define LSR_THRE 1<<5 /* Xmit holding register empty */ +#define LSR_TEMT 1<<6 /* Xmitter empty */ +#define LSR_ERR 1<<7 /* Error */
+/* useful defaults for LCR*/ +#define LCR_8N1 LCR_WLS_8 | LCR_1_STB
please move this macro to a header as include/asm/arch/serial.h as example
+/* 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)
please no upper case and please add static, this function is not use outside
+{
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);
+}
- 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)
please move this to a header include/asm/arch/spi.h as example
+#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;
writel(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);
writel(KW_REG_SPI_CONFIG, 0x00000210 | data);
writel(KW_REG_SPI_IRQ_CAUSE, 0x00000001);
writel(KW_REG_SPI_IRQ_MASK, 0x00000000);
/* program mpp registers to select SPI_CSn */
if (cs)
writel(KW_REG_MPP_CONTROL0,
((readl(KW_REG_MPP_CONTROL0) & 0x0fffffff) |
0x20000000));
else
writel(KW_REG_MPP_CONTROL0,
((readl(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) +{
writel_set_bits(KW_REG_SPI_CTRL, 1<<0);
I prefer writel(t, readl(t) |Â 1);
+}
+void spi_cs_deactivate(struct spi_slave *slave) +{
writel_reset_bits(KW_REG_SPI_CTRL, 1<<0);
please add a space before and after '<<'
+}
+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;
please no upper case
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) {
please no dead code
/*1 byte xfer mode */
writel_reset_bits(KW_REG_SPI_CONFIG, 1<<5);
/* Shift data so it's msb-justified */
if (dout) {
tmpdout = *(u32 *) dout & 0x0ff;
}
} else {
/*2 byte xfer mode */
writel_set_bits(KW_REG_SPI_CONFIG, 1<<5);
/* Shift data so it's msb-justified */
if (dout) {
tmpdout = *(u32 *) dout & 0x0ffff;
}
}
writel(KW_REG_SPI_IRQ_CAUSE, 0x0); /* clear bit */
writel(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 (readl(KW_REG_SPI_IRQ_CAUSE)) {
isRead = 1;
tmpdin = readl(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;
- 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
+#if defined (__ARMEL__) +#define LE +#else +#define BE +#endif /* __ARMEL__ */
no need please remove
+#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_DEVICE_ID (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))
please add a space before and after '+' '*'
+#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)
+#define KW_REG_PCIE_BASE (0x40000)
+/*
- Macros
- CPU architecture dependent I/O read/write
- */
+#define writel(addr, data) \
- (*((volatile unsigned int*)(KW_REGISTER(addr))) \
= (unsigned int)WORD_SWAP((data)))
no need please use generic arm/io.h (mandatory)
+#define readl(addr) \
- (WORD_SWAP(*((volatile unsigned int*)(KW_REGISTER(addr)))))
+#define writel_set_bits(adr, bits) (writel(adr, readl(adr)\
| ((unsigned int)WORD_SWAP(bits))))
+#define writel_reset_bits(adr, bits) (writel(adr, readl(adr)\
& ~((unsigned int)WORD_SWAP(bits))))
+/*
- Error codes
- */
+#define KW_ERROR (-1) +#define KW_OK (0)
no need please remove
Best Regards, J.

Kirkwood family controllers are highly integrated SOCs based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
SOC versions supported:- 1) 88F6281-A0 define CONFIG_KW88F6281_A0 2) 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 --- Change log: 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
v3: lowlevel_init.S converted to lowlevel_init.c removed BITxx macros, removed entire assembly code Added CONFIG_ARCH_LOWLEVE_INIT support for arm926ejs core updated as per review commens for v2
v4: updated as per review comments for v3 print_cpuinfo used to display Soc info arch_misc_init support created and used for lib_arm mandatory readl/write macros used asm/cache.h asm/arch/spi.h asm//arch/serial.h created and used
cpu/arm926ejs/kirkwood/Makefile | 50 +++++ cpu/arm926ejs/kirkwood/config.mk | 25 +++ cpu/arm926ejs/kirkwood/dram.c | 57 ++++++ cpu/arm926ejs/kirkwood/kwcore.c | 284 +++++++++++++++++++++++++++++ cpu/arm926ejs/kirkwood/kwcore.h | 99 ++++++++++ cpu/arm926ejs/kirkwood/lowlevel_init.S | 43 +++++ cpu/arm926ejs/kirkwood/timer.c | 159 ++++++++++++++++ cpu/arm926ejs/start.S | 9 +- drivers/serial/Makefile | 1 + drivers/serial/kirkwood_serial.c | 128 +++++++++++++ drivers/spi/Makefile | 1 + drivers/spi/kirkwood_spi.c | 167 +++++++++++++++++ include/asm-arm/arch-kirkwood/kirkwood.h | 118 ++++++++++++ include/asm-arm/arch-kirkwood/kw88f6192.h | 37 ++++ include/asm-arm/arch-kirkwood/kw88f6281.h | 37 ++++ include/asm-arm/arch-kirkwood/serial.h | 89 +++++++++ include/asm-arm/arch-kirkwood/spi.h | 39 ++++ include/asm-arm/cache.h | 49 +++++ include/asm-arm/config.h | 4 + include/common.h | 1 + lib_arm/board.c | 4 + 21 files changed, 1399 insertions(+), 2 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 create mode 100644 include/asm-arm/arch-kirkwood/serial.h create mode 100644 include/asm-arm/arch-kirkwood/spi.h create mode 100644 include/asm-arm/cache.h
diff --git a/cpu/arm926ejs/kirkwood/Makefile b/cpu/arm926ejs/kirkwood/Makefile new file mode 100644 index 0000000..781a3c6 --- /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..9abdca2 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/dram.c @@ -0,0 +1,57 @@ +/* + * (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 KW_REG_CPUCS_WIN_BAR(x) (KW_REGISTER(0x1500) + (x * 0x08)) +#define KW_REG_CPUCS_WIN_SZ(x) (KW_REGISTER(0x1504) + (x * 0x08)) +/* + * kw_sdram_bar - reads SDRAM Base Address Register + */ +u32 kw_sdram_bar(enum memory_bank bank) +{ + u32 result = 0; + u32 enable = 0x01 & readl(KW_REG_CPUCS_WIN_SZ(bank)); + + if ((!enable) || (bank > BANK3)) + return 0; + + result = readl(KW_REG_CPUCS_WIN_BAR(bank)); + return result; +} + +/* + * kw_sdram_bs - reads SDRAM Bank size + */ +u32 kw_sdram_bs(enum memory_bank bank) +{ + u32 result = 0; + u32 enable = 0x01 & readl(KW_REG_CPUCS_WIN_SZ(bank)); + + if ((!enable) || (bank > BANK3)) + return 0; + result = 0xff000000 & readl(KW_REG_CPUCS_WIN_SZ(bank)); + result += 0x01000000; + return result; +} diff --git a/cpu/arm926ejs/kirkwood/kwcore.c b/cpu/arm926ejs/kirkwood/kwcore.c new file mode 100644 index 0000000..9eaaab6 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.c @@ -0,0 +1,284 @@ +/* + * (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) +{ + writel(readl(KW_REG_CPU_RSTOUTN_MASK) | 1 << 2, + KW_REG_CPU_RSTOUTN_MASK); + writel(readl(KW_REG_CPU_SYS_SOFT_RST) | 1, KW_REG_CPU_SYS_SOFT_RST); + 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]; + + /* + * in case of 88F6281/88F6192 A0, + * 1<<7 need to reset to generate random values in KW_REG_UNDOC_0x1470 + * Soc reg offsets KW_REG_UNDOC_0x1470 and KW_REG_UNDOC_0x1478 are reserved regs and + * Does not have names at this moment (no errata available) + */ + writel(readl(KW_REG_UNDOC_0x1478) | 1 << 7, KW_REG_UNDOC_0x1478); + for (i = 0; i < 16; i++) { + inbuf[i] = readl(KW_REG_UNDOC_0x1470); + } + md5((u8 *) inbuf, 64, outbuf); + return outbuf[outbuf[7] % 0x0f]; +} + +/* + * Window Size + * Used with the Base register to set the address window size and location. + * Must be programmed from LSB to MSB as sequence of 1’s followed by + * sequence of 0’s. The number of 1’s specifies the size of the window in + * 64 KByte granularity (e.g., a value of 0x00FF specifies 256 = 16 MByte). + * NOTE: A value of 0x0 specifies 64-KByte size. + */ +static unsigned int kw_winctrl_calcsize(unsigned int sizeval) +{ + int i; + unsigned int j = 0; + + for (i = 0; i < (sizeval / 0x10000); i++) { + j |= 1 << i; + } + return (0x0000ffff & j); +} + +/* prepares data to be loaded in win_Ctrl register */ +#define KWCPU_WIN_CTRL_DATA(size, target, attr, en) (en | target<<4 \ + | attr<<8 | kw_winctrl_calcsize(size)<<16) + +/* + * kw_config_adr_windows - Configure address Windows + * + * There are 7 address windows supported by Kirkwood Soc to addess different + * devices. Each window can be configured for size, BAR and remap addr + * Below configuration is standard for most of the cases + * + * Reference Documentation: + * Mbus-L to Mbus Bridge Registers Configuration. + * (Sec 25.1 and 25.3 of Datasheet) + */ +int kw_config_adr_windows(void) +{ + writel(KWCPU_WIN_CTRL_DATA(0xc0000, KWCPU_TARGET_PCIE, + KWCPU_ATTR_PCIE_MEM, KWCPU_WIN_ENABLE), + KW_REG_WIN_CTRL(0)); + + writel(0x90000000, KW_REG_WIN_BASE(0)); + writel(0x90000000, KW_REG_WIN_REMAP_LOW(0)); + writel(0x00000000, KW_REG_WIN_REMAP_HIGH(0)); + + writel(KWCPU_WIN_CTRL_DATA(0x70000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_NANDFLASH, KWCPU_WIN_ENABLE), + KW_REG_WIN_CTRL(1)); + writel(0xF9000000, KW_REG_WIN_BASE(1)); + writel(0xF9000000, KW_REG_WIN_REMAP_LOW(1)); + writel(0x00000000, KW_REG_WIN_REMAP_HIGH(1)); + + writel(KWCPU_WIN_CTRL_DATA(0x80000, KWCPU_TARGET_PCIE, + KWCPU_ATTR_PCIE_IO, KWCPU_WIN_ENABLE), + KW_REG_WIN_CTRL(2)); + writel(0xF0000000, KW_REG_WIN_BASE(2)); + writel(0xC0000000, KW_REG_WIN_REMAP_LOW(2)); + writel(0x00000000, KW_REG_WIN_REMAP_HIGH(2)); + + writel(KWCPU_WIN_CTRL_DATA(0x80000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_SPIFLASH, KWCPU_WIN_ENABLE), + KW_REG_WIN_CTRL(3)); + writel(0xF8000000, KW_REG_WIN_BASE(3)); + writel(0x00000000, KW_REG_WIN_REMAP_LOW(3)); + writel(0x00000000, KW_REG_WIN_REMAP_HIGH(3)); + + writel(KWCPU_WIN_CTRL_DATA(0x80000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_BOOTROM, KWCPU_WIN_ENABLE), + KW_REG_WIN_CTRL(4)); + writel(0xFF000000, KW_REG_WIN_BASE(4)); + writel(0x00000000, KW_REG_WIN_REMAP_LOW(4)); + writel(0x00000000, KW_REG_WIN_REMAP_HIGH(4)); + + writel(KWCPU_WIN_CTRL_DATA(0xb0000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_SPIFLASH, KWCPU_WIN_DISABLE), + KW_REG_WIN_CTRL(5)); + writel(0xE8000000, KW_REG_WIN_BASE(5)); + writel(0x00000000, KW_REG_WIN_REMAP_LOW(5)); + writel(0x00000000, KW_REG_WIN_REMAP_HIGH(5)); + + writel(KWCPU_WIN_CTRL_DATA(0xb0000, KWCPU_TARGET_MEMORY, + KWCPU_ATTR_BOOTROM, KWCPU_WIN_DISABLE), + KW_REG_WIN_CTRL(6)); + writel(0xF0000000, KW_REG_WIN_BASE(6)); + writel(0x00000000, KW_REG_WIN_REMAP_LOW(6)); + writel(0x00000000, KW_REG_WIN_REMAP_HIGH(6)); + + writel(KWCPU_WIN_CTRL_DATA(0x0, KWCPU_TARGET_SASRAM, KWCPU_ATTR_SASRAM, + KWCPU_WIN_ENABLE), KW_REG_WIN_CTRL(7)); + writel(0xFB000000, KW_REG_WIN_BASE(7)); + writel(0x00000000, KW_REG_WIN_REMAP_LOW(7)); + writel(0x00000000, KW_REG_WIN_REMAP_HIGH(7)); + + return 0; +} + +/* + * kw_config_gpio - GPIO configuration + */ +void kw_config_gpio(u32 gpp0_oe_val, u32 gpp1_oe_val, u32 gpp0_oe, u32 gpp1_oe) +{ + /* Init GPIOS to default values as per board requirement */ + writel(gpp0_oe_val, KW_REG_GPP0_DATA_OUT); + writel(gpp1_oe_val, KW_REG_GPP1_DATA_OUT); + writel(gpp0_oe, KW_REG_GPP0_DATA_OUT_EN); + writel(gpp1_oe, KW_REG_GPP1_DATA_OUT_EN); +} + +/* + * kw_config_mpp - Multi-Purpose Pins Functionality configuration + * + * Each MPP can be configured to different functionality through + * MPP control register, ref (sec 6.1 of kirkwood h/w specification) + * + * There are maximum 64 Multi-Pourpose Pins on Kirkwood + * Each MPP functionality can be configuration by a 4bit value + * of MPP control reg, the value and associated functionality depends + * upon used SoC varient + */ +int kw_config_mpp(u32 mpp0_7, u32 mpp8_15, u32 mpp16_23, u32 mpp24_31, + u32 mpp32_39, u32 mpp40_47, u32 mpp48_55) +{ + /* program mpp registers */ + writel(mpp0_7, KW_REG_MPP_CONTROL0); + writel(mpp8_15, KW_REG_MPP_CONTROL1); + writel(mpp16_23, KW_REG_MPP_CONTROL2); + writel(mpp24_31, KW_REG_MPP_CONTROL3); + writel(mpp32_39, KW_REG_MPP_CONTROL4); + writel(mpp40_47, KW_REG_MPP_CONTROL5); + writel(mpp48_55, KW_REG_MPP_CONTROL6); + return 0; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + char *name = "Unknown"; + + switch (readl(KW_REG_DEVICE_ID) & 0x03) { + case 1: + name = "88F6192_A0"; + break; + case 2: + name = "88F6281_A0"; + break; + default: + break; + } + printf("SoC: Kirkwood %s\n", name); + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + +static void kw_basic_init(void) +{ + u32 reg; + + kw_config_adr_windows(); + +#ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8 + /* + * Configures the I/O voltage of the pads connected to Egigabit + * Ethernet interface to 1.8V + * By defult it is set to 3.3V + */ + reg = readl(KW_REG_MPP_OUT_DRV_REG); + reg |= 1 << 7; + writel((u32) & reg, KW_REG_MPP_OUT_DRV_REG); +#endif +#ifdef CONFIG_KIRKWOOD_EGIGA_INIT + /* + * 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 + */ + reg = readl((KW_EGIGA0_BASE + 0x44c)); /* PORT_SERIAL_CONTROL1_REG */ + reg &= ~(1 << 4); /* Clear PortReset Bit */ + writel((u32) & reg, (KW_EGIGA0_BASE + 0x44c)); /* PORT_SERIAL_CONTROL1_REG */ + reg = readl((KW_EGIGA1_BASE + 0x44c)); /* PORT_SERIAL_CONTROL1_REG */ + reg &= ~(1 << 4); /* Clear PortReset Bit */ + writel((u32) & reg, (KW_EGIGA1_BASE + 0x44c)); /* PORT_SERIAL_CONTROL1_REG */ +#endif +#ifdef CONFIG_KIRKWOOD_PCIE_INIT + /* + * Enable PCI Express Port0 + */ + reg = readl(KW_REG_CPU_CTRL_STAT); + reg |= 1 << 0; /* Set PEX0En Bit */ + writel((u32) & reg, KW_REG_CPU_CTRL_STAT); +#endif +} + +/* + * SOC specific misc init + */ +int arch_misc_init(void) +{ + volatile u32 temp; + + kw_basic_init(); + + /*CPU streaming & write allocate */ + temp = readfr_extra_feature_reg(); + temp &= ~1 << 28; /* disable wr alloc */ + writefr_extra_feature_reg(temp); + + temp = readfr_extra_feature_reg(); + temp &= ~1 << 29; /* streaming disabled */ + writefr_extra_feature_reg(temp); + + /* L2Cache settings */ + temp = readfr_extra_feature_reg(); + /* Disable L2C pre fetch - Set bit 24 */ + temp |= 1 << 24; + /* enable L2C - Set bit 22 */ + temp |= 1 << 22; + writefr_extra_feature_reg(temp); + + icache_enable(); + /* Change reset vector to address 0x0 */ + temp = get_cr(); + set_cr(temp & ~CR_V); + + return (0); +} diff --git a/cpu/arm926ejs/kirkwood/kwcore.h b/cpu/arm926ejs/kirkwood/kwcore.h new file mode 100644 index 0000000..fae769d --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.h @@ -0,0 +1,99 @@ +/* + * (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 + +#include <asm/system.h> + +#ifndef __ASSEMBLY__ +enum memory_bank { + BANK0, + BANK1, + BANK2, + BANK3 +}; + +enum kwcpu_winen { + KWCPU_WIN_DISABLE, + KWCPU_WIN_ENABLE +}; + +enum kwcpu_target { + KWCPU_TARGET_RESERVED, + KWCPU_TARGET_MEMORY, + KWCPU_TARGET_1RESERVED, + KWCPU_TARGET_SASRAM, + KWCPU_TARGET_PCIE +}; + +enum kwcpu_attrib { + KWCPU_ATTR_SASRAM = 0x01, + KWCPU_ATTR_NANDFLASH = 0x2f, + KWCPU_ATTR_SPIFLASH = 0x1e, + KWCPU_ATTR_BOOTROM = 0x1d, + KWCPU_ATTR_PCIE_IO = 0xe0, + KWCPU_ATTR_PCIE_MEM = 0xe8 +}; + +/* + * read feroceon/sheeva core extra feature register + * using co-proc instruction + */ +static inline unsigned int readfr_extra_feature_reg(void) +{ + unsigned int val; + asm volatile ("mrc p15, 1, %0, c15, c1, 0 @ readfr exfr":"=r" + (val)::"cc"); + return val; +} + +/* + * write feroceon/sheeva core extra feature register + * using co-proc instruction + */ +static inline void writefr_extra_feature_reg(unsigned int val) +{ + asm volatile ("mcr p15, 1, %0, c15, c1, 0 @ writefr exfr"::"r" + (val):"cc"); + isb(); +} + +/* + * functions + */ +void reset_cpu(unsigned long ignored); +unsigned char get_random_hex(void); +unsigned int kw_sdram_bar(enum memory_bank bank); +unsigned int kw_sdram_bs(enum memory_bank bank); +int kw_config_adr_windows(void); +void kw_config_gpio(unsigned int gpp0_oe_val, unsigned int gpp1_oe_val, + unsigned int gpp0_oe, unsigned int gpp1_oe); +int kw_config_mpp(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); +#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..d81ad05 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/lowlevel_init.S @@ -0,0 +1,43 @@ +/* + * (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> +#include <asm/cache.h> + + .globl arch_lowlevel_init +arch_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] + + /* Enable L2 cache in write through mode */ + ldr r1, = KW_REG_CPU_L2_CONFIG + ldr r2, [r1] + orr r2, r2, #0x18 + str r2, [r1] + + asm_invalidate_l2_cache + + mov pc, lr diff --git a/cpu/arm926ejs/kirkwood/timer.c b/cpu/arm926ejs/kirkwood/timer.c new file mode 100644 index 0000000..40b9aa0 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/timer.c @@ -0,0 +1,159 @@ +/* + * 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) 1<<1 +#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 + +#define READ_TIMER (readl(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 = readl(CNTMR_VAL_REG(UBOOT_CNTR)); + delayticks = (usec * (CONFIG_SYS_TCLK / 1000000)); + + if (current < delayticks) { + delayticks -= current; + while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) < current) ; + while ((TIMER_LOAD_VAL - delayticks) < + readl(CNTMR_VAL_REG(UBOOT_CNTR))) ; + } else { + while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) > + (current - delayticks)) ; + } +} + +/* + * init the counter + */ +int timer_init(void) +{ + unsigned int cntmrCtrl; + + /* load value onto counter\timer */ + writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR)); + writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); + + /* set the counter to load in the first time */ + writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); + + /* set control for timer \ cunter and enable */ + /* read control register */ + cntmrCtrl = readl(CNTMR_CTRL_REG); + cntmrCtrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR); /* enable cnt\timer */ + cntmrCtrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR); /* Auto mode */ + + writel(cntmrCtrl, CNTMR_CTRL_REG); + + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + return 0; +} diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index ed4932a..bdbb7e0 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -139,7 +139,7 @@ reset: * we do sys-critical inits only at reboot, * not when booting from ram! */ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined (CONFIG_ARCH_LOWLEVEL_INIT) bl cpu_init_crit #endif
@@ -201,7 +201,7 @@ _start_armboot: * ************************************************************************* */ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined (CONFIG_ARCH_LOWLEVEL_INIT) cpu_init_crit: /* * flush v4 I/D caches @@ -224,7 +224,12 @@ cpu_init_crit: * Go setup Memory and board specific bits prior to relocation. */ mov ip, lr /* perserve link reg across call */ +#ifdef CONFIG_ARCH_LOWLEVEL_INIT + bl arch_lowlevel_init /* go setup arch specific init */ +#endif /* CONFIG_ARCH_LOWLEVEL_INIT */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl lowlevel_init /* go setup pll,mux,memory */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ mov lr, ip /* restore link */ mov pc, lr /* back to my caller */ #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index bb99a34..8003447 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_SERIAL) += 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..2f79d59 --- /dev/null +++ b/drivers/serial/kirkwood_serial.c @@ -0,0 +1,128 @@ +/* + * 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> +#include <asm/arch/serial.h> + +/* static variables */ +#if defined (CONFIG_CONS_INDEX) /* comes from board config */ +#if (CONFIG_CONS_INDEX == 0 ) +static volatile struct kw_uart_port *p_uart_port = + (void *)KW_REGISTER(KW_UART0_BASE); +#elif (CONFIG_CONS_INDEX == 1 ) +static volatile struct 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); +} + +static void kw_uart_putc(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') + kw_uart_putc('\r'); + + kw_uart_putc(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..f7a70ce --- /dev/null +++ b/drivers/spi/kirkwood_spi.c @@ -0,0 +1,167 @@ +/* + * (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> +#include <asm/arch/spi.h> + +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; + + writel(0x00000002, KW_REG_SPI_CTRL); + /* program spi clock prescaller using max_hz */ + data = ((CONFIG_SYS_TCLK / 2) / max_hz) & 0x0000000f; + debug("data = 0x%08x \n", data); + writel(0x00000210 | data, KW_REG_SPI_CONFIG); + writel(0x00000001, KW_REG_SPI_IRQ_CAUSE); + writel(0x00000000, KW_REG_SPI_IRQ_MASK); + + /* program mpp registers to select SPI_CSn */ + if (cs) + writel((readl(KW_REG_MPP_CONTROL0) & 0x0fffffff) | + 0x20000000, KW_REG_MPP_CONTROL0); + else + writel((readl(KW_REG_MPP_CONTROL0) & 0xfffffff0) | + 0x00000002, KW_REG_MPP_CONTROL0); + + 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) +{ + writel(readl(KW_REG_SPI_CTRL) | 1, KW_REG_SPI_CTRL); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + writel(readl(KW_REG_SPI_CTRL) & ~1, KW_REG_SPI_CTRL); +} + +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; + /*1 byte xfer mode */ + writel(readl(KW_REG_SPI_CONFIG) & ~(1 << 5), KW_REG_SPI_CONFIG); + /* Shift data so it's msb-justified */ + if (dout) + tmpdout = *(u32 *) dout & 0x0ff; + + writel(0x0, KW_REG_SPI_IRQ_CAUSE); /* clear bit */ + writel(tmpdout, KW_REG_SPI_DATA_OUT); /* 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 (readl(KW_REG_SPI_IRQ_CAUSE)) { + isread = 1; + tmpdin = readl(KW_REG_SPI_DATA_IN); + debug + ("*** spi_xfer: din %08X ... %08x read\n", + din, tmpdin); + + if (din) { + *((u8 *) din) = (u8) tmpdin; + din += 1; + } + if (dout) + dout += 1; + bitlen -= 8; + } + 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..b94c6cd --- /dev/null +++ b/include/asm-arm/arch-kirkwood/kirkwood.h @@ -0,0 +1,118 @@ +/* + * (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/types.h> +#include <asm/io.h> +#endif /* __ASSEMBLY__ */ + +#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) + +/* undocumented registers */ +#define KW_REG_UNDOC_0x1470 (KW_REGISTER(0x1470)) +#define KW_REG_UNDOC_0x1478 (KW_REGISTER(0x1478)) + +#define KW_UART0_BASE (KW_REGISTER(0x12000)) /* UArt 0 */ +#define KW_UART1_BASE (KW_REGISTER(0x13000)) /* UArt 1 */ + +/* Controler environment registers offsets */ +#define KW_REG_MPP_CONTROL0 (KW_REGISTER(0x10000)) +#define KW_REG_MPP_CONTROL1 (KW_REGISTER(0x10004)) +#define KW_REG_MPP_CONTROL2 (KW_REGISTER(0x10008)) +#define KW_REG_MPP_CONTROL3 (KW_REGISTER(0x1000C)) +#define KW_REG_MPP_CONTROL4 (KW_REGISTER(0x10010)) +#define KW_REG_MPP_CONTROL5 (KW_REGISTER(0x10014)) +#define KW_REG_MPP_CONTROL6 (KW_REGISTER(0x10018)) +#define KW_REG_MPP_SMPL_AT_RST (KW_REGISTER(0x10030)) +#define KW_REG_DEVICE_ID (KW_REGISTER(0x10034)) +#define KW_REG_MPP_OUT_DRV_REG (KW_REGISTER(0x100E0)) + +#define KW_REG_GPP0_DATA_OUT (KW_REGISTER(0x10100)) +#define KW_REG_GPP0_DATA_OUT_EN (KW_REGISTER(0x10104)) +#define KW_REG_GPP0_BLINK_EN (KW_REGISTER(0x10108)) +#define KW_REG_GPP0_DATA_IN_POL (KW_REGISTER(0x1010C)) +#define KW_REG_GPP0_DATA_IN (KW_REGISTER(0x10110)) +#define KW_REG_GPP0_INT_CAUSE (KW_REGISTER(0x10114)) +#define KW_REG_GPP0_INT_MASK (KW_REGISTER(0x10118)) +#define KW_REG_GPP0_INT_LVL (KW_REGISTER(0x1011c)) + +#define KW_REG_GPP1_DATA_OUT (KW_REGISTER(0x10140)) +#define KW_REG_GPP1_DATA_OUT_EN (KW_REGISTER(0x10144)) +#define KW_REG_GPP1_BLINK_EN (KW_REGISTER(0x10148)) +#define KW_REG_GPP1_DATA_IN_POL (KW_REGISTER(0x1014C)) +#define KW_REG_GPP1_DATA_IN (KW_REGISTER(0x10150)) +#define KW_REG_GPP1_INT_CAUSE (KW_REGISTER(0x10154)) +#define KW_REG_GPP1_INT_MASK (KW_REGISTER(0x10158)) +#define KW_REG_GPP1_INT_LVL (KW_REGISTER(0x1015c)) + +#define KW_REG_NAND_READ_PARAM (KW_REGISTER(0x10418)) +#define KW_REG_NAND_WRITE_PARAM (KW_REGISTER(0x1041c)) +#define KW_REG_NAND_CTRL (KW_REGISTER(0x10470)) + +#define KW_REG_WIN_CTRL(x) (KW_REGISTER((0x20000 + (x * 0x10)))) +#define KW_REG_WIN_BASE(x) (KW_REGISTER((0x20004 + (x * 0x10)))) +#define KW_REG_WIN_REMAP_LOW(x) (KW_REGISTER((0x20008 + (x * 0x10)))) +#define KW_REG_WIN_REMAP_HIGH(x) (KW_REGISTER((0x2000c + (x * 0x10)))) + +#define KW_REG_CPU_CONFIG (KW_REGISTER(0x20100)) +#define KW_REG_CPU_CTRL_STAT (KW_REGISTER(0x20104)) +#define KW_REG_CPU_RSTOUTN_MASK (KW_REGISTER(0x20108)) +#define KW_REG_CPU_SYS_SOFT_RST (KW_REGISTER(0x2010C)) +#define KW_REG_CPU_AHB_MBUS_CAUSE_INT (KW_REGISTER(0x20110)) +#define KW_REG_CPU_AHB_MBUS_MASK_INT (KW_REGISTER(0x20114)) +#define KW_REG_CPU_FTDLL_CONFIG (KW_REGISTER(0x20120)) +#define KW_REG_CPU_L2_CONFIG (KW_REGISTER(0x20128)) +#define KW_REG_L2_RAM_TIMING0 (KW_REGISTER(0x20134)) +#define KW_REG_L2_RAM_TIMING1 (KW_REGISTER(0x20138)) + +#define KW_REG_TMR_CTRL (KW_REGISTER(0x20300)) +#define KW_REG_TMR_RELOAD (KW_REGISTER(0x20310)) +#define KW_REG_TMR_VAL (KW_REGISTER(0x20314)) + +#define KW_REG_PCIE_BASE (KW_REGISTER(0x40000)) + +#define KW_EGIGA0_BASE (KW_REGISTER(0x72000)) +#define KW_EGIGA1_BASE (KW_REGISTER(0x76000)) + +#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..270d931 --- /dev/null +++ b/include/asm-arm/arch-kirkwood/kw88f6281.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 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*/ +#define CONFIG_SYS_TCLK 200000000 /* 200MHz */ + +#endif /* _ASM_ARCH_KW88F6281_H */ diff --git a/include/asm-arm/arch-kirkwood/serial.h b/include/asm-arm/arch-kirkwood/serial.h new file mode 100644 index 0000000..59fe56f --- /dev/null +++ b/include/asm-arm/arch-kirkwood/serial.h @@ -0,0 +1,89 @@ +/* + * 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 + */ + +#ifndef __KW_SERIAL_H__ +#define __KW_SERIAL_H__ + +/* registers feilds */ +#define FCR_FIFO_EN 1<<0 /* fifo enable */ +#define FCR_RXSR 1<<1 /* receiver soft reset */ +#define FCR_TXSR 1<<2 /* transmitter soft reset */ +#define MCR_RTS 1<<1 /* 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 1<<0 /* Data ready */ +#define LSR_OE 1<<1 /* Overrun */ +#define LSR_PE 1<<2 /* Parity error */ +#define LSR_FE 1<<3 /* Framing error */ +#define LSR_BI 1<<4 /* Break */ +#define LSR_THRE 1<<5 /* Xmit holding register empty */ +#define LSR_TEMT 1<<6 /* Xmitter empty */ +#define LSR_ERR 1<<7 /* 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 */ +struct kw_uart_port { + 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]; +}; + +/* aliases - for registers which has the same offsets */ +#define thr rbr +#define iir fcr +#define dll rbr +#define dlm ier + +#endif /* __KW_SERIAL_H__ */ diff --git a/include/asm-arm/arch-kirkwood/spi.h b/include/asm-arm/arch-kirkwood/spi.h new file mode 100644 index 0000000..0fd9131 --- /dev/null +++ b/include/asm-arm/arch-kirkwood/spi.h @@ -0,0 +1,39 @@ +/* + * (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 + */ + +#ifndef __KW_SPI_H__ +#define __KW_SPI_H__ + +/* SPI Registers on kirkwood SOC */ +#define KW_REG_SPI_CTRL KW_REGISTER(0x10600) +#define KW_REG_SPI_CONFIG KW_REGISTER(0x10604) +#define KW_REG_SPI_DATA_OUT KW_REGISTER(0x10608) +#define KW_REG_SPI_DATA_IN KW_REGISTER(0x1060c) +#define KW_REG_SPI_IRQ_CAUSE KW_REGISTER(0x10610) +#define KW_REG_SPI_IRQ_MASK KW_REGISTER(0x10614) + +#define KW_SPI_TIMEOUT 10000 +#endif __KW_SPI_H__ diff --git a/include/asm-arm/cache.h b/include/asm-arm/cache.h new file mode 100644 index 0000000..07eef4c --- /dev/null +++ b/include/asm-arm/cache.h @@ -0,0 +1,49 @@ +/* + * (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 _ASM_CACHE_H +#define _ASM_CACHE_H + +#ifndef __ASSEMBLY__ +#include <asm/system.h> + +/* + * Invalidate L2 Cache using co-proc instruction + */ +static inline void invalidate_l2_cache(void) +{ + unsigned int val=0; + + asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache" + : : "r" (val) : "cc"); + isb(); +} +#else +.macro asm_invalidate_l2_cache + mov r0, #0 + mcr p15, 1, r0, c15, c11, 0 +.endm +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_CACHE_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 diff --git a/include/common.h b/include/common.h index 30fff7d..9e4b859 100644 --- a/include/common.h +++ b/include/common.h @@ -294,6 +294,7 @@ void pciinfo (int, int); #endif #endif
+int arch_misc_init (void); int misc_init_f (void); int misc_init_r (void);
diff --git a/lib_arm/board.c b/lib_arm/board.c index 3dfaec0..7f7c28d 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -390,6 +390,10 @@ void start_armboot (void)
console_init_r (); /* fully init console as a device */
+#if defined(CONFIG_ARCH_MISC_INIT) + /* miscellaneous arch dependent initialisations */ + arch_misc_init (); +#endif #if defined(CONFIG_MISC_INIT_R) /* miscellaneous platform dependent initialisations */ misc_init_r ();

- if ((!enable) || (bank > BANK3))
return 0;
- result = 0xff000000 & readl(KW_REG_CPUCS_WIN_SZ(bank));
- result += 0x01000000;
- return result;
+} diff --git a/cpu/arm926ejs/kirkwood/kwcore.c b/cpu/arm926ejs/kirkwood/kwcore.c new file mode 100644 index 0000000..9eaaab6 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.c
please cpu.c
@@ -0,0 +1,284 @@ +/*
- (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
- */
diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index ed4932a..bdbb7e0 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -139,7 +139,7 @@ reset: * we do sys-critical inits only at reboot, * not when booting from ram! */ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined (CONFIG_ARCH_LOWLEVEL_INIT) bl cpu_init_crit #endif
@@ -201,7 +201,7 @@ _start_armboot:
*/ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined (CONFIG_ARCH_LOWLEVEL_INIT)
NACK
if you skip the lowlevel init you also skip the arch lowlevel_init
if it's permannent arch init please use arch_cpu_init
Best regards, J.

Thanks Jean for your review...
diff --git a/cpu/arm926ejs/kirkwood/kwcore.c b/cpu/arm926ejs/kirkwood/kwcore.c new file mode 100644 index 0000000..9eaaab6 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.c
please cpu.c
Okay I will rename it
*/ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined +(CONFIG_ARCH_LOWLEVEL_INIT)
NACK
if you skip the lowlevel init you also skip the arch lowlevel_init
I got it already, I have encapsulated similar condition at caller function so that even though only ARCH_LOWLEVEL_INIT is define it will not skip it.
if it's permannent arch init please use arch_cpu_init
Is it really lowlevel init, needs to be called before stack/dram init, so please let it be arch_lowlevel_init. I am trying to keep minimal code under arch_lowlevel_init (only few assembly lines) rest I am moving to arch_cpu_init under lib_arm/board.c
Thanks I will send v5 soon
Regards.. Prafulla . .

On 14:41 Sat 02 May , Prafulla Wadaskar wrote:
Thanks Jean for your review...
diff --git a/cpu/arm926ejs/kirkwood/kwcore.c b/cpu/arm926ejs/kirkwood/kwcore.c new file mode 100644 index 0000000..9eaaab6 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.c
please cpu.c
Okay I will rename it
*/ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined +(CONFIG_ARCH_LOWLEVEL_INIT)
NACK
if you skip the lowlevel init you also skip the arch lowlevel_init
I got it already, I have encapsulated similar condition at caller function so that even though only ARCH_LOWLEVEL_INIT is define it will not skip it.
if it's permannent arch init please use arch_cpu_init
Is it really lowlevel init, needs to be called before stack/dram init, so please let it be arch_lowlevel_init. I am trying to keep minimal code under arch_lowlevel_init (only few assembly lines) rest I am moving to arch_cpu_init under lib_arm/board.c
the arch_cpu_init is the first init in c and I want the current design clear If you choice to skip the lowlevel_init you will skip all lowlevel_init with no exception as I've in mind to regroup all start.S
Best Regards, J.

-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Sunday, May 03, 2009 2:02 PM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Prabhanjan Sarnaik; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v4] Marvell Kirkwood family SOC support
On 14:41 Sat 02 May , Prafulla Wadaskar wrote:
Thanks Jean for your review...
diff --git a/cpu/arm926ejs/kirkwood/kwcore.c b/cpu/arm926ejs/kirkwood/kwcore.c new file mode 100644 index 0000000..9eaaab6 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.c
please cpu.c
Okay I will rename it
*/ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined +(CONFIG_ARCH_LOWLEVEL_INIT)
NACK
if you skip the lowlevel init you also skip the arch lowlevel_init
I got it already, I have encapsulated similar condition at
caller function so that even though only ARCH_LOWLEVEL_INIT is define it will not skip it.
if it's permannent arch init please use arch_cpu_init
Is it really lowlevel init, needs to be called before
stack/dram init, so please let it be arch_lowlevel_init.
I am trying to keep minimal code under arch_lowlevel_init (only few assembly lines) rest I am moving to arch_cpu_init under lib_arm/board.c
the arch_cpu_init is the first init in c and I want the current design clear If you choice to skip the lowlevel_init you will skip all lowlevel_init with no exception as I've in mind to regroup all start.S
In this case....I think Let's have arch_cpu_init (c function call) to take care of Soc Specific init and Let's use lowlevel_init instead of arch_lowlevel_init for any configuration before stack init. arch_lowlevel_init should be assembly code similar to lowlevel_init and is invoking should be similar
In case of kirkwood specially in some board version if we use Kirkwood without internal BootROM we need to configure DRAM before setting stack in DRAM, this should be done in lowlevel_init.S i.e. lowlevel_init or arch_lowlevel_init jump
What do you think? Or what is in your mind about regroup start.S?
Regards.. Prafulla . .
Best Regards, J.

Dear Prafulla Wadaskar,
In message 73173D32E9439E4ABB5151606C3E19E201CD5CF545@SC-VEXCH1.marvell.com you wrote:
In case of kirkwood specially in some board version if we use Kirkwood without internal BootROM we need to configure DRAM before setting stack in DRAM, this should be done in lowlevel_init.S i.e. lowlevel_init or arch_lowlevel_init jump
This may be what many ARM systems are currently doing, but actually it is not what I'd like to see.
Normally DRAM should only be initialized right before relocation to RAM, i. e. relatively late in the boot sequence, and definitely by C code (at a time, when you have printf() and friends for debugging).
Also, normally the actual RAM size should be auto-detected using the utilities provided by common/memsize.c, etc. [Also, flash sizes should be auto-detected.]
If you don't have any on-chip memory on your system, or any other SRAM etc. that could be used for initial data or stack, then the standard method is to lock (parts of) D-Cache and use this as RAM.
It would be great if such standard procedures would find their way into U-Boot on ARM, too.
[Note that I wrote "I'd like to see", and "normally", and "should". I did not say "must" - I'm a realist, and I know that ARM still has a long way to go to fully recover from the ARMBoot heritage.]
Thanks in advance.
Best regards,
Wolfgang Denk

On 10:16 Sun 03 May , Prafulla Wadaskar wrote:
-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Sunday, May 03, 2009 2:02 PM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Prabhanjan Sarnaik; Ronen Shitrit Subject: Re: [U-Boot] [PATCH v4] Marvell Kirkwood family SOC support
On 14:41 Sat 02 May , Prafulla Wadaskar wrote:
Thanks Jean for your review...
diff --git a/cpu/arm926ejs/kirkwood/kwcore.c b/cpu/arm926ejs/kirkwood/kwcore.c new file mode 100644 index 0000000..9eaaab6 --- /dev/null +++ b/cpu/arm926ejs/kirkwood/kwcore.c
please cpu.c
Okay I will rename it
*/ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined +(CONFIG_ARCH_LOWLEVEL_INIT)
NACK
if you skip the lowlevel init you also skip the arch lowlevel_init
I got it already, I have encapsulated similar condition at
caller function so that even though only ARCH_LOWLEVEL_INIT is define it will not skip it.
if it's permannent arch init please use arch_cpu_init
Is it really lowlevel init, needs to be called before
stack/dram init, so please let it be arch_lowlevel_init.
I am trying to keep minimal code under arch_lowlevel_init (only few assembly lines) rest I am moving to arch_cpu_init under lib_arm/board.c
the arch_cpu_init is the first init in c and I want the current design clear If you choice to skip the lowlevel_init you will skip all lowlevel_init with no exception as I've in mind to regroup all start.S
In this case....I think Let's have arch_cpu_init (c function call) to take care of Soc Specific init and Let's use lowlevel_init instead of arch_lowlevel_init for any configuration before stack init. arch_lowlevel_init should be assembly code similar to lowlevel_init and is invoking should be similar
In case of kirkwood specially in some board version if we use Kirkwood without internal BootROM we need to configure DRAM before setting stack in DRAM, this should be done in lowlevel_init.S i.e. lowlevel_init or arch_lowlevel_init jump
sure but in this case you will have to init everythink as done for ofther ARCH at91 in norflash boot, ixp, pxa etc...
if the dram init is common of the arch the arch_lowlevel_init is the right place, it's board specific lowlevel_init is.
please also note I'm preparing 2 new patch that will introduce board_pre_lowlevel_init and arch_pre_lowlevel_init with the board that use it (already mainline)
What do you think? Or what is in your mind about regroup start.S?
For the start.S I'll take care of this actually nearly all arm share the same start.S and normaly the lowlevel_init is always the same wiht just few specific thinks which will be care by some few callback
Best Regards, J.

This is Marvell's 88F6281_A0 based custom board developed for wireless access point product
This patch is tested for- 1. Boot from DRAM/SPI flash/NFS 2. File transfer using tftp and loadb 3. SPI flash read/write/erase 4. Booting Linux kernel and RFS from SPI flash
Reviewed-by: Ronen Shitrit rshitrit@marvell.com Signed-off-by: Prafulla Wadaskar prafulla@marvell.com --- Change log v2: updated as per first review comments debug_prints updated to debug
v3: updated as per review comments for v2 added mv88f6281gtw_ge.h file removed BITxx macros
MAKEALL | 1 + Makefile | 3 + board/Marvell/mv88f6281gtw_ge/Makefile | 51 +++++++ board/Marvell/mv88f6281gtw_ge/config.mk | 25 ++++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c | 102 +++++++++++++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h | 46 ++++++ board/Marvell/mv88f6281gtw_ge/u-boot.lds | 53 +++++++ include/configs/mv88f6281gtw_ge.h | 175 +++++++++++++++++++++++ 8 files changed, 456 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/mv88f6281gtw_ge/Makefile create mode 100644 board/Marvell/mv88f6281gtw_ge/config.mk create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h create mode 100644 board/Marvell/mv88f6281gtw_ge/u-boot.lds create mode 100644 include/configs/mv88f6281gtw_ge.h
diff --git a/MAKEALL b/MAKEALL index e4eb42b..1caf81d 100755 --- a/MAKEALL +++ b/MAKEALL @@ -504,6 +504,7 @@ LIST_ARM9=" \ cp946es \ cp966 \ lpd7a400 \ + mv88f6281gtw_ge \ mx1ads \ mx1fs2 \ netstar \ diff --git a/Makefile b/Makefile index d2c7c3f..709e4be 100644 --- a/Makefile +++ b/Makefile @@ -2792,6 +2792,9 @@ lpd7a400_config \ lpd7a404_config: unconfig @$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x
+mv88f6281gtw_ge_config: unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs $(@:_config=) Marvell kirkwood + mx1ads_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t mx1ads NULL imx
diff --git a/board/Marvell/mv88f6281gtw_ge/Makefile b/board/Marvell/mv88f6281gtw_ge/Makefile new file mode 100644 index 0000000..8c49a3e --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/Makefile @@ -0,0 +1,51 @@ +# +# (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$(BOARD).a + +COBJS := mv88f6281gtw_ge.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/Marvell/mv88f6281gtw_ge/config.mk b/board/Marvell/mv88f6281gtw_ge/config.mk new file mode 100644 index 0000000..fb29a1b --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/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 +# + +TEXT_BASE = 0x00600000 diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c new file mode 100644 index 0000000..2e789a9 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c @@ -0,0 +1,102 @@ +/* + * (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 <../drivers/net/phy/mv88e61xx.h> +#include <netdev.h> +#include "mv88f6281gtw_ge.h" + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + /* Board Parameters initializations */ + kw_window_ctrl_reg_init(); + kw_gpio_init(MV88F6281GTW_GE_OE_VAL_LOW, + MV88F6281GTW_GE_OE_VAL_HIGH, + MV88F6281GTW_GE_OE_LOW, MV88F6281GTW_GE_OE_HIGH); + + kw_mpp_control_init(MV88F6281GTW_GE_MPP0_7, + MV88F6281GTW_GE_MPP8_15, + MV88F6281GTW_GE_MPP16_23, + MV88F6281GTW_GE_MPP24_31, + MV88F6281GTW_GE_MPP32_39, + MV88F6281GTW_GE_MPP40_47, MV88F6281GTW_GE_MPP48_55); + + /* serial config */ + gd->baudrate = CONFIG_BAUDRATE; + gd->have_console = 1; + /* + * arch number of USED SOC + */ + gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + return 0; +} + +int dram_init(void) +{ + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = kw_sdram_bar(i); + gd->bd->bi_dram[i].size = kw_sdram_bs(i); + } + return 0; +} + +int last_stage_init(void) +{ + return 0; +} + +#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent init */ +int misc_init_r(void) +{ + return kw_misc_init_r(); +} + +void reset_phy(void) +{ +#ifdef CONFIG_MV88E61XX_SWITCH + /* configure and initialize switch */ + struct mv88e61xx_config swcfg = { + .name = "egiga0", + .vlancfg = MV88E61XX_VLANCFG_ROUTER, + .rgmii_delay = MV88E61XX_RGMII_DELAY_EN, + .portstate = MV88E61XX_PORTSTT_FORWARDING, + .cpuport = 5, + .ports_enabled = (PORT(0) | PORT(1) | PORT(2) + | PORT(3) | PORT(4) | PORT(5)) + }; + + mv88e61xx_switch_initialize(&swcfg); +#endif +} + +#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h new file mode 100644 index 0000000..6e91c25 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h @@ -0,0 +1,46 @@ +/* + * (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 __MV88F6281GTW_GE_H +#define __MV88F6281GTW_GE_H + +#define MV88F6281GTW_GE_OE_LOW (~((1<<7) | (1<<20) \ + |(1<<21))) /*enable GLED,RLED */ +#define MV88F6281GTW_GE_OE_HIGH (~((1<<4)|(1<<6)|(1<<7)|(1<<12) \ + |(1<<13)|(1<<16)|(1<<17))) +#define MV88F6281GTW_GE_OE_VAL_LOW (1<<20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH ((1<<6)|(1<<13)|(1<<16)|(1<<17)) + +/* + * Default values for MPP registers + */ +#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000 + +#endif /* __MV88F6281GTW_GE_H */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds new file mode 100644 index 0000000..9695f3f --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata))) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } + _end = .; +} + diff --git a/include/configs/mv88f6281gtw_ge.h b/include/configs/mv88f6281gtw_ge.h new file mode 100644 index 0000000..10f213f --- /dev/null +++ b/include/configs/mv88f6281gtw_ge.h @@ -0,0 +1,175 @@ +/* + * (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 _CONFIG_MV88F6281GTW_GE_H +#define _CONFIG_MV88F6281GTW_GE_H + +/* + * Version number information + */ +#define CONFIG_IDENT_STRING "\nMarvell-MV88F6281GTW_GE-A0" + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* Basic Architecture */ +#define CONFIG_FEROCEON_88FR131 1 /* CPU Core subversion */ +#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */ + +#ifdef CONFIG_KIRKWOOD +#define CONFIG_MD5 /* get_random_hex on krikwood needs MD5 support */ +#define CONFIG_ARCH_LOWLEVEL_INIT /* enable arch_lowlevel_init */ +#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */ +#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */ +#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE Port0 for kernel */ +#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to 1.8V */ +#endif + +/* + * CLKs configurations + */ +#define CONFIG_SYS_HZ 1000 + +/* + * Serial Port configuration + * The following definitions let you select what serial you want to use + * for your console driver. + */ +#define CONFIG_KW_SERIAL +#define CONFIG_CONS_INDEX 0 /*Console on UART0 */ + +#define CONFIG_BAUDRATE 115200 /* console baudrate */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \ + 115200,230400, 460800, 921600 } +/* auto boot */ +#define CONFIG_BOOTDELAY 3 /* default enable autoboot */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CONFIG_BOOTMAPSZ (8<<20) /* Initial Memmap for Linux */ +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS 1 /* enable memory tag */ + +#define CONFIG_SYS_PROMPT "Marvell>> " /* Command Prompt */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ + +sizeof(CONFIG_SYS_PROMPT) + 16) /* Print Buff */ +/* + * Commands configuration + */ +#define CONFIG_CMD_ENV +#define CONFIG_CMD_RUN +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_NET +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_AUTOSCRIPT +#define CONFIG_CMD_MEMORY +#define CONFIG_CMD_BOOTD +#define CONFIG_CMD_SAVEENV +#define CONFIG_CMD_SF + +/* + * Flash configuration + */ +#ifdef CONFIG_CMD_SF +#define CONFIG_SYS_NO_FLASH 1 /* Declare no NOR flash */ +#define CONFIG_SPI_FLASH 1 +#define CONFIG_HARD_SPI 1 +#define CONFIG_KIRKWOOD_SPI 1 +#define CONFIG_SPI_FLASH_MACRONIX 1 +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 +#define CONFIG_ENV_SPI_MAX_HZ 50000000 /*50Mhz */ +#endif + +/* + * Environment variables configurations + */ +#ifdef CONFIG_SPI_FLASH +#define CONFIG_ENV_IS_IN_SPI_FLASH 1 +#define CONFIG_ENV_SIZE 0x10000 /* spi flash block (64k) */ +#define CONFIG_ENV_SECT_SIZE 0x10000 /* _64K */ +#else +#define CONFIG_ENV_IS_NOWHERE 1 /* if env in SDRAM */ +#define CONFIG_ENV_SIZE 0x20000 /* default 128k */ +#endif +#define CONFIG_ENV_ADDR 0x20000 +#define CONFIG_ENV_OFFSET 0x20000 /* env starts here */ + +/* + * Default environment variables + */ +#define CONFIG_BOOTCOMMAND "$(x_bootcmd_kernel); setenv bootargs " \ + "$(x_bootargs) $(x_bootargs_root); bootm 0x6400000;" +#define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console=ttyS0,115200 " \ + "mtdparts=spi0.0:512k(uboot),512k@512k(psm),2m@1m(kernel),13m@3m(rootfs)\0" \ + "x_bootcmd_kernel=cp.b 0xf8100000 0x6400000 0x200000\0" \ + "x_bootargs_root=root=/dev/mtdblock3 ro rootfstype=squashfs\0" + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */ +/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128 + +/* + * Other required minimal configurations + */ +#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() */ +#define CONFIG_NR_DRAM_BANKS 4 +#define CONFIG_STACKSIZE 0x00100000 /* regular stack- 1M */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */ +#define CONFIG_SYS_MEMTEST_START 0x00400000 /* 4M */ +#define CONFIG_SYS_MEMTEST_END 0x007fffff /*(_8M -1) */ +#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ + +/* + * Ethernet Driver configuration + */ +#ifdef CONFIG_CMD_NET +#define CONFIG_NETCONSOLE /* include NetConsole support */ +#define CONFIG_NET_MULTI /* specify more that one ports available */ +#define CONFIG_MII /* expose smi ove miiphy interface */ +#define CONFIG_KIRKWOOD_EGIGA /* Enable kirkwood Gbe Controller Driver */ +#define CONFIG_SYS_FAULT_ECHO_LINK_DOWN /* detect link using phy */ +#define CONFIG_KIRKWOOD_EGIGA_PORTS {TRUE,FALSE} /* enable port 0 only */ +#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ +#endif /* CONFIG_CMD_NET */ + +/* + * Marvell 88Exxxx Switch configurations + */ +#define CONFIG_RESET_PHY_R /* use reset_phy() to init phy/swtich */ +#define CONFIG_MV88E61XX_SWITCH /* Enable mv88e61xx switch driver */ + +#endif /* _CONFIG_MV88F6281GTW_GE_H */ -- 1.5.3.4

On 07:19 Thu 23 Apr , Prafulla Wadaskar wrote:
This is Marvell's 88F6281_A0 based custom board developed for wireless access point product
This patch is tested for-
- Boot from DRAM/SPI flash/NFS
- File transfer using tftp and loadb
- SPI flash read/write/erase
- Booting Linux kernel and RFS from SPI flash
Reviewed-by: Ronen Shitrit rshitrit@marvell.com Signed-off-by: Prafulla Wadaskar prafulla@marvell.com
Change log v2: updated as per first review comments debug_prints updated to debug
v3: updated as per review comments for v2 added mv88f6281gtw_ge.h file removed BITxx macros
first a general comment I do not known if it's your mailer but all tab are converted in whitespace please fix it
MAKEALL | 1 + Makefile | 3 + board/Marvell/mv88f6281gtw_ge/Makefile | 51 +++++++ board/Marvell/mv88f6281gtw_ge/config.mk | 25 ++++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c | 102 +++++++++++++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h | 46 ++++++ board/Marvell/mv88f6281gtw_ge/u-boot.lds | 53 +++++++ include/configs/mv88f6281gtw_ge.h | 175 +++++++++++++++++++++++ 8 files changed, 456 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/mv88f6281gtw_ge/Makefile create mode 100644 board/Marvell/mv88f6281gtw_ge/config.mk create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h create mode 100644 board/Marvell/mv88f6281gtw_ge/u-boot.lds create mode 100644 include/configs/mv88f6281gtw_ge.h
diff --git a/MAKEALL b/MAKEALL index e4eb42b..1caf81d 100755 --- a/MAKEALL +++ b/MAKEALL @@ -504,6 +504,7 @@ LIST_ARM9=" \ cp946es \ cp966 \ lpd7a400 \
mv88f6281gtw_ge \ mx1ads \ mx1fs2 \ netstar \
- 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 <../drivers/net/phy/mv88e61xx.h> +#include <netdev.h> +#include "mv88f6281gtw_ge.h"
+DECLARE_GLOBAL_DATA_PTR;
+int board_init(void) +{
/* Board Parameters initializations */
could explain what you do a few more?
kw_window_ctrl_reg_init();
kw_gpio_init(MV88F6281GTW_GE_OE_VAL_LOW,
MV88F6281GTW_GE_OE_VAL_HIGH,
MV88F6281GTW_GE_OE_LOW, MV88F6281GTW_GE_OE_HIGH);
kw_mpp_control_init(MV88F6281GTW_GE_MPP0_7,
MV88F6281GTW_GE_MPP8_15,
MV88F6281GTW_GE_MPP16_23,
MV88F6281GTW_GE_MPP24_31,
MV88F6281GTW_GE_MPP32_39,
MV88F6281GTW_GE_MPP40_47, MV88F6281GTW_GE_MPP48_55);
from
/* serial config */
gd->baudrate = CONFIG_BAUDRATE;
gd->have_console = 1;
no need please remove
/*
* arch number of USED SOC
*/
gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x00000100;
please be more consistant with the other arm boards RAM_BASE + 0x100
return 0;
+}
+int dram_init(void) +{
int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
gd->bd->bi_dram[i].start = kw_sdram_bar(i);
gd->bd->bi_dram[i].size = kw_sdram_bs(i);
}
return 0;
+}
+int last_stage_init(void) +{
return 0;
+}
no need please remove
+#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent init */ +int misc_init_r(void) +{
return kw_misc_init_r();
+}
if it's really arch late init please create a generic function like arch_late_init or arch_misc_init and call it from lib_arm/board.c
+void reset_phy(void) +{ +#ifdef CONFIG_MV88E61XX_SWITCH
/* configure and initialize switch */
struct mv88e61xx_config swcfg = {
.name = "egiga0",
.vlancfg = MV88E61XX_VLANCFG_ROUTER,
.rgmii_delay = MV88E61XX_RGMII_DELAY_EN,
.portstate = MV88E61XX_PORTSTT_FORWARDING,
.cpuport = 5,
.ports_enabled = (PORT(0) | PORT(1) | PORT(2)
| PORT(3) | PORT(4) | PORT(5))
};
mv88e61xx_switch_initialize(&swcfg);
+#endif +}
please only call reset_phy when the SWITCH is enable. it will reduce the size of u-boot whenyou do not use the switch
+#endif /* CONFIG_MISC_INIT_R */ diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h new file mode 100644 index 0000000..6e91c25 --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h @@ -0,0 +1,46 @@ +/*
- (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 __MV88F6281GTW_GE_H +#define __MV88F6281GTW_GE_H
+#define MV88F6281GTW_GE_OE_LOW (~((1<<7) | (1<<20) \
|(1<<21))) /*enable GLED,RLED */
+#define MV88F6281GTW_GE_OE_HIGH (~((1<<4)|(1<<6)|(1<<7)|(1<<12) \
|(1<<13)|(1<<16)|(1<<17)))
+#define MV88F6281GTW_GE_OE_VAL_LOW (1<<20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH ((1<<6)|(1<<13)|(1<<16)|(1<<17))
+/*
- Default values for MPP registers
- */
+#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000
could explain a few more these value
+#endif /* __MV88F6281GTW_GE_H */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds new file mode 100644 index 0000000..9695f3f --- /dev/null
- 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_MV88F6281GTW_GE_H +#define _CONFIG_MV88F6281GTW_GE_H
+/*
- Version number information
- */
+#define CONFIG_IDENT_STRING "\nMarvell-MV88F6281GTW_GE-A0"
+/*
- High Level Configuration Options (easy to change)
- */
+#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* Basic Architecture */ +#define CONFIG_FEROCEON_88FR131 1 /* CPU Core subversion */ +#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */
+#ifdef CONFIG_KIRKWOOD +#define CONFIG_MD5 /* get_random_hex on krikwood needs MD5 support */ +#define CONFIG_ARCH_LOWLEVEL_INIT /* enable arch_lowlevel_init */ +#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */ +#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */ +#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE Port0 for kernel */ +#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to 1.8V */ +#endif
why? this boards is not a KIRWOOD?
+/*
- CLKs configurations
- */
+#define CONFIG_SYS_HZ 1000
+/*
- Serial Port configuration
- The following definitions let you select what serial you want to use
- for your console driver.
- */
- Default environment variables
- */
+#define CONFIG_BOOTCOMMAND "$(x_bootcmd_kernel); setenv bootargs " \
IIRC please use ${} instead of $()
"$(x_bootargs) $(x_bootargs_root); bootm 0x6400000;"
+#define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console=ttyS0,115200 " \
"mtdparts=spi0.0:512k(uboot),512k@512k(psm),2m@1m(kernel),13m@3m(rootfs)\0" \
he could be usefull to use CONFIG_MTDPARTS
"x_bootcmd_kernel=cp.b 0xf8100000 0x6400000 0x200000\0" \
"x_bootargs_root=root=/dev/mtdblock3 ro rootfstype=squashfs\0"
Best Regards, J.

Hi Jean Thanks for your review feedback Pls see my in lined comments
-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Monday, April 27, 2009 4:06 AM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ashish Karkare; Ronen Shitrit; Prabhanjan Sarnaik Subject: Re: [PATCH v3] Marvell MV88F6281GTW_GE Board support
On 07:19 Thu 23 Apr , Prafulla Wadaskar wrote:
This is Marvell's 88F6281_A0 based custom board developed
for wireless
access point product v3: updated as per review comments for v2 added
mv88f6281gtw_ge.h file
removed BITxx macros
first a general comment I do not known if it's your mailer but all tab are converted in whitespace please fix it
This should be mailer problem, I will fix it for all next patch send
+DECLARE_GLOBAL_DATA_PTR;
+int board_init(void) +{
/* Board Parameters initializations */
could explain what you do a few more?
This is explained in detail in Kirkwood support file (i.e. cpu/arm926ejs/kirkwood/kwcore.c) in Kirkwood SOC support patch I will put some explanation here too for each init call
kw_window_ctrl_reg_init();
kw_gpio_init(MV88F6281GTW_GE_OE_VAL_LOW,
MV88F6281GTW_GE_OE_VAL_HIGH,
MV88F6281GTW_GE_OE_LOW,
MV88F6281GTW_GE_OE_HIGH);
kw_mpp_control_init(MV88F6281GTW_GE_MPP0_7,
MV88F6281GTW_GE_MPP8_15,
MV88F6281GTW_GE_MPP16_23,
MV88F6281GTW_GE_MPP24_31,
MV88F6281GTW_GE_MPP32_39,
MV88F6281GTW_GE_MPP40_47,
- MV88F6281GTW_GE_MPP48_55);
from
/* serial config */
gd->baudrate = CONFIG_BAUDRATE;
gd->have_console = 1;
no need please remove
Okay I will remove this
/*
* arch number of USED SOC
*/
gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x00000100;
please be more consistant with the other arm boards RAM_BASE + 0x100
Okay..
return 0;
+}
+int dram_init(void) +{
int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
gd->bd->bi_dram[i].start = kw_sdram_bar(i);
gd->bd->bi_dram[i].size = kw_sdram_bs(i);
}
return 0;
+}
+int last_stage_init(void) +{
return 0;
+}
no need please remove
Okay
+#if defined(CONFIG_MISC_INIT_R) +/* miscellaneous platform dependent init */ int misc_init_r(void) {
return kw_misc_init_r();
+}
if it's really arch late init please create a generic function like arch_late_init or arch_misc_init and call it from lib_arm/board.c
+void reset_phy(void) +{ +#ifdef CONFIG_MV88E61XX_SWITCH
/* configure and initialize switch */
struct mv88e61xx_config swcfg = {
.name = "egiga0",
.vlancfg = MV88E61XX_VLANCFG_ROUTER,
.rgmii_delay = MV88E61XX_RGMII_DELAY_EN,
.portstate = MV88E61XX_PORTSTT_FORWARDING,
.cpuport = 5,
.ports_enabled = (PORT(0) | PORT(1) | PORT(2)
| PORT(3) | PORT(4) | PORT(5))
};
mv88e61xx_switch_initialize(&swcfg);
+#endif +}
please only call reset_phy when the SWITCH is enable. it will reduce the size of u-boot whenyou do not use the switch
Yes... I will do it
+/*
- Default values for MPP registers
- */
+#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000
could explain a few more these value
I will put explanation for this
GbePort0/1 for kernel */
+#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE
Port0 for kernel */
+#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to +1.8V */ #endif
why? this boards is not a KIRWOOD?
No, This board is MV88F6281GTW_GE which uses 88F6281 belongs to kirkwood family of SoCs. Soc has provision to configure RGMII pad voltages to 1.8 or 3.3 Volts connected to Gbe interface (i.e. switch used on this board). Also kernel switch and Gbe controller driver does not take care of this since they are generic.
+#define CONFIG_BOOTCOMMAND
"$(x_bootcmd_kernel); setenv bootargs " \ IIRC please use ${} instead of $()
Okay
"$(x_bootargs) $(x_bootargs_root); bootm 0x6400000;"
+#define CONFIG_EXTRA_ENV_SETTINGS
"x_bootargs=console=ttyS0,115200 " \
+"mtdparts=spi0.0:512k(uboot),512k@512k(psm),2m@1m(kernel),13m@3m(root
+fs)\0" \
he could be usefull to use CONFIG_MTDPARTS
I will check this and use it
Regards.. Prafulla . .

From: prafulla_wadaskar prafulla@marvell.com
This is Marvell's 88F6281_A0 based custom board developed for wireless access point product
This patch is tested for- 1. Boot from DRAM/SPI flash/NFS 2. File transfer using tftp and loadb 3. SPI flash read/write/erase 4. Booting Linux kernel and RFS from SPI flash
Reviewed-by: Ronen Shitrit rshitrit@marvell.com Signed-off-by: Prafulla Wadaskar prafulla@marvell.com --- Change log v2: updated as per first review comments debug_prints updated to debug
v3: updaed as per review comments for v2 added mv88f6281gtw_ge.h file removed BITxx macros
v4: updated as per review comments for v3 arch_misc_init support is added and used from kirkwood
MAKEALL | 1 + Makefile | 3 + board/Marvell/mv88f6281gtw_ge/Makefile | 51 +++++++ board/Marvell/mv88f6281gtw_ge/config.mk | 25 +++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c | 86 +++++++++++ board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h | 51 +++++++ board/Marvell/mv88f6281gtw_ge/u-boot.lds | 53 +++++++ include/configs/mv88f6281gtw_ge.h | 180 +++++++++++++++++++++++ 8 files changed, 450 insertions(+), 0 deletions(-) create mode 100644 board/Marvell/mv88f6281gtw_ge/Makefile create mode 100644 board/Marvell/mv88f6281gtw_ge/config.mk create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c create mode 100644 board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h create mode 100644 board/Marvell/mv88f6281gtw_ge/u-boot.lds create mode 100644 include/configs/mv88f6281gtw_ge.h
diff --git a/MAKEALL b/MAKEALL index e4eb42b..1caf81d 100755 --- a/MAKEALL +++ b/MAKEALL @@ -504,6 +504,7 @@ LIST_ARM9=" \ cp946es \ cp966 \ lpd7a400 \ + mv88f6281gtw_ge \ mx1ads \ mx1fs2 \ netstar \ diff --git a/Makefile b/Makefile index d2c7c3f..709e4be 100644 --- a/Makefile +++ b/Makefile @@ -2792,6 +2792,9 @@ lpd7a400_config \ lpd7a404_config: unconfig @$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x
+mv88f6281gtw_ge_config: unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs $(@:_config=) Marvell kirkwood + mx1ads_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t mx1ads NULL imx
diff --git a/board/Marvell/mv88f6281gtw_ge/Makefile b/board/Marvell/mv88f6281gtw_ge/Makefile new file mode 100644 index 0000000..8c49a3e --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/Makefile @@ -0,0 +1,51 @@ +# +# (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$(BOARD).a + +COBJS := mv88f6281gtw_ge.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/Marvell/mv88f6281gtw_ge/config.mk b/board/Marvell/mv88f6281gtw_ge/config.mk new file mode 100644 index 0000000..fb29a1b --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/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 +# + +TEXT_BASE = 0x00600000 diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c new file mode 100644 index 0000000..718ed6b --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c @@ -0,0 +1,86 @@ +/* + * (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 <../drivers/net/phy/mv88e61xx.h> +#include <netdev.h> +#include "mv88f6281gtw_ge.h" + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + kw_config_gpio(MV88F6281GTW_GE_OE_VAL_LOW, + MV88F6281GTW_GE_OE_VAL_HIGH, + MV88F6281GTW_GE_OE_LOW, MV88F6281GTW_GE_OE_HIGH); + + /* Multi-Purpose Pins Functionality configuration */ + kw_config_mpp(MV88F6281GTW_GE_MPP0_7, + MV88F6281GTW_GE_MPP8_15, + MV88F6281GTW_GE_MPP16_23, + MV88F6281GTW_GE_MPP24_31, + MV88F6281GTW_GE_MPP32_39, + MV88F6281GTW_GE_MPP40_47, MV88F6281GTW_GE_MPP48_55); + + /* serial config */ + gd->baudrate = CONFIG_BAUDRATE; + /* + * arch number of USED SOC + */ + gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100; + + return 0; +} + +int dram_init(void) +{ + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = kw_sdram_bar(i); + gd->bd->bi_dram[i].size = kw_sdram_bs(i); + } + return 0; +} + +#ifdef CONFIG_MV88E61XX_SWITCH +void reset_phy(void) +{ + /* configure and initialize switch */ + struct mv88e61xx_config swcfg = { + .name = "egiga0", + .vlancfg = MV88E61XX_VLANCFG_ROUTER, + .rgmii_delay = MV88E61XX_RGMII_DELAY_EN, + .portstate = MV88E61XX_PORTSTT_FORWARDING, + .cpuport = 5, + .ports_enabled = (PORT(0) | PORT(1) | PORT(2) + | PORT(3) | PORT(4) | PORT(5)) + }; + + mv88e61xx_switch_initialize(&swcfg); +} +#endif /* CONFIG_MV88E61XX_SWITCH */ diff --git a/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h new file mode 100644 index 0000000..fbc7dea --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.h @@ -0,0 +1,51 @@ +/* + * (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 __MV88F6281GTW_GE_H +#define __MV88F6281GTW_GE_H + +#define MV88F6281GTW_GE_OE_LOW (~((1<<7) | (1<<20) \ + |(1<<21))) /*enable GLED,RLED */ +#define MV88F6281GTW_GE_OE_HIGH (~((1<<4)|(1<<6)|(1<<7)|(1<<12) \ + |(1<<13)|(1<<16)|(1<<17))) +#define MV88F6281GTW_GE_OE_VAL_LOW (1<<20) /*make GLED on */ +#define MV88F6281GTW_GE_OE_VAL_HIGH ((1<<6)|(1<<13)|(1<<16)|(1<<17)) + +/* + * Default values for MPP registers + * + * There are maximum 64 Multi-Pourpose Pins on Kirkwood + * Each MPP functionality can be configuration by a 4bit value + * of MPP control reg, the value and associated functionality is SoC + * varient dependent + */ +#define MV88F6281GTW_GE_MPP0_7 0x01112222 +#define MV88F6281GTW_GE_MPP8_15 0x11103311 +#define MV88F6281GTW_GE_MPP16_23 0x00001111 +#define MV88F6281GTW_GE_MPP24_31 0x22222222 +#define MV88F6281GTW_GE_MPP32_39 0x40440222 +#define MV88F6281GTW_GE_MPP40_47 0x00004444 +#define MV88F6281GTW_GE_MPP48_55 0x00000000 + +#endif /* __MV88F6281GTW_GE_H */ diff --git a/board/Marvell/mv88f6281gtw_ge/u-boot.lds b/board/Marvell/mv88f6281gtw_ge/u-boot.lds new file mode 100644 index 0000000..9695f3f --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata))) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } + _end = .; +} + diff --git a/include/configs/mv88f6281gtw_ge.h b/include/configs/mv88f6281gtw_ge.h new file mode 100644 index 0000000..b3d2d02 --- /dev/null +++ b/include/configs/mv88f6281gtw_ge.h @@ -0,0 +1,180 @@ +/* + * (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 _CONFIG_MV88F6281GTW_GE_H +#define _CONFIG_MV88F6281GTW_GE_H + +/* + * Version number information + */ +#define CONFIG_IDENT_STRING "\nMarvell-MV88F6281GTW_GE-A0" + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* Basic Architecture */ +#define CONFIG_FEROCEON_88FR131 1 /* CPU Core subversion */ +#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */ + +#ifdef CONFIG_KIRKWOOD +#define CONFIG_MD5 /* get_random_hex on krikwood needs MD5 support */ +#define CONFIG_ARCH_LOWLEVEL_INIT /* enable arch_lowlevel_init */ +#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */ +#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */ +#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE Port0 for kernel */ +#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to 1.8V */ +#endif + +/* + * CLKs configurations + */ +#define CONFIG_SYS_HZ 1000 + +/* + * Serial Port configuration + * The following definitions let you select what serial you want to use + * for your console driver. + */ +#define CONFIG_KIRKWOOD_SERIAL /* enable kirkwood serial driver */ +#define CONFIG_CONS_INDEX 0 /*Console on UART0 */ + +#define CONFIG_BAUDRATE 115200 /* console baudrate */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \ + 115200,230400, 460800, 921600 } +/* auto boot */ +#define CONFIG_BOOTDELAY 3 /* default enable autoboot */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CONFIG_BOOTMAPSZ (8<<20) /* Initial Memmap for Linux */ +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS 1 /* enable memory tag */ + +#define CONFIG_SYS_PROMPT "Marvell>> " /* Command Prompt */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ + +sizeof(CONFIG_SYS_PROMPT) + 16) /* Print Buff */ +/* + * Commands configuration + */ +#define CONFIG_CMD_ENV +#define CONFIG_CMD_RUN +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_NET +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_AUTOSCRIPT +#define CONFIG_CMD_MEMORY +#define CONFIG_CMD_BOOTD +#define CONFIG_CMD_SAVEENV +#define CONFIG_CMD_SF + +/* + * Flash configuration + */ +#ifdef CONFIG_CMD_SF +#define CONFIG_SYS_NO_FLASH 1 /* Declare no NOR flash */ +#define CONFIG_SPI_FLASH 1 +#define CONFIG_HARD_SPI 1 +#define CONFIG_KIRKWOOD_SPI 1 +#define CONFIG_SPI_FLASH_MACRONIX 1 +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 +#define CONFIG_ENV_SPI_MAX_HZ 50000000 /*50Mhz */ +#endif + +/* + * Environment variables configurations + */ +#ifdef CONFIG_SPI_FLASH +#define CONFIG_ENV_IS_IN_SPI_FLASH 1 +#define CONFIG_ENV_SIZE 0x10000 /* spi flash block (64k) */ +#define CONFIG_ENV_SECT_SIZE 0x10000 /* _64K */ +#else +#define CONFIG_ENV_IS_NOWHERE 1 /* if env in SDRAM */ +#define CONFIG_ENV_SIZE 0x20000 /* default 128k */ +#endif +#define CONFIG_ENV_ADDR 0x20000 +#define CONFIG_ENV_OFFSET 0x20000 /* env starts here */ + +/* + * Default environment variables + */ +#define CONFIG_BOOTCOMMAND "${x_bootcmd_kernel}; setenv bootargs " \ + "${x_bootargs} ${x_bootargs_root}; bootm 0x6400000;" + +#define CONFIG_MTDPARTS "spi0.0:512k(uboot),512k@512k(psm), " \ + "2m@1m(kernel),13m@3m(rootfs)\0" + +#define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console=ttyS0,115200 " \ + "mtdparts="CONFIG_MTDPARTS \ + "x_bootcmd_kernel=cp.b 0xf8100000 0x6400000 0x200000\0" \ + "x_bootargs_root=root=/dev/mtdblock3 ro rootfstype=squashfs\0" + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN 0x00400000 /* 4M */ +/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128 + +/* + * Other required minimal configurations + */ +#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */ +#define CONFIG_ARCH_MISC_INIT /* call arch_misc_init() */ +#define CONFIG_DISPLAY_CPUINFO /* Display cpu info */ +#define CONFIG_NR_DRAM_BANKS 4 +#define CONFIG_STACKSIZE 0x00100000 /* regular stack- 1M */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */ +#define CONFIG_SYS_MEMTEST_START 0x00400000 /* 4M */ +#define CONFIG_SYS_MEMTEST_END 0x007fffff /*(_8M -1) */ +#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ + +/* + * Ethernet Driver configuration + */ +#ifdef CONFIG_CMD_NET +#define CONFIG_NETCONSOLE /* include NetConsole support */ +#define CONFIG_NET_MULTI /* specify more that one ports available */ +#define CONFIG_MII /* expose smi ove miiphy interface */ +#define CONFIG_KIRKWOOD_EGIGA /* Enable kirkwood Gbe Controller Driver */ +#define CONFIG_SYS_FAULT_ECHO_LINK_DOWN /* detect link using phy */ +#define CONFIG_KIRKWOOD_EGIGA_PORTS {1,0} /* enable port 0 only */ +#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ +#endif /* CONFIG_CMD_NET */ + +/* + * Marvell 88Exxxx Switch configurations + */ +#define CONFIG_RESET_PHY_R /* use reset_phy() to init phy/swtich */ +#define CONFIG_MV88E61XX_SWITCH /* Enable mv88e61xx switch driver */ + +#endif /* _CONFIG_MV88F6281GTW_GE_H */

+# (C) Copyright 2009
- 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 <../drivers/net/phy/mv88e61xx.h>
Ben I not sure it's clean any better idea?
+#include <netdev.h> +#include "mv88f6281gtw_ge.h"
+DECLARE_GLOBAL_DATA_PTR;
+int board_init(void) +{
please add comment
- kw_config_gpio(MV88F6281GTW_GE_OE_VAL_LOW,
MV88F6281GTW_GE_OE_VAL_HIGH,
MV88F6281GTW_GE_OE_LOW, MV88F6281GTW_GE_OE_HIGH);
- /* Multi-Purpose Pins Functionality configuration */
- kw_config_mpp(MV88F6281GTW_GE_MPP0_7,
MV88F6281GTW_GE_MPP8_15,
MV88F6281GTW_GE_MPP16_23,
MV88F6281GTW_GE_MPP24_31,
MV88F6281GTW_GE_MPP32_39,
MV88F6281GTW_GE_MPP40_47, MV88F6281GTW_GE_MPP48_55);
From
- /* serial config */
- gd->baudrate = CONFIG_BAUDRATE;
againt please remove
- /*
* arch number of USED SOC
*/
- gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE;
- /* adress of boot parameters */
- gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
- return 0;
+}
+int dram_init(void) +{
- int i;
- for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
gd->bd->bi_dram[i].start = kw_sdram_bar(i);
gd->bd->bi_dram[i].size = kw_sdram_bs(i);
- }
- return 0;
+}
index 0000000..9695f3f --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
please move to cpu/arm/kirkwood/
@@ -0,0 +1,53 @@ +/*
- (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
- */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{
- . = _start;
- . = ALIGN(4);
- .text :
- {
cpu/arm926ejs/start.o (.text)
*(.text)
- }
- .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata))) }
- . = ALIGN(4);
- .data : { *(.data) }
- . = ALIGN(4);
- .got : { *(.got) }
- MA 02110-1301 USA
- */
+#ifndef _CONFIG_MV88F6281GTW_GE_H +#define _CONFIG_MV88F6281GTW_GE_H
+/*
- Version number information
- */
+#define CONFIG_IDENT_STRING "\nMarvell-MV88F6281GTW_GE-A0"
+/*
- High Level Configuration Options (easy to change)
- */
+#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* Basic Architecture */ +#define CONFIG_FEROCEON_88FR131 1 /* CPU Core subversion */ +#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */
please define the CONFIG_MACH
+#ifdef CONFIG_KIRKWOOD
as I guess it will be always KIRKWOOD please remove
+#define CONFIG_MD5 /* get_random_hex on krikwood needs MD5 support */ +#define CONFIG_ARCH_LOWLEVEL_INIT /* enable arch_lowlevel_init */ +#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */ +#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */ +#define CONFIG_KIRKWOOD_PCIE_INIT /* Enable PCIE Port0 for kernel */ +#define CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* Set RGMII Pad voltage to 1.8V */ +#endif
otherwise fine
Best Regards, J.

Thanks Jean...
+#include <common.h> +#include <../drivers/net/phy/mv88e61xx.h>
Ben I not sure it's clean any better idea?
+#include <netdev.h> +#include "mv88f6281gtw_ge.h"
+DECLARE_GLOBAL_DATA_PTR;
+int board_init(void) +{
please add comment
Okay
- kw_config_gpio(MV88F6281GTW_GE_OE_VAL_LOW,
MV88F6281GTW_GE_OE_VAL_HIGH,
MV88F6281GTW_GE_OE_LOW, MV88F6281GTW_GE_OE_HIGH);
- /* Multi-Purpose Pins Functionality configuration */
- kw_config_mpp(MV88F6281GTW_GE_MPP0_7,
MV88F6281GTW_GE_MPP8_15,
MV88F6281GTW_GE_MPP16_23,
MV88F6281GTW_GE_MPP24_31,
MV88F6281GTW_GE_MPP32_39,
MV88F6281GTW_GE_MPP40_47,
MV88F6281GTW_GE_MPP48_55);
From
- /* serial config */
- gd->baudrate = CONFIG_BAUDRATE;
againt please remove
Okay
index 0000000..9695f3f --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
please move to cpu/arm/kirkwood/
I tried it, If we move it to Kirkwood there is build error, how do we invoke it for the build? currently it provides boot from DRAM since doimage (utility to convert u-boot.bin to flashable bin) is outside. I think this is board specific and each board will have different configuration, for ex. Board with boot from NAND will have different info
+#define CONFIG_KIRKWOOD 1 /* SOC Family Name */ +#define CONFIG_KW88F6281 1 /* SOC Name */
please define the CONFIG_MACH
Okay I will check this and do the needful
+#ifdef CONFIG_KIRKWOOD
as I guess it will be always KIRKWOOD please remove
Sounds good, I will remove it
Regards.. Prafulla . .

On 14:32 Sat 02 May , Prafulla Wadaskar wrote:
Thanks Jean...
+#include <common.h> +#include <../drivers/net/phy/mv88e61xx.h>
Ben I not sure it's clean any better idea?
+#include <netdev.h> +#include "mv88f6281gtw_ge.h"
index 0000000..9695f3f --- /dev/null +++ b/board/Marvell/mv88f6281gtw_ge/u-boot.lds
please move to cpu/arm/kirkwood/
I tried it, If we move it to Kirkwood there is build error, how do we invoke it for the build? currently it provides boot from DRAM since doimage (utility to convert u-boot.bin to flashable bin) is outside. I think this is board specific and each board will have different configuration, for ex. Board with boot from NAND will have different info
3 thinks
1) to boot from DRAM you normaly do not need to change it for nand maybe but it will be normaly the same for all kirkwood
2) do you update your arch confif.mk cat cpu/arm926ejs/kirwood/config.mk LDSCRIPT := $(SRCTREE)/cpu/arm926ejs/kirwood/u-boot.lds
3) I'm in favor as Mike to have the tool to build the final flashable bin in the tree as done for the blackfin with a new target and a new extention as .kwd (or any other)
Best Regards, J.

Dear Jean-Christophe PLAGNIOL-VILLARD,
In message 20090503083923.GS25959@game.jcrosoft.org you wrote:
- I'm in favor as Mike to have the tool to build the final flashable bin
in the tree as done for the blackfin with a new target and a new extention as .kwd (or any other)
You know my opinion about this; it has not changed.
Best regards,
Wolfgang Denk

On 04:09 Sat 04 Apr , Prafulla Wadaskar wrote:
This is ARM v5TE-compliant processor core with MMU and L1/L2 Cache
Signed-off-by: prafulla_wadaskar prafulla@marvell.com Reviewed by: Ronen Shitrit rshitrit@marvell.com
cpu/arm926ejs/start.S | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index ed4932a..08ec955 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -214,10 +214,15 @@ cpu_init_crit: * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 +#if defined (CONFIG_FEROCEON_88FR131) || defined (CONFIG_SHEEVA_88SV131)
- bic r0, r0, #0x00000007 /* clear bits 2:0 (CAM) */
- orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
+#else bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ +#endif
I've plan to clean up the asm mmu and cache management as I've done for the C part. The idea is to avoid to duplicated code and #ifdef every where. So please create asm macro to handle this
and please explain a few more why you need it
Best Regards, J.

-----Original Message----- From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] Sent: Saturday, April 04, 2009 9:46 PM To: Prafulla Wadaskar Cc: u-boot@lists.denx.de; Ronen Shitrit; Nicolas Pitre Subject: Re: [U-Boot] [PATCH] Marvell Feroceon-FR131/Sheeva-88SV131 cpu core support
On 04:09 Sat 04 Apr , Prafulla Wadaskar wrote:
This is ARM v5TE-compliant processor core with MMU and L1/L2 Cache
Signed-off-by: prafulla_wadaskar prafulla@marvell.com
Reviewed by:
Ronen Shitrit rshitrit@marvell.com
cpu/arm926ejs/start.S | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index ed4932a..08ec955 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -214,10 +214,15 @@ cpu_init_crit: * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 +#if defined (CONFIG_FEROCEON_88FR131) || defined
(CONFIG_SHEEVA_88SV131)
- bic r0, r0, #0x00000007 /* clear bits 2:0 (CAM) */
- orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
+#else bic r0, r0, #0x00002300 /* clear bits 13, 9:8
(--V- --RS) */
bic r0, r0, #0x00000087 /* clear bits 7, 2:0
(B--- -CAM) */
orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ +#endif
I've plan to clean up the asm mmu and cache management as I've done for the C part. The idea is to avoid to duplicated code and #ifdef every where. So please create asm macro to handle this
and please explain a few more why you need it
The issue was of 'order of operations'. In our devices we have L2 cache and the L2 must be enabled before the L1. this change was with reference to older u-boot and earlier SOC versions. I have tested the code without this patch and is functional. We can add code for disabling the L1 before enabling the L2 in SOC specific .
This patch is not needed now, We can skip this patch.
Best Regards, J.
participants (9)
-
Andrew Dyer
-
Andy Fleming
-
Ben Warren
-
Jean-Christophe PLAGNIOL-VILLARD
-
Mike Frysinger
-
Norbert van Bolhuis
-
Prafulla Wadaskar
-
Sergey Nikulov
-
Wolfgang Denk