
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 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
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 */