diff options
Diffstat (limited to 'roms/SLOF/board-js2x')
76 files changed, 11661 insertions, 0 deletions
| diff --git a/roms/SLOF/board-js2x/Makefile b/roms/SLOF/board-js2x/Makefile new file mode 100644 index 00000000..f24a5046 --- /dev/null +++ b/roms/SLOF/board-js2x/Makefile @@ -0,0 +1,81 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# *     IBM Corporation - initial implementation +# ****************************************************************************/ + +BOARD_TARGETS = tools_build romfs_build clients_build stage1 subdirs + +SUBDIRS = slof rtas  +COMMON_LIBS = libc libipmi libbootmsg libbases libnvram libelf libusb libbcm + +all: $(BOARD_TARGETS) +	$(MAKE) boot_rom.bin + +.PHONY : subdirs $(SUBDIRS) clean distclean + +include config +include Makefile.dirs +include $(TOPCMNDIR)/make.rules +include $(TOPCMNDIR)/Makefile.gen + +subdirs: $(SUBDIRS) + +$(SUBDIRS): common-libs +	@echo " ====== Building $@ ======" +	$(MAKE) -C $@ $(MAKEARG) + +stage1:	common-libs +	@echo " ====== Building llfw ======" +	$(MAKE) -C llfw RELEASE=-DRELEASE=\"\\\"$(RELEASE)\\\"\" + +clean_here: +	rm -f ../slof/OF.ffs +	rm -f ../boot_rom.bin + +clean:		clean_here clean_gen +	@for dir in $(SUBDIRS); do \ +		$(MAKE) -C $$dir clean || exit 1; \ +	done +	rm -f ../boot_rom.bin ../js2*.img  +	@$(MAKE) -C llfw clean +	@$(MAKE) -C $(TOPCMNDIR)/clients/takeover clean + +distclean:	clean_here distclean_gen +	@for dir in $(SUBDIRS); do \ +		$(MAKE) -C $$dir distclean || exit 1; \ +	done +	rm -f ../boot_rom.bin ../js2*.img  +	$(MAKE) -C llfw clean +	$(MAKE) -C $(TOPCMNDIR)/clients/takeover distclean + +takeover: all +	$(MAKE) -C $(TOPCMNDIR)/clients/takeover + +.driver_dirs: +	@rm -rf ../driver-$(RELEASE) +	@mkdir -p ../driver-$(RELEASE) + +.tar_gz:	.driver_dirs takeover external_flasher +	@mv ../boot_rom.bin \ +		../driver-$(RELEASE)/$(RELEASE)-js2x.bin +	@mv ../boot_rom-$(FLASH_SIZE_MB)MB-BigEndian.bin \ +		../driver-$(RELEASE)/$(RELEASE)-$(FLASH_SIZE_MB)MB-BigEndian.bin +	@mv $(TOPCMNDIR)/clients/takeover/takeover.elf \ +		../driver-$(RELEASE)/$(RELEASE)-takeover.bin +	@cp ../VERSION ../driver-$(RELEASE) +	@cp changes.txt ../driver-$(RELEASE) +	@cd ../driver-$(RELEASE) && md5sum * > md5sum.txt +	@chmod 644 ../driver-$(RELEASE)/* +	@mv ../driver-$(RELEASE) ../driver-$(RELEASE)-`date +%Y-%h%d` +	@tar czf ../driver-$(RELEASE)-`date +%Y-%h%d`.tar.gz \ +		../driver-$(RELEASE)-`date +%Y-%h%d` > /dev/null  2>&1 +	@rm -rf ../driver-$(RELEASE)-`date +%Y-%h%d` + +driver:		driver_prep clean .tar_gz diff --git a/roms/SLOF/board-js2x/Makefile.dirs b/roms/SLOF/board-js2x/Makefile.dirs new file mode 100644 index 00000000..1493d3bf --- /dev/null +++ b/roms/SLOF/board-js2x/Makefile.dirs @@ -0,0 +1,41 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# *     IBM Corporation - initial implementation +# ****************************************************************************/ +# +# This sub-Makefile contains the directory configuration variables. +# It can be included from all board specific subdirectories. +# + +# The board specific top directory: +export TOPBRDDIR ?= $(shell while ! test -e Makefile.dirs ; do cd .. ; done ; pwd ) + +# The board specific directories: +export INCLBRDDIR ?= $(TOPBRDDIR)/include +export LLFWBRDDIR ?= $(TOPBRDDIR)/llfw +export RTASBRDDIR ?= $(TOPBRDDIR)/rtas +export SLOFBRDDIR ?= $(TOPBRDDIR)/slof +export ROMFSBRDDIR ?=  $(TOPBRDDIR)/romfs + +# The common top directory: +export TOPCMNDIR ?= $(shell cd $(TOPBRDDIR)/.. && pwd) + +# The common directories: +export INCLCMNDIR ?= $(TOPCMNDIR)/include +export LLFWCMNDIR ?= $(TOPCMNDIR)/llfw +export RTASCMNDIR ?= $(TOPCMNDIR)/rtas +export SLOFCMNDIR ?= $(TOPCMNDIR)/slof +export ROMFSCMNDIR ?=  $(TOPCMNDIR)/romfs + +export LIBCMNDIR ?= $(TOPCMNDIR)/lib + +export TOOLSDIR ?= $(TOPCMNDIR)/tools +export CLIENTSDIR ?= $(TOPCMNDIR)/clients +export OTHERLICENCEDIR ?= $(TOPCMNDIR)/other-licence diff --git a/roms/SLOF/board-js2x/config b/roms/SLOF/board-js2x/config new file mode 100644 index 00000000..d6891e10 --- /dev/null +++ b/roms/SLOF/board-js2x/config @@ -0,0 +1,13 @@ +BOARD=js2x +TARG=ppc64 +export FLAG="-DBIOSEMU" +export CPUARCH=ppc970 +export CPUARCHDEF=-DCPU_PPC970 + +ifneq ($(wildcard ../other-licence/x86emu/*.c),) +export SNK_BIOSEMU_APPS=1 +else +export SNK_BIOSEMU_APPS=0 +endif + +FLASH_SIZE=8388608 diff --git a/roms/SLOF/board-js2x/include/bmc.h b/roms/SLOF/board-js2x/include/bmc.h new file mode 100644 index 00000000..39dff80b --- /dev/null +++ b/roms/SLOF/board-js2x/include/bmc.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef __BMC_H +#define __BMC_H + +void (*bmc_system_reboot) (void); +void (*bmc_power_off) (void); + +short (*bmc_set_flashside) (short mode); +short (*bmc_get_flashside) (void); +int (*bmc_stop_bootwatchdog) (void); +int (*bmc_set_bootwatchdog) (unsigned short); + +uint32_t(*bmc_read_vpd) (uint8_t * dst, uint32_t len, uint32_t offset); +uint32_t(*bmc_write_vpd) (uint8_t * src, uint32_t len, uint32_t offset); + +uint32_t(*bmc_get_blade_descr) (uint8_t * dst, uint32_t maxlen, uint32_t * len); + +#endif				/* __BMC_H */ diff --git a/roms/SLOF/board-js2x/include/hw.h b/roms/SLOF/board-js2x/include/hw.h new file mode 100644 index 00000000..27117c3f --- /dev/null +++ b/roms/SLOF/board-js2x/include/hw.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +uint16_t bswap16_load(uint64_t addr) ; +uint32_t bswap32_load(uint64_t addr) ; + +void bswap16_store(uint64_t addr, uint16_t val) ; +void bswap32_store(uint64_t addr, uint32_t val) ; + +uint8_t load8_ci(uint64_t addr) ; +uint16_t load16_ci(uint64_t addr) ; +uint32_t load32_ci(uint64_t addr) ; +uint64_t load64_ci(uint64_t addr) ; + +void store8_ci(uint64_t  addr, uint8_t val) ; +void store16_ci(uint64_t  addr, uint16_t val) ; +void store32_ci(uint64_t  addr, uint32_t val) ; +void store64_ci(uint64_t  addr, uint64_t val) ; diff --git a/roms/SLOF/board-js2x/include/nvramlog.h b/roms/SLOF/board-js2x/include/nvramlog.h new file mode 100644 index 00000000..5d6c5d1c --- /dev/null +++ b/roms/SLOF/board-js2x/include/nvramlog.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef NVRAMLOG_H +	#define NVRAMLOG_H + +/* ---------------------------------------------------------------------------- + *	NVRAM Log-Partition header design: + * + *	Partition Header + *	00h	- signature	( 1 byte) + *	01h	- checksum	( 1 byte) + *	02h	- length	( 2 byte) value = 1st_byte*256 + 2nd_byte + *	04h	- name		(12 byte) + *	space for partiton header = 16 byte + * + *	Log Header + *	10h	- offset	( 2 byte) from Partition Header to Data Section + *	12h	- flags		( 2 byte) control flags + *	14h	- pointer	( 4 byte) pointer to first free byte in Data Section + *					  relative to the beginning of the data section + *	18h	- zero		( 32 byte) reserved as stack for four  64 bit register + *	38h - reserved		(  8 byte) reserved for 64 bit CRC (not implemented yet) + *	space for header = 64 byte + *	Data Section + *	40h	- cyclic data + * -------------------------------------------------------------------------------- */ + +	// initial values +	#define LLFW_LOG_BE0_SIGNATURE		0x51			// signature for general firmware usage +	#define LLFW_LOG_BE0_NAME_PREFIX	0x69626D2C		// first 4 bytes of name: "ibm," +	#define LLFW_LOG_BE0_NAME		0x435055306C6F6700	// remaining 8 bytes	: "CPU0log\0" +	#define LLFW_LOG_BE0_LENGTH		0x2000			// Partition length in block of 16 bytes +	#define LLFW_LOG_BE0_DATA_OFFSET	0x40			// offset in bytes between header and data +	#define LLFW_LOG_BE0_FLAGS		0			// unused + +	#define LLFW_LOG_BE1_SIGNATURE		0x51			// signature for general firmware usage +	#define LLFW_LOG_BE1_NAME_PREFIX	0x69626D2C		// first 4 bytes of name: "ibm," +	#define LLFW_LOG_BE1_NAME		0x435055316C6F6700	// remaining 8 bytes	: "CPU1log\0\0" +	#define LLFW_LOG_BE1_LENGTH		0x500			// Partition length in block of 16 bytes +	#define LLFW_LOG_BE1_DATA_OFFSET	0x40			// offset in bytes between header and data +	#define LLFW_LOG_BE1_FLAGS		0x0			// unused + +	// positions of the initial values +	#define LLFW_LOG_POS_CHECKSUM	0x01			// 1 +	#define LLFW_LOG_POS_LENGTH	0x02			// 2 +	#define LLFW_LOG_POS_NAME	0x04			// 4 +	#define LLFW_LOG_POS_DATA_OFFSET 0x10			// 16 +	#define LLFW_LOG_POS_FLAGS	0x12			// 18 +	#define LLFW_LOG_POS_POINTER	0x14			// 20 + +	// NVRAM info +	#define MAMBO_NVRAM_BASE	0x100000		// NVRAM Base for MAMBO +	#define NVRAM_EMPTY_PATTERN	0x0000000000000000	// Pattern (64-bit) used to overwrite NVRAM + +#endif diff --git a/roms/SLOF/board-js2x/include/product.h b/roms/SLOF/board-js2x/include/product.h new file mode 100644 index 00000000..55e9132f --- /dev/null +++ b/roms/SLOF/board-js2x/include/product.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _PRODUCT_H +#define _PRODUCT_H + +/* This is also the name which is also put in the flash and should + * therefore not excedd the length of 32 bytes */ +#define PRODUCT_NAME "JS2XBlade" + +/* Generic identifier used in the flash */ +#define FLASHFS_MAGIC "magic123" + +/* Magic identifying the platform */ +#define FLASHFS_PLATFORM_MAGIC "JS2XBlade" + +/* also used in the flash */ +#define FLASHFS_PLATFORM_REVISION "1" + +#define BOOT_MESSAGE  "Press \"s\" to enter Open Firmware.\r\n\r\n\0" + +#endif diff --git a/roms/SLOF/board-js2x/include/southbridge.h b/roms/SLOF/board-js2x/include/southbridge.h new file mode 100644 index 00000000..1edeb6d7 --- /dev/null +++ b/roms/SLOF/board-js2x/include/southbridge.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _SOUTHBRIDGE_H +#define _SOUTHBRIDGE_H + + +#define SB_FLASH_adr           (0xff000000)          // FLASH (EBC_CS0/Bank0) +#define SB_NVRAM_adr           (0xff800000)          // NonVolatile mapping +#define SB_NVRAM_FWONLY_adr    (0xff8FF000)          // NonVolatile mapping +#define NVRAM_LENGTH           0x100000 +#define NVRAM_FWONLY_LENGTH    0x1000 +#define SB_MAILBOX_adr         0 + +#define FLASH_LENGTH           0x400000 + +#define SB_IPMI_KCS_adr        0xF4000CA8            // IPMI KCS + +#endif diff --git a/roms/SLOF/board-js2x/llfw/Cboot.S b/roms/SLOF/board-js2x/llfw/Cboot.S new file mode 100644 index 00000000..d22f3c93 --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/Cboot.S @@ -0,0 +1,18 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +	.org 0 + +	/* Boot Information, hardcoded to ColdReset */ +	.quad	1 +	/* start address */ +	.quad	0x100 diff --git a/roms/SLOF/board-js2x/llfw/Makefile b/roms/SLOF/board-js2x/llfw/Makefile new file mode 100644 index 00000000..41cdc35c --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/Makefile @@ -0,0 +1,61 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# *     IBM Corporation - initial implementation +# ****************************************************************************/ + +include ../../make.rules + +CPPFLAGS	= -I$(INCLBRDDIR) -I$(INCLCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH) \ +		  -I$(LIBCMNDIR)/libc/include +CFLAGS		+= -fno-builtin $(CPPFLAGS) -O2  -msoft-float $(MAMBO) +CFLAGS		+= $(BOOT) $(IOCONF) -Wa,-mregnames $(RELEASE) $(CPUARCHDEF) -Wall +ASFLAGS         = $(BOOT) $(IOCONF) $(RELEASE)$(CPUARCHDEF)  -Wa,-mregnames +LDFLAGS1	= -nostdlib -e__start -Tstage2.lds -N -Ttext=0x100 + + +STG1OBJ		 = startup.o boot_abort.o romfs.o hw.o io_generic.o board_io.o  +STG1OBJ		 += stage2_head.o stage2.o comlib.o romfs_wrap.o nvramlog.o +STG1OBJ		 += u4mem.o + +all: stage1.bin stageS.bin Cboot.o + +stage1.bin:	$(STG1OBJ) $(LIBCMNDIR)/libelf.a $(LIBCMNDIR)/libc.a +		$(LD) $(LDFLAGS1) -o stage1.elf $^ +		$(OBJCOPY) -O binary stage1.elf $@ + +stageS.bin:	stage_s.o +		$(LD) -nostdlib -N -Tstage_s.lds -o stage_s.elf stage_s.o +		$(OBJCOPY) -O binary stage_s.elf stageS.bin + +romfs.o:	../../llfw/romfs.S +		$(CC) $(CFLAGS) -c ../../llfw/romfs.S + +boot_abort.o:	../../llfw/boot_abort.S +		$(CC) $(CFLAGS) -c ../../llfw/boot_abort.S + +nvramlog.o:	../../llfw/nvramlog.S +		$(CC) $(CFLAGS) -c ../../llfw/nvramlog.S + +include $(LLFWCMNDIR)/clib/Makefile.inc + +include $(LLFWCMNDIR)/io_generic/Makefile.inc + +romfs_wrap.o:	../../llfw/romfs_wrap.c +		$(CC) $(CFLAGS) -c ../../llfw/romfs_wrap.c + +Cboot.o: Cboot.S +		$(CC) $(CFLAGS) -c $^ +		$(OBJCOPY) -O binary Cboot.o Cboot.bin + +%.o: %.S +		$(CC) $(CFLAGS) -c $^ + +clean: +		rm -f *.o *.bin *.elf diff --git a/roms/SLOF/board-js2x/llfw/board_io.S b/roms/SLOF/board-js2x/llfw/board_io.S new file mode 100644 index 00000000..2f365883 --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/board_io.S @@ -0,0 +1,62 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include <macros.h> +#include <cpu.h> + +	.text + +C_ENTRY(copy_from_flash) +# size in GPR3 (multiple of 64), from GPR4, to GPR5 +	mflr 24 ; mtctr 3 ; addi 4,4,-64 ; addi 5,5,-64 +0:	SETCI(r0) +	ldu 16,64(4) ; ld 17,8(4) ; ld 18,16(4) ; ld 19,24(4) +	ld 20,32(4) ; ld 21,40(4) ; ld 22,48(4) ; ld 23,56(4) +	CLRCI(r0) +	stdu 16,64(5) ; std 17,8(5) ; std 18,16(5) ; std 19,24(5) +	std 20,32(5) ; std 21,40(5) ; std 22,48(5) ; std 23,56(5) +	sync ; icbi 0,2 ; bdnz 0b ; sync ; isync ; mtlr 24 ; blr + +/**************************************************************************** + * prints one character to serial console + * + * Input: + * R3 - character + * + * Returns: - + * + * Modifies Registers: + * R3, R4, R5, R6, R7 + ****************************************************************************/ +ENTRY(io_putchar) +	mflr	r7 + +	SETCI(r0) + +	# always use serial1 +	li 4,0x3f8 ; oris 4,4,0xf400 + +	# print one char +0:	lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio  + +	# also print char to serial2 if on a JS21 +	# read ID register: only if it is a PC87427 (JS21) also use serial2 +	addi 4,4,-0x3f8 +	li 5,0x20 ; stb 5,0x2e(4) ; lbz 5,0x2f(4) ; cmpdi 5,0xf2 ; bne 1f + +	addi 4,4,0x2f8 +0:	lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio  + +1:	CLRCI(r0) + +	mtlr	r7 +	blr diff --git a/roms/SLOF/board-js2x/llfw/hw.c b/roms/SLOF/board-js2x/llfw/hw.c new file mode 100644 index 00000000..e01b583b --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/hw.c @@ -0,0 +1,124 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include <cpu.h> +#include <stdint.h> +#include <hw.h> + +uint16_t +bswap16_load(uint64_t addr) +{ +	unsigned int val; +	set_ci(); +	asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr)); +	clr_ci(); +	return val; +} + +uint32_t +bswap32_load(uint64_t addr) +{ +	unsigned int val; +	set_ci(); +	asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr)); +	clr_ci(); +	return val; +} + +void +bswap16_store(uint64_t addr, uint16_t val) +{ +	set_ci(); +	asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr)); +	clr_ci(); +} + +void +bswap32_store(uint64_t addr, uint32_t val) +{ +	set_ci(); +	asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr)); +	clr_ci(); +} + +uint8_t +load8_ci(uint64_t addr) +{ +	uint8_t val; +	set_ci(); +	val = *(uint8_t *) addr; +	clr_ci(); +	return val; +} + +uint16_t +load16_ci(uint64_t addr) +{ +	uint16_t val; +	set_ci(); +	val = *(uint16_t *) addr; +	clr_ci(); +	return val; +} + +uint32_t +load32_ci(uint64_t addr) +{ +	uint32_t val; +	set_ci(); +	val = *(uint32_t *) addr; +	clr_ci(); +	return val; +} + +uint64_t +load64_ci(uint64_t addr) +{ +	uint64_t val; +	set_ci(); +	val = *(uint64_t *) addr; +	clr_ci(); +	return val; +} + + +void +store8_ci(uint64_t addr, uint8_t val) +{ +	set_ci(); +	*(uint8_t *) addr = val; +	clr_ci(); +} + +void +store16_ci(uint64_t addr, uint16_t val) +{ +	set_ci(); +	*(uint16_t *) addr = val; +	clr_ci(); +} + +void +store32_ci(uint64_t addr, uint32_t val) +{ +	set_ci(); +	*(uint32_t *) addr = val; +	clr_ci(); +} + +void +store64_ci(uint64_t addr, uint64_t val) +{ +	set_ci(); +	*(uint64_t *) addr = val; +	clr_ci(); +} diff --git a/roms/SLOF/board-js2x/llfw/stage2.c b/roms/SLOF/board-js2x/llfw/stage2.c new file mode 100644 index 00000000..d05a4949 --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/stage2.c @@ -0,0 +1,276 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdint.h> +#include <xvect.h> +#include <hw.h> +#include <stdio.h> +#include <romfs.h> +#include "memmap.h" +#include "stage2.h" +#include <termctrl.h> +#include "product.h" +#include "calculatecrc.h" +#include <cpu.h> +#include <libelf.h> +#include <string.h> + +uint64_t uart; +uint64_t gVecNum; +uint8_t u4Flag; + +uint64_t exception_stack_frame; + +typedef void (*pInterruptFunc_t) (void); + +pInterruptFunc_t vectorTable[0x2E << 1]; + +extern void proceedInterrupt(void); + +/* Prototypes for functions in this file: */ +void c_interrupt(uint64_t vecNum); +void set_exceptionVector(int num, void *func); +int io_getchar(char *ch); +void early_c_entry(uint64_t start_addr); + + +static void +exception_forward(void) +{ +	uint64_t val; + +	if (*(uint64_t *) XVECT_M_HANDLER) { +		proceedInterrupt(); +	} + +	printf("\r\n exception %llx ", gVecNum); +	asm volatile ("mfsrr0	%0":"=r" (val):); +	printf("\r\nSRR0 = %08llx%08llx ", val >> 32, val); +	asm volatile ("mfsrr1	%0":"=r" (val):); +	printf(" SRR1 = %08llx%08llx ", val >> 32, val); + +	asm volatile ("mfsprg	%0,2":"=r" (val):); +	printf("\r\nSPRG2 = %08llx%08llx ", val >> 32, val); +	asm volatile ("mfsprg	%0,3":"=r" (val):); +	printf(" SPRG3 = %08llx%08llx \r\n", val >> 32, val); +	while (1); +} + +void +c_interrupt(uint64_t vecNum) +{ +	gVecNum = vecNum; +	if (vectorTable[vecNum >> 7]) { +		vectorTable[vecNum >> 7] (); +	} else { +		exception_forward(); +	} +} + +void +set_exceptionVector(int num, void *func) +{ +	vectorTable[num >> 7] = (pInterruptFunc_t) func; +} + +static void +io_init(void) +{ +	// read ID register: only if it is a PC87427, enable serial2 +	store8_ci(0xf400002e, 0x20); +	if (load8_ci(0xf400002f) != 0xf2) { +		uart = 0xf40003f8; +		u4Flag = 0; +	} else { +		uart = 0xf40002f8; +		u4Flag = 1; +	} +} + +int +io_getchar(char *ch) +{ +	int retVal = 0; +	if ((load8_ci(uart + 5) & 0x01)) { +		*ch = load8_ci(uart); +		retVal = 1; +	} +	return retVal; +} + + +void copy_from_flash(uint64_t cnt, uint64_t src, uint64_t dest); + +const uint32_t CrcTableHigh[16] = { +	0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90, +	0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7, +	0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E, +	0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09 +}; +const uint32_t CrcTableLow[16] = { +	0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, +	0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, +	0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, +	0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD +}; + +static unsigned long +check_flash_image(unsigned long rombase, unsigned long length, +		  unsigned long start_crc) +{ + +	uint32_t AccumCRC = start_crc; +	char val; +	uint32_t Temp; +	while (length-- > 0) { +		val = load8_ci(rombase++); +		Temp = ((AccumCRC >> 24) ^ val) & 0x000000ff; +		AccumCRC <<= 8; +		AccumCRC ^= CrcTableHigh[Temp / 16]; +		AccumCRC ^= CrcTableLow[Temp % 16]; +	} + +	return AccumCRC; +} + +static void +load_file(uint64_t destAddr, char *name, uint64_t maxSize, uint64_t romfs_base) +{ +	uint64_t *src, *dest, cnt; +	struct romfs_lookup_t fileInfo; +	c_romfs_lookup(name, romfs_base, &fileInfo); +	if (maxSize) { +		cnt = maxSize / 8; +	} else { +		cnt = (fileInfo.size_data + 7) / 8; +	} +	dest = (uint64_t *) destAddr; +	src = (uint64_t *) fileInfo.addr_data; +	while (cnt--) { +		store64_ci((uint64_t) dest, *src); +		dest++; +		src++; +	} +	flush_cache((void *) destAddr, fileInfo.size_data); +} + +/*************************************************************************** + * Function: early_c_entry + * Input   : start_addr + * + * Description: + **************************************************************************/ +void +early_c_entry(uint64_t start_addr) +{ +	struct romfs_lookup_t fileInfo; +	uint32_t crc; +	void (*ofw_start) (uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); +	uint64_t *boot_info; +	exception_stack_frame = 0; +	/* destination for the flash image; we copy it to RAM +	 * because from flash it is much too slow +	 * the flash is copied at 224MB - 4MB (max flash size) +	 * at 224MB starts SLOF +	 * at 256MB is the SLOF load-base */ +	uint64_t romfs_base = 0xe000000 - 0x400000; +	// romfs header values +	struct stH *header = (struct stH *) (start_addr + 0x28); +	//since we cannot read the fh_magic directly from flash as a string, we need to copy it to memory +	uint64_t magic_val = 0; +	uint64_t startVal = 0; +	uint64_t flashlen = 0; +	unsigned long ofw_addr; + +	io_init(); + +	flashlen = load64_ci((uint64_t) (&header->flashlen)); + +	//copy fh_magic to magic_val since, we cannot use it as a string from flash +	magic_val = load64_ci((uint64_t) (header->magic)); + +	printf(" Check ROM  = "); +	if (strncmp((char *) &magic_val, FLASHFS_MAGIC, 8) == 0) { +		// somehow, the first 8 bytes in flashfs are overwritten, if booting from drone... +		// so if we find "IMG1" in the first 4 bytes, we skip the CRC check... +		startVal = load64_ci((uint64_t) start_addr); +		if (strncmp((char *) &startVal, "IMG1", 4) == 0) { +			printf +			    ("start from RAM detected, skipping CRC check!\r\n"); +			// for romfs accesses (c_romfs_lookup) to work, we must fix the first uint64_t to the value we expect... +			store64_ci((uint64_t) start_addr, 0xd8); +		} else { +			//checking CRC in flash, we must use cache_inhibit +			// since the crc is included as the last 32 bits in the image, the resulting crc should be 0 +			crc = +			    check_flash_image((uint64_t) start_addr, +					      load64_ci((uint64_t) +							(&header->flashlen)), +					      0); +			if (crc == 0) { +				printf("OK\r\n"); +			} else { +				printf("failed!\r\n"); +				while (1); +			} +		} +	} else { +		printf +		    ("failed (magic string is \"%.8s\" should be \"%.8s\")\r\n", +		     (char *) &magic_val, FLASHFS_MAGIC); +		while (1); +	} + +	printf(" Press \"s\" to enter Open Firmware.\r\n\r\n"); + +	if ((start_addr > 0xF0000000) && u4Flag) +		u4memInit(); + +	/* here we have real ram avail -> hopefully +	 * copy flash to ram; size is in 64 byte blocks */ +	flashlen /= 64; +	/* align it a bit */ +	flashlen += 7; +	flashlen &= ~7; +	copy_from_flash(flashlen, start_addr, romfs_base); +	/* takeover sometimes fails if the image running on the system +	 * has a different size; flushing the cache helps, because it is +	 * the right thing to do anyway */ +	flush_cache((void *) romfs_base, flashlen * 64); + +	c_romfs_lookup("bootinfo", romfs_base, &fileInfo); +	boot_info = (uint64_t *) fileInfo.addr_data; +	boot_info[1] = start_addr; +	load_file(0x100, "xvect", 0, romfs_base); +	load_file(SLAVELOOP_LOADBASE, "stageS", 0, romfs_base); +	c_romfs_lookup("ofw_main", romfs_base, &fileInfo); + +	elf_load_file((void *) fileInfo.addr_data, &ofw_addr, +		      NULL, flush_cache); +	ofw_start = +	    (void (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)) +	    &ofw_addr; +	// re-enable the cursor +	printf("%s%s", TERM_CTRL_RESET, TERM_CTRL_CRSON); +	/* ePAPR 0.5 +	 * r3 = R3 Effective address of the device tree image. Note: this +	 *      address must be 8-byte aligned in memory. +	 * r4 = implementation dependent +	 * r5 = 0 +	 * r6 = 0x65504150 -- ePAPR magic value-to distinguish from +	 *      non-ePAPR-compliant firmware +	 * r7 = implementation dependent +	 */ +	asm volatile("isync; sync;" : : : "memory"); +	ofw_start(0, romfs_base, 0, 0, 0); +	// never return +} diff --git a/roms/SLOF/board-js2x/llfw/stage2.h b/roms/SLOF/board-js2x/llfw/stage2.h new file mode 100644 index 00000000..9ce3c820 --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/stage2.h @@ -0,0 +1,23 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef __STAGE2_H +#define __STAGE2_H + +#ifndef __ASSEMBLER__ + +#include <stddef.h> + +void u4memInit(void); + +#endif		/* __ASSEMBLER__ */ +#endif		/* __STAGE2_H */ diff --git a/roms/SLOF/board-js2x/llfw/stage2.lds b/roms/SLOF/board-js2x/llfw/stage2.lds new file mode 100644 index 00000000..f91f0658 --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/stage2.lds @@ -0,0 +1,56 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc") +OUTPUT_ARCH(powerpc:common64) + +/* set the entry point */ +ENTRY ( __start ) + +SECTIONS { +	.text : { +		*(.text) +	} + +	. = ALIGN(8); + +	.data : { +		*(.data) +		*(.rodata .rodata.*) +		*(.got1) +	        *(.sdata) +	        *(.opd) +	} + +	/* FIXME bss at end ??? */ + +	. = ALIGN(8); +	__bss_start = .; +	.bss : { +		*(.sbss) *(.scommon) +		*(.dynbss) +		*(.bss) +	} + +	. = ALIGN(8); +	__bss_end = .; +	__bss_size = (__bss_end - __bss_start); + +	__toc_start = .; +	.got       : +	{ +		 *(.toc .got) +	} +	. = ALIGN(8); +	__toc_end = .;                                                                          +	__stack_end = . ; +} diff --git a/roms/SLOF/board-js2x/llfw/stage2_head.S b/roms/SLOF/board-js2x/llfw/stage2_head.S new file mode 100644 index 00000000..5460bfeb --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/stage2_head.S @@ -0,0 +1,91 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include "macros.h" +#include "../../llfw/boot_abort.h" + +/*#################### defines #####################*/ +#define STACK_SIZE   0x4000 + +/*#################### code ########################*/ +	.text +	.globl .gluon_c_entry +	.globl __toc_start +	.globl __toc_end +	.globl __stack_end +	.globl __bss_start +	.globl __bss_size +	.globl __start + +ASM_ENTRY(__startC) +	/* clear out bss section                */ +        LOAD64(r3, (__bss_start - 8)) +        LOAD64(r4, __bss_size) + +        /* divide __bss_size by 8 to get number */ +        /* of dwords to clear                   */ +        srwi.   r4, r4, 3 +        beq     bsscdone +        li      r5, 0 +        mtctr   r4 +bssc:   stdu    r5, 8(r3) +        bdnz    bssc +bsscdone: +	/* setup stack                          */ +	LOAD64(r1, __stack_end + STACK_SIZE) + +	/* save return address beside stack     */ +	addi	r3, r1, 128 +	mflr	r0 +	std	r0, 0(r3) +	 +	/* setup toc                            */ +	bl	toc_init + +	/* ------------------------------------ */ +	/* jump to c-code                       */ +	/* r10 = cpu_init_slave address - r3    */ +	/* r11 = slave_setup address    - r4    */ +	/* ------------------------------------ */ +	mr	r3, r10 +	mr	r4, r11 +	bl	.early_c_entry + +	/* return to caller...                  */ +	LOAD64(r1, __stack_end + STACK_SIZE) +	addi	r1, r1, 128 +	ld	r3, 0(r1) +	mtlr	r3 +	blr + +	/* #################################### */ +	/* Basic Additional Functions           */ +	/* for extended lib functions see       */ +	/* external library                     */ +	/* #################################### */ +	.align 	2 + +	/* ------------------------------------ */ +	/* updates toc in r2                    */ +	/* ------------------------------------ */ +ASM_ENTRY(toc_init)	 +	LOAD64(r2, __toc_start) +	addi	r2,r2,0x4000 +	addi	r2,r2,0x4000 +	blr + +	/* ------------------------------------ */ +	/* stores arg#1 in r27 and stops        */ +	/* ------------------------------------ */ +ENTRY(do_panic) +ENTRY(halt_sys) +	BOOT_ABORT_R3HINT(ABORT_CANIO, ALTBOOT, msg_e_ierror); diff --git a/roms/SLOF/board-js2x/llfw/stage_s.S b/roms/SLOF/board-js2x/llfw/stage_s.S new file mode 100644 index 00000000..202350f6 --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/stage_s.S @@ -0,0 +1,43 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ +	.text +	.org	0 /* after loading to mem this is at slaveloop_base */ +#	. = 0x3f00 loaded to this addr +	.globl __stage_s_entry + +__stage_s_entry: +	bl	$+4 +	mflr	r4 +	li	r3, 0xff +	not 	r3, r3 +	and	r4, r4, r3 +	li 0,1 ; std 0,0xf8(4) +	li 0,0 ; std 0,0xa0(4) +slaveloop: +	ori 28,28,0x100 +	lis 0,10 +	mtctr 0 +	bdnz $		# do some waiting, to prevent flooding the buses +	lwz 0,0xa0(4) +	cmpw 0,28 +	bne $-20	# wait for our flag + +	lwz 0,0x80(4) +	lwz 3,0xc0(4) +	mtctr 0 +	bctr		# jump to specified address, with specified GPR3 + +#	.quad	0	 +#	.quad	0	 + + + diff --git a/roms/SLOF/board-js2x/llfw/stage_s.lds b/roms/SLOF/board-js2x/llfw/stage_s.lds new file mode 100644 index 00000000..200c1b33 --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/stage_s.lds @@ -0,0 +1,22 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc") +OUTPUT_ARCH(powerpc:common64) + +ENTRY( __stage_s_entry ) + +SECTIONS { +  .text : { +	*(.text) +	  }  +} diff --git a/roms/SLOF/board-js2x/llfw/startup.S b/roms/SLOF/board-js2x/llfw/startup.S new file mode 100644 index 00000000..1357d3fd --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/startup.S @@ -0,0 +1,708 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +# SLOF for JS20/JS21 -- ROM boot code. +# Initial entry point, copy code from flash to cache, memory setup. +# Also sets up serial console and optimizes some settings. + +#include "termctrl.h" +#include <product.h> +#include <xvect.h> +#include <cpu.h> +#include <macros.h> +#include <southbridge.h> + +	.text +	.globl __start +__start: +	/* put rombase in sprg1 ***********************/ + +	bl	postHeader +	.long 0xDEADBEE0 +	.long 0x0       /* size */  +	.long 0x0       /* crc  */ +	.long relTag - __start +postHeader: +	mflr	r3 +	li	r4, 0x7fff +	not	r4, r4 +	and	r3, r3, r4 +	mtsprg	1, r3      /* romfs base */ +	bl	_start + +	.org 0x150 - 0x100 +__startSlave: +	bl setup_cpu +	bl set_ci_bit +#	b slaveWithNumber +	b slave + +	.org 0x180 - 0x100 +__startMaster: +	li 3,0 +	mtsprg	1, r3      /* romfs base */ +	bl setup_cpu +	bl set_ci_bit +	b master + + +	/* FIXME: Also need 0280, 0380, 0f20, etc. */ + +	.irp i, 0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,0x0400,0x0500,0x0600,0x0700, \ +		0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00, \ +		0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, \ +		0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, \ +		0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, \ +		0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00 +	. = \i + +	/* enable this if you get exceptions before the console works    */ +	/* this will allow using the hardware debugger to see where      */ +	/* it traps, and with what register values etc.                  */ +	// b	$ + +	mtsprg	0, r0 +	mfctr	r0 +	mtsprg  2,r0 +	mflr	r0 +// 10 +	mtsprg  3,r0 +	ld	r0, (\i + 0x160)(0) +	mtctr	r0 +	li	r0, \i + 0x100 +// 20 +	bctr + +	. = \i + 0x60 + +	.quad intHandler2C + +	.endr + + +	. = XVECT_M_HANDLER - 0x100 +	.quad 0x00 +	. = XVECT_S_HANDLER - 0x100 + +	.quad 0 + + + +	.org 0x4000 - 0x100 +_start: +	# optimize HID register settings +	bl setup_cpu +	bl set_ci_bit + +	# read semaphore, run as slave if not the first to do so +	li 3,0 ; oris 3,3,0xf800 ; lwz 3,0x60(3) ; andi. 3,3,1 ; beq slave +master: +	# setup flash, serial +	bl setup_sio + +	# early greet +	li	r3, 10 +	bl	putc +	li 3,13 ; bl putc ; li 3,10 ; bl putc ; li 3,'S' ; bl putc + + +	#do we run from ram ? +	mfsprg	r3, 1	/* rombase */ +	cmpdi	r3,0	/* rombase is 0 when running from RAM */ + +	bne copy_to_cache + +	# wait a bit, start scripts are slow...  need to get all cores running! +	lis 3,0x4000 ; mtctr 3 ; bdnz $ + +	# copy 4MB from 0 to temp memory +   lis 4,0x8 ; mtctr 4 ; lis 4,0x200  ; li 3,0 ; addi 4,4,-8 ; addi 3,3,-8 +0:	ldu 5,8(3) ; stdu 5,8(4) ; bdnz 0b + +	lis 4,0x200 +	mtsprg	1, r4 + +	lis 4,0x1 +	lis 3,0x20 ; addi 3,3,0x200-8 ; +	FLUSH_CACHE(r3, r4) + +	lis 4,0x200 +	addi 4,4,copy_to_cache@l +	mtctr 4 +	bctr + +# make all data accesses cache-inhibited +set_ci_bit: +	SETCI(r0) +	blr + +# make all data accesses cacheable +clr_ci_bit: +	CLRCI(r0) +	blr + +# write a character to the serial port +putc: +# always write to serial1 +0:	lbz 0,5(13) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(13) ; eieio + +# read ID register: only if it is a PC87427 (JS21) also use serial2 +	li 4,0 ; oris 4,4,0xf400 +	li 5,0x20 ; stb 5,0x2e(4) ; lbz 5,0x2f(4); cmpdi 5,0xf2 ; bne 1f + +	addi 4,4,0x2f8 +0:	lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio + +1:	blr + +# transfer from running from flash to running from cache +return_cacheable: +	# find and set address to start running from cache, set msr value  +	mflr 3 ; rldicl 3,3,0,44  +jump_cacheable: +	mtsrr0 3 ;  +	mfmsr 3 ; ori 3,3,0x1000 ; mtsrr1 3 # enable MCE, as well + +	# set cacheable insn fetches, jump to cache +	mfspr 3,HID1 ; rldicl 3,3,32,0 ; oris 3,3,0x0020 ; rldicl 3,3,32,0 +	sync ; mtspr HID1,3 ; mtspr HID1,3 ; rfid ; b . + + + + +copy_to_cache: +	# zero the whole cache +	# also, invalidate the insn cache, to clear parity errors +	# 128kB @ 0MB (boot code and vectors from 0x0 up to 0x20000) +	li 4,0x400 ; mtctr 4 ; li 5,0x0 ; bl clr_ci_bit +0:	dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b + +	# 0x2000 to 0x100000/0x80000 (smaller on 970/970FX) +	li 4,0x1C00 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0xC00 +0: +	mtctr 4 ; li 5,0x2000 +0:	dcbz 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b ; bl set_ci_bit + +	# find base address +	bcl 20,31,$+4 ; mflr 31 ; rldicr 31,31,0,43 + +	# copy 1kB from 0x4000 +	li 4,0x80 ; mtctr 4 ;  +	li	5,0x3ff8 +	addi 3,31,0x3ff8 +0:	ldu 4,8(3) ; bl clr_ci_bit ; stdu 4,8(5) ; bl set_ci_bit ; bdnz 0b +	# now start executing from cache -- insn cache is huge speed boost + +	bl return_cacheable + +	li 3,'L' ; bl putc + +	# copy 128kB of flash to cache +	li 4,0x800 ; mtctr 4 ; li 5,0x200-64 ; addi 3,31,0x200-64 ;  +0:	ldu 16,64(3) ; ld 17,8(3) ; ld 18,16(3) ; ld 19,24(3) +	ld 20,32(3) ; ld 21,40(3) ; ld 22,48(3) ; ld 23,56(3) +	bl clr_ci_bit +	stdu 16,64(5) ; std 17,8(5) ; std 18,16(5) ; std 19,24(5) +	std 20,32(5) ; std 21,40(5) ; std 22,48(5) ; std 23,56(5) +	icbi 0,5 ; bl set_ci_bit ; bdnz 0b ; isync + + +	li 3,'O' ; bl putc + +	lis 4,0x20 +	mfsprg	r3,1 +	cmpd r3,r4 +	beq 1f + +	// at 0xf8000000 we decide if it is u3 or u4 +	li 4,0 ; oris 4,4,0xf800 ; lwz 3,0(4) ; srdi 3,3,4 ; cmpdi 3,3 ; bne 0f +	bl setup_mem_u3 +	bl setup_mem_size +	b 1f +0: + +1: +	li 3,'F' ; bl putc + +	# setup nvram logging only when not running from RAM +	mfsprg	r3, 1	/* rombase */ +	cmpdi	r3, 0	/* rombase is 0 when running from RAM */ +	beq	0f + +	// at 0xf8000000 we decide if it is u3 or u4 +	li	r4, 0 +	oris	r4, r4, 0xf800 +	lwz	r3, 0(r4) +	srdi	r3, r3, 4 +	cmpdi	r3, 3	/* 3 means js20; no nvram logging on js20 */ +	beq	0f + +	bl	io_log_init +0: + +	#bl print_mem + +	# data is cacheable by default from now on +	bl clr_ci_bit + + +	/* give live sign *****************************/ +	bl	0f +	.ascii	TERM_CTRL_RESET +	.ascii	TERM_CTRL_CRSOFF +	.ascii  " **********************************************************************" +	.ascii	"\r\n" +	.ascii	TERM_CTRL_BRIGHT +	.ascii	PRODUCT_NAME +	.ascii  " Starting\r\n" +	.ascii  TERM_CTRL_RESET +	.ascii  " Build Date = ", __DATE__, " ", __TIME__ +	.ascii	"\r\n" +	.ascii  " FW Version = " , RELEASE +	.ascii	"\r\n\0" +	.align	2 +0:	mflr	r3 +	bl	io_print + +	# go! +	li	r3,__startC@l +	mtctr	r3 +	mfsprg	r10, 1 +	bctrl + +relTag: +	.ascii  RELEASE +	.ascii	"\0" +	.align	2 + +slave: + +	# get cpu number +	li 3,0 ; oris 3,3,0xf800 ; lwz 28,0x50(3) + +slaveWithNumber: +	# create our slave loop address +	sldi 3,28,24 ; oris 3,3,0x3000 + +	# invalidate the insn cache, to clear parity errors +	# clear the L2 cache as well, to get ECC right +	li 4,0x2000 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0x1000 +0:	mtctr 4 ; mr 5,3 ; bl clr_ci_bit + +0:	dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b + + +	# write a "b $" insn in there +	lis 4,0x4800 ; stw 4,0(3) +/* +	mr 5,3 + +	# jump there +	bl set_ci_bit +	li 13,0 ; oris 13,13,0xf400 +	# device address +	addi 13,13,0x2f8 +	li 3,'O' ; add 3,3,28 ; bl putc +	bl clr_ci_bit +	mr 3,5 +*/ +	b jump_cacheable + + + + +# allow the flash chip to be accessed faster +# initialize the 16550-compatible uart on serial port 1 of the sio +setup_sio: + +	# i/o base address +	li 3,0 ; oris 3,3,0xf400 + +	# i/o base address +	li 3,0 ; oris 3,3,0xf400 + +	# put x-bus in turbo mode +	li 4,0xf1 ; stb 4,0x400(3) ; eieio + + +	# select sio serial1 +	li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio + +	# set base address to 3f8 +	li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio + +	# enable device +	li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio + +	# read ID register: only if it is a PC87427, enable serial2 +	li 4,0x20 ; stb 4,0x2e(3) ; eieio ; lbz 4,0x2f(3) ; cmpdi 4,0xf2 ; bne 0f + +	# select sio serial2 +	li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio + +	# set base address to 2f8 +	li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio + +	# enable device +	li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio + +	# uart @0x2f8 +	addi 3,3,0x2f8 + +	# disable interrupts, fifo off +	li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio + +	# set serial speed +	li 4,0x80 ; stb 4,3(3) ; eieio +	li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio + +	# set 8-N-1, set RTS and DTR +	li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio + +	eieio + +	addi 3,3,-0x2f8 + +	# uart @0x3f8 +0:	addi 3,3,0x3f8 + +	# disable interrupts, fifo off +	li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio + +	# set serial speed +	li 4,0x80 ; stb 4,3(3) ; eieio +	li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio + +	# set 8-N-1, set RTS and DTR +	li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio + +	eieio + +	# save UART base for putc routine +0:	mr 13,3 + +	blr + + + + +# set the HID registers of the 970 for optimally executing from flash +setup_cpu: + +	/* clear all the HV cruft */ +	li	r0, 0 +	sync +	mtspr	HID4, r0 +	isync + +	/* enable dpm, disable attn insn, enable external mce +	 * first, try external time base; if clock doesn't run, switch to +	 * internal */ +	li	r0, 1			/* do the setup for external timebase */ +	rldicl	r0, r0, 44, 0		/* bit 19 has to be set */ +	oris	r0, r0, 0x8000		/* Enable external machine check */ +					/* interrupts (preferred state */ +					/* equals `1'). */ +	sync +	mtspr	HID0, r0 +	isync + +	mftb	r3			/* read the timebase */ +	li	r1, 0x4000		/* wait long enough for the external */ +	mtctr	r1			/* timebase (14MHz) to tick a bit */ +	bdnz	$			/* 0x4000 seems to be enough (for now) */ +	mftb	r4			/* read the timebase a second time */ +	cmpld	r3, r4			/* see if it changed */ +	bne	0f +	/* timebase did not change, do the setup for internal */ +	rldicl	r0, r0, 19, 1 +	rldicl	r0, r0, 45, 0 +	sync +	mtspr	HID0, r0 +	isync + +0: +	/* enable insn prefetch, speculative table walks */ +	mfspr	r0, HID1 +	rldicl	r0, r0, 20, 0 +	ori	r0, r0, 0x1002 +	mfsprg	r3, 1			/* read rombase */ +	cmpdi	r3, 0			/* check if running from ram */ +	bne	0f +	/* running from ram */ +	/* Enable instruction fetch cacheability control */ +	ori	r0, r0, 0x200 +0: +	rldicl	r0, r0, 44, 0 +	sync +	mtspr	HID1, r0 +	isync + +	/* enable cache parity */ +	mfspr	r0, HID4 +	oris	r0, r0, 0xfff0 +	xoris	r0, r0, 0xfff0 +	sync +	mtspr	HID4, r0 +	isync + +	/* exception offset at 0 */ +	li	r3, 0 +	mtspr	HIOR, r3 + +	blr + +C_ENTRY(proceedInterrupt) + +	ld      r3,exception_stack_frame@got(r2) +	ld	r1,0(r3) + +	.irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ +	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \ +		27, 28, 29, 30, 31 +	ld	r\i, 0x30+\i*8 (r1) +	.endr + +	ld	r14,0x138(r1); +	mtsrr0	r14 + +	ld	r14,0x140(r1); +	mtsrr1	r14 + +	ld	r14,0x148(r1); +	mtcr	r14 + + +	ld 0,XVECT_M_HANDLER(0) +	mtctr 0 + +	ld	r0,0x30(r1); # restore vector number +	ld	r1,0x38(r1); + +	bctr + +intHandler2C: +	mtctr	r1 # save old stack pointer +	lis	r1,0x4 +	stdu	r1, -0x160(r1) +	.irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ +	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \ +		27, 28, 29, 30, 31 +	std	r\i, 0x30+\i*8 (r1) +	.endr + +	std	r0,0x30(r1);  # save vector number + +	mfctr	r14 +	std	r14,0x38(r1); # save old r1 + +	mfsrr0	r14 +	std	r14,0x138(r1); + +	mfsrr1	r14 +	std	r14,0x140(r1); + +	mfcr	r14 +	std	r14,0x148(r1); + +	mfxer	r14 +	std	r14,0x150(r1); + +	bl toc_init + +	ld      r3,exception_stack_frame@got(r2) +	std     r1,0(r3) + + +	mr 	r3,r0 +	bl .c_interrupt + +	ld	r14,0x138(r1); +	mtsrr0	r14 + +	ld	r14,0x140(r1); +	mtsrr1	r14 + +	ld	r14,0x148(r1); +	mtcr	r14 + +	ld	r14,0x150(r1); +	mtxer	r14 + + +	.irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ +	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \ +		27, 28, 29, 30, 31 +	ld	r\i, 0x30+\i*8 (r1) +	.endr + +	ld	r1,0x38(r1); + +	mfsprg	r0,2 +	mtctr	r0 +	mfsprg	r0,3 +	mtlr	r0 +	mfsprg	r0,0 +	rfid + +/* Set exception handler for given exception vector.   +	r3:	exception vector offset +	r4:	exception handler +*/ +	.globl .set_exception +.set_exception: +	.globl set_exception +set_exception: +    ld r4,0x0(r4) +	.globl .set_exception_asm +.set_exception_asm: +	.globl set_exception_asm +set_exception_asm: +	std	r4, 0x60(r3)	# fixme diff 1f - 0b +	blr + + +setup_mem_u3: +	li 4,0x2000 ; oris 4,4,0xf800 + +	# MemTimingParam -- CAS lat 2.5 / 4 (read-to-read / read-to-write) +	lis 3,0x49e1 ; ori 3,3,0xa000 ; stw 3,0x50(4) + +	# MRSRegCntl -- CAS lat 2.5 +	li 3,0x6a ; stw 3,0xf0(4) + +	# MemBusConfig -- 128 bit bus +	lis 3,0x8500 ; stw 3,0x190(4) + +	# CKDelAdj -- clock delay 75 +	lis 3,0x12c3 ; ori 3,3,0x30cc ; stw 3,0x520(4) + +	# IOModeCntl -- no termination on differential and 3-state drivers +	lis 3,0x0350 ; stw 3,0x530(4) + +	li 3,18 ; mtctr 3 ; addi 5,4,0x5f0 +0:	# DQSDelAdj -- read delay offset -10 +	lis 3,0x3d8f ; ori 3,3,0x6000 ; stwu 3,0x10(5) + +	# DQSDataDelAdj -- write delay offset -32, write data delay offset +15 +	lis 3,0x380e ; ori 3,3,0x003c ; stwu 3,0x10(5) +	bdnz 0b + +	# MemProgCntl -- set all +	lis 3,0xc000 ; stw 3,0xe0(4) + +	eieio + +	blr + + +# read dimm SPDs, program memory size and type +setup_mem_size: +	mflr 14 + +	li 15,0 ; oris 15,15,0xf800 ; li 17,0 +	li 3,0xa0 ; li 4,3 ; li 5,3 ; bl i2c_read +	mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0 +0:	li 3,0xa2 ; li 4,3 ; li 5,3 ; bl i2c_read +	cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f +0:	li 16,0x1e00 +1:	#li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte +	#mr 3,16 ; bl print_hex + +	#li 3,0x20 ; bl print_byte +	sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00 +	stw 3,0x21c0(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x21e0(15) +0:	#bl print_hex +	sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3 +		# slw, not sld, so that empty/bad banks translate into size 0 +	stw 17,0x21d0(15) ; bl add17173 ; stw 17,0x21f0(15) +	andi. 0,16,2 ; beq 0f ; bl add17173 +0:	#bl print_hex + +	li 3,0xa4 ; li 4,3 ; li 5,3 ; bl i2c_read +	mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0 +0:	li 3,0xa6 ; li 4,3 ; li 5,3 ; bl i2c_read +	cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f +0:	li 16,0x1e00 +1:	#li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte +	#mr 3,16 ; bl print_hex + +	#li 3,0x20 ; bl print_byte +	sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00 +	stw 3,0x2200(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x2220(15) +0:	#bl print_hex +	sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3 +	stw 17,0x2210(15) ; bl add17173 ; stw 17,0x2230(15) +	andi. 0,16,2 ; beq 0f ; bl add17173 +0:	#bl print_hex +	#mr 3,17 ; bl print_hex +	stw 17,0x2250(15) ; stw 17,0x2270(15) +	stw 17,0x2290(15) ; stw 17,0x22b0(15) + +	mtlr 14 +	blr + + + + +# print GPR3 as 8-digit hex.  uses GPR18,19 +print_hex: +	mflr 18 ; mr 19,3 ; li 3,8 ; mtctr 3 +1:	rlwinm 3,19,4,28,31 ; sldi 19,19,4 +	cmpdi 3,0xa ; blt 0f ; addi 3,3,0x27 +0:	addi 3,3,0x30 ; bl putc +	bdnz 1b ; mtlr 18 ; blr + + +# i2c stuff uses GPR20..GPR24 + +# terminate any i2c transaction, at any point during that transaction +i2c_stop: +0:	lwz 3,0x30(20) ; stw 3,0x30(20) ; andi. 3,3,4 ; beq 0b +	mr 3,21 ; mr 4,22 ; mtlr 24 ; eieio ; blr + +# do a combined-mode read +# in: GPR3 = addr, GPR4 = subaddr, GPR5 = len +# out: GPR3 = error, GPR4 = result (right-aligned, msb) +i2c_read: +	mflr 24 +	li 20,0x1000 ; oris 20,20,0xf800	# uni-n i2c base +	mr 21,3 ; mr 22,4 ; mr 23,5		# save params +	li 4,0xc ; stw 4,0(20)			# set mode (combined) +	ori 4,21,1 ; stw 4,0x50(20)		# set addr, read +	stw 22,0x60(20)				# set subaddr +	li 4,2 ; stw 4,0x10(20) ; eieio		# start address phase +	li 21,1					# error +	li 22,0					# result accumulator +0:	lwz 3,0x30(20) ; andi. 3,3,2 ; beq 0b	# wait until sent +	lwz 3,0x20(20) ; andi. 3,3,2 ; beq i2c_stop # check result +	li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0 +0:	stw 4,0x10(20)				# AAK for next byte (or not) +	li 4,2 ; stw 4,0x30(20) ; eieio		# ack address phase +i2c_read_loop: +	lwz 3,0x30(20) ; andi. 3,3,1 ; beq 1f	# if byte recv'd: +	subi 23,23,1 ; sldi 22,22,8		# shift byte accum +	lwz 3,0x70(20) ; rlwimi 22,3,0,24,31	# get byte +	cmpdi 23,0 ; bne 0f ; li 21,0 ; b i2c_stop # all done +0:	li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0 +0:      stw 4,0x10(20)				# AAK for next byte (or not) +	li 4,1 ; stw 4,0x30(20) ; eieio		# ack data phase +1:	lwz 3,0x30(20) ; andi. 3,3,4 ; beq i2c_read_loop +	li 4,0 ; stw 4,0x10(20) ; eieio ; b i2c_stop # stop bit received + +add17173: # add GPR3 into GPR17; if passing 2GB (0x10000000), add another 2GB. +	lis 0,0x1000 ; cmpld 17,0 ; add 17,17,3 ; bgtlr +	cmpld 17,0 ; blelr ; add 17,17,0 ; blr + +io_log_init: +	LOAD64(r3, SB_NVRAM_adr) +	b checkinitLog diff --git a/roms/SLOF/board-js2x/llfw/u4mem.c b/roms/SLOF/board-js2x/llfw/u4mem.c new file mode 100644 index 00000000..68bba56d --- /dev/null +++ b/roms/SLOF/board-js2x/llfw/u4mem.c @@ -0,0 +1,4065 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ +#include <stdint.h> +#include <hw.h> +#include <stdio.h> +#include "stage2.h" +#include <cpu.h> +#include <string.h> + +/* + * compiler switches + ******************************************************************************* + */ +#define U4_DEBUG +#define U4_INFO +//#define U4_SHOW_REGS + +int io_getchar(char *); + +/* + * version info + */ +static const uint32_t VER    = 2; +static const uint32_t SUBVER = 1; + +/* + * local macros + ******************************************************************************* + */ +// bit shifting in Motorola/IBM bit enumeration format (yaks...) +#define IBIT( nr )		( (uint32_t) 0x80000000 >> (nr) ) +#define BIT( nr )		( (uint32_t) 0x1 << (nr) ) + +/* + * macros to detect the current board layout + */ +#define IS_MAUI		( ( load8_ci( 0xf4000682 ) >> 4 ) == 0 ) +#define IS_BIMINI		( ( load8_ci( 0xf4000682 ) >> 4 ) == 1 ) +#define IS_KAUAI		( ( load8_ci( 0xf4000682 ) >> 4 ) == 2 ) + +/* + * local constants + ******************************************************************************* + */ + +/* + * u4 base address + */ +#define U4_BASE_ADDR		((uint64_t) 0xf8000000 ) +#define u4reg( reg )		(U4_BASE_ADDR + (uint64_t) (reg)) + +/* + * I2C registers + */ +#define I2C_MODE_R		u4reg(0x1000) +#define I2C_CTRL_R		u4reg(0x1010) +#define I2C_STAT_R		u4reg(0x1020) +#define I2C_ISR_R		u4reg(0x1030) +#define I2C_ADDR_R		u4reg(0x1050) +#define I2C_SUBA_R		u4reg(0x1060) +#define I2C_DATA_R		u4reg(0x1070) + +/* + * clock control registers & needed bits/masks + */ +#define ClkCntl_R		u4reg(0x0800) +#define PLL2Cntl_R		u4reg(0x0860) + +/* + * clock control bits & masks + */ +#define CLK_DDR_CLK_MSK		(IBIT(11) | IBIT(12) | IBIT(13)) + +/* + * memory controller registers + */ +#define RASTimer0_R		u4reg(0x2030) +#define RASTimer1_R		u4reg(0x2040) +#define CASTimer0_R		u4reg(0x2050) +#define CASTimer1_R		u4reg(0x2060) +#define MemRfshCntl_R		u4reg(0x2070) +#define MemProgCntl_R		u4reg(0x20b0) +#define Dm0Cnfg_R		u4reg(0x2200) +#define Dm1Cnfg_R		u4reg(0x2210) +#define Dm2Cnfg_R		u4reg(0x2220) +#define Dm3Cnfg_R		u4reg(0x2230) +#define MemWrQCnfg_R		u4reg(0x2270) +#define MemArbWt_R		u4reg(0x2280) +#define UsrCnfg_R		u4reg(0x2290) +#define MemRdQCnfg_R		u4reg(0x22a0) +#define MemQArb_R		u4reg(0x22b0) +#define MemRWArb_R		u4reg(0x22c0) +#define MemBusCnfg_R		u4reg(0x22d0) +#define MemBusCnfg2_R		u4reg(0x22e0) +#define ODTCntl_R        	u4reg(0x23a0) +#define MemModeCntl_R		u4reg(0x2500) +#define MemPhyModeCntl_R 	u4reg(0x2880) +#define CKDelayL_R		u4reg(0x2890) +#define CKDelayU_R		u4reg(0x28a0) +#define IOPadCntl_R      	u4reg(0x29a0) +#define ByteWrClkDelC0B00_R	u4reg(0x2800) +#define ByteWrClkDelC0B01_R	u4reg(0x2810) +#define ByteWrClkDelC0B02_R	u4reg(0x2820) +#define ByteWrClkDelC0B03_R	u4reg(0x2830) +#define ByteWrClkDelC0B04_R	u4reg(0x2900) +#define ByteWrClkDelC0B05_R	u4reg(0x2910) +#define ByteWrClkDelC0B06_R	u4reg(0x2920) +#define ByteWrClkDelC0B07_R	u4reg(0x2930) +#define ByteWrClkDelC0B16_R	u4reg(0x2980) +#define ByteWrClkDelC0B08_R	u4reg(0x2a00) +#define ByteWrClkDelC0B09_R	u4reg(0x2a10) +#define ByteWrClkDelC0B10_R	u4reg(0x2a20) +#define ByteWrClkDelC0B11_R	u4reg(0x2a30) +#define ByteWrClkDelC0B12_R	u4reg(0x2b00) +#define ByteWrClkDelC0B13_R	u4reg(0x2b10) +#define ByteWrClkDelC0B14_R	u4reg(0x2b20) +#define ByteWrClkDelC0B15_R	u4reg(0x2b30) +#define ByteWrClkDelC0B17_R	u4reg(0x2b80) +#define ReadStrobeDelC0B00_R	u4reg(0x2840) +#define ReadStrobeDelC0B01_R	u4reg(0x2850) +#define ReadStrobeDelC0B02_R	u4reg(0x2860) +#define ReadStrobeDelC0B03_R	u4reg(0x2870) +#define ReadStrobeDelC0B04_R	u4reg(0x2940) +#define ReadStrobeDelC0B05_R	u4reg(0x2950) +#define ReadStrobeDelC0B06_R	u4reg(0x2960) +#define ReadStrobeDelC0B07_R	u4reg(0x2970) +#define ReadStrobeDelC0B16_R	u4reg(0x2990) +#define ReadStrobeDelC0B08_R	u4reg(0x2a40) +#define ReadStrobeDelC0B09_R	u4reg(0x2a50) +#define ReadStrobeDelC0B10_R	u4reg(0x2a60) +#define ReadStrobeDelC0B11_R	u4reg(0x2a70) +#define ReadStrobeDelC0B12_R	u4reg(0x2b40) +#define ReadStrobeDelC0B13_R	u4reg(0x2b50) +#define ReadStrobeDelC0B14_R	u4reg(0x2b60) +#define ReadStrobeDelC0B15_R	u4reg(0x2b70) +#define ReadStrobeDelC0B17_R	u4reg(0x2b90) +#define MemInit00_R		u4reg(0x2100) +#define MemInit01_R		u4reg(0x2110) +#define MemInit02_R		u4reg(0x2120) +#define MemInit03_R		u4reg(0x2130) +#define MemInit04_R		u4reg(0x2140) +#define MemInit05_R		u4reg(0x2150) +#define MemInit06_R		u4reg(0x2160) +#define MemInit07_R		u4reg(0x2170) +#define MemInit08_R		u4reg(0x2180) +#define MemInit09_R		u4reg(0x2190) +#define MemInit10_R		u4reg(0x21a0) +#define MemInit11_R		u4reg(0x21b0) +#define MemInit12_R		u4reg(0x21c0) +#define MemInit13_R		u4reg(0x21d0) +#define MemInit14_R		u4reg(0x21e0) +#define MemInit15_R		u4reg(0x21f0) +#define CalConf0_R		u4reg(0x29b0) +#define CalConf1_R		u4reg(0x29c0) +#define MeasStatusC0_R		u4reg(0x28f0) +#define MeasStatusC1_R		u4reg(0x29f0) +#define MeasStatusC2_R		u4reg(0x2af0) +#define MeasStatusC3_R		u4reg(0x2bf0) +#define CalC0_R			u4reg(0x28e0) +#define CalC1_R			u4reg(0x29e0) +#define CalC2_R			u4reg(0x2ae0) +#define CalC3_R			u4reg(0x2be0) +#define RstLdEnVerniersC0_R	u4reg(0x28d0) +#define RstLdEnVerniersC1_R	u4reg(0x29d0) +#define RstLdEnVerniersC2_R	u4reg(0x2ad0) +#define RstLdEnVerniersC3_R	u4reg(0x2bd0) +#define ExtMuxVernier0_R	u4reg(0x28b0) +#define ExtMuxVernier1_R	u4reg(0x28c0) +#define OCDCalCmd_R		u4reg(0x2300) +#define OCDCalCntl_R		u4reg(0x2310) +#define MCCR_R      		u4reg(0x2440) +#define MSRSR_R     		u4reg(0x2410) +#define MSRER_R     		u4reg(0x2420) +#define MSPR_R      		u4reg(0x2430) +#define MSCR_R      		u4reg(0x2400) +#define MEAR0_R			u4reg(0x2460) +#define MEAR1_R			u4reg(0x2470) +#define MESR_R			u4reg(0x2480) +#define MRSRegCntl_R		u4reg(0x20c0) +#define EMRSRegCntl_R		u4reg(0x20d0) +#define APIMemRdCfg_R		u4reg(0x30090) +#define APIExcp_R		u4reg(0x300a0) + +/* + * common return values + */ +#define RET_OK			 0 +#define RET_ERR			-1 +#define RET_ACERR_CE		-1 +#define RET_ACERR_UEWT		-2 +#define RET_ACERR_UE		-3 + +/* + * 'DIMM slot populated' indicator + */ +#define SL_POP			1 + +/* + * spd buffer size + */ +#define SPD_BUF_SIZE		0x40 + +/* + * maximum number of DIMM banks & DIMM groups + */ +#define NUM_SLOTS		8 +#define NUM_BANKS		( NUM_SLOTS / 2 ) +#define MAX_DGROUPS		( NUM_SLOTS / 2 ) +#define SLOT_ADJ()		( ( IS_MAUI ) ? NUM_SLOTS / 4 : NUM_SLOTS / 2 ) + +/* + * values needed for auto calibration + */ +#define MAX_DRANKS		NUM_SLOTS +#define MAX_BLANE		18 +#define MAX_RMD			0xf + +/* + * maximum number of supported CAS latencies + */ +#define NUM_CL			3 + +/* + * min/max supported CL values by U4 + */ +#define U4_MIN_CL		3 +#define U4_MAX_CL		5 + +/* + * DIMM constants + */ +#define DIMM_TYPE_MSK		BIT(0) +#define DIMM_ORG_x4		BIT(0) +#define DIMM_ORG_x8		BIT(1) +#define DIMM_ORG_x16		BIT(2) +#define DIMM_ORG_MIXx8x16	BIT(30) +#define DIMM_ORG_UNKNOWN	0 +#define DIMM_WIDTH		72 +#define DIMM_BURSTLEN_4		BIT(2) + +/* + * L2 cache size + */ +#define L2_CACHE_SIZE		(uint32_t) 0x100000 + +/* + * scrub types + */ +#define	IMMEDIATE_SCRUB			IBIT(0) +#define	IMMEDIATE_SCRUB_WITH_FILL	( IBIT(0) | IBIT(1) ) +#define	BACKGROUND_SCRUB		( IBIT(1) | ( 0x29 << 16 ) ) + +/* + * I2C starting slave addresses of the DIMM banks + */ +#define I2C_START		0x50 + +/* + * Index to the speed dependend DIMM settings + */ +enum +{ +	SPEED_IDX_400 = 0, +	SPEED_IDX_533, +	SPEED_IDX_667, +	NUM_SPEED_IDX +}; + +/* + * number of read/write strobes of the U4 + */ +#define NUM_STROBES 		18 + +/* + * 2GB hole definition + */ +static const uint64_t _2GB = (uint64_t) 0x80000000; + +/* + * local types + ******************************************************************************* + */ +/* + * DIMM definition + */ +typedef struct +{ +	uint32_t m_pop_u32;		// set if bank is populated +	uint32_t m_bank_u32;		// bank number +	uint32_t m_clmsk_u32;		// mask of supported CAS latencies +	uint32_t m_clcnt_u32;		// number of supporetd CAS latencies +	uint32_t m_clval_pu32[NUM_CL];	// values of supporeted CAS latencies +	uint32_t m_speed_pu32[NUM_CL];	// speed (Mhz) at CAS latency of same index +	uint32_t m_size_u32;		// chip size in Mb +	uint32_t m_rank_u32;		// # of ranks, total size = chip size*rank +	uint32_t m_orgmsk_u32;		// data organisation (x4, x8, x16) (mask) +	uint32_t m_orgval_u32;		// data organisation (value) +	uint32_t m_width_u32;		// data width +	uint32_t m_ecc_u32;             // set if ecc +	uint32_t m_type_u32;		// rdimm or udimm +	uint32_t m_burst_u32;		// supported burst lengths +	uint32_t m_bankcnt_u32;		// number of banks + +	/* +	 * the following timing values are all in 1/100ns +	 */ +	uint32_t m_tCK_pu32[NUM_CL]; +	uint32_t m_tRAS_u32; +	uint32_t m_tRTP_u32; +	uint32_t m_tRP_u32; +	uint32_t m_tWR_u32; +	uint32_t m_tRRD_u32; +	uint32_t m_tRC_u32; +	uint32_t m_tRCD_u32; +	uint32_t m_tWTR_u32; +	uint32_t m_tREF_u32; +	uint32_t m_tRFC_u32; +}	dimm_t; + +/* + * DIMM group definition + */ +typedef struct +{ +	uint32_t  m_size_u32;		// group size in MB +	uint32_t  m_start_u32;		// in 128Mb granularity +	uint32_t  m_end_u32;		// in 128Mb granularity +	uint32_t  m_ss_u32;		// single sided/double sided +	uint32_t  m_csmode_u32;		// selected CS mode for this group +	uint32_t  m_add2g_u32; +	uint32_t  m_sub2g_u32; +	uint32_t  m_memmd_u32;		// selected mem mode for this group +	uint32_t  m_dcnt_u32;		// number of DIMMs in group +	dimm_t   *m_dptr[NUM_SLOTS]; +}	dgroup_t; + +/* + * auto calibration result structure + */ +typedef struct +{ +	uint32_t m_MemBusCnfg_u32; +	uint32_t m_MemBusCnfg2_u32; +	uint32_t m_RstLdEnVerniers_pu32[4]; +}	auto_calib_t; + +/* + * ECC error structure + */ +typedef struct +{ +	int32_t  m_err_i32; +	uint32_t m_uecnt_u32;		// number of uncorrectable errors +	uint32_t m_cecnt_u32;		// number of correctable errors +	uint32_t m_rank_u32;		// erroneous rank +	uint32_t m_col_u32;		// erroneous column +	uint32_t m_row_u32;		// erroneous row +	uint32_t m_bank_u32;		// erroneous bank +}	eccerror_t; + +/* + * U4 register setup structure + */ +typedef struct +{ +	/* +	 * external MUX delays +	 */ +	uint32_t RRMux; +	uint32_t WRMux; +	uint32_t WWMux; +	uint32_t RWMux; + +	/* +	 * default Wr/Rd Queue & Arbiter register settings +	 */ +	uint32_t MemRdQCnfg; +	uint32_t MemWrQCnfg; +	uint32_t MemQArb; +	uint32_t MemRWArb; + +	/* +	 * misc fixed register values +	 */ +	uint32_t ODTCntl; +	uint32_t IOPadCntl; +	uint32_t MemPhyModeCntl; +	uint32_t OCDCalCntl; +	uint32_t OCDCalCmd; +	uint32_t CKDelayL; +	uint32_t CKDelayU; +	uint32_t MemBusCnfg; +	uint32_t CAS1Dly0; +	uint32_t CAS1Dly1; +	uint32_t ByteWrClkDel[NUM_STROBES]; +	uint32_t ReadStrobeDel[NUM_STROBES]; +} reg_statics_t; + +/* + * local variables + ******************************************************************************* + */ +static dimm_t	 m_dimm[NUM_SLOTS]; +static dimm_t	 m_gendimm; +static uint32_t  m_dcnt_u32; +static dimm_t   *m_dptr[NUM_SLOTS]; +static uint32_t  m_bankoff_u32; +static uint32_t	 m_bankpop_u32[NUM_BANKS]; +static uint32_t  m_dclidx_u32; +static uint32_t  m_dgrcnt_u32; +static dgroup_t  m_dgroup[MAX_DGROUPS]; +static dgroup_t *m_dgrptr[MAX_DGROUPS]; +static uint64_t  m_memsize_u64;	// memsize in bytes + +/* + * local functions + ******************************************************************************* + */ +static void +progbar( void ) +{ +	static uint8_t  bar[] = +			{ '|', '/', '-', '\\', 0 }; +	static uint32_t idx = 0; + +	printf( "\b%c", bar[idx] ); + +	if( bar[++idx] == 0 ) { +		idx = 0; +	} + +} + +static void +or32_ci( uint64_t r, uint32_t m ) +{ +	uint32_t v; + +	v  = load32_ci( r ); +	v |= m; +	store32_ci( r, v ); +} + +static void +and32_ci( uint64_t r, uint32_t m ) +{ +	uint32_t v; + +	v  = load32_ci( r ); +	v &= m; +	store32_ci( r, v ); +} + +static void +dly( uint64_t volatile f_wait_u64 ) \ +{ +	while( f_wait_u64 ) { +		f_wait_u64--; +	} +} + +/* + * local i2c access functions + */ +static void +i2c_term( void ) +{ +	uint32_t l_stat_u32; + +	/* +	 * clear out all pending int's and wait +	 * for the stop condition to occur +	 */ +	do { +		l_stat_u32 = load32_ci( I2C_ISR_R ); +		store32_ci( I2C_ISR_R, l_stat_u32 ); +	} while( ( l_stat_u32 & IBIT(29) ) == 0 ); + +} + +static int32_t +i2c_read( uint32_t f_addr_u32, uint32_t f_suba_u32, uint8_t *f_buf_pu08, uint32_t f_len_u32 ) +{ +	uint32_t  l_val_u32; +	int32_t   l_ret_i32 = 1; + +	/* +	 * parameter check +	 */ +	if( ( f_addr_u32 > (uint32_t) 0x7f ) || +	    ( f_suba_u32 > (uint32_t) 0xff ) || +	    ( f_len_u32 == (uint32_t) 0x00 ) ) { +		return RET_ERR; +	} + +	/* +	 * set I2C Interface to combined mode +	 */ +	store32_ci( I2C_MODE_R, IBIT(28) | IBIT(29) ); + +	/* +	 * set address, subaddress & read mode +	 */ +	store32_ci( I2C_ADDR_R, ( f_addr_u32 << 1 ) | (uint32_t) 0x1 ); +	store32_ci( I2C_SUBA_R, f_suba_u32 ); + +	/* +	 * start address transmission phase +	 */ +	store32_ci( I2C_CTRL_R, IBIT(30) ); + +	/* +	 * wait for address transmission to finish +	 */ +	do { +		l_val_u32 = load32_ci( I2C_ISR_R ); +	} while( ( l_val_u32 & IBIT(30) ) == 0 ); + +	/* +	 * check for success +	 */ +	if( ( load32_ci( I2C_STAT_R ) & IBIT(30) ) == 0 ) { +		i2c_term(); +		return RET_ERR; +	} else { +		// send ack +		store32_ci( I2C_CTRL_R, IBIT(31) ); +		// clear int +		store32_ci( I2C_ISR_R, IBIT(30) ); +	} + +	/* +	 * read data +	 */ +	while( l_ret_i32 > 0 ) { +		l_val_u32 = load32_ci( I2C_ISR_R ); + +		if( ( l_val_u32 & IBIT(31) ) != 0 ) { +			// data was received +			*f_buf_pu08 = ( uint8_t ) load32_ci( I2C_DATA_R ); + +			f_buf_pu08++; +			f_len_u32--; + +			/* +			 * continue when there is more data to read or +			 * exit if not +			 */ +			if( f_len_u32 != 0 ) { +				// send ack +				store32_ci( I2C_CTRL_R, IBIT(31) ); +				// clear int +				store32_ci( I2C_ISR_R, IBIT(31) ); +			} else { +				// send nack +				store32_ci( I2C_CTRL_R, 0 ); +				// set exit flag +				l_ret_i32 = RET_OK; +			} + +		} else if( ( l_val_u32 & IBIT(29) ) != 0 ) { +			// early stop condition +			// set exit flag +			l_ret_i32 = RET_ERR; +		} + +	}; + +	i2c_term(); + +	return( l_ret_i32 ); +} + +static uint32_t +i2c_get_slot( uint32_t i2c_addr ) +{ +	uint32_t slot; + +	slot = ( i2c_addr - I2C_START ) / 2; + +	if( ( i2c_addr & 0x1 ) != 0 ) { +		slot += SLOT_ADJ(); +	} + +	return slot; +} + +/* + * 'serial presence detect' interpretation functions + */ +static uint32_t +ddr2_get_dimm_rank( uint8_t *f_spd_pu08 ) +{ +	static const int RANK_IDX = (int) 5; + +	return (uint32_t) ( f_spd_pu08[RANK_IDX] & 0x3 ) + 1; +} + +static uint32_t +ddr2_get_dimm_size( uint8_t *f_spd_pu08 ) +{ +	static const int SIZE_IDX   = (int) 31; +	uint8_t          l_smsk_u08; +	uint32_t         i; + +	l_smsk_u08 = ( f_spd_pu08[SIZE_IDX] << 3 ) | +		     ( f_spd_pu08[SIZE_IDX] >> 5 ); + +	for( i = 0; ( ( l_smsk_u08 & ( (uint8_t) 0x1 << i ) ) == 0 ) ; i++ ); + +	return (uint32_t) 0x80 << i; +} + +static uint32_t +ddr2_get_dimm_type( uint8_t *f_spd_pu08 ) +{ +	static const int TYPE_IDX = (int) 20; + +	return (uint32_t) f_spd_pu08[TYPE_IDX] & DIMM_TYPE_MSK; +} + +static uint32_t +ddr2_get_dimm_org( uint8_t *f_spd_pu08, uint32_t /*out*/ *f_omsk_pu32 ) +{ +	static const int ORG_IDX   = (int) 13; +	uint32_t         l_ret_u32 = (uint32_t) f_spd_pu08[ORG_IDX]; + +	if( l_ret_u32 == 4 ) { +		*f_omsk_pu32  = DIMM_ORG_x4; +	} else if( l_ret_u32 == 8 ) { +		*f_omsk_pu32  = DIMM_ORG_x8; +		*f_omsk_pu32 |= DIMM_ORG_MIXx8x16; +	} else if( l_ret_u32 == 16 ) { +		*f_omsk_pu32  = DIMM_ORG_x16; +		*f_omsk_pu32 |= DIMM_ORG_MIXx8x16; +	} else { +		*f_omsk_pu32  = DIMM_ORG_UNKNOWN; +		 l_ret_u32    = (uint32_t) ~0; +	} + +	return l_ret_u32; +} + +static uint32_t +ddr2_get_dimm_width( uint8_t *f_spd_pu08 ) +{ +	static const int WIDTH_IDX = (int) 6; + +	return (uint32_t) f_spd_pu08[WIDTH_IDX]; +} + +static uint32_t +ddr2_get_dimm_ecc( uint8_t *f_spd_pu08 ) +{ +	static const int ECC_IDX = (int) 11; + +	return ( f_spd_pu08[ECC_IDX] & BIT(1) ) != 0; +} + +static uint32_t +ddr2_get_dimm_burstlen( uint8_t *f_spd_pu08 ) +{ +	static const int BURST_IDX = (int) 16; + +	return (uint32_t) f_spd_pu08[BURST_IDX]; +} + +static void +ddr2_get_dimm_speed( dimm_t *f_dimm, uint8_t *f_spd_pu08 ) +{ +	static const int      SPEED_IDX[] = { 25, 23, 9 }; +	static const uint32_t NS[]        = { 25, 33, 66, 75 }; +	uint8_t               l_tmp_u08; +	uint32_t	      l_dspeed_u32; +	uint32_t	      idx = 0; +	uint32_t	      i; + +	for( i = NUM_CL - f_dimm->m_clcnt_u32; i < NUM_CL; i++ ) { +		l_tmp_u08     = f_spd_pu08[SPEED_IDX[i]]; +		l_dspeed_u32  = (uint32_t) ( l_tmp_u08 >> 4 ) * 100; +		l_tmp_u08    &= (uint8_t) 0xf; + +		if( l_tmp_u08 >= (uint8_t) 10 ) { +			l_dspeed_u32 += NS[l_tmp_u08 - 10]; +		} else { +			l_dspeed_u32 += (uint32_t) l_tmp_u08 * 10; +		} + +		f_dimm->m_tCK_pu32[idx]    = l_dspeed_u32; +		f_dimm->m_speed_pu32[idx]  = (uint32_t) 2000000 / l_dspeed_u32; +		f_dimm->m_speed_pu32[idx] += (uint32_t) 5; +		f_dimm->m_speed_pu32[idx] /= (uint32_t) 10; +		idx++; +	} + +} + +static void +ddr2_get_dimm_timings( dimm_t *f_dimm, uint8_t *f_spd_pu08 ) +{ +	static const uint32_t NS[]  = { 00, 25, 33, 50, 66, 75, 00, 00 }; +	static const uint32_t USMUL = (uint32_t) 390625; +	static const int tREF_IDX   = (int) 12; +	static const int tRP_IDX    = (int) 27; +	static const int tRRD_IDX   = (int) 28; +	static const int tRCD_IDX   = (int) 29; +	static const int tRAS_IDX   = (int) 30; +	static const int tWR_IDX    = (int) 36; +	static const int tWTR_IDX   = (int) 37; +	static const int tRTP_IDX   = (int) 38; +	static const int tRC_IDX    = (int) 41;	// & 40 +	static const int tRFC_IDX   = (int) 42;	// & 40 + +	uint32_t         l_tmp_u32; + +	f_dimm->m_tRP_u32  = (uint32_t) f_spd_pu08[tRP_IDX]  *  25; +	f_dimm->m_tRRD_u32 = (uint32_t) f_spd_pu08[tRRD_IDX] *  25; +	f_dimm->m_tRCD_u32 = (uint32_t) f_spd_pu08[tRCD_IDX] *  25; +	f_dimm->m_tWR_u32  = (uint32_t) f_spd_pu08[tWR_IDX]  *  25; +	f_dimm->m_tWTR_u32 = (uint32_t) f_spd_pu08[tWTR_IDX] *  25; +	f_dimm->m_tRTP_u32 = (uint32_t) f_spd_pu08[tRTP_IDX] *  25; +	f_dimm->m_tRAS_u32 = (uint32_t) f_spd_pu08[tRAS_IDX] * 100; + +	l_tmp_u32          = (uint32_t) ( f_spd_pu08[tRC_IDX - 1] >> 4 ); +	l_tmp_u32         &= (uint32_t) 0x7; +	f_dimm->m_tRC_u32  = (uint32_t) f_spd_pu08[tRC_IDX] * 100 + +			   		NS[l_tmp_u32]; + +	l_tmp_u32	    = (uint32_t) f_spd_pu08[tRFC_IDX - 2]; +	l_tmp_u32          &= (uint32_t) 0xf; +	f_dimm->m_tRFC_u32  = (uint32_t) 256 * ( l_tmp_u32 & (uint32_t) 0x1 ); +	f_dimm->m_tRFC_u32 += (uint32_t) f_spd_pu08[tRFC_IDX]; +	f_dimm->m_tRFC_u32 *= 100; +	l_tmp_u32         >>= 1; +	f_dimm->m_tRFC_u32 += NS[l_tmp_u32]; + +	l_tmp_u32           = (uint32_t) f_spd_pu08[tREF_IDX]; +	l_tmp_u32          &= (uint32_t) 0x7f; + +	if( l_tmp_u32 == 0 ) { +		l_tmp_u32 = (uint32_t) 2; +	} else if( l_tmp_u32 <= (uint32_t) 2 ) { +		l_tmp_u32--; +	} + +	f_dimm->m_tREF_u32 = ( l_tmp_u32 + 1 ) * USMUL; +} + +static uint32_t +ddr2_get_banks( uint8_t *f_spd_pu08 ) +{ +	static const int BANK_IDX = (int) 17; + +	return (uint32_t) f_spd_pu08[BANK_IDX]; +} + +static uint32_t +ddr2_get_cl_mask( uint8_t *f_spd_pu08 ) +{ +	static const int CL_IDX = (int) 18; + +	return (uint32_t) f_spd_pu08[CL_IDX]; +} + +static void +ddr2_get_cl( dimm_t *f_dimm ) +{ +	uint32_t l_clcnt_u32 = 0; +	uint32_t i; + +	for( i = 0; ( i < 8 ) && ( l_clcnt_u32 < NUM_CL ) ; i++ ) { + +		if( ( f_dimm->m_clmsk_u32 & ( (uint32_t) 0x1 << i ) ) != 0 ) { +			f_dimm->m_clval_pu32[l_clcnt_u32] = i; +			l_clcnt_u32++; +		} + +	} + +	f_dimm->m_clcnt_u32 = l_clcnt_u32; +} + +static uint32_t +ddr2_cl2speed( dimm_t *f_dimm, uint32_t f_cl_u32, uint32_t *f_tCK_pu32 ) +{ +	uint32_t i; + +	for(i = 0; (i < NUM_CL) && (f_dimm->m_clval_pu32[i] != f_cl_u32); i++); + +	if( i == NUM_CL ) { +		return (uint32_t) ~0; +	} + +	*f_tCK_pu32 = f_dimm->m_tCK_pu32[i]; + +	return f_dimm->m_speed_pu32[i]; +} + +static void +ddr2_setupDIMM( dimm_t *f_dimm, uint32_t f_bank_u32, uint8_t *f_spd_pu08 ) +{ +	f_dimm->m_pop_u32     = SL_POP; +	f_dimm->m_bank_u32    = f_bank_u32; +	f_dimm->m_size_u32    = ddr2_get_dimm_size( f_spd_pu08 ); +	f_dimm->m_rank_u32    = ddr2_get_dimm_rank( f_spd_pu08 ); +	f_dimm->m_type_u32    = ddr2_get_dimm_type( f_spd_pu08 ); +	f_dimm->m_orgval_u32  = ddr2_get_dimm_org( f_spd_pu08, &f_dimm->m_orgmsk_u32 ); +	f_dimm->m_width_u32   = ddr2_get_dimm_width( f_spd_pu08 ); +	f_dimm->m_ecc_u32     = ddr2_get_dimm_ecc( f_spd_pu08 ); +	f_dimm->m_burst_u32   = ddr2_get_dimm_burstlen( f_spd_pu08 ); +	f_dimm->m_clmsk_u32   = ddr2_get_cl_mask( f_spd_pu08 ); +	f_dimm->m_bankcnt_u32 = ddr2_get_banks( f_spd_pu08 ); + +	ddr2_get_cl( f_dimm ); +	ddr2_get_dimm_speed( f_dimm, f_spd_pu08 ); +	ddr2_get_dimm_timings( f_dimm, f_spd_pu08 ); +} + +static int32_t +ddr2_checkSPD( uint8_t *f_spd_pu08 ) +{ +	uint8_t  crc = 0; +	uint32_t i; + +	for( i = 0; i < SPD_BUF_SIZE - 1; i++ ) { +		crc += f_spd_pu08[i]; +	} + +	if( crc != f_spd_pu08[i] ) { +		return RET_ERR; +	} + +	return RET_OK; +} + +static int32_t +ddr2_readSPDs( void ) +{ +	static const uint32_t MAX_SPD_FAIL = 3; +	uint8_t  l_spdbuf_pu08[SPD_BUF_SIZE]; +	uint32_t l_bankfail_u32 = 0; +	uint32_t l_spdfail_u32  = 0; +	int32_t  l_i2c_i32      = RET_OK; +	int32_t  l_spd_i32      = RET_OK; +	int32_t  ret            = RET_OK; +	uint32_t i; + +	/* +	 * read spd's and detect populated slots +	 */ +	for( i = 0; i < NUM_SLOTS; i++ ) { +		/* +		 * indicate slot as empty +		 */ +		m_dimm[i].m_pop_u32 = 0; + +		/* +		 * check whether bank is switched off +		 */ +		if( ( m_bankoff_u32 & ( 0x1 << ( i / 2 ) ) ) != 0 ) { +			continue; +		} + +		/* +		 * read SPD data +		 */ + +		/* +		 * reset SPD fail counter +		 */ +		l_spdfail_u32 = MAX_SPD_FAIL; +		l_spd_i32     = RET_OK; + +		while( l_spdfail_u32 != 0 ) { +			l_i2c_i32 = i2c_read( I2C_START + i, 0x0, l_spdbuf_pu08, SPD_BUF_SIZE ); + +			if( l_i2c_i32 == RET_OK ) { +				l_spd_i32 = ddr2_checkSPD( l_spdbuf_pu08 ); + +				if( l_spd_i32 == RET_OK ) { +					l_spdfail_u32 = 0; +				} else { +					l_spdfail_u32--; +				} + +			} else { +				l_spdfail_u32--; +			} + +		} + +		if( l_spd_i32 != RET_OK ) { +			#ifdef U4_INFO +			printf( "\r\n  [ERROR -> SPD read failure in slot %u]", +				i2c_get_slot( I2C_START + i ) ); +			#endif + +			l_bankfail_u32 |= ( 0x1 << ( i / 2 ) ); +			ret             = RET_ERR; +		} else if( l_i2c_i32 == RET_OK ) { +			/* +			 * slot is populated +			 */ +			ddr2_setupDIMM( &m_dimm[i], i / 2, l_spdbuf_pu08 ); + +			m_dptr[m_dcnt_u32] = &m_dimm[i]; +			m_dcnt_u32++; +		} + +	} + +	if( ret != RET_OK ) { +		m_bankoff_u32 |= l_bankfail_u32; +		#ifdef U4_INFO +		printf( "\r\n" ); +		#endif +	} + +	return ret; +} + +static int32_t +ddr2_setupDIMMcfg( void ) +{ +	uint32_t  l_tmp_u32; +	uint32_t  l_tmp0_u32; +	uint32_t  l_tmp1_u32; +	uint32_t  i, j, e, b; + +	/* +	 * check wether on board DIMM slot population is valid +	 */ +	e = 0; +	b = 0; +	for( i = 0; i < NUM_SLOTS; i += 2 ) { + +		switch( m_dimm[i].m_pop_u32 + m_dimm[i+1].m_pop_u32 ) { +			case 0: { +				m_bankpop_u32[i/2] = 0; +				break; +			} + +			case 2 * SL_POP: { +				m_bankpop_u32[i/2] = !0; +				b++; +				break; +			} + +			default: { +				#ifdef U4_DEBUG +				printf( "\r\n  [ERROR -> only 1 DIMM installed in bank %u]", i/2 ); +				#endif +				e++; +			} + +		} + +	} + +	/* +	 * return on error +	 */ +	if( e != 0 ) { +		#ifdef U4_DEBUG +		printf( "\r\n" ); +		#endif +		return RET_ERR; +	} + +	if( b == 0 ) { +		#ifdef U4_DEBUG +		printf( "\r\n  [ERROR -> no (functional) memory installed]\r\n" ); +		#endif +		return RET_ERR; +	} + +	/* +	 * check DIMM compatibility +	 * configuration is 128 bit data/128 bit bus +	 * -all DIMMs must be organized as x4 +	 * -all DIMMs must be 72 bit wide with ECC +	 * -all DIMMs must be registered DIMMs (RDIMMs) +	 * -paired DIMMs must have the same # of ranks, size & organization +	 */ + +	/* +	 * check DIMM ranks & sizes +	 */ +	e = 0; +	for( i = 0; i < NUM_SLOTS; i += 2 ) { + +		if( (   m_bankpop_u32[i/2]   != 0	               ) && +		    ( ( m_dimm[i].m_rank_u32 != m_dimm[i+1].m_rank_u32 ) || +		      ( m_dimm[i].m_size_u32 != m_dimm[i+1].m_size_u32 ) ) ) { +			#ifdef U4_DEBUG +			printf( "\r\n  [ERROR -> installed DIMMs in bank %u have different ranks/sizes]", i/2 ); +			#endif +			e++; +		} + +	} + +	/* +	 * return on error +	 */ +	if( e != 0 ) { +		#ifdef U4_DEBUG +		printf( "\r\n" ); +		#endif +		return RET_ERR; +	} + +	/* +	 * check valid DIMM organisation (must be x4) +	 */ +	e = 0; +	for( i = 0; i < m_dcnt_u32; i++ ) { + +		if( ( m_dptr[i]->m_orgmsk_u32 & DIMM_ORG_x4 ) == 0 ) { +			#ifdef U4_DEBUG +			printf( "\r\n  [ERROR -> wrong DIMM organisation in bank %u]", +				m_dptr[i]->m_bank_u32 ); +			#endif +			e++; +		} + +	} + +	/* +	 * return on error +	 */ +	if( e != 0 ) { +		#ifdef U4_DEBUG +		printf( "\r\n" ); +		#endif +		return RET_ERR; +	} + +	e = (uint32_t) ~0; +	for( i = 0; i < m_dcnt_u32; i++ ) { +		e &= m_dptr[i]->m_type_u32; +	} + +	/* +	 * return on error +	 */ +	if( e == 0 ) { +		#ifdef U4_DEBUG +		printf( "\r\n  [ERROR -> installed DIMMs are of different type]\r\n" ); +		#endif +		return RET_ERR; +	} + +	/* +	 * setup generic dimm +	 */ +	m_gendimm.m_type_u32 = e; + +	/* +	 * check valid width, ecc & burst length +	 */ +	e = 0; +	for( i = 0; i < m_dcnt_u32; i++ ) { + +		if( m_dptr[i]->m_width_u32 != DIMM_WIDTH ) { +			#ifdef U4_DEBUG +			printf( "\r\n  [ERROR -> invalid DIMM width in bank %u]", +				m_dptr[i]->m_bank_u32 ); +			#endif +			e++; +		} + +		if( m_dptr[i]->m_ecc_u32 == 0 ) { +			#ifdef U4_DEBUG +			printf( "\r\n  [ERROR -> DIMM(s) do not support ECC in bank %u]", +				m_dptr[i]->m_bank_u32 ); +			#endif +			e++; +		} + +		if( ( m_dptr[i]->m_burst_u32 & DIMM_BURSTLEN_4 ) == 0 ) { +			#ifdef U4_DEBUG +			printf( "\r\n  [ERROR -> DIMM(s) have invalid burst length in bank %u]", +				m_dptr[i]->m_bank_u32 ); +			#endif +			e++; +		} + +	} + +	/* +	 * return on error +	 */ +	if( e != 0 ) { +		#ifdef U4_DEBUG +		printf( "\r\n" ); +		#endif +		return RET_ERR; +	} + +	/* +	 * setup generic dimm +	 */ +	m_gendimm.m_width_u32 = m_dptr[0]->m_width_u32; +	m_gendimm.m_ecc_u32   = m_dptr[0]->m_ecc_u32; +	m_gendimm.m_burst_u32 = m_dptr[0]->m_burst_u32; + +	/* +	 * success +	 */ +	m_gendimm.m_pop_u32 = SL_POP; + +	/* +	 * setup timing parameters +	 */ + +	/* +	 * find smallest common CL value +	 */ +	l_tmp_u32 = (uint32_t) ~0; +	for( i = 0; i < m_dcnt_u32; i++ ) { +		l_tmp_u32 &= m_dptr[i]->m_clmsk_u32; +	} + +	m_gendimm.m_clmsk_u32 = l_tmp_u32; +	ddr2_get_cl( &m_gendimm ); + +	/* +	 * find fastest common DIMM speed for all common CL values +	 */ +	for( i = 0; i < m_gendimm.m_clcnt_u32; i++ ) { +		m_gendimm.m_speed_pu32[i] = (uint32_t) ~0; + +		for( j = 0; j < m_dcnt_u32; j++ ) { +			l_tmp0_u32 = +			ddr2_cl2speed( m_dptr[j], +				       m_gendimm.m_clval_pu32[i], +				       &l_tmp1_u32 ); + +			if( m_gendimm.m_speed_pu32[i] > l_tmp0_u32 ) { +				m_gendimm.m_speed_pu32[i] = l_tmp0_u32; +				m_gendimm.m_tCK_pu32[i]   = l_tmp1_u32; +			} + +		} + +	} + +	/* +	 * check wether cl values are supported by U4 +	 */ +	for( i = 0; i < m_gendimm.m_clcnt_u32; i++ ) { + +		if( ( m_gendimm.m_clval_pu32[i] >= U4_MIN_CL ) && +		    ( m_gendimm.m_clval_pu32[i] <= U4_MAX_CL ) ) { +			break; +		} + +	} + +	if( i == m_gendimm.m_clcnt_u32 ) { +		#ifdef U4_DEBUG +		printf( "\r\n  [ERROR -> DIMM's CL values not supported]\r\n" ); +		#endif +		return RET_ERR; +	} + +	/* +	 * choose cl/speed values to use: prefer speed over CL +	 * i holds smallest supported cl value of u4 already +	 */ +	l_tmp_u32 = 0; +	while( i < m_gendimm.m_clcnt_u32 ) { + +		if( l_tmp_u32 < m_gendimm.m_speed_pu32[i] ) { +			l_tmp_u32    = m_gendimm.m_speed_pu32[i]; +			m_dclidx_u32 = i; +		} + +		i++; +	} + +	/* +	 * choose largest number of banks +	 */ +	m_gendimm.m_bankcnt_u32 = 0; + +	for( i = 0; i < m_dcnt_u32; i++ ) { + +		if( m_gendimm.m_bankcnt_u32 < m_dptr[i]->m_bankcnt_u32 ) { +			m_gendimm.m_bankcnt_u32 = m_dptr[i]->m_bankcnt_u32; +		} + +	} + +	/* +	 * setup fastest possible timing parameters for all DIMMs +	 */ +	m_gendimm.m_tRP_u32  = 0; +	m_gendimm.m_tRRD_u32 = 0; +	m_gendimm.m_tRCD_u32 = 0; +	m_gendimm.m_tWR_u32  = 0; +	m_gendimm.m_tWTR_u32 = 0; +	m_gendimm.m_tRTP_u32 = 0; +	m_gendimm.m_tRAS_u32 = 0; +	m_gendimm.m_tRC_u32  = 0; +	m_gendimm.m_tRFC_u32 = 0; +	m_gendimm.m_tREF_u32 = (uint32_t) ~0; + +	for( i = 0; i < m_dcnt_u32; i++ ) { + +		if( m_gendimm.m_tRP_u32  < m_dptr[i]->m_tRP_u32  ) { +			m_gendimm.m_tRP_u32  = m_dptr[i]->m_tRP_u32; +		} + +		if( m_gendimm.m_tRRD_u32 < m_dptr[i]->m_tRRD_u32 ) { +			m_gendimm.m_tRRD_u32 = m_dptr[i]->m_tRRD_u32; +		} + +		if( m_gendimm.m_tRCD_u32 < m_dptr[i]->m_tRCD_u32 ) { +			m_gendimm.m_tRCD_u32 = m_dptr[i]->m_tRCD_u32; +		} + +		if( m_gendimm.m_tWR_u32  < m_dptr[i]->m_tWR_u32  ) { +			m_gendimm.m_tWR_u32  = m_dptr[i]->m_tWR_u32; +		} + +		if( m_gendimm.m_tWTR_u32 < m_dptr[i]->m_tWTR_u32 ) { +			m_gendimm.m_tWTR_u32 = m_dptr[i]->m_tWTR_u32; +		} + +		if( m_gendimm.m_tRTP_u32 < m_dptr[i]->m_tRTP_u32 ) { +			m_gendimm.m_tRTP_u32 = m_dptr[i]->m_tRTP_u32; +		} + +		if( m_gendimm.m_tRAS_u32 < m_dptr[i]->m_tRAS_u32 ) { +			m_gendimm.m_tRAS_u32 = m_dptr[i]->m_tRAS_u32; +		} + +		if( m_gendimm.m_tRC_u32  < m_dptr[i]->m_tRC_u32  ) { +			m_gendimm.m_tRC_u32  = m_dptr[i]->m_tRC_u32; +		} + +		if( m_gendimm.m_tRFC_u32 < m_dptr[i]->m_tRFC_u32 ) { +			m_gendimm.m_tRFC_u32 = m_dptr[i]->m_tRFC_u32; +		} + +		if( m_gendimm.m_tREF_u32 > m_dptr[i]->m_tREF_u32 ) { +			m_gendimm.m_tREF_u32 = m_dptr[i]->m_tREF_u32; +		} + +	} + +	return RET_OK; +} + +static void +u4_group2dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1 ) +{ +	dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; + +	/* +	 * known conditions at this point: +	 * -at least 2 slots are populated +	 * -the 2 DIMMs are equal +	 * -DIMMs are double sided (2 ranks) +	 * +	 * RESULT: +	 * 1 group of 2 ranks (2 ranks/2 DIMMs) +	 * -> CS mode 1 (one double sided DIMM pair) +	 */ +	l_dgr->m_size_u32   = 2 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); +	l_dgr->m_ss_u32     = 0; +	l_dgr->m_csmode_u32 = 1; +	l_dgr->m_dcnt_u32   = 2; +	l_dgr->m_dptr[0]    = f_dimm0; +	l_dgr->m_dptr[1]    = f_dimm1; + +	m_dgrcnt_u32++; +} + +static void +u4_group2dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1 ) +{ +	dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; + +	/* +	 * known conditions at this point: +	 * -at least 2 slots are populated +	 * -the 2 DIMMs are equal +	 * -DIMMs are single sided (1 rank) +	 * +	 * RESULT: +	 * 1 group of 1 rank (1 rank/2 DIMMs) +	 * -> CS mode 0 (one single sided DIMM pair) +	 */ +	l_dgr->m_size_u32   = 2 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); +	l_dgr->m_ss_u32     = 1; +	l_dgr->m_csmode_u32 = 0; +	l_dgr->m_dcnt_u32   = 2; +	l_dgr->m_dptr[0]    = f_dimm0; +	l_dgr->m_dptr[1]    = f_dimm1; + +	m_dgrcnt_u32++; +} + +static void +u4_group4dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1, +		  dimm_t *f_dimm2, dimm_t *f_dimm3 ) +{ +	dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; + +	/* +	 * known conditions at this point: +	 * -4 slots are populated +	 * -all 4 DIMMs are equal +	 * -DIMMs are double sided (2 ranks) +	 * +	 * RESULT: +	 * 1 group of 4 ranks (2 ranks/2 DIMMs) +	 * -> CS mode 2 (two double sided DIMM pairs) +	 */ +	l_dgr->m_size_u32   = 4 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); +	l_dgr->m_ss_u32     = 0; +	l_dgr->m_csmode_u32 = 2; +	l_dgr->m_dcnt_u32   = 4; +	l_dgr->m_dptr[0]    = f_dimm0; +	l_dgr->m_dptr[1]    = f_dimm1; +	l_dgr->m_dptr[2]    = f_dimm2; +	l_dgr->m_dptr[3]    = f_dimm3; + +	m_dgrcnt_u32++; +} + +static void +u4_group4dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1, +		  dimm_t *f_dimm2, dimm_t *f_dimm3 ) +{ +	dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; + +	/* +	 * known conditions at this point: +	 * -4 slots are populated +	 * -all 4 DIMMs are equal +	 * -DIMMs are single sided (1 rank) +	 * +	 * RESULT: +	 * 1 group of 2 ranks (1 rank/2 DIMMs) +	 * -> CS mode 1 (two single sided DIMM pairs) +	 */ +	l_dgr->m_size_u32   = 4 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); +	l_dgr->m_ss_u32     = 1; +	l_dgr->m_csmode_u32 = 1; +	l_dgr->m_dcnt_u32   = 4; +	l_dgr->m_dptr[0]    = f_dimm0; +	l_dgr->m_dptr[1]    = f_dimm1; +	l_dgr->m_dptr[2]    = f_dimm2; +	l_dgr->m_dptr[3]    = f_dimm3; + +	m_dgrcnt_u32++; +} + +static void +u4_group8dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1, +		  dimm_t *f_dimm2, dimm_t *f_dimm3, +		  dimm_t *f_dimm4, dimm_t *f_dimm5, +		  dimm_t *f_dimm6, dimm_t *f_dimm7 ) +{ +	dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; + +	/* +	 * known conditions at this point: +	 * -8 slots are populated +	 * -all 8 DIMMs are equal +	 * -DIMMs are double sided (2 ranks) +	 * +	 * RESULT: +	 * 1 group of 8 ranks (2 ranks/2 DIMMs) +	 * -> CS mode 3 (four double sided DIMM pairs) +	 */ +	l_dgr->m_size_u32   = 8 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); +	l_dgr->m_ss_u32     = 0; +	l_dgr->m_csmode_u32 = 3; +	l_dgr->m_dcnt_u32   = 8; +	l_dgr->m_dptr[0]    = f_dimm0; +	l_dgr->m_dptr[1]    = f_dimm1; +	l_dgr->m_dptr[2]    = f_dimm2; +	l_dgr->m_dptr[3]    = f_dimm3; +	l_dgr->m_dptr[4]    = f_dimm4; +	l_dgr->m_dptr[5]    = f_dimm5; +	l_dgr->m_dptr[6]    = f_dimm6; +	l_dgr->m_dptr[7]    = f_dimm7; + +	m_dgrcnt_u32++; +} + +static void +u4_group8dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1, +		  dimm_t *f_dimm2, dimm_t *f_dimm3, +		  dimm_t *f_dimm4, dimm_t *f_dimm5, +		  dimm_t *f_dimm6, dimm_t *f_dimm7 ) +{ +	dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; + +	/* +	 * known conditions at this point: +	 * -8 slots are populated +	 * -all 8 DIMMs are equal +	 * -DIMMs are single sided (1 rank) +	 * +	 * RESULT: +	 * 1 group of 4 ranks (1 rank/2 DIMMs) +	 * -> CS mode 2 (four single sided DIMM pairs) +	 */ +	l_dgr->m_size_u32   = 8 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); +	l_dgr->m_ss_u32     = 1; +	l_dgr->m_csmode_u32 = 2; +	l_dgr->m_dcnt_u32   = 8; +	l_dgr->m_dptr[0]    = f_dimm0; +	l_dgr->m_dptr[1]    = f_dimm1; +	l_dgr->m_dptr[2]    = f_dimm2; +	l_dgr->m_dptr[3]    = f_dimm3; +	l_dgr->m_dptr[4]    = f_dimm4; +	l_dgr->m_dptr[5]    = f_dimm5; +	l_dgr->m_dptr[6]    = f_dimm6; +	l_dgr->m_dptr[7]    = f_dimm7; + +	m_dgrcnt_u32++; +} + +static int32_t +u4_Dcmp( dimm_t *f_dimm0, dimm_t *f_dimm1 ) +{ + +	if( ( f_dimm0->m_size_u32 == f_dimm1->m_size_u32 ) && +	    ( f_dimm0->m_rank_u32 == f_dimm1->m_rank_u32 ) ) { +		return RET_OK; +	} + +	return RET_ERR; +} + +static void +u4_group1banks( uint32_t *bidx ) +{ +	uint32_t didx = 2 * bidx[0]; + +	/* +	 * known conditions at this point: +	 * -either DIMMs 0 & 4 or +	 *	   DIMMs 1 & 5 or +	 *	   DIMMs 2 & 6 or +	 *	   DIMMs 3 & 7 are populated +	 * -3 (bimini)/1 (maui) pair of slots is empty +	 * -installed DIMMs are equal +	 */ + +	/* +	 * double/single sided setup +	 */ +	if( m_dimm[didx].m_rank_u32 == 1 ) { +		u4_group2dimmsSS( &m_dimm[didx], &m_dimm[didx+1] ); +	} else { +		u4_group2dimmsDS( &m_dimm[didx], &m_dimm[didx+1] ); +	} + +} + +static void +u4_group2banks( uint32_t *bidx ) +{ +	uint32_t didx0 = 2 * bidx[0]; +	uint32_t didx1 = 2 * bidx[1]; + +	/* +	 * known conditions at this point: +	 * -4 slots are populated +	 */ + +	/* +	 * check wether DIMM banks may be grouped +	 */ +	if( ( ( ( bidx[0] + bidx[1] ) & 0x1 )           != 0 ) && +	    ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx1] ) == 0 ) ) { +		/* +		 * double/single sided setup +		 * NOTE: at this point all DIMMs have the same amount +		 * of ranks, therefore only the # of ranks on DIMM 0 is checked +		 */ +		if( m_dimm[didx0].m_rank_u32 == 1 ) { +			u4_group4dimmsSS( &m_dimm[didx0], &m_dimm[didx0+1], +					  &m_dimm[didx1], &m_dimm[didx1+1]); +		} else { +			u4_group4dimmsDS( &m_dimm[didx0], &m_dimm[didx0+1], +					  &m_dimm[didx1], &m_dimm[didx1+1]); +		} + +	} else { +		u4_group1banks( &bidx[0] ); +		u4_group1banks( &bidx[1] ); +	} + +} + +static void +u4_group3banks( uint32_t *bidx ) +{ + +	if(        ( bidx[0] == 0 ) && ( bidx[1] == 1 ) ) { +		u4_group2banks( &bidx[0] ); +		u4_group1banks( &bidx[2] ); +	} else if( ( bidx[1] == 2 ) && ( bidx[2] == 3 ) ) { +		u4_group2banks( &bidx[1] ); +		u4_group1banks( &bidx[0] ); +	} + +} + +static void +u4_group4banks( uint32_t *bidx ) +{ +	uint32_t didx0 = 2 * bidx[0]; +	uint32_t didx1 = 2 * bidx[1]; +	uint32_t didx2 = 2 * bidx[2]; +	uint32_t didx3 = 2 * bidx[3]; + +	if( ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx1] ) == RET_OK ) && +	    ( u4_Dcmp( &m_dimm[didx2], &m_dimm[didx3] ) == RET_OK ) && +	    ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx2] ) == RET_OK ) ) { + +		if( m_dimm[didx0].m_rank_u32 == 1 ) { +			u4_group8dimmsSS( &m_dimm[didx0], &m_dimm[didx0+1], +					  &m_dimm[didx1], &m_dimm[didx1+1], +					  &m_dimm[didx2], &m_dimm[didx2+1], +					  &m_dimm[didx3], &m_dimm[didx3+1] ); +		} else { +			u4_group8dimmsDS( &m_dimm[didx0], &m_dimm[didx0+1], +					  &m_dimm[didx1], &m_dimm[didx1+1], +					  &m_dimm[didx2], &m_dimm[didx2+1], +					  &m_dimm[didx3], &m_dimm[didx3+1] ); +		} + +	} else { +		u4_group2banks( &bidx[0] ); +		u4_group2banks( &bidx[2] ); +	} + +} + +static void +u4_sortDIMMgroups( void ) +{ +	uint32_t i, j; + +	/* +	 * setup global group pointers +	 */ +	for( i = 0; i < m_dgrcnt_u32; i++ ) { +		m_dgrptr[i] = &m_dgroup[i]; +	} + +	/* +	 * use a simple bubble sort to sort groups by size (descending) +	 */ +	for( i = 0; i < ( m_dgrcnt_u32 - 1 ); i++ ) { + +		for( j = i + 1; j < m_dgrcnt_u32; j++ ) { + +			if( m_dgrptr[i]->m_size_u32 < m_dgrptr[j]->m_size_u32 ) { +				dgroup_t *l_sgr; + +				l_sgr       = m_dgrptr[i]; +				m_dgrptr[i] = m_dgrptr[j]; +				m_dgrptr[j] = l_sgr; +			} + +		} + +	} + +} + +static void +u4_calcDIMMcnfg( void ) +{ +	static const uint32_t _2GB  = (uint32_t) 0x00800; +	static const uint32_t _4GB  = (uint32_t) 0x01000; +	static const uint32_t _64GB = (uint32_t) 0x10000; +	uint32_t l_start_u32        = (uint32_t) 0; +	uint32_t l_end_u32          = (uint32_t) 0; +	uint32_t l_add2g_u32        = (uint32_t) 1; +	uint32_t l_sub2g_u32        = (uint32_t) 1; +	uint32_t i; + +	/* +	 * setup DIMM group parameters +	 */ +	for( i = 0; i < m_dgrcnt_u32; i++ ) { +		l_end_u32 = l_start_u32 + m_dgrptr[i]->m_size_u32; + +		if( m_dgrptr[i]->m_size_u32 > _2GB ) { + +			if( l_end_u32 < _64GB ) { +				l_add2g_u32 = ( l_end_u32 >> 11 ); +			} else { +				l_add2g_u32 = 1; +			} + +			if( l_start_u32 == 0 ) { +				l_sub2g_u32 = 1; +			} else { +				l_sub2g_u32 = ( l_start_u32 >> 11 ); +			} + +		} else if( l_add2g_u32 != 1 ) { +			l_start_u32 += _2GB; +			l_end_u32   += _2GB; +			l_add2g_u32  = 1; +			l_sub2g_u32  = 1; +		} + +		/* +		 * save values for the group +		 */ +		m_dgrptr[i]->m_start_u32 = ( l_start_u32 >> 7 ); // = /128 +		m_dgrptr[i]->m_end_u32   = ( l_end_u32   >> 7 ); +		m_dgrptr[i]->m_add2g_u32 = l_add2g_u32; +		m_dgrptr[i]->m_sub2g_u32 = l_sub2g_u32; + +		/* +		 * continue with next group +		 */ +		if( l_end_u32 != _2GB ) { +			l_start_u32 = l_end_u32; +		} else { +			l_start_u32 = _4GB; +		} + +	} + +} + +static int32_t +u4_calcDIMMmemmode( void ) +{ +	static const uint32_t MAX_ORG  = (uint32_t) 0x10; +	static const uint32_t MIN_BASE = (uint32_t) 0x80; +	static const uint32_t MAX_MODE = (uint32_t) 0x10; +	static const uint32_t MODE_ADD = (uint32_t) 0x04; +	dimm_t   *l_dptr; +	uint32_t  l_modeoffs_u32; +	uint32_t  l_sizebase_u32; +	int32_t	  ret = RET_OK; +	uint32_t  i, j; + +	/* +	 * loop through all DIMM groups and calculate memmode setting +	 */ +	for( i = 0; i < m_dgrcnt_u32; i++ ) { +		l_dptr = m_dgrptr[i]->m_dptr[0]; // all dimms in one group are equal! + +		l_modeoffs_u32  = MAX_ORG / l_dptr->m_orgval_u32; +		l_modeoffs_u32 /= (uint32_t) 2; +		l_sizebase_u32  = ( MIN_BASE << l_modeoffs_u32 ); + +		j = 0; +		while( ( l_sizebase_u32 != l_dptr->m_size_u32 ) && +		       ( j               < MAX_MODE           ) ) { +			l_sizebase_u32 <<= 1; +			j += (uint32_t) MODE_ADD; +		} + +		// return on error +		if( j >= MAX_MODE ) { +			#ifdef U4_INFO +			uint32_t b, k, l; +			printf( "\r\n  [ERROR -> unsupported memory type in bank(s)" ); + +			l = 0; +			for( k = 0; k < m_dgrptr[i]->m_dcnt_u32; k++ ) { +				b = m_dgrptr[i]->m_dptr[k]->m_bank_u32; + +				if( ( l & ( 1 << b ) ) == 0 ) { +					printf( " %u", b ); +					l |= ( 1 << b ); +				} + +			} + +			printf( "]\r\n" ); +			#endif + +			ret = RET_ERR; +		} else { +			m_dgrptr[i]->m_memmd_u32 = l_modeoffs_u32 + j; +		} + +	} + +	return ret; +} + +static void +u4_setupDIMMgroups( void ) +{ +	static const uint64_t _1MB = (uint64_t) 0x100000; +	uint32_t l_bcnt_u32; +	uint32_t l_bidx_u32[NUM_BANKS]; +	uint32_t i; + +	/* +	 * calculate number of populated banks +	 * IMPORTANT: array must be in ascending order! +	 */ +	l_bcnt_u32 = 0; +	for( i = 0; i < NUM_BANKS; i++ ) { + +		if( m_bankpop_u32[i] != 0 ) { +			l_bidx_u32[l_bcnt_u32] = i; +			l_bcnt_u32++; +		} + +	} + +	switch( l_bcnt_u32 ) { +		case 4: u4_group4banks( &l_bidx_u32[0] ); break; +		case 3: u4_group3banks( &l_bidx_u32[0] ); break; +		case 2: u4_group2banks( &l_bidx_u32[0] ); break; +		case 1: u4_group1banks( &l_bidx_u32[0] ); break; +	} + +	/* +	 * sort DIMM groups by size (descending) +	 */ +	u4_sortDIMMgroups(); + +	/* +	 * calculate overall memory size in bytes +	 * (group size is in MB) +	 */ +	m_memsize_u64 = 0; +	for( i = 0; i < m_dgrcnt_u32; i++ ) { +		m_memsize_u64 += (uint64_t) m_dgrptr[i]->m_size_u32 * _1MB; +	} + +} + +static int32_t +u4_setup_core_clock( void ) +{ +	static const uint32_t MCLK = (uint32_t) 266; +	static const uint32_t CDIV = (uint32_t) 66; +	static const uint32_t CMAX = (uint32_t) 7; +	static const uint32_t MERR = (uint32_t) 10; +	uint32_t volatile     l_cclk_u32; +	uint32_t volatile     l_pll2_u32; +	uint32_t              i, s; + +	#ifdef U4_INFO +	printf( "  [core clock reset:          ]" ); +	#endif + +	/* +	 * calculate speed value +	 */ +	s  = m_gendimm.m_speed_pu32[m_dclidx_u32]; +	s -= MCLK; +	s /= CDIV; + +	/* +	 * insert new core clock value +	 */ +	l_cclk_u32  = load32_ci( ClkCntl_R ); +	l_cclk_u32 &= ~CLK_DDR_CLK_MSK; +	l_cclk_u32 |= ( s << 18 ); + + +	// return on error +	if( s > CMAX ) { +		#ifdef U4_INFO +		printf( "\b\b\b\bERR\r\n" ); +		#endif +		return RET_ERR; +	} + +	/* +	 * reset core clock +	 */ +	store32_ci( ClkCntl_R, l_cclk_u32 ); +	dly( 0x1000000 ); +	or32_ci( PLL2Cntl_R, IBIT(0) ); +	dly( 0x1000000 ); + +	/* +	 * wait for reset to finish +	 */ +	do { +		l_pll2_u32 = load32_ci( PLL2Cntl_R ); +	} while( ( l_pll2_u32 & IBIT(0) ) != 0 ); + +	/* +	 * wait for stable PLL +	 */ +	s = 0; +	do { +		l_pll2_u32  = ( load32_ci( PLL2Cntl_R ) & IBIT(2) ); + +		for( i = 0; i < 4; i++ ) { +			l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) ); +			l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) ); +			l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) ); +			dly( 0x10000 ); +		} + +	} while( ( l_pll2_u32 == 0 ) && ( s++ < MERR ) ); + +	if( s >= MERR ) { +		#ifdef U4_INFO +		printf( "\b\b\b\bERR\r\n" ); +		#endif +		return RET_ERR; +	} + +	#ifdef U4_INFO +	printf( "\b\b\bOK\r\n" ); +	#endif + +	return RET_OK; +} + +static void +u4_auto_calib_init( void ) +{ +	static const uint32_t SEQ[] = { +		0xb1000000, 0xd1000000, 0xd1000000, 0xd1000000, +		0xd1000000, 0xd1000000, 0xd1000000, 0xd1000000, +		0xd1000000, 0xd1000000, 0xd1000000, 0xd1000000, +		0xd1000000, 0xd1000000, 0xd1000400, 0x00000000, +	}; + +	uint64_t i; +	uint32_t j; + +	for( i = MemInit00_R, j = 0; i <= MemInit15_R; i += 0x10, j++ ) { +		store32_ci( i, SEQ[j] ); +	} + +} + +#if 0 +static uint32_t +u4_RSL_BLane( uint32_t f_Rank_u32, uint32_t f_BLane_u32 ) +{ +	static const uint32_t MemProgCntl_V = (uint32_t) 0x80000500; +	static const uint32_t CalConf0_V    = (uint32_t) 0x0000aa10; +	uint32_t l_MemProgCntl_u32; +	uint32_t l_CalConf0_u32; +	uint32_t l_MeasStat_u32; +	uint32_t l_CalC_u32; +	uint64_t MeasStat_R; +	uint64_t CalC_R; +	uint64_t VerC_R; +	uint32_t shft; +	uint32_t v; + +	if( f_BLane_u32 < 4 ) { +		MeasStat_R   = MeasStatusC0_R; +		CalC_R       = CalC0_R; +		VerC_R       = RstLdEnVerniersC0_R; +	} else if( f_BLane_u32  <  8 ) { +		f_BLane_u32 -= 4; +		MeasStat_R   = MeasStatusC1_R; +		CalC_R       = CalC1_R; +		VerC_R       = RstLdEnVerniersC1_R; +	} else if( f_BLane_u32  < 12 ) { +		f_BLane_u32 -= 8; +		MeasStat_R   = MeasStatusC2_R; +		CalC_R       = CalC2_R; +		VerC_R       = RstLdEnVerniersC2_R; +	} else if( f_BLane_u32 == 16 ) { +		f_BLane_u32  = 4; +		MeasStat_R   = MeasStatusC1_R; +		CalC_R       = CalC1_R; +		VerC_R       = RstLdEnVerniersC1_R; +	} else if( f_BLane_u32 == 17 ) { +		f_BLane_u32  = 4; +		MeasStat_R   = MeasStatusC3_R; +		CalC_R       = CalC3_R; +		VerC_R       = RstLdEnVerniersC3_R; +	} else { +		f_BLane_u32 -= 12; +		MeasStat_R   = MeasStatusC3_R; +		CalC_R       = CalC3_R; +		VerC_R       = RstLdEnVerniersC3_R; +	} + +	shft = (uint32_t) 28 - ( f_BLane_u32 * 4 ); + +	/* +	 * start auto calibration logic & wait for completion +	 */ +	or32_ci( MeasStat_R, IBIT(0) ); + +	do { +		l_MeasStat_u32 = load32_ci( MeasStat_R ); +	} while( ( l_MeasStat_u32 & IBIT(0) ) == 1 ); + +	l_CalConf0_u32  = CalConf0_V; +	store32_ci( CalConf0_R, l_CalConf0_u32 ); + +	for( v = 0x000; v < (uint32_t) 0x100; v++ ) { +		store32_ci( VerC_R, ( v << 24 ) | ( v << 16 ) ); + +		l_MemProgCntl_u32  = MemProgCntl_V; +		l_MemProgCntl_u32 |= +			( (uint32_t) 0x00800000 >> f_Rank_u32 ); +		store32_ci( MemProgCntl_R, l_MemProgCntl_u32 ); + +		do { +			l_MemProgCntl_u32 = load32_ci( MemProgCntl_R ); +		} while( ( l_MemProgCntl_u32 & IBIT(1) ) == 0 ); + +		l_CalC_u32 = ( ( load32_ci( CalC_R ) >> shft ) & +			         (uint32_t) 0xf ); + +		if( l_CalC_u32 != (uint32_t) 0xa ) { +			v--; +			break; +		} + +	} + +	if( v == (uint32_t) 0x100 ) { +		v = (uint32_t) ~1; +	} + +	return v; +} +#endif + +static uint32_t +u4_RMDF_BLane( uint32_t f_Rank_u32, uint32_t f_BLane_u32 ) +{ +	static const uint32_t MemProgCntl_V = (uint32_t) 0x80000f00; +	static const uint32_t CalConf0_V    = (uint32_t) 0x0000ac10; +	uint32_t l_MemProgCntl_u32; +	uint32_t l_CalConf0_u32; +	uint32_t l_MeasStat_u32; +	uint32_t l_CalC_u32; +	uint64_t MeasStat_R; +	uint64_t CalC_R; +	uint64_t VerC_R; +	uint32_t shft; +	uint32_t v; + +	if( f_BLane_u32 < 4 ) { +		MeasStat_R   = MeasStatusC0_R; +		CalC_R       = CalC0_R; +		VerC_R       = RstLdEnVerniersC0_R; +	} else if( f_BLane_u32  <  8 ) { +		f_BLane_u32 -= 4; +		MeasStat_R   = MeasStatusC1_R; +		CalC_R       = CalC1_R; +		VerC_R       = RstLdEnVerniersC1_R; +	} else if( f_BLane_u32  < 12 ) { +		f_BLane_u32 -= 8; +		MeasStat_R   = MeasStatusC2_R; +		CalC_R       = CalC2_R; +		VerC_R       = RstLdEnVerniersC2_R; +	} else if( f_BLane_u32 == 16 ) { +		f_BLane_u32  = 4; +		MeasStat_R   = MeasStatusC1_R; +		CalC_R       = CalC1_R; +		VerC_R       = RstLdEnVerniersC1_R; +	} else if( f_BLane_u32 == 17 ) { +		f_BLane_u32  = 4; +		MeasStat_R   = MeasStatusC3_R; +		CalC_R       = CalC3_R; +		VerC_R       = RstLdEnVerniersC3_R; +	} else { +		f_BLane_u32 -= 12; +		MeasStat_R   = MeasStatusC3_R; +		CalC_R       = CalC3_R; +		VerC_R       = RstLdEnVerniersC3_R; +	} + +	shft = (uint32_t) 28 - ( f_BLane_u32 * 4 ); + +	/* +	 * start auto calibration logic & wait for completion +	 */ +	or32_ci( MeasStat_R, IBIT(0) ); + +	do { +		l_MeasStat_u32 = load32_ci( MeasStat_R ); +	} while( ( l_MeasStat_u32 & IBIT(0) ) == 1 ); + +	l_CalConf0_u32  = CalConf0_V; +	l_CalConf0_u32 |= ( f_BLane_u32 << 5 ); +	store32_ci( CalConf0_R, l_CalConf0_u32 ); + +	for( v = 0x000; v < (uint32_t) 0x100; v++ ) { +		store32_ci( VerC_R, ( v << 24 ) | ( v << 16 ) ); + +		l_MemProgCntl_u32  = MemProgCntl_V; +		l_MemProgCntl_u32 |= +			( (uint32_t) 0x00800000 >> f_Rank_u32 ); +		store32_ci( MemProgCntl_R, l_MemProgCntl_u32 ); + +		do { +			l_MemProgCntl_u32 = load32_ci( MemProgCntl_R ); +		} while( ( l_MemProgCntl_u32 & IBIT(1) ) == 0 ); + +		l_CalC_u32 = ( ( load32_ci( CalC_R ) >> shft ) & +			         (uint32_t) 0xf ); + +		if( l_CalC_u32 != (uint32_t) 0xa ) { +			v--; +			break; +		} + +	} + +	if( v == (uint32_t) 0x100 ) { +		v = (uint32_t) ~1; +	} + +	return v; +} + +static int32_t +u4_RMDF_Rank( uint32_t  f_Rank_u32, +	      uint32_t *f_Buf_pu32 ) +{ +	int32_t  l_Err_pi32 = 0; +	uint32_t b; + +	for( b = 0; ( b < MAX_BLANE ) && ( l_Err_pi32 == 0 ); b++ ) { +		f_Buf_pu32[b] = u4_RMDF_BLane( f_Rank_u32, b ); + +		if( f_Buf_pu32[b] == (uint32_t) ~0 ) { +			f_Buf_pu32[b] = 0; +			l_Err_pi32++; +		} else if( f_Buf_pu32[b] == (uint32_t) ~1 ) { +			f_Buf_pu32[b] = (uint32_t) 0xff; +			l_Err_pi32++; +		} + +	} + +	return l_Err_pi32; +} + +static int32_t +u4_auto_calib_MemBus( auto_calib_t *f_ac_pt ) +{ +	uint32_t RdMacDly, RdMacCnt; +	uint32_t ResMuxDly, ResMuxCnt; +	uint32_t RdPipeDly; +	uint32_t l_Buf_pu32[MAX_DRANKS][MAX_BLANE]; +	uint32_t l_Rnk_pu32[MAX_DRANKS]; +	uint32_t l_Ver_u32; +	int32_t  l_Err_i32; +	uint32_t bidx; +	uint32_t n, r, b; + +	/* +	 * read starting delays out of the MemBus register +	 */ +	RdMacDly  = ( load32_ci( MemBusCnfg_R ) >> 28 ) & 0xf; +	ResMuxDly = ( load32_ci( MemBusCnfg_R ) >> 24 ) & 0xf; + +	/* +	 * initialize ranks as not populated +	 */ +	for( r = 0; r < MAX_DRANKS; r++ ) { +		l_Rnk_pu32[r] = 0; +	} + +	/* +	 * run through every possible delays of +	 * RdMacDly, ResMuxDly & RdPipeDly until +	 * the first working configuration is found +	 */ +	RdPipeDly = 0; +	do { +		and32_ci( MemBusCnfg2_R, ~0x3 ); +		or32_ci(  MemBusCnfg2_R, RdPipeDly ); + +		RdMacCnt  =  RdMacDly; +		ResMuxCnt =  ResMuxDly; + +		/* +		 * RdMacDly >= ResMuxDly +		 */ +		do { +			and32_ci( MemBusCnfg_R, ( 1 << 24 ) - 1 ); +			or32_ci(  MemBusCnfg_R, ( RdMacCnt  << 28 ) | +						( ResMuxCnt << 24 ) ); +			and32_ci( MemBusCnfg2_R, ( 1 << 28 ) - 1 ); +			or32_ci(  MemBusCnfg2_R, ( RdMacCnt << 28 ) ); + +			/* +			 * check the current value for every installed +			 * DIMM on each side for every bytelane +			 */ +			l_Err_i32 = 0; +			for( n = 0; +			     ( n < NUM_SLOTS ) && +			     ( l_Err_i32 == 0 ); +			     n += 2 ) { + +				if( m_dimm[n].m_pop_u32 ) { +					/* +					 * run through all 18 bytelanes of every rank +					 */ +					for( r = n; +					     ( r < n + m_dimm[n].m_rank_u32 ) && +					     ( l_Err_i32 == 0 ); +					     r++ ) { +						l_Rnk_pu32[r] = 1; + +						l_Err_i32 = +						u4_RMDF_Rank( r, +							      &l_Buf_pu32[r][0] ); +					} + +				} + +			} + +			/* +			 * decrementation before exit is wanted! +			 */ +			RdMacCnt--; +			ResMuxCnt--; +		} while( ( ResMuxCnt  > 0 ) && +			 ( l_Err_i32 != 0 ) ); + +		if( l_Err_i32 != 0 ) { +			RdPipeDly++; +		} + +	} while( ( RdPipeDly   < 4 ) && +		 ( l_Err_i32 != 0 ) ); + +	/* +	 * if l_Err_pi32 == 0 the auto calibration passed ok +	 */ +	if( l_Err_i32 != 0 ) { +		return RET_ERR; +	} + +	/* +	 * insert delay values into return struct +	 */ +	and32_ci( MemBusCnfg_R, ( 1 << 24 ) - 1 ); +	or32_ci(  MemBusCnfg_R, ( RdMacCnt  << 28 ) | +				( ResMuxCnt << 24 ) ); +	and32_ci( MemBusCnfg2_R, ( ( 1 << 28 ) - 1 ) & ~0x3 ); +	or32_ci(  MemBusCnfg2_R, ( RdMacCnt << 28 ) | RdPipeDly ); + +	f_ac_pt->m_MemBusCnfg_u32  = load32_ci( MemBusCnfg_R ); +	f_ac_pt->m_MemBusCnfg2_u32 = load32_ci( MemBusCnfg2_R ); + +	/* +	 * calculate the average vernier setting for the +	 * bytelanes which share one vernier +	 */ +	for( b = 0; b < MAX_BLANE - 2; b += 2 ) { +		n         = 0; +		l_Ver_u32 = 0; + +		for( r = 0; r < MAX_DRANKS; r++ ) { +			/* +			 * calculation is done or populated ranks only +			 */ +			if( l_Rnk_pu32[r] != 0 ) { +				/* +				 * calculate average value +				 */ +				l_Ver_u32 += l_Buf_pu32[r][b]; +				l_Ver_u32 += l_Buf_pu32[r][b+1]; +				n         += 2; + +				if( b == 4 ) { +					l_Ver_u32 += l_Buf_pu32[r][16]; +					n++; +				} else if( b == 12 ) { +					l_Ver_u32 += l_Buf_pu32[r][17]; +					n++; +				} + +			} + +		} + +		/* +		 * average the values +		 */ +		l_Ver_u32 /= n; + +		/* +		 * set appropriate vernier register for +		 * the current bytelane +		 */ +		bidx = ( b >> 2 ); +		if( ( b & (uint32_t) 0x3 ) == 0 ) { +			l_Ver_u32 <<= 24; +			f_ac_pt->m_RstLdEnVerniers_pu32[bidx]  = l_Ver_u32; +		} else { +			l_Ver_u32 <<= 16; +			f_ac_pt->m_RstLdEnVerniers_pu32[bidx] |= l_Ver_u32; +		} + +	} + +	return RET_OK; +} + +static int32_t +u4_auto_calib( auto_calib_t *f_ac_pt ) +{ +	uint32_t l_MemBusCnfg_S; +	uint32_t l_MemBusCnfg2_S; +	uint32_t l_RstLdEnVerniers_S[4]; +	int32_t  l_Ret_i32; + +	/* +	 * save manipulated registers +	 */ +	l_MemBusCnfg_S         = load32_ci( MemBusCnfg_R ); +	l_MemBusCnfg2_S        = load32_ci( MemBusCnfg2_R ); +	l_RstLdEnVerniers_S[0] = load32_ci( RstLdEnVerniersC0_R ); +	l_RstLdEnVerniers_S[1] = load32_ci( RstLdEnVerniersC1_R ); +	l_RstLdEnVerniers_S[2] = load32_ci( RstLdEnVerniersC2_R ); +	l_RstLdEnVerniers_S[3] = load32_ci( RstLdEnVerniersC3_R ); + +	u4_auto_calib_init(); +	l_Ret_i32 = u4_auto_calib_MemBus( f_ac_pt ); + +	/* +	 * restore manipulated registers +	 */ +	store32_ci( MemBusCnfg_R,  l_MemBusCnfg_S ); +	store32_ci( MemBusCnfg2_R, l_MemBusCnfg2_S ); +	store32_ci( RstLdEnVerniersC0_R, l_RstLdEnVerniers_S[0] ); +	store32_ci( RstLdEnVerniersC1_R, l_RstLdEnVerniers_S[1] ); +	store32_ci( RstLdEnVerniersC2_R, l_RstLdEnVerniers_S[2] ); +	store32_ci( RstLdEnVerniersC3_R, l_RstLdEnVerniers_S[3] ); + +	return l_Ret_i32; +} + +static int32_t +u4_checkeccerr( eccerror_t *f_ecc_pt ) +{ +	uint32_t l_val_u32; +	int32_t  ret = RET_OK; + +	l_val_u32   = load32_ci( MESR_R ); +	l_val_u32 >>= 29; + +	if( ( l_val_u32 & (uint32_t) 0x7 ) != 0 ) { + +		if(        ( l_val_u32 & (uint32_t) 0x4 ) != 0 ) { +			/* UE */ +			ret = RET_ACERR_UE; +		} else if( ( l_val_u32 & (uint32_t) 0x1 ) != 0 ) { +			/* UEWT */ +			ret = RET_ACERR_UEWT; +		} else { +			/* CE */ +			ret = RET_ACERR_CE; +		} + +	} + +	f_ecc_pt->m_err_i32   = ret; + +	l_val_u32             = load32_ci( MEAR1_R ); +	f_ecc_pt->m_uecnt_u32 = ( ( l_val_u32 >> 24 ) & (uint32_t) 0xff ); +	f_ecc_pt->m_cecnt_u32 = ( ( l_val_u32 >> 16 ) & (uint32_t) 0xff ); + +	l_val_u32             = load32_ci( MEAR0_R ); +	f_ecc_pt->m_rank_u32  = ( ( l_val_u32 >> 29 ) & (uint32_t) 0x7 ); +	f_ecc_pt->m_col_u32   = ( ( l_val_u32 >> 18 ) & (uint32_t) 0x7ff ); +	f_ecc_pt->m_row_u32   = ( ( l_val_u32 >>  0 ) & (uint32_t) 0x7fff ); +	f_ecc_pt->m_bank_u32  = ( ( l_val_u32 >> 15 ) & (uint32_t) 0x7 ); + +	return ret; +} + +static uint32_t +u4_CalcScrubEnd( void ) +{ +	uint64_t l_scrend_u64 = m_memsize_u64; + +	/* +	 * check for memory hole at 2GB +	 */ +	if( l_scrend_u64 > _2GB ) { +		l_scrend_u64 += _2GB; +	} + +	l_scrend_u64 -= 0x40; +	l_scrend_u64 /= 0x10; + +	return( (uint32_t) l_scrend_u64 ); +} + +static int32_t +u4_Scrub( uint32_t f_scrub_u32, uint32_t f_pattern_u32, eccerror_t *f_eccerr_pt ) +{ +	uint32_t i; +	int32_t  ret; + +	/* +	 * setup scrub parameters +	 */ +	store32_ci( MSCR_R, 0 );			// stop scrub +	store32_ci( MSRSR_R, 0x0 );			// set start +	store32_ci( MSRER_R, u4_CalcScrubEnd() );	// set end +	store32_ci( MSPR_R, f_pattern_u32 );		// set pattern + +	/* +	 * clear out ECC error registers +	 */ +	store32_ci( MEAR0_R, 0x0 ); +	store32_ci( MEAR1_R, 0x0 ); +	store32_ci( MESR_R, 0x0 ); + +	/* +	 * Setup Scrub Type +	 */ +	store32_ci( MSCR_R, f_scrub_u32 ); + +	if( f_scrub_u32 != BACKGROUND_SCRUB ) { +		/* +		 * wait for scrub to complete +		 */ +		do { +			progbar(); +			dly( 15000000 ); +			i = load32_ci( MSCR_R ); +		} while( ( i & f_scrub_u32 ) != 0 ); + +		ret = u4_checkeccerr( f_eccerr_pt ); +	} else { +		ret = RET_OK; +	} + +	return ret; +} + +static eccerror_t +u4_InitialScrub( void ) +{ +	eccerror_t l_eccerr_st[2]; +	int32_t    l_err_i32[2] = { 0, 0 }; + +	l_err_i32[0] = u4_Scrub( IMMEDIATE_SCRUB_WITH_FILL, 0x0, &l_eccerr_st[0] ); + +	if( l_err_i32[0] >= -1 /*CE*/ ) { +		l_err_i32[1] = u4_Scrub( IMMEDIATE_SCRUB, 0x0, &l_eccerr_st[1] ); +	} + +	if( l_err_i32[0] < l_err_i32[1] ) { +		return l_eccerr_st[0]; +	} else { +		return l_eccerr_st[1]; +	} + +} + +/* + * RND: calculates Timer cycles from the given frequency + *	divided by the clock frequency. Values are rounded + * 	up to the nearest integer value if the division is not even. + */ +#define RND( tXXX )	( ( ( tXXX ) + tCK - 1 ) / tCK ) + +static void +u4_MemInitSequence( uint32_t tRP, uint32_t tWR, uint32_t tRFC, uint32_t CL, +		    uint32_t tCK, uint32_t TD ) +{ +	/* +	 * DIMM init sequence +	 */ +	static const uint32_t INI_SEQ[] = { +		0xa0000400, 0x80020000, 0x80030000, 0x80010404, +		0x8000100a, 0xa0000400, 0x90000000, 0x90000000, +		0x8ff0100a, 0x80010784, 0x80010404, 0x00000000, +		0x00000000, 0x00000000, 0x00000000, 0x00000000 +	}; + +	uint32_t l_MemInit_u32; +	uint64_t r; +	uint32_t i; + +	for( r = MemInit00_R, i = 0; r <= MemInit15_R; r += 0x10, i++ ) { +		l_MemInit_u32 = INI_SEQ[i]; + +		switch( i ) { +			case 0: +			case 5: { +				l_MemInit_u32 |= ( ( RND( tRP ) - TD )  << 20 ); +				break; +			} +			case 3: { +				store32_ci( EMRSRegCntl_R, l_MemInit_u32 & +							   (uint32_t) 0xffff ); +				break; +			} +			case 4: { +				l_MemInit_u32 |= IBIT(23); +			} +			case 8: { +				l_MemInit_u32 |= ( ( RND( tWR ) - 1 )  <<  9 ); +				l_MemInit_u32 |= ( CL                  <<  4 ); + +				store32_ci( MRSRegCntl_R, l_MemInit_u32 & +							  (uint32_t) 0xffff ); +				break; +			} +			case 6: +			case 7: { +				l_MemInit_u32 |= ( ( RND( tRFC ) - TD ) << 20 ); +				break; +			} + +		} + +		store32_ci( r, l_MemInit_u32 ); + +#ifdef U4_SHOW_REGS +		printf( "\r\nMemInit%02d (0x%04X): 0x%08X", i, (uint16_t) r, l_MemInit_u32 ); +#endif +	} +#ifdef U4_SHOW_REGS +	printf( "\r\n" ); +#endif +	/* +	 * Kick off memory init sequence & wait for completion +	 */ +	store32_ci( MemProgCntl_R, IBIT(0) ); + +	do { +		i = load32_ci( MemProgCntl_R ); +	} while( ( i & IBIT(1) ) == 0 ); + +} + +/* + * static DIMM configuartion settings + */ +static reg_statics_t reg_statics_maui[NUM_SPEED_IDX] = { +	{	/* 400 Mhz */ +		.RRMux          = 1, +		.WRMux          = 1, +		.WWMux          = 1, +		.RWMux          = 1, + +		.MemRdQCnfg     = 0x20020820, +		.MemWrQCnfg     = 0x40041040, +		.MemQArb        = 0x00000000, +		.MemRWArb       = 0x30413cc0, + +		.ODTCntl        = 0x60000000, +		.IOPadCntl      = 0x001a4000, +		.MemPhyModeCntl = 0x00000000, +		.OCDCalCntl     = 0x00000000, +		.OCDCalCmd      = 0x00000000, + +		.CKDelayL       = 0x34000000, +		.CKDelayU       = 0x34000000, + +		.MemBusCnfg     = 0x00000050                  | +				  ( (   MAX_RMD       << 28 ) | +				    ( ( MAX_RMD - 2 ) << 24 ) ), + +		.CAS1Dly0       = 0, +		.CAS1Dly1	= 0, + +		.ByteWrClkDel   = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		} + +	}, +	{	/* 533 Mhz */ +		.RRMux          = 1, +		.WRMux          = 1, +		.WWMux          = 1, +		.RWMux          = 1, + +		.MemRdQCnfg     = 0x20020820, +		.MemWrQCnfg     = 0x40041040, +		.MemQArb        = 0x00000000, +		.MemRWArb       = 0x30413cc0, + +		.ODTCntl        = 0x60000000, +		.IOPadCntl      = 0x001a4000, +		.MemPhyModeCntl = 0x00000000, +		.OCDCalCntl     = 0x00000000, +		.OCDCalCmd      = 0x00000000, + +		.CKDelayL       = 0x18000000, +		.CKDelayU       = 0x18000000, + +		.MemBusCnfg     = 0x00002070	              | +				  ( (   MAX_RMD       << 28 ) | +				    ( ( MAX_RMD - 3 ) << 24 ) ), + +		.CAS1Dly0       = 0, +		.CAS1Dly1	= 0, + +		.ByteWrClkDel   = { + +			0x12000000, 0x12000000, 0x12000000 , 0x12000000, +			0x12000000, 0x12000000, 0x12000000 , 0x12000000, +			0x12000000, 0x12000000, 0x12000000 , 0x12000000, +			0x12000000, 0x12000000, 0x12000000 , 0x12000000, +			0x12000000, 0x12000000 +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000 , 0x00000000, +			0x00000000, 0x00000000, 0x00000000 , 0x00000000, +			0x00000000, 0x00000000, 0x00000000 , 0x00000000, +			0x00000000, 0x00000000, 0x00000000 , 0x00000000, +			0x00000000, 0x00000000 +		} + +	}, +	{	/* 667 Mhz */ +		.RRMux          = 1, +		.WRMux          = 1, +		.WWMux          = 1, +		.RWMux          = 3, + +		.MemRdQCnfg     = 0x20020820, +		.MemWrQCnfg     = 0x40041040, +		.MemQArb        = 0x00000000, +		.MemRWArb       = 0x30413cc0, + +		.ODTCntl        = 0x60000000, +		.IOPadCntl      = 0x001a4000, +		.MemPhyModeCntl = 0x00000000, +		.OCDCalCntl     = 0x00000000, +		.OCDCalCmd      = 0x00000000, + +		.CKDelayL       = 0x0a000000, +		.CKDelayU       = 0x0a000000, + +		.MemBusCnfg     = 0x000040a0		      | +				  ( (   MAX_RMD       << 28 ) | +				    ( ( MAX_RMD - 3 ) << 24 ) ), + +		.CAS1Dly0       = 2, +		.CAS1Dly1	= 2, + +		.ByteWrClkDel   = { + +			0x12000000, 0x12000000, 0x12000000, 0x12000000, +			0x12000000, 0x12000000, 0x12000000, 0x12000000, +			0x12000000, 0x12000000, 0x12000000, 0x12000000, +			0x12000000, 0x12000000, 0x12000000, 0x12000000, +			0x12000000, 0x12000000 +/* +			0x31000000, 0x31000000, 0x31000000, 0x31000000, +			0x31000000, 0x31000000, 0x31000000, 0x31000000, +			0x31000000, 0x31000000, 0x31000000, 0x31000000, +			0x31000000, 0x31000000, 0x31000000, 0x31000000, +			0x31000000, 0x31000000 +*/ +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		} + +	} +}; + +static reg_statics_t reg_statics_bimini[NUM_SPEED_IDX] = { +	{	/* 400 Mhz */ +		.RRMux          = 2, +		.WRMux          = 2, +		.WWMux          = 2, +		.RWMux          = 2, + +		.MemRdQCnfg     = 0x20020820, +		.MemWrQCnfg     = 0x40041040, +		.MemQArb        = 0x00000000, +		.MemRWArb       = 0x30413cc0, + +		.ODTCntl        = 0x40000000, +		.IOPadCntl      = 0x001a4000, +		.MemPhyModeCntl = 0x00000000, +		.OCDCalCntl     = 0x00000000, +		.OCDCalCmd      = 0x00000000, + +		.CKDelayL       = 0x00000000, +		.CKDelayU       = 0x28000000, + +		.MemBusCnfg     = 0x00552070                  | +				  ( (   MAX_RMD       << 28 ) | +				    ( ( MAX_RMD - 2 ) << 24 ) ), + +		.CAS1Dly0       = 0, +		.CAS1Dly1	= 0, + +		.ByteWrClkDel   = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		} + +	}, +	{	/* 533 Mhz */ +		.RRMux          = 3, +		.WRMux          = 3, +		.WWMux          = 3, +		.RWMux          = 3, + +		.MemRdQCnfg     = 0x20020820, +		.MemWrQCnfg     = 0x40041040, +		.MemQArb        = 0x00000000, +		.MemRWArb       = 0x30413cc0, + +		.ODTCntl        = 0x40000000, +		.IOPadCntl      = 0x001a4000, +		.MemPhyModeCntl = 0x00000000, +		.OCDCalCntl     = 0x00000000, +		.OCDCalCmd      = 0x00000000, + +		.CKDelayL       = 0x00000000, +		.CKDelayU       = 0x20000000, + +		.MemBusCnfg     = 0x00644190		      | +				  ( (   MAX_RMD       << 28 ) | +				    ( ( MAX_RMD - 3 ) << 24 ) ), + +		.CAS1Dly0       = 2, +		.CAS1Dly1	= 2, + +		.ByteWrClkDel   = { +			0x14000000, 0x14000000, 0x14000000, 0x14000000, +			0x14000000, 0x14000000, 0x14000000, 0x14000000, +			0x14000000, 0x14000000, 0x14000000, 0x14000000, +			0x14000000, 0x14000000, 0x14000000, 0x14000000, +			0x14000000, 0x14000000 +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		} + +	}, +	{	/* 667 Mhz */ +		.RRMux          = 3, +		.WRMux          = 3, +		.WWMux          = 3, +		.RWMux          = 3, + +		.MemRdQCnfg     = 0x20020820, +		.MemWrQCnfg     = 0x40041040, +		.MemQArb        = 0x00000000, +		.MemRWArb       = 0x30413cc0, + +		.ODTCntl        = 0x40000000, +		.IOPadCntl      = 0x001a4000, +		.MemPhyModeCntl = 0x00000000, +		.OCDCalCntl     = 0x00000000, +		.OCDCalCmd      = 0x00000000, + +		.CKDelayL       = 0x00000000, +		.CKDelayU       = 0x00000000, + +		.MemBusCnfg     = 0x00666270		      | +				  ( (   MAX_RMD       << 28 ) | +				    ( ( MAX_RMD - 3 ) << 24 ) ), + +		.CAS1Dly0       = 2, +		.CAS1Dly1	= 2, + +		.ByteWrClkDel   = { +			0x14000000, 0x14000000, 0x14000000, 0x14000000, +			0x14000000, 0x14000000, 0x14000000, 0x14000000, +			0x14000000, 0x14000000, 0x14000000, 0x14000000, +			0x14000000, 0x14000000, 0x14000000, 0x14000000, +			0x14000000, 0x14000000 +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		} + +	} +}; + +static reg_statics_t reg_statics_kauai[NUM_SPEED_IDX] = { +	{	/* 400 Mhz */ +		.RRMux          = 0, +		.WRMux          = 0, +		.WWMux          = 0, +		.RWMux          = 0, + +		.MemRdQCnfg     = 0, +		.MemWrQCnfg     = 0, +		.MemQArb        = 0, +		.MemRWArb       = 0, + +		.ODTCntl        = 0, +		.IOPadCntl      = 0, +		.MemPhyModeCntl = 0, +		.OCDCalCntl     = 0, +		.OCDCalCmd      = 0, + +		.CKDelayL       = 0, +		.CKDelayU       = 0, + +		.MemBusCnfg     = 0, + +		.CAS1Dly0       = 0, +		.CAS1Dly1	= 0, + +		.ByteWrClkDel   = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		} + +	}, +	{	/* 533 Mhz */ +		.RRMux          = 0, +		.WRMux          = 0, +		.WWMux          = 0, +		.RWMux          = 0, + +		.MemRdQCnfg     = 0, +		.MemWrQCnfg     = 0, +		.MemQArb        = 0, +		.MemRWArb       = 0, + +		.ODTCntl        = 0, +		.IOPadCntl      = 0, +		.MemPhyModeCntl = 0, +		.OCDCalCntl     = 0, +		.OCDCalCmd      = 0, + +		.CKDelayL       = 0, +		.CKDelayU       = 0, + +		.MemBusCnfg     = 0, + +		.CAS1Dly0       = 0, +		.CAS1Dly1	= 0, + +		.ByteWrClkDel   = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		} + +	}, +	{	/* 667 Mhz */ +		.RRMux          = 0, +		.WRMux          = 0, +		.WWMux          = 0, +		.RWMux          = 0, + +		.MemRdQCnfg     = 0, +		.MemWrQCnfg     = 0, +		.MemQArb        = 0, +		.MemRWArb       = 0, + +		.ODTCntl        = 0, +		.IOPadCntl      = 0, +		.MemPhyModeCntl = 0, +		.OCDCalCntl     = 0, +		.OCDCalCmd      = 0, + +		.CKDelayL       = 0, +		.CKDelayU       = 0, + +		.MemBusCnfg     = 0, + +		.CAS1Dly0       = 0, +		.CAS1Dly1	= 0, + +		.ByteWrClkDel   = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		}, +		.ReadStrobeDel  = { +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000, 0x00000000, 0x00000000, +			0x00000000, 0x00000000 +		} + +	} +}; + +static int32_t +u4_start( eccerror_t *f_ecc_pt ) +{ +	/* +	 * maximum runs for auto calibration +	 */ +	static const uint32_t MAX_ACERR	= (uint32_t) 5; + +	/* +	 * fixed u4/DIMM timer/timing values for calculation +	 */ +	static const uint32_t TD      = (uint32_t) 2;	// u4 delay cycles for loading a timer +	static const uint32_t AL      = (uint32_t) 0; 	// additional latency (fix) +	static const uint32_t BL      = (uint32_t) 4; 	// burst length (fix) + +	uint32_t	      SPEED   = m_gendimm.m_speed_pu32[m_dclidx_u32]; +	uint32_t              CL      = m_gendimm.m_clval_pu32[m_dclidx_u32]; +	uint32_t              RL      = AL + CL; +	uint32_t              WL      = RL - 1; +	uint32_t              tCK     = m_gendimm.m_tCK_pu32[m_dclidx_u32]; +	uint32_t 	      tRAS    = m_gendimm.m_tRAS_u32; +	uint32_t 	      tRTP    = m_gendimm.m_tRTP_u32; +	uint32_t 	      tRP     = m_gendimm.m_tRP_u32; +	uint32_t 	      tWR     = m_gendimm.m_tWR_u32; +	uint32_t 	      tRRD    = m_gendimm.m_tRRD_u32; +	uint32_t 	      tRC     = m_gendimm.m_tRC_u32; +	uint32_t 	      tRCD    = m_gendimm.m_tRCD_u32; +	uint32_t 	      tWTR    = m_gendimm.m_tWTR_u32; +	uint32_t	      tRFC    = m_gendimm.m_tRFC_u32; +	uint32_t	      tREF    = m_gendimm.m_tREF_u32; + +	reg_statics_t *rst = 0; + +	uint32_t       l_RAS0_u32; +	uint32_t       l_RAS1_u32; +	uint32_t       l_CAS0_u32; +	uint32_t       l_CAS1_u32; +	uint32_t       l_MemRfshCntl_u32; +	uint32_t       l_UsrCnfg_u32; +	uint32_t       l_DmCnfg_u32; + +	uint32_t       l_MemArbWt_u32; +	uint32_t       l_MemRWArb_u32; +	uint32_t       l_MemBusCnfg_u32; + +	auto_calib_t   l_ac_st; +	int32_t	       l_ac_i32; +	uint32_t       l_acerr_i32; +	uint32_t       sidx; +	uint32_t       i, j, t0, t1; + +	/* +	 * set index for different 400/533/667 Mhz setup +	 */ +	switch( SPEED ) { +		case 400: +		case 533: +		case 667: { +			sidx  = SPEED; +			sidx -= 400; +			sidx /= 133; +			break; +		} + +		default: { +			#ifdef U4_DEBUG2 +			printf( "\r\n-> DIMM speed of %03u not supported\r\n", +				m_gendimm.m_speed_pu32[m_dclidx_u32]  ); +			#endif +			return RET_ERR; +		} + +	} + +	/* +	 * setup pointer to the static register settings +	 */ +	if( IS_MAUI ) { +		rst = ®_statics_maui[sidx]; +	} else if( IS_BIMINI ) { +		rst = ®_statics_bimini[sidx]; +	} else if( IS_KAUAI ) { +		rst = ®_statics_kauai[sidx]; +	} + +	/* +	 * Switch off Fast Path by default for all DIMMs +	 * running with more than 400Mhz +	 */ +	if( SPEED == 400 ) { +		or32_ci( APIMemRdCfg_R, IBIT(30) ); +		#ifdef U4_INFO +		printf( "  [fastpath        :        ON]\r\n" ); +		#endif +	} else { +		and32_ci( APIMemRdCfg_R, ~IBIT(30) ); +		#ifdef U4_INFO +		printf( "  [fastpath        :       OFF]\r\n" ); +		#endif +	} + + +	#ifdef U4_INFO +	printf( "  [register setup  :          ]" ); +	#endif + +	/* +	 * setup RAS/CAS timers2 +	 * NOTE: subtract TD from all values because of the delay +	 * caused by reloading timers (see spec) +	 */ + +	/* +	 * RAS Timer 0 +	 */ +	// TiAtP = RND(tRAS) -> RAS0[0:4] +	l_RAS0_u32  = ( ( RND( tRAS )                           - TD ) << 27 ); +	// TiRtP = AL + BL/2 - 2 + RND(tRTP) -> RAS01[5:9] +	l_RAS0_u32 |= ( ( AL + BL/2 - 2 + RND( tRTP )           - TD ) << 22 ); +	// TiWtP = WL + BL/2 + RND(tWR) -> RAS0[10:14] +	l_RAS0_u32 |= ( ( WL + BL/2 + RND( tWR )                - TD ) << 17 ); +	// TiPtA = RND(tRP) -> RAS0[15:19] +	l_RAS0_u32 |= ( ( RND( tRP )                            - TD ) << 12 ); +	// TiPAtA = RND(tRP) or +	//          RND(tRP) + 1 for 8 bank devices -> RAS0[20:24] +	if( m_gendimm.m_bankcnt_u32 <= 4 ) { +		l_RAS0_u32 |= ( ( RND( tRP )                    - TD ) <<  7 ); +	} else { +		l_RAS0_u32 |= ( ( RND( tRP ) + 1                - TD ) <<  7 ); +	} + +	/* +	 * RAS Timer 1 +	 */ +	// TiRAPtA = AL + BL/2 - 2 + RND(tRTP + tRP) -> RAS1[0:4] +	l_RAS1_u32  = ( ( AL + BL/2 - 2 + RND( tRTP + tRP )     - TD ) << 27 ); +	// TiWAPtA = CL + AL + BL/2 - 1 + RND(tWR + tRP) -> RAS1[5:9] +	l_RAS1_u32 |= ( ( CL + AL + BL/2 - 1 + RND( tWR + tRP ) - TD ) << 22 ); +	// TiAtARk = tRRD -> RAS1[10:14] +	l_RAS1_u32 |= ( ( RND( tRRD )                           - TD ) << 17 ); +	// TiAtABk = tRC -> RAS1[15:19] +	l_RAS1_u32 |= ( ( RND( tRC )                            - TD ) << 12 ); +	// TiAtRW = tRCD -> RAS1[20:24] +	l_RAS1_u32 |= ( ( RND( tRCD )                           - TD ) <<  7 ); +	// TiSAtARk Win = 4 * tRRD + 2 -> RAS1[25:29] +	l_RAS1_u32 |= ( ( RND( 4 * tRRD ) + 2                   - TD ) <<  2 ); + +	/* +	 * CAS Timer 0 +	 */ +	// TiRtRRk = BL/2 -> CAS0[0:4] +	l_CAS0_u32  = ( ( BL/2                                  - TD ) << 27 ); +	// TiRtRDm = BL/2 + 1 -> CAS0[5:9] +	l_CAS0_u32 |= ( ( BL/2 + 1                              - TD ) << 22 ); +	// TiRtRSy = BL/2 + RRMux -> CAS0[10:14] +	l_CAS0_u32 |= ( ( BL/2 + rst->RRMux                     - TD ) << 17 ); +	// TiWtRRk = CL - 1 + BL/2 + tWTR ->CAS0[15:19] +	l_CAS0_u32 |= ( ( CL - 1 + BL/2 + RND( tWTR )           - TD ) << 12 ); +	// TiWtRDm = BL/2 + 1 -> CAS0[20:24] +	l_CAS0_u32 |= ( ( BL/2 + 1                              - TD ) <<  7 ); +	// TiWtRSy = BL/2 + WRMux -> CAS0[25:29] +	l_CAS0_u32 |= ( ( BL/2 + rst->WRMux                     - TD ) <<  2 ); + +	/* +	 * CAS Timer 1 +	 */ +	// TiWtWRk = BL/2 -> CAS1[0:4] +	l_CAS1_u32  = ( ( BL/2                                  - TD ) << 27 ); +	// TiWtWDm = BL/2 + 1 -> CAS1[5:9] +	l_CAS1_u32 |= ( ( BL/2 + 1                              - TD ) << 22 ); +	// TiWtWSy = BL/2 + WWMux -> CAS1[10:14] +	l_CAS1_u32 |= ( ( BL/2 + rst->WWMux                     - TD ) << 17 ); +	// TiRtWRk = BL/2 + 2 -> CAS1[15:19] + 	l_CAS1_u32 |= ( ( BL/2 + 2            + rst->CAS1Dly0   - TD ) << 12 ); +	// TiRtWDm = BL/2 + 2 -> CAS1[20:24] +	l_CAS1_u32 |= ( ( BL/2 + 2            + rst->CAS1Dly1   - TD ) <<  7 ); +	// TiRtWSy = BL/2 + RWMux + 1 -> CAS1[25:29] +	l_CAS1_u32 |= ( ( BL/2 + rst->RWMux + 1                 - TD ) <<  2 ); + +	store32_ci( RASTimer0_R, l_RAS0_u32 ); +	store32_ci( RASTimer1_R, l_RAS1_u32 ); +	store32_ci( CASTimer0_R, l_CAS0_u32 ); +	store32_ci( CASTimer1_R, l_CAS1_u32 ); + +	/* +	 * Mem Refresh Control register +	 */ +	l_MemRfshCntl_u32  = ( ( ( tREF / tCK ) / 16 ) << 23 ); +	l_MemRfshCntl_u32 |= ( ( RND( tRFC )    - TD ) <<  8 ); +	store32_ci( MemRfshCntl_R, l_MemRfshCntl_u32 ); + +	/* +	 * setup DmXCnfg registers +	 */ +	store32_ci( Dm0Cnfg_R, (uint32_t) 0x0 ); +	store32_ci( Dm1Cnfg_R, (uint32_t) 0x0 ); +	store32_ci( Dm2Cnfg_R, (uint32_t) 0x0 ); +	store32_ci( Dm3Cnfg_R, (uint32_t) 0x0 ); + +	/* +	 * create DmCnfg & UsrCnfg values out of group data +	 */ +	l_UsrCnfg_u32 = 0; +	for( i = 0; i < m_dgrcnt_u32; i++ ) { +		l_DmCnfg_u32  = ( m_dgrptr[i]->m_add2g_u32 << 27 ); +		l_DmCnfg_u32 |= ( m_dgrptr[i]->m_sub2g_u32 << 19 ); +		l_DmCnfg_u32 |= ( m_dgrptr[i]->m_memmd_u32 << 12 ); +		l_DmCnfg_u32 |= ( m_dgrptr[i]->m_start_u32 <<  3 ); +		l_DmCnfg_u32 |= ( m_dgrptr[i]->m_ss_u32    <<  1 ); +		l_DmCnfg_u32 |= IBIT(31);	// enable bit + +		/* +		 * write value into DmXCnfg registers +		 */ +		for( j = 0; j < m_dgrptr[i]->m_dcnt_u32; j++ ) { +			t0 = m_dgrptr[i]->m_dptr[j]->m_bank_u32; +			t1 = Dm0Cnfg_R + 0x10 * t0; + +			if( load32_ci( t1 ) == 0 ) { +				store32_ci( t1, l_DmCnfg_u32 ); +				l_UsrCnfg_u32 |= +				( m_dgrptr[i]->m_csmode_u32 << ( 30 - 2 * t0 ) ); +			} + +		} + +	} + +	/* +	 * setup UsrCnfg register +	 *- cs mode is selected above +	 *- Interleave on L2 cache line +	 *- Usually closed page policy +	 */ +	l_UsrCnfg_u32 |=  IBIT(8);	// interleave on L2 cache line +	l_UsrCnfg_u32 &= ~IBIT(9);	// usually closed +	l_UsrCnfg_u32 |=  IBIT(10); +	store32_ci( UsrCnfg_R, l_UsrCnfg_u32 ); + +	/* +	 * Memory Arbiter Weight Register +	 */ +	// CohWt  -> MemAWt[0:1] +	l_MemArbWt_u32  = ( (uint32_t) 1 << 30 ); +	// NCohWt -> MemAWt[2:3] +	l_MemArbWt_u32 |= ( (uint32_t) 1 << 28 ); +	// ScrbWt -> MemAWt[4:5] +	l_MemArbWt_u32 |= ( (uint32_t) 0 << 26 ); +	store32_ci( MemArbWt_R, l_MemArbWt_u32 ); + +	/* +	 * misc fixed register setup +	 */ +	store32_ci( ODTCntl_R,        rst->ODTCntl ); +	store32_ci( IOPadCntl_R,      rst->IOPadCntl ); +	store32_ci( MemPhyModeCntl_R, rst->MemPhyModeCntl ); +	store32_ci( OCDCalCntl_R,     rst->OCDCalCntl ); +	store32_ci( OCDCalCmd_R,      rst->OCDCalCmd ); + +	/* +	 * CK Delay registers +	 */ +	store32_ci( CKDelayL_R, rst->CKDelayL ); +	store32_ci( CKDelayU_R, rst->CKDelayU ); + +	/* +	 * read/write strobe delays +	 */ +	store32_ci( ByteWrClkDelC0B00_R, rst->ByteWrClkDel[ 0] ); +	store32_ci( ByteWrClkDelC0B01_R, rst->ByteWrClkDel[ 1] ); +	store32_ci( ByteWrClkDelC0B02_R, rst->ByteWrClkDel[ 2] ); +	store32_ci( ByteWrClkDelC0B03_R, rst->ByteWrClkDel[ 3] ); +	store32_ci( ByteWrClkDelC0B04_R, rst->ByteWrClkDel[ 4] ); +	store32_ci( ByteWrClkDelC0B05_R, rst->ByteWrClkDel[ 5] ); +	store32_ci( ByteWrClkDelC0B06_R, rst->ByteWrClkDel[ 6] ); +	store32_ci( ByteWrClkDelC0B07_R, rst->ByteWrClkDel[ 7] ); +	store32_ci( ByteWrClkDelC0B16_R, rst->ByteWrClkDel[16] ); +	store32_ci( ByteWrClkDelC0B08_R, rst->ByteWrClkDel[ 8] ); +	store32_ci( ByteWrClkDelC0B09_R, rst->ByteWrClkDel[ 9] ); +	store32_ci( ByteWrClkDelC0B10_R, rst->ByteWrClkDel[10] ); +	store32_ci( ByteWrClkDelC0B11_R, rst->ByteWrClkDel[11] ); +	store32_ci( ByteWrClkDelC0B12_R, rst->ByteWrClkDel[12] ); +	store32_ci( ByteWrClkDelC0B13_R, rst->ByteWrClkDel[13] ); +	store32_ci( ByteWrClkDelC0B14_R, rst->ByteWrClkDel[14] ); +	store32_ci( ByteWrClkDelC0B15_R, rst->ByteWrClkDel[15] ); +	store32_ci( ByteWrClkDelC0B17_R, rst->ByteWrClkDel[17] ); +	store32_ci( ReadStrobeDelC0B00_R, rst->ReadStrobeDel[ 0] ); +	store32_ci( ReadStrobeDelC0B01_R, rst->ReadStrobeDel[ 1] ); +	store32_ci( ReadStrobeDelC0B02_R, rst->ReadStrobeDel[ 2] ); +	store32_ci( ReadStrobeDelC0B03_R, rst->ReadStrobeDel[ 3] ); +	store32_ci( ReadStrobeDelC0B04_R, rst->ReadStrobeDel[ 4] ); +	store32_ci( ReadStrobeDelC0B05_R, rst->ReadStrobeDel[ 5] ); +	store32_ci( ReadStrobeDelC0B06_R, rst->ReadStrobeDel[ 6] ); +	store32_ci( ReadStrobeDelC0B07_R, rst->ReadStrobeDel[ 7] ); +	store32_ci( ReadStrobeDelC0B16_R, rst->ReadStrobeDel[16] ); +	store32_ci( ReadStrobeDelC0B08_R, rst->ReadStrobeDel[ 8] ); +	store32_ci( ReadStrobeDelC0B09_R, rst->ReadStrobeDel[ 9] ); +	store32_ci( ReadStrobeDelC0B10_R, rst->ReadStrobeDel[10] ); +	store32_ci( ReadStrobeDelC0B11_R, rst->ReadStrobeDel[11] ); +	store32_ci( ReadStrobeDelC0B12_R, rst->ReadStrobeDel[12] ); +	store32_ci( ReadStrobeDelC0B13_R, rst->ReadStrobeDel[13] ); +	store32_ci( ReadStrobeDelC0B14_R, rst->ReadStrobeDel[14] ); +	store32_ci( ReadStrobeDelC0B15_R, rst->ReadStrobeDel[15] ); +	store32_ci( ReadStrobeDelC0B17_R, rst->ReadStrobeDel[17] ); + +	/* +	 * Mem Bus Configuration +	 * initial setup used in auto calibration +	 * final values will be written after +	 * auto calibration has finished +	 */ +	l_MemBusCnfg_u32  = rst->MemBusCnfg; + +/*	values calculation has been dropped, static values are used instead +	// WdbRqDly = 2 * (CL - 3) (registered DIMMs) -> MBC[16:19] +	l_MemBusCnfg_u32 += ( ( 2 * ( CL - 3 ) ) << 12 ); +	// RdOEOnDly = 0 (typically) +	l_MemBusCnfg_u32 += ( ( 0 )              <<  8 ); +	// RdOEOffDly = (2 * CL) - 4 -> MBC[24:27] +	// NOTE: formula is not working, changed to: +	// RdOEOffDly = (2 * CL) - 1 +	l_MemBusCnfg_u32 += ( ( ( 2 * CL ) - 1 ) <<  4 ); +*/ + +	store32_ci( MemBusCnfg_R, l_MemBusCnfg_u32 ); +	store32_ci( MemBusCnfg2_R, rst->MemBusCnfg & (uint32_t) 0xf0000000 ); + +	/* +	 * reset verniers registers +	 */ +	store32_ci( RstLdEnVerniersC0_R, 0x0 ); +	store32_ci( RstLdEnVerniersC1_R, 0x0 ); +	store32_ci( RstLdEnVerniersC2_R, 0x0 ); +	store32_ci( RstLdEnVerniersC3_R, 0x0 ); +	store32_ci( ExtMuxVernier0_R,    0x0 ); +	store32_ci( ExtMuxVernier1_R,    0x0 ); + +	/* +	 * Queue Configuration +	 */ +	store32_ci( MemRdQCnfg_R, rst->MemRdQCnfg ); +	store32_ci( MemWrQCnfg_R, rst->MemWrQCnfg ); +	store32_ci( MemQArb_R,    rst->MemQArb ); +	store32_ci( MemRWArb_R,   rst->MemRWArb ); + +	#ifdef U4_INFO +	printf( "\b\b\bOK\r\n" ); +	#endif + +	/* +	 * start up clocks & wait for pll2 to stabilize +	 */ +	#ifdef U4_INFO +	printf( "  [start DDR clock :          ]" ); +	#endif + +	store32_ci( MemModeCntl_R, IBIT(0) | IBIT(8) ); +	dly( 50000000 ); + +	#ifdef U4_INFO +	printf( "\b\b\bOK\r\n" ); + +	#endif + +	/* +	 * memory initialization sequence +	 */ +	#ifdef U4_INFO +	printf( "  [memory init     :          ]" ); +	#endif +	u4_MemInitSequence( tRP, tWR, tRFC, CL, tCK, TD ); +	#ifdef U4_INFO +	printf( "\b\b\bOK\r\n" ); +	#endif + +	/* +	 * start ECC before auto calibration to enable ECC bytelane +	 */ +	store32_ci( MCCR_R, IBIT(0) ); +	dly( 15000000 ); + +	/* +	 * start up auto calibration +	 */ +	#ifdef U4_INFO +	printf( "  [auto calibration:          ]\b" ); +	#endif + +	/* +	 * start auto calibration +	*/ +	l_acerr_i32 = 0; +	do { +		progbar(); + +		l_ac_i32 = u4_auto_calib( &l_ac_st ); + +		if( l_ac_i32 != 0 ) { +			l_acerr_i32++; +		} + +		dly( 15000000 ); +	} while( ( l_ac_i32    != 0             ) && +		 ( l_acerr_i32 <= MAX_ACERR     ) ); + +	if( l_acerr_i32 > MAX_ACERR ) { +		#ifdef U4_INFO +		printf( "\b\b\bERR\r\n" ); +		#endif +		return RET_ERR; +	} + +	/* +	 * insert auto calibration results +	 */ +	store32_ci( MemBusCnfg_R,  	 l_ac_st.m_MemBusCnfg_u32 ); +	store32_ci( MemBusCnfg2_R, 	 l_ac_st.m_MemBusCnfg2_u32 ); +	store32_ci( RstLdEnVerniersC0_R, l_ac_st.m_RstLdEnVerniers_pu32[0] ); +	store32_ci( RstLdEnVerniersC1_R, l_ac_st.m_RstLdEnVerniers_pu32[1] ); +	store32_ci( RstLdEnVerniersC2_R, l_ac_st.m_RstLdEnVerniers_pu32[2] ); +	store32_ci( RstLdEnVerniersC3_R, l_ac_st.m_RstLdEnVerniers_pu32[3] ); + +	/* +	 * insert final timing value into MemRWArb +	 */ +	l_MemRWArb_u32  = ( ( l_ac_st.m_MemBusCnfg_u32 >> 28 /*RdMacDel*/) + 1 ); +	l_MemRWArb_u32 *= 10;	// needed for rounding +	l_MemRWArb_u32 /= 2;	// due to spec +	l_MemRWArb_u32 += 9;	// round up +	l_MemRWArb_u32 /= 10;	// value is rounded now +	l_MemRWArb_u32  = l_MemRWArb_u32 + 6 - WL - TD; +	l_MemRWArb_u32 |= rst->MemRWArb; +	store32_ci( MemRWArb_R, l_MemRWArb_u32 ); + +	progbar(); +	dly( 15000000 ); + +	/* +	 * do initial scrubbing +	 */ +	*f_ecc_pt = u4_InitialScrub(); + +	switch( f_ecc_pt->m_err_i32 ) { +		case  RET_OK: { +			#ifdef U4_INFO +			printf( "\b\bOK\r\n" ); +			#endif +			break; +		} + +		case RET_ACERR_CE: { +			#ifdef U4_INFO +			printf( "\b\b\b\bWEAK][correctable errors during scrub (%u)]\r\n", +				f_ecc_pt->m_cecnt_u32 ); +			#endif +			break; +		} + +		case RET_ACERR_UEWT: +		case RET_ACERR_UE: { +			#ifdef U4_INFO +			printf( "\b\b\bERR][uncorrectable errors during scrub (%u)]\r\n", +				f_ecc_pt->m_uecnt_u32 ); +			#endif +			return RET_ACERR_UE; +		} + +	} + +	/* +	 * start continuous background scrub +	 */ +	#ifdef U4_INFO +	printf( "  [background scrub:          ]" ); +	#endif + +	u4_Scrub( BACKGROUND_SCRUB, 0, NULL ); + +	#ifdef U4_INFO +	printf( "\b\b\bOK\r\n" ); +	#endif + +	/* +	 * finally clear API Exception register +	 * (read to clear) +	 */ +	load32_ci( APIExcp_R ); + +	return RET_OK; +} + +#undef RND + +#if 0 +void +u4_memtest(uint8_t argCnt, char *pArgs[], uint64_t flags) +{ +	#define TEND			99 +	#define TCHK			100 +	static const uint64_t _2GB   = (uint64_t) 0x80000000; +	static const uint64_t _start = (uint64_t) 0x08000000;	// 128Mb +	static const uint64_t _bsize = (uint64_t) 0x08000000;	// 128MB +	static const uint64_t _line  = (uint64_t) 128; +	static const uint64_t _256MB = (uint64_t) 0x10000000; + +	static const uint64_t PATTERN[] = { +		0x9090909090909090, 0x0020002000200020, +		0x0c0c0c0c0c0c0c0c, 0x8080808080808080, +		0x1004010004001041, 0x0000000000000000 +	}; + +     	uint64_t mend      = (uint64_t) 0x200000000;//m_memsize_u64; +	uint64_t numblocks = ( mend - _start ) / _bsize;	// 128Mb blocks +	uint64_t numlines  = _bsize / _line; +	uint64_t tstate    = 0; +	uint64_t tlast     = 0; +	uint64_t pidx      = 0; +	uint64_t rotr      = 0; +	uint64_t rotl      = 0; +	uint64_t block; +	uint64_t line; +	uint64_t addr; +	uint64_t i; +	uint64_t check = 0; +	uint64_t dcnt; +	uint64_t uerr = 0; +	uint64_t cerr = 0; +	uint64_t merr = 0; +	char     c; + +	printf( "\n\nU4 memory test" ); +	printf( "\n--------------" ); + +	/* +	 * mask out UEC & CEC +	 */ +	or32_ci( MCCR_R, IBIT(6) | IBIT(7) ); + +	while( PATTERN[pidx] ) { + +		switch( tstate ) +		{ +		case 0: { +			printf( "\npattern fill 0x%08X%08X: ", (uint32_t) (PATTERN[pidx] >> 32), (uint32_t) PATTERN[pidx] ); + +			/* +			 * first switch lines, then blocks. This way the CPU +			 * is not able to cache data +			 */ +			for( line = 0, dcnt = 0; line < numlines; line++ ) { + +				for( block = 0; block < numblocks; block++ ) { + +					for( i = 0; i < _line; i += 8 ) { +						addr =  _start + +							( block * _bsize ) + +							( line * _line )   + +							i; + +						if( addr >= _2GB ) { +							addr += _2GB; +						} + +						*( (uint64_t *) addr ) = PATTERN[pidx]; + +						/* +						 * print out a dot every 256Mb +						 */ +						dcnt += 8; +						if( dcnt == _256MB ) { +							dcnt = 0; +							printf( "*" ); + +							if( io_getchar( &c ) ) { +								goto mtend; +							} + +						} + +					} + +				} + +			} + +			check  = PATTERN[pidx]; +			tlast  = 0; +			tstate = TCHK; +		} 	break; + +		case 1: { +			uint64_t one; + +			/* +			 * new check pattern + +			 */ +			one     = ( ( check & 0x1 ) != 0 ); +			check >>= 1; +			if( one ) { +				check |= 0x8000000000000000; +			} + +			printf( "\nrotate right 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check ); + +			/* +			 * first switch lines, then blocks. This way the CPU +			 * is not able to cache data +			 */ +			for( line = 0, dcnt = 0; line < numlines; line++ ) { + +				for( block = 0; block < numblocks; block++ ) { + +					for( i = 0; i < _line; i += 8 ) { +						addr =  _start + +							( block * _bsize ) + +							( line * _line )   + +							i; + +						if( addr >= _2GB ) { +							addr += _2GB; +						} + +						*( (uint64_t *) addr ) >>= 1; + +						if( one ) { +							*( (uint64_t *) addr ) |= +								(uint64_t) 0x8000000000000000; +						} + +						/* +						 * print out a dot every 256Mb +						 */ +						dcnt += 8; +						if( dcnt == _256MB ) { +							dcnt = 0; +							printf( "*" ); + +							if( io_getchar( &c ) ) { +								goto mtend; +							} + +						} + +					} + +				} + +			} + +			tlast  = 1; +			tstate = TCHK; +		}	break; + +		case 2: { + +			if( rotr < 6 ) { +				rotr++; +				tstate = 1; +			} else { +				rotr   = 0; +				tstate = 3; +			} + +		}	break; + +		case 3: { +			/* +			 * new check pattern +			 */ +			check ^= (uint64_t) ~0; + +			printf( "\ninverting    0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check ); + +			/* +			 * first switch lines, then blocks. This way the CPU +			 * is not able to cache data +			 */ +			for( line = 0, dcnt = 0; line < numlines; line++ ) { + +				for( block = 0; block < numblocks; block++ ) { + +					for( i = 0; i < _line; i += 8 ) { +						addr =  _start + +							( block * _bsize ) + +							( line * _line )   + +							i; + +						if( addr >= _2GB ) { +							addr += _2GB; +						} + +						*( (uint64_t *) addr ) ^= (uint64_t) ~0; + +						/* +						 * print out a dot every 256Mb +						 */ +						dcnt += 8; +						if( dcnt == _256MB ) { +							dcnt = 0; +							printf( "*" ); + +							if( io_getchar( &c ) ) { +								goto mtend; +							} + +						} + +					} + +				} + +			} + +			tlast  = 3; +			tstate = TCHK; +		}	break; + +		case 4: { +			uint64_t one; + +			/* +			 * new check pattern +			 */ +			one     = ( ( check & 0x8000000000000000 ) != 0 ); +			check <<= 1; +			if( one ) { +				check |= 0x1; +			} + +			printf( "\nrotate left  0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check ); + +			/* +			 * first switch lines, then blocks. This way the CPU +			 * is not able to cache data +			 */ +			for( line = 0, dcnt = 0; line < numlines; line++ ) { + +				for( block = 0; block < numblocks; block++ ) { + +					for( i = 0; i < _line; i += 8 ) { +						addr =  _start + +							( block * _bsize ) + +							( line * _line )   + +							i; + +						if( addr >= _2GB ) { +							addr += _2GB; +						} + +						*( (uint64_t *) addr ) <<= 1; + +						if( one ) { +							*( (uint64_t *) addr ) |= +								(uint64_t) 0x1; +						} + +						/* +						 * print out a dot every 256Mb +						 */ +						dcnt += 8; +						if( dcnt == _256MB ) { +							dcnt = 0; +							printf( "*" ); + +							if( io_getchar( &c ) ) { +								goto mtend; +							} + +						} + +					} + +				} + +			} + +			tlast  = 4; +			tstate = TCHK; +		}	break; + +		case 5: { + +			if( rotl < 6 ) { +				rotl++; +				tstate = 4; +			} else { +				rotl   = 0; +				tstate = 6; +			} + +		}	break; + +		case 6: { +			/* +			 * new check pattern +			 */ +			check *= ~check; +			printf( "\nmultiply     0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check ); + +			/* +			 * first switch lines, then blocks. This way the CPU +			 * is not able to cache data +			 */ +			for( line = 0, dcnt = 0; line < numlines; line++ ) { + +				for( block = 0; block < numblocks; block++ ) { + +					for( i = 0; i < _line; i += 8 ) { +						addr =  _start + +							( block * _bsize ) + +							( line * _line )   + +							i; + +						if( addr >= _2GB ) { +							addr += _2GB; +						} + +						*( (uint64_t *) addr ) *= ~( *( (uint64_t *) addr ) ); + +						/* +						 * print out a dot every 256Mb +						 */ +						dcnt += 8; +						if( dcnt == _256MB ) { +							dcnt = 0; +							printf( "*" ); + +							if( io_getchar( &c ) ) { +								goto mtend; +							} + +						} + +					} + +				} + +			} + +			tlast  = TEND - 1; +			tstate = TCHK; +		}	break; + +		case TEND: { +			pidx++; +			tstate = 0; +		}	break; + +		case TCHK: { +			uint64_t err; +			/* +			 * check data +			 */ +			printf( "\nchecking                       : " ); + +			for( line = 0, dcnt = 0; line < numlines; line++ ) { + +				for( block = 0; block < numblocks; block++ ) { + +					for( i = 0; i < _line; i += 8 ) { +						addr =  _start + +							( block * _bsize ) + +							( line * _line )   + +							i; + +						if( addr >= _2GB ) { +							addr += _2GB; +						} + +						err = ( *( (uint64_t *) addr ) != check ); + +						if( err ) { +							merr++; +						} + +						/* +						 * print out a dot every 256Mb +						 */ +						dcnt += 8; +						if( dcnt == _256MB ) { +							dcnt = 0; + +							if( err ) { +								printf( "X" ); +							} else { +								printf( "*" ); +							} + +							if( io_getchar( &c ) ) { +								goto mtend; +							} + +						} + +					} + +				} + +			} + +			err   = (uint64_t) load32_ci( MEAR1_R ); +			uerr += ( err >> 24 ) & (uint64_t) 0xff; +			cerr += ( err >> 16 ) & (uint64_t) 0xff; + +			printf( " (UE: %02llX, CE: %02llX)", ( err >> 24 ) & (uint64_t) 0xff, ( err >> 16 ) & (uint64_t) 0xff ); + +			tstate = tlast + 1; +			tlast  = TCHK; +		} 	break; + +		} + +	} + +mtend: +	printf( "\n\nmemory test results" ); +	printf( "\n-------------------" ); +	printf( "\nuncorrectable errors: %u", (uint32_t) uerr ); +	printf( "\ncorrectable errors  : %u", (uint32_t) cerr ); +	printf( "\nread/write errors   : %u\n", (uint32_t) merr ); + +	and32_ci( MCCR_R, ~( IBIT(6) | IBIT(7) ) ); +} +#endif + +#if 0 +void +u4_dump(uint8_t argCnt, char *pArgs[], uint64_t flags) +{ +	printf( "\r\n*** u4 register dump ***\r\n\n" ); +	printf( "register      (offset): value\r\n" ); +	printf( "----------------------------------\r\n" ); +	printf( "Clock Control (0x%04X): 0x%08X\r\n", (uint16_t) ClkCntl_R, load32_ci( ClkCntl_R ) ); +	printf( "PLL2 Control  (0x%04X): 0x%08X\r\n", (uint16_t) PLL2Cntl_R, load32_ci( PLL2Cntl_R ) ); +	printf( "MemModeCntl   (0x%04X): 0x%08X\r\n", (uint16_t) MemModeCntl_R, load32_ci( MemModeCntl_R ) ); +	printf( "RASTimer0     (0x%04X): 0x%08X\r\n", (uint16_t) RASTimer0_R, load32_ci( RASTimer0_R ) ); +	printf( "RASTimer1     (0x%04X): 0x%08X\r\n", (uint16_t) RASTimer1_R, load32_ci( RASTimer1_R ) ); +	printf( "CASTimer0     (0x%04X): 0x%08X\r\n", (uint16_t) CASTimer0_R, load32_ci( CASTimer0_R ) ); +	printf( "CASTimer1     (0x%04X): 0x%08X\r\n", (uint16_t) CASTimer1_R, load32_ci( CASTimer1_R ) ); +	printf( "MemRfshCntl   (0x%04X): 0x%08X\r\n", (uint16_t) MemRfshCntl_R, load32_ci( MemRfshCntl_R ) ); +	printf( "Dm0Cnfg       (0x%04X): 0x%08X\r\n", (uint16_t) Dm0Cnfg_R, load32_ci( Dm0Cnfg_R ) ); +	printf( "Dm1Cnfg       (0x%04X): 0x%08X\r\n", (uint16_t) Dm1Cnfg_R, load32_ci( Dm1Cnfg_R ) ); +	printf( "Dm2Cnfg       (0x%04X): 0x%08X\r\n", (uint16_t) Dm2Cnfg_R, load32_ci( Dm2Cnfg_R ) ); +	printf( "Dm3Cnfg       (0x%04X): 0x%08X\r\n", (uint16_t) Dm3Cnfg_R, load32_ci( Dm3Cnfg_R ) ); +	printf( "UsrCnfg       (0x%04X): 0x%08X\r\n", (uint16_t) UsrCnfg_R, load32_ci( UsrCnfg_R ) ); +	printf( "MemArbWt      (0x%04X): 0x%08X\r\n", (uint16_t) MemArbWt_R, load32_ci( MemArbWt_R ) ); +	printf( "ODTCntl       (0x%04X): 0x%08X\r\n", (uint16_t) ODTCntl_R, load32_ci( ODTCntl_R ) ); +	printf( "IOPadCntl     (0x%04X): 0x%08X\r\n", (uint16_t) IOPadCntl_R, load32_ci( IOPadCntl_R ) ); +	printf( "MemPhyMode    (0x%04X): 0x%08X\r\n", (uint16_t) MemPhyModeCntl_R, load32_ci( MemPhyModeCntl_R ) ); +	printf( "OCDCalCntl    (0x%04X): 0x%08X\r\n", (uint16_t) OCDCalCntl_R, load32_ci( OCDCalCntl_R ) ); +	printf( "OCDCalCmd     (0x%04X): 0x%08X\r\n", (uint16_t) OCDCalCmd_R, load32_ci( OCDCalCmd_R ) ); +	printf( "CKDelayL      (0x%04X): 0x%08X\r\n", (uint16_t) CKDelayL_R, load32_ci( CKDelayL_R ) ); +	printf( "CKDelayH      (0x%04X): 0x%08X\r\n", (uint16_t) CKDelayU_R, load32_ci( CKDelayU_R ) ); +	printf( "MemBusCnfg    (0x%04X): 0x%08X\r\n", (uint16_t) MemBusCnfg_R, load32_ci( MemBusCnfg_R ) ); +	printf( "MemBusCnfg2   (0x%04X): 0x%08X\r\n", (uint16_t) MemBusCnfg2_R, load32_ci( MemBusCnfg2_R ) ); +	printf( "MemRdQCnfg    (0x%04X): 0x%08X\r\n", (uint16_t) MemRdQCnfg_R, load32_ci( MemRdQCnfg_R ) ); +	printf( "MemWrQCnfg    (0x%04X): 0x%08X\r\n", (uint16_t) MemWrQCnfg_R, load32_ci( MemWrQCnfg_R ) ); +	printf( "MemQArb       (0x%04X): 0x%08X\r\n", (uint16_t) MemQArb_R, load32_ci( MemQArb_R ) ); +	printf( "MemRWArb      (0x%04X): 0x%08X\r\n", (uint16_t) MemRWArb_R, load32_ci( MemRWArb_R ) ); +	printf( "ByteWrClkDel  (0x%04X): 0x%08X\r\n", (uint16_t) ByteWrClkDelC0B00_R, load32_ci( ByteWrClkDelC0B00_R ) ); +	printf( "ReadStrobeDel (0x%04X): 0x%08X\r\n", (uint16_t) ReadStrobeDelC0B00_R, load32_ci( ReadStrobeDelC0B00_R ) ); +	printf( "RstLdEnVerC0  (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC0_R, load32_ci( RstLdEnVerniersC0_R ) ); +	printf( "RstLdEnVerC1  (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC1_R, load32_ci( RstLdEnVerniersC1_R ) ); +	printf( "RstLdEnVerC2  (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC2_R, load32_ci( RstLdEnVerniersC2_R ) ); +	printf( "RstLdEnVerC3  (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC3_R, load32_ci( RstLdEnVerniersC3_R ) ); +	printf( "APIMemRdCfg   (0x%04X): 0x%08X\r\n", (uint16_t) APIMemRdCfg_R, load32_ci( APIMemRdCfg_R ) ); +	printf( "scrub start   (0x%04X): 0x%08X\r\n", (uint16_t) MSRSR_R, load32_ci( MSRSR_R ) ); +	printf( "scrub end     (0x%04X): 0x%08X\r\n", (uint16_t) MSRER_R, load32_ci( MSRER_R ) ); +} +#endif + +static int32_t +u4_memBegin( eccerror_t *f_ecc_pt ) +{ +	int32_t i; + +	#ifdef U4_INFO +	printf( "\r\n" ); +	printf( "U4 DDR2 memory controller setup V%u.%u\r\n", +		VER, SUBVER ); +	printf( "------------------------------------\r\n" ); +	printf( "> detected board              : " ); + +	if( IS_MAUI ) { +		printf( "MAUI" ); +	} else if( IS_BIMINI ) { +		printf( "BIMINI" ); +	} else if( IS_KAUAI ) { +		printf( "KAUAI" ); +	} else { +		printf( "unknown!" ); +		return RET_ERR; +	} +	#endif + +	do { +		/* +		 * initialize variables +		 */ +		m_memsize_u64    = 0; +		m_dcnt_u32       = 0; +		m_dgrcnt_u32     = 0; +		m_dclidx_u32     = 0; + +		for( i = 0; i < NUM_SLOTS; i++ ) { +			m_dptr[i] = NULL; +			memset( ( void * ) &m_dimm[i], 0, sizeof( dimm_t ) ); +		} + +		for( i = 0; i < MAX_DGROUPS; i++ ) { +			m_dgrptr[i] = NULL; +			memset( ( void * ) &m_dgroup[i], 0, sizeof( dimm_t ) ); +		} + +		/* +		 * start configuration +		 */ +		#ifdef U4_INFO +		printf( "\r\n> detected DIMM configuration : " ); +		#endif + +		i = ddr2_readSPDs(); + +		if( i != RET_OK ) { +			#ifdef U4_INFO +			printf( "\r\n-------------------------------------------------------------" ); +			printf( "\r\n  switching off memory bank(s) due to SPD integrity failure" ); +			printf( "\r\n-------------------------------------------------------------\r\n" ); +			#endif +		} + +	} while( i != RET_OK ); + +	/* +	 * check DIMM configuration +	 */ +	if( ddr2_setupDIMMcfg() != RET_OK ) { +		#ifdef U4_INFO +		printf( "> initialization failure.\r\n" ); +		#endif +		return RET_ERR; +	} + +	/* +	 * create DIMM groups +	 */ +	u4_setupDIMMgroups(); + +	/* +	 * start configuration of u4 +	 */ +	u4_calcDIMMcnfg(); + +	if( u4_calcDIMMmemmode() != RET_OK ) { +		#ifdef U4_INFO +		printf( "> initialization failure.\r\n" ); +		#endif +		return RET_ERR; +	} + +	#ifdef U4_INFO +	printf( "%uMb @ %uMhz, CL %u\r\n", +		(uint32_t) ( m_memsize_u64 / 0x100000 ), +		m_gendimm.m_speed_pu32[m_dclidx_u32], +		m_gendimm.m_clval_pu32[m_dclidx_u32] ); + +	printf( "> initializing memory         :\r\n" ); +	#endif + +	if( u4_setup_core_clock() != RET_OK ) { +		#ifdef U4_INFO +		printf( "> initialization failure.\r\n" ); +		#endif +		return RET_ERR; +	} + +	i = u4_start( f_ecc_pt ); +	if( i != RET_OK ) { +		#ifdef U4_INFO +		printf( "> initialization failure.\r\n" ); +		#endif +		return i; +	} + +	#ifdef U4_INFO +	printf( "  [flush cache     :          ]" ); +	#endif + +	flush_cache( 0x0, L2_CACHE_SIZE ); + +	#ifdef U4_INFO +	printf( "\b\b\bOK\r\n" ); +	printf( "> initialization complete.\r\n" ); +	#endif + +#ifdef U4_SHOW_REGS +	u4_dump(0,0,0); +#endif + +	return RET_OK; +} + + +#if 0 +static int32_t scrubstarted = 0; +void +u4_scrubStart(uint8_t argCnt, char *pArgs[], uint64_t flags ) +{ +	scrubstarted = 1; + +	/* +	 * setup scrub parameters +	 */ +	store32_ci( MSCR_R, 0 );			// stop scrub +	store32_ci( MSRSR_R, 0x0 );			// set start +	store32_ci( MSRER_R, 0x1c );			// set end +	store32_ci( MSPR_R, 0x0 );			// set pattern + +	/* +	 * clear out ECC error registers +	 */ +	store32_ci( MEAR0_R, 0x0 ); +	store32_ci( MEAR1_R, 0x0 ); +	store32_ci( MESR_R, 0x0 ); + +	/* +	 * Setup Scrub Type +	 */ +	store32_ci( MSCR_R, IBIT(1) ); +	printf( "\r\nscrub started\r\n" ); +} +#endif + +#if 0 +void +u4_scrubEnd(uint8_t argCnt, char *pArgs[], uint64_t flags ) +{ +	store32_ci( MSCR_R, 0 );			// stop scrub +	scrubstarted = 0; +	printf( "\r\nscrub stopped\r\n" ); +} +#endif + +#if 0 +void +u4_memwr(uint8_t argCnt, char *pArgs[], uint64_t flags ) +{ +	uint32_t i; +	uint32_t v = 0; + +	for( i = 0; i < 0x200; i += 4 ) { + +		if( ( i & 0xf ) == 0 ) { +			v = ~v; +		} + +		store32_ci( i, v ); +	} + +} +#endif + +void +u4memInit() +{ +	static uint32_t l_isInit_u32 = 0; +	eccerror_t	l_ecc_t; +	int32_t		ret; + +	/* +	 * do not initialize memory more than once +	 */ +	if( l_isInit_u32 ) { +		#ifdef U4_INFO +		printf( "\r\n\nmemory already initialized\r\n" ); +		#endif +		return; +	} else { +		l_isInit_u32 = 1; +	} + +	/* +	 * enable all DIMM banks on first run +	 */ +	m_bankoff_u32 = 0; + +	do { +		ret = u4_memBegin( &l_ecc_t ); + +		if( ret < RET_ERR ) { +			uint32_t l_bank_u32 = l_ecc_t.m_rank_u32 / 2; +			printf( "\r\n-----------------------------------------------------" ); +			printf( "\r\n  switching off memory bank %u due to memory failure", l_bank_u32 ); +			printf( "\r\n-----------------------------------------------------" ); +			m_bankoff_u32 |= ( 1 << l_bank_u32 ); +		} + +	} while( ret < RET_ERR ); + +} diff --git a/roms/SLOF/board-js2x/romfs/boot_rom.ffs b/roms/SLOF/board-js2x/romfs/boot_rom.ffs new file mode 100644 index 00000000..fe54cb67 --- /dev/null +++ b/roms/SLOF/board-js2x/romfs/boot_rom.ffs @@ -0,0 +1,22 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2011 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# *     IBM Corporation - initial implementation +# ****************************************************************************/ + +# FFile-Name	Real Filename			Flags		ROM-Offset i/a +#--------------|-------------------------------|---------------|-------------- +header		romfs/header.img		0		0 +stage1		board-js2x/llfw/stage1.bin	1		0x100 +xvect		slof/xvect.bin			0		0 +ofw_main	board-js2x/slof/paflof		0		0 +stageS		board-js2x/llfw/stageS.bin	0		0 +bootinfo	board-js2x/llfw/Cboot.bin	0		0 +rtas		board-js2x/rtas/rtas.bin	0		0 +snk		clients/net-snk.client		0		0 diff --git a/roms/SLOF/board-js2x/rtas/Makefile b/roms/SLOF/board-js2x/rtas/Makefile new file mode 100644 index 00000000..5ab5c34c --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/Makefile @@ -0,0 +1,89 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# *     IBM Corporation - initial implementation +# ****************************************************************************/ + +include ../Makefile.dirs + +include $(TOPBRDDIR)/config +include $(TOPCMNDIR)/make.rules + + +LDFLAGS		= -nostdlib +CPPFLAGS	= -I. -I$(LIBCMNDIR)/libc/include -I$(LIBCMNDIR)/libipmi -I$(INCLBRDDIR) \ +		  -I$(INCLCMNDIR) -I$(RTASCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH) +ASFLAGS		= -Wa,-mregnames $(FLAG) +CFLAGS		+= -Wall -Wextra -O2 -msoft-float -ffreestanding $(FLAG) + +# Board specific RTAS files: +BOARD_SRC_ASM	= +BOARD_SRC_C	= rtas_flash.c rtas_board.c rtas_pci.c  \ +		  rtas_out.c rtas_table.c  +BOARD_SRCS	= $(BOARD_SRC_ASM) $(BOARD_SRC_C) +BOARD_OBJ	= $(BOARD_SRC_ASM:%.S=%.o) $(BOARD_SRC_C:%.c=%.o) $(BOARD_OCO:%.oco=%.o) +BOARD_OCO	= i2c_bmc.oco ipmi_oem.oco + + +# Common RTAS files (from $(RTASCMNDIR) directory): +RTAS_SRC_ASM	= rtas_entry.S rtas_common.S reloc.S +RTAS_SRC_C	= rtas_call.c +RTAS_SRCS	= $(RTAS_SRC_ASM) $(RTAS_SRC_C) +RTAS_OBJ	= $(RTAS_SRC_ASM:%.S=%.o) $(RTAS_SRC_C:%.c=%.o) + +RTAS_FLASH_SRC  = block_lists.c +RTAS_FLASH_OBJ  = $(RTAS_FLASH_SRC:%.c=$(RTASCMNDIR)/flash/%.o) + +# Additional object files: +EXTRA_OBJ	= ../llfw/hw.o ../../lib/libc.a ../../lib/libipmi.a + +OBJS 		= $(RTAS_OBJ:%=$(RTASCMNDIR)/%) $(BOARD_OBJ) $(EXTRA_OBJ) \ +		  $(RTAS_FLASH_OBJ) + + +all:	Makefile.dep rtas.bin + +rtas.bin: rtas  +	$(OBJCOPY) -O binary $< $@ + +rtas: $(RTASCMNDIR)/rtas.lds $(OBJS) reloc_table.o  +	$(LD) $(LDFLAGS) -o $@ -T $(RTASCMNDIR)/rtas.lds $(OBJS) reloc_table.o + +reloc_table.o: $(TOOLSDIR)/gen_reloc_table $(OBJS) +	$(TOOLSDIR)/create_reloc_table.sh --ld "$(ONLY_LD)" --ldflags "$(LDFLAGS)" \ +	  --lds "$(RTASCMNDIR)/rtas.lds" --objcopy "$(OBJCOPY)" $(OBJS) + +$(TOOLSDIR)/gen_reloc_table: $(TOOLSDIR)/gen_reloc_table.c +	$(MAKE) -C $(TOOLSDIR) gen_reloc_table + +../../lib/libc.a: +	$(MAKE) -C ../../lib + +clean: +	$(MAKE) -C ../../lib clean +	rm -f $(OBJS) reloc_table.o rtas rtas.bin + +distclean : clean +	rm -f Makefile.dep + + +# Rules for creating the dependency file: +depend: +	$(CC) -MM $(CPPFLAGS) $(CFLAGS) $(BOARD_SRCS) > Makefile.dep +	$(CC) -MM $(CPPFLAGS) $(CFLAGS) $(RTAS_SRCS:%=$(RTASCMNDIR)/%) \ +	  | sed -e '/:/s,^,$(RTASCMNDIR)/,' >> Makefile.dep +Makefile.dep: +	$(MAKE) depend + +# Include dependency file if available: +ifneq (,$(wildcard Makefile.dep)) +include Makefile.dep +endif +%.o: %.oco +	cp -f $< $@ diff --git a/roms/SLOF/board-js2x/rtas/i2c_bmc.oco b/roms/SLOF/board-js2x/rtas/i2c_bmc.ocoBinary files differ new file mode 100644 index 00000000..004e7f2e --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/i2c_bmc.oco diff --git a/roms/SLOF/board-js2x/rtas/ipmi_oem.oco b/roms/SLOF/board-js2x/rtas/ipmi_oem.ocoBinary files differ new file mode 100644 index 00000000..ae401eaf --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/ipmi_oem.oco diff --git a/roms/SLOF/board-js2x/rtas/rtas_board.c b/roms/SLOF/board-js2x/rtas/rtas_board.c new file mode 100644 index 00000000..7f7409d9 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_board.c @@ -0,0 +1,218 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdint.h> +#include <rtas.h> +#include "rtas_board.h" +#include <bmc.h> +#include <rtas_i2c_bmc.h> +#include <rtas_ipmi_bmc.h> +#include "libipmi.h" +#include <hw.h> + +void io_init(void); +short reg_get_flashside(void); +void rtas_init(void); + +typedef struct { +	uint64_t r3; +	uint64_t addr; +	volatile uint64_t id; +} slave_t; + +volatile slave_t rtas_slave_interface; + +static void +rtas_slave_loop(volatile slave_t * pIface) +{ +	uint64_t mask = pIface->id; +	pIface->id = 0; +	while (pIface->id != mask); { +		int dly = 0x1000; +		while (dly--); +	} +	pIface->id = 0; +	asm volatile ("  mr 3,%0 ; mtctr %1 ; bctr " +			::"r"(pIface->r3), "r"(pIface->addr)); +} + +void +rtas_fetch_slaves(rtas_args_t * pArgs) +{ +	int retVal = 0; +	int idx = 0; +	uint32_t mask = pArgs->args[0] & 0xFFFFFFFE; +	uint64_t *rtas_slave_loop_ptr = (uint64_t *)rtas_slave_loop; +	while (mask) { +		if (mask & 0x1) { +			rtas_slave_interface.id = idx | 0x100; +			*(int *) 0x3fc0 = (int)(unsigned long) &rtas_slave_interface;	// r3 +			*(int *) 0x3f80 = *rtas_slave_loop_ptr;		// addr +			*(int *) 0x3fa0 = idx | 0x100;	// pid +			while (rtas_slave_interface.id); +		} +		mask >>= 1; +		idx++; +	} +	pArgs->args[pArgs->nargs] = retVal; +} + +void +rtas_start_cpu(rtas_args_t * pArgs) +{ +	int retVal = 0; +	int idx = pArgs->args[0];	// pid +	rtas_slave_interface.r3 = pArgs->args[2];	// r3 +	rtas_slave_interface.addr = pArgs->args[1];	// addr +	asm(" sync "); +	rtas_slave_interface.id = idx | 0x100;	// pid +	while (rtas_slave_interface.id); +	pArgs->args[pArgs->nargs] = retVal; +} + +void +rtas_read_vpd(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = +	    bmc_read_vpd((uint8_t *) (uint64_t) pArgs->args[2], pArgs->args[1], +			 pArgs->args[0]); +} + +void +rtas_write_vpd(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = +	    bmc_write_vpd((uint8_t *) (uint64_t) pArgs->args[2], pArgs->args[1], +			  pArgs->args[0]); +} + +void +rtas_set_indicator(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_event_scan(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_stop_bootwatchdog(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = bmc_stop_bootwatchdog(); +} + +void +rtas_set_bootwatchdog(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = bmc_set_bootwatchdog(pArgs->args[0]); +} + +void +rtas_set_flashside(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = bmc_set_flashside(pArgs->args[0]); +} + +void +rtas_get_flashside(rtas_args_t * pArgs) +{ +	int retVal = bmc_get_flashside(); +	pArgs->args[pArgs->nargs] = retVal; +} + +void +rtas_flash_test(rtas_args_t * pArgs) +{ +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_system_reboot(rtas_args_t * pArgs) +{ +	bmc_system_reboot(); +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_power_off(rtas_args_t * pArgs) +{ +	bmc_power_off(); +	pArgs->args[pArgs->nargs] = -1; +} + +void +rtas_get_blade_descr(rtas_args_t * pArgs) +{ +	uint8_t *buffer = (uint8_t *) (uint64_t) pArgs->args[0]; +	uint32_t maxlen = pArgs->args[1]; +	uint32_t retlen = 0; +	uint32_t retval = bmc_get_blade_descr(buffer, maxlen, &retlen); +	pArgs->args[pArgs->nargs] = retlen; +	pArgs->args[pArgs->nargs + 1] = retval; +} + +// for JS20 cannot read blade descr +static uint32_t +dummy_get_blade_descr(uint8_t *dst, uint32_t maxlen, uint32_t *len) +{ +	// to not have a warning we need to do _something_ with *dst and maxlen... +	*dst = *dst; +	maxlen = maxlen; +	*len = 0; +	return -1; +} + +/* read flashside from register */ +short +reg_get_flashside(void) +{ +	short retVal; +	uint8_t val = load8_ci(0xf4003fe3); +	if (val & 0x80) { +		// temp +		retVal = 1; +	} else { +		// perm +		retVal = 0; +	} +	return retVal; +} + +void +rtas_init(void) +{ +	io_init(); +	if (u4Flag) { +		bmc_system_reboot = ipmi_system_reboot; +		bmc_power_off = ipmi_power_off; +		bmc_set_flashside = ipmi_set_flashside; +		bmc_get_flashside = reg_get_flashside; +		bmc_stop_bootwatchdog = ipmi_oem_stop_bootwatchdog; +		bmc_set_bootwatchdog = ipmi_oem_set_bootwatchdog; +		bmc_read_vpd = ipmi_oem_read_vpd; +		bmc_write_vpd = ipmi_oem_write_vpd; +		bmc_get_blade_descr = ipmi_oem_get_blade_descr; +	} else { +		bmc_system_reboot = i2c_system_reboot; +		bmc_power_off = i2c_power_off; +		bmc_set_flashside = i2c_set_flashside; +		bmc_get_flashside = i2c_get_flashside; +		bmc_stop_bootwatchdog = i2c_stop_bootwatchdog; +		bmc_set_bootwatchdog = i2c_set_bootwatchdog; +		bmc_read_vpd = i2c_read_vpd; +		bmc_write_vpd = i2c_write_vpd; +		bmc_get_blade_descr = dummy_get_blade_descr; +	} +} diff --git a/roms/SLOF/board-js2x/rtas/rtas_board.h b/roms/SLOF/board-js2x/rtas/rtas_board.h new file mode 100644 index 00000000..06766e14 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_board.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef __RTAS_BOARD_H +#define __RTAS_BOARD_H + +#include <stddef.h> + +extern volatile unsigned char u4Flag; + +void rtas_ibm_read_pci_config(rtas_args_t * pArgs); +void rtas_ibm_write_pci_config(rtas_args_t * pArgs); +void rtas_read_pci_config(rtas_args_t * pArgs); +void rtas_write_pci_config(rtas_args_t * pArgs); +void rtas_system_reboot(rtas_args_t * pArgs); +void rtas_power_off(rtas_args_t * pArgs); +void rtas_display_character(rtas_args_t * pArgs); +void rtas_flash_test(rtas_args_t * pArgs); +void rtas_ibm_update_flash_64_and_reboot(rtas_args_t * pArgs); +void rtas_set_indicator(rtas_args_t * pArgs); +void rtas_event_scan(rtas_args_t * pArgs); +void rtas_ibm_manage_flash_image(rtas_args_t * pArgs); +void rtas_ibm_validate_flash_image(rtas_args_t * pArgs); +void rtas_update_flash(rtas_args_t * pArgs); +void rtas_set_flashside(rtas_args_t * pArgs); +void rtas_get_flashside(rtas_args_t * pArgs); +void rtas_dump_flash(rtas_args_t * pArgs); +void rtas_start_cpu(rtas_args_t * pArgs); +void rtas_read_vpd(rtas_args_t * pArgs); +void rtas_write_vpd(rtas_args_t * pArgs); +void rtas_fetch_slaves(rtas_args_t * pArgs); +void rtas_stop_bootwatchdog(rtas_args_t * pArgs); +void rtas_get_blade_descr(rtas_args_t * pArgs); +void rtas_set_bootwatchdog(rtas_args_t * pArgs); + +#endif				/* __RTAS_BOARD_H */ diff --git a/roms/SLOF/board-js2x/rtas/rtas_flash.c b/roms/SLOF/board-js2x/rtas/rtas_flash.c new file mode 100644 index 00000000..189878da --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_flash.c @@ -0,0 +1,614 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include <cpu.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> +#include <hw.h> +#include <rtas.h> +#include "rtas_board.h" +#include <bmc.h> +#include "rtas_flash.h" +#include <flash/block_lists.h> +#include "product.h" +#include "calculatecrc.h" + +#undef DEBUG + +#ifdef DEBUG +#define dprintf(_x ...) printf(_x) +#else +#define dprintf(_x ...) +#endif + +static uint64_t size; +static uint64_t flashOffset; + +unsigned char manage_flash_buffer[BUFSIZE*2]; +unsigned long check_flash_image(unsigned long rombase, unsigned long length, +				unsigned long start_crc); + +#ifdef DEBUG +static void +dump_blocklist(uint64_t *bl, int version) +{ +	uint64_t bl_size; +	uint8_t *addr = (uint8_t *)bl; + +	if (version == 1) { +		/* version 1 blocklist */ +		bl_size = *bl & 0x00FFFFFFFFFFFFFFUL; + +	} else { +		bl_size = *bl; +	} + +	printf("\n\rblocklist_dump %lx", bl_size); +	while (bl_size) { +		unsigned int tmpCnt = bl_size; +		unsigned char x; +		if (tmpCnt > 8) +			tmpCnt = 8; +		printf("\n\r%08x: ", addr); +		/* print hex */ +		while (tmpCnt--) { +			set_ci(); +			x = *addr++; +			clr_ci(); +			printf("%02x ", x); +		} +		tmpCnt = bl_size; +		if (tmpCnt > 8) +			tmpCnt = 8; +		bl_size -= tmpCnt; +		/* reset addr ptr to print ascii */ +		addr = addr - tmpCnt; +		/* print ascii */ +		while (tmpCnt--) { +			set_ci(); +			x = *addr++; +			clr_ci(); +			if ((x < 32) || (x >= 127)) { +				/* non-printable char */ +				x = '.'; +			} +			printf("%c", x); +		} +	} +	printf("\r\n"); +} +#endif + +void +rtas_dump_flash(rtas_args_t *rtas_args) +{ +	int retVal = 0; +	unsigned int size = rtas_args->args[0]; +	unsigned int offset = rtas_args->args[1]; +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; + +	printf("\n\rflash_dump %x %x", size, offset); +	flash += offset; +	while (size) { +		unsigned int tmpCnt = size; +		unsigned char x; +		if (tmpCnt > 16) +			tmpCnt = 16; +		printf("\n\r%p: ", flash); +		/* print hex */ +		while (tmpCnt--) { +			set_ci(); +			x = *flash++; +			clr_ci(); +			printf("%02x ", x); +		} +		tmpCnt = size; +		if (tmpCnt > 16) +			tmpCnt = 16; +		size -= tmpCnt; +		/* reset flash ptr to print ascii */ +		flash = flash - tmpCnt; +		/* print ascii */ +		while (tmpCnt--) { +			set_ci(); +			x = *flash++; +			clr_ci(); +			if ((x < 32) || (x >= 127)) { +				/* non-printable char */ +				x = '.'; +			} +			printf("%c", x); +		} +	} +	printf("\r\n"); +	rtas_args->args[rtas_args->nargs] = retVal; +} + + +static void +print_block(int i) +{ +	int counter = 8; + +	while (counter--) +		printf("\b"); +	printf("%08x", i); +} + + + +/* To enter data mode after flash has been in programming mode + * a 0xFF has to be written */ +static void +enter_data_mode(void) +{ +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; + +	set_ci(); +	*flash = 0xFF; +	eieio(); +	clr_ci(); +} + + +static void +erase_flash_block(unsigned long offset) +{ +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; + +	flash += offset; +	set_ci(); +	*flash = 0x20; +	eieio(); +	*flash = 0xd0; +	eieio(); +	while (!(*flash & 0x80)) ; +	clr_ci(); +} + + +void +write_flash(unsigned long offset, unsigned char *data) +{ +	int cnt = 32; +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; + +	flash += (offset + flashOffset); +	set_ci(); +	while (cnt) { +		if (!((uint64_t)flash & 0x1F)) { +			while (cnt) { +				uint64_t tmpcnt = cnt; +				if (tmpcnt > 0x20) +					tmpcnt = 0x20; +				do { +					*flash = 0xE8; +					eieio(); +				} while (!(*flash & 0x80)); +				cnt -= tmpcnt; +				*flash = tmpcnt - 1; +				while (tmpcnt--) { +					*flash++ = *data++; +				} +				*flash = 0xD0; +				eieio(); +				while (!(*flash & 0x80)) ; +			} +			break; +		} +		*flash = 0x40; +		eieio(); +		*flash++ = *data++; +		eieio(); +		while (!(*flash & 0x80)) ; +		cnt--; +	} +	clr_ci(); +} + +static void +write_flash_page(unsigned long offset, unsigned short *data) +{ +	int i = 0; + +	for (i = 0; i < BUFSIZE; i += 32, offset += 32) { +		write_flash(offset, ((unsigned char *)data + i)); +	} +} + +/* + * 0 reject temporary image + * 1 commit temporary image + * */ +static int +copy_flash(short mode) +{ +	volatile unsigned char *flash = (volatile unsigned char *)FLASH; +	uint64_t blockCnt; +	uint64_t hash = 0; +	short notmode = mode ^ 0x1; + +	if (bmc_set_flashside(notmode) != notmode) { +		return -1; +	} +	printf("\r\nErasing Flash: 0x        "); + +	for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += FLASH_BLOCK_SIZE) { +		print_block(blockCnt); +		erase_flash_block(blockCnt); +	} +	enter_data_mode(); +	progress = FLASHSIZE / 38; +	print_writing(); + +	for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += BUFSIZE) { +		uint64_t *srcPtr = (uint64_t *)(flash + blockCnt); +		uint64_t *destPtr = (uint64_t *)manage_flash_buffer; +		uint64_t cnt = BUFSIZE / 8; +		if (bmc_set_flashside(mode) != mode) { +			return -1; +		} +		enter_data_mode(); +		set_ci(); +		while (cnt--) { +			*destPtr++ = *srcPtr++; +		} +		clr_ci(); + +		if (bmc_set_flashside(notmode) != notmode) { +			return -1; +		} +		write_flash_page(blockCnt, +				 (unsigned short *)manage_flash_buffer); + +		/* progress output... */ +		print_progress(); +		if (blockCnt > hash * progress) { +			print_hash(); +			hash++; +		} +	} +	enter_data_mode(); +	if (bmc_set_flashside(mode) != mode) { +		return -1; +	} +	printf("\b#\n"); +	return 0; +} + +/* + * Function: ibm_manage_flash_image + *	Input: + *		r3:   rtas parm structure + *			token:  46 + *			in:     1 + *			out:    1 + *			parm0:  0 reject temporary image + *				1 commit temporary image + *	Output: + *			parm1:  Status (hw -1, busy -2, parameter error -3 + *					-9001 cannot overwrite the active firmware image) + * + */ + +void +rtas_ibm_manage_flash_image(rtas_args_t *rtas_args) +{ +	int side; +	int result = 0; +	short mode = rtas_args->args[0]; + +	if (mode < 0 || mode > 1) { +		rtas_args->args[rtas_args->nargs] = -3; +		return; +	} +	side = bmc_get_flashside(); +	if (side == 0) { +		/* we are on the permanent side */ +		if (mode != 0) { +			rtas_args->args[rtas_args->nargs] = -9001; +			return; +		} +	} else if (side == 1) { +		/* we are on the temporary side */ +		if (mode != 1) { +			rtas_args->args[rtas_args->nargs] = -9001; +			return; +		} +	} else { +		rtas_args->args[rtas_args->nargs] = -1; +		return; +	} + +	result = copy_flash(mode); +	bmc_set_flashside(mode); +	enter_data_mode(); +	rtas_args->args[rtas_args->nargs] = result; +} + +/** + * check, if we find the FLASHFS_MAGIC token in bl + **/ +static uint8_t +check_magic(uint64_t *bl, int version) +{ +	struct stH *pHeader; + +	if (version == 1) { +		/* version 1 blocklist */ +		/* if block list size <= 0x10, it is only block list header */ +		/* and address of block list extension, so look at the extension... */ +		while ((*bl & 0x00FFFFFFFFFFFFFFUL) <= 0x10) +			bl = (uint64_t *)bl[1]; + +		/* block list item 2 _should_ be the address of our flashfs image */ +		pHeader = (struct stH *)(bl[2] + 0x28); +		/* printf("FlashFS Magic: \"%#s\"\r\n", pHeader->magic); */ +		return strncmp(pHeader->magic, FLASHFS_MAGIC, 8); +	} else { +		/* block list item 1 _should_ be the address of our flashfs image */ +		pHeader = (struct stH *)(bl[1] + 0x28); +		/* printf("FlashFS Magic: \"%#s\"\r\n", pHeader->magic); */ +		return strncmp(pHeader->magic, FLASHFS_MAGIC, 8); +	} +} + +static void +get_image_name(char *buffer, int maxsize) +{ +	volatile struct stH *flash_header = (volatile struct stH *)(SB_FLASH_adr + 0x28); +	/* since we cannot read the fh_magic directly from flash as a string, we need to copy it to memory */ +	uint64_t magic_val = 0; +	uint64_t addr; + +	/* copy fh_magic to magic_val since, we cannot use it as a string from flash */ +	magic_val = load64_ci((uint64_t)(flash_header->magic)); +	if (strncmp((char *)&magic_val, FLASHFS_MAGIC, 8)) { +		/* magic does not match */ +		sprintf(buffer, "Unknown"); +		buffer[maxsize - 1] = '\0'; +		return; +	} +	addr = (uint64_t)flash_header->version; +	while (--maxsize) { +		*buffer = load8_ci(addr++); +		if (!*buffer++) +			return; +	} +	*buffer = '\0'; +} + +/** + * validate_flash_image + * this function checks if the flash will be updated with the given image + * @param args[0] - buffer with minimum 4K of the image to flash + * @param args[1] - size of the buffer + * @param args[2] - status: + *                           0    success + *                          -1    hw + *                          -2    busy + *                          -3    parameter error + * @param args[3] - update result token + */ +void +rtas_ibm_validate_flash_image(rtas_args_t *rtas_args) +{ +	dprintf("\nrtas_ibm_validate_flash_image\n"); +	unsigned long new_image = rtas_args->args[0]; +	char *ret_str = (char *)new_image; +	struct stH *flash_header = (struct stH *)(new_image + 0x28); +	char current_temp_version[16]; +	char current_perm_version[16]; +	char new_version[16]; +	int side = bmc_get_flashside(); + +	/* fill args[0] with the current values which is needed +	 * in an error case */ + +	bmc_set_flashside(0); +	get_image_name(current_perm_version, sizeof(current_perm_version)); +	bmc_set_flashside(1); +	get_image_name(current_temp_version, sizeof(current_temp_version)); +	bmc_set_flashside(side); + +	/* check if the candidate image if valid for this platform */ +	if (strncmp(flash_header->magic, FLASHFS_MAGIC, 8)) { +		/* magic does not match */ +		rtas_args->args[rtas_args->nargs] = 0; +		/* No update done, the candidate image is +		 * not valid for this platform */ +		rtas_args->args[rtas_args->nargs + 1] = 2; +		sprintf(ret_str, "MI %s %s\xaMI %s %s", +			current_temp_version, current_perm_version, +			current_temp_version, current_perm_version); +		return; +	} + +	if (strncmp(flash_header->platform_name, (char *)sig_org, 32)) { +		/* this image if for a different board */ +		rtas_args->args[rtas_args->nargs] = 0; +		/* No update done, the candidate image is +		 * not valid for this platform */ +		rtas_args->args[rtas_args->nargs + 1] = 2; +		sprintf(ret_str, "MI %s %s\xaMI %s %s", +			current_temp_version, current_perm_version, +			current_temp_version, current_perm_version); +		return; +	} + +	/* check header crc */ +	if (check_flash_image(rtas_args->args[0], 0x88, 0)) { +		/* header crc failed */ +		rtas_args->args[rtas_args->nargs] = 0; +		/* No update done, the candidate image is +		 * not valid for this platform */ +		rtas_args->args[rtas_args->nargs + 1] = 2; +		sprintf(ret_str, "MI %s %s\xaMI %s %s", +			current_temp_version, current_perm_version, +			current_temp_version, current_perm_version); +		return; +	} +	memcpy(new_version, flash_header->version, 16); +	sprintf(ret_str, "MI %s %s\xaMI %s %s", current_temp_version, +		current_perm_version, new_version, current_perm_version); +	rtas_args->args[rtas_args->nargs] = 0; + +	if (strncmp(new_version, current_temp_version, 16) >= 0) +		rtas_args->args[rtas_args->nargs + 1] = 0; +	else +		rtas_args->args[rtas_args->nargs + 1] = 6; +} + +/* + * Function: ibm_update_flash_64 + *	Input: + *		r3:   rtas parm structure + *			token:  7 + *			in:     1 + *			out:    1 + *			parm0:  A real pointer to a block list + *	Output: + *			parm1:  Status (hw -1, bad image -3, programming failed -4) + * + *   Description: flash if addresses above 4GB have to be addressed + */ +void +rtas_update_flash(rtas_args_t *rtas_args) +{ +	void *bl = (void *)(uint64_t)rtas_args->args[0]; +	int version = get_block_list_version((unsigned char *)bl); +	uint64_t erase_size; +	unsigned int i; +	int perm_check = 1; + +#ifdef DEBUG +	dump_blocklist(bl, version); +#endif + +	/* from SLOF we pass a second (unofficial) parameter, if this parameter is 1, we do not +	 * check wether we are on permanent side. Needed for update-flash -c to work! */ +	if ((rtas_args->nargs > 1) && (rtas_args->args[1] == 1)) +		perm_check = 0; + +	/* check magic string */ +	printf("\r\nChecking magic string : "); +	if (check_magic(bl, version) != 0) { +		printf("failed!\n"); +		rtas_args->args[rtas_args->nargs] = -3; /* bad image */ +		return; +	} +	printf("succeeded!\n"); + +	/* check platform */ +	printf("Checking platform : "); +	if (check_platform(bl, 0x48, version) == -1) { +		printf("failed!\n"); +		rtas_args->args[rtas_args->nargs] = -3; /* bad image */ +		return; +	} +	printf("succeeded!\n"); + +	/* checkcrc */ +	printf("Checking CRC : "); +	/* the actual CRC is included at the end of the flash image, thus the resulting CRC must be 0! */ +	if (image_check_crc(bl, version) != 0) { +		printf("failed!\n"); +		rtas_args->args[1] = -3;        /* bad image */ +		return; +	} +	printf("succeeded!\n"); + +	/* check if we are running on P +	 * if so, let's switch to temp and flash temp */ +	if (bmc_get_flashside() == 0  && perm_check) { +		printf("Set flashside: "); +		bmc_set_flashside(1); +		printf("Temp!\n"); +	} + +#ifdef DEBUG +	rtas_args_t ra; +	ra.args[0] = 0x100;     /* size; */ +	ra.args[1] = flashOffset; +	ra.nargs = 2; + +	rtas_dump_flash(&ra); +	printf("\n"); +#endif + +	size = get_size(bl, version); +	erase_size = (size + (FLASH_BLOCK_SIZE - 1)) & ~(FLASH_BLOCK_SIZE - 1); +	dprintf("Erasing: size: %#x, erase_size: %#x, FLASH_BLOCK_SIZE: %#x\n", +		size, erase_size, FLASH_BLOCK_SIZE); + +	progress = size / 39; +	printf("Erasing : 0x%08x", 0); +	for (i = 0; i < erase_size; i += FLASH_BLOCK_SIZE) { +		print_block(i); +		erase_flash_block(i); +	} + +	enter_data_mode(); +#ifdef DEBUG +	rtas_dump_flash(&ra); +	printf("\n"); +#endif +	print_writing(); +	write_block_list(bl, version); +	printf("\b#\n"); +	enter_data_mode(); + +#ifdef DEBUG +	rtas_dump_flash(&ra); +	printf("\n"); +#endif + +	/* checkcrc */ +	printf("Recheck CRC : "); +	if (check_flash_image(FLASH + flashOffset, size, 0) != 0) { +		/* failed */ +		printf("failed!\n\r"); +		dprintf("flash_addr: %#x, flashOffset: %#x, size: %#x\n", FLASH, +			flashOffset, size); +		dprintf("crc: %#x\n", +			check_flash_image(FLASH + flashOffset, size, 0)); +		rtas_args->args[rtas_args->nargs] = -4; /* programming failed */ +		return; +	} +	printf("succeeded!\n"); +	rtas_args->args[rtas_args->nargs] = 0; +} + +/* + * Function: ibm_update_flash_64_and_reboot + *	Input: + *		r3:   rtas parm structure + *			token:  27 + *			in:     1 + *			out:    1 + *			parm0:  A real pointer to a block list + *	Output: + *			parm1:  Status (hw -1, bad image -3, programming failed -4) + *				Currently -4 and -1 are not returned + * + *  Description: flash and reboot if addresses above 4GB have to be addressed + */ +void +rtas_ibm_update_flash_64_and_reboot(rtas_args_t *rtas_args) +{ +	rtas_update_flash(rtas_args); +	dprintf("rc: %#d\n", rtas_args->args[rtas_args->nargs]); +	if (rtas_args->args[rtas_args->nargs] == 0) { +		rtas_system_reboot(rtas_args); +	} +} diff --git a/roms/SLOF/board-js2x/rtas/rtas_flash.h b/roms/SLOF/board-js2x/rtas/rtas_flash.h new file mode 100644 index 00000000..3eec45d2 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_flash.h @@ -0,0 +1,20 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include <southbridge.h> + +#define FLASHSIZE FLASH_LENGTH +#define FLASH SB_FLASH_adr +#define BUFSIZE 4096 +#define FLASH_BLOCK_SIZE 0x20000 + +void write_flash(unsigned long offset, unsigned char *data); diff --git a/roms/SLOF/board-js2x/rtas/rtas_i2c_bmc.h b/roms/SLOF/board-js2x/rtas/rtas_i2c_bmc.h new file mode 100644 index 00000000..e46de880 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_i2c_bmc.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef __RTAS_I2C_BMC_H +#define __RTAS_I2C_BMC_H + +#include <stddef.h> + +void i2c_system_reboot (void); +void i2c_power_off (void); +short i2c_set_flashside (short mode); +short i2c_get_flashside (void); +int i2c_stop_bootwatchdog (void); +uint32_t i2c_read_vpd (uint8_t *dst, uint32_t len, uint32_t offset); +uint32_t i2c_write_vpd (uint8_t *src, uint32_t len, uint32_t offset); +int i2c_set_bootwatchdog(unsigned short seconds); + +#endif		/* __RTAS_I2C_BMC_H */ diff --git a/roms/SLOF/board-js2x/rtas/rtas_ipmi_bmc.h b/roms/SLOF/board-js2x/rtas/rtas_ipmi_bmc.h new file mode 100644 index 00000000..00532d4c --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_ipmi_bmc.h @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef __RTAS_IPMI_BMC_H +#define __RTAS_IPMI_BMC_H + +#include <stddef.h> + +short ipmi_set_flashside (short mode); +short ipmi_get_flashside (void); + +#endif		/* __RTAS_IPMI_BMC_H */ diff --git a/roms/SLOF/board-js2x/rtas/rtas_out.c b/roms/SLOF/board-js2x/rtas/rtas_out.c new file mode 100644 index 00000000..ce4c00bd --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_out.c @@ -0,0 +1,120 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include <cpu.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <rtas.h> +#include <hw.h> +#include "rtas_board.h" + +volatile unsigned char *uart; +volatile unsigned char u4Flag; + +void io_init(void); +unsigned long check_flash_image(unsigned long rombase, unsigned long length, +				unsigned long start_crc); + +void +io_init(void) +{ +	// read ID register: only if it is a PC87427, enable serial2 +	store8_ci(0xf400002e, 0x20); +	if (load8_ci(0xf400002f) != 0xf2) { +		uart = (volatile unsigned char *) 0xf40003f8; +		u4Flag = 0; +	} else { +		uart = (volatile unsigned char *) 0xf40002f8; +		u4Flag = 1; +	} +} + +static void +display_char(char ch) +{ +	volatile int i = 0; +	volatile unsigned char *uart = (volatile unsigned char *) 0xf40002f8; +	int cnt = 2; +	while (cnt--) { +		set_ci(); +		while (!(uart[5] & 0x20)) { +			i++; +		} +		uart[0] = ch; +		clr_ci(); +		uart += 0x100; +	} +} + +ssize_t +write(int fd __attribute((unused)), const void *buf, size_t cnt) +{ +	while (cnt--) { +		display_char(*(char *) buf); +		if (*(char *) buf++ == '\n') +			display_char('\r'); +	} +	return 0; +} + +void * +sbrk(int incr __attribute((unused))) +{ +	return (void *) -1; +} + + + +void +rtas_display_character(rtas_args_t * pArgs) +{ +	int retVal = 0; +	display_char((char) pArgs->args[0]); +	pArgs->args[1] = retVal; +} + +unsigned long +check_flash_image(unsigned long rombase, unsigned long length, +		  unsigned long start_crc) +{ +	const uint32_t CrcTableHigh[16] = { +		0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90, +		0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7, +		0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E, +		0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09 +	}; +	const uint32_t CrcTableLow[16] = { +		0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, +		0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, +		0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, +		0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD +	}; + +	char *Buffer = (char *) rombase; +	uint32_t AccumCRC = start_crc; +	char val; +	uint32_t Temp; +	while (length-- > 0) { +		set_ci(); +		val = *Buffer; +		clr_ci(); +		Temp = ((AccumCRC >> 24) ^ val) & 0x000000ff; +		AccumCRC <<= 8; +		AccumCRC ^= CrcTableHigh[Temp / 16]; +		AccumCRC ^= CrcTableLow[Temp % 16]; +		++Buffer; +	} +	return AccumCRC; +} diff --git a/roms/SLOF/board-js2x/rtas/rtas_pci.c b/roms/SLOF/board-js2x/rtas/rtas_pci.c new file mode 100644 index 00000000..55dbf533 --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_pci.c @@ -0,0 +1,116 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ +#include <stdint.h> +#include <rtas.h> +#include <hw.h> +#include "rtas_board.h" + +void +rtas_ibm_read_pci_config (rtas_args_t *rtas_args) +{ +	int retVal = 0; +	uint64_t addr = ((uint64_t) rtas_args->args[1]) << 32;  // high 32 bits of PHB UID +	addr |= (rtas_args->args[2] & 0xFFFFFFFF); // low 32 bits of PHB UID +	addr |= (rtas_args->args[0] & 0x00FFFFFF); // bus, devfn, offset +	unsigned int size = rtas_args->args[3]; + +	/* Check for bus != 0  on PCI/PCI-X (PHB UID = 0xf2000000) */ +	if (((addr & 0xf2000000) == 0xf2000000) && (addr & 0xff0000)) +		addr += 0x1000000; + +	if (size == 1) +		rtas_args->args[5] = load8_ci(addr); +	else if (size == 2) +		rtas_args->args[5] = bswap16_load(addr); +	else if (size == 4) +		rtas_args->args[5] = bswap32_load(addr); +	else +		retVal = -3;  /* Bad arguments */ + +	rtas_args->args[4] = retVal; +} + +void +rtas_ibm_write_pci_config (rtas_args_t *rtas_args) +{ +	int retVal = 0; +	uint64_t addr = ((uint64_t) rtas_args->args[1]) << 32;  // high 32 bits of PHB UID +	addr |= (rtas_args->args[2] & 0xFFFFFFFF); // low 32 bits of PHB UID +	addr |= (rtas_args->args[0] & 0x00FFFFFF); // bus, devfn, offset +	unsigned int size = rtas_args->args[3]; + +	addr |= 0xf2000000; + +	/* Check for bus != 0  on PCI/PCI-X (PHB UID = 0xf2000000) */ +	if (((addr & 0xf2000000) == 0xf2000000) && (addr & 0xff0000)) +		addr += 0x1000000; + +	if (size == 1) +		store8_ci(addr, rtas_args->args[4]); +	else if (size == 2) +		bswap16_store(addr, rtas_args->args[4]); +	else if (size == 4) +		bswap32_store(addr, rtas_args->args[4]); +	else +		retVal = -3;  /* Bad arguments */ + +	rtas_args->args[5] = retVal; +} + +void +rtas_read_pci_config (rtas_args_t *rtas_args) +{ +	int retVal = 0; +	unsigned long addr = rtas_args->args[0]; +	unsigned int size = rtas_args->args[1]; +	addr |= 0xf2000000; + +	/* Check for bus != 0 */ +	if (addr & 0xff0000) +		addr += 0x1000000; + +	if (size == 1) +		rtas_args->args[3] = load8_ci(addr); +	else if (size == 2) +		rtas_args->args[3] = bswap16_load(addr); +	else if (size == 4) +		rtas_args->args[3] = bswap32_load(addr); +	else +		retVal = -3;  /* Bad arguments */ + +	rtas_args->args[2] = retVal; +} + +void +rtas_write_pci_config (rtas_args_t *rtas_args) +{ +	int retVal = 0; +	unsigned long addr = rtas_args->args[0]; +	unsigned int size = rtas_args->args[1]; + +	addr |= 0xf2000000; + +	/* Check for bus != 0 */ +	if (addr & 0xff0000) +		addr += 0x1000000; + +	if (size == 1) +		store8_ci(addr, rtas_args->args[2]); +	else if (size == 2) +		bswap16_store(addr, rtas_args->args[2]); +	else if (size == 4) +		bswap32_store(addr, rtas_args->args[2]); +	else +		retVal = -3;  /* Bad arguments */ + +	rtas_args->args[3] = retVal; +} diff --git a/roms/SLOF/board-js2x/rtas/rtas_table.c b/roms/SLOF/board-js2x/rtas/rtas_table.c new file mode 100644 index 00000000..fed4032a --- /dev/null +++ b/roms/SLOF/board-js2x/rtas/rtas_table.c @@ -0,0 +1,45 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + *     IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdint.h> +#include <rtas.h> +#include "rtas_table.h" +#include "rtas_board.h" + +const rtas_funcdescr_t rtas_func_tab[] = { +	{"ibm,read-pci-config", rtas_ibm_read_pci_config, 0}, +	{"ibm,write-pci-config", rtas_ibm_write_pci_config, 0}, +	{"system-reboot", rtas_system_reboot, 0}, +	{"power-off", rtas_power_off, 0}, +	{"set-indicator", rtas_set_indicator, 0}, +	{"rtas-flash-test", rtas_flash_test, RTAS_TBLFLG_INTERNAL}, +	{"ibm,update-flash-64-and-reboot", rtas_ibm_update_flash_64_and_reboot, 0}, +	{"display-character", rtas_display_character, 0}, +	{"event-scan", rtas_event_scan, 0}, +	{"ibm,manage-flash-image", rtas_ibm_manage_flash_image, 0}, +	{"ibm,validate-flash-image", rtas_ibm_validate_flash_image, 0}, +	{"ibm,update-flash-64", rtas_update_flash, 0}, +	{"rtas-set-flashside", rtas_set_flashside, 0}, +	{"rtas-get-flashside", rtas_get_flashside, 0}, +	{"rtas-dump-flash", rtas_dump_flash, RTAS_TBLFLG_INTERNAL}, +	{"start-cpu", rtas_start_cpu, 0}, +	{"msg-read-vpd", rtas_read_vpd, RTAS_TBLFLG_INTERNAL}, +	{"msg-write-vpd", rtas_write_vpd, RTAS_TBLFLG_INTERNAL}, +	{"read-pci-config", rtas_read_pci_config, 0}, +	{"write-pci-config", rtas_write_pci_config, 0}, +	{"rtas-fetch-slaves", rtas_fetch_slaves, RTAS_TBLFLG_INTERNAL}, +	{"rtas-stop-bootwatchdog", rtas_stop_bootwatchdog, RTAS_TBLFLG_INTERNAL}, +	{"rtas-set-bootwatchdog", rtas_set_bootwatchdog, RTAS_TBLFLG_INTERNAL}, +	{"rtas-get-blade-descr", rtas_get_blade_descr, RTAS_TBLFLG_INTERNAL}, +}; + +const int rtas_func_tab_size = sizeof(rtas_func_tab) / sizeof(rtas_func_tab[0]); diff --git a/roms/SLOF/board-js2x/slof/Makefile b/roms/SLOF/board-js2x/slof/Makefile new file mode 100644 index 00000000..ab3e683a --- /dev/null +++ b/roms/SLOF/board-js2x/slof/Makefile @@ -0,0 +1,111 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# *     IBM Corporation - initial implementation +# ****************************************************************************/ + + +include ../Makefile.dirs + +include $(TOPBRDDIR)/config +include $(TOPCMNDIR)/make.rules + + +all: Makefile.dep OF.ffs paflof $(SLOFCMNDIR)/xvect.bin + +CPPFLAGS = -I$(LIBCMNDIR)/libbootmsg -I$(LIBCMNDIR)/libnvram \ +	   -I$(LIBCMNDIR)/libusb -I$(LIBCMNDIR)/libbcm +SLOF_LIBS = \ +	$(LIBCMNDIR)/libbootmsg.a \ +	$(LIBCMNDIR)/libelf.a \ +	$(LIBCMNDIR)/libusb.a \ +	$(LIBCMNDIR)/libnvram.a \ +	$(LIBCMNDIR)/libbcm.a +BOARD_SLOF_IN = \ +	$(LIBCMNDIR)/libbootmsg/bootmsg.in \ +	$(LIBCMNDIR)/libelf/libelf.in \ +	$(LIBCMNDIR)/libusb/usb.in \ +	$(LIBCMNDIR)/libbases/libbases.in  \ +	$(LIBCMNDIR)/libnvram/libnvram.in \ +	$(LIBCMNDIR)/libnativeio/nativeio.in \ +	$(LIBCMNDIR)/libbcm/bcm.in +BOARD_SLOF_CODE = $(BOARD_SLOF_IN:%.in=%.code) + +include $(SLOFCMNDIR)/Makefile.inc + +FPPINCLUDES = -I. -I$(SLOFCMNDIR)/fs -I$(SLOFCMNDIR) + +USB_FFS_FILES = \ +	$(SLOFCMNDIR)/fs/devices/pci-class_0c.fs \ +	$(SLOFCMNDIR)/fs/usb/dev-hci.fs \ +	$(SLOFCMNDIR)/fs/usb/slofdev.fs \ +	$(SLOFCMNDIR)/fs/usb/dev-parent-calls.fs \ +	$(SLOFCMNDIR)/fs/usb/dev-keyb.fs \ +	$(SLOFCMNDIR)/fs/usb/dev-mouse.fs \ +	$(SLOFCMNDIR)/fs/usb/dev-storage.fs \ +	$(SLOFCMNDIR)/fs/usb/dev-hub.fs + +# Files that should go into the ROM fs (and so have to be listed in OF.ffs): +OF_FFS_FILES = \ +	$(SLOFBRDDIR)/u4-mem.fs \ +	$(SLOFBRDDIR)/attu.fs \ +	$(SLOFBRDDIR)/cpu.fs \ +	$(SLOFBRDDIR)/ioapic.fs \ +	$(SLOFBRDDIR)/pci-bridge_1022_7460.fs \ +	$(SLOFBRDDIR)/pci-device_1014_028c.fs \ +	$(SLOFBRDDIR)/pci-device_1014_02bd.fs \ +	$(SLOFBRDDIR)/pci-device_1022_7468.fs \ +	$(SLOFBRDDIR)/pci-device_1022_7469.fs \ +	$(SLOFBRDDIR)/pci-device_1022_7451.fs \ +	$(SLOFBRDDIR)/pci-device_14e4_16a8.fs \ +	$(SLOFBRDDIR)/bcm57xx.fs \ +	$(SLOFBRDDIR)/pci-class_03.fs \ +	$(SLOFBRDDIR)/vga-display.fs \ +	$(SLOFBRDDIR)/freq.fs \ +	$(SLOFBRDDIR)/pci-device_1002_515e.fs \ +	$(SLOFBRDDIR)/citrine.fs \ +	$(SLOFBRDDIR)/citrine-disk.fs \ +	$(SLOFBRDDIR)/sio.fs \ +	$(SLOFBRDDIR)/tpm.fs \ +	$(SLOFBRDDIR)/ipmi-kcs.fs \ +	$(SLOFCMNDIR)/fs/ide.fs \ +	$(SLOFCMNDIR)/fs/fbuffer.fs \ +	$(SLOFCMNDIR)/fs/graphics.fs \ +	$(SLOFCMNDIR)/fs/generic-disk.fs \ +	$(SLOFCMNDIR)/fs/scsi-disk.fs \ +	$(SLOFCMNDIR)/fs/scsi-host-helpers.fs \ +	$(SLOFCMNDIR)/fs/scsi-probe-helpers.fs \ +	$(SLOFCMNDIR)/fs/scsi-support.fs \ +	$(SLOFCMNDIR)/fs/pci-device.fs \ +	$(SLOFCMNDIR)/fs/pci-bridge.fs \ +	$(SLOFCMNDIR)/fs/pci-properties.fs \ +	$(SLOFCMNDIR)/fs/pci-config-bridge.fs \ +	$(SLOFCMNDIR)/fs/update_flash.fs \ +	$(SLOFCMNDIR)/fs/xmodem.fs \ +	$(SLOFCMNDIR)/fs/devices/pci-device_10de_0141.fs \ +	$(SLOFCMNDIR)/fs/devices/pci-class_02.fs \ +	$(SLOFBRDDIR)/default-font.bin + +# Uncomment the following line to enable the USB code: +OF_FFS_FILES += $(USB_FFS_FILES) + +OF_FFS_FILES := $(OF_FFS_FILES:%.fs=%.fsi) + +OF.ffs: Makefile $(SLOFCMNDIR)/Makefile.inc $(OF_FFS_FILES) +	$(MAKE) create_OF_ffs + +# Rules for cleaning up: +.PHONY: clean_here clean distclean + +clean_here: +	rm -f *.o OF.fsi OF.ffs + +clean: clean_here clean_slof + +distclean: clean_here distclean_slof diff --git a/roms/SLOF/board-js2x/slof/OF.fs b/roms/SLOF/board-js2x/slof/OF.fs new file mode 100644 index 00000000..3e377358 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/OF.fs @@ -0,0 +1,557 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ The master file.  Everything else is included into here. + +hex + +' ll-cr to cr + +\ as early as possible we want to know if it is js20, js21 or bimini +\ u3 = js20; u4 = js21/bimini +\ the difference if bimini or js21 will be done later depending if +\ obsidian or citrine is found +\ f8000000 is probably the place of the u3/u4 version +f8000000 rl@ CONSTANT uni-n-version +uni-n-version 4 rshift  dup 3 = CONSTANT u3?  4 = CONSTANT u4? +\ if (f4000682 >> 4) == 1... it is a bimini... +f4000682 rb@ 4 rshift 1 = CONSTANT bimini? + +\ to decide wether vga initialisation using bios emulation should be attempted, +\ we need to know wether a vga-device was found during pci-scan. +\ If it is found, this value will be set to the device's phandle +0 value vga-device-node? + +\ planar-id reads back GPIO 29 30 31 and returns it as one value +\ if planar-id >= 5 it should be GA2 else it is GA1 (JS20 only) +defer planar-id  ( -- planar-id ) + +: (planar-id)  ( -- planar-id) +   \ default implementation of planar-id just returns 8 +   \ the highest possible planar id for JS20 is 7 +   8 +; + +' (planar-id) to planar-id + +#include "header.fs" + +\ I/O accesses. +#include "io.fs" + +\ XXX: Enable first UART on JS20, scripts forget to do this.  Sigh. +3 7 siocfg!  1 30 siocfg! + +#include "serial.fs" + +cr + +#include "base.fs" + +\ Little-endian accesses.  Also known as `wrong-endian'. +#include <little-endian.fs> + +\ do not free-mem if address is not within the heap +\ workaround for NVIDIA card +: free-mem  (  addr len -- ) +   over heap-start heap-end within  IF +      free-mem +   ELSE +      2drop +   THEN +; + +: #join  ( lo hi #bits -- x )  lshift or ; +: #split ( x #bits -- lo hi )  2dup rshift dup >r swap lshift xor r> ; + +: blink ; + +: reset-dual-emit ; + +: console-clean-fifo ; + +: bootmsg-nvupdate ; + +: asm-cout 2drop drop ; + +#include "logging.fs" + +: log-string 2drop ; + +#include "bootmsg.fs" + +000 cp + +\ disable the nvram logging until we know if we are +\ running from ram/takeover/js20 or in normal mode on js21 +: (nvramlog-write-byte)  drop ; +' (nvramlog-write-byte) to nvramlog-write-byte + +#include "exception.fs" + +: mm-log-warning 2drop ; + +: write-mm-log ( data length type -- status ) +	3drop 0 +; + +080 cp + +#include "rtc.fs" + +100 cp + +\ Input line editing. +#include "accept.fs" + +120 cp + +#include "dump.fs" + +cistack ciregs >r1 ! \ kernel wants a stack :-) + +#include "romfs.fs" + +140 cp +#include "flash.fs" + +\ 1 temp; 0 perm; let's default to temp +1 VALUE flashside? + +\ claim the memory used by copy of the flash +flash-header  IF +   romfs-base dup flash-image-size 0 claim drop +THEN + +s" bootinfo" romfs-lookup drop c + l@ CONSTANT start-addr +start-addr flash-addr <> CONSTANT takeover? + +takeover? u3? or 0=  IF +   \ we want nvram logging to work +   ['] .nvramlog-write-byte to nvramlog-write-byte +THEN + +160 cp + +u4? IF f8002100 rl@ 0= ELSE false THEN  ?INCLUDE u4-mem.fs +u3?  IF +   planar-id 5 >=  IF +      40000 to nvram-size +   ELSE +      \ change nvram-size to 8000 for GA1 blades +      8000 to nvram-size +   THEN +THEN + + +takeover?  IF +   \ potentially coming from phype +   u4?  IF +      \ takeover on JS21 is using some nvram area +      \ which might be available +      \ on JS20 the nvram is too small and +      \ we just overwrite the nvram +      sec-nvram-base to nvram-base +   THEN +   sec-nvram-size to nvram-size +   \ in takeover mode the nvram is probably not mapped +   \ to the exact location where the nvram starts +   \ doing a small check to see if we have a partition +   \ starting with 70; this test is far from perfect but +   \ takeover is not the most common mode of running slof +   nvram-base rb@ 70 <>  IF  0 nvram-base rb!  THEN +THEN + +200 cp + +#include <slof-logo.fs> +#include <banner.fs> + +: .banner .slof-logo .banner ; + +\ Get the secondary CPUs into our own spinloop. +f8000050 rl@ CONSTANT master-cpu +\ cr .( The master cpu is #) master-cpu . + +VARIABLE cpu-mask +: get-slave ( n -- online? ) +  0 3ff8 ! 18 lshift 30000000 or 48003f02 over l! icbi 10000 0 DO LOOP 3ff8 @ ; +: mark-online ( n -- )  1 swap lshift cpu-mask @ or cpu-mask ! ; +: get-slaves  40 0 DO i get-slave IF i mark-online THEN LOOP ; +: cpu-report  ( -- ) +   cpu-mask @ 40 0  DO  dup 1 and  IF  ." #" i .  THEN  1 rshift  LOOP  drop +; + +220 cp +master-cpu mark-online get-slaves + +DEFER disable-watchdog ( -- ) +DEFER find-boot-sector ( -- ) + + +240 cp +\ Timebase frequency, in Hz. +\ -1 VALUE tb-frequency +d# 14318378 VALUE tb-frequency   \ default value - needed for "ms" to work +-1 VALUE cpu-frequency + +#include "helper.fs" +260 cp + +#include <timebase.fs> + +270 cp + +#include <fcode/evaluator.fs> + +280 cp + +\ rtas-config is not used +0 CONSTANT rtas-config + +#include "rtas.fs" +290 cp +s" update_flash.fs" included +2a0 cp +cpu-mask @ rtas-fetch-cpus drop + +: of-start-cpu rtas-start-cpu ; + +' power-off to halt +' rtas-system-reboot to reboot + +: other-firmware  rtas-get-flashside 0= IF 1 ELSE 0 THEN rtas-set-flashside reboot ; +: disable-boot-watchdog rtas-stop-bootwatchdog drop ; +' disable-boot-watchdog to disable-watchdog + +true value bmc? +false value debug-boot? + +\ for JS21/Bimini try to detect BMC... if kcs (io @ca8) status is not ff... +u4? IF ca8 4 + io-c@ ff = IF false to bmc? true to debug-boot? THEN THEN + +VARIABLE memnode + +\ Hook to help loading our secondary boot loader. +DEFER disk-read ( lba cnt addr -- ) +0 VALUE disk-off + +create vpd-cb 24 allot +create vpd-bootlist 4 allot +2c0 cp +#include "ipmi-vpd.fs" +2e0 cp +#include <quiesce.fs> +300 cp +#include <usb/usb-static.fs> +320 cp +#include <scsi-loader.fs> +#include <root.fs> +360 cp +#include "tree.fs" + +: .system-information  ( -- ) +   s"                   " type cr +   s" SYSTEM INFORMATION" type cr +   s"  Processor  = " type s" cpu" get-chosen  IF +      drop l@ >r pvr@ s" pvr>name" r> $call-method type +      s"  @ " type cpu-frequency d# 1000000 / +      decimal . hex s" MHz" type +   THEN  cr s"  I/O Bridge = " type u3?  IF +      s" U3"  ELSE  s" U4"  THEN type +   f8000000 rl@ 4 rshift s"  (" type 1 0.r s" ." type +   f8000000 rl@ f and 1 0.r s" )" type cr +   s"  SMP Size   = " type cpu-mask @ cnt-bits 1 0.r +   s"  (" type cpu-report 8 emit s" )" type +   cr s"  Boot-Date  = " type .date cr +   s"  Memory     = " type s" memory" get-chosen  IF +      drop l@ s" mem-report" rot $call-method  THEN +   cr s"  Board Type = " type u3?  IF +      s" JS20(GA" type planar-id 5 >=  IF +         s" 2)" ELSE s" 1)" THEN type +   ELSE bimini?  IF  s" Bimini"  ELSE  s" JS21"  THEN  type  THEN +   s"  (" type .vpd-machine-type [char] / emit +   .vpd-machine-serial [char] / emit +   .vpd-hw-revision 8 emit  s" )" type cr +   s"  MFG Date   = " type .vpd-manufacturer-date cr +   s"  Part No.   = " type .vpd-part-number cr +   s"  FRU No.    = " type .vpd-fru-number cr +   s"  FRU Serial = " type .vpd-cardprefix-serial .vpd-card-serial cr +   s"  UUID       = " type .vpd-uuid cr +   s"  Flashside  = " type rtas-get-flashside 0=  IF +      ." 0 (permanent)" +   ELSE +      ." 1 (temporary)" THEN cr +   s"  Version    = " type  +   takeover?  IF +      romfs-base 38 + a type +   ELSE +      slof-build-id here swap rmove  +      here slof-build-id nip type cr +      s"  Build Date = " type bdate2human type +   THEN +   cr cr +; + +800 cp + +#include "nvram.fs" +takeover? not u4? and  IF +   \ if were are not in takeover mode the nvram should look +   \ something like this: +   \ type  size  name +   \ ======================== +   \  51  20000  ibm,CPU0log +   \  51   5000  ibm,CPU1log +   \  70   1000  common +   \  7f  da000  <free-space> +   \ the partition with the type 51 should have been added +   \ by LLFW... if it does not exist then something went +   \ wrong and we just destroy the whole thing +   51 get-nvram-partition IF  0 0 nvram-c!  ELSE  2drop  THEN +THEN + +880 cp + +\ dmesg/dmesg2 not available if running in takeover/ram mode or on js20 +: dmesg  ( -- )  u3? takeover? or 0=  IF  dmesg  THEN ; +: dmesg2  ( -- )  u3? takeover? or 0=  IF  dmesg2  THEN ; + +#include "envvar.fs" +check-for-nvramrc + +8a0 cp +\ The client interface. +#include "client.fs" +\ ELF binary file format. +#include "elf.fs" +#include <loaders.fs> + +8a8 cp + +\ check wether a VGA device was found during pci scan, if it was +\ try to initialize it and create the needed device-nodes +0 value biosemu-vmem +100000 value biosemu-vmem-size +0 value screen-info + +: init-vga-devices  ( -- ) +   vga-device-node? 0= use-biosemu? 0= OR IF +      EXIT +   THEN +   s" VGA Device found: " type vga-device-node? node>path type s"  initializing..." type cr +   \ claim virtual memory for biosemu of 1MB +   biosemu-vmem-size 4 claim to biosemu-vmem +   \ claim memory for screen-info struct (140 bytes) +   d# 140 4 claim to screen-info +   \ remember current-node (it might be node 0 so we cannot use get-node) +   current-node @ +   \ change into vga device node +   vga-device-node? set-node +   \ run biosemu to initialize the vga card +   \ s" Time before biosemu:" type .date cr +   vga-device-node? node>path ( pathstr len ) +   s" biosemu " biosemu-vmem $cathex ( pathstr len paramstr len ) +   20 char-cat \ add a space ( pathstr len paramstr len ) +   biosemu-vmem-size $cathex \ add VMEM Size ( pathstr len paramstr len ) +   20 char-cat \ add a space ( pathstr len paramstr len ) +   2swap $cat ( paramstr+path len ) +   biosemu-debug 0<> IF +      20 char-cat biosemu-debug $cathex \ add biosemu-debug as param +      ( paramstr+path+biosemu-debug len ) +   THEN +   .(client-exec) IF +      ." biosemu client exec failed!" cr +      set-node                          \ restore old current-node +      EXIT +   THEN +   \ s" Time after biosemu:" type .date cr +   s" VGA initialization: detecting displays..." type cr +   \ try to get info for two monitors +   2 0 DO  +      \ setup screen-info struct as input to get_vbe_info +      s" DDC" 0 char-cat screen-info swap move \ null-terminated "DDC" as signature +      d# 140 screen-info 4 + w! \ reserved size in bytes (see claim above) +      i screen-info 6 + c! \ monitor number +      \ 320 screen-info 7 + w! \ max. screen width (800) +      500 screen-info 7 + w! \ max. screen width (1280) +      \ following line would be the right thing to do, however environment seems not setup yet... +      \ screen-#columns char-width * 500 min 280 max screen-info 7 + w! \ max. screen width, calculated from environment variable screen-#columns, but max. 1280, min. 640... +      8 screen-info 9 + c! \ requested color depth (8bpp) +      \ d# 16 screen-info 9 + c! \ requested color depth (16bpp) +      \ execute get_vbe_info from load-base +      \ s" Time before client exec:" type .date cr +      \ since node>path overwrites strings created with s"  +      \ we need to call it before assembling the parameter string +      vga-device-node? node>path ( pathstr len ) +      s" get_vbe_info " biosemu-vmem $cathex ( pathstr len paramstr len ) +      20 char-cat \ add a space ( pathstr len paramstr len ) +      biosemu-vmem-size $cathex \ add VMEM Size ( pathstr len paramstr len ) +      20 char-cat \ add a space ( pathstr len paramstr len ) +      2swap $cat ( paramstr+path len ) +      20 char-cat +      screen-info $cathex +      .(client-exec) 0= +      \ s" Time after client exec:" type .date cr +      screen-info c@ 0<> AND IF +        s"   display " type i . s" found..." type  +        \ screen found +        \ create device entry +        get-node node>name \ get current nodes name (e.g. "vga") ( str len ) +        i \ put display-num on the stack ( str len displaynum ) +        new-device \ create new device +           s" vga-display.fs" included +        finish-device +        s" created." type cr +      THEN +   LOOP +   \ return to where we were before changing to vga device node +   set-node +   \ release the claimed memory +   screen-info d# 140 release  +   biosemu-vmem biosemu-vmem-size release + +   s" VGA initialization done." type cr +; + +init-vga-devices + +: enable-framebuffer-output  ( -- ) +\ enable output on framebuffer +   s" screen" find-alias ?dup  IF +      \ we need to open/close the screen device once +      \ before "ticking" display-emit to emit +      open-dev close-node +      s" display-emit" $find  IF  +         to emit  +      ELSE +         2drop +      THEN +   THEN +; + +enable-framebuffer-output + +8b0 cp + +\ do not let the usb scan overwrite the atapi cdrom alias +\ pci-cdrom-num TO cdrom-alias-num +usb-scan + +: create-aliases  ( -- ) +   s" net" s" net1" find-alias ?dup  IF  set-alias ELSE 2drop  THEN +   s" disk" s" disk0" find-alias ?dup  IF  set-alias  ELSE  2drop  THEN +   s" cdrom" s" cdrom0" find-alias ?dup  IF  set-alias  ELSE  2drop  THEN +; + +create-aliases + +8ff cp + +.system-information + +: directserial +u3? IF +	s" /ht/isa/serial@3f8" io +ELSE +	s" direct-serial?" evaluate IF s" /ht/isa/serial@2f8" io ELSE s" /ht/isa/serial@3f8" io THEN +THEN +; + +directserial +   +\ on bimini we want to automatically enable screen and keyboard, if they are detected... +bimini? IF +   key? IF +      cr ."    input available on current console input device, not switching input / output." cr +   ELSE +      \ this enables the framebuffer as primary output device +      s" screen" find-alias  IF  drop +         s" screen" output +         \ at this point serial output is theoretically disabled +         ."    screen detected and set as default output device" cr +      THEN +      \ enable USB keyboard +      s" keyboard" find-alias  IF  drop +         s" keyboard" input +         \ at this point serial input is disabled +         ."    keyboard detected and set as default input device" cr cr cr +         s"   Press 's' to enter Open Firmware." type cr +         500 ms +      THEN +   THEN +THEN + +: .flashside +   cr ." The currently active flashside is: " +   rtas-get-flashside 0= IF ." 0 (permanent)" ELSE +   ." 1 (temporary)" THEN +; + +bmc? IF  disable-watchdog  THEN + +: flashsave  ( "{filename}" -- rc ) +  (parse-line) dup 0> IF +    s" netsave "             \ command +    get-flash-base $cathex   \ Flash base addr +    s"  400000 " $cat        \ Flash size (4MB) +    2swap $cat               \ add parameters from (parse-line) +    evaluate +  ELSE +    cr +    ." Usage: flashsave [bootp|dhcp,]filename[,siaddr][,ciaddr][,giaddr][,bootp-retries][,tftp-retries][,use_ci]" +    cr 2drop +  THEN +; + +#include <vpd-bootlist.fs> + +\ for the blades we read the bootlist from the VPD +bimini? takeover? or 0=  IF  ['] vpd-boot-import to read-bootlist  THEN + +\ for the bimini, we try to boot from disk, if it exists,  +\ only if "boot-device" is not set in the nvram +: bimini-bootlist +   \ check nvram +   s" boot-device" evaluate swap drop ( boot-device-strlen ) +   0= IF +      \ no boot-device set in NVRAM, check if disk is available and set it... +      \ clear boot-device list +      0 0 set-boot-device +      s" disk" find-alias ?dup IF +         \ alias found, use it as default +         add-boot-device +      THEN +   THEN +; + +bimini? IF ['] bimini-bootlist to read-bootlist THEN + +#include <start-up.fs> + +#include <boot.fs> + +cr .(   Welcome to Open Firmware) +cr +#include "copyright-oss.fs" +cr + +\ this CATCH is to ensure the code bellow always executes:  boot may ABORT! +' start-it CATCH drop + +#include <history.fs> +nvram-history? [IF] +." loading shell history .. " +history-load +." done" cr +[THEN] + diff --git a/roms/SLOF/board-js2x/slof/attu.fs b/roms/SLOF/board-js2x/slof/attu.fs new file mode 100644 index 00000000..cc122529 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/attu.fs @@ -0,0 +1,101 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ U4 "Attu" PCIe root complex. + +\ See the PCI OF binding document. + +new-device + +s" pciex" device-name s" pci" device-type +s" U4-pcie" compatible +s" U4" encode-string s" model" property + +\ spare out 0xc0000000-0xefffffff for pcie +f8070200 rl@ fffffff0 and f8070200 rl! +\ enable io memory for pcie @ c0000000-efffffff +70000003 f80903f0 rl!-le + +3 encode-int s" #address-cells" property +2 encode-int s" #size-cells" property + +s" /mpic" find-node encode-int s" interrupt-parent" property +\ XXX should have interrupt map, etc.  this works for now though. + +: decode-unit  2 hex-decode-unit  3 #join  8 lshift  0 0 rot F00000 + ; +: encode-unit  nip nip  ff00 and 8 rshift  3 #split +               over IF 2 ELSE nip 1 THEN hex-encode-unit ; + +f1000000 CONSTANT my-puid +\ Configuration space accesses. +: >config  f1000000 + ; +: config-l!  >config rl!-le ; +: config-l@  >config rl@-le ; +: config-w!  >config rw!-le ; +: config-w@  >config rw@-le ; +: config-b!  >config rb! ; +: config-b@  >config rb@ ; + +: config-dump ( addr size -- )  ['] config-l@ 4 (dump) ; + +\ 16MB of configuration space +f1000000 encode-64 1000000 encode-64+ s" reg" property + +\ 4MB of I/O space. +01000000 encode-int  00000000 encode-int+ 00000000 encode-int+  +00000000 encode-int+ f0000000 encode-int+  +00000000 encode-int+ 00400000 encode-int+ + +\ 1.75GB of memory space @ c0000000. +02000000 encode-int+ c0000000 encode-64+ +c0000000 encode-64+  30000000 encode-64+ s" ranges" property + +\ Host bridge, so full bus range. +f0 encode-int ff encode-int+ s" bus-range" property + +: open  true ; +: close ; + +\ : probe-pci-host-bridge ( bus-max bus-min mmio-max mmio-base mem-max mem-base io-max io-base my-puid -- ) +s" /mpic" find-node my-puid pci-irq-init drop + +00fff1f0 18 config-l! + +ff F0 f0000000 e8000000 e8000000 c0000000 100000000 f000 +my-puid probe-pci-host-bridge + +\ \ PCIe debug / fixup +: find-pcie-cap  ( devfn -- offset | 0 ) +   >r 34  BEGIN  r@ + config-b@ dup ff <> over and  WHILE +       dup r@ + config-b@ 10 =  IF +          r> drop EXIT +       THEN 1+ +   REPEAT r> 2drop 0 +; + + : (set-ps) ( ps addr -- ) +   8 + >r 5 lshift r@ config-w@ ff1f and or r> config-w! ; + : set-ps ( ps -- ) +   log2 7 - +   10000 0 DO i 8 lshift dup find-pcie-cap ?dup IF +   + 2dup (set-ps) THEN drop LOOP drop ; +  + : (set-rr) ( rr addr -- ) +   8 + >r c lshift r@ config-w@ 8fff and or r> config-w! ; + : set-rr ( rr -- ) +   log2 7 - +   10000 0 DO i 8 lshift dup find-pcie-cap ?dup IF +   + 2dup (set-rr) THEN drop LOOP drop ; + +80 set-ps  80 set-rr   + +finish-device diff --git a/roms/SLOF/board-js2x/slof/bcm57xx.fs b/roms/SLOF/board-js2x/slof/bcm57xx.fs new file mode 100644 index 00000000..c8e6f5aa --- /dev/null +++ b/roms/SLOF/board-js2x/slof/bcm57xx.fs @@ -0,0 +1,75 @@ +\ ***************************************************************************** +\ * Copyright (c) 2013 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ Handle bcm57xx device + +s" network" device-type + +my-space pci-alias-net + +VARIABLE obp-tftp-package + +0 VALUE bcm57xx-priv +0 VALUE open-count + +: open  ( -- okay? ) +   open-count 0= IF +      open IF +         bcm57xx-open dup not IF ." bcm57xx-open failed" EXIT THEN +         drop dup TO bcm57xx-priv +         6 encode-bytes s" local-mac-address" property +         true +      ELSE +         false +      THEN +   ELSE +      true +   THEN +   my-args s" obp-tftp" $open-package obp-tftp-package ! +   open-count 1 + to open-count +; + + +: close  ( -- ) +    open-count 0> IF +      open-count 1 - dup to open-count +      0= IF +         bcm57xx-priv bcm57xx-close +         close +      THEN +   THEN +   s" close" obp-tftp-package @ $call-method +; + +: read ( buf len -- actual ) +   dup IF +      bcm57xx-read +   ELSE   +      nip +   THEN +; + +: write ( buf len -- actual ) +   dup IF +      bcm57xx-write +   ELSE +      nip +   THEN +; + +: load  ( addr -- len ) +   s" load" obp-tftp-package @ $call-method +; + +: ping  ( -- ) +   s" ping" obp-tftp-package @ $call-method +; diff --git a/roms/SLOF/board-js2x/slof/citrine-disk.fs b/roms/SLOF/board-js2x/slof/citrine-disk.fs new file mode 100644 index 00000000..146e7ece --- /dev/null +++ b/roms/SLOF/board-js2x/slof/citrine-disk.fs @@ -0,0 +1,79 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +( max-#blocks rsrc id -- ) + +new-device    + +lwsplit swap wbsplit rot set-unit + +s" disk" device-name  s" block" device-type + +CONSTANT resource-id +CONSTANT max-#blocks +get-parent CONSTANT ppack + + +: our-disk-read ( lba count addr -- ) +  >r >r >r resource-id r> r> r> s" do-read" ppack $call-static ; + +0 pci-alias-disk + +\ Requiered interface for deblocker + +200   CONSTANT block-size +40000 CONSTANT max-transfer  + +: read-blocks ( addr block# #blocks -- #read ) +\   my-unit s" dev-read-blocks" $call-parent +   \ check if the read is within max-#blocks +   2dup + max-#blocks 1 + > IF  +     \ 2drop drop 0 \ return 0  +     \ returning 0 would be correct (maybe?) but it confuses the deblocker... +     \ so i erase whatever would have been read and return the "expected" #read +     dup >r  +     swap drop \ drop block# (not needed) +     block-size * erase \ erase at addr #blocks * block-size +     r>   \ return #read  +   ELSE +     dup >r rot our-disk-read r> +   THEN +;     + +INSTANCE VARIABLE deblocker + +: open ( -- okay? ) +   0 0 s" deblocker" $open-package dup deblocker ! dup IF  +      s" disk-label" find-package IF +	 my-args rot interpose +      THEN +   THEN 0<> ; + +: close ( -- ) +   deblocker @ close-package ; + +: seek ( pos.lo pos.hi -- status ) +   2dup lxjoin max-#blocks 1 + block-size *  > IF  +     \ illegal seek, return -1 +     2drop -1 +   ELSE +     s" seek" deblocker @ $call-method +   THEN +; + +: read ( addr len -- actual ) +   s" read" deblocker @ $call-method ; + + +finish-device + diff --git a/roms/SLOF/board-js2x/slof/citrine-flash.fs b/roms/SLOF/board-js2x/slof/citrine-flash.fs new file mode 100644 index 00000000..5842b07c --- /dev/null +++ b/roms/SLOF/board-js2x/slof/citrine-flash.fs @@ -0,0 +1,36 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ we do all flash accesses as 8-bit + +9f000000 CONSTANT citrine-flash-addr + +: >citrine-flash  citrine-flash-addr + ; +: citrine-flash@  >citrine-flash rb@ ; +: citrine-flash!  >citrine-flash rb! ; +: wait-for-citrine-flash-ready  BEGIN 0 citrine-flash@ 80 and UNTIL ; +: erase-citrine-flash-block ( offset -- ) +  cr dup 8 .r ."  Erasing..." +  20 over citrine-flash! d0 swap citrine-flash! wait-for-citrine-flash-ready ; +: write-citrine-flash ( data offset -- ) +  over ff = IF 2drop EXIT THEN +  40 over citrine-flash! citrine-flash! wait-for-citrine-flash-ready ; +: write-citrine-flash-block ( addr offset -- ) \ always writes 128kB! +  ."  Writing..." +  20000 0 DO over i + c@ over i + write-citrine-flash LOOP 2drop +  ."  Done." ; +: citrine-flash ( addr offset size -- ) +  BEGIN dup 0 > WHILE >r dup erase-citrine-flash-block +  2dup write-citrine-flash-block >r 20000 + r> 20000 + r> 20000 - REPEAT +  drop 2drop -1 0 citrine-flash! ; + diff --git a/roms/SLOF/board-js2x/slof/citrine.fs b/roms/SLOF/board-js2x/slof/citrine.fs new file mode 100644 index 00000000..ad677769 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/citrine.fs @@ -0,0 +1,245 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ Citrine storage controller. +2dup type + +device-name s" ide" device-type + + +3 encode-int s" #address-cells" property +0 encode-int s" #size-cells" property + +: decode-unit  3 hex-decode-unit ; +: encode-unit  3 hex-encode-unit ; + + +: >ioa  [ 10 config-l@ -10 and ] LITERAL + ; +: ioa@  >ioa rl@-le ; +: ioa!  >ioa rl!-le ; + + +\ Clear request completion doorbell. +2 228 ioa! + +\ status +CREATE ioasa 200 allot  ioasa 200 erase \ can reduce to 8 later + +\ request/response queue +CREATE rrq 100 allot  rrq 100 erase \ can be smaller + +\ data descriptor +CREATE ioadl 8 allot + +\ control block +CREATE ioarcb 80 allot  ioarcb 80 erase +ioarcb dup l! +60708090 ioarcb c + l! \ user handle +ioadl ioarcb 2c + l! \ read ioadl +ioasa ioarcb 34 + l!  200 ioarcb 38 + w! + +\ ioa config data (max. 16 devices) +CREATE ioacfg 404 allot  ioacfg 404 erase +CREATE setsupbuff  2c allot +   setsupbuff 2c erase +   2c setsupbuff w! +   1 setsupbuff 3 + c! + +: wait-ready ( -- ) +	82800000 214 ioa! +	80000000 BEGIN dup 224 ioa@ cr .s dup 8000000 and IF  +		cr ." Unit check on SAS-Controller detected" +		cr 42c ioa@ . +		8 110 ioa! + 		BEGIN cr 0 config-l@ dup . ffffffff <> UNTIL +\		ABORT" Unit check on SAS-Controller detected" +	THEN +	and +	UNTIL drop  +; + +\ wait-ready + +: wait-ioa ( int-mask -- )  BEGIN dup 224 ioa@ and UNTIL drop ; +: init-ioa ( -- )  82800000 214 ioa!  80000000 wait-ioa ; +: do-request ( -- )  ioasa 20 erase  ioarcb 404 ioa! +                     2 wait-ioa 2 228 ioa!  +; + +: setup-ioarcb ( rsrc type addr len -- ) +  tuck  49000000 or ioadl l!  ioadl 4 + l! \ setup ioadl +  ioarcb 20 + l!  ioadl ioarcb 2c + l! 8 ioarcb 30 + l! \ set len, ioadl addr +  ioarcb 3e + c!  ioarcb 8 + l! \ set type and resource +  ioarcb 40 + 40 erase ; + +: setup-wrioarcb ( rsrc type addr len -- ) +  tuck  49000000 or ioadl l!  ioadl 4 + l! \ setup ioadl +  ioarcb 1C + l!  ioadl ioarcb 24 + l! 8 ioarcb 28 + l! \ set len, ioadl addr +  ioarcb 3e + c!  ioarcb 8 + l! \ set type and resource +  ioarcb 40 + 40 erase ; + +: setup-idrrq ( rrq len -- ) +  c4 ioarcb 42 + c!  8 lshift ioarcb 48 + l!  ioarcb 44 + l! ; +: do-idrrq ( -- )  -1 1 0 0 setup-ioarcb  rrq 100 setup-idrrq  do-request ; + +: setup-query ( len -- )  c5 ioarcb 42 + c!  8 lshift ioarcb 48 + l! ; +: do-query ( -- )  -1 1 ioacfg 404 setup-ioarcb  404 setup-query  do-request ; + +: setup-startUnit ( -- )  1b ioarcb 42 + c! 3 ioarcb 46 + c! ; +: do-startUnit ( hndl -- )  0 0 0 setup-ioarcb  setup-startUnit  do-request ; + +: setup-setsupported ( len -- ) 80 ioarcb 40 + c! fb ioarcb 42 + c! 8 lshift ioarcb 48 + l! ; +: do-setsupported (  -- )  -1 1 setsupbuff 2c setup-wrioarcb  2c setup-setsupported  do-request ; + +\ ******************************** +\ read capacity +\ ******************************** +CREATE cap 8 allot + +: setup-cap ( -- ) 25 ioarcb 42 + c!  cap 8 erase ; +: do-cap ( rsrc addr -- ) +  >r 0 r> 8 setup-ioarcb  setup-cap  do-request ; + +: .id  ( id -- )  ." @" lwsplit 2 0.r ." ," wbsplit 2 0.r ." ," 2 0.r ; + +: .cap ( rsrc -- ) +  cap do-cap cap l@ cap 4 + l@ * d# 50000000 + d# 100000000 / +  base @ >r decimal d# 10 /mod 4 .r ." ." 0 .r ." GB" r> base ! ; + +\ ******************************** +\ Test Unit Ready +\ ******************************** +: setup-test-unit-ready ( -- ) +   00 ioarcb 42 + c!   \ SCSI cmd: Test-Unit-Ready +; + +: do-test-unit-ready       ( rsrc -- ) +   0 0 0 setup-ioarcb      ( rsrc type addr len -- ) +   setup-test-unit-ready +   do-request +; + +\ ******************************** +\ Check devices +\ ******************************** +: check-device  ( ioacfg-entry -- ) +   dup 2 + w@ 2001 and 0<>       \ generic or raid disk +   IF                            \ is an IOA resource ? +      dup 8 + l@                 ( ioacfg-entry rsrc )  \ get resource handle +      8 0 +      DO                         ( ioacfg-entry rsrc ) +         dup do-test-unit-ready  ( ioacfg-entry rsrc ) +         ioasa l@ 0=             \ read returned status +         IF +            LEAVE +         THEN +      LOOP +      drop                       ( ioacfg-entry ) +   THEN +   drop  (  ) +; + +: check-devices   ( -- ) +   ioacfg 4 +     ( ioacfg-entry )  \ config block for 16 devices +   ioacfg c@ 0    \ amount of detected devices +   ?DO +      dup +      check-device   ( ioacfg-entry ) +      40 + +   LOOP +   drop +; + +\ ******************************** +\ Show Devices +\ ******************************** +: show-device  ( ioacfg-entry -- ) +   cr ."     " dup 2 + w@ +   dup 8000 and  IF  ." Controller         :"  THEN +   dup 2000 and  IF  ."  Disk (RAID Member):"  THEN +   dup 0002 and  IF  ."  Disk (Volume Set) :"  THEN +   0001 and  IF  ."  Disk (Generic)    :"  THEN +   space dup 4 + l@ ffffff and dup ffffff <>  IF +      .id +   ELSE  drop 9 spaces  THEN  space +   dup 1c + 8 type space dup 24 + 10 type +   dup 2 + w@ 8000 and 0=  IF +      space dup 8 + l@ .cap  +   THEN drop +; + +: show-devices  ( -- ) +   ioacfg 4 + ioacfg c@ 0 +   ?DO dup show-device 40 + LOOP drop +; + +: setup-read  ( lba len -- ) \ len is in blocks +   28 ioarcb 42 + c! +   swap ioarcb 44 + l! +   8 lshift ioarcb 48 + l! +; + +: do-read  ( hndl lba len addr -- )  \ len is in blocks +   over >r rot >r swap 0 -rot 200 * ( 0 hndl addr len* )  +   setup-ioarcb r> r> ( lba len )  +   setup-read do-request  +; + +: make-subnode  ( rsrc-type rsrc-handle id -- ) +   rot 2 and  IF  \ only device which are part of a RAID should be started +      over do-startUnit  \ at least on citrine there are problems starting +                         \ Generic SCSI devices +   THEN  do-setsupported +   dup ffffff <>  IF +      \ we need max-#blocks for citrine-disk.fs +                             ( rsrc id ) +      over cap do-cap cap l@ ( rsrc id max-#blocks ) +      swap rot swap ( max-#block rsrc id ) \ this is what citrine-disk.fs expects... +      s" citrine-disk.fs" included +   ELSE +      2drop +   THEN +; + +: make-subnodes  ( -- ) +   ioacfg 4 + ioacfg c@ 0  ?DO  dup 2 + w@ dup  ( ioacfg rsrc-type rsrc-type ) +   A000  \ 8000 = Resource Subtype is IOA Focal Point. +         \ 2000 = Device is a member of a data redundancy group (eg. RAID). +         \ (1000 = Device is designated for use as a hot spare. +         \         Unfortunately obsidian reports disk which are not part of +         \         of a RAID also as hot space even if they are not.) +         \ all these devices should not appeat in DT +         \ SIS40 page 60 +   and 0=  IF +      swap dup  ( rsrc-type ioacfg ioacfg ) +      8 + l@ over 4 + l@  ( rsrc-type ioacfg rsrc-handle rsrc-addr ) +      ffffff and 2swap swap 2swap  ( ioacfg rsrc-type rsrc-handle rsrc-addr ) +      make-subnode  ELSE  drop  THEN  40 +  LOOP  drop ; + +: do-it  ( -- ) +   init-ioa do-idrrq +   do-query +   check-devices +   show-devices +; + +: setup-shutdown ( -- ) +  f7 ioarcb 42 + c!  0 ioarcb 48 + l!  0 ioarcb 44 + l! ; +: do-shutdown ( -- )  -1 1 0 0 setup-ioarcb  setup-shutdown  do-request ; + +: open  true ; +: close ; + +: start ['] do-it CATCH IF cr ." Citrine disabled" ELSE make-subnodes THEN ; + +cr start cr cr diff --git a/roms/SLOF/board-js2x/slof/copyright-oss.fs b/roms/SLOF/board-js2x/slof/copyright-oss.fs new file mode 100644 index 00000000..06f9a3ad --- /dev/null +++ b/roms/SLOF/board-js2x/slof/copyright-oss.fs @@ -0,0 +1,16 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +cr .(   Copyright (c) char ) emit .(  2004, 2008 IBM Corporation All rights reserved.) +cr .(   This program and the accompanying materials are made available) +cr .(   under the terms of the BSD License available at) +cr .(   http://www.opensource.org/licenses/bsd-license.php) diff --git a/roms/SLOF/board-js2x/slof/cpu.fs b/roms/SLOF/board-js2x/slof/cpu.fs new file mode 100644 index 00000000..bee07d10 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/cpu.fs @@ -0,0 +1,44 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ CPU node.  Pretty minimal... + +( cpu# -- ) +new-device  set-space + +: pvr>name  s" PowerPC," rot 10 rshift CASE +            39 OF s" 970"   ENDOF +            3c OF s" 970FX" ENDOF +            44 OF 1 my-space 1 xor lshift cpu-mask @ and IF +                  s" 970MP" ELSE s" 970GX" THEN ENDOF +                  \ On GX CPUs, the sibling is missing, numbering is the same. +       dup dup OF 0 <# # # # # [char] # hold #> ENDOF ENDCASE $cat ; + +pvr@ pvr>name device-name +s" cpu" device-type + +my-space encode-int s" reg" property + +tb-frequency  encode-int s" timebase-frequency" property +cpu-frequency encode-int s" clock-frequency" property + + 8000 encode-int s" d-cache-size"      property +   80 encode-int s" d-cache-line-size" property +10000 encode-int s" i-cache-size"      property +   80 encode-int s" i-cache-line-size" property + +: open  true ; +: close ; + + +finish-device diff --git a/roms/SLOF/board-js2x/slof/dart.fs b/roms/SLOF/board-js2x/slof/dart.fs new file mode 100644 index 00000000..8fdac83f --- /dev/null +++ b/roms/SLOF/board-js2x/slof/dart.fs @@ -0,0 +1,31 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ CPC9x5 DART. + +new-device + +s" dart" 2dup device-name device-type +u3? IF s" u3-dart" compatible THEN +u4? IF s" u4-dart" compatible THEN + +0 encode-int  f8033000 encode-int+ +0 encode-int+     7000 encode-int+ s" reg" property + +: open  true ; +: close ; + +\ Now clear and disable the DART. +20000000 f8033000 rl! + +finish-device diff --git a/roms/SLOF/board-js2x/slof/flash.fs b/roms/SLOF/board-js2x/slof/flash.fs new file mode 100644 index 00000000..110f5c86 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/flash.fs @@ -0,0 +1,43 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ we do all flash accesses as 8-bit + +ff000000 CONSTANT flash-addr + +: >flash  flash-addr + ; +: flash@  >flash rb@ ; +: flash!  >flash rb! ; +: wait-for-flash-ready  BEGIN 0 flash@ 80 and UNTIL ; +: erase-flash-block ( offset -- ) +  cr dup 8 .r ."  Erasing..." +  20 over flash! d0 swap flash! wait-for-flash-ready ; +: write-flash ( data offset -- ) +  40 over flash! flash! wait-for-flash-ready ; +: write-flash-buffer ( addr offset -- ) +  e8 over flash!  wait-for-flash-ready  1f over flash! +  20 0 DO over i + c@ over i + flash! LOOP +  d0 over flash! wait-for-flash-ready 2drop ; +: write-flash-block ( addr offset -- ) \ always writes 128kB! +  ."  Writing..." +  20000 0 DO over i + over i + write-flash-buffer 20 +LOOP 2drop +  ."  Done." ; +: flash ( addr offset size -- ) +  BEGIN dup 0 > WHILE >r dup erase-flash-block 2dup write-flash-block +  >r 20000 + r> 20000 + r> 20000 - REPEAT drop 2drop -1 0 flash! ; + +: flash-it  get-load-base 0 e0000  flash ; +: flash4    get-load-base 0 400000 flash ; + +\ for update-flash +: flash-image-size  ( addr -- size )  30 + rx@  ; diff --git a/roms/SLOF/board-js2x/slof/freq.fs b/roms/SLOF/board-js2x/slof/freq.fs new file mode 100644 index 00000000..9f1d36d7 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/freq.fs @@ -0,0 +1,39 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ Use the HPET to calculate various frequencies. + +\ Make HPET run. +1 10 hpet! + +\ Set PMC1 to count CPU cycles. +f00 mmcr0! + +d# 1000000000000000 4 hpet@ / CONSTANT hpet-freq + +: get-times  tbl@ pmc1@ f0 hpet@ ; + +\ Calculate the CPU and TB frequencies. +: calibrate  get-times dup >r swap >r swap >r hpet-freq d# 100 / + >r +             BEGIN get-times dup r@ < WHILE 3drop REPEAT r> drop +             rot r> - ffffffff and \ TB +             rot r> - ffffffff and \ CPU +             rot r> - >r           \ HPET +             hpet-freq * r@ / swap +             hpet-freq * r> / ; + +: round-to  tuck 2/ + over / * ; +calibrate TO tb-frequency d# 100000000 round-to TO cpu-frequency + +\ Stop HPET. +0 10 hpet! diff --git a/roms/SLOF/board-js2x/slof/header.fs b/roms/SLOF/board-js2x/slof/header.fs new file mode 100644 index 00000000..be2b7221 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/header.fs @@ -0,0 +1,19 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +get-flash-base VALUE flash-addr + +get-nvram-base CONSTANT nvram-base +get-nvram-size CONSTANT nvram-size +ff8f9000 CONSTANT sec-nvram-base  \ save area from phype.... not really known +2000 CONSTANT sec-nvram-size diff --git a/roms/SLOF/board-js2x/slof/helper.fs b/roms/SLOF/board-js2x/slof/helper.fs new file mode 100644 index 00000000..34d60da1 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/helper.fs @@ -0,0 +1,28 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +: slof-build-id  ( -- str len ) +   flash-header 10 + a +; + +: slof-revision s" 001" ; + +: read-version-and-date +   flash-header 0= IF +   s"  " encode-string +   ELSE +   flash-header 10 + 10 +   here swap rmove +   here 10 +   s" , " $cat +   bdate2human $cat encode-string THEN +; diff --git a/roms/SLOF/board-js2x/slof/ht.fs b/roms/SLOF/board-js2x/slof/ht.fs new file mode 100644 index 00000000..8f818a82 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/ht.fs @@ -0,0 +1,189 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ Hypertransport. + +\ See the PCI OF binding document. + +new-device + +s" ht" 2dup device-name device-type +s" u3-ht" compatible +s" U3" encode-string s" model" property + +3 encode-int s" #address-cells" property +2 encode-int s" #size-cells" property + +s" /mpic" find-node encode-int s" interrupt-parent" property + +4000 encode-int 0 encode-int+ 0 encode-int+ +1 encode-int+ s" /mpic" find-node encode-int+  +10 encode-int+ 0 encode-int+ +s" interrupt-map" property + +f800 encode-int 0 encode-int+ 0 encode-int+ +7 encode-int+ s" interrupt-map-mask" property + +: decode-unit  2 hex-decode-unit 3 lshift or +               8 lshift 0 0 rot ; +: encode-unit  nip nip ff00 and 8 rshift dup 7 and swap 3 rshift +               over IF 2 ELSE nip 1 THEN hex-encode-unit ; + +f2000000 CONSTANT my-puid +\ Configuration space accesses. +: >config  dup ffff > IF 1000000 + THEN f2000000 + ; + +\ : config-l!  >config cr ." config-l! " 2dup . space . rl!-le ; +\ : config-l@  >config cr ." config-l@ " dup . rl@-le space dup . ; +\ : config-w!  >config cr ." config-w! " 2dup . space . rw!-le ; +\ : config-w@  >config cr ." config-w@ " dup . rw@-le space dup . ; +\ : config-b!  >config cr ." config-b! " 2dup . space . rb! ; +\ : config-b@  >config cr ." config-b@ " dup . rb@ space dup . ; + +: config-l!  >config rl!-le ; +: config-l@  >config rl@-le ; +: config-w!  >config rw!-le ; +: config-w@  >config rw@-le ; +: config-b!  >config rb! ; +: config-b@  >config rb@ ; + +: config-dump ( addr size -- )  ['] config-l@ 4 (dump) ; + + +\ 16MB of configuration space, separate for type 0 and type 1. +00000000 encode-int  f2000000 encode-int+ +00000000 encode-int+ 02000000 encode-int+ s" reg" property + +\ 4MB of I/O space. +01000000 encode-int  00000000 encode-int+ 00000000 encode-int+  +00000000 encode-int+ f4000000 encode-int+  +00000000 encode-int+ 00400000 encode-int+ + +\ 1 GB of memory space @ 80000000 +02000000 encode-int+ 00000000 encode-int+ 80000000 encode-int+  +00000000 encode-int+ 80000000 encode-int+  +00000000 encode-int+ 40000000 encode-int+ s" ranges" property + +\ Host bridge, so full bus range. +0 encode-int ff encode-int+ s" bus-range" property + +: enable-ht-apic-space 3c0300fe f8070200 rl! ; +enable-ht-apic-space + +\ spare out 0xc0000000-0xefffffff for pcie +f8070200 rl@ fffffff0 and f8070200 rl! +\ enable io memory for pcie @ c0000000-efffffff +70000003 f80903f0 rl!-le + + +\ Workaround for "takeover" boot on JS20: the top 8131 is programmed to be +\ device #1f, while it should be #01. +u3? IF f800 config-l@ 74501022 = IF 41 f8c2 config-w! THEN THEN + +\ Assign BUIDs. + +: find-ht-primary +  34 BEGIN config-b@ dup 0= ABORT" No HT capability block found!" +  dup config-l@ e00000ff and 8 = IF 2 + EXIT THEN 1 + AGAIN ; + +: assign-buid ( this -- next ) +  find-ht-primary dup >r config-w@ 5 rshift 1f and over r> config-b! + ; + +: assign-buids ( -- ) +  1 BEGIN 0 config-l@ ffffffff <> WHILE assign-buid REPEAT drop ; + +assign-buids  + +: ldtstop  f8000840 rl@ 40000 or f8000840 rl! ; +: delay 100000 0 DO LOOP ; +: wait-for-done  BEGIN f8070110  rl@ 30 and UNTIL +                 BEGIN 8b4 config-l@ 30 and UNTIL ; +: ldtstop1  f8000840 rl@ dup 20000 or f8000840 rl! delay +            f8000840 rl! wait-for-done ; +: warm  400000 f8070300 rl! 0 f8070300 rl! ; + +: dumpht  cr f8070110 rl@ 8 0.r space 8b4 config-l@ 8 0.r +       space f8070122 rb@ 2 0.r space 8bd config-b@ 2 0.r ;  + +: clearht  f8070110 dup rl@ swap rl! +           f8070120 dup rl@ swap rl! +           08b4 dup config-l@ swap config-l! +           08bc dup config-l@ swap config-l! ; + +: setwidth  dup f8070110 rb! 8b7 config-b! ; +: set8   00 setwidth ; +: set16  11 setwidth ; + +: setfreq  dup f8070122 rb! 8bd config-b! ; +: set200   0 setfreq ; +: set300   1 setfreq ; +: set400   2 setfreq ; +: set500   3 setfreq ; +: set600   4 setfreq ; +: set800   5 setfreq ; +: set1000  6 setfreq ; +: set1200  7 setfreq ; +: set1400  8 setfreq ; +: set1600  9 setfreq ; + +: ht>freq  2 + dup 6 > IF 2* 6 - THEN d# 100 * ; +\ XXX: looks only at the U3/U4 side for max. link speed and width. +clearht f8070111 rb@ setwidth +f8070120 rw@ 2log dup .(  Switching top HT bus to ) ht>freq 0 d# .r .( MHz...) cr +setfreq u3? IF ldtstop THEN u4? IF ldtstop1 THEN + +: open  true ; +: close ; + +\ : probe-pci-host-bridge ( bus-max bus-min mmio-max mmio-base mem-max mem-base io-max io-base my-puid -- ) +s" /mpic" find-node my-puid pci-irq-init drop +1f 0 c0000000 b8000000 b8000000 80000000 100000000 10000 +my-puid probe-pci-host-bridge + +: msi +  f80040f0 010854 config-l!   0 010858 config-l! +      ffff 01085c config-w!  81 010852 config-b! +; + +\ This works.  Needs cleaning up though; and we need to communicate the +\ MSI address range to the client program.  (We keep the default range +\ at fee00000 for now). +: msi-on  7 1 DO 10000 i 800 * a0 + config-l! LOOP ; +msi-on + +\ PCIe debug / fixup +: find-pcie-cap  ( devfn -- offset | 0 ) +   >r 34  BEGIN  r@ + config-b@ dup ff <> over and  WHILE +      dup r@ + config-b@ 10 = IF +         r> drop EXIT  +      THEN 1+ +   REPEAT r> 2drop 0 +; + +: (set-ps) ( ps addr -- ) +  8 + >r 5 lshift r@ config-w@ ff1f and or r> config-w! ; +: set-ps ( ps -- ) +  log2 7 - +  10000 0 DO i 8 lshift dup find-pcie-cap ?dup IF +  + 2dup (set-ps) THEN drop LOOP drop ; + +: (set-rr) ( rr addr -- ) +  8 + >r c lshift r@ config-w@ 8fff and or r> config-w! ; +: set-rr ( rr -- ) +  log2 7 - +  10000 0 DO i 8 lshift dup find-pcie-cap ?dup IF +  + 2dup (set-rr) THEN drop LOOP drop ; + +100 set-ps  200 set-rr   +100 set-ps  200 set-rr   + +finish-device diff --git a/roms/SLOF/board-js2x/slof/i2c.fs b/roms/SLOF/board-js2x/slof/i2c.fs new file mode 100644 index 00000000..044bde92 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/i2c.fs @@ -0,0 +1,77 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +new-device + +s" i2c" 2dup device-name device-type +s" u4-i2c" compatible + +0 encode-int  f8001000 encode-int+ +0 encode-int+     1000 encode-int+ s" reg" property + +: >i2c  f8001000 + ; +: i2c@  >i2c rl@ ; +: i2c!  >i2c rl! ; + +: .i2c  80 0 DO i i2c@ . 10 +LOOP ; + +\ 0 mode  1 ctrl  2 stat  3 isr  4 ier  5 addr  6 suba  7 data +\ 8 rev  9 risetime  a bittime + +\ 0 mode: 08 +\ 1 ctrl: 8 = start  4 = stop  2 = xaddr  1 = aak +\ 2 stat: 2 = lastaak  1 = busy +\ 3 isr: 8 = istart  4 = istop  2 = iaddr  1 = idata +\ 4 ier: -- +\ 5 addr: a1..a7 +\ 6 suba: offset +\ 7 data: data + +: i2c-addr ( addr -- )  50 i2c!  2 10 i2c!  BEGIN 30 i2c@ 2 and UNTIL ; +: i2c-subaddr ( suba -- )  60 i2c! ; +: i2c-stop ( -- )  BEGIN 30 i2c@ dup 30 i2c! 4 and UNTIL ; +: i2c-nak? ( -- failed? )  20 i2c@ 2 and 0= dup IF i2c-stop THEN ; +: i2c-short? ( -- failed? )  30 i2c@ 4 and 0<> dup IF 0 10 i2c! i2c-stop THEN ; +: i2c-aak-if-more ( n -- )  1 <> 1 and 10 i2c! ; + +: (read) ( buf len addr -- error? ) +  1 or i2c-addr  i2c-nak? IF 2drop true EXIT THEN +  dup i2c-aak-if-more  2 30 i2c! +  BEGIN +  30 i2c@ 1 and IF +    1- >r 70 i2c@ over c! char+ r> +    dup 0= IF i2c-stop 2drop false EXIT THEN +    dup i2c-aak-if-more 1 30 i2c! THEN +  i2c-short? IF 2drop true EXIT THEN +  AGAIN ; + +: i2c-read ( buf len addr -- error? ) +  4 0 i2c!  (read) ; +: i2c-sub-read ( buf len addr suba -- error? ) +  c 0 i2c!  i2c-subaddr  (read) ; + +: i2c-write ( buf len addr -- error? ) +  4 0 i2c!  i2c-addr  i2c-nak? IF 2drop true EXIT THEN +  over c@ 70 i2c!  2 30 i2c! +  BEGIN +  30 i2c@ 1 and IF +    1- >r char+ r> i2c-nak? IF 2drop true EXIT THEN +    dup 0= IF 4 10 i2c! i2c-stop nip EXIT THEN +    over c@ 70 i2c!  1 30 i2c! THEN +  i2c-short? IF 2drop true EXIT THEN +  AGAIN ; + +: open  true ; +: close ; + +finish-device diff --git a/roms/SLOF/board-js2x/slof/io.fs b/roms/SLOF/board-js2x/slof/io.fs new file mode 100644 index 00000000..f3889840 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/io.fs @@ -0,0 +1,26 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ I/O accesses. + +\ Legacy I/O accesses. +: >io  f4000000 + ; + +: io-c!  >io rb! ; +: io-c@  >io rb@ ; + +: io-w!  >io rw! ; +: io-w@  >io rw@ ; + +\ Accessing the SIO config registers. +: siocfg!  2e io-c! 2f io-c! ; +: siocfg@  2e io-c! 2f io-c@ ; diff --git a/roms/SLOF/board-js2x/slof/ioapic.fs b/roms/SLOF/board-js2x/slof/ioapic.fs new file mode 100644 index 00000000..685d6dfe --- /dev/null +++ b/roms/SLOF/board-js2x/slof/ioapic.fs @@ -0,0 +1,36 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ ( ioapic-addr -- ) +\ IO-APIC setup. + +CONSTANT ioapic + +: ioapic@  ( offset -- x )  ioapic rb! ioapic 10 + rl@-le ; +: ioapic!  ( x offset -- )  ioapic rb! ioapic 10 + rl!-le ; + +: init-ioapic  ( irq# -- ) +   1a000 or 1 ioapic@ 10 rshift 1+ 0  ?DO +      0 i 2* 11 + ioapic! dup +      \ move all ISA IRQs to 40 and higher, +      \ as to not conflict with U3/U4 internal +      \ IRQs. ISA IRQs are positive edge. +      dup ff and 0c <  IF  a000 - 40 +  THEN +      i 2* 10 + ioapic! 1+  LOOP  drop +; + +: dump-ioapic  ( -- ) +   1 ioapic@ 10 rshift 1+ +   dup cr . ." irqs" 0  ?DO +      cr i 2 0.r space i 2* 11 + ioapic@ 8 0.r +      i 2* 10 + ioapic@ 8 0.r  LOOP +; diff --git a/roms/SLOF/board-js2x/slof/ipmi-kcs.fs b/roms/SLOF/board-js2x/slof/ipmi-kcs.fs new file mode 100644 index 00000000..cf9d5af5 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/ipmi-kcs.fs @@ -0,0 +1,57 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ IPMI KCS interface to the BMC. + +new-device +   ca8 1 set-unit + +   : open true ; +   : close ; + +   create descr-buf 100 allot + +   : rtas-get-bmc-version ( -- adr len ) +      descr-buf 100 rtas-get-blade-descr   ( len status ) +      IF +         drop 0 0 +      ELSE +         descr-buf 9 + swap 11 -               ( adr len ) +      THEN +   ; + +   ' rtas-get-bmc-version to bmc-version + +   s" system-controller" 2dup device-name device-type +   \ s" IBM,BMC." get-build-name $cat encode-string s" model" property +   \ s" IBM,BMC.12345" encode-string s" model" property +   s" IBM,BMC." bmc-version $cat encode-string s" model" property +   0 0 s" ranges" property + +   new-device + +      : open true ; +      : close ; + +      s" ipmi" 2dup device-name device-type +      s" ipmi-kcs" compatible + +      1 encode-int ca8 encode-int+ 1 encode-int+ s" reg" property +      4 encode-int s" reg-spacing" property +      s" IBM,BMC." bmc-version $cat encode-string s" model" property + +      s" ipmi"  get-node node>path set-alias + +   finish-device + +finish-device diff --git a/roms/SLOF/board-js2x/slof/ipmi-vpd.fs b/roms/SLOF/board-js2x/slof/ipmi-vpd.fs new file mode 100644 index 00000000..bfb3e501 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/ipmi-vpd.fs @@ -0,0 +1,98 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +: vpd-read-bootlist  ( -- ) +   837 4 vpd-bootlist rtas-read-vpd IF vpd-bootlist 4 erase THEN +; + +: vpd-write-bootlist  ( offset len data -- ) +   837 4 vpd-bootlist rtas-write-vpd +; + +: .vpd-machine-type +	e 7 vpd-cb rtas-read-vpd drop +	0 vpd-cb 7 + c! +	vpd-cb zcount type +; + +: .vpd-machine-serial +	15 7 vpd-cb rtas-read-vpd drop +	0 vpd-cb 7 + c! +	vpd-cb zcount type +; + +: .vpd-card-serial +	54 6 vpd-cb rtas-read-vpd drop +	0 vpd-cb 6 + c! +	vpd-cb zcount type +; +: .vpd-cardprefix-serial +	5a 6 vpd-cb rtas-read-vpd drop +	0 vpd-cb 6 + c! +	vpd-cb zcount type +; + +: .vpd-hw-revision +	65 1 vpd-cb rtas-read-vpd drop +	vpd-cb c@ . +; + +: .vpd-part-number +	3c c vpd-cb rtas-read-vpd drop +	vpd-cb c type +; + +: .vpd-fru-number +	48 c vpd-cb rtas-read-vpd drop +	vpd-cb c type +; + +: .vpd-manufacturer-date +	6b 4 vpd-cb rtas-read-vpd drop +	0 vpd-cb 4 + c! +	vpd-cb zcount type +; + +: .vpd-uuid +	9f 10 vpd-cb rtas-read-vpd drop +	10 0 do i vpd-cb + c@ 2 0.r loop +; + +: vpd-read-model  ( -- addr len ) +   60 4 vpd-cb rtas-read-vpd drop vpd-cb 4 -leading s" ," $cat  +   e 7 vpd-cb rtas-read-vpd drop vpd-cb 4 $cat s" -" $cat vpd-cb 4 + 3 $cat +; + +: .vpd +	." ===================== VPD ====================="  +	cr ." Machine Type        : " .vpd-machine-type +	cr ." Machine Serial No.  : " .vpd-machine-serial +	cr ." Hardware Revision   : " .vpd-hw-revision	 +	cr ." Manuf. Date         : " .vpd-manufacturer-date +	cr ." Part Number         : " .vpd-part-number +	cr ." FRU Number          : " .vpd-fru-number +	cr ." FRU Serial No.      : " .vpd-cardprefix-serial .vpd-card-serial +	cr ." UUID                : " .vpd-uuid +; + +: vpd-write-revision-and-build-id  ( -- ) +   406 24 vpd-cb rtas-read-vpd drop 0 +   vpd-cb 1a + zcount bdate2human drop a string=ci 0= +   IF  bdate2human drop a vpd-cb 1a + zplace drop 1  THEN +   vpd-cb zcount slof-revision string=ci 0= +   IF  slof-revision vpd-cb zplace drop 1  THEN +   vpd-cb 4 + zcount slof-build-id string=ci 0= +   IF  slof-build-id vpd-cb 4 + rzplace drop 1  THEN +   1 =  IF  406 24 vpd-cb rtas-write-vpd drop  THEN +; + +vpd-write-revision-and-build-id diff --git a/roms/SLOF/board-js2x/slof/memory.fs b/roms/SLOF/board-js2x/slof/memory.fs new file mode 100644 index 00000000..b1b7aaa9 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/memory.fs @@ -0,0 +1,52 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ The /memory node. + +\ See 3.7.6. +new-device + +s" memory" 2dup device-name device-type + +: mem-size-u3  20000000 ; +: (mem-size-u4) ( # -- size ) +  4 lshift f8002200 + rl@ dup 1 and 0= IF drop 0 EXIT THEN +  dup c000 and e rshift over 3000 and c rshift + 10000000 swap lshift +  swap 2 and 0= IF 2* THEN ; +: mem-size-u4  0 4 0 DO i (mem-size-u4) + LOOP ; +: mem-size   u3? IF mem-size-u3 THEN  u4? IF mem-size-u4 THEN ; +: mem-speed-u4  f8000800 rl@ 12 rshift 7 and 4 + d# 200 * 3 / ; +: mem-speed-u3  f8000f60 rl@ c rshift f and d# 100 * 3 / ; +: mem-speed  u3? IF mem-speed-u3 THEN  u4? IF mem-speed-u4 THEN ; + + +: encode-our-reg +  0 encode-int 0 encode-int+ +  mem-size dup >r 80000000 > IF +  0 encode-int+ 80000000 encode-int+ +  1 encode-int+ 0 encode-int+ r> 80000000 - >r THEN +  r@ 20 rshift encode-int+ r> ffffffff and encode-int+ ; +encode-our-reg s" reg" property +0  mem-size release	\ Make our memory available + + +: mem-report +  base @ decimal mem-size 1e rshift 0 .r +  mem-size 3fffffff and IF ." .5" THEN ."  GB of RAM @ " +  mem-speed . ." MHz" base ! ; + +get-node memnode ! + +: open  true ; +: close ; + +finish-device diff --git a/roms/SLOF/board-js2x/slof/mpic.fs b/roms/SLOF/board-js2x/slof/mpic.fs new file mode 100644 index 00000000..a9523445 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/mpic.fs @@ -0,0 +1,31 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +new-device + +s" mpic" device-name s" interrupt-controller" device-type +s" open-pic" compatible +0 0 s" interrupt-controller" property + +2 encode-int s" #interrupt-cells" property + +0 encode-int  f8040000 encode-int+ +0 encode-int+    30000 encode-int+ s" reg" property + +: enable-mpic  6 f80000e0 rl! ; +enable-mpic + +: open  true ; +: close ; + +finish-device diff --git a/roms/SLOF/board-js2x/slof/pci-aliases.fs b/roms/SLOF/board-js2x/slof/pci-aliases.fs new file mode 100644 index 00000000..f017e4a5 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-aliases.fs @@ -0,0 +1,85 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ Starting alias number for net devices after the onboard devices. +2 VALUE pci-net-num +\ Starting alias number for disks after the onboard devices. +0 VALUE pci-disk-num +\ Starting alias number for cdroms after the onboard devices. +0 VALUE pci-cdrom-num + +\ define a new alias for this device +: pci-set-alias ( str-addr str-len num -- ) +        $cathex strdup       \ create alias name +        get-node node>path   \ get path string +        set-alias            \ and set the alias +; + +\ define a new net alias +: unknown-enet ( -- pci-net-num ) +	pci-net-num dup 1+ TO pci-net-num +; +: pci-alias-net ( config-addr -- ) +	u3? IF +		pci-device-vec c@ CASE  +		2 OF pci-device-vec-len 1 >= IF   +					pci-device-vec 1+ c@ CASE  +						1 OF dup pci-addr2fn 1 >= IF 1 ELSE 0 THEN  ENDOF  +						dup OF  unknown-enet ENDOF +					ENDCASE +				ELSE +					unknown-enet +				THEN +			ENDOF +			dup OF unknown-enet  ENDOF	 +		ENDCASE +	ELSE +		pci-device-vec c@ CASE  +		2 OF pci-device-vec-len 1 >= IF   +					pci-device-vec 1+ c@ CASE  +						4 OF dup pci-addr2fn 1 >= IF 1 ELSE 0 THEN  ENDOF  +						dup OF  unknown-enet ENDOF +					ENDCASE +				ELSE +					unknown-enet +				THEN +			ENDOF +			dup OF unknown-enet  ENDOF	 +		ENDCASE +	THEN +	swap drop                               \ forget the config address + +        s" net" rot pci-set-alias              \ create the alias +; + +\ define a new disk alias +: pci-alias-disk ( config-addr -- ) +        drop                                    \ forget the config address +        pci-disk-num dup 1+ TO pci-disk-num     \ increase the pci-disk-num +        s" disk" rot pci-set-alias              \ create the alias +; +\ define a new cdrom alias +: pci-alias-cdrom ( config-addr -- ) +        drop                                    \ forget the config address +        pci-cdrom-num dup 1+ TO pci-cdrom-num     \ increase the pci-cdrom-num +        s" cdrom" rot pci-set-alias              \ create the alias +; + +\ define the alias for the calling device +: pci-alias ( config-addr -- ) +        dup pci-class@  +        10 rshift CASE +                01 OF   pci-alias-disk ENDOF +                02 OF   pci-alias-net  ENDOF +               dup OF   drop           ENDOF +        ENDCASE +; diff --git a/roms/SLOF/board-js2x/slof/pci-bridge_1022_7460.fs b/roms/SLOF/board-js2x/slof/pci-bridge_1022_7460.fs new file mode 100644 index 00000000..87b58308 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-bridge_1022_7460.fs @@ -0,0 +1,203 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ AMD 8111 I/O hub. + +\ See the documentation at http://www.amd.com ; the datasheet for this chip is +\ document #24674. + +\ Config space access functions - we're touching multiple device numbers and +\ device functions below, so we've got to add our own my-space base here: +: config-b@  dup 1000 < IF my-space + THEN config-b@ ; +: config-w@  dup 1000 < IF my-space + THEN config-w@ ; +: config-l@  dup 1000 < IF my-space + THEN config-l@ ; +: config-b!  dup 1000 < IF my-space + THEN config-b! ; +: config-w!  dup 1000 < IF my-space + THEN config-w! ; +: config-l!  dup 1000 < IF my-space + THEN config-l! ; + +\ First, some master config.  Not all of this logically belongs to just +\ one function, and certainly not to the LPC bridge; also, we'll +\ initialize all functions in "downstream" order, and this code has to be +\ run first.  So do it now. + +00 842 config-b! \ Disable 8237 & 8254 & 8259's.  We're not a PC. +u3?  IF +   80 847 config-b! \ Disable EHCI, as it is terminally broken. +THEN +03 848 config-b! \ Enable LPC, IDE; disable I2C, SMM, AC'97 functions. +01 849 config-b! \ Enable USB, disable 100Mb enet. +01 84b config-b! \ Enable IO-APIC. + +fec00000 s" ioapic.fs" included +00 init-ioapic + +\ Program PNPIRQ[0,1,2] as IRQ #D,E,F; switch those GPIOs to low-active. +  0b 848 config-b! \ enable devB:3 +7000 b58 config-l! \ map PMxx at pci i/o 7000 +  d1 b41 config-b! \ enable access to PMxx space + +\ on JS20 the planar id is encoded in GPIO 29, 30 and 31 +\ >=5 is GA2 else it is GA1 +: (planar-id) ( -- planar-id) +   [ 70dd io-c@ 5 rshift 1 and ]  LITERAL +   [ 70de io-c@ 5 rshift 2 and ]  LITERAL +   [ 70df io-c@ 5 rshift 4 and ]  LITERAL +   + + 7 xor +; + +u3?  IF  [']  (planar-id) to planar-id  THEN + +8 70d3 io-c!  8 70d4 io-c!  8 70d5 io-c! \ set the pins to low-active + bimini? IF 5 70c4 io-c! THEN \ on bimini set gpio4 as output and high to power up USB + fec b44 config-w! \ set PNPIRQ pnpirq2 -> f , pnpirq1 -> e pnpirq0 -> c +  51 b41 config-b! \ disable access to PMxx space +  03 848 config-b! \ disable devB:3 + +\ The function of the PCI controller BARs change depending on the mode the +\ controller is in. +\ And the default is legacy mode.  Gross. +05 909 config-b! \ Enable native PCI mode. +03 940 config-b! \ Enable both ports. + +\ Enable HPET on 8111, at address fe000000. +fe000001 8a0 config-l! + +: >hpet  fe000000 + ; +: hpet@  >hpet rl@-le ; +: hpet!  >hpet rl!-le ; + +INCLUDE freq.fs + +\ Disable HPET. +0 8a0 config-l! + +\ 8111 has only 16 bits of PCI I/O space.  Get the address in range. +8000 next-pci-io ! + +\ before disabling EHCI it needs to be reset + +\ first we are setting up the BAR0, so that we can talk to the +\ memory mapped controller; not using the PCI scan because we just +\ want a temporary setup + +: really-disable-broken-amd8111-ehci  ( -- ) +   \ this word only works on U4 systems (JS21/Bimini) +   \ yeah, hardcoded! +   f2000000 to puid +    +   \ the PCI scan would assign pci-next-mmio to that device +   \ let's just take that address +   pci-next-mmio @ 100000 #aligned  +   \ pci-bus-number 10 lshift 210 or could be something like 70210 +   \ 7: pci-bus-number +   \ 2: device function +   \ 10: offset 10 (bar 0) +   pci-bus-number 10 lshift 210 or rtas-config-l! + +   \ enable memory space +   pci-bus-number 10 lshift 204 or dup rtas-config-l@ 2 or swap rtas-config-l! + +   pci-next-mmio @ 100000 #aligned ( base ) + +   \ Sequence prescribed for resetting the EHCI contoller + +   \ If Run/Stop bit (ECAP30 bit 0) is 1 +   \   Set Run/Stop bit to 0 +   \   wait 2ms + +   dup 30 + rl@ 1 and 1 =  IF +      dup 30 + rl@ 1 or +      over 30 + rl! +      2 ms +   THEN + +   \ While HCHalted bit (ECAP34 bit 12) is 0  (still running, wait forever) +   \   wait 2ms + +   BEGIN  dup 34 + rl@ 1000 and 0= 2 ms UNTIL + +   \ Set HCReset bit (ECAP30 bit 1) + +   dup 30 + 2 swap rl! + +   \ While HCReset bit is 1 (wait forever for reset to complete) +   \   wait 2ms + +   BEGIN  dup 30 + rl@ 2 and 0= 2 ms UNTIL  drop + +   \ now it is really disabled + +   \ disable memory space access again +   2100000 pci-bus-number 10 lshift 204 or rtas-config-l! + +   80 847 config-b! \ Disable EHCI, as it is terminally broken. +; + +my-space pci-class-name type cr + +\ copied from pci-properties.fs and pci-scan.fs +\ changed to disable the EHCI completely just before the scan +\ and after mem/IO transactions have been enabled + +\ Setup the Base and Limits in the Bridge +\ and scan the bus(es) beyond that Bridge +: pci-bridge-probe-amd8111 ( addr -- ) +   dup pci-bridge-set-bases                        \ SetUp all Base Registers +   dup pci-bridge-range-props                      \ Setup temporary "range +   pci-bus-number 1+ TO pci-bus-number             \ increase number of busses found +   pci-device-vec-len 1+ TO pci-device-vec-len     \ increase the device-slot vector depth +   dup                                             \ stack config-addr for pci-bus! +   FF swap                                         \ Subordinate Bus Number ( for now to max to open all subbusses ) +   pci-bus-number swap                             \ Secondary   Bus Number ( the new busnumber ) +   dup pci-addr2bus swap                           \ Primary     Bus Number ( the current bus ) +   pci-bus!                                        \ and set them into the bridge +   pci-enable                                      \ enable mem/IO transactions + +   \ at this point we can talk to the broken EHCI controller +   really-disable-broken-amd8111-ehci + +   dup pci-bus-scnd@ func-pci-probe-bus            \ and probe the secondary bus +   dup pci-bus-number swap pci-bus-subo!           \ set SubOrdinate Bus Number to current number of busses +   pci-device-vec-len 1- TO pci-device-vec-len     \ decrease the device-slot vector depth +   dup pci-bridge-set-limits                       \ SetUp all Limit Registers +   drop                                            \ forget the config-addr +; + +\ used to set up all unknown Bridges. +\ If a Bridge has no special handling for setup +\ the device file (pci-bridge_VENDOR_DEVICE.fs) can call +\ this word to setup busses and scan beyond. +: pci-bridge-generic-setup-amd8111 ( addr -- ) +   pci-device-slots >r             \ save the slot array on return stack +   dup pci-common-props            \ set the common properties before scanning the bus +   s" pci" device-type             \ the type is allways "pci" +   dup pci-bridge-probe-amd8111    \ find all device connected to it +   dup assign-all-bridge-bars      \ set up all memory access BARs +   dup pci-set-irq-line            \ set the interrupt pin +   dup pci-set-capabilities        \ set up the capabilities +   pci-bridge-props                \ and generate all properties +   r> TO pci-device-slots          \ and reset the slot array +; + +: amd8111-bridge-setup +    my-space +    u3? takeover? or  IF +       \ if it is js20 or we are coming from takeover +       \ we just do the normal setup +       pci-bridge-generic-setup +    ELSE +       pci-bridge-generic-setup-amd8111 +    THEN +    s" pci" device-name +; + +amd8111-bridge-setup diff --git a/roms/SLOF/board-js2x/slof/pci-capabilities.fs b/roms/SLOF/board-js2x/slof/pci-capabilities.fs new file mode 100644 index 00000000..a50714a6 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-capabilities.fs @@ -0,0 +1,23 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ ----------------------------------------------------------------------------- +\ Set the msi address for a device +: pci-set-msi ( cap-addr -- ) +        drop +; + +\ Set up all known capabilities for this board to the plugged devices +: pci-set-capabilities ( config-addr -- ) +        dup 05 pci-cap-find ?dup IF pci-set-msi THEN +        drop +; diff --git a/roms/SLOF/board-js2x/slof/pci-class_03.fs b/roms/SLOF/board-js2x/slof/pci-class_03.fs new file mode 100644 index 00000000..05c8eb62 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-class_03.fs @@ -0,0 +1,55 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +my-space pci-class-name type + +my-space pci-device-generic-setup + +my-space pci-class-name device-type + +\ add legacy I/O Ports / Memory regions to assigned-addresses +\ see PCI Bus Binding Revision 2.1 Section 7. +s" reg" get-my-property +IF +   \ "reg" does not exist, create new +   encode-start +ELSE +   \ "reg" does exist, copy it  +   encode-bytes +THEN +\ I/O Range 0x3B0-0x3BB +my-space a1000000 or encode-int+ \ non-relocatable, aliased I/O space +3b0 encode-64+ \ addr +c encode-64+ \ size +\ I/O Range 0x3C0-0x3DF +my-space a1000000 or encode-int+ \ non-relocatable, aliased I/O space +3c0 encode-64+ \ addr +20 encode-64+ \ size +\ the U4 does not support memory accesses to this region... so we dont put it into "reg" +\ maybe with some clever hacking of the address map registers it will be possible to access +\ these regions?? +\ Memory Range 0xA0000-0xBFFFF +\ my-space a2000000 or encode-int+ \ non-relocatable, <1MB Memory space +\ a0000 encode-64+ \ addr +\ 20000 encode-64+ \ size + +s" reg" property \ store "reg" property + +\ check wether we have already found a vga-device (vga-device-node? != 0) and if +\ this device has Expansion ROM +vga-device-node? 0= 30 config-l@ 0<> AND IF +   \ remember this vga device's phandle +   get-node to vga-device-node? +THEN + +cr + diff --git a/roms/SLOF/board-js2x/slof/pci-device_1002_515e.fs b/roms/SLOF/board-js2x/slof/pci-device_1002_515e.fs new file mode 100644 index 00000000..39a02ded --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-device_1002_515e.fs @@ -0,0 +1,501 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +my-space pci-class-name type + +my-space assign-all-device-bars +my-space pci-device-props +my-space pci-set-irq-line + +7 4 config-w! + +\ Special notice from ATI: +\ ATI TECHNOLOGIES INC. ("ATI") HAS NOT ASSISTED IN THE CREATION OF, +\ AND DOES NOT ENDORSE THE USE OF, THIS SOFTWARE.  ATI WILL NOT BE +\ RESPONSIBLE OR LIABLE FOR ANY ACTUAL OR ALLEGED DAMAGE OR LOSS +\ CAUSED BY OR IN CONNECTION WITH THE USE OF, OR RELIANCE ON, +\ THIS SOFTWARE. + +\  Description: This FCODE driver initializes the RN50 (ES1000) ATI +\               adaptor. + +-1 value mem-addr +-1 value regs-addr +false value is_installed + +: reg-rl@ regs-addr + rl@-le ; +: reg-rl! regs-addr + rl!-le ; +: map-in   " map-in"   $call-parent ; +: map-out  " map-out"  $call-parent ; +: pc@ ( offset -- byte ) regs-addr + rb@ ; +: pc! ( byte offset -- ) regs-addr + rb! ; + +0 value phys_low +0 value phys_mid +0 value phys_high +0 value phys_len + +: MAP-CSR-BASE ( -- ) +  " assigned-addresses" get-my-property 0= if +    begin dup 0> while  ( prop-addr len ) +     \ Get the phys-hi mid low and the low order 32 bits of the length + +      decode-phys to phys_high to phys_mid to phys_low decode-int drop decode-int to phys_len + +      phys_high H# FF and  \ See which BAR this refers to +      case +        h# 10 of phys_low phys_mid phys_high h# 1000000  map-in to mem-addr  endof +        h# 18 of phys_low phys_mid phys_high    phys_len map-in to regs-addr endof +      endcase +    repeat +    ( prop-addr 0 ) 2drop +  then + +  ; + +: enable-card my-space 4 + dup config-b@ 3 or swap config-b! ; + +: EARLY-MAP ( -- ) + +  " reg" get-my-property 0= if +    begin dup 0> while  ( prop-addr len ) + +   \ Get the phys-hi mid low and the low order 32 bits of the length + +      decode-phys to phys_high to phys_mid to phys_low decode-int drop decode-int to phys_len + +      phys_high H# FF and  \ See which BAR this refers to +      case +        h# 10 of phys_low phys_mid phys_high H# 1000000  map-in to mem-addr  endof +        h# 18 of phys_low phys_mid phys_high h#    1000  map-in to regs-addr endof +      endcase +    repeat +    ( prop-addr 0 ) 2drop +  then +  ; + +: EARLY-UNMAP ( -- ) + +  mem-addr -1 <> if +    mem-addr h# 1000000 map-out +    -1 to mem-addr +  then + +  regs-addr -1 <> if +    regs-addr h# 1000   map-out +    -1 to regs-addr +  then + +  ; + +CREATE INIT1_ARRAY +H# 0F8  ( CONFIG_MEMSIZE )  L,    H# 00000000 L, H# 01000000 L, +H# 1C0  ( MPP_TB_CONFIG )   L,    H# 00FFFFFF L, H# 07000000 L, +H# 030  ( BUS_CNTL      )   L,    H# 00000000 L, H# 5133A3B0 L, +H# 0EC  ( RBBM_CNTL     )   L,    H# 00000000 L, h# 00004443 L, +H# 1D0  ( DEBUG_CNTL    )   L,    H# FFFFFFFD L, H# 00000002 L, +H# 050  ( CRTC_GEN_CNTL )   L,    H# 00000000 L, H# 04000000 L, +H# 058  ( DAC_CNTL      )   L,    H# 00000000 L, H# FF604102 L, +H# 168  ( PAD_CTLR_STRENGTH ) L,  H# FFFEFFFF L, H# 00001200 L, +H# 178  ( MEM_REFRESH_CNTL  ) L,  H# 00000000 L, H# 88888888 L, +H# 17C  ( MEM_READ_CNTL )   L,    H# 00000000 L, H# B7C20000 L, +H# 188  ( MC_DEBUG      )   L,    H# FFFFFFFF L, H# 00000000 L, +H# D00  ( DISP_MISC_CNTL)   L,    H# 00FFFFFF L, H# 5B000000 L, +H# 88C  ( TV_DAC_CNTL   )   L,    H# F800FCEF L, H# 00490200 L, +H# D04  ( DAC_MACRO_CNTL)   L,    H# 00000000 L, H# 00000905 L, +H# 284  ( FP_GEN_CNTL   )   L,    H# FFFFFFFF L, H# 00000008 L, +H# 030  ( BUS_CNTL      )   L,    H# FFFFFFEF L, H# 00000000 L, + +here  INIT1_ARRAY  - /L / CONSTANT INIT1_LENGTH + + +CREATE INIT2_ARRAY + +H# 140  ( MEM_CNTL )           L, H#  00000000 L, H# 38001A01 L, 0 L, +H# 158  ( MEM_SDRAM_MODE_REG ) L, H#  E0000000 L, H# 08320032 L, 0 L, +H# 144  ( MEM_TIMING_CNTL    ) L, H#  00000000 L, H# 20123833 L, 0 L, +H# 14C  ( MC_AGP_LOCATION    ) L, H#  00000000 L, H# 000FFFF0 L, 0 L, +H# 148  ( MC_FB_LOCATION     ) L, H#  00000000 L, H# FFFF0000 L, 0 L, +H# 154  ( MEM_INIT_LAT_TIMER ) L, H#  00000000 L, H# 34444444 L, 0 L, +H# 18C  ( MC_CHP_IO_OE_CNTL  ) L, H#  00000000 L, H# 0A540002 L, 0 L, +H# 910  ( FCP_CNTL           ) L, H#  00000000 L, H# 00000004 L, 0 L, +H# 010  ( BIOS_0_SCRATCH     ) L, H#  FFFFFFFB L, H# 00000004 L, 0 L, +H# D64  ( DISP_OUTPUT_CNTL   ) L, H#  FFFFFBFF L, H# 00000000 L, 0 L, +H# 2A8  ( TMDS_PLL_CNTL      ) L, H#  00000000 L, H# 00000A1B L, 0 L, +H# 800  ( TV_MASTER_CNTL     ) L, H#  BFFFFFFF L, H# 40000000 L, 0 L, +H# D10  ( DISP_TEST_DBUG_CTL ) L, H#  EFFFFFFF L, H# 10000000 L, 0 L, +H# 4DC  ( OV0_FLAG_CNTRL     ) L, H#  FFFFFEFF L, H# 00000100 L, 0 L, +H# 034  ( BUS_CNTL1          ) L, H#  73FFFFFF L, H# 84000000 L, 0 L, +H# 174  ( AGP_CNTL           ) L, H#  FFEFFF00 L, H# 001E0000 L, 0 L, +H# 18C  ( MC_CHP_IO_OE_CNTL  ) L, H#  FFFFFFF9 L, H# 00000006 L, h# 000A L, +H# 18C  ( MC_CHP_IO_OE_CNTL  ) L, H#  FFFFFFFB L, H# 00000000 L, H# 000A L, +H# 18C  ( MC_CHP_IO_OE_CNTL  ) L, H#  FFFFFFFD L, H# 00000000 L, 0 L, + +here  INIT2_ARRAY  - /L / CONSTANT INIT2_LENGTH + +CREATE PLLINIT_ARRAY + +H# 0D   L, H# FFFFFFFF L, H# FFFF8000 L, 0 L, +H# 12   L, H# FFFFFFFF L, H# 00350000 L, 0 L, +H# 08   L, H# FFFFFFFF L, H# 00000000 L, 0 L, +H# 2D   L, H# FFFFFFFF L, H# 00000000 L, 0 L, +H# 1F   L, H# FFFFFFFF L, H# 0000000A L, 5 L, +H# 03   L, H# FFFFFFFF L, H# 0000003C L, 0 L, +H# 0A   L, H# FFFFFFFF L, H# 00252504 L, 0 L, +H# 25   L, H# FFFFFFFF L, H# 00000005 L, 0 L, +H# 0E   L, H# FFFFFFFF L, H# 04756400 L, 0 L, +H# 0C   L, H# FFFFFFFF L, H# 04006401 L, 0 L, +H# 02   L, H# FFFFFFFF L, H# 0000A703 L, 0 L, +H# 0F   L, H# FFFFFFFF L, H# 0000051C L, 0 L, +H# 10   L, H# FFFFFFFF L, H# 04000400 L, 5 L, +H# 0E   L, H# FFFFFFFD L, H# 00000000 L, 5 L, +H# 0E   L, H# FFFFFFFE L, H# 00000000 L, 5 L, +H# 12   L, H# FFFFFFFF L, H# 00350012 L, 5 L, +H# 0F   L, H# FFFFFFFE L, H# 00000000 L, 6 L, +H# 10   L, H# FFFFFFFE L, H# 00000000 L, 5 L, +H# 10   L, H# FFFEFFFF L, H# 00000000 L, 6 L, +H# 0F   L, H# FFFFFFFD L, H# 00000000 L, 5 L, +H# 10   L, H# FFFFFFFD L, H# 00000000 L, 5 L, +H# 10   L, H# FFFDFFFF L, H# 00000000 L, d# 10 L, +H# 0C   L, H# FFFFFFFE L, H# 00000000 L, 6 L, +H# 0C   L, H# FFFFFFFD L, H# 00000000 L, 5 L, +h# 0D   L, H# FFFFFFFF L, H# FFFF8007 L, 5 L, +H# 08   L, H# FFFFFF3C L, H# 00000000 L, 0 L, +H# 02   L, H# FFFFFFFF L, H# 00000003 L, 0 L, +H# 04   L, H# FFFFFFFF L, H# 000381C0 L, 0 L, +H# 05   L, H# FFFFFFFF L, H# 000381F7 L, 0 L, +H# 06   L, H# FFFFFFFF L, H# 000381C0 L, 0 L, +H# 07   L, H# FFFFFFFF L, H# 000381F7 L, 0 L, +H# 02   L, H# FFFFFFFD L, H# 00000000 L, 6 L, +H# 02   L, H# FFFFFFFE L, H# 00000000 L, 5 L, +h# 08   L, H# FFFFFF3C L, H# 00000003 L, 5 L, +H# 0B   L, H# FFFFFFFF L, H# 78000800 L, 0 L, +H# 0B   L, H# FFFFFFFF L, H# 00004000 L, 0 L, +h# 01   L, h# FFFFFFFF L, H# 00000010 L, 0 L, + +here  PLLINIT_ARRAY  - /L / CONSTANT PLLINIT_LENGTH + +CREATE MEMINIT_ARRAY +h# 6FFF0000  L, H# 00004000 L, H# 6FFF0000 L, H# 80004000 L, +h# 6FFF0000  L, H# 00000132 L, H# 6FFF0000 L, H# 80000132 L, +h# 6FFF0000  L, H# 00000032 L, H# 6FFF0000 L, H# 80000032 L, +h# 6FFF0000  L, H# 10000032 L, +here MEMINIT_ARRAY - /L / CONSTANT MEMINIT_LENGTH +: L@+ ( addr -- value addr' ) + +dup l@ swap la1+ +; + +0 VALUE _len + +: ENCODE-ARRAY  ( array len -- ) +   dup to _len 0  do  l@+ swap encode-int rot  loop +   drop _len 1 - 0  ?do  encode+  loop +; + +: andorset  ( reg and or -- ) +   2 pick dup reg-rl@ +   3 pick AND 2 pick OR swap reg-rl! 3drop +; + +: INIT1 +H# 0F8  ( CONFIG_MEMSIZE )      H# 00000000  H# 01000000 andorset \ Set 16Mb memory size +H# 1C0  ( MPP_TB_CONFIG )       H# 00FFFFFF  H# 07000000 andorset +H# 030  ( BUS_CNTL      )       H# 00000000  H# 5133A3B0 andorset +H# 0EC  ( RBBM_CNTL     )       H# 00000000  h# 00004443 andorset +H# 1D0  ( DEBUG_CNTL    )       H# FFFFFFFD  H# 00000002 andorset +H# 050  ( CRTC_GEN_CNTL )       H# 00000000  H# 04000000 andorset +H# 058  ( DAC_CNTL      )       H# 00000000  H# FF604102 andorset +H# 168  ( PAD_CTLR_STRENGTH )   H# FFFEFFFF  H# 00001200 andorset +H# 178  ( MEM_REFRESH_CNTL  )   H# 00000000  H# 88888888 andorset +H# 17C  ( MEM_READ_CNTL )       H# 00000000  H# B7C20000 andorset +H# 188  ( MC_DEBUG      )       H# FFFFFFFF  H# 00000000 andorset +H# D00  ( DISP_MISC_CNTL)       H# 00FFFFFF  H# 5B000000 andorset +H# 88C  ( TV_DAC_CNTL   )       H# F800FCEF  H# 00490200 andorset +H# D04  ( DAC_MACRO_CNTL)       H# 00000000  H# 00000905 andorset +H# 284  ( FP_GEN_CNTL   )       H# FFFFFFFF  H# 00000008 andorset +H# 030  ( BUS_CNTL      )       H# FFFFFFEF  H# 00000000 andorset +; + + +: INIT2 +H# 140  ( MEM_CNTL )            H#  00000000  H# 38001A01 andorset +H# 158  ( MEM_SDRAM_MODE_REG )  H#  E0000000  H# 08320032 andorset +H# 144  ( MEM_TIMING_CNTL    )  H#  00000000  H# 20123833 andorset +H# 14C  ( MC_AGP_LOCATION    )  H#  00000000  H# 000FFFF0 andorset +H# 148  ( MC_FB_LOCATION     )  H#  00000000  H# FFFF0000 andorset +H# 154  ( MEM_INIT_LAT_TIMER )  H#  00000000  H# 34444444 andorset +H# 18C  ( MC_CHP_IO_OE_CNTL  )  H#  00000000  H# 0A540002 andorset +H# 910  ( FCP_CNTL           )  H#  00000000  H# 00000004 andorset +H# 010  ( BIOS_0_SCRATCH     )  H#  FFFFFFFB  H# 00000004 andorset +H# D64  ( DISP_OUTPUT_CNTL   )  H#  FFFFFBFF  H# 00000000 andorset +H# 2A8  ( TMDS_PLL_CNTL      )  H#  00000000  H# 00000A1B andorset +H# 800  ( TV_MASTER_CNTL     )  H#  BFFFFFFF  H# 40000000 andorset +H# D10  ( DISP_TEST_DEBUG_CTL ) H#  EFFFFFFF  H# 10000000 andorset +H# 4DC  ( OV0_FLAG_CNTRL     )  H#  FFFFFEFF  H# 00000100 andorset +H# 034  ( BUS_CNTL1          )  H#  73FFFFFF  H# 84000000 andorset +H# 174  ( AGP_CNTL           )  H#  FFEFFF00  H# 001E0000 andorset +H# 18C  ( MC_CHP_IO_OE_CNTL  )  H#  FFFFFFF9  H# 00000006 andorset h# 000A ms +H# 18C  ( MC_CHP_IO_OE_CNTL  )  H#  FFFFFFFB  H# 00000000 andorset H# 000A ms +H# 18C  ( MC_CHP_IO_OE_CNTL  )  H#  FFFFFFFD  H# 00000000 andorset +; + +: CLK-CNTL-INDEX! 8 ( CLK_CNTL_INDEX ) reg-rl! ; + +: CLK-CNTL-INDEX@ 8 ( CLK_CNTL_INDEX ) reg-rl@ ; + +: PLLWRITEON  clk-cntl-index@ H# 80 ( PLL_WR_ENABLE ) or clk-cntl-index! ; + +: PLLWRITEOFF clk-cntl-index@ H# 80 ( PLL_WR_ENABLE ) not and clk-cntl-index! ; \ Remove PLL_WR_ENABLE + +: CLKDATA! h# 0c ( CLK_CNTL_DATA ) reg-rl! ; + +: CLKDATA@ h# 0c ( CLK_CNTL_DATA ) reg-rl@ ; + +: PLLINDEXSET clk-cntl-index@ h# FFFFFFC0 and or clk-cntl-index! ; + +: PLLSET swap pllindexset clkdata! ; + +: pllandorset  ( index and or -- ) +   2 pick pllindexset clkdata@ +   2 pick AND over OR clkdata! 3drop +; + +: PLLINIT +pllwriteon +H# 0D   H# FFFF8000 pllset +H# 12   H# 00350000 pllset +H# 08   H# 00000000 pllset +H# 2D   H# 00000000 pllset +H# 1F   H# 0000000A pllset 5 ms + +H# 03   H# 0000003C pllset +H# 0A   H# 00252504 pllset +H# 25   H# 00000005 pllset +H# 0E   H# 04756400 pllset +H# 0C   H# 04006401 pllset +H# 02   H# 0000A703 pllset +H# 0F   H# 0000051C pllset +H# 10   H# 04000400 pllset 5 ms + +H# 0E   H# FFFFFFFD 00 pllandorset 5 ms +H# 0E   H# FFFFFFFE 00 pllandorset 5 ms +H# 12   H# 00350012 pllset 5 ms +H# 0F   H# FFFFFFFE 00 pllandorset 6 ms +H# 10   H# FFFFFFFE 00 pllandorset 5 ms +H# 10   H# FFFEFFFF 00 pllandorset 6 ms +H# 0F   H# FFFFFFFD 00 pllandorset 5 ms +H# 10   H# FFFFFFFD 00 pllandorset 5 ms +H# 10   H# FFFDFFFF 00 pllandorset d# 10 ms +H# 0C   H# FFFFFFFE 00 pllandorset 6 ms +H# 0C   H# FFFFFFFD 00 pllandorset 5 ms +h# 0D   h# FFFF8007      pllset 5 ms +H# 08   H# FFFFFF3C 00   pllandorset +H# 02   h# FFFFFFFF 03   pllandorset +H# 04   H# 000381C0      pllset +H# 05   H# 000381F7      pllset +H# 06   H# 000381C0      pllset +H# 07   H# 000381F7      pllset +H# 02   H# FFFFFFFD 00   pllandorset 6 ms +H# 02   h# FFFFFFFE 00   pllandorset 5 ms +h# 08   H# FFFFFF3C 03   pllandorset 5 ms +H# 0B   h# 78000800      pllset +H# 0B   H# FFFFFFFF h# 4000 pllandorset +h# 01   h# FFFFFFFF h# 0010 pllandorset + +pllwriteoff +; + +: DYNCKE +pllwriteon +H# 14   H# FFFF3FFF H# 30 pllandorset +H# 14   H# FF1FFFFF H# 00 pllandorset +H# 01   h# FFFFFFFF h# 80 pllandorset +H# 0D   H# 00000007       pllset 5 ms +h# 2D   H# 0000F8C0       pllset +h# 08   H# FFFFFFFF h# C0 pllandorset 5 ms +pllwriteoff +; + +: MEM-MODE@ +    h# 158 ( MEM_SDRAM_MODE_REG ) reg-rl@ ; + +: MEM-MODE! +    h# 158 ( MEM_SDRAM_MODE_REG ) reg-rl! ; + +: MEM-STATUS@ +    H# 150 reg-rl@ ; + +: WAIT-MEM-CMPLT +    h# 8000 0 do mem-status@ 3 and 3 = if leave then loop ; + +: INITMEM + +  mem-mode@ h# 6FFF0000 and h# 4000     or mem-mode! +  mem-mode@ h# 6FFF0000 and h# 80004000 or mem-mode! +  wait-mem-cmplt +  mem-mode@ h# 6FFF0000 and h# 0132     or mem-mode! +  mem-mode@ h# 6FFF0000 and h# 80000132 or mem-mode! +  wait-mem-cmplt +  mem-mode@ h# 6FFF0000 and h# 0032     or mem-mode! +  mem-mode@ h# 6FFF0000 and h# 80000032 or mem-mode! +  wait-mem-cmplt +  mem-mode@ h# 6FFF0000 and h# 10000032 or mem-mode! +; + + + +: CLR-REG ( reg -- ) +  0 swap  reg-rl! + +; +: SET-PALETTE  ( -- ) +  h# 0 h# b0 pc!                \ Reset PALETTE_INDEX + +  d# 16 0 do +    H# 000000 h# B4 reg-rl!     \ Write the PALETTE_DATA ( Auto increments) +    H# aa0000 H# B4 reg-rl! +    H# 00aa00 H# B4 reg-rl! +    H# aa5500 H# B4 reg-rl! +    H# 0000aa H# B4 reg-rl! +    H# aa00aa H# B4 reg-rl! +    H# 00aaaa H# B4 reg-rl! +    H# aaaaaa H# B4 reg-rl! +    H# 555555 H# B4 reg-rl! +    H# ff5555 H# B4 reg-rl! +    H# 55ff55 H# B4 reg-rl! +    H# ffff55 H# B4 reg-rl! +    H# 5555ff H# B4 reg-rl! +    H# ff55ff H# B4 reg-rl! +    H# 55ffff H# B4 reg-rl! +    H# ffffff H# B4 reg-rl! +  loop + + ; + +0 VALUE _addr +0 VALUE _color + +: DO-COLOR  ( color-addr addr color -- ) +   to _color to _addr 0 to _color +   3 0  do  _addr i + c@ 2 i - 8 * << _color + to _color  loop +   _color h# B4 reg-rl! +; + +: SET-COLORS ( addr index #indices -- ) + +  swap h# B0 pc! +  ( addr #indices ) 0 ?do dup ( index ) i 3 * + DO-COLOR loop +  ( addr ) drop ; + +: init-card + +  h# FF h# 58 3 + pc!   \ +  h# 59 pc@ h# FE and  h# 59 pc!   \ +  h# 50 reg-rl@ H# FEFFFFFF AND h# 02000200 or  \ Clear 24 set 25 and 8-11 to 2 +  h# 50 reg-rl! +  h# 4F0063  h# 200 reg-rl! +  H# 8C02A2  h# 204 reg-rl! +  H# 1Df020C h# 208 reg-rl! +  h# 8201EA  h# 20C reg-rl! +  h# 50 reg-rl@ H# F8FFFFFF AND h# 03000000 or h# 50 reg-rl! +  h# 50 h# 22C reg-rl! +  set-palette + +  \ at this point for some reason mem-addr does not point +  \ to the right address and therefore the following command +  \ which should probably clean the frame buffer just +  \ overwrites everything starting from 0 including the +  \ exception vectors + +  \ mem-addr h# F0000 0 fill + ; + +: DO-INIT +  early-map +  enable-card +  init1 +  pllinit +  init2 +  initmem +  init-card +  h# 8020 h# 54 reg-rl! +  early-unmap +; + +d# 640 constant /scanline +d# 480 constant #scanlines +/scanline #scanlines * constant /fb + +" okay" encode-string " status" property + +: display-install ( -- ) +  is_installed not if +    map-csr-base +    enable-card +    mem-addr to frame-buffer-adr +    h# 8020 h# 54 reg-rl! +    default-font set-font +    /scanline #scanlines  d# 100 d# 40 fb8-install +    true to is_installed +  then +; + +: display-remove  ( -- )  ; + +do-init                                                 \ Set up the card +\ clear at least 640x480 +10 config-l@ 8 - F0000 0 rfill +init1_array init1_length encode-array " ibm,init1" property +init2_array init2_length encode-array " ibm,init2" property +pllinit_array pllinit_length   encode-array " ibm,pllinit" property +meminit_array meminit_length   encode-array " ibm,meminit" property +0 0 encode-bytes " iso6429-1983-colors" property +s" display" device-type +/scanline  encode-int " width" property + #scanlines encode-int " height" property +8 encode-int " depth" property +/scanline  encode-int " linebytes" property + +' display-install is-install +' display-remove is-remove + +: fill-rectangle ( index x y w h -- ) +  2swap -rot /scanline * + frame-buffer-adr + ( index w h fbadr ) +  swap 0 ?do ( index w fbadr ) +    3dup swap rot fill ( index w fbadr ) +    /scanline + ( index w fbadr' ) +  loop +  3drop +; +: draw-rectangle ( addr x y w h -- ) + 2swap -rot /scanline * + frame-buffer-adr + ( addr w h fbadr ) + swap 0 ?do ( addr w fbadr ) +   3dup swap move ( addr w fbadr ) +    >r tuck + swap r> ( addr' w fbadr ) +    /scanline + ( addr' w fbadr' ) +  loop +  3drop + ; + : read-rectangle ( addr x y w h -- ) +  2swap -rot /scanline * + frame-buffer-adr + ( addr w h fbadr ) +  swap 0 ?do ( addr w fbadr ) +    3dup -rot move ( addr w fbadr ) +    >r tuck + swap r> ( addr' w fbadr ) +    /scanline + ( addr' w fbadr' ) +  loop +  3drop + ; + +: dimensions  ( -- width height )  /scanline #scanlines  ; + +."  ( rn50 )" cr diff --git a/roms/SLOF/board-js2x/slof/pci-device_1014_028c.fs b/roms/SLOF/board-js2x/slof/pci-device_1014_028c.fs new file mode 100644 index 00000000..e83a4e04 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-device_1014_028c.fs @@ -0,0 +1,25 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +my-space assign-all-device-bars +my-space pci-device-props +my-space pci-set-irq-line + +\ set Memory Write and Invalidate Enable, SERR# Enable (see PCI 3.0 Spec Chapter 6.2.2 device control) + +7 4 config-w! + + +\ Citrine storage controller. +s" citrine" + +include citrine.fs diff --git a/roms/SLOF/board-js2x/slof/pci-device_1014_02bd.fs b/roms/SLOF/board-js2x/slof/pci-device_1014_02bd.fs new file mode 100644 index 00000000..1db6bdaf --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-device_1014_02bd.fs @@ -0,0 +1,23 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +my-space assign-all-device-bars +my-space pci-device-props +my-space pci-set-irq-line + +\ set Memory Write and Invalidate Enable, SERR# Enable (see PCI 3.0 Spec Chapter 6.2.2 device control) +7 4 config-w! + +\ Citrine storage controller. +s" obsidian" + +include citrine.fs diff --git a/roms/SLOF/board-js2x/slof/pci-device_1022_7451.fs b/roms/SLOF/board-js2x/slof/pci-device_1022_7451.fs new file mode 100644 index 00000000..e540cba9 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-device_1022_7451.fs @@ -0,0 +1,34 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ IO-APIC init + +s" io-apic" 2dup device-name device-type +my-space pci-class-name type s"  ( 8131 IO-APIC )" type + +pci-io-enable +pci-mem-enable +pci-master-enable + +my-space b rshift  \ Get slot #. +dup c lshift fec00000 or  \ Calculate base address. +dup 48 config-l! 0 4c config-l!  \ Set base address. +03 44 config-b!  \ Enable IO-APIC. + +s" ioapic.fs" included + +2 lshift 14 +  \ Calculate first IRQ #. +init-ioapic  \ Set IRQs. + +my-space pci-device-props + +cr diff --git a/roms/SLOF/board-js2x/slof/pci-device_1022_7468.fs b/roms/SLOF/board-js2x/slof/pci-device_1022_7468.fs new file mode 100644 index 00000000..4126ca24 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-device_1022_7468.fs @@ -0,0 +1,50 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +my-space assign-all-device-bars +my-space pci-device-props +my-space pci-set-irq-line + +\ See the "ISA/EISA/ISA-PnP" OF binding document. + +.( isa) + +s" isa" 2dup device-name device-type +\ We have to say it's ISA i.s.o. LPC, as otherwise Linux can't find +\ the serial port for its console.  Linux uses the name instead of the +\ device type (and it completely ignores any "compatible" property). + +2 encode-int s" #address-cells" property +1 encode-int s" #size-cells" property + +\ We assume all ISA addresses to refer to I/O space. +: decode-unit  1 hex-decode-unit 1 ; +: encode-unit  drop 1 hex-encode-unit ; + +\ 32kB of ISA I/O space. +1 encode-int my-space 01000000 + encode-64+ 0 encode-int+ 0 encode-int+ +8000 encode-int+ s" ranges" property + +: open  true ; +: close ; + +\ There's a SIO chip on the LPC bus. +INCLUDE sio.fs + +\ There's also an Atmel TPM chip on JS21 +\ removed on Bimini Pass 2 and therefore disabled on all Biminis +u4? bimini? not and ?INCLUDE tpm.fs + +\ And finally there's the IPMI interface to the BMC. +u4? ?INCLUDE ipmi-kcs.fs + +cr diff --git a/roms/SLOF/board-js2x/slof/pci-device_1022_7469.fs b/roms/SLOF/board-js2x/slof/pci-device_1022_7469.fs new file mode 100644 index 00000000..fdae920c --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-device_1022_7469.fs @@ -0,0 +1,23 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +my-space assign-all-device-bars +my-space pci-device-props +my-space pci-set-irq-line + +7 4 config-w! + +s" ide" type cr + +include ide.fs + +cr diff --git a/roms/SLOF/board-js2x/slof/pci-device_14e4_16a8.fs b/roms/SLOF/board-js2x/slof/pci-device_14e4_16a8.fs new file mode 100644 index 00000000..ef782c94 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-device_14e4_16a8.fs @@ -0,0 +1,23 @@ +\ ***************************************************************************** +\ * Copyright (c) 2013 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ Handle bcm57xx device + +s" bcm57xx [ net ]" type cr + +my-space pci-device-generic-setup + +pci-io-enable + +s" bcm57xx.fs" included + +pci-device-disable diff --git a/roms/SLOF/board-js2x/slof/pci-interrupts.fs b/roms/SLOF/board-js2x/slof/pci-interrupts.fs new file mode 100644 index 00000000..92851cd5 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/pci-interrupts.fs @@ -0,0 +1,235 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ define function pointer as forward declaration for get-interrupt-line +\ this is board wireing and southbridge dependent +\ returns the wired interrupt line for this config addr +\ ( config-addr -- irq-line ) +DEFER pci-get-irq-line + +\ define function pointer as forward declaration for get-interrupt-sense-type +\ this is board wireing and southbridge dependent +\ returns the wired interrupt sense type for this config addr +\ 0 - Edge rising +\ 1 - Level low +\ 2 - Level high +\ 3 - Edge falling +\ ( config-addr -- irq-sense ) +DEFER pci-get-irq-sense + + +\ ***************************************************************************** +\ Generic IRQ routines +\ ***************************************************************************** + + + +: unknown-slot ( -- 0 ) +\	cr pci-vec ABORT" Unknown slot " +	0 +; +\ 0c s" /ht/@1/@2"    PCI-X INTA & INTC Pnpirq0 -> irq12 +\ 0e s" /ht/@1/@2"    PCI-X INTB & INTD Pnpirq1 -> irq14 +\ 10 s" /ht/@8,1"     ATA          +\ 0f s" /ht/@1/@1"    Obsidian     Pnpirq2 -> irq15 +\ 10 s" /ht/@7/@2"    Video / Exar Serial  PirqA +\ 11 s" /ht/@2/@4"    Ethernet     PirqB +\ 12 s" /ht/@2/@4,1"  Ethernet     PirqC +\ 13 s" /ht/@7/@0"    USB          PirqD +\ 13 s" /ht/@7/@0,1"  USB          PirqD +\ 13 s" /ht/@7/@0,2"  USB          PirqD + +\ 14 s" /ht/@3/@0"    PCIe gpio28 +\ 15 s" /ht/@4/@0"    PCIe gpio29 +\ 16 s" /ht/@5/@0"    PCIe gpio30 +\ 17 s" /ht/@6/@0"    PCIe gpio31 + + +\ ----------------------------------------------------------------------------- +\ Get the interrupt pin for a device on ht u4 +: u4-get-irq-line ( config-addr -- irq-line ) +\	cr s" u4-get-irq-line " type +	pci-device-vec c@ CASE  +		1 OF pci-device-vec-len 1 >= IF   +				pci-device-vec 1+ c@ CASE  +					1 OF f ENDOF +					2 OF dup pci-interrupt@ CASE +							1 OF c ENDOF +							3 OF e ENDOF +							2 OF c ENDOF +							4 OF e ENDOF +						ENDCASE +					ENDOF  +					dup OF unknown-slot  ENDOF +				ENDCASE +			ELSE +				unknown-slot +			THEN +		ENDOF +		2 OF pci-device-vec-len 1 >= IF   +				 pci-device-vec 1+ c@ CASE +					4 OF dup pci-addr2fn 1 >= IF 12 ELSE 11 THEN  ENDOF  +					dup OF unknown-slot  ENDOF +				ENDCASE +			ELSE +				unknown-slot +			THEN +		ENDOF +		3 OF 14 ENDOF +		4 OF 15 ENDOF +		5 OF 16 ENDOF +		6 OF 17 ENDOF +		7 OF pci-device-vec-len 1 >= IF   +				pci-device-vec 1+ c@ CASE  +					0 OF 13  ENDOF  +					2 OF 10  ENDOF  +					dup OF unknown-slot  ENDOF +				ENDCASE +			ELSE +				unknown-slot +			THEN +		ENDOF +		8 OF 10 ENDOF +                dup OF unknown-slot  ENDOF	 +        ENDCASE +	swap drop +; + +\ ----------------------------------------------------------------------------- +\ Get the interrupt sense type for a device on ht u4 +: u4-get-irq-sense ( config-addr -- irq-sense ) +\	cr s" u4-get-irq-sense " type +        u4-get-irq-line CASE  +	0c OF 00 ENDOF +	0e OF 00 ENDOF +	dup OF 01  ENDOF +        ENDCASE +; + +\ 10 s" /ht/@4,1"    set-pci-interrupt \ ATA +\ 13 s" /ht/@3/@0"   set-pci-interrupt \ USB +\ 13 s" /ht/@3/@0,1" set-pci-interrupt \ USB +\ 13 s" /ht/@3/@0,2" set-pci-interrupt \ USB +\ 1c s" /ht/@2/@1"   set-pci-interrupt \ Ethernet +\ 1d s" /ht/@2/@1,1" set-pci-interrupt \ Ethernet + +\ ----------------------------------------------------------------------------- +\ Get the interrupt pin for a device on ht u3 +: u3-get-irq-line ( config-addr -- irq-line ) +\	cr s" u3-get-irq-line " type +	pci-device-vec c@ CASE  +		2 OF pci-device-vec-len 1 >= IF   +				pci-device-vec 1+ c@ CASE  +					1 OF dup pci-addr2fn 1 >= IF 1d ELSE 1c THEN  ENDOF  +					dup OF unknown-slot  ENDOF +				ENDCASE +			ELSE +				unknown-slot +			THEN +		ENDOF +		3 OF 13 ENDOF +		4 OF 10 ENDOF +                dup OF unknown-slot  ENDOF	 +        ENDCASE +	swap drop +; + +\ ----------------------------------------------------------------------------- +\ Get the interrupt sense type for a device on ht u3 +: u3-get-irq-sense ( config-addr -- irq-sense ) +\	cr s" u3-get-irq-sense " type +        u3-get-irq-line CASE  +	dup OF 01  ENDOF +        ENDCASE +; + + + +\ ----------------------------------------------------------------------------- +\ Get the interrupt pin for a device on attu +: pcie-get-irq-line ( config-addr -- irq-line ) +\	cr s" pcie-get-irq-line " type +	drop +	3 +; + + +\ ----------------------------------------------------------------------------- +\ Get the interrupt sense type for a device on attu +: pcie-get-irq-sense ( config-addr -- irq-sense ) +\ 	cr s" pcie-get-irq-sense " type +       drop +        01 +; + +\ ----------------------------------------------------------------------------- +\ Set up the special routines for HT irq handling +: ht-irq-init ( -- ) +\	cr s" ht-irq-init " type +	u4? IF +       		['] u4-get-irq-line TO pci-get-irq-line +       		['] u4-get-irq-sense TO pci-get-irq-sense +	ELSE +        	['] u3-get-irq-line TO pci-get-irq-line +	       	['] u3-get-irq-sense TO pci-get-irq-sense +	THEN +; + +\ ----------------------------------------------------------------------------- +\ Set up the special routines for PCI-e irq handling +: pcie-irq-init ( -- ) +\	cr s" pcie-irq-init " type +        ['] pcie-get-irq-sense TO pci-get-irq-sense +        ['] pcie-get-irq-line TO pci-get-irq-line +; + +\ ----------------------------------------------------------------------------- +\ Set up the special routines for irq handling +0 VALUE mpic +: pci-irq-init ( mpic puid -- mpic ) +        over TO mpic +        18 rshift FF and +        CASE +                F1 OF pcie-irq-init ENDOF +                F2 OF ht-irq-init ENDOF +                dup OF ABORT" Wrong PUID! in pci-irq-init" ENDOF +        ENDCASE +; + +\ ----------------------------------------------------------------------------- +\ Set the interrupt pin for a device +: pci-set-irq-line ( config-addr -- ) +\	cr pci-vec +        dup pci-get-irq-line  +\	." ->" dup . +        swap pci-irq-line! +; + +\ ----------------------------------------------------------------------------- +\ Add an irq entry for the device at config-addr into the irq map +\ each entry consists of 7 integer values +\ Structure of an entry: +\             +----------+---+---+------------+--------------+---------+---------------+ +\  Number#    |    0     | 1 | 2 |     3      |      4       |    5    |      6        | +\             +----------+---+---+------------+--------------+---------+---------------+ +\  meaning    |  config  |   |   |      int#  |  phandle     | intr nr | pos edge (0)  | +\             |   addr   |   |   | (1=a, 2=b, |  intr contr  |         | act ll   (1)  | +\             +----------+---+---+------------+--------------+---------+---------------+ +\  value      | pci slot | 0 | 0 |    1       |        mpic  |     7   |     0|1       | +\             +----------+---+---+------------+--------------+---------+---------------+ +: pci-gen-irq-entry ( prop-addr prop-len config-addr -- prop-addr prop-len ) +        dup >r encode-int+ 0    encode-64+      \ config addr +        r@ pci-interrupt@       encode-int+     \ interrupt type +        mpic                    encode-int+     \ phandle to MPIC +        r@ pci-irq-line@        encode-int+     \ interrupt number +        r> pci-get-irq-sense    encode-int+     \ trigger type +; diff --git a/roms/SLOF/board-js2x/slof/rtas.fs b/roms/SLOF/board-js2x/slof/rtas.fs new file mode 100644 index 00000000..0a90c290 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/rtas.fs @@ -0,0 +1,240 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +#include <rtas/rtas-init.fs> +#include <rtas/rtas-cpu.fs> +#include <rtas/rtas-reboot.fs> +#include <rtas/rtas-flash.fs> +#include <rtas/rtas-vpd.fs> + +\ for update-flash +: (get-flashside)  ( -- flashside )  rtas-get-flashside  ; + +' (get-flashside) to get-flashside + +\ remember the current flashside +get-flashside to flashside?  + +\ for update-flash +: (set-flashside)  ( flashside -- status ) +   dup rtas-set-flashside =  IF  0  ELSE  -1  THEN +; + +' (set-flashside) to set-flashside + +: rtas-ibm-read-pci-config  ( size puid bus devfn off -- x ) +   [ s" ibm,read-pci-config" rtas-get-token ] LITERAL rtas-cb rtas>token l! +   4 rtas-cb rtas>nargs l! +   2 rtas-cb rtas>nret l! +   swap 8 lshift or swap 10 lshift or rtas-cb rtas>args0 l! +   dup 20 rshift rtas-cb rtas>args1 l! +   ffffffff and rtas-cb rtas>args2 l! +   rtas-cb rtas>args3 l! +   enter-rtas +   rtas-cb rtas>args5 l@ +; + +: rtas-fetch-cpus  ( mask -- status ) +   [ s" rtas-fetch-slaves" rtas-get-token ] LITERAL rtas-cb rtas>token l! +   1 rtas-cb rtas>nargs l! +   1 rtas-cb rtas>nret l! +   rtas-cb rtas>args0 l! +   0 rtas-cb rtas>args1 l! +   enter-rtas +   rtas-cb rtas>args1 l@ +; + +: rtas-stop-bootwatchdog  ( -- status ) +   [ s" rtas-stop-bootwatchdog" rtas-get-token ] LITERAL rtas-cb rtas>token l! +   0 rtas-cb rtas>nargs l! +   1 rtas-cb rtas>nret l! +   enter-rtas +   rtas-cb rtas>args0 l@ +; + +: rtas-set-bootwatchdog  ( seconds -- ) +   [ s" rtas-set-bootwatchdog" rtas-get-token ] LITERAL rtas-cb rtas>token l! +   1 rtas-cb rtas>nargs l! +   0 rtas-cb rtas>nret l! +   rtas-cb rtas>args0 l! +   enter-rtas +; + +' rtas-set-bootwatchdog to set-watchdog + +: rtas-dump-flash  ( offset cnt -- ) +   [ s" rtas-dump-flash" rtas-get-token ] LITERAL rtas-cb rtas>token l! +   2 rtas-cb rtas>nargs l! +   0 rtas-cb rtas>nret l! +   rtas-cb rtas>args0 l! +   rtas-cb rtas>args1 l! +   enter-rtas +; + +create blist 50 allot +blist 50 erase + +: build-blocklist_old +   \ set version +   1 blist c! +   \ set length of block list +   50 blist 7 + c! +   \ no more block list +   0000000000000000 blist 8 + ! +   \ first block +   get-load-base 0 + blist 10 + ! +   80000 blist 18 + ! +   get-load-base 80000 + blist 20 + ! +   80000 blist 28 + ! +   get-load-base 100000 + blist 30 + ! +   80000 blist 38 + ! +   get-load-base 180000 + blist 40 + ! +   8006C blist 48 + ! +; + +80000 constant _block_size + +: build-blocklist +   \ set length of block list +   \ length of flashfs at load-base is at offset 30... get it... +   get-load-base 30 + @ +   \ calculate the number of blocks we need +   _block_size / 1 + +   \ total number of blocks is 2 (for header and block_list extension + (number of blocks for flashfs * 2 (1 for address 1 for length)) +   2 * 2 + 8 * blist ! +   \ set version ( in first byte only ) +   1 blist c! +   \ no more block list +   0000000000000000 blist 8 + ! +   \ length of flashfs at load-base is at offset 30... get it... +   get-load-base 30 + @ +   \ i define one block to be 64K, so calculate the number of blocks we need and loop over them +   _block_size / 1 + 0 do +      get-load-base _block_size i * +  \ which position of load-base to store +      blist 10 +             \ at what offset of blist ( 0x8 + for header 0x8 + for extension ) +      i 10 * +               \ for each loop we have done 0x10 + +      !                      \ store it +      get-load-base 30 + @ +      _block_size i * -      \ remaining length +      dup _block_size >  +      IF                     \ is the remaining length > block size +	drop _block_size     \ then store the block size as length +      ELSE +			     \ do nothing (store remaining length) +      THEN +      blist 10 +          \ store the length at +      i 10 * +            \ correct blist offset  +      8 +                 \ + 8 (we have stored address, now the length) +      !                   \ store it +   loop +; + + + +: build-blocklist-v0_old +   \ set version +   0 blist c! +   48 blist 7 + c! +   \ first block +   get-load-base 0 + blist 8 + ! +   80000 blist 10 + ! +   get-load-base 80000 + blist 18 + ! +   80000 blist 20 + ! +   get-load-base 100000 + blist 28 + ! +   80000 blist 30 + ! +   get-load-base 180000 + blist 38 + ! +   8006C blist 40 + ! +; + +: build-blocklist-v0 +   \ set length of block list +   \ length of flashfs at load-base is at offset 30... get it... +   get-load-base 30 + @ +   \ calculate the number of blocks we need +   _block_size / 1 + +   \ total number of blocks is 1 (for header + (number of blocks for flashfs * 2 (1 for address 1 for length)) +   2 * 1 + 8 * blist ! +   \ length of flashfs at load-base is at offset 30... get it... +   get-load-base 30 + @ +   \ i define one block to be 64K, so calculate the number of blocks we need and loop over them +   _block_size / 1 + 0 do +      get-load-base _block_size i * +  \ which position of load-base to store +      blist 8 +             \ at what offset of blist ( 0x8 + for header) +      i 10 * +               \ for each loop we have done 0x10 + +      !                      \ store it +      get-load-base 30 + @ +      _block_size i * -      \ remaining length +      dup _block_size >  +      IF                     \ is the remaining length > block size +	drop _block_size     \ then store the block size as length +      ELSE +			     \ do nothing (store remaining length) +      THEN +      blist 8 +          \ store the length at +      i 10 * +            \ correct blist offset  +      8 +                 \ + 8 (we have stored address, now the length) +      !                   \ store it +   loop +; + + +: yy +   build-blocklist +   blist rtas-ibm-update-flash-64-and-reboot +; + +: yy0 +   build-blocklist-v0 +   blist rtas-ibm-update-flash-64-and-reboot +; + +: rtas-ibm-update-flash-64  ( block-list -- status ) +   [ s" ibm,update-flash-64" rtas-get-token ] LITERAL rtas-cb rtas>token l! +   2 rtas-cb rtas>nargs l! +   1 rtas-cb rtas>nret l! +   rtas-cb rtas>args0 l! +   \ special unofficial parameter: if this is set to 1, the rtas function will not check, wether +   \ we are on the perm side... this is needed for "update-flash -c" to work... +   1 rtas-cb rtas>args1 l! +   enter-rtas +   rtas-cb rtas>args2 l@ +; + +\ for update-flash +: flash-write  ( image-address -- status) +   load-base-override >r to load-base-override build-blocklist-v0 +   blist rtas-ibm-update-flash-64 +   r> to load-base-override 0=  IF  true  ELSE  false  THEN +; + +: commit  1 rtas-ibm-manage-flash-image ; +: reject  0 rtas-ibm-manage-flash-image ; + +: rtas-ibm-validate-flash-image  ( image-to-commit -- status ) +   [ s" ibm,validate-flash-image" rtas-get-token ] LITERAL rtas-cb rtas>token l! +   2 rtas-cb rtas>nargs l! +   2 rtas-cb rtas>nret l! +   rtas-cb rtas>args0 l! +   enter-rtas +   rtas-cb rtas>args1 l@ +; + +: rtas-get-blade-descr ( address size -- len status ) +   [ s" rtas-get-blade-descr" rtas-get-token ] LITERAL rtas-cb rtas>token l! +   2 rtas-cb rtas>nargs l! +   2 rtas-cb rtas>nret l! +   rtas-cb rtas>args1 l! +   rtas-cb rtas>args0 l! +   enter-rtas +   rtas-cb rtas>args2 l@ +   rtas-cb rtas>args3 l@ +; diff --git a/roms/SLOF/board-js2x/slof/rtc.fs b/roms/SLOF/board-js2x/slof/rtc.fs new file mode 100644 index 00000000..861b3f9f --- /dev/null +++ b/roms/SLOF/board-js2x/slof/rtc.fs @@ -0,0 +1,59 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ National Semiconductor SIO. +\ See http://www.national.com/pf/PC/PC87417.html for the datasheet. +\ PC87417.pdf +\ moved the RTC initialisation from the device tree to a much earlier point +\ so that the RTC can be accessed before device tree is generated + +\ Enable the RTC, set its address at 1070 +\ see PC87417.pdf page 39 (chapter 3.2.3) +10 7 siocfg! +1 30 siocfg! +1070 wbsplit nip dup 60 siocfg! 62 siocfg! + +: rtc@  ( offset -- value ) +   1070 io-c! 1071 io-c@ +; + +: rtc!  ( value offset -- ) +   1070 io-c! 1071 io-c! +; + +\ Set sane configuration; BCD mode is required by Linux. +\ PC87417.pdf page 153 (chapter 8.3.13) - RTC Control Register A +\ 20 - Divider Chain Control = Normal Operation +20 0a rtc! +\ PC87417.pdf page 155 (chapter 8.3.14) - RTC Control Register B +\ 02 - 24-hour format enabled +02 0b rtc! +\ PC87417.pdf page 156 (chapter 8.3.15) - RTC Control Register C +00 0c rtc! + +\ read from the rtc and do the bcd-to-bin conversion +: rtc-bin@  ( offset -- value ) +   rtc@ bcd-to-bin +; + +\ to be compatible with the cell boards we provide a .date word +\ .date prints the current date and time on the firmware prompt +: .date  ( -- ) +   0 rtc-bin@  ( seconds ) +   2 rtc-bin@ +   4 rtc-bin@ +   7 rtc-bin@ +   8 rtc-bin@  ( seconds minutes hours day month ) +   9 rtc-bin@ d# 1900 + dup d# 1970 <  IF  d# 100 +  THEN +   decimal 4 0.r 2d emit 2 0.r 2d emit 2 0.r space +   2 0.r 3a emit 2 0.r 3a emit 2 0.r hex +; diff --git a/roms/SLOF/board-js2x/slof/serial.fs b/roms/SLOF/board-js2x/slof/serial.fs new file mode 100644 index 00000000..98b2f293 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/serial.fs @@ -0,0 +1,48 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ Serial console.  Enabled very early. +\ remember last console used +CREATE lastser 4 allot  0 lastser l! + +\ On JS21, use serial port 2.  Detect Maui by looking at the SIO version. +20 siocfg@ f2 = IF 2f8 ELSE 3f8 THEN + +: >serial  LITERAL + ; +: js21?	   -2f8 >serial 0= ; +: serial!  js21? IF 2dup 2f8 + io-c! THEN 3f8 + io-c! ; +: serial1@ 3f8 + io-c@ ; +: serial2@ 2f8 + io-c@ ; + +: serial-init  0 1 serial!  0 2 serial! +               80 3 serial! d# 115200 swap / 0 serial!  0 1 serial! +               3 3 serial!  3 4 serial! ; +: serial-emit  BEGIN 5 serial1@ 20 and UNTIL   + 	       js21? IF BEGIN 5 serial2@ 20 and UNTIL THEN 0 serial! ; +: serial1-key? 5 serial1@ 1 and 0<> ; +: serial2-key? 5 serial2@ 1 and 0<> ; +: serial1-key  serial1-key? dup IF 0 serial1@ swap 0 lastser l! THEN ; +: serial2-key  serial2-key? dup IF 0 serial2@ swap 1 lastser l! THEN ; +: serial-key   BEGIN serial1-key dup IF ELSE js21? IF drop serial2-key THEN THEN UNTIL ; +: serial-key?  serial1-key? js21? IF serial2-key? or THEN ; + +\ : serial-key   BEGIN 5 serial2@ 1 and UNTIL  0 serial2@ ; +\ : serial-key?  5 serial2@  1 and 0<> ; + +d# 19200 serial-init +' serial-emit to emit +' serial-key  to key +' serial-key? to key? + +( .( SLOF) +\ .(  has started execution, serial console @ ) 0 >serial . diff --git a/roms/SLOF/board-js2x/slof/sio.fs b/roms/SLOF/board-js2x/slof/sio.fs new file mode 100644 index 00000000..554cf83e --- /dev/null +++ b/roms/SLOF/board-js2x/slof/sio.fs @@ -0,0 +1,85 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ National Semiconductor SIO. +\ See http://www.national.com/pf/PC/PC87417.html for the datasheet. + +\ We use both serial ports, and the RTC. + +\ See 3.7.5. +new-device   3f8 1 set-unit + +s" serial" 2dup device-name device-type + +\ Enable this UART. +3 7 siocfg!  1 30 siocfg! + +\ 8 bytes of ISA I/O space +my-unit encode-int rot encode-int+ 8 encode-int+ s" reg" property +d# 19200 encode-int s" current-speed" property +44 encode-int 0 encode-int+ s" interrupts" property + +: open  true ; +: close ; +: write ( adr len -- actual )  tuck type ; +: read  ( adr len -- actual )  0= IF drop 0 EXIT THEN +                               serial-key? 0= IF 0 swap c! -2 EXIT THEN +                               serial-key swap c! 1 ; + +finish-device + + +new-device   2f8 1 set-unit + +s" serial" 2dup device-name device-type + +\ Enable this UART. +2 7 siocfg!  1 30 siocfg! + +\ 8 bytes of ISA I/O space +my-unit encode-int rot encode-int+ 8 encode-int+ s" reg" property +d# 19200 encode-int s" current-speed" property +43 encode-int 0 encode-int+ s" interrupts" property + +: open  true ; +: close ; +: write ( adr len -- actual )  tuck type ; +: read  ( adr len -- actual )  0= IF drop 0 EXIT THEN +                               serial-key? 0= IF 0 swap c! -2 EXIT THEN +                               serial-key swap c! 1 ; + +finish-device + + + +\ See the "Device Support Extensions" OF Recommended Practice document. +new-device   1070 1 set-unit + +s" rtc" 2dup device-name device-type +\ Following is for Linux, to recognize this RTC: +s" pnpPNP,b00" compatible + +: rtc!  my-space io-c!  my-space 1+ io-c! ; +: rtc@  my-space io-c!  my-space 1+ io-c@ ; + +\ 10 bytes of ISA I/O space, at 1070. +my-unit encode-int rot encode-int+ 10 encode-int+ s" reg" property + +: open   true ; +: close ; + +\ XXX: dummy methods. +: get-time ( -- sec min hr day mth yr )  38 22 c 1 1 d# 1973 ; +: set-time ( sec min hr day mth yr -- )  3drop 3drop ; + +finish-device diff --git a/roms/SLOF/board-js2x/slof/tpm.fs b/roms/SLOF/board-js2x/slof/tpm.fs new file mode 100644 index 00000000..69b9bc40 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/tpm.fs @@ -0,0 +1,63 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ Atmel TPM. + +new-device   500 1 set-unit + +s" tpm" 2dup device-name device-type + +s" AT97SC3201" compatible + +\ 2 bytes of ISA I/O space +my-unit encode-int rot encode-int+ 2 encode-int+ s" reg" property + +: >tpm  4e io-c! ; +: tpm@  >tpm 4f io-c@ ; +: tpm!  >tpm 4f io-c! ; + +: dump-tpm  11 0 DO cr i 2 .r space i tpm@ 2 0.r LOOP ; + +my-address wbsplit 9 tpm! 8 tpm! \ set base address +0 a tpm! \ disable serint + +\ Now we need to execute TPM_Startup. +CREATE startup-cmd +0 c, c1 c, +0 c, 0 c, 0 c, c c, +0 c, 0 c, 0 c, 99 c, \ TPM_ORD_Startup +0 c, 1 c, \ TCPA_ST_CLEAR + +: send ( addr len -- )  bounds ?DO i c@ 500 io-c! LOOP ; +: wait-for-ready ( -- )  BEGIN 501 io-c@ 3 and 2 = UNTIL ; +: recv-verbose  ( -- ) +   cr ." TPM result: " +   500 io-c@ 2 0.r 500 io-c@ 2 0.r space +   500 io-c@ 500 io-c@ 500 io-c@ 500 io-c@  +   bljoin lbflip 6 - dup 8 0.r space 0 +   ?DO  500 io-c@ .  LOOP +; + +: recv ( -- ) +   500 io-c@ drop 500 io-c@ drop +   500 io-c@ 500 io-c@ 500 io-c@ 500 io-c@ +   bljoin lbflip 6 - 0 +   ?DO  500 io-c@ drop  LOOP +; + +startup-cmd c send  wait-for-ready  recv + +: open  true ; +: close ; + +finish-device diff --git a/roms/SLOF/board-js2x/slof/tree.fs b/roms/SLOF/board-js2x/slof/tree.fs new file mode 100644 index 00000000..040d99f0 --- /dev/null +++ b/roms/SLOF/board-js2x/slof/tree.fs @@ -0,0 +1,225 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +400 cp + +0 value puid + +: >conf-rtas ( config-addr  -- config-addr ) +   puid f2000000 >= IF +      ffffff AND                        \ Mask away highest byte for normal PCI +      dup ffff > IF +         1000000 + +      THEN +   THEN +   puid + +; + +: rtas-config-b@ ( config-addr -- value ) >conf-rtas rb@ ; +: rtas-config-b! ( value config-addr -- ) >conf-rtas rb! ; +: rtas-config-w@ ( config-addr -- value ) >conf-rtas rw@-le ; +: rtas-config-w! ( value config-addr -- ) >conf-rtas rw!-le ; +: rtas-config-l@ ( config-addr -- value ) >conf-rtas rl@-le ; +: rtas-config-l! ( value config-addr -- ) >conf-rtas rl!-le ; + +440 cp + +#include "pci-scan.fs" + +480 cp + +\ The root of the device tree and some of its kids. + +s" /" find-device +\ read model string from VPD +vpd-read-model ( straddr strlen ) +\ if it is a bimini, we replace the "IBM," in the model string with "TSS," +bimini? IF +   2dup drop 4 ( straddr strlen str 4 ) \ for string comparison: only first 4 bytes ("IBM,") +   \ string comparison +   s" IBM," str= IF +      \ model starts with "IBM,", we replace it with "TSS," +      2dup drop s" TSS," ( straddr strlen straddr replacestr len ) +      rot swap ( straddr strlen replacestr straddr len ) \ correct order for move: src dest len +      move ( straddr strlen ) \ now we have TSS, at beginning of str... +   THEN +THEN +\ store the model string +encode-string s" model" property + +2 encode-int s" #address-cells" property +2 encode-int s" #size-cells" property + +\ XXX: what requires this?  Linux? +0 encode-int  f8040000 encode-int+ +0 encode-int+ f8050000 encode-int+ s" platform-open-pic" property + +\ Yaboot is stupid.  Without this, it can't/won't find /etc/yaboot.conf. +s" chrp SLOF based 970 blade" device-type + +\ add more information to the compatible property +js21?  IF +   bimini?  IF +      s" IBM,Bimini" +   ELSE +      s" IBM,JS21" +   THEN +ELSE +   s" IBM,JS20" +THEN  encode-string +\ To get linux-2.6.10 and later to work out-of-the-box. +s" Momentum,Maple" encode-string encode+ s" compatible" property + + +\ See 3.6.5, and the PowerPC OF binding document. +new-device +s" mmu" 2dup device-name device-type +0 0 s" translations" property + +: open  true ; +: close ; + +finish-device + +new-device flash-addr set-unit-64 +   s" flash" 2dup device-name device-type +   0 encode-int flash-addr encode-int+ +   0 encode-int+ get-flash-size encode-int+ s" reg" property +   get-flash-size encode-int s" #bytes" property +   0 0 s" used-by-rtas" property +   : open  true  ; +   : close  ; +finish-device + +4a0 cp + +new-device nvram-base set-unit-64 +   s" nvram" 2dup device-name device-type +   nvram-size encode-int s" #bytes" property +   0 encode-int nvram-base encode-int+ +   0 encode-int+ nvram-size encode-int+ s" reg" property +   get-node node>path s" nvram" 2swap set-alias +   : open  true  ; +   : close  ; +finish-device + +4c0 cp + +#include "memory.fs" + +500 cp + +#include "mpic.fs" + +580 cp + +#include "dart.fs" + +5a0 cp + +#include "i2c.fs" + +600 cp +get-node device-end +620 cp +\ if it is js21/bimini the fbuffer code is included +u4? ?include fbuffer.fs +640 cp +set-node + +690 cp + +#include "ht.fs" + +6b0 cp + +u4? ?include attu.fs +6c0 cp + +\ See the PowerPC OF binding document. +new-device +s" cpus" device-name + +1 encode-int s" #address-cells" property +0 encode-int s" #size-cells" property + +: decode-unit  1 hex-decode-unit ; +: encode-unit  1 hex-encode-unit ; + +cpu-mask @ 40 0 DO dup 1 and IF +i s" cpu.fs" INCLUDED THEN u2/ LOOP drop + +: open  true ; +: close ; + +finish-device + +master-cpu s" /cpus/@" rot (u.) $cat open-dev encode-int s" cpu" set-chosen +s" /memory" open-dev encode-int s" memory" set-chosen + +6e0 cp + +new-device +   s" rtas" device-name + +   rtas-size encode-int s" rtas-size" property +   00000001 encode-int s" ibm,flash-block-version" property +   00000001 encode-int s" rtas-event-scan-rate" property +   rtas-create-token-properties +   00000001 encode-int s" rtas-version" property + +: open  true ; +: close ; + +: instantiate-rtas instantiate-rtas ; + +finish-device + +700 cp + +device-end + +\ Hack for AIX. +s" /options" find-device +   \ s" 33554432" encode-string s" load-base" property +   s" 16384" encode-string s" load-base" property +device-end + +\ See 3.5. +s" /openprom" find-device +   s" SLOF," slof-build-id here swap rmove here slof-build-id nip $cat encode-string s" model" property +   0 0 s" relative-addressing" property +   flashside? 1 = IF s" T" ELSE s" P" THEN +   encode-string s" ibm,fw-bank" property +   takeover? not  IF +      0 set-flashside drop +      read-version-and-date  s" ibm,fw-perm-bank" property +      1 set-flashside drop +      read-version-and-date  s" ibm,fw-temp-bank" property +      flashside? set-flashside drop +   THEN +device-end + +s" /aliases" find-device +   : open  true ; +   : close ; +device-end + +s" /mmu" open-dev encode-int s" mmu" set-chosen + +#include "available.fs" + +#include <term-io.fs> + +u3? IF s" /ht/isa/serial@3f8" io +  ELSE s" /ht/isa/serial@2f8" io THEN + diff --git a/roms/SLOF/board-js2x/slof/u4-mem.fs b/roms/SLOF/board-js2x/slof/u4-mem.fs new file mode 100644 index 00000000..0f8b1eef --- /dev/null +++ b/roms/SLOF/board-js2x/slof/u4-mem.fs @@ -0,0 +1,313 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ U4 DDR2 memory controller. + +cr .( Setting up memory controller...) + + +\ First, I2C access to the SPDs. + +: >i2c  f8001000 + ; +: i2c@  >i2c rl@ ; +: i2c!  >i2c rl! ; + +: .i2c  80 0 DO i i2c@ . 10 +LOOP ; + +: i2c-addr ( addr -- )  50 i2c!  2 10 i2c!  BEGIN 30 i2c@ 2 and UNTIL ; +: i2c-addr-subaddr ( addr suba -- )  60 i2c! i2c-addr ; +: i2c-stop ( -- )  BEGIN 30 i2c@ dup 30 i2c! 4 and UNTIL ; +: i2c-nak? ( -- failed? )  20 i2c@ 2 and 0= dup IF i2c-stop THEN ; +: i2c-short? ( -- failed? )  30 i2c@ 4 and 0<> dup IF 0 10 i2c! i2c-stop THEN ; +: i2c-aak-if-more ( n -- )  1 <> 1 and 10 i2c! ; + +: i2c-sub-read ( buf len addr suba -- error? ) +  c 0 i2c!  >r 1 or r> i2c-addr-subaddr  i2c-nak? IF 2drop true EXIT THEN +  dup i2c-aak-if-more  2 30 i2c! +  BEGIN +  30 i2c@ 1 and IF +    1- >r 70 i2c@ over c! char+ r> +    dup 0= IF i2c-stop 2drop false EXIT THEN +    dup i2c-aak-if-more 1 30 i2c! THEN +  i2c-short? IF 2drop true EXIT THEN +  AGAIN ; + + +\ What slots are filled with working memory (bitmask). + +f VALUE dimms-valid +: dimm-invalid  1 swap lshift invert dimms-valid and to dimms-valid ; +: dimm-invalid  dup dimm-invalid 2 xor dimm-invalid ; \ DIMMs are paired +: dimm-valid?  1 swap lshift dimms-valid and ; +: dimm(  +comp postpone 4 postpone 0 postpone DO +               postpone i postpone dimm-valid? postpone IF ; immediate +: )dimm  postpone THEN postpone LOOP -comp ; immediate + + +\ The data from the SPDs. + +CREATE spds 100 allot +: spd@ ( dimm# off -- value ) swap 40 * + spds + c@ ; + +CREATE addresses a0 c, a4 c, a2 c, a6 c, +dimm( spds i 40 * + 40 addresses i + c@ 0 i2c-sub-read IF i dimm-invalid THEN )dimm + + +\ Accessors. + +: spd>rows  3 spd@ ; +: spd>cols  4 spd@ ; +: spd>ranks 5 spd@ 7 and 1+ ; +: spd>width d spd@ ; +: spd>banks 11 spd@ ; +: spd>cas   12 spd@ ; \ bit mask of allowable CAS latencies +: spd>trp   1b spd@ ; \ in units of 0.25 ns +: spd>trrd  1c spd@ ; \ in units of 0.25 ns +: spd>trcd  1d spd@ ; \ in units of 0.25 ns +: spd>tras  1e spd@ ; \ in units of 1 ns +: spd>twr   24 spd@ ; \ in units of 0.25 ns +: spd>twtr  25 spd@ ; \ in units of 0.25 ns +: spd>trtp  26 spd@ ; \ in units of 0.25 ns +: spd>trc   29 spd@ ; \ in units of 1 ns  XXX: should also look at byte 28 +: spd>trfc  2a spd@ ; \ in units of 1 ns  XXX: should also look at byte 28 + +cr .( rows cols ranks width banks trp trrd trcd tras twr twtr trtp trc trfc) +cr .( =====================================================================) +decimal +dimm( cr +i spd>rows  4 .r  i spd>cols  5 .r  i spd>ranks 6 .r  i spd>width 6 .r +i spd>banks 6 .r  i spd>trp   4 .r  i spd>trrd  5 .r  i spd>trcd  5 .r +i spd>tras  5 .r  i spd>twr   4 .r  i spd>twtr  5 .r  i spd>trtp  5 .r +i spd>trc   4 .r  i spd>trfc  5 .r +)dimm +hex + +ff dimm( i spd>cas and )dimm CONSTANT cl-supported +: max-cl  -1 swap 8 0 DO dup 1 and IF nip i swap THEN u2/ LOOP drop ; +cl-supported max-cl VALUE cl + +: tck>60*ns dup f and swap 4 rshift a * over + 6 * swap CASE +            a OF 2d - ENDOF b OF 2e - ENDOF c OF 20 - ENDOF d OF 21 - ENDOF +            ENDCASE ; +: cl>tck  0 spd>cas max-cl swap - +          CASE 0 OF 9 ENDOF 1 OF 17 ENDOF 2 OF 19 ENDOF +          true ABORT" No supported CAS latency for this DIMM" ENDCASE +          0 swap spd@ tck>60*ns ; + +: spd>min-tck  dup spd>cas max-cl cl - +               CASE 0 OF 9 ENDOF 1 OF 17 ENDOF 2 OF 19 ENDOF +               true ABORT" No supported CAS latency for this DIMM" ENDCASE +               spd@ tck>60*ns ; +: spd>max-tck  2b spd@ tck>60*ns ; + +: .tck  base @ >r decimal dup d# 60 / 0 .r [char] . emit +        d# 60 mod d# 1000 * d# 60 / 3 0.r ." ns" r> base ! ; + +cr .( CAS latencies supported: ) +8 0 DO cl-supported 1 i lshift and IF i . THEN LOOP + +\ Find the lowest CL at the highest tCK. +8 0 DO cl-supported 1 i lshift and IF cl cl>tck i cl>tck = IF +       i to cl LEAVE THEN THEN LOOP + +.( -- using ) cl . + + +0 dimm( i spd>min-tck max )dimm  CONSTANT tck +dimm( i spd>max-tck tck < IF i dimm-invalid THEN )dimm +cr .( tCK is ) tck .tck + + +0 CONSTANT al +cl al + CONSTANT rl +rl 1- CONSTANT wl + +: //  dup >r 1- + r> / ; \ round up +0 spd>tras d# 60 * tck // CONSTANT tras +0 spd>trtp d# 15 * tck // CONSTANT trtp +0 spd>twr  d# 15 * tck // CONSTANT twr +0 spd>trp  d# 15 * tck // CONSTANT trp +0 spd>trrd d# 15 * tck // CONSTANT trrd +0 spd>trrd d# 60 * tck // CONSTANT 4*trrd +0 spd>trcd d# 15 * tck // CONSTANT trcd +0 spd>trc  d# 60 * tck // CONSTANT trc +0 spd>twtr d# 15 * tck // CONSTANT twtr + +: spd>memmd +  >r r@ spd>rows r@ spd>cols + +  r@ spd>banks 2log + 4 * r> spd>width 2log 3 * + 6c - ; +: dimm-group-size ( dimm# -- size ) +  >r r@ spd>rows r@ spd>cols + 1 swap lshift +  r@ spd>banks * r> spd>ranks * 10 * ; +VARIABLE start-address +VARIABLE was-prev-big +: assign-dimm-group ( dimm# -- config-value ) +  dup dimm-valid? 0= IF drop 0 EXIT THEN +  \ MemMd, enable, single-sided or not +  dup spd>memmd c lshift 1 or over spd>ranks 1 = IF 2 or THEN  +cr ." ---> " dup . +>r +  dimm-group-size start-address @ 2dup + rot ( start end size ) +  80000000 > IF +    dup 1000000000 < IF dup 4 rshift ELSE 08000000 THEN r> or >r \ Add2G +    over 0<>        IF over c rshift ELSE 00080000 THEN r> or >r \ Sub2G +    was-prev-big on +  ELSE +    was-prev-big @ IF 80000000 + swap 80000000 + swap THEN r> 08080000 or >r +    was-prev-big off +  THEN +  swap 18 rshift r> or >r \ start address +  dup 80000000 = IF drop 100000000 THEN start-address ! r> ; + + +\ Now set the frequency in the memory controller +d# 1800 tck / 4 - 12 lshift 33c or f8000800 rl! +f8000860 rl@ 80000000 or f8000860 rl!  10000 0 DO LOOP + +: mc!  f8002000 + rl! ; +: mc@  f8002000 + rl@ ; + + +\ memory timing regs (state machine) + +tras 2- +5 lshift al trtp + 2- or +5 lshift wl twr + or +5 lshift trp 2- or +5 lshift trp 2- 0 spd>banks 8 = IF 1+ THEN or +7 lshift 030 mc! + +al trtp + trp + 2- +5 lshift cl al + twr + trp + 1- or +5 lshift trrd 2- or +5 lshift trc 2- or +5 lshift trcd 2- or +5 lshift 4*trrd or +2 lshift 040 mc! + +0 +5 lshift 1 or +5 lshift 1 or +5 lshift cl 1- twtr + or +5 lshift 1 or +5 lshift 1 or +2 lshift 050 mc! + +0 +5 lshift 1 or +5 lshift 1 or +5 lshift 2 or +5 lshift 2 or +5 lshift 2 or +2 lshift 060 mc! \ XXX joerg has different setting + +cl 3 = IF 30801800 ( 30800d00 ) 070 mc! \ XXX memory refresh +ELSE 41002000 070 mc! THEN + +\ memory size regs + +1 dimm-group-size 0 dimm-group-size > 1 0 rot IF swap THEN \ biggest first +assign-dimm-group 200 mc! +assign-dimm-group 210 mc! +0 220 mc! 0 230 mc! + + + + + +\ arbiter tunables +\ 40041040 270 mc! +04041040 270 mc! +50000000 280 mc! +\ a0a00000 290 mc! \ a0000000 might be faster +00000000 290 mc! +\ 20020820 2a0 mc! +04020822 2a0 mc! +00000000 2b0 mc! +\ 30413cc7 2c0 mc! \ have to calculate the low five bits +30413dc5 2c0 mc! +\ cl 3 = IF 76000050 2d0 mc!  70000000 2e0 mc! ELSE +cl 3 = IF 75000050 2d0 mc!  70000000 2e0 mc! ELSE +    b8002080 2d0 mc!  b0000000 2e0 mc! THEN +\ Should test for something else really + + + +cl 3 = IF 00006000 890 mc!  00006000 8a0 mc! ELSE +          00006500 890 mc!  00006500 8a0 mc! THEN + +cl 3 = IF 1e008a8a ELSE 31000000 THEN +dup 800 mc! dup 810 mc! dup 820 mc! dup 830 mc! +dup 900 mc! dup 910 mc! dup 920 mc! dup 930 mc! dup 980 mc! +dup a00 mc! dup a10 mc! dup a20 mc! dup a30 mc! +dup b00 mc! dup b10 mc! dup b20 mc! dup b30 mc!     b80 mc! + +\ 0 8d0 mc!  0 9d0 mc!  0 ad0 mc!  0 bd0 mc! +61630000 8d0 mc! +61630000 9d0 mc! +52510000 ad0 mc! +434e0000 bd0 mc! + +a0200400 100 mc! +80020000 110 mc! +80030000 120 mc! +80010404 130 mc! +cl 3 = IF +8000153a 140 mc! ELSE +8000174a 140 mc! THEN +a0200400 150 mc! +\ 92000000 160 mc! +\ 92000000 170 mc! +\ 91300000 160 mc! +\ 91300000 170 mc! +91800000 160 mc! +91800000 170 mc! +cl 3 = IF +8ff0143a 180 mc! ELSE +8ff0164a 180 mc! THEN +80010784 190 mc! +80010404 1a0 mc! +0 1b0 mc!  0 1c0 mc!  0 1d0 mc!  0 1e0 mc!  0 1f0 mc! + +cl 3 = IF +143a 0c0 mc! ELSE +164a 0c0 mc! THEN +0404 0d0 mc! + +\ after this point, setup is common for all speeds and sizes of dimms (sort of) + +60000000 3a0 mc! + +0 840 mc!  0 850 mc!  0 860 mc!  0 870 mc! +0 940 mc!  0 950 mc!  0 960 mc!  0 970 mc!  0 990 mc! +0 a40 mc!  0 a50 mc!  0 a60 mc!  0 a70 mc! +0 b40 mc!  0 b50 mc!  0 b60 mc!  0 b70 mc!  0 b90 mc! + +0 880 mc! + +001a4000 9a0 mc! + +84800000 500 mc! + +10000 0 DO LOOP + +80000000 b0 mc!  BEGIN b0 mc@ 40000000 and UNTIL + +0 300 mc!  0 310 mc! + +80000000 440 mc! +0 410 mc!  27fffffc 420 mc! +fedcba98 430 mc! +c0000000 400 mc!  BEGIN 400 mc@ c0000000 and 0= UNTIL + +cr .( mem done) diff --git a/roms/SLOF/board-js2x/slof/version.c b/roms/SLOF/board-js2x/slof/version.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/roms/SLOF/board-js2x/slof/version.c diff --git a/roms/SLOF/board-js2x/slof/vga-display.fs b/roms/SLOF/board-js2x/slof/vga-display.fs new file mode 100644 index 00000000..96417e2d --- /dev/null +++ b/roms/SLOF/board-js2x/slof/vga-display.fs @@ -0,0 +1,157 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ *     IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ included by pci-class_03.fs + +( str len display_num ) \ name prefix + +false value is-installed? +value display_num ( str len ) + +s" ,Display-" $cat 41 display_num + char-cat \ add ", Display-A" or "-B" to name ( str len ) +encode-string s" name" property \ store as name property + +s" display" device-type + +\ screen-info is set by pci-class_03.fs contains output of get_vbe_info bios-snk call +CASE screen-info c@ \ ( display-type ) +   0 OF s" NONE" ENDOF \ No display +   1 OF s" Analog" ENDOF +   2 OF s" Digital" ENDOF +ENDCASE +encode-string s" display-type" property  + +screen-info 8 + l@ value mem-adr +screen-info 1 + w@ value width +screen-info 3 + w@ value height + +screen-info c@ IF +   \ if screen-info is not 0, we have some screen attached, add needed properties... +   width encode-int s" width" property +   height encode-int s" height" property +   screen-info 5 + w@ encode-int s" linebytes" property +   screen-info 7 + c@ encode-int s" depth" property +   mem-adr encode-int s" address" property +   \ the EDID property breaks the boot... so i leave it out for now,  +   \ maybe encode-bytes does s.th. wrong??? +   \ screen-info c + 80 encode-bytes s" EDID" property +   s" ISO8859-1" encode-string s" character-set" property \ i hope this is ok... +THEN + +\ words for installation/removal, needed by is-install/is-remove, see display.fs +: display-remove ( -- )  +; +: display-install ( -- )  +   is-installed? NOT IF  +      mem-adr to frame-buffer-adr  +      default-font  +      set-font +      width height width char-width / height char-height / ( width height #lines #cols ) +      fb8-install  +      true to is-installed? +   THEN +; + +: color! ( r g b number -- )  +   \ 3c8 is RAMDAC write mode select palette entry register +   \ 3c9 is RAMDAC write mode write palette entry register ( 3 consecutive writes set new entry ) +   vga-device-node? 3c8 translate-address ( r g b number address )  +   swap 1 pick ( r g b address number address ) +   rb! \ write palette entry number ( r g b address ) +   1 + \ select next register (3c9) +   dup 4 pick swap rb! \ write red ( r g b address ) +   dup 3 pick swap rb! \ write green ( r g b address ) +   dup 2 pick swap rb! \ write blue ( r g b address ) +   4drop +; + +: color@ ( number -- r g b )  +   \ 3c7 is RAMDAC read mode select palette entry register +   \ 3c9 is RAMDAC read mode read palette entry register ( 3 consecutive reads read entry ) +   vga-device-node? 3c7 translate-address ( number address )  +   swap 1 pick ( address number address ) +   rb! \ write palette entry number ( address ) +   2 + >r \ select next register (3c9) ( R: address ) +   r@ rb@ \ read red ( r R: address ) +   r@ rb@ \ read green ( r g R: address ) +   r@ rb@ \ write blue ( r g b R: address ) +   r> drop ( r g b ) +; + +: set-colors ( adr number #numbers -- ) +   \ 3c8 is RAMDAC write mode select palette entry register +   \ 3c9 is RAMDAC write mode write palette entry register ( 3 consecutive writes set new entry ) +   \ since after writing 3 entries, the palette entry is automagically incremented,  +   \ we can just continue writing... +   vga-device-node? 3c8 translate-address ( adr number #numbers )  +   dup 3 pick swap ( adr number #numbers address number address ) +   rb! \ write palette entry number ( adr number #numbers address ) +   1 + \ select next register (3c9)   +   -rot swap drop ( adr address #numbers ) +   -rot swap rot  ( address adr #numbers ) +   0 ?DO +      ( address adr ) +      dup rb@ \ read red value from adr ( address adr r ) +      2 pick rb! \ write to register ( address adr ) +      1 + \ next adr  +      dup rb@ \ read green value from adr ( address adr g ) +      2 pick rb! \ write to register ( address adr ) +      1 + \ next adr  +      dup rb@ \ read blue value from adr ( address adr r ) +      2 pick rb! \ write to register ( address adr ) +      1 + \ next adr  +   LOOP +   2drop +; + +: get-colors ( adr number #numbers -- ) +   \ 3c7 is RAMDAC read mode select palette entry register +   \ 3c9 is RAMDAC read mode read palette entry register ( 3 consecutive reads get entry ) +   \ since after reading 3 entries, the palette entry is automagically incremented,  +   \ we can just continue reading... +   vga-device-node? 3c7 translate-address ( adr number #numbers )  +   dup 3 pick swap ( adr number #numbers address number address ) +   rb! \ write palette entry number ( adr number #numbers address ) +   2 + \ select next register (3c9)   +   -rot swap drop ( adr address #numbers ) +   -rot swap rot  ( address adr #numbers ) +   0 ?DO +      ( address adr ) +      1 pick rb@ \ read red value from register ( address adr r ) +      1 pick rb! \ write to adr ( address adr ) +      1 + \ next adr  +      1 pick rb@ \ read green value from register ( address adr g ) +      1 pick rb! \ write to adr ( address adr ) +      1 + \ next adr  +      1 pick rb@ \ read blue value from register ( address adr b ) +      1 pick rb! \ write to adr ( address adr ) +      1 + \ next adr  +   LOOP +   2drop +; + +include graphics.fs + +\ clear screen  +mem-adr width height * 0 rfill + +\ call is-install and is-remove +' display-install is-install + +' display-remove is-remove + +s" screen" find-alias 0= IF +   \ no previous screen alias defined, define it... +   s" screen" get-node node>path set-alias +ELSE +   drop +THEN  | 
