From 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 15:20:36 -0700 Subject: Linux-2.6.12-rc2 Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip! --- arch/ppc/boot/simple/Makefile | 252 +++++++ arch/ppc/boot/simple/chrpmap.c | 12 + arch/ppc/boot/simple/clear.S | 19 + arch/ppc/boot/simple/cpc700_memory.c | 36 + arch/ppc/boot/simple/dummy.c | 4 + arch/ppc/boot/simple/embed_config.c | 981 ++++++++++++++++++++++++ arch/ppc/boot/simple/head.S | 142 ++++ arch/ppc/boot/simple/iic.c | 214 ++++++ arch/ppc/boot/simple/m8260_tty.c | 325 ++++++++ arch/ppc/boot/simple/m8xx_tty.c | 290 +++++++ arch/ppc/boot/simple/misc-chestnut.c | 35 + arch/ppc/boot/simple/misc-cpci690.c | 27 + arch/ppc/boot/simple/misc-embedded.c | 275 +++++++ arch/ppc/boot/simple/misc-ev64260.c | 57 ++ arch/ppc/boot/simple/misc-katana.c | 37 + arch/ppc/boot/simple/misc-mv64x60.c | 61 ++ arch/ppc/boot/simple/misc-prep.c | 212 ++++++ arch/ppc/boot/simple/misc-radstone_ppc7d.c | 26 + arch/ppc/boot/simple/misc-spruce.c | 274 +++++++ arch/ppc/boot/simple/misc.c | 284 +++++++ arch/ppc/boot/simple/mpc10x_memory.c | 111 +++ arch/ppc/boot/simple/mpc52xx_tty.c | 140 ++++ arch/ppc/boot/simple/mv64x60_tty.c | 360 +++++++++ arch/ppc/boot/simple/openbios.c | 37 + arch/ppc/boot/simple/pci.c | 274 +++++++ arch/ppc/boot/simple/pibs.c | 103 +++ arch/ppc/boot/simple/prepmap.c | 12 + arch/ppc/boot/simple/qspan_pci.c | 269 +++++++ arch/ppc/boot/simple/relocate.S | 216 ++++++ arch/ppc/boot/simple/rw4/ppc_40x.h | 664 ++++++++++++++++ arch/ppc/boot/simple/rw4/rw4_init.S | 78 ++ arch/ppc/boot/simple/rw4/rw4_init_brd.S | 1125 ++++++++++++++++++++++++++++ arch/ppc/boot/simple/rw4/stb.h | 239 ++++++ 33 files changed, 7191 insertions(+) create mode 100644 arch/ppc/boot/simple/Makefile create mode 100644 arch/ppc/boot/simple/chrpmap.c create mode 100644 arch/ppc/boot/simple/clear.S create mode 100644 arch/ppc/boot/simple/cpc700_memory.c create mode 100644 arch/ppc/boot/simple/dummy.c create mode 100644 arch/ppc/boot/simple/embed_config.c create mode 100644 arch/ppc/boot/simple/head.S create mode 100644 arch/ppc/boot/simple/iic.c create mode 100644 arch/ppc/boot/simple/m8260_tty.c create mode 100644 arch/ppc/boot/simple/m8xx_tty.c create mode 100644 arch/ppc/boot/simple/misc-chestnut.c create mode 100644 arch/ppc/boot/simple/misc-cpci690.c create mode 100644 arch/ppc/boot/simple/misc-embedded.c create mode 100644 arch/ppc/boot/simple/misc-ev64260.c create mode 100644 arch/ppc/boot/simple/misc-katana.c create mode 100644 arch/ppc/boot/simple/misc-mv64x60.c create mode 100644 arch/ppc/boot/simple/misc-prep.c create mode 100644 arch/ppc/boot/simple/misc-radstone_ppc7d.c create mode 100644 arch/ppc/boot/simple/misc-spruce.c create mode 100644 arch/ppc/boot/simple/misc.c create mode 100644 arch/ppc/boot/simple/mpc10x_memory.c create mode 100644 arch/ppc/boot/simple/mpc52xx_tty.c create mode 100644 arch/ppc/boot/simple/mv64x60_tty.c create mode 100644 arch/ppc/boot/simple/openbios.c create mode 100644 arch/ppc/boot/simple/pci.c create mode 100644 arch/ppc/boot/simple/pibs.c create mode 100644 arch/ppc/boot/simple/prepmap.c create mode 100644 arch/ppc/boot/simple/qspan_pci.c create mode 100644 arch/ppc/boot/simple/relocate.S create mode 100644 arch/ppc/boot/simple/rw4/ppc_40x.h create mode 100644 arch/ppc/boot/simple/rw4/rw4_init.S create mode 100644 arch/ppc/boot/simple/rw4/rw4_init_brd.S create mode 100644 arch/ppc/boot/simple/rw4/stb.h (limited to 'arch/ppc/boot/simple') diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile new file mode 100644 index 00000000000..d8d801fcee1 --- /dev/null +++ b/arch/ppc/boot/simple/Makefile @@ -0,0 +1,252 @@ +# This is far from simple, but I couldn't think of a good name. This is +# for making the 'zImage' or 'zImage.initrd' on a number of targets. +# +# Author: Tom Rini +# +# Notes: +# (1) For machines that do not want to use the ELF image directly (including +# stripping just the ELF header off), they must set the variables +# zimage-$(CONFIG_MACHINE) and zimagerd-$(CONFIG_MACHINE) to the target +# that produces the desired image and they must set end-$(CONFIG_MACHINE) +# to what will be suffixed to the image filename. +# (2) Regardless of (1), to have the resulting image be something other +# than 'zImage.elf', set end-$(CONFIG_MACHINE) to be the suffix used for +# the zImage, znetboot, and znetbootrd targets. +# (3) For machine targets which use the mktree program, you can optionally +# set entrypoint-$(CONFIG_MACHINE) to the location which the image should be +# loaded at. The optimal setting for entrypoint-$(CONFIG_MACHINE) is the link +# address. +# (4) It is advisable to pass in the memory size using BI_MEMSIZE and +# get_mem_size(), which is memory controller dependent. Add in the correct +# XXX_memory.o file for this to work, as well as editing the +# misc-$(CONFIG_MACHINE) variable. + +boot := arch/ppc/boot +common := $(boot)/common +utils := $(boot)/utils +bootlib := $(boot)/lib +images := $(boot)/images +of1275 := $(boot)/of1275 +tftpboot := /tftpboot + +# Normally, we use the 'misc.c' file for decompress_kernel and +# whatnot. Sometimes we need to override this however. +misc-y := misc.o + +# Normally, we have our images end in .elf, but something we want to +# change this. +end-y := elf + +# Additionally, we normally don't need to mess with the L2 / L3 caches +# if present on 'classic' PPC. +cacheflag-y := -DCLEAR_CACHES="" +# This file will flush / disable the L2, and L3 if present. +clear_L2_L3 := $(srctree)/$(boot)/simple/clear.S + +# +# See arch/ppc/kconfig and arch/ppc/platforms/Kconfig +# for definition of what platform each config option refer to. +#---------------------------------------------------------------------------- + zimage-$(CONFIG_CPCI690) := zImage-STRIPELF +zimageinitrd-$(CONFIG_CPCI690) := zImage.initrd-STRIPELF + extra.o-$(CONFIG_CPCI690) := misc-cpci690.o + end-$(CONFIG_CPCI690) := cpci690 + cacheflag-$(CONFIG_CPCI690) := -include $(clear_L2_L3) + + zimage-$(CONFIG_IBM_OPENBIOS) := zImage-TREE +zimageinitrd-$(CONFIG_IBM_OPENBIOS) := zImage.initrd-TREE + end-$(CONFIG_IBM_OPENBIOS) := treeboot + misc-$(CONFIG_IBM_OPENBIOS) := misc-embedded.o + + end-$(CONFIG_EMBEDDEDBOOT) := embedded + misc-$(CONFIG_EMBEDDEDBOOT) := misc-embedded.o + + zimage-$(CONFIG_EBONY) := zImage-TREE +zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE + end-$(CONFIG_EBONY) := ebony + entrypoint-$(CONFIG_EBONY) := 0x01000000 + extra.o-$(CONFIG_EBONY) := openbios.o + + zimage-$(CONFIG_LUAN) := zImage-TREE +zimageinitrd-$(CONFIG_LUAN) := zImage.initrd-TREE + end-$(CONFIG_LUAN) := luan + entrypoint-$(CONFIG_LUAN) := 0x01000000 + extra.o-$(CONFIG_LUAN) := pibs.o + + zimage-$(CONFIG_OCOTEA) := zImage-TREE +zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE + end-$(CONFIG_OCOTEA) := ocotea + entrypoint-$(CONFIG_OCOTEA) := 0x01000000 + extra.o-$(CONFIG_OCOTEA) := pibs.o + + extra.o-$(CONFIG_EV64260) := misc-ev64260.o + end-$(CONFIG_EV64260) := ev64260 + cacheflag-$(CONFIG_EV64260) := -include $(clear_L2_L3) + + extra.o-$(CONFIG_CHESTNUT) := misc-chestnut.o + end-$(CONFIG_CHESTNUT) := chestnut + + zimage-$(CONFIG_GEMINI) := zImage-STRIPELF +zimageinitrd-$(CONFIG_GEMINI) := zImage.initrd-STRIPELF + end-$(CONFIG_GEMINI) := gemini + + extra.o-$(CONFIG_K2) := prepmap.o + end-$(CONFIG_K2) := k2 + cacheflag-$(CONFIG_K2) := -include $(clear_L2_L3) + + extra.o-$(CONFIG_KATANA) := misc-katana.o + end-$(CONFIG_KATANA) := katana + cacheflag-$(CONFIG_KATANA) := -include $(clear_L2_L3) + + extra.o-$(CONFIG_RADSTONE_PPC7D) := misc-radstone_ppc7d.o + end-$(CONFIG_RADSTONE_PPC7D) := radstone_ppc7d + cacheflag-$(CONFIG_RADSTONE_PPC7D) := -include $(clear_L2_L3) + +# kconfig 'feature', only one of these will ever be 'y' at a time. +# The rest will be unset. +motorola := $(CONFIG_MCPN765)$(CONFIG_MVME5100)$(CONFIG_PRPMC750) \ +$(CONFIG_PRPMC800)$(CONFIG_LOPEC)$(CONFIG_PPLUS) +motorola := $(strip $(motorola)) +pcore := $(CONFIG_PCORE)$(CONFIG_POWERPMC250) + + zimage-$(motorola) := zImage-PPLUS +zimageinitrd-$(motorola) := zImage.initrd-PPLUS + end-$(motorola) := pplus + +# Overrides previous assingment + extra.o-$(CONFIG_PPLUS) := prepmap.o + extra.o-$(CONFIG_LOPEC) := mpc10x_memory.o + + zimage-$(pcore) := zImage-STRIPELF +zimageinitrd-$(pcore) := zImage.initrd-STRIPELF + extra.o-$(pcore) := chrpmap.o + end-$(pcore) := pcore + cacheflag-$(pcore) := -include $(clear_L2_L3) + + zimage-$(CONFIG_PPC_PREP) := zImage-PPLUS +zimageinitrd-$(CONFIG_PPC_PREP) := zImage.initrd-PPLUS + extra.o-$(CONFIG_PPC_PREP) := prepmap.o + misc-$(CONFIG_PPC_PREP) += misc-prep.o mpc10x_memory.o + end-$(CONFIG_PPC_PREP) := prep + + end-$(CONFIG_SANDPOINT) := sandpoint + cacheflag-$(CONFIG_SANDPOINT) := -include $(clear_L2_L3) + + zimage-$(CONFIG_SPRUCE) := zImage-TREE +zimageinitrd-$(CONFIG_SPRUCE) := zImage.initrd-TREE + end-$(CONFIG_SPRUCE) := spruce + entrypoint-$(CONFIG_SPRUCE) := 0x00800000 + misc-$(CONFIG_SPRUCE) += misc-spruce.o + + zimage-$(CONFIG_LITE5200) := zImage-STRIPELF +zimageinitrd-$(CONFIG_LITE5200) := zImage.initrd-STRIPELF + end-$(CONFIG_LITE5200) := lite5200 + cacheflag-$(CONFIG_LITE5200) := -include $(clear_L2_L3) + + +# SMP images should have a '.smp' suffix. + end-$(CONFIG_SMP) := $(end-y).smp + +# This is a treeboot that needs init functions until the +# boot rom is sorted out (i.e. this is short lived) +extra-aflags-$(CONFIG_REDWOOD_4) := -Wa,-m405 +extra.o-$(CONFIG_REDWOOD_4) := rw4/rw4_init.o rw4/rw4_init_brd.o +EXTRA_AFLAGS := $(extra-aflags-y) +# head.o needs to get the cacheflags defined. +AFLAGS_head.o += $(cacheflag-y) + +# Linker args. This specifies where the image will be run at. +LD_ARGS := -T $(srctree)/$(boot)/ld.script \ + -Ttext $(CONFIG_BOOT_LOAD) -Bstatic +OBJCOPY_ARGS := -O elf32-powerpc + +# head.o and relocate.o must be at the start. +boot-y := head.o relocate.o $(extra.o-y) $(misc-y) +boot-$(CONFIG_40x) += embed_config.o +boot-$(CONFIG_8xx) += embed_config.o +boot-$(CONFIG_8260) += embed_config.o +boot-$(CONFIG_BSEIP) += iic.o +boot-$(CONFIG_MBX) += iic.o pci.o qspan_pci.o +boot-$(CONFIG_MV64X60) += misc-mv64x60.o +boot-$(CONFIG_RPXCLASSIC) += iic.o pci.o qspan_pci.o +boot-$(CONFIG_RPXLITE) += iic.o +# Different boards need different serial implementations. +ifeq ($(CONFIG_SERIAL_CPM_CONSOLE),y) +boot-$(CONFIG_8xx) += m8xx_tty.o +boot-$(CONFIG_8260) += m8260_tty.o +endif +boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o +boot-$(CONFIG_SERIAL_MPSC_CONSOLE) += mv64x60_tty.o + +LIBS := $(common)/lib.a $(bootlib)/lib.a +ifeq ($(CONFIG_PPC_PREP),y) +LIBS += $(of1275)/lib.a +endif + +OBJS := $(addprefix $(obj)/,$(boot-y)) + +# Tools +MKBUGBOOT := $(utils)/mkbugboot +MKPREP := $(utils)/mkprep +MKTREE := $(utils)/mktree + +targets := dummy.o + +$(obj)/zvmlinux: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \ + $(images)/vmlinux.gz $(obj)/dummy.o + $(OBJCOPY) $(OBJCOPY_ARGS) \ + --add-section=.image=$(images)/vmlinux.gz \ + --set-section-flags=.image=contents,alloc,load,readonly,data \ + $(obj)/dummy.o $(obj)/image.o + $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \ + -R .stabstr -R .ramdisk -R .sysmap + +$(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \ + $(images)/vmlinux.gz $(obj)/dummy.o + $(OBJCOPY) $(OBJCOPY_ARGS) \ + --add-section=.ramdisk=$(images)/ramdisk.image.gz \ + --set-section-flags=.ramdisk=contents,alloc,load,readonly,data \ + --add-section=.image=$(images)/vmlinux.gz \ + --set-section-flags=.image=contents,alloc,load,readonly,data \ + $(obj)/dummy.o $(obj)/image.o + $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS) + $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \ + -R .stabstr -R .sysmap + +# Sort-of dummy rules, that let us format the image we want. +zImage: $(images)/$(zimage-y) $(obj)/zvmlinux + cp -f $(obj)/zvmlinux $(images)/zImage.elf + rm -f $(obj)/zvmlinux + +zImage.initrd: $(images)/$(zimageinitrd-y) $(obj)/zvmlinux.initrd + cp -f $(obj)/zvmlinux.initrd $(images)/zImage.initrd.elf + rm -f $(obj)/zvmlinux.initrd + +znetboot: zImage + cp $(images)/zImage.$(end-y) $(tftpboot)/zImage.$(end-y) + +znetboot.initrd: zImage.initrd + cp $(images)/zImage.initrd.$(end-y) $(tftpboot)/zImage.initrd.$(end-y) + +$(images)/zImage-STRIPELF: $(obj)/zvmlinux + dd if=$(obj)/zvmlinux of=$(images)/zImage.$(end-y) skip=64 bs=1k + +$(images)/zImage.initrd-STRIPELF: $(obj)/zvmlinux.initrd + dd if=$(obj)/zvmlinux.initrd of=$(images)/zImage.initrd.$(end-y) \ + skip=64 bs=1k + +$(images)/zImage-TREE: $(obj)/zvmlinux $(MKTREE) + $(MKTREE) $(obj)/zvmlinux $(images)/zImage.$(end-y) $(ENTRYPOINT) + +$(images)/zImage.initrd-TREE: $(obj)/zvmlinux.initrd $(MKTREE) + $(MKTREE) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(end-y) \ + $(ENTRYPOINT) + +$(images)/zImage-PPLUS: $(obj)/zvmlinux $(MKPREP) $(MKBUGBOOT) + $(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.$(end-y) + $(MKBUGBOOT) $(obj)/zvmlinux $(images)/zImage.bugboot + +$(images)/zImage.initrd-PPLUS: $(obj)/zvmlinux.initrd $(MKPREP) $(MKBUGBOOT) + $(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(end-y) + $(MKBUGBOOT) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.bugboot diff --git a/arch/ppc/boot/simple/chrpmap.c b/arch/ppc/boot/simple/chrpmap.c new file mode 100644 index 00000000000..14d9e05d98b --- /dev/null +++ b/arch/ppc/boot/simple/chrpmap.c @@ -0,0 +1,12 @@ +/* + * 2004 (C) IBM. This file is licensed under the terms of the GNU General + * Public License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include + +void board_isa_init(void) +{ + ISA_init(0xFE000000); +} diff --git a/arch/ppc/boot/simple/clear.S b/arch/ppc/boot/simple/clear.S new file mode 100644 index 00000000000..95c5647a0f5 --- /dev/null +++ b/arch/ppc/boot/simple/clear.S @@ -0,0 +1,19 @@ +/* + * Code to call _setup_L2CR to flus, invalidate and disable the L2, + * and if present, do the same to the L3. + */ + +#define CLEAR_CACHES \ + bl _setup_L2CR; \ + \ + /* If 745x, turn off L3CR as well */ \ + mfspr r8,SPRN_PVR; \ + srwi r8,r8,16; \ + \ + cmpli cr0,r8,0x8000; /* 7450 */ \ + cmpli cr1,r8,0x8001; /* 7455 */ \ + cmpli cr2,r8,0x8002; /* 7457 */ \ + /* Now test if any are true. */ \ + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq; \ + cror 4*cr0+eq,4*cr0+eq,4*cr2+eq; \ + beql _setup_L3CR diff --git a/arch/ppc/boot/simple/cpc700_memory.c b/arch/ppc/boot/simple/cpc700_memory.c new file mode 100644 index 00000000000..8c75cf6c238 --- /dev/null +++ b/arch/ppc/boot/simple/cpc700_memory.c @@ -0,0 +1,36 @@ +/* + * arch/ppc/boot/common/cpc700_memory.c + * + * Find memory based upon settings in the CPC700 bridge + * + * Author: Dan Cox + * + * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include "cpc700.h" + +unsigned long +cpc700_get_mem_size(void) +{ + int i; + unsigned long len, amt; + + /* Start at MB1EA, since MB0EA will most likely be the ending address + for ROM space. */ + for(len = 0, i = CPC700_MB1EA; i <= CPC700_MB4EA; i+=4) { + amt = cpc700_read_memreg(i); + if (amt == 0) + break; + len = amt; + } + + return len; +} + + diff --git a/arch/ppc/boot/simple/dummy.c b/arch/ppc/boot/simple/dummy.c new file mode 100644 index 00000000000..31dbf45bf99 --- /dev/null +++ b/arch/ppc/boot/simple/dummy.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/arch/ppc/boot/simple/embed_config.c b/arch/ppc/boot/simple/embed_config.c new file mode 100644 index 00000000000..c342b47e763 --- /dev/null +++ b/arch/ppc/boot/simple/embed_config.c @@ -0,0 +1,981 @@ +/* Board specific functions for those embedded 8xx boards that do + * not have boot monitor support for board information. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#ifdef CONFIG_8xx +#include +#endif +#ifdef CONFIG_8260 +#include +#include +#endif +#ifdef CONFIG_40x +#include +#endif +extern unsigned long timebase_period_ns; + +/* For those boards that don't provide one. +*/ +#if !defined(CONFIG_MBX) +static bd_t bdinfo; +#endif + +/* IIC functions. + * These are just the basic master read/write operations so we can + * examine serial EEPROM. + */ +extern void iic_read(uint devaddr, u_char *buf, uint offset, uint count); + +/* Supply a default Ethernet address for those eval boards that don't + * ship with one. This is an address from the MBX board I have, so + * it is unlikely you will find it on your network. + */ +static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; + +#if defined(CONFIG_MBX) + +/* The MBX hands us a pretty much ready to go board descriptor. This + * is where the idea started in the first place. + */ +void +embed_config(bd_t **bdp) +{ + u_char *mp; + u_char eebuf[128]; + int i = 8; + bd_t *bd; + + bd = *bdp; + + /* Read the first 128 bytes of the EEPROM. There is more, + * but this is all we need. + */ + iic_read(0xa4, eebuf, 0, 128); + + /* All we are looking for is the Ethernet MAC address. The + * first 8 bytes are 'MOTOROLA', so check for part of that. + * Next, the VPD describes a MAC 'packet' as being of type 08 + * and size 06. So we look for that and the MAC must follow. + * If there are more than one, we still only care about the first. + * If it's there, assume we have a valid MAC address. If not, + * grab our default one. + */ + if ((*(uint *)eebuf) == 0x4d4f544f) { + while (i < 127 && !(eebuf[i] == 0x08 && eebuf[i + 1] == 0x06)) + i += eebuf[i + 1] + 2; /* skip this packet */ + + if (i == 127) /* Couldn't find. */ + mp = (u_char *)def_enet_addr; + else + mp = &eebuf[i + 2]; + } + else + mp = (u_char *)def_enet_addr; + + for (i=0; i<6; i++) + bd->bi_enetaddr[i] = *mp++; + + /* The boot rom passes these to us in MHz. Linux now expects + * them to be in Hz. + */ + bd->bi_intfreq *= 1000000; + bd->bi_busfreq *= 1000000; + + /* Stuff a baud rate here as well. + */ + bd->bi_baudrate = 9600; +} +#endif /* CONFIG_MBX */ + +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) || \ + defined(CONFIG_RPX8260) || defined(CONFIG_EP405) +/* Helper functions for Embedded Planet boards. +*/ +/* Because I didn't find anything that would do this....... +*/ +u_char +aschex_to_byte(u_char *cp) +{ + u_char byte, c; + + c = *cp++; + + if ((c >= 'A') && (c <= 'F')) { + c -= 'A'; + c += 10; + } else if ((c >= 'a') && (c <= 'f')) { + c -= 'a'; + c += 10; + } else + c -= '0'; + + byte = c * 16; + + c = *cp; + + if ((c >= 'A') && (c <= 'F')) { + c -= 'A'; + c += 10; + } else if ((c >= 'a') && (c <= 'f')) { + c -= 'a'; + c += 10; + } else + c -= '0'; + + byte += c; + + return(byte); +} + +static void +rpx_eth(bd_t *bd, u_char *cp) +{ + int i; + + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = aschex_to_byte(cp); + cp += 2; + } +} + +#ifdef CONFIG_RPX8260 +static uint +rpx_baseten(u_char *cp) +{ + uint retval; + + retval = 0; + + while (*cp != '\n') { + retval *= 10; + retval += (*cp) - '0'; + cp++; + } + return(retval); +} +#endif + +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) +static void +rpx_brate(bd_t *bd, u_char *cp) +{ + uint rate; + + rate = 0; + + while (*cp != '\n') { + rate *= 10; + rate += (*cp) - '0'; + cp++; + } + + bd->bi_baudrate = rate * 100; +} + +static void +rpx_cpuspeed(bd_t *bd, u_char *cp) +{ + uint num, den; + + num = den = 0; + + while (*cp != '\n') { + num *= 10; + num += (*cp) - '0'; + cp++; + if (*cp == '/') { + cp++; + den = (*cp) - '0'; + break; + } + } + + /* I don't know why the RPX just can't state the actual + * CPU speed..... + */ + if (den) { + num /= den; + num *= den; + } + bd->bi_intfreq = bd->bi_busfreq = num * 1000000; + + /* The 8xx can only run a maximum 50 MHz bus speed (until + * Motorola changes this :-). Greater than 50 MHz parts + * run internal/2 for bus speed. + */ + if (num > 50) + bd->bi_busfreq /= 2; +} +#endif + +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_EP405) +static void +rpx_memsize(bd_t *bd, u_char *cp) +{ + uint size; + + size = 0; + + while (*cp != '\n') { + size *= 10; + size += (*cp) - '0'; + cp++; + } + + bd->bi_memsize = size * 1024 * 1024; +} +#endif /* LITE || CLASSIC || EP405 */ +#if defined(CONFIG_EP405) +static void +rpx_nvramsize(bd_t *bd, u_char *cp) +{ + uint size; + + size = 0; + + while (*cp != '\n') { + size *= 10; + size += (*cp) - '0'; + cp++; + } + + bd->bi_nvramsize = size * 1024; +} +#endif /* CONFIG_EP405 */ + +#endif /* Embedded Planet boards */ + +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) + +/* Read the EEPROM on the RPX-Lite board. +*/ +void +embed_config(bd_t **bdp) +{ + u_char eebuf[256], *cp; + bd_t *bd; + + /* Read the first 256 bytes of the EEPROM. I think this + * is really all there is, and I hope if it gets bigger the + * info we want is still up front. + */ + bd = &bdinfo; + *bdp = bd; + +#if 1 + iic_read(0xa8, eebuf, 0, 128); + iic_read(0xa8, &eebuf[128], 128, 128); + + /* We look for two things, the Ethernet address and the + * serial baud rate. The records are separated by + * newlines. + */ + cp = eebuf; + for (;;) { + if (*cp == 'E') { + cp++; + if (*cp == 'A') { + cp += 2; + rpx_eth(bd, cp); + } + } + if (*cp == 'S') { + cp++; + if (*cp == 'B') { + cp += 2; + rpx_brate(bd, cp); + } + } + if (*cp == 'D') { + cp++; + if (*cp == '1') { + cp += 2; + rpx_memsize(bd, cp); + } + } + if (*cp == 'H') { + cp++; + if (*cp == 'Z') { + cp += 2; + rpx_cpuspeed(bd, cp); + } + } + + /* Scan to the end of the record. + */ + while ((*cp != '\n') && (*cp != 0xff)) + cp++; + + /* If the next character is a 0 or ff, we are done. + */ + cp++; + if ((*cp == 0) || (*cp == 0xff)) + break; + } + bd->bi_memstart = 0; +#else + /* For boards without initialized EEPROM. + */ + bd->bi_memstart = 0; + bd->bi_memsize = (8 * 1024 * 1024); + bd->bi_intfreq = 48000000; + bd->bi_busfreq = 48000000; + bd->bi_baudrate = 9600; +#endif +} +#endif /* RPXLITE || RPXCLASSIC */ + +#ifdef CONFIG_BSEIP +/* Build a board information structure for the BSE ip-Engine. + * There is more to come since we will add some environment + * variables and a function to read them. + */ +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + bd = &bdinfo; + *bdp = bd; + + /* Baud rate and processor speed will eventually come + * from the environment variables. + */ + bd->bi_baudrate = 9600; + + /* Get the Ethernet station address from the Flash ROM. + */ + cp = (u_char *)0xfe003ffa; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } + + /* The rest of this should come from the environment as well. + */ + bd->bi_memstart = 0; + bd->bi_memsize = (16 * 1024 * 1024); + bd->bi_intfreq = 48000000; + bd->bi_busfreq = 48000000; +} +#endif /* BSEIP */ + +#ifdef CONFIG_FADS +/* Build a board information structure for the FADS. + */ +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + bd = &bdinfo; + *bdp = bd; + + /* Just fill in some known values. + */ + bd->bi_baudrate = 9600; + + /* Use default enet. + */ + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } + + bd->bi_memstart = 0; + bd->bi_memsize = (8 * 1024 * 1024); + bd->bi_intfreq = 40000000; + bd->bi_busfreq = 40000000; +} +#endif /* FADS */ + +#ifdef CONFIG_8260 +/* Compute 8260 clock values if the rom doesn't provide them. + */ +static unsigned char bus2core_8260[] = { +/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 3, 2, 2, 2, 4, 4, 5, 9, 6, 11, 8, 10, 3, 12, 7, 2, + 6, 5, 13, 2, 14, 4, 15, 2, 3, 11, 8, 10, 16, 12, 7, 2, +}; + +static void +clk_8260(bd_t *bd) +{ + uint scmr, vco_out, clkin; + uint plldf, pllmf, corecnf; + volatile cpm2_map_t *ip; + + ip = (cpm2_map_t *)CPM_MAP_ADDR; + scmr = ip->im_clkrst.car_scmr; + + /* The clkin is always bus frequency. + */ + clkin = bd->bi_busfreq; + + /* Collect the bits from the scmr. + */ + plldf = (scmr >> 12) & 1; + pllmf = scmr & 0xfff; + corecnf = (scmr >> 24) &0x1f; + + /* This is arithmetic from the 8260 manual. + */ + vco_out = clkin / (plldf + 1); + vco_out *= 2 * (pllmf + 1); + bd->bi_vco = vco_out; /* Save for later */ + + bd->bi_cpmfreq = vco_out / 2; /* CPM Freq, in MHz */ + bd->bi_intfreq = bd->bi_busfreq * bus2core_8260[corecnf] / 2; + + /* Set Baud rate divisor. The power up default is divide by 16, + * but we set it again here in case it was changed. + */ + ip->im_clkrst.car_sccr = 1; /* DIV 16 BRG */ + bd->bi_brgfreq = vco_out / 16; +} + +static unsigned char bus2core_8280[] = { +/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 3, 2, 2, 2, 4, 4, 5, 9, 6, 11, 8, 10, 3, 12, 7, 2, + 6, 5, 13, 2, 14, 2, 15, 2, 3, 2, 2, 2, 16, 2, 2, 2, +}; + +static void +clk_8280(bd_t *bd) +{ + uint scmr, main_clk, clkin; + uint pllmf, corecnf; + volatile cpm2_map_t *ip; + + ip = (cpm2_map_t *)CPM_MAP_ADDR; + scmr = ip->im_clkrst.car_scmr; + + /* The clkin is always bus frequency. + */ + clkin = bd->bi_busfreq; + + /* Collect the bits from the scmr. + */ + pllmf = scmr & 0xf; + corecnf = (scmr >> 24) & 0x1f; + + /* This is arithmetic from the 8280 manual. + */ + main_clk = clkin * (pllmf + 1); + + bd->bi_cpmfreq = main_clk / 2; /* CPM Freq, in MHz */ + bd->bi_intfreq = bd->bi_busfreq * bus2core_8280[corecnf] / 2; + + /* Set Baud rate divisor. The power up default is divide by 16, + * but we set it again here in case it was changed. + */ + ip->im_clkrst.car_sccr = (ip->im_clkrst.car_sccr & 0x3) | 0x1; + bd->bi_brgfreq = main_clk / 16; +} +#endif + +#ifdef CONFIG_SBC82xx +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + unsigned long pvr; + + bd = *bdp; + + bd = &bdinfo; + *bdp = bd; + bd->bi_baudrate = 9600; + bd->bi_memsize = 256 * 1024 * 1024; /* just a guess */ + + cp = (void*)SBC82xx_MACADDR_NVRAM_SCC1; + memcpy(bd->bi_enetaddr, cp, 6); + + /* can busfreq be calculated? */ + pvr = mfspr(SPRN_PVR); + if ((pvr & 0xffff0000) == 0x80820000) { + bd->bi_busfreq = 100000000; + clk_8280(bd); + } else { + bd->bi_busfreq = 66000000; + clk_8260(bd); + } + +} +#endif /* SBC82xx */ + +#if defined(CONFIG_EST8260) || defined(CONFIG_TQM8260) +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + bd = *bdp; +#if 0 + /* This is actually provided by my boot rom. I have it + * here for those people that may load the kernel with + * a JTAG/COP tool and not the rom monitor. + */ + bd->bi_baudrate = 115200; + bd->bi_intfreq = 200000000; + bd->bi_busfreq = 66666666; + bd->bi_cpmfreq = 66666666; + bd->bi_brgfreq = 33333333; + bd->bi_memsize = 16 * 1024 * 1024; +#else + /* The boot rom passes these to us in MHz. Linux now expects + * them to be in Hz. + */ + bd->bi_intfreq *= 1000000; + bd->bi_busfreq *= 1000000; + bd->bi_cpmfreq *= 1000000; + bd->bi_brgfreq *= 1000000; +#endif + + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } +} +#endif /* EST8260 */ + +#ifdef CONFIG_SBS8260 +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + /* This should provided by the boot rom. + */ + bd = &bdinfo; + *bdp = bd; + bd->bi_baudrate = 9600; + bd->bi_memsize = 64 * 1024 * 1024; + + /* Set all of the clocks. We have to know the speed of the + * external clock. The development board had 66 MHz. + */ + bd->bi_busfreq = 66666666; + clk_8260(bd); + + /* I don't know how to compute this yet. + */ + bd->bi_intfreq = 133000000; + + + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } +} +#endif /* SBS8260 */ + +#ifdef CONFIG_RPX8260 +void +embed_config(bd_t **bdp) +{ + u_char *cp, *keyvals; + int i; + bd_t *bd; + + keyvals = (u_char *)*bdp; + + bd = &bdinfo; + *bdp = bd; + + /* This is almost identical to the RPX-Lite/Classic functions + * on the 8xx boards. It would be nice to have a key lookup + * function in a string, but the format of all of the fields + * is slightly different. + */ + cp = keyvals; + for (;;) { + if (*cp == 'E') { + cp++; + if (*cp == 'A') { + cp += 2; + rpx_eth(bd, cp); + } + } + if (*cp == 'S') { + cp++; + if (*cp == 'B') { + cp += 2; + bd->bi_baudrate = rpx_baseten(cp); + } + } + if (*cp == 'D') { + cp++; + if (*cp == '1') { + cp += 2; + bd->bi_memsize = rpx_baseten(cp) * 1024 * 1024; + } + } + if (*cp == 'X') { + cp++; + if (*cp == 'T') { + cp += 2; + bd->bi_busfreq = rpx_baseten(cp); + } + } + if (*cp == 'N') { + cp++; + if (*cp == 'V') { + cp += 2; + bd->bi_nvsize = rpx_baseten(cp) * 1024 * 1024; + } + } + + /* Scan to the end of the record. + */ + while ((*cp != '\n') && (*cp != 0xff)) + cp++; + + /* If the next character is a 0 or ff, we are done. + */ + cp++; + if ((*cp == 0) || (*cp == 0xff)) + break; + } + bd->bi_memstart = 0; + + /* The memory size includes both the 60x and local bus DRAM. + * I don't want to use the local bus DRAM for real memory, + * so subtract it out. It would be nice if they were separate + * keys. + */ + bd->bi_memsize -= 32 * 1024 * 1024; + + /* Set all of the clocks. We have to know the speed of the + * external clock. + */ + clk_8260(bd); + + /* I don't know how to compute this yet. + */ + bd->bi_intfreq = 200000000; +} +#endif /* RPX6 for testing */ + +#ifdef CONFIG_ADS8260 +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + /* This should provided by the boot rom. + */ + bd = &bdinfo; + *bdp = bd; + bd->bi_baudrate = 9600; + bd->bi_memsize = 16 * 1024 * 1024; + + /* Set all of the clocks. We have to know the speed of the + * external clock. The development board had 66 MHz. + */ + bd->bi_busfreq = 66666666; + clk_8260(bd); + + /* I don't know how to compute this yet. + */ + bd->bi_intfreq = 200000000; + + + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } +} +#endif /* ADS8260 */ + +#ifdef CONFIG_WILLOW +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + /* Willow has Open Firmware....I should learn how to get this + * information from it. + */ + bd = &bdinfo; + *bdp = bd; + bd->bi_baudrate = 9600; + bd->bi_memsize = 32 * 1024 * 1024; + + /* Set all of the clocks. We have to know the speed of the + * external clock. The development board had 66 MHz. + */ + bd->bi_busfreq = 66666666; + clk_8260(bd); + + /* I don't know how to compute this yet. + */ + bd->bi_intfreq = 200000000; + + + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } +} +#endif /* WILLOW */ + +#ifdef CONFIG_XILINX_ML300 +void +embed_config(bd_t ** bdp) +{ + static const unsigned long line_size = 32; + static const unsigned long congruence_classes = 256; + unsigned long addr; + unsigned long dccr; + bd_t *bd; + + /* + * Invalidate the data cache if the data cache is turned off. + * - The 405 core does not invalidate the data cache on power-up + * or reset but does turn off the data cache. We cannot assume + * that the cache contents are valid. + * - If the data cache is turned on this must have been done by + * a bootloader and we assume that the cache contents are + * valid. + */ + __asm__("mfdccr %0": "=r" (dccr)); + if (dccr == 0) { + for (addr = 0; + addr < (congruence_classes * line_size); + addr += line_size) { + __asm__("dccci 0,%0": :"b"(addr)); + } + } + + bd = &bdinfo; + *bdp = bd; + bd->bi_memsize = XPAR_DDR_0_SIZE; + bd->bi_intfreq = XPAR_CORE_CLOCK_FREQ_HZ; + bd->bi_busfreq = XPAR_PLB_CLOCK_FREQ_HZ; + bd->bi_pci_busfreq = XPAR_PCI_0_CLOCK_FREQ_HZ; + timebase_period_ns = 1000000000 / bd->bi_tbfreq; + /* see bi_tbfreq definition in arch/ppc/platforms/4xx/xilinx_ml300.h */ +} +#endif /* CONFIG_XILINX_ML300 */ + +#ifdef CONFIG_IBM_OPENBIOS +/* This could possibly work for all treeboot roms. +*/ +#if defined(CONFIG_ASH) || defined(CONFIG_BEECH) || defined(CONFIG_BUBINGA) +#define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */ +#else +#define BOARD_INFO_VECTOR 0xFFFE0B50 +#endif + +#ifdef CONFIG_BEECH +static void +get_board_info(bd_t **bdp) +{ + typedef void (*PFV)(bd_t *bd); + ((PFV)(*(unsigned long *)BOARD_INFO_VECTOR))(*bdp); + return; +} + +void +embed_config(bd_t **bdp) +{ + *bdp = &bdinfo; + get_board_info(bdp); +} +#else /* !CONFIG_BEECH */ +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd, *treeboot_bd; + bd_t *(*get_board_info)(void) = + (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR); +#if !defined(CONFIG_STB03xxx) + + /* shut down the Ethernet controller that the boot rom + * sometimes leaves running. + */ + mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* 1st reset MAL */ + while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */ + out_be32((volatile u32*)EMAC0_BASE,0x20000000); /* then reset EMAC */ +#endif + + bd = &bdinfo; + *bdp = bd; + if ((treeboot_bd = get_board_info()) != NULL) { + memcpy(bd, treeboot_bd, sizeof(bd_t)); + } + else { + /* Hmmm...better try to stuff some defaults. + */ + bd->bi_memsize = 16 * 1024 * 1024; + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + /* I should probably put different ones here, + * hopefully only one is used. + */ + bd->BD_EMAC_ADDR(0,i) = *cp; + +#ifdef CONFIG_PCI + bd->bi_pci_enetaddr[i] = *cp++; +#endif + } + bd->bi_tbfreq = 200 * 1000 * 1000; + bd->bi_intfreq = 200000000; + bd->bi_busfreq = 100000000; +#ifdef CONFIG_PCI + bd->bi_pci_busfreq = 66666666; +#endif + } + /* Yeah, this look weird, but on Redwood 4 they are + * different object in the structure. Sincr Redwwood 5 + * and Redwood 6 use OpenBIOS, it requires a special value. + */ +#if defined(CONFIG_REDWOOD_5) || defined (CONFIG_REDWOOD_6) + bd->bi_tbfreq = 27 * 1000 * 1000; +#endif + timebase_period_ns = 1000000000 / bd->bi_tbfreq; +} +#endif /* CONFIG_BEECH */ +#endif /* CONFIG_IBM_OPENBIOS */ + +#ifdef CONFIG_EP405 +#include + +void +embed_config(bd_t **bdp) +{ + u32 chcr0; + u_char *cp; + bd_t *bd; + + /* Different versions of the PlanetCore firmware vary in how + they set up the serial port - in particular whether they + use the internal or external serial clock for UART0. Make + sure the UART is in a known state. */ + /* FIXME: We should use the board's 11.0592MHz external serial + clock - it will be more accurate for serial rates. For + now, however the baud rates in ep405.h are for the internal + clock. */ + chcr0 = mfdcr(DCRN_CHCR0); + if ( (chcr0 & 0x1fff) != 0x103e ) { + mtdcr(DCRN_CHCR0, (chcr0 & 0xffffe000) | 0x103e); + /* The following tricks serial_init() into resetting the baud rate */ + writeb(0, UART0_IO_BASE + UART_LCR); + } + + /* We haven't seen actual problems with the EP405 leaving the + * EMAC running (as we have on Walnut). But the registers + * suggest it may not be left completely quiescent. Reset it + * just to be sure. */ + mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* 1st reset MAL */ + while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */ + out_be32((unsigned *)EMAC0_BASE,0x20000000); /* then reset EMAC */ + + bd = &bdinfo; + *bdp = bd; +#if 1 + cp = (u_char *)0xF0000EE0; + for (;;) { + if (*cp == 'E') { + cp++; + if (*cp == 'A') { + cp += 2; + rpx_eth(bd, cp); + } + } + + if (*cp == 'D') { + cp++; + if (*cp == '1') { + cp += 2; + rpx_memsize(bd, cp); + } + } + + if (*cp == 'N') { + cp++; + if (*cp == 'V') { + cp += 2; + rpx_nvramsize(bd, cp); + } + } + while ((*cp != '\n') && (*cp != 0xff)) + cp++; + + cp++; + if ((*cp == 0) || (*cp == 0xff)) + break; + } + bd->bi_intfreq = 200000000; + bd->bi_busfreq = 100000000; + bd->bi_pci_busfreq= 33000000 ; +#else + + bd->bi_memsize = 64000000; + bd->bi_intfreq = 200000000; + bd->bi_busfreq = 100000000; + bd->bi_pci_busfreq= 33000000 ; +#endif +} +#endif + +#ifdef CONFIG_RAINIER +/* Rainier uses vxworks bootrom */ +void +embed_config(bd_t **bdp) +{ + u_char *cp; + int i; + bd_t *bd; + + bd = &bdinfo; + *bdp = bd; + + for(i=0;i<8192;i+=32) { + __asm__("dccci 0,%0" :: "r" (i)); + } + __asm__("iccci 0,0"); + __asm__("sync;isync"); + + /* init ram for parity */ + memset(0, 0,0x400000); /* Lo memory */ + + + bd->bi_memsize = (32 * 1024 * 1024) ; + bd->bi_intfreq = 133000000; //the internal clock is 133 MHz + bd->bi_busfreq = 100000000; + bd->bi_pci_busfreq= 33000000; + + cp = (u_char *)def_enet_addr; + for (i=0; i<6; i++) { + bd->bi_enetaddr[i] = *cp++; + } + +} +#endif + diff --git a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S new file mode 100644 index 00000000000..524053202bb --- /dev/null +++ b/arch/ppc/boot/simple/head.S @@ -0,0 +1,142 @@ +/* + * arch/ppc/boot/simple/head.S + * + * Initial board bringup code for many different boards. + * + * Author: Tom Rini + * trini@mvista.com + * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). + * + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include + + .text + +/* + * Begin at some arbitrary location in RAM or Flash + * Initialize core registers + * Configure memory controller (Not executing from RAM) + * Move the boot code to the link address (8M) + * Setup C stack + * Initialize UART + * Decompress the kernel to 0x0 + * Jump to the kernel entry + * + */ + + .globl start +start: + bl start_ +#ifdef CONFIG_IBM_OPENBIOS + /* The IBM "Tree" bootrom knows that the address of the bootrom + * read only structure is 4 bytes after _start. + */ + .long 0x62726f6d # structure ID - "brom" + .long 0x5f726f00 # - "_ro\0" + .long 1 # structure version + .long bootrom_cmdline # address of *bootrom_cmdline +#endif + +start_: +#ifdef CONFIG_FORCE + /* We have some really bad firmware. We must disable the L1 + * icache/dcache now or the board won't boot. + */ + li r4,0x0000 + isync + mtspr SPRN_HID0,r4 + sync + isync +#endif + +#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP) + mr r29,r3 /* On the MBX860, r3 is the board info pointer. + * On the RPXSUPER, r3 points to the NVRAM + * configuration keys. + * On PReP, r3 is the pointer to the residual data. + */ +#endif + + mflr r3 /* Save our actual starting address. */ + + /* The following functions we call must not modify r3 or r4..... + */ +#ifdef CONFIG_6xx + /* On PReP we must look at the OpenFirmware pointer and sanity + * test it. On other platforms, we disable the MMU right now + * and other bits. + */ +#ifdef CONFIG_PPC_PREP +/* + * Save the OF pointer to r25, but only if the entry point is in a sane + * location; if not we store 0. If there is no entry point, or it is + * invalid, we establish the default MSR value immediately. Otherwise, + * we defer doing that, to allow OF functions to be called, until we + * begin uncompressing the kernel. + */ + lis r8,0x0fff /* r8 = 0x0fffffff */ + ori r8,r8,0xffff + + subc r8,r8,r5 /* r8 = (r5 <= r8) ? ~0 : 0 */ + subfe r8,r8,r8 + nand r8,r8,r8 + + and. r5,r5,r8 /* r5 will be cleared if (r5 > r8) */ + bne+ haveOF + + li r8,MSR_IP|MSR_FP /* Not OF: set MSR immediately */ + mtmsr r8 + isync +haveOF: + mr r25,r5 +#else + bl disable_6xx_mmu +#endif + bl disable_6xx_l1cache + + CLEAR_CACHES +#endif + +#ifdef CONFIG_8xx + mfmsr r8 /* Turn off interrupts */ + li r9,0 + ori r9,r9,MSR_EE + andc r8,r8,r9 + mtmsr r8 + + /* We do this because some boot roms don't initialize the + * processor correctly. Don't do this if you want to debug + * using a BDM device. + */ + li r4,0 /* Zero DER to prevent FRZ */ + mtspr SPRN_DER,r4 +#endif + +#ifdef CONFIG_REDWOOD_4 + /* All of this Redwood 4 stuff will soon disappear when the + * boot rom is straightened out. + */ + mr r29, r3 /* Easier than changing the other code */ + bl HdwInit + mr r3, r29 +#endif + +#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP) + mr r4,r29 /* put the board info pointer where the relocate + * routine will find it + */ +#endif + + /* Get the load address. + */ + subi r3, r3, 4 /* Get the actual IP, not NIP */ + b relocate + diff --git a/arch/ppc/boot/simple/iic.c b/arch/ppc/boot/simple/iic.c new file mode 100644 index 00000000000..e4efd838bfa --- /dev/null +++ b/arch/ppc/boot/simple/iic.c @@ -0,0 +1,214 @@ +/* Minimal support functions to read configuration from IIC EEPROMS + * on MPC8xx boards. Originally written for RPGC RPX-Lite. + * Dan Malek (dmalek@jlc.net). + */ +#include +#include +#include +#include + + +/* IIC functions. + * These are just the basic master read/write operations so we can + * examine serial EEPROM. + */ +void iic_read(uint devaddr, u_char *buf, uint offset, uint count); + +static int iic_init_done; + +static void +iic_init(void) +{ + volatile iic_t *iip; + volatile i2c8xx_t *i2c; + volatile cpm8xx_t *cp; + volatile immap_t *immap; + uint dpaddr; + + immap = (immap_t *)IMAP_ADDR; + cp = (cpm8xx_t *)&(immap->im_cpm); + + /* Reset the CPM. This is necessary on the 860 processors + * that may have started the SCC1 ethernet without relocating + * the IIC. + * This also stops the Ethernet in case we were loaded by a + * BOOTP rom monitor. + */ + cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG); + + /* Wait for it. + */ + while (cp->cp_cpcr & (CPM_CR_RST | CPM_CR_FLG)); + + /* Remove any microcode patches. We will install our own + * later. + */ + cp->cp_cpmcr1 = 0; + cp->cp_cpmcr2 = 0; + cp->cp_cpmcr3 = 0; + cp->cp_cpmcr4 = 0; + cp->cp_rccr = 0; + + iip = (iic_t *)&cp->cp_dparam[PROFF_IIC]; + i2c = (i2c8xx_t *)&(immap->im_i2c); + + /* Initialize Port B IIC pins. + */ + cp->cp_pbpar |= 0x00000030; + cp->cp_pbdir |= 0x00000030; + cp->cp_pbodr |= 0x00000030; + + /* Initialize the parameter ram. + */ + + /* Allocate space for a two transmit and one receive buffer + * descriptor in the DP ram. + * For now, this address seems OK, but it may have to + * change with newer versions of the firmware. + */ + dpaddr = 0x0840; + + /* Set up the IIC parameters in the parameter ram. + */ + iip->iic_tbase = dpaddr; + iip->iic_rbase = dpaddr + (2 * sizeof(cbd_t)); + + iip->iic_tfcr = SMC_EB; + iip->iic_rfcr = SMC_EB; + + /* This should really be done by the reader/writer. + */ + iip->iic_mrblr = 128; + + /* Initialize Tx/Rx parameters. + */ + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Select an arbitrary address. Just make sure it is unique. + */ + i2c->i2c_i2add = 0x34; + + /* Make clock run maximum slow. + */ + i2c->i2c_i2brg = 7; + + /* Disable interrupts. + */ + i2c->i2c_i2cmr = 0; + i2c->i2c_i2cer = 0xff; + + /* Enable SDMA. + */ + immap->im_siu_conf.sc_sdcr = 1; + + iic_init_done = 1; +} + +/* Read from IIC. + * Caller provides device address, memory buffer, and byte count. + */ +static u_char iitemp[32]; + +void +iic_read(uint devaddr, u_char *buf, uint offset, uint count) +{ + volatile iic_t *iip; + volatile i2c8xx_t *i2c; + volatile cbd_t *tbdf, *rbdf; + volatile cpm8xx_t *cp; + volatile immap_t *immap; + u_char *tb; + uint temp; + + /* If the interface has not been initialized, do that now. + */ + if (!iic_init_done) + iic_init(); + + immap = (immap_t *)IMAP_ADDR; + cp = (cpm8xx_t *)&(immap->im_cpm); + + iip = (iic_t *)&cp->cp_dparam[PROFF_IIC]; + i2c = (i2c8xx_t *)&(immap->im_i2c); + + tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase]; + rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase]; + + /* Send a "dummy write" operation. This is a write request with + * only the offset sent, followed by another start condition. + * This will ensure we start reading from the first location + * of the EEPROM. + */ + tb = iitemp; + tb = (u_char *)(((uint)tb + 15) & ~15); + tbdf->cbd_bufaddr = (int)tb; + *tb = devaddr & 0xfe; /* Device address */ + *(tb+1) = offset; /* Offset */ + tbdf->cbd_datlen = 2; /* Length */ + tbdf->cbd_sc = + BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START; + + i2c->i2c_i2mod = 1; /* Enable */ + i2c->i2c_i2cer = 0xff; + i2c->i2c_i2com = 0x81; /* Start master */ + + /* Wait for IIC transfer. + */ +#if 0 + while ((i2c->i2c_i2cer & 3) == 0); + + if (tbdf->cbd_sc & BD_SC_READY) + printf("IIC ra complete but tbuf ready\n"); +#else + temp = 10000000; + while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0)) + temp--; +#if 0 + /* We can't do this...there is no serial port yet! + */ + if (temp == 0) { + printf("Timeout reading EEPROM\n"); + return; + } +#endif +#endif + + /* Chip errata, clear enable. + */ + i2c->i2c_i2mod = 0; + + /* To read, we need an empty buffer of the proper length. + * All that is used is the first byte for address, the remainder + * is just used for timing (and doesn't really have to exist). + */ + tbdf->cbd_bufaddr = (int)tb; + *tb = devaddr | 1; /* Device address */ + rbdf->cbd_bufaddr = (uint)buf; /* Desination buffer */ + tbdf->cbd_datlen = rbdf->cbd_datlen = count + 1; /* Length */ + tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START; + rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP; + + /* Chip bug, set enable here. + */ + i2c->i2c_i2mod = 1; /* Enable */ + i2c->i2c_i2cer = 0xff; + i2c->i2c_i2com = 0x81; /* Start master */ + + /* Wait for IIC transfer. + */ +#if 0 + while ((i2c->i2c_i2cer & 1) == 0); + + if (rbdf->cbd_sc & BD_SC_EMPTY) + printf("IIC read complete but rbuf empty\n"); +#else + temp = 10000000; + while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0)) + temp--; +#endif + + /* Chip errata, clear enable. + */ + i2c->i2c_i2mod = 0; +} diff --git a/arch/ppc/boot/simple/m8260_tty.c b/arch/ppc/boot/simple/m8260_tty.c new file mode 100644 index 00000000000..d770947e9b8 --- /dev/null +++ b/arch/ppc/boot/simple/m8260_tty.c @@ -0,0 +1,325 @@ +/* Minimal serial functions needed to send messages out the serial + * port on SMC1. + */ +#include +#include +#include +#include + +uint no_print; +extern char *params[]; +extern int nparams; +static u_char cons_hold[128], *sgptr; +static int cons_hold_cnt; + +/* If defined, enables serial console. The value (1 through 4) + * should designate which SCC is used, but this isn't complete. Only + * SCC1 is known to work at this time. + * We're only linked if SERIAL_CPM_CONSOLE=y, so we only need to test + * SERIAL_CPM_SCC1. + */ +#ifdef CONFIG_SERIAL_CPM_SCC1 +#define SCC_CONSOLE 1 +#endif + +unsigned long +serial_init(int ignored, bd_t *bd) +{ +#ifdef SCC_CONSOLE + volatile scc_t *sccp; + volatile scc_uart_t *sup; +#else + volatile smc_t *sp; + volatile smc_uart_t *up; +#endif + volatile cbd_t *tbdf, *rbdf; + volatile cpm2_map_t *ip; + volatile iop_cpm2_t *io; + volatile cpm_cpm2_t *cp; + uint dpaddr, memaddr; + + ip = (cpm2_map_t *)CPM_MAP_ADDR; + cp = &ip->im_cpm; + io = &ip->im_ioport; + + /* Perform a reset. + */ + cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG); + + /* Wait for it. + */ + while (cp->cp_cpcr & CPM_CR_FLG); + +#ifdef CONFIG_ADS8260 + /* Enable the RS-232 transceivers. + */ + *(volatile uint *)(BCSR_ADDR + 4) &= + ~(BCSR1_RS232_EN1 | BCSR1_RS232_EN2); +#endif + +#ifdef SCC_CONSOLE + sccp = (scc_t *)&(ip->im_scc[SCC_CONSOLE-1]); + sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)]; + sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); + sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + /* Use Port D for SCC1 instead of other functions. + */ + io->iop_ppard |= 0x00000003; + io->iop_psord &= ~0x00000001; /* Rx */ + io->iop_psord |= 0x00000002; /* Tx */ + io->iop_pdird &= ~0x00000001; /* Rx */ + io->iop_pdird |= 0x00000002; /* Tx */ + +#else + sp = (smc_t*)&(ip->im_smc[0]); + *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1; + up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1]; + + /* Disable transmitter/receiver. + */ + sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); + + /* Use Port D for SMC1 instead of other functions. + */ + io->iop_ppard |= 0x00c00000; + io->iop_pdird |= 0x00400000; + io->iop_pdird &= ~0x00800000; + io->iop_psord &= ~0x00c00000; +#endif + + /* Allocate space for two buffer descriptors in the DP ram. + * For now, this address seems OK, but it may have to + * change with newer versions of the firmware. + */ + dpaddr = 0x0800; + + /* Grab a few bytes from the top of memory. + */ + memaddr = (bd->bi_memsize - 256) & ~15; + + /* Set the physical address of the host memory buffers in + * the buffer descriptors. + */ + rbdf = (cbd_t *)&ip->im_dprambase[dpaddr]; + rbdf->cbd_bufaddr = memaddr; + rbdf->cbd_sc = 0; + tbdf = rbdf + 1; + tbdf->cbd_bufaddr = memaddr+128; + tbdf->cbd_sc = 0; + + /* Set up the uart parameters in the parameter ram. + */ +#ifdef SCC_CONSOLE + sup->scc_genscc.scc_rbase = dpaddr; + sup->scc_genscc.scc_tbase = dpaddr + sizeof(cbd_t); + + /* Set up the uart parameters in the + * parameter ram. + */ + sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB; + sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB; + + sup->scc_genscc.scc_mrblr = 128; + sup->scc_maxidl = 8; + sup->scc_brkcr = 1; + sup->scc_parec = 0; + sup->scc_frmec = 0; + sup->scc_nosec = 0; + sup->scc_brkec = 0; + sup->scc_uaddr1 = 0; + sup->scc_uaddr2 = 0; + sup->scc_toseq = 0; + sup->scc_char1 = 0x8000; + sup->scc_char2 = 0x8000; + sup->scc_char3 = 0x8000; + sup->scc_char4 = 0x8000; + sup->scc_char5 = 0x8000; + sup->scc_char6 = 0x8000; + sup->scc_char7 = 0x8000; + sup->scc_char8 = 0x8000; + sup->scc_rccm = 0xc0ff; + + /* Send the CPM an initialize command. + */ + cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0, + CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sccp->scc_gsmrh = 0; + sccp->scc_gsmrl = + (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); + + /* Disable all interrupts and clear all pending + * events. + */ + sccp->scc_sccm = 0; + sccp->scc_scce = 0xffff; + sccp->scc_dsr = 0x7e7e; + sccp->scc_psmr = 0x3000; + + /* Wire BRG1 to SCC1. The console driver will take care of + * others. + */ + ip->im_cpmux.cmx_scr = 0; +#else + up->smc_rbase = dpaddr; + up->smc_tbase = dpaddr+sizeof(cbd_t); + up->smc_rfcr = CPMFCR_EB; + up->smc_tfcr = CPMFCR_EB; + up->smc_brklen = 0; + up->smc_brkec = 0; + up->smc_brkcr = 0; + up->smc_mrblr = 128; + up->smc_maxidl = 8; + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + + /* Mask all interrupts and remove anything pending. + */ + sp->smc_smcm = 0; + sp->smc_smce = 0xff; + + /* Set up the baud rate generator. + */ + ip->im_cpmux.cmx_smr = 0; +#endif + + /* The baud rate divisor needs to be coordinated with clk_8260(). + */ + ip->im_brgc1 = + (((bd->bi_brgfreq/16) / bd->bi_baudrate) << 1) | + CPM_BRG_EN; + + /* Make the first buffer the only buffer. + */ + tbdf->cbd_sc |= BD_SC_WRAP; + rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; + + /* Initialize Tx/Rx parameters. + */ +#ifdef SCC_CONSOLE + sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#else + cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Enable transmitter/receiver. + */ + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; +#endif + + /* This is ignored. + */ + return 0; +} + +int +serial_readbuf(u_char *cbuf) +{ + volatile cbd_t *rbdf; + volatile char *buf; +#ifdef SCC_CONSOLE + volatile scc_uart_t *sup; +#else + volatile smc_uart_t *up; +#endif + volatile cpm2_map_t *ip; + int i, nc; + + ip = (cpm2_map_t *)CPM_MAP_ADDR; + +#ifdef SCC_CONSOLE + sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)]; + rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase]; +#else + up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]); + rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase]; +#endif + + /* Wait for character to show up. + */ + buf = (char *)rbdf->cbd_bufaddr; + while (rbdf->cbd_sc & BD_SC_EMPTY); + nc = rbdf->cbd_datlen; + for (i=0; icbd_sc |= BD_SC_EMPTY; + + return(nc); +} + +void +serial_putc(void *ignored, const char c) +{ + volatile cbd_t *tbdf; + volatile char *buf; +#ifdef SCC_CONSOLE + volatile scc_uart_t *sup; +#else + volatile smc_uart_t *up; +#endif + volatile cpm2_map_t *ip; + + ip = (cpm2_map_t *)CPM_MAP_ADDR; +#ifdef SCC_CONSOLE + sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)]; + tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase]; +#else + up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]); + tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase]; +#endif + + /* Wait for last character to go. + */ + buf = (char *)tbdf->cbd_bufaddr; + while (tbdf->cbd_sc & BD_SC_READY); + + *buf = c; + tbdf->cbd_datlen = 1; + tbdf->cbd_sc |= BD_SC_READY; +} + +char +serial_getc(void *ignored) +{ + char c; + + if (cons_hold_cnt <= 0) { + cons_hold_cnt = serial_readbuf(cons_hold); + sgptr = cons_hold; + } + c = *sgptr++; + cons_hold_cnt--; + + return(c); +} + +int +serial_tstc(void *ignored) +{ + volatile cbd_t *rbdf; +#ifdef SCC_CONSOLE + volatile scc_uart_t *sup; +#else + volatile smc_uart_t *up; +#endif + volatile cpm2_map_t *ip; + + ip = (cpm2_map_t *)CPM_MAP_ADDR; +#ifdef SCC_CONSOLE + sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)]; + rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase]; +#else + up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]); + rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase]; +#endif + + return(!(rbdf->cbd_sc & BD_SC_EMPTY)); +} diff --git a/arch/ppc/boot/simple/m8xx_tty.c b/arch/ppc/boot/simple/m8xx_tty.c new file mode 100644 index 00000000000..1d2778e248c --- /dev/null +++ b/arch/ppc/boot/simple/m8xx_tty.c @@ -0,0 +1,290 @@ +/* Minimal serial functions needed to send messages out the serial + * port on the MBX console. + * + * The MBX uxes SMC1 for the serial port. We reset the port and use + * only the first BD that EPPC-Bug set up as a character FIFO. + * + * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug + * use COM1 instead of SMC1 as the console port. This kinda sucks + * for the rest of the kernel, so here we force the use of SMC1 again. + */ +#include +#include +#include +#include +#include + +#ifdef CONFIG_MBX +#define MBX_CSR1 ((volatile u_char *)0xfa100000) +#define CSR1_COMEN (u_char)0x02 +#endif + +#ifdef TQM_SMC2_CONSOLE +#define PROFF_CONS PROFF_SMC2 +#define CPM_CR_CH_CONS CPM_CR_CH_SMC2 +#define SMC_INDEX 1 +static volatile iop8xx_t *iopp = (iop8xx_t *)&(((immap_t *)IMAP_ADDR)->im_ioport); +#else +#define PROFF_CONS PROFF_SMC1 +#define CPM_CR_CH_CONS CPM_CR_CH_SMC1 +#define SMC_INDEX 0 +#endif + +static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); + +unsigned long +serial_init(int ignored, bd_t *bd) +{ + volatile smc_t *sp; + volatile smc_uart_t *up; + volatile cbd_t *tbdf, *rbdf; + volatile cpm8xx_t *cp; + uint dpaddr, memaddr; +#ifndef CONFIG_MBX + uint ui; +#endif + + cp = cpmp; + sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]); + up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS]; + + /* Disable transmitter/receiver. + */ + sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); + +#ifdef CONFIG_FADS + /* Enable SMC1/2 transceivers. + */ + *((volatile uint *)BCSR1) &= ~(BCSR1_RS232EN_1|BCSR1_RS232EN_2); +#endif + +#ifndef CONFIG_MBX + { + /* Initialize SMCx and use it for the console port. + */ + + /* Enable SDMA. + */ + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; + +#ifdef TQM_SMC2_CONSOLE + /* Use Port A for SMC2 instead of other functions. + */ + iopp->iop_papar |= 0x00c0; + iopp->iop_padir &= ~0x00c0; + iopp->iop_paodr &= ~0x00c0; +#else + /* Use Port B for SMCs instead of other functions. + */ + cp->cp_pbpar |= 0x00000cc0; + cp->cp_pbdir &= ~0x00000cc0; + cp->cp_pbodr &= ~0x00000cc0; +#endif + + /* Allocate space for two buffer descriptors in the DP ram. + * For now, this address seems OK, but it may have to + * change with newer versions of the firmware. + */ + dpaddr = 0x0800; + + /* Grab a few bytes from the top of memory for SMC FIFOs. + */ + memaddr = (bd->bi_memsize - 32) & ~15; + + /* Set the physical address of the host memory buffers in + * the buffer descriptors. + */ + rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr]; + rbdf->cbd_bufaddr = memaddr; + rbdf->cbd_sc = 0; + tbdf = rbdf + 1; + tbdf->cbd_bufaddr = memaddr+4; + tbdf->cbd_sc = 0; + + /* Set up the uart parameters in the parameter ram. + */ + up->smc_rbase = dpaddr; + up->smc_tbase = dpaddr+sizeof(cbd_t); + up->smc_rfcr = SMC_EB; + up->smc_tfcr = SMC_EB; + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + + /* Mask all interrupts and remove anything pending. + */ + sp->smc_smcm = 0; + sp->smc_smce = 0xff; + + /* Set up the baud rate generator. + * See 8xx_io/commproc.c for details. + * This wires BRG1 to SMC1 and BRG2 to SMC2; + */ + cp->cp_simode = 0x10000000; + ui = bd->bi_intfreq / 16 / bd->bi_baudrate; +#ifdef TQM_SMC2_CONSOLE + cp->cp_brgc2 = +#else + cp->cp_brgc1 = +#endif + ((ui - 1) < 4096) + ? (((ui - 1) << 1) | CPM_BRG_EN) + : ((((ui / 16) - 1) << 1) | CPM_BRG_EN | CPM_BRG_DIV16); + +#else /* CONFIG_MBX */ + if (*MBX_CSR1 & CSR1_COMEN) { + /* COM1 is enabled. Initialize SMC1 and use it for + * the console port. + */ + + /* Enable SDMA. + */ + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; + + /* Use Port B for SMCs instead of other functions. + */ + cp->cp_pbpar |= 0x00000cc0; + cp->cp_pbdir &= ~0x00000cc0; + cp->cp_pbodr &= ~0x00000cc0; + + /* Allocate space for two buffer descriptors in the DP ram. + * For now, this address seems OK, but it may have to + * change with newer versions of the firmware. + */ + dpaddr = 0x0800; + + /* Grab a few bytes from the top of memory. EPPC-Bug isn't + * running any more, so we can do this. + */ + memaddr = (bd->bi_memsize - 32) & ~15; + + /* Set the physical address of the host memory buffers in + * the buffer descriptors. + */ + rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr]; + rbdf->cbd_bufaddr = memaddr; + rbdf->cbd_sc = 0; + tbdf = rbdf + 1; + tbdf->cbd_bufaddr = memaddr+4; + tbdf->cbd_sc = 0; + + /* Set up the uart parameters in the parameter ram. + */ + up->smc_rbase = dpaddr; + up->smc_tbase = dpaddr+sizeof(cbd_t); + up->smc_rfcr = SMC_EB; + up->smc_tfcr = SMC_EB; + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + + /* Mask all interrupts and remove anything pending. + */ + sp->smc_smcm = 0; + sp->smc_smce = 0xff; + + /* Set up the baud rate generator. + * See 8xx_io/commproc.c for details. + */ + cp->cp_simode = 0x10000000; + cp->cp_brgc1 = + (((bd->bi_intfreq/16) / 9600) << 1) | CPM_BRG_EN; + + /* Enable SMC1 for console output. + */ + *MBX_CSR1 &= ~CSR1_COMEN; + } + else { +#endif /* ndef CONFIG_MBX */ + /* SMCx is used as console port. + */ + tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase]; + rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase]; + + /* Issue a stop transmit, and wait for it. + */ + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, + CPM_CR_STOP_TX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + } + + /* Make the first buffer the only buffer. + */ + tbdf->cbd_sc |= BD_SC_WRAP; + rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; + + /* Single character receive. + */ + up->smc_mrblr = 1; + up->smc_maxidl = 0; + + /* Initialize Tx/Rx parameters. + */ + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Enable transmitter/receiver. + */ + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; + + /* This is ignored. + */ + return 0; +} + +void +serial_putc(void *ignored, const char c) +{ + volatile cbd_t *tbdf; + volatile char *buf; + volatile smc_uart_t *up; + + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; + tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; + + /* Wait for last character to go. + */ + buf = (char *)tbdf->cbd_bufaddr; + while (tbdf->cbd_sc & BD_SC_READY); + + *buf = c; + tbdf->cbd_datlen = 1; + tbdf->cbd_sc |= BD_SC_READY; +} + +char +serial_getc(void *ignored) +{ + volatile cbd_t *rbdf; + volatile char *buf; + volatile smc_uart_t *up; + char c; + + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; + rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; + + /* Wait for character to show up. + */ + buf = (char *)rbdf->cbd_bufaddr; + while (rbdf->cbd_sc & BD_SC_EMPTY); + c = *buf; + rbdf->cbd_sc |= BD_SC_EMPTY; + + return(c); +} + +int +serial_tstc(void *ignored) +{ + volatile cbd_t *rbdf; + volatile smc_uart_t *up; + + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; + rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; + + return(!(rbdf->cbd_sc & BD_SC_EMPTY)); +} diff --git a/arch/ppc/boot/simple/misc-chestnut.c b/arch/ppc/boot/simple/misc-chestnut.c new file mode 100644 index 00000000000..0dce7f3557e --- /dev/null +++ b/arch/ppc/boot/simple/misc-chestnut.c @@ -0,0 +1,35 @@ +/* + * arch/ppc/boot/simple/misc-chestnut.c + * + * Setup for the IBM Chestnut (ibm-750fxgx_eval) + * + * Author: Mark A. Greer + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include + +/* Not in the kernel so won't include kernel.h to get its 'max' definition */ +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +void +mv64x60_board_init(void __iomem *old_base, void __iomem *new_base) +{ +#ifdef CONFIG_SERIAL_8250_CONSOLE + /* + * Change device bus 2 window so that bootoader can do I/O thru + * 8250/16550 UART that's mapped in that window. + */ + out_le32(new_base + MV64x60_CPU2DEV_2_BASE, CHESTNUT_UART_BASE >> 16); + out_le32(new_base + MV64x60_CPU2DEV_2_SIZE, CHESTNUT_UART_SIZE >> 16); + __asm__ __volatile__("sync"); +#endif +} diff --git a/arch/ppc/boot/simple/misc-cpci690.c b/arch/ppc/boot/simple/misc-cpci690.c new file mode 100644 index 00000000000..ef08e86c9b2 --- /dev/null +++ b/arch/ppc/boot/simple/misc-cpci690.c @@ -0,0 +1,27 @@ +/* + * arch/ppc/boot/simple/misc-cpci690.c + * + * Add birec data for Force CPCI690 board. + * + * Author: Mark A. Greer + * + * 2003 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include + +extern u32 mv64x60_console_baud; +extern u32 mv64x60_mpsc_clk_src; +extern u32 mv64x60_mpsc_clk_freq; + +void +mv64x60_board_init(void __iomem *old_base, void __iomem *new_base) +{ + mv64x60_console_baud = CPCI690_MPSC_BAUD; + mv64x60_mpsc_clk_src = CPCI690_MPSC_CLK_SRC; + mv64x60_mpsc_clk_freq = CPCI690_BUS_FREQ; +} diff --git a/arch/ppc/boot/simple/misc-embedded.c b/arch/ppc/boot/simple/misc-embedded.c new file mode 100644 index 00000000000..3865f3f8dcd --- /dev/null +++ b/arch/ppc/boot/simple/misc-embedded.c @@ -0,0 +1,275 @@ +/* + * Originally adapted by Gary Thomas. Much additional work by + * Cort Dougan . On top of that still more work by + * Dan Malek . + * + * Currently maintained by: Tom Rini + */ + +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_4xx) +#include +#elif defined(CONFIG_8xx) +#include +#elif defined(CONFIG_8260) +#include +#endif + +#include "nonstdio.h" + +/* The linker tells us where the image is. */ +extern char __image_begin, __image_end; +extern char __ramdisk_begin, __ramdisk_end; +extern char _end[]; + +/* Because of the limited amount of memory on embedded, it presents + * loading problems. The biggest is that we load this boot program + * into a relatively low memory address, and the Linux kernel Bss often + * extends into this space when it get loaded. When the kernel starts + * and zeros the BSS space, it also writes over the information we + * save here and pass to the kernel (usually board info). + * On these boards, we grab some known memory holes to hold this information. + */ +char cmd_buf[256]; +char *cmd_line = cmd_buf; +char *avail_ram; +char *end_avail; +char *zimage_start; + +/* This is for 4xx treeboot. It provides a place for the bootrom + * give us a pointer to a rom environment command line. + */ +char *bootrom_cmdline = ""; + +/* This is the default cmdline that will be given to the user at boot time.. + * If none was specified at compile time, we'll give it one that should work. + * -- Tom */ +#ifdef CONFIG_CMDLINE_BOOL +char compiled_string[] = CONFIG_CMDLINE; +#endif +char ramroot_string[] = "root=/dev/ram"; +char netroot_string[] = "root=/dev/nfs rw ip=on"; + +/* Serial port to use. */ +unsigned long com_port; + +/* We need to make sure that this is before the images to ensure + * that it's in a mapped location. - Tom */ +bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot"))); +bd_t *hold_residual = &hold_resid_buf; + +extern unsigned long serial_init(int chan, bd_t *bp); +extern void serial_close(unsigned long com_port); +extern unsigned long start; +extern void flush_instruction_cache(void); +extern void gunzip(void *, int, unsigned char *, int *); +extern void embed_config(bd_t **bp); + +/* Weak function for boards which don't need to build the + * board info struct because they are using PPCBoot/U-Boot. + */ +void __attribute__ ((weak)) +embed_config(bd_t **bdp) +{ +} + +unsigned long +load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp) +{ + char *cp, ch; + int timer = 0, zimage_size; + unsigned long initrd_size; + + /* First, capture the embedded board information. Then + * initialize the serial console port. + */ + embed_config(&bp); +#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) + com_port = serial_init(0, bp); +#endif + + /* Grab some space for the command line and board info. Since + * we no longer use the ELF header, but it was loaded, grab + * that space. + */ +#ifdef CONFIG_MBX + /* Because of the way the MBX loads the ELF image, we can't + * tell where we started. We read a magic variable from the NVRAM + * that gives us the intermediate buffer load address. + */ + load_addr = *(uint *)0xfa000020; + load_addr += 0x10000; /* Skip ELF header */ +#endif + /* copy board data */ + if (bp) + memcpy(hold_residual,bp,sizeof(bd_t)); + + /* Set end of memory available to us. It is always the highest + * memory address provided by the board information. + */ + end_avail = (char *)(bp->bi_memsize); + + puts("\nloaded at: "); puthex(load_addr); + puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); + if ( (unsigned long)load_addr != (unsigned long)&start ) { + puts("relocated to: "); puthex((unsigned long)&start); + puts(" "); + puthex((unsigned long)((unsigned long)&start + (4*num_words))); + puts("\n"); + } + + if ( bp ) { + puts("board data at: "); puthex((unsigned long)bp); + puts(" "); + puthex((unsigned long)((unsigned long)bp + sizeof(bd_t))); + puts("\nrelocated to: "); + puthex((unsigned long)hold_residual); + puts(" "); + puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t))); + puts("\n"); + } + + /* + * We link ourself to an arbitrary low address. When we run, we + * relocate outself to that address. __image_being points to + * the part of the image where the zImage is. -- Tom + */ + zimage_start = (char *)(unsigned long)(&__image_begin); + zimage_size = (unsigned long)(&__image_end) - + (unsigned long)(&__image_begin); + + initrd_size = (unsigned long)(&__ramdisk_end) - + (unsigned long)(&__ramdisk_begin); + + /* + * The zImage and initrd will be between start and _end, so they've + * already been moved once. We're good to go now. -- Tom + */ + puts("zimage at: "); puthex((unsigned long)zimage_start); + puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); + puts("\n"); + + if ( initrd_size ) { + puts("initrd at: "); + puthex((unsigned long)(&__ramdisk_begin)); + puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); + } + + /* + * setup avail_ram - this is the first part of ram usable + * by the uncompress code. Anything after this program in RAM + * is now fair game. -- Tom + */ + avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); + + puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); + puthex((unsigned long)end_avail); puts("\n"); + puts("\nLinux/PPC load: "); + cp = cmd_line; + /* This is where we try and pick the right command line for booting. + * If we were given one at compile time, use it. It Is Right. + * If we weren't, see if we have a ramdisk. If so, thats root. + * When in doubt, give them the netroot (root=/dev/nfs rw) -- Tom + */ +#ifdef CONFIG_CMDLINE_BOOL + memcpy (cmd_line, compiled_string, sizeof(compiled_string)); +#else + if ( initrd_size ) + memcpy (cmd_line, ramroot_string, sizeof(ramroot_string)); + else + memcpy (cmd_line, netroot_string, sizeof(netroot_string)); +#endif + while ( *cp ) + putc(*cp++); + while (timer++ < 5*1000) { + if (tstc()) { + while ((ch = getc()) != '\n' && ch != '\r') { + if (ch == '\b' || ch == '\177') { + if (cp != cmd_line) { + cp--; + puts("\b \b"); + } + } else if (ch == '\030' /* ^x */ + || ch == '\025') { /* ^u */ + while (cp != cmd_line) { + cp--; + puts("\b \b"); + } + } else { + *cp++ = ch; + putc(ch); + } + } + break; /* Exit 'timer' loop */ + } + udelay(1000); /* 1 msec */ + } + *cp = 0; + puts("\nUncompressing Linux..."); + + gunzip(0, 0x400000, zimage_start, &zimage_size); + flush_instruction_cache(); + puts("done.\n"); + { + struct bi_record *rec; + unsigned long initrd_loc = 0; + unsigned long rec_loc = _ALIGN((unsigned long)(zimage_size) + + (1 << 20) - 1, (1 << 20)); + rec = (struct bi_record *)rec_loc; + + /* We need to make sure that the initrd and bi_recs do not + * overlap. */ + if ( initrd_size ) { + initrd_loc = (unsigned long)(&__ramdisk_begin); + /* If the bi_recs are in the middle of the current + * initrd, move the initrd to the next MB + * boundary. */ + if ((rec_loc > initrd_loc) && + ((initrd_loc + initrd_size) + > rec_loc)) { + initrd_loc = _ALIGN((unsigned long)(zimage_size) + + (2 << 20) - 1, (2 << 20)); + memmove((void *)initrd_loc, &__ramdisk_begin, + initrd_size); + puts("initrd moved: "); puthex(initrd_loc); + puts(" "); puthex(initrd_loc + initrd_size); + puts("\n"); + } + } + + rec->tag = BI_FIRST; + rec->size = sizeof(struct bi_record); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + rec->tag = BI_CMD_LINE; + memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); + rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + if ( initrd_size ) { + rec->tag = BI_INITRD; + rec->data[0] = initrd_loc; + rec->data[1] = initrd_size; + rec->size = sizeof(struct bi_record) + 2 * + sizeof(unsigned long); + rec = (struct bi_record *)((unsigned long)rec + + rec->size); + } + + rec->tag = BI_LAST; + rec->size = sizeof(struct bi_record); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + } + puts("Now booting the kernel\n"); +#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) + serial_close(com_port); +#endif + + return (unsigned long)hold_residual; +} diff --git a/arch/ppc/boot/simple/misc-ev64260.c b/arch/ppc/boot/simple/misc-ev64260.c new file mode 100644 index 00000000000..52ece6937a7 --- /dev/null +++ b/arch/ppc/boot/simple/misc-ev64260.c @@ -0,0 +1,57 @@ +/* + * arch/ppc/boot/simple/misc-ev64260.c + * + * Host bridge init code for the Marvell/Galileo EV-64260-BP evaluation board + * with a GT64260 onboard. + * + * Author: Mark A. Greer + * + * 2001 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SERIAL_MPSC_CONSOLE +extern u32 mv64x60_console_baud; +extern u32 mv64x60_mpsc_clk_src; +extern u32 mv64x60_mpsc_clk_freq; +#endif + +void +mv64x60_board_init(void __iomem *old_base, void __iomem *new_base) +{ + u32 p, v; + + /* DINK doesn't enable 745x timebase, so enable here (Adrian Cox) */ + p = mfspr(SPRN_PVR); + p >>= 16; + + /* Reasonable SWAG at a 745x PVR value */ + if (((p & 0xfff0) == 0x8000) && (p != 0x800c)) { + v = mfspr(SPRN_HID0); + v |= HID0_TBEN; + mtspr(SPRN_HID0, v); + } + +#ifdef CONFIG_SERIAL_8250_CONSOLE + /* + * Change device bus 2 window so that bootoader can do I/O thru + * 8250/16550 UART that's mapped in that window. + */ + out_le32(new_base + MV64x60_CPU2DEV_2_BASE, EV64260_UART_BASE >> 20); + out_le32(new_base + MV64x60_CPU2DEV_2_SIZE, EV64260_UART_END >> 20); + __asm__ __volatile__("sync"); +#elif defined(CONFIG_SERIAL_MPSC_CONSOLE) + mv64x60_console_baud = EV64260_DEFAULT_BAUD; + mv64x60_mpsc_clk_src = EV64260_MPSC_CLK_SRC; + mv64x60_mpsc_clk_freq = EV64260_MPSC_CLK_FREQ; +#endif +} diff --git a/arch/ppc/boot/simple/misc-katana.c b/arch/ppc/boot/simple/misc-katana.c new file mode 100644 index 00000000000..b6e1bb83315 --- /dev/null +++ b/arch/ppc/boot/simple/misc-katana.c @@ -0,0 +1,37 @@ +/* + * arch/ppc/boot/simple/misc-katana.c + * + * Set up MPSC values to bootwrapper can prompt user. + * + * Author: Mark A. Greer + * + * 2004 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include + +extern u32 mv64x60_console_baud; +extern u32 mv64x60_mpsc_clk_src; +extern u32 mv64x60_mpsc_clk_freq; + +/* Not in the kernel so won't include kernel.h to get its 'min' definition */ +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +void +mv64x60_board_init(void __iomem *old_base, void __iomem *new_base) +{ + mv64x60_console_baud = KATANA_DEFAULT_BAUD; + mv64x60_mpsc_clk_src = KATANA_MPSC_CLK_SRC; + mv64x60_mpsc_clk_freq = + min(katana_bus_freq((void __iomem *)KATANA_CPLD_BASE), + MV64x60_TCLK_FREQ_MAX); +} diff --git a/arch/ppc/boot/simple/misc-mv64x60.c b/arch/ppc/boot/simple/misc-mv64x60.c new file mode 100644 index 00000000000..7e88fc6d207 --- /dev/null +++ b/arch/ppc/boot/simple/misc-mv64x60.c @@ -0,0 +1,61 @@ +/* + * arch/ppc/boot/simple/misc-mv64x60.c + * + * Relocate bridge's register base and call board specific routine. + * + * Author: Mark A. Greer + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include + +extern struct bi_record *decompress_kernel(unsigned long load_addr, + int num_words, unsigned long cksum); + +void +mv64x60_move_base(void __iomem *old_base, void __iomem *new_base) +{ + u32 bits, mask, b; + + if (old_base != new_base) { +#ifdef CONFIG_GT64260 + bits = 12; + mask = 0x07000000; +#else /* Must be mv64[34]60 */ + bits = 16; + mask = 0x03000000; +#endif + b = in_le32(old_base + MV64x60_INTERNAL_SPACE_DECODE); + b &= mask; + b |= ((u32)new_base >> (32 - bits)); + out_le32(old_base + MV64x60_INTERNAL_SPACE_DECODE, b); + + __asm__ __volatile__("sync"); + + /* Wait for change to happen (in accordance with the manual) */ + while (in_le32(new_base + MV64x60_INTERNAL_SPACE_DECODE) != b); + } +} + +void __attribute__ ((weak)) +mv64x60_board_init(void __iomem *old_base, void __iomem *new_base) +{ +} + +void * +load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, + void *ign1, void *ign2) +{ + mv64x60_move_base((void __iomem *)CONFIG_MV64X60_BASE, + (void __iomem *)CONFIG_MV64X60_NEW_BASE); + mv64x60_board_init((void __iomem *)CONFIG_MV64X60_BASE, + (void __iomem *)CONFIG_MV64X60_NEW_BASE); + return decompress_kernel(load_addr, num_words, cksum); +} diff --git a/arch/ppc/boot/simple/misc-prep.c b/arch/ppc/boot/simple/misc-prep.c new file mode 100644 index 00000000000..75380ac4166 --- /dev/null +++ b/arch/ppc/boot/simple/misc-prep.c @@ -0,0 +1,212 @@ +/* + * arch/ppc/boot/simple/misc-prep.c + * + * Maintainer: Tom Rini + * + * In the past: Gary Thomas, Cort Dougan + */ + +#include +#include +#include +#include +#include +#include +#include "mpc10x.h" +#include "of1275.h" +#include "nonstdio.h" + +extern int keyb_present; /* keyboard controller is present by default */ +RESIDUAL hold_resid_buf; +RESIDUAL *hold_residual = &hold_resid_buf; +static void *OFW_interface; /* Pointer to OF, if available. */ + +#ifdef CONFIG_VGA_CONSOLE +char *vidmem = (char *)0xC00B8000; +int lines = 25, cols = 80; +int orig_x, orig_y = 24; +#endif /* CONFIG_VGA_CONSOLE */ + +extern int CRT_tstc(void); +extern int vga_init(unsigned char *ISA_mem); +extern void gunzip(void *, int, unsigned char *, int *); +extern unsigned long serial_init(int chan, void *ignored); +extern void serial_fixups(void); +extern struct bi_record *decompress_kernel(unsigned long load_addr, + int num_words, unsigned long cksum); +extern void disable_6xx_mmu(void); +extern unsigned long mpc10x_get_mem_size(void); + +static void +writel(unsigned int val, unsigned int address) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + *(unsigned int *)address = cpu_to_le32(val); +} + +#define PCI_CFG_ADDR(dev,off) ((0x80<<24) | (dev<<8) | (off&0xfc)) +#define PCI_CFG_DATA(off) (MPC10X_MAPA_CNFG_DATA+(off&3)) + +static void +pci_read_config_32(unsigned char devfn, + unsigned char offset, + unsigned int *val) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + *(unsigned int *)PCI_CFG_ADDR(devfn,offset) = + cpu_to_le32(MPC10X_MAPA_CNFG_ADDR); + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + *val = le32_to_cpu(*(unsigned int *)PCI_CFG_DATA(offset)); + return; +} + +#ifdef CONFIG_VGA_CONSOLE +void +scroll(void) +{ + int i; + + memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 ); + for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) + vidmem[i] = ' '; +} +#endif /* CONFIG_VGA_CONSOLE */ + +unsigned long +load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, + RESIDUAL *residual, void *OFW) +{ + int start_multi = 0; + unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base; + + /* If we have Open Firmware, initialise it immediately */ + if (OFW) { + OFW_interface = OFW; + ofinit(OFW_interface); + } + + board_isa_init(); +#if defined(CONFIG_VGA_CONSOLE) + vga_init((unsigned char *)0xC0000000); +#endif /* CONFIG_VGA_CONSOLE */ + + if (residual) { + /* Is this Motorola PPCBug? */ + if ((1 & residual->VitalProductData.FirmwareSupports) && + (1 == residual->VitalProductData.FirmwareSupplier)) { + unsigned char base_mod; + unsigned char board_type = inb(0x801) & 0xF0; + + /* + * Reset the onboard 21x4x Ethernet + * Motorola Ethernet is at IDSEL 14 (devfn 0x70) + */ + pci_read_config_32(0x70, 0x00, &pci_viddid); + pci_did = (pci_viddid & 0xffff0000) >> 16; + /* Be sure we've really found a 21x4x chip */ + if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_DEC) && + ((pci_did == PCI_DEVICE_ID_DEC_TULIP_FAST) || + (pci_did == PCI_DEVICE_ID_DEC_TULIP) || + (pci_did == PCI_DEVICE_ID_DEC_TULIP_PLUS) || + (pci_did == PCI_DEVICE_ID_DEC_21142))) { + pci_read_config_32(0x70, + 0x10, + &tulip_pci_base); + /* Get the physical base address */ + tulip_base = + (tulip_pci_base & ~0x03UL) + 0x80000000; + /* Strobe the 21x4x reset bit in CSR0 */ + writel(0x1, tulip_base); + } + + /* If this is genesis 2 board then check for no + * keyboard controller and more than one processor. + */ + if (board_type == 0xe0) { + base_mod = inb(0x803); + /* if a MVME2300/2400 or a Sitka then no keyboard */ + if((base_mod == 0xFA) || (base_mod == 0xF9) || + (base_mod == 0xE1)) { + keyb_present = 0; /* no keyboard */ + } + } + /* If this is a multiprocessor system then + * park the other processor so that the + * kernel knows where to find them. + */ + if (residual->MaxNumCpus > 1) + start_multi = 1; + } + memcpy(hold_residual,residual,sizeof(RESIDUAL)); + } + + /* Call decompress_kernel */ + decompress_kernel(load_addr, num_words, cksum); + + if (start_multi) { + residual->VitalProductData.SmpIar = (unsigned long)0xc0; + residual->Cpus[1].CpuState = CPU_GOOD; + hold_residual->VitalProductData.Reserved5 = 0xdeadbeef; + } + + /* Now go and clear out the BATs and ensure that our MSR is + * correct .*/ + disable_6xx_mmu(); + + /* Make r3 be a pointer to the residual data. */ + return (unsigned long)hold_residual; +} + +unsigned long +get_mem_size(void) +{ + unsigned int pci_viddid, pci_did; + + /* First, figure out what kind of host bridge we are on. If it's + * an MPC10x, we can ask it directly how much memory it has. + * Otherwise, see if the residual data has anything. This isn't + * the best way, but it can be the only way. If there's nothing, + * assume 32MB. -- Tom. + */ + /* See what our host bridge is. */ + pci_read_config_32(0x00, 0x00, &pci_viddid); + pci_did = (pci_viddid & 0xffff0000) >> 16; + /* See if we are on an MPC10x. */ + if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA) + && ((pci_did == PCI_DEVICE_ID_MOTOROLA_MPC105) + || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC106) + || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC107))) + return mpc10x_get_mem_size(); + /* If it's not, see if we have anything in the residual data. */ + else if (hold_residual && hold_residual->TotalMemory) + return hold_residual->TotalMemory; + else if (OFW_interface) { + /* + * This is a 'best guess' check. We want to make sure + * we don't try this on a PReP box without OF + * -- Cort + */ + while (OFW_interface) + { + phandle dev_handle; + int mem_info[2]; + + /* get handle to memory description */ + if (!(dev_handle = finddevice("/memory@0"))) + break; + + /* get the info */ + if (getprop(dev_handle, "reg", mem_info, + sizeof(mem_info)) != 8) + break; + + return mem_info[1]; + } + } + + /* Fall back to hard-coding 32MB. */ + return 32*1024*1024; +} diff --git a/arch/ppc/boot/simple/misc-radstone_ppc7d.c b/arch/ppc/boot/simple/misc-radstone_ppc7d.c new file mode 100644 index 00000000000..569e0d4feea --- /dev/null +++ b/arch/ppc/boot/simple/misc-radstone_ppc7d.c @@ -0,0 +1,26 @@ +/* + * arch/ppc/boot/simple/misc-radstone_ppc7d.c + * + * Misc data for Radstone PPC7D board. + * + * Author: James Chapman + */ + +#include +#include + +#if defined(CONFIG_SERIAL_MPSC_CONSOLE) +extern u32 mv64x60_console_baud; +extern u32 mv64x60_mpsc_clk_src; +extern u32 mv64x60_mpsc_clk_freq; +#endif + +void +mv64x60_board_init(void __iomem *old_base, void __iomem *new_base) +{ +#if defined(CONFIG_SERIAL_MPSC_CONSOLE) + mv64x60_console_baud = PPC7D_DEFAULT_BAUD; + mv64x60_mpsc_clk_src = PPC7D_MPSC_CLK_SRC; + mv64x60_mpsc_clk_freq = PPC7D_MPSC_CLK_FREQ; +#endif +} diff --git a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c new file mode 100644 index 00000000000..d012c39278f --- /dev/null +++ b/arch/ppc/boot/simple/misc-spruce.c @@ -0,0 +1,274 @@ +/* + * arch/ppc/boot/spruce/misc.c + * + * Misc. bootloader code for IBM Spruce reference platform + * + * Authors: Johnnie Peters + * Matt Porter + * + * Derived from arch/ppc/boot/prep/misc.c + * + * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include + +#include + +extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, + unsigned long cksum); + +/* Define some important locations of the Spruce. */ +#define SPRUCE_PCI_CONFIG_ADDR 0xfec00000 +#define SPRUCE_PCI_CONFIG_DATA 0xfec00004 + +/* PCI configuration space access routines. */ +unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR; +unsigned char *pci_config_data = (unsigned char *)SPRUCE_PCI_CONFIG_DATA; + +void cpc700_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val) +{ + out_le32(pci_config_address, + (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); + + *val= (in_le32((unsigned *)pci_config_data) >> (8 * (offset & 3))) & 0xff; +} + +void cpc700_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val) +{ + out_le32(pci_config_address, + (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); + + out_8(pci_config_data + (offset&3), val); +} + +void cpc700_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val) +{ + out_le32(pci_config_address, + (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); + + *val= in_le16((unsigned short *)(pci_config_data + (offset&3))); +} + +void cpc700_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val) +{ + out_le32(pci_config_address, + (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); + + out_le16((unsigned short *)(pci_config_data + (offset&3)), val); +} + +void cpc700_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val) +{ + out_le32(pci_config_address, + (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); + + *val= in_le32((unsigned *)pci_config_data); +} + +void cpc700_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val) +{ + out_le32(pci_config_address, + (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); + + out_le32((unsigned *)pci_config_data, val); +} + +#define PCNET32_WIO_RDP 0x10 +#define PCNET32_WIO_RAP 0x12 +#define PCNET32_WIO_RESET 0x14 + +#define PCNET32_DWIO_RDP 0x10 +#define PCNET32_DWIO_RAP 0x14 +#define PCNET32_DWIO_RESET 0x18 + +/* Processor interface config register access */ +#define PIFCFGADDR 0xff500000 +#define PIFCFGDATA 0xff500004 + +#define PLBMIFOPT 0x18 /* PLB Master Interface Options */ + +#define MEM_MBEN 0x24 +#define MEM_TYPE 0x28 +#define MEM_B1SA 0x3c +#define MEM_B1EA 0x5c +#define MEM_B2SA 0x40 +#define MEM_B2EA 0x60 + +unsigned long +get_mem_size(void) +{ + int loop; + unsigned long mem_size = 0; + unsigned long mem_mben; + unsigned long mem_type; + unsigned long mem_start; + unsigned long mem_end; + volatile int *mem_addr = (int *)0xff500008; + volatile int *mem_data = (int *)0xff50000c; + + /* Get the size of memory from the memory controller. */ + *mem_addr = MEM_MBEN; + asm("sync"); + mem_mben = *mem_data; + asm("sync"); + for(loop = 0; loop < 1000; loop++); + + *mem_addr = MEM_TYPE; + asm("sync"); + mem_type = *mem_data; + asm("sync"); + for(loop = 0; loop < 1000; loop++); + + *mem_addr = MEM_TYPE; + /* Confirm bank 1 has DRAM memory */ + if ((mem_mben & 0x40000000) && + ((mem_type & 0x30000000) == 0x10000000)) { + *mem_addr = MEM_B1SA; + asm("sync"); + mem_start = *mem_data; + asm("sync"); + for(loop = 0; loop < 1000; loop++); + + *mem_addr = MEM_B1EA; + asm("sync"); + mem_end = *mem_data; + asm("sync"); + for(loop = 0; loop < 1000; loop++); + + mem_size = mem_end - mem_start + 0x100000; + } + + /* Confirm bank 2 has DRAM memory */ + if ((mem_mben & 0x20000000) && + ((mem_type & 0xc000000) == 0x4000000)) { + *mem_addr = MEM_B2SA; + asm("sync"); + mem_start = *mem_data; + asm("sync"); + for(loop = 0; loop < 1000; loop++); + + *mem_addr = MEM_B2EA; + asm("sync"); + mem_end = *mem_data; + asm("sync"); + for(loop = 0; loop < 1000; loop++); + + mem_size += mem_end - mem_start + 0x100000; + } + return mem_size; +} + +unsigned long +load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, + void *ign1, void *ign2) +{ + int csr0; + int csr_id; + int pci_devfn; + int found_multi = 0; + unsigned short vendor; + unsigned short device; + unsigned short command; + unsigned char header_type; + unsigned int bar0; + volatile int *pif_addr = (int *)0xff500000; + volatile int *pif_data = (int *)0xff500004; + + /* + * Gah, these firmware guys need to learn that hardware + * byte swapping is evil! Disable all hardware byte + * swapping so it doesn't hurt anyone. + */ + *pif_addr = PLBMIFOPT; + asm("sync"); + *pif_data = 0x00000000; + asm("sync"); + + /* Search out and turn off the PcNet ethernet boot device. */ + for (pci_devfn = 1; pci_devfn < 0xff; pci_devfn++) { + if (PCI_FUNC(pci_devfn) && !found_multi) + continue; + + cpc700_pcibios_read_config_byte(0, pci_devfn, + PCI_HEADER_TYPE, &header_type); + + if (!PCI_FUNC(pci_devfn)) + found_multi = header_type & 0x80; + + cpc700_pcibios_read_config_word(0, pci_devfn, PCI_VENDOR_ID, + &vendor); + + if (vendor != 0xffff) { + cpc700_pcibios_read_config_word(0, pci_devfn, + PCI_DEVICE_ID, &device); + + /* If this PCI device is the Lance PCNet board then turn it off */ + if ((vendor == PCI_VENDOR_ID_AMD) && + (device == PCI_DEVICE_ID_AMD_LANCE)) { + + /* Turn on I/O Space on the board. */ + cpc700_pcibios_read_config_word(0, pci_devfn, + PCI_COMMAND, &command); + command |= 0x1; + cpc700_pcibios_write_config_word(0, pci_devfn, + PCI_COMMAND, command); + + /* Get the I/O space address */ + cpc700_pcibios_read_config_dword(0, pci_devfn, + PCI_BASE_ADDRESS_0, &bar0); + bar0 &= 0xfffffffe; + + /* Reset the PCNet Board */ + inl (bar0+PCNET32_DWIO_RESET); + inw (bar0+PCNET32_WIO_RESET); + + /* First do a work oriented read of csr0. If the value is + * 4 then this is the correct mode to access the board. + * If not try a double word ortiented read. + */ + outw(0, bar0 + PCNET32_WIO_RAP); + csr0 = inw(bar0 + PCNET32_WIO_RDP); + + if (csr0 == 4) { + /* Check the Chip id register */ + outw(88, bar0 + PCNET32_WIO_RAP); + csr_id = inw(bar0 + PCNET32_WIO_RDP); + + if (csr_id) { + /* This is the valid mode - set the stop bit */ + outw(0, bar0 + PCNET32_WIO_RAP); + outw(csr0, bar0 + PCNET32_WIO_RDP); + } + } else { + outl(0, bar0 + PCNET32_DWIO_RAP); + csr0 = inl(bar0 + PCNET32_DWIO_RDP); + if (csr0 == 4) { + /* Check the Chip id register */ + outl(88, bar0 + PCNET32_WIO_RAP); + csr_id = inl(bar0 + PCNET32_WIO_RDP); + + if (csr_id) { + /* This is the valid mode - set the stop bit*/ + outl(0, bar0 + PCNET32_WIO_RAP); + outl(csr0, bar0 + PCNET32_WIO_RDP); + } + } + } + } + } + } + + return decompress_kernel(load_addr, num_words, cksum); +} diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c new file mode 100644 index 00000000000..ab0f9902cb6 --- /dev/null +++ b/arch/ppc/boot/simple/misc.c @@ -0,0 +1,284 @@ +/* + * arch/ppc/simple/misc.c + * + * Misc. bootloader code for many machines. This assumes you have are using + * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory + * below 8MB is free. Finally, it assumes you have a NS16550-style uart for + * your serial console. If a machine meets these requirements, it can quite + * likely use this code during boot. + * + * Author: Matt Porter + * Derived from arch/ppc/boot/prep/misc.c + * + * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include + +#include +#include +#include +#ifdef CONFIG_44x +#include +#endif +#include + +#include "nonstdio.h" + +/* Default cmdline */ +#ifdef CONFIG_CMDLINE +#define CMDLINE CONFIG_CMDLINE +#else +#define CMDLINE "" +#endif + +/* Keyboard (and VGA console)? */ +#ifdef CONFIG_VGA_CONSOLE +#define HAS_KEYB 1 +#else +#define HAS_KEYB 0 +#endif + +/* Will / Can the user give input? + * Val Henson has requested that Gemini doesn't wait for the + * user to edit the cmdline or not. + */ +#if (defined(CONFIG_SERIAL_8250_CONSOLE) \ + || defined(CONFIG_VGA_CONSOLE) \ + || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ + || defined(CONFIG_SERIAL_MPSC_CONSOLE)) \ + && !defined(CONFIG_GEMINI) +#define INTERACTIVE_CONSOLE 1 +#endif + +char *avail_ram; +char *end_avail; +char *zimage_start; +char cmd_preset[] = CMDLINE; +char cmd_buf[256]; +char *cmd_line = cmd_buf; +int keyb_present = HAS_KEYB; +int zimage_size; + +unsigned long com_port; +unsigned long initrd_size = 0; + +/* The linker tells us various locations in the image */ +extern char __image_begin, __image_end; +extern char __ramdisk_begin, __ramdisk_end; +extern char _end[]; +/* Original location */ +extern unsigned long start; + +extern int CRT_tstc(void); +extern unsigned long serial_init(int chan, void *ignored); +extern void serial_close(unsigned long com_port); +extern void gunzip(void *, int, unsigned char *, int *); +extern void serial_fixups(void); + +/* Allow get_mem_size to be hooked into. This is the default. */ +unsigned long __attribute__ ((weak)) +get_mem_size(void) +{ + return 0; +} + +struct bi_record * +decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) +{ +#ifdef INTERACTIVE_CONSOLE + int timer = 0; + char ch; +#endif + char *cp; + struct bi_record *rec; + unsigned long initrd_loc = 0, TotalMemory = 0; + +#if defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_MPSC_CONSOLE) + com_port = serial_init(0, NULL); +#endif + +#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0) + /* Reset MAL */ + mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); + /* Wait for reset */ + while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; + /* Reset EMAC */ + *(volatile unsigned long *)PPC44x_EMAC0_MR0 = 0x20000000; + __asm__ __volatile__("eieio"); +#endif + + /* + * Call get_mem_size(), which is memory controller dependent, + * and we must have the correct file linked in here. + */ + TotalMemory = get_mem_size(); + + /* assume the chunk below 8M is free */ + end_avail = (char *)0x00800000; + + /* + * Reveal where we were loaded at and where we + * were relocated to. + */ + puts("loaded at: "); puthex(load_addr); + puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); + puts("\n"); + if ( (unsigned long)load_addr != (unsigned long)&start ) + { + puts("relocated to: "); puthex((unsigned long)&start); + puts(" "); + puthex((unsigned long)((unsigned long)&start + (4*num_words))); + puts("\n"); + } + + /* + * We link ourself to 0x00800000. When we run, we relocate + * ourselves there. So we just need __image_begin for the + * start. -- Tom + */ + zimage_start = (char *)(unsigned long)(&__image_begin); + zimage_size = (unsigned long)(&__image_end) - + (unsigned long)(&__image_begin); + + initrd_size = (unsigned long)(&__ramdisk_end) - + (unsigned long)(&__ramdisk_begin); + + /* + * The zImage and initrd will be between start and _end, so they've + * already been moved once. We're good to go now. -- Tom + */ + avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); + puts("zimage at: "); puthex((unsigned long)zimage_start); + puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); + puts("\n"); + + if ( initrd_size ) { + puts("initrd at: "); + puthex((unsigned long)(&__ramdisk_begin)); + puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); + } + + avail_ram = (char *)0x00400000; + end_avail = (char *)0x00800000; + puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); + puthex((unsigned long)end_avail); puts("\n"); + + if (keyb_present) + CRT_tstc(); /* Forces keyboard to be initialized */ +#ifdef CONFIG_GEMINI + /* + * If cmd_line is empty and cmd_preset is not, copy cmd_preset + * to cmd_line. This way we can override cmd_preset with the + * command line from Smon. + */ + + if ( (cmd_line[0] == '\0') && (cmd_preset[0] != '\0')) + memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); +#endif + + /* Display standard Linux/PPC boot prompt for kernel args */ + puts("\nLinux/PPC load: "); + cp = cmd_line; + memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); + while ( *cp ) putc(*cp++); + +#ifdef INTERACTIVE_CONSOLE + /* + * If they have a console, allow them to edit the command line. + * Otherwise, don't bother wasting the five seconds. + */ + while (timer++ < 5*1000) { + if (tstc()) { + while ((ch = getc()) != '\n' && ch != '\r') { + /* Test for backspace/delete */ + if (ch == '\b' || ch == '\177') { + if (cp != cmd_line) { + cp--; + puts("\b \b"); + } + /* Test for ^x/^u (and wipe the line) */ + } else if (ch == '\030' || ch == '\025') { + while (cp != cmd_line) { + cp--; + puts("\b \b"); + } + } else { + *cp++ = ch; + putc(ch); + } + } + break; /* Exit 'timer' loop */ + } + udelay(1000); /* 1 msec */ + } + *cp = 0; +#endif + puts("\n"); + + puts("Uncompressing Linux..."); + gunzip(0x0, 0x400000, zimage_start, &zimage_size); + puts("done.\n"); + + /* get the bi_rec address */ + rec = bootinfo_addr(zimage_size); + + /* We need to make sure that the initrd and bi_recs do not + * overlap. */ + if ( initrd_size ) { + unsigned long rec_loc = (unsigned long) rec; + initrd_loc = (unsigned long)(&__ramdisk_begin); + /* If the bi_recs are in the middle of the current + * initrd, move the initrd to the next MB + * boundary. */ + if ((rec_loc > initrd_loc) && + ((initrd_loc + initrd_size) > rec_loc)) { + initrd_loc = _ALIGN((unsigned long)(zimage_size) + + (2 << 20) - 1, (2 << 20)); + memmove((void *)initrd_loc, &__ramdisk_begin, + initrd_size); + puts("initrd moved: "); puthex(initrd_loc); + puts(" "); puthex(initrd_loc + initrd_size); + puts("\n"); + } + } + + bootinfo_init(rec); + if ( TotalMemory ) + bootinfo_append(BI_MEMSIZE, sizeof(int), (void*)&TotalMemory); + + bootinfo_append(BI_CMD_LINE, strlen(cmd_line)+1, (void*)cmd_line); + + /* add a bi_rec for the initrd if it exists */ + if (initrd_size) { + unsigned long initrd[2]; + + initrd[0] = initrd_loc; + initrd[1] = initrd_size; + + bootinfo_append(BI_INITRD, sizeof(initrd), &initrd); + } + puts("Now booting the kernel\n"); + serial_close(com_port); + + return rec; +} + +void __attribute__ ((weak)) +board_isa_init(void) +{ +} + +/* Allow decompress_kernel to be hooked into. This is the default. */ +void * __attribute__ ((weak)) +load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, + void *ign1, void *ign2) +{ + board_isa_init(); + return decompress_kernel(load_addr, num_words, cksum); +} diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c new file mode 100644 index 00000000000..977daedc14c --- /dev/null +++ b/arch/ppc/boot/simple/mpc10x_memory.c @@ -0,0 +1,111 @@ +/* + * arch/ppc/boot/common/mpc10x_common.c + * + * A routine to find out how much memory the machine has. + * + * Based on: + * arch/ppc/kernel/mpc10x_common.c + * + * Author: Mark A. Greer + * mgreer@mvista.com + * + * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include "mpc10x.h" + +/* + * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs *** + */ + +/* + * PCI config space macros, similar to indirect_xxx and early_xxx macros. + * We assume bus 0. + */ +#define MPC10X_CFG_read(val, addr, type, op) *val = op((type)(addr)) +#define MPC10X_CFG_write(val, addr, type, op) op((type *)(addr), (val)) + +#define MPC10X_PCI_OP(rw, size, type, op, mask) \ +static void \ +mpc10x_##rw##_config_##size(unsigned int *cfg_addr, \ + unsigned int *cfg_data, int devfn, int offset, \ + type val) \ +{ \ + out_be32(cfg_addr, \ + ((offset & 0xfc) << 24) | (devfn << 16) \ + | (0 << 8) | 0x80); \ + MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op); \ + return; \ +} + +MPC10X_PCI_OP(read, byte, u8 *, in_8, 3) +MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0) + +/* + * Read the memory controller registers to determine the amount of memory in + * the system. This assumes that the firmware has correctly set up the memory + * controller registers. On CONFIG_PPC_PREP, we know we are being called + * under a PReP memory map. On all other machines, we assume we are under + * a CHRP memory map. Further, on CONFIG_PPC_MULTIPLATFORM we must rename + * this function. + */ +#ifdef CONFIG_PPC_MULTIPLATFORM +#define get_mem_size mpc10x_get_mem_size +#endif +unsigned long +get_mem_size(void) +{ + unsigned int *config_addr, *config_data, val; + unsigned long start, end, total, offset; + int i; + unsigned char bank_enables; + +#ifdef CONFIG_PPC_PREP + config_addr = (unsigned int *)MPC10X_MAPA_CNFG_ADDR; + config_data = (unsigned int *)MPC10X_MAPA_CNFG_DATA; +#else + config_addr = (unsigned int *)MPC10X_MAPB_CNFG_ADDR; + config_data = (unsigned int *)MPC10X_MAPB_CNFG_DATA; +#endif + + mpc10x_read_config_byte(config_addr, config_data, PCI_DEVFN(0,0), + MPC10X_MCTLR_MEM_BANK_ENABLES, &bank_enables); + + total = 0; + + for (i = 0; i < 8; i++) { + if (bank_enables & (1 << i)) { + offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0); + mpc10x_read_config_dword(config_addr, config_data, + PCI_DEVFN(0,0), offset, &val); + start = (val >> ((i & 3) << 3)) & 0xff; + + offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0); + mpc10x_read_config_dword(config_addr, config_data, + PCI_DEVFN(0,0), offset, &val); + val = (val >> ((i & 3) << 3)) & 0x03; + start = (val << 28) | (start << 20); + + offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0); + mpc10x_read_config_dword(config_addr, config_data, + PCI_DEVFN(0,0), offset, &val); + end = (val >> ((i & 3) << 3)) & 0xff; + + offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0); + mpc10x_read_config_dword(config_addr, config_data, + PCI_DEVFN(0,0), offset, &val); + val = (val >> ((i & 3) << 3)) & 0x03; + end = (val << 28) | (end << 20) | 0xfffff; + + total += (end - start + 1); + } + } + + return total; +} diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c new file mode 100644 index 00000000000..3acc6b7c072 --- /dev/null +++ b/arch/ppc/boot/simple/mpc52xx_tty.c @@ -0,0 +1,140 @@ +/* + * arch/ppc/boot/simple/mpc52xx_tty.c + * + * Minimal serial functions needed to send messages out a MPC52xx + * Programmable Serial Controller (PSC). + * + * Author: Dale Farnsworth + * + * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is licensed + * "as is" without any warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef MPC52xx_PF_CONSOLE_PORT +#define MPC52xx_CONSOLE MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT) +#define MPC52xx_PSC_CONFIG_SHIFT ((MPC52xx_PF_CONSOLE_PORT-1)<<2) +#else +#error "MPC52xx_PF_CONSOLE_PORT not defined" +#endif + +static struct mpc52xx_psc __iomem *psc = + (struct mpc52xx_psc __iomem *) MPC52xx_PA(MPC52xx_CONSOLE); + +/* The decrementer counts at the system bus clock frequency + * divided by four. The most accurate time base is connected to the + * rtc. We read the decrementer change during one rtc tick + * and multiply by 4 to get the system bus clock frequency. Since a + * rtc tick is one seconds, and that's pretty long, we change the rtc + * dividers temporarly to set them 64x faster ;) + */ +static int +mpc52xx_ipbfreq(void) +{ + struct mpc52xx_rtc __iomem *rtc = + (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET); + struct mpc52xx_cdm __iomem *cdm = + (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET); + int current_time, previous_time; + int tbl_start, tbl_end; + int xlbfreq, ipbfreq; + + out_be32(&rtc->dividers, 0x8f1f0000); /* Set RTC 64x faster */ + previous_time = in_be32(&rtc->time); + while ((current_time = in_be32(&rtc->time)) == previous_time) ; + tbl_start = get_tbl(); + previous_time = current_time; + while ((current_time = in_be32(&rtc->time)) == previous_time) ; + tbl_end = get_tbl(); + out_be32(&rtc->dividers, 0xffff0000); /* Restore RTC */ + + xlbfreq = (tbl_end - tbl_start) << 8; + ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ? xlbfreq / 2 : xlbfreq; + + return ipbfreq; +} + +unsigned long +serial_init(int ignored, void *ignored2) +{ + struct mpc52xx_gpio __iomem *gpio = + (struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET); + int divisor; + int mode1; + int mode2; + u32 val32; + + static int been_here = 0; + + if (been_here) + return 0; + + been_here = 1; + + val32 = in_be32(&gpio->port_config); + val32 &= ~(0x7 << MPC52xx_PSC_CONFIG_SHIFT); + val32 |= MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD + << MPC52xx_PSC_CONFIG_SHIFT; + out_be32(&gpio->port_config, val32); + + out_8(&psc->command, MPC52xx_PSC_RST_TX + | MPC52xx_PSC_RX_DISABLE | MPC52xx_PSC_TX_ENABLE); + out_8(&psc->command, MPC52xx_PSC_RST_RX); + + out_be32(&psc->sicr, 0x0); + out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); + out_be16(&psc->tfalarm, 0xf8); + + out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1 + | MPC52xx_PSC_RX_ENABLE + | MPC52xx_PSC_TX_ENABLE); + + divisor = ((mpc52xx_ipbfreq() + / (CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD * 16)) + 1) >> 1; + + mode1 = MPC52xx_PSC_MODE_8_BITS | MPC52xx_PSC_MODE_PARNONE + | MPC52xx_PSC_MODE_ERR; + mode2 = MPC52xx_PSC_MODE_ONE_STOP; + + out_8(&psc->ctur, divisor>>8); + out_8(&psc->ctlr, divisor); + out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); + out_8(&psc->mode, mode1); + out_8(&psc->mode, mode2); + + return 0; /* ignored */ +} + +void +serial_putc(void *ignored, const char c) +{ + serial_init(0, NULL); + + while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ; + out_8(&psc->mpc52xx_psc_buffer_8, c); + while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ; +} + +char +serial_getc(void *ignored) +{ + while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY)) ; + + return in_8(&psc->mpc52xx_psc_buffer_8); +} + +int +serial_tstc(void *ignored) +{ + return (in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY) != 0; +} diff --git a/arch/ppc/boot/simple/mv64x60_tty.c b/arch/ppc/boot/simple/mv64x60_tty.c new file mode 100644 index 00000000000..5b45eb46b66 --- /dev/null +++ b/arch/ppc/boot/simple/mv64x60_tty.c @@ -0,0 +1,360 @@ +/* + * arch/ppc/boot/simple/mv64x60_tty.c + * + * Bootloader version of the embedded MPSC/UART driver for the Marvell 64x60. + * Note: Due to a GT64260A erratum, DMA will be used for UART input (via SDMA). + * + * Author: Mark A. Greer + * + * 2001 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +/* This code assumes that the data cache has been disabled (L1, L2, L3). */ + +#include +#include +#include +#include +#include +#include +#include + +u32 mv64x60_console_baud = 9600; +u32 mv64x60_mpsc_clk_src = 8; /* TCLK */ +u32 mv64x60_mpsc_clk_freq = 100000000; + +extern void udelay(long); +static void stop_dma(int chan); + +static void __iomem *mv64x60_base = (void __iomem *)CONFIG_MV64X60_NEW_BASE; + +struct sdma_regs { + u32 sdc; + u32 sdcm; + u32 rx_desc; + u32 rx_buf_ptr; + u32 scrdp; + u32 tx_desc; + u32 sctdp; + u32 sftdp; +}; + +static struct sdma_regs sdma_regs[2]; + +#define SDMA_REGS_INIT(s, reg_base) { \ + (s)->sdc = (reg_base) + SDMA_SDC; \ + (s)->sdcm = (reg_base) + SDMA_SDCM; \ + (s)->rx_desc = (reg_base) + SDMA_RX_DESC; \ + (s)->rx_buf_ptr = (reg_base) + SDMA_RX_BUF_PTR; \ + (s)->scrdp = (reg_base) + SDMA_SCRDP; \ + (s)->tx_desc = (reg_base) + SDMA_TX_DESC; \ + (s)->sctdp = (reg_base) + SDMA_SCTDP; \ + (s)->sftdp = (reg_base) + SDMA_SFTDP; \ +} + +static u32 mpsc_base[2] = { MV64x60_MPSC_0_OFFSET, MV64x60_MPSC_1_OFFSET }; + +struct mv64x60_rx_desc { + u16 bufsize; + u16 bytecnt; + u32 cmd_stat; + u32 next_desc_ptr; + u32 buffer; +}; + +struct mv64x60_tx_desc { + u16 bytecnt; + u16 shadow; + u32 cmd_stat; + u32 next_desc_ptr; + u32 buffer; +}; + +#define MAX_RESET_WAIT 10000 +#define MAX_TX_WAIT 10000 + +#define RX_NUM_DESC 2 +#define TX_NUM_DESC 2 + +#define RX_BUF_SIZE 32 +#define TX_BUF_SIZE 32 + +static struct mv64x60_rx_desc rd[2][RX_NUM_DESC] __attribute__ ((aligned(32))); +static struct mv64x60_tx_desc td[2][TX_NUM_DESC] __attribute__ ((aligned(32))); + +static char rx_buf[2][RX_NUM_DESC * RX_BUF_SIZE] __attribute__ ((aligned(32))); +static char tx_buf[2][TX_NUM_DESC * TX_BUF_SIZE] __attribute__ ((aligned(32))); + +static int cur_rd[2] = { 0, 0 }; +static int cur_td[2] = { 0, 0 }; + +static char chan_initialized[2] = { 0, 0 }; + + +#define RX_INIT_RDP(rdp) { \ + (rdp)->bufsize = 2; \ + (rdp)->bytecnt = 0; \ + (rdp)->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F | \ + SDMA_DESC_CMDSTAT_O; \ +} + +#ifdef CONFIG_MV64360 +static u32 cpu2mem_tab[MV64x60_CPU2MEM_WINDOWS][2] = { + { MV64x60_CPU2MEM_0_BASE, MV64x60_CPU2MEM_0_SIZE }, + { MV64x60_CPU2MEM_1_BASE, MV64x60_CPU2MEM_1_SIZE }, + { MV64x60_CPU2MEM_2_BASE, MV64x60_CPU2MEM_2_SIZE }, + { MV64x60_CPU2MEM_3_BASE, MV64x60_CPU2MEM_3_SIZE } +}; + +static u32 com2mem_tab[MV64x60_CPU2MEM_WINDOWS][2] = { + { MV64360_MPSC2MEM_0_BASE, MV64360_MPSC2MEM_0_SIZE }, + { MV64360_MPSC2MEM_1_BASE, MV64360_MPSC2MEM_1_SIZE }, + { MV64360_MPSC2MEM_2_BASE, MV64360_MPSC2MEM_2_SIZE }, + { MV64360_MPSC2MEM_3_BASE, MV64360_MPSC2MEM_3_SIZE } +}; + +static u32 dram_selects[MV64x60_CPU2MEM_WINDOWS] = { 0xe, 0xd, 0xb, 0x7 }; +#endif + +unsigned long +serial_init(int chan, void *ignored) +{ + u32 mpsc_routing_base, sdma_base, brg_bcr, cdv; + int i; + + chan = (chan == 1); /* default to chan 0 if anything but 1 */ + + if (chan_initialized[chan]) + return chan; + + chan_initialized[chan] = 1; + + if (chan == 0) { + sdma_base = MV64x60_SDMA_0_OFFSET; + brg_bcr = MV64x60_BRG_0_OFFSET + BRG_BCR; + SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_0_OFFSET); + } else { + sdma_base = MV64x60_SDMA_1_OFFSET; + brg_bcr = MV64x60_BRG_1_OFFSET + BRG_BCR; + SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_1_OFFSET); + } + + mpsc_routing_base = MV64x60_MPSC_ROUTING_OFFSET; + + stop_dma(chan); + + /* Set up ring buffers */ + for (i=0; i= TX_NUM_DESC) + cur_td[com_port] = 0; + + *(unchar *)(tdp->buffer ^ 7) = c; + tdp->bytecnt = 1; + tdp->shadow = 1; + tdp->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F | + SDMA_DESC_CMDSTAT_O; + + out_le32(mv64x60_base + sdma_regs[com_port].sctdp, (int)tdp); + out_le32(mv64x60_base + sdma_regs[com_port].sftdp, (int)tdp); + out_le32(mv64x60_base + sdma_regs[com_port].sdcm, + in_le32(mv64x60_base + sdma_regs[com_port].sdcm) | + SDMA_SDCM_TXD); +} + +unsigned char +serial_getc(unsigned long com_port) +{ + struct mv64x60_rx_desc *rdp; + unchar c = '\0'; + + rdp = &rd[com_port][cur_rd[com_port]]; + + if ((rdp->cmd_stat & (SDMA_DESC_CMDSTAT_O|SDMA_DESC_CMDSTAT_ES)) == 0) { + c = *(unchar *)(rdp->buffer ^ 7); + RX_INIT_RDP(rdp); + if (++cur_rd[com_port] >= RX_NUM_DESC) + cur_rd[com_port] = 0; + } + + return c; +} + +int +serial_tstc(unsigned long com_port) +{ + struct mv64x60_rx_desc *rdp; + int loop_count = 0; + int rc = 0; + + rdp = &rd[com_port][cur_rd[com_port]]; + + /* Go thru rcv desc's until empty looking for one with data (no error)*/ + while (((rdp->cmd_stat & SDMA_DESC_CMDSTAT_O) == 0) && + (loop_count++ < RX_NUM_DESC)) { + + /* If there was an error, reinit the desc & continue */ + if ((rdp->cmd_stat & SDMA_DESC_CMDSTAT_ES) != 0) { + RX_INIT_RDP(rdp); + if (++cur_rd[com_port] >= RX_NUM_DESC) + cur_rd[com_port] = 0; + rdp = (struct mv64x60_rx_desc *)rdp->next_desc_ptr; + } else { + rc = 1; + break; + } + } + + return rc; +} + +void +serial_close(unsigned long com_port) +{ + stop_dma(com_port); +} diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c new file mode 100644 index 00000000000..c732b6d70cf --- /dev/null +++ b/arch/ppc/boot/simple/openbios.c @@ -0,0 +1,37 @@ +/* + * arch/ppc/boot/simple/openbios.c + * + * 2005 (c) SYSGO AG - g.jaeger@sysgo.com + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Derived from arch/ppc/boot/simple/pibs.c (from MontaVista) + */ + +#include +#include +#include +#include +#include + +extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, + unsigned long cksum); + +/* We need to make sure that this is before the images to ensure + * that it's in a mapped location. */ +bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot"))); +bd_t *hold_residual = &hold_resid_buf; + +void * +load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, + void *ign1, void *ign2) +{ + decompress_kernel(load_addr, num_words, cksum); + + /* simply copy the MAC addresses */ + memcpy(hold_residual->bi_enetaddr, (char *)EBONY_OPENBIOS_MAC_BASE, 6); + memcpy(hold_residual->bi_enet1addr, (char *)(EBONY_OPENBIOS_MAC_BASE+EBONY_OPENBIOS_MAC_OFFSET), 6); + + return (void *)hold_residual; +} diff --git a/arch/ppc/boot/simple/pci.c b/arch/ppc/boot/simple/pci.c new file mode 100644 index 00000000000..b0f673c8b7d --- /dev/null +++ b/arch/ppc/boot/simple/pci.c @@ -0,0 +1,274 @@ +/* Stand alone funtions for QSpan Tundra support. + */ +#include +#include +#include + +extern void puthex(unsigned long val); +extern void puts(const char *); + +/* To map PCI devices, you first write 0xffffffff into the device + * base address registers. When the register is read back, the + * number of most significant '1' bits describes the amount of address + * space needed for mapping. If the most significant bit is not set, + * either the device does not use that address register, or it has + * a fixed address that we can't change. After the address is assigned, + * the command register has to be written to enable the card. + */ +typedef struct { + u_char pci_bus; + u_char pci_devfn; + ushort pci_command; + uint pci_addrs[6]; +} pci_map_t; + +/* We should probably dynamically allocate these structures. +*/ +#define MAX_PCI_DEVS 32 +int pci_dev_cnt; +pci_map_t pci_map[MAX_PCI_DEVS]; + +void pci_conf_write(int bus, int device, int func, int reg, uint writeval); +void pci_conf_read(int bus, int device, int func, int reg, void *readval); +void probe_addresses(int bus, int devfn); +void map_pci_addrs(void); + +extern int +qs_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val); +extern int +qs_pci_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val); +extern int +qs_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val); +extern int +qs_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val); +extern int +qs_pci_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val); +extern int +qs_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val); + + +/* This is a really stripped version of PCI bus scan. All we are + * looking for are devices that exist. + */ +void +pci_scanner(int addr_probe) +{ + unsigned int devfn, l, class, bus_number; + unsigned char hdr_type, is_multi; + + is_multi = 0; + bus_number = 0; + for (devfn = 0; devfn < 0xff; ++devfn) { + /* The device numbers are comprised of upper 5 bits of + * device number and lower 3 bits of multi-function number. + */ + if ((devfn & 7) && !is_multi) { + /* Don't scan multifunction addresses if this is + * not a multifunction device. + */ + continue; + } + + /* Read the header to determine card type. + */ + qs_pci_read_config_byte(bus_number, devfn, PCI_HEADER_TYPE, + &hdr_type); + + /* If this is a base device number, check the header to + * determine if it is mulifunction. + */ + if ((devfn & 7) == 0) + is_multi = hdr_type & 0x80; + + /* Check to see if the board is really in the slot. + */ + qs_pci_read_config_dword(bus_number, devfn, PCI_VENDOR_ID, &l); + /* some broken boards return 0 if a slot is empty: */ + if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || + l == 0xffff0000) { + /* Nothing there. + */ + is_multi = 0; + continue; + } + + /* If we are not performing an address probe, + * just simply print out some information. + */ + if (!addr_probe) { + qs_pci_read_config_dword(bus_number, devfn, + PCI_CLASS_REVISION, &class); + + class >>= 8; /* upper 3 bytes */ + +#if 0 + printf("Found (%3d:%d): vendor 0x%04x, device 0x%04x, class 0x%06x\n", + (devfn >> 3), (devfn & 7), + (l & 0xffff), (l >> 16) & 0xffff, class); +#else + puts("Found ("); puthex(devfn >> 3); + puts(":"); puthex(devfn & 7); + puts("): vendor "); puthex(l & 0xffff); + puts(", device "); puthex((l >> 16) & 0xffff); + puts(", class "); puthex(class); puts("\n"); +#endif + } + else { + /* If this is a "normal" device, build address list. + */ + if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) + probe_addresses(bus_number, devfn); + } + } + + /* Now map the boards. + */ + if (addr_probe) + map_pci_addrs(); +} + +/* Probe addresses for the specified device. This is a destructive + * operation because it writes the registers. + */ +void +probe_addresses(bus, devfn) +{ + int i; + uint pciaddr; + ushort pcicmd; + pci_map_t *pm; + + if (pci_dev_cnt >= MAX_PCI_DEVS) { + puts("Too many PCI devices\n"); + return; + } + + pm = &pci_map[pci_dev_cnt++]; + + pm->pci_bus = bus; + pm->pci_devfn = devfn; + + for (i=0; i<6; i++) { + qs_pci_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4), -1); + qs_pci_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4), + &pciaddr); + pm->pci_addrs[i] = pciaddr; + qs_pci_read_config_word(bus, devfn, PCI_COMMAND, &pcicmd); + pm->pci_command = pcicmd; + } +} + +/* Map the cards into the PCI space. The PCI has separate memory + * and I/O spaces. In addition, some memory devices require mapping + * below 1M. The least significant 4 bits of the address register + * provide information. If this is an I/O device, only the LS bit + * is used to indicate that, so I/O devices can be mapped to a two byte + * boundard. Memory addresses can be mapped to a 32 byte boundary. + * The QSpan implementations usually have a 1Gbyte space for each + * memory and I/O spaces. + * + * This isn't a terribly fancy algorithm. I just map the spaces from + * the top starting with the largest address space. When finished, + * the registers are written and the card enabled. + * + * While the Tundra can map a large address space on most boards, we + * need to be careful because it may overlap other devices (like IMMR). + */ +#define MEMORY_SPACE_SIZE 0x20000000 +#define IO_SPACE_SIZE 0x20000000 + +void +map_pci_addrs() +{ + uint pci_mem_top, pci_mem_low; + uint pci_io_top; + uint addr_mask, reg_addr, space; + int i, j; + pci_map_t *pm; + + pci_mem_top = MEMORY_SPACE_SIZE; + pci_io_top = IO_SPACE_SIZE; + pci_mem_low = (1 * 1024 * 1024); /* Below one meg addresses */ + + /* We can't map anything more than the maximum space, but test + * for it anyway to catch devices out of range. + */ + addr_mask = 0x80000000; + + do { + space = (~addr_mask) + 1; /* Size of the space */ + for (i=0; ipci_addrs[j]; + if ((reg_addr & 0x80000000) == 0) + continue; + if (reg_addr & PCI_BASE_ADDRESS_SPACE_IO) { + if ((reg_addr & PCI_BASE_ADDRESS_IO_MASK) != addr_mask) + continue; + if (pci_io_top < space) { + puts("Out of PCI I/O space\n"); + } + else { + pci_io_top -= space; + pm->pci_addrs[j] = pci_io_top; + pm->pci_command |= PCI_COMMAND_IO; + } + } + else { + if ((reg_addr & PCI_BASE_ADDRESS_MEM_MASK) != addr_mask) + continue; + + /* Memory space. Test if below 1M. + */ + if (reg_addr & PCI_BASE_ADDRESS_MEM_TYPE_1M) { + if (pci_mem_low < space) { + puts("Out of PCI 1M space\n"); + } + else { + pci_mem_low -= space; + pm->pci_addrs[j] = pci_mem_low; + } + } + else { + if (pci_mem_top < space) { + puts("Out of PCI Mem space\n"); + } + else { + pci_mem_top -= space; + pm->pci_addrs[j] = pci_mem_top; + } + } + pm->pci_command |= PCI_COMMAND_MEMORY; + } + } + } + addr_mask >>= 1; + addr_mask |= 0x80000000; + } while (addr_mask != 0xfffffffe); + + /* Now, run the list one more time and map everything. + */ + for (i=0; ipci_bus, pm->pci_devfn, + PCI_BASE_ADDRESS_0 + (j * 4), pm->pci_addrs[j]); + } + + /* Enable memory or address mapping. + */ + qs_pci_write_config_word(pm->pci_bus, pm->pci_devfn, PCI_COMMAND, + pm->pci_command); + } +} + diff --git a/arch/ppc/boot/simple/pibs.c b/arch/ppc/boot/simple/pibs.c new file mode 100644 index 00000000000..1348740e503 --- /dev/null +++ b/arch/ppc/boot/simple/pibs.c @@ -0,0 +1,103 @@ +/* + * 2004-2005 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include + +extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, + unsigned long cksum); + +/* We need to make sure that this is before the images to ensure + * that it's in a mapped location. - Tom */ +bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot"))); +bd_t *hold_residual = &hold_resid_buf; + +/* String functions lifted from lib/vsprintf.c and lib/ctype.c */ +unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ + +/** + * simple_strtoull - convert a string to an unsigned long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) +{ + unsigned long long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } else if (base == 16) { + if (cp[0] == '0' && toupper(cp[1]) == 'X') + cp += 2; + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +void * +load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, + void *ign1, void *ign2) +{ + unsigned long long mac64; + + decompress_kernel(load_addr, num_words, cksum); + + mac64 = simple_strtoull((char *)PIBS_MAC_BASE, 0, 16); + memcpy(hold_residual->bi_enetaddr, (char *)&mac64+2, 6); +#ifdef CONFIG_440GX + mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET), 0, 16); + memcpy(hold_residual->bi_enet1addr, (char *)&mac64+2, 6); + mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*2), 0, 16); + memcpy(hold_residual->bi_enet2addr, (char *)&mac64+2, 6); + mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*3), 0, 16); + memcpy(hold_residual->bi_enet3addr, (char *)&mac64+2, 6); +#endif + return (void *)hold_residual; +} diff --git a/arch/ppc/boot/simple/prepmap.c b/arch/ppc/boot/simple/prepmap.c new file mode 100644 index 00000000000..c871a4db6e8 --- /dev/null +++ b/arch/ppc/boot/simple/prepmap.c @@ -0,0 +1,12 @@ +/* + * 2004 (C) IBM. This file is licensed under the terms of the GNU General + * Public License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include + +void board_isa_init(void) +{ + ISA_init(0x80000000); +} diff --git a/arch/ppc/boot/simple/qspan_pci.c b/arch/ppc/boot/simple/qspan_pci.c new file mode 100644 index 00000000000..d2966d032a4 --- /dev/null +++ b/arch/ppc/boot/simple/qspan_pci.c @@ -0,0 +1,269 @@ +/* + * LinuxPPC arch/ppc/kernel/qspan_pci.c Dan Malek (dmalek@jlc.net) + * + * QSpan Motorola bus to PCI bridge. The config address register + * is located 0x500 from the base of the bridge control/status registers. + * The data register is located at 0x504. + * This is a two step operation. First, the address register is written, + * then the data register is read/written as required. + * I don't know what to do about interrupts (yet). + */ + +#include +#include +#include +#include + +/* + * When reading the configuration space, if something does not respond + * the bus times out and we get a machine check interrupt. So, the + * good ol' exception tables come to mind to trap it and return some + * value. + * + * On an error we just return a -1, since that is what the caller wants + * returned if nothing is present. I copied this from __get_user_asm, + * with the only difference of returning -1 instead of EFAULT. + * There is an associated hack in the machine check trap code. + * + * The QSPAN is also a big endian device, that is it makes the PCI + * look big endian to us. This presents a problem for the Linux PCI + * functions, which assume little endian. For example, we see the + * first 32-bit word like this: + * ------------------------ + * | Device ID | Vendor ID | + * ------------------------ + * If we read/write as a double word, that's OK. But in our world, + * when read as a word, device ID is at location 0, not location 2 as + * the little endian PCI would believe. We have to switch bits in + * the PCI addresses given to us to get the data to/from the correct + * byte lanes. + * + * The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5. + * It always forces the MS bit to zero. Therefore, dev_fn values + * greater than 128 are returned as "no device found" errors. + * + * The QSPAN can only perform long word (32-bit) configuration cycles. + * The "offset" must have the two LS bits set to zero. Read operations + * require we read the entire word and then sort out what should be + * returned. Write operations other than long word require that we + * read the long word, update the proper word or byte, then write the + * entire long word back. + * + * PCI Bridge hack. We assume (correctly) that bus 0 is the primary + * PCI bus from the QSPAN. If we are called with a bus number other + * than zero, we create a Type 1 configuration access that a downstream + * PCI bridge will interpret. + */ + +#define __get_pci_config(x, addr, op) \ + __asm__ __volatile__( \ + "1: "op" %0,0(%1)\n" \ + " eieio\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: li %0,-1\n" \ + " b 2b\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 2\n" \ + " .long 1b,3b\n" \ + ".text" \ + : "=r"(x) : "r"(addr)) + +#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500)) +#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504)) + +#define mk_config_addr(bus, dev, offset) \ + (((bus)<<16) | ((dev)<<8) | (offset & 0xfc)) + +#define mk_config_type1(bus, dev, offset) \ + mk_config_addr(bus, dev, offset) | 1; + +/* Initialize the QSpan device registers after power up. +*/ +void +qspan_init(void) +{ + uint *qptr; + + + + qptr = (uint *)PCI_CSR_ADDR; + + /* PCI Configuration/status. Upper bits written to clear + * pending interrupt or status. Lower bits enable QSPAN as + * PCI master, enable memory and I/O cycles, and enable PCI + * parity error checking. + * IMPORTANT: The last two bits of this word enable PCI + * master cycles into the QBus. The QSpan is broken and can't + * meet the timing specs of the PQ bus for this to work. Therefore, + * if you don't have external bus arbitration, you can't use + * this function. + */ +#ifdef EXTERNAL_PQ_ARB + qptr[1] = 0xf9000147; +#else + qptr[1] = 0xf9000144; +#endif + + /* PCI Misc configuration. Set PCI latency timer resolution + * of 8 cycles, set cache size to 4 x 32. + */ + qptr[3] = 0; + + /* Set up PCI Target address mapping. Enable, Posted writes, + * 2Gbyte space (processor memory controller determines actual size). + */ + qptr[64] = 0x8f000080; + + /* Map processor 0x80000000 to PCI 0x00000000. + * Processor address bit 1 determines I/O type access (0x80000000) + * or memory type access (0xc0000000). + */ + qptr[65] = 0x80000000; + + /* Enable error logging and clear any pending error status. + */ + qptr[80] = 0x90000000; + + qptr[512] = 0x000c0003; + + /* Set up Qbus slave image. + */ + qptr[960] = 0x01000000; + qptr[961] = 0x000000d1; + qptr[964] = 0x00000000; + qptr[965] = 0x000000d1; + +} + +/* Functions to support PCI bios-like features to read/write configuration + * space. If the function fails for any reason, a -1 (0xffffffff) value + * must be returned. + */ +#define DEVICE_NOT_FOUND (-1) +#define SUCCESSFUL 0 + +int qs_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val) +{ + uint temp; + u_char *cp; + + if ((bus > 7) || (dev_fn > 127)) { + *val = 0xff; + return DEVICE_NOT_FOUND; + } + + if (bus == 0) + *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); + else + *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); + __get_pci_config(temp, QS_CONFIG_DATA, "lwz"); + + offset ^= 0x03; + cp = ((u_char *)&temp) + (offset & 0x03); + *val = *cp; + return SUCCESSFUL; +} + +int qs_pci_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val) +{ + uint temp; + ushort *sp; + + if ((bus > 7) || (dev_fn > 127)) { + *val = 0xffff; + return DEVICE_NOT_FOUND; + } + + if (bus == 0) + *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); + else + *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); + __get_pci_config(temp, QS_CONFIG_DATA, "lwz"); + offset ^= 0x02; + + sp = ((ushort *)&temp) + ((offset >> 1) & 1); + *val = *sp; + return SUCCESSFUL; +} + +int qs_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val) +{ + if ((bus > 7) || (dev_fn > 127)) { + *val = 0xffffffff; + return DEVICE_NOT_FOUND; + } + if (bus == 0) + *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); + else + *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); + __get_pci_config(*val, QS_CONFIG_DATA, "lwz"); + return SUCCESSFUL; +} + +int qs_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val) +{ + uint temp; + u_char *cp; + + if ((bus > 7) || (dev_fn > 127)) + return DEVICE_NOT_FOUND; + + qs_pci_read_config_dword(bus, dev_fn, offset, &temp); + + offset ^= 0x03; + cp = ((u_char *)&temp) + (offset & 0x03); + *cp = val; + + if (bus == 0) + *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); + else + *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); + *QS_CONFIG_DATA = temp; + + return SUCCESSFUL; +} + +int qs_pci_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val) +{ + uint temp; + ushort *sp; + + if ((bus > 7) || (dev_fn > 127)) + return DEVICE_NOT_FOUND; + + qs_pci_read_config_dword(bus, dev_fn, offset, &temp); + + offset ^= 0x02; + sp = ((ushort *)&temp) + ((offset >> 1) & 1); + *sp = val; + + if (bus == 0) + *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); + else + *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); + *QS_CONFIG_DATA = temp; + + return SUCCESSFUL; +} + +int qs_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val) +{ + if ((bus > 7) || (dev_fn > 127)) + return DEVICE_NOT_FOUND; + + if (bus == 0) + *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); + else + *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); + *(unsigned int *)QS_CONFIG_DATA = val; + + return SUCCESSFUL; +} + diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S new file mode 100644 index 00000000000..555a216ccc4 --- /dev/null +++ b/arch/ppc/boot/simple/relocate.S @@ -0,0 +1,216 @@ +/* + * arch/ppc/boot/simple/relocate.S + * + * This is the common part of the loader relocation and initialization + * process. All of the board/processor specific initialization is + * done before we get here. + * + * Author: Tom Rini + * trini@mvista.com + * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). + * + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include + +#define GETSYM(reg, sym) \ + lis reg, sym@h; ori reg, reg, sym@l + + .text + /* We get called from the early initialization code. + * Register 3 has the address where we were loaded, + * Register 4 contains any residual data passed from the + * boot rom. + */ + .globl relocate +relocate: + /* Save r3, r4 for later. + * The r8/r11 are legacy registers so I don't have to + * rewrite the code below :-). + */ + mr r8, r3 + mr r11, r4 + + /* compute the size of the whole image in words. */ + GETSYM(r4,start) + GETSYM(r5,end) + + addi r5,r5,3 /* round up */ + sub r5,r5,r4 /* end - start */ + srwi r5,r5,2 + mr r7,r5 /* Save for later use. */ + + /* + * Check if we need to relocate ourselves to the link addr or were + * we loaded there to begin with. + */ + cmpw cr0,r3,r4 + beq start_ldr /* If 0, we don't need to relocate */ + + /* Move this code somewhere safe. This is max(load + size, end) + * r8 == load address + */ + GETSYM(r4, start) + GETSYM(r5, end) + + sub r6,r5,r4 + add r6,r8,r6 /* r6 == phys(load + size) */ + + cmpw r5,r6 + bgt 1f + b 2f +1: + mr r6, r5 +2: + /* dest is in r6 */ + /* Ensure alignment --- this code is precautionary */ + addi r6,r6,4 + li r5,0x0003 + andc r6,r6,r5 + + /* Find physical address and size of do_relocate */ + GETSYM(r5, __relocate_start) + GETSYM(r4, __relocate_end) + GETSYM(r3, start) + + /* Size to copy */ + sub r4,r4,r5 + srwi r4,r4,2 + + /* Src addr to copy (= __relocate_start - start + where_loaded) */ + sub r3,r5,r3 + add r5,r8,r3 + + /* Save dest */ + mr r3, r6 + + /* Do the copy */ + mtctr r4 +3: lwz r4,0(r5) + stw r4,0(r3) + addi r3,r3,4 + addi r5,r5,4 + bdnz 3b + + GETSYM(r4, __relocate_start) + GETSYM(r5, do_relocate) + + sub r4,r5,r4 /* Get entry point for do_relocate in */ + add r6,r6,r4 /* relocated section */ + + /* This will return to the relocated do_relocate */ + mtlr r6 + b flush_instruction_cache + + .section ".relocate_code","xa" + +do_relocate: + /* We have 2 cases --- start < load, or start > load + * This determines whether we copy from the end, or the start. + * Its easier to have 2 loops than to have paramaterised + * loops. Sigh. + */ + li r6,0 /* Clear checksum */ + mtctr r7 /* Setup for a loop */ + + GETSYM(r4, start) + mr r3,r8 /* Get the load addr */ + + cmpw cr0,r4,r3 /* If we need to copy from the end, do so */ + bgt do_relocate_from_end + +do_relocate_from_start: +1: lwz r5,0(r3) /* Load and decrement */ + stw r5,0(r4) /* Store and decrement */ + addi r3,r3,4 + addi r4,r4,4 + xor r6,r6,r5 /* Update checksum */ + bdnz 1b /* Are we done? */ + b do_relocate_out /* Finished */ + +do_relocate_from_end: + GETSYM(r3, end) + slwi r4,r7,2 + add r4,r8,r4 /* Get the physical end */ +1: lwzu r5,-4(r4) + stwu r5, -4(r3) + xor r6,r6,r5 + bdnz 1b + +do_relocate_out: + GETSYM(r3,start_ldr) + mtlr r3 /* Easiest way to do an absolute jump */ +/* Some boards don't boot up with the I-cache enabled. Do that + * now because the decompress runs much faster that way. + * As a side effect, we have to ensure the data cache is not enabled + * so we can access the serial I/O without trouble. + */ + b flush_instruction_cache + + .previous + +start_ldr: +/* Clear all of BSS and set up stack for C calls */ + lis r3,edata@h + ori r3,r3,edata@l + lis r4,end@h + ori r4,r4,end@l + subi r3,r3,4 + subi r4,r4,4 + li r0,0 +50: stwu r0,4(r3) + cmpw cr0,r3,r4 + bne 50b +90: mr r9,r1 /* Save old stack pointer (in case it matters) */ + lis r1,.stack@h + ori r1,r1,.stack@l + addi r1,r1,4096*2 + subi r1,r1,256 + li r2,0x000F /* Mask pointer to 16-byte boundary */ + andc r1,r1,r2 + + /* + * Exec kernel loader + */ + mr r3,r8 /* Load point */ + mr r4,r7 /* Program length */ + mr r5,r6 /* Checksum */ + mr r6,r11 /* Residual data */ + mr r7,r25 /* Validated OFW interface */ + bl load_kernel + + /* + * Make sure the kernel knows we don't have things set in + * registers. -- Tom + */ + li r4,0 + li r5,0 + li r6,0 + + /* + * Start at the begining. + */ +#ifdef CONFIG_PPC_MULTIPLATFORM + li r9,0xc + mtlr r9 + /* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD, + * and tell the kernel to start on the 4th instruction since we + * overwrite the first 3 sometimes (which are 'nop'). + */ + lis r10,0xdeadc0de@h + ori r10,r10,0xdeadc0de@l + li r9,0 + stw r10,0(r9) +#else + li r9,0 + mtlr r9 +#endif + blr + + .comm .stack,4096*2,4 diff --git a/arch/ppc/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h new file mode 100644 index 00000000000..561fb26f5a9 --- /dev/null +++ b/arch/ppc/boot/simple/rw4/ppc_40x.h @@ -0,0 +1,664 @@ +/*----------------------------------------------------------------------------+ +| This source code has been made available to you by IBM on an AS-IS +| basis. Anyone receiving this source is licensed under IBM +| copyrights to use it in any way he or she deems fit, including +| copying it, modifying it, compiling it, and redistributing it either +| with or without modifications. No license under IBM patents or +| patent applications is to be implied by the copyright license. +| +| Any user of this software should understand that IBM cannot provide +| technical support for this software and will not be responsible for +| any consequences resulting from the use of this software. +| +| Any person who transfers this source code or any derivative work +| must include the IBM copyright notice, this paragraph, and the +| preceding two paragraphs in the transferred software. +| +| COPYRIGHT I B M CORPORATION 1997 +| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M ++----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------+ +| Author: Tony J. Cerreto +| Component: Assembler include file. +| File: ppc_40x.h +| Purpose: Include file containing PPC DCR defines. +| +| Changes: +| Date Author Comment +| --------- ------ -------------------------------------------------------- +| 01-Mar-00 tjc Created ++----------------------------------------------------------------------------*/ +/* added by linguohui*/ +#define MW +/*----------------------------------------------------------------------------+ +| PPC Special purpose registers Numbers ++----------------------------------------------------------------------------*/ +#define ccr0 0x3b3 /* core configuration reg */ +#define ctr 0x009 /* count register */ +#define ctrreg 0x009 /* count register */ +#define dbcr0 0x3f2 /* debug control register 0 */ +#define dbcr1 0x3bd /* debug control register 1 */ +#define dbsr 0x3f0 /* debug status register */ +#define dccr 0x3fa /* data cache control reg. */ +#define dcwr 0x3ba /* data cache write-thru reg */ +#define dear 0x3d5 /* data exception address reg */ +#define esr 0x3d4 /* exception syndrome register */ +#define evpr 0x3d6 /* exception vector prefix reg */ +#define iccr 0x3fb /* instruction cache cntrl re */ +#define icdbdr 0x3d3 /* instr cache dbug data reg */ +#define lrreg 0x008 /* link register */ +#define pid 0x3b1 /* process id reg */ +#define pit 0x3db /* programmable interval time */ +#define pvr 0x11f /* processor version register */ +#define sgr 0x3b9 /* storage guarded reg */ +#define sler 0x3bb /* storage little endian reg */ +#define sprg0 0x110 /* special general purpose 0 */ +#define sprg1 0x111 /* special general purpose 1 */ +#define sprg2 0x112 /* special general purpose 2 */ +#define sprg3 0x113 /* special general purpose 3 */ +#define sprg4 0x114 /* special general purpose 4 */ +#define sprg5 0x115 /* special general purpose 5 */ +#define sprg6 0x116 /* special general purpose 6 */ +#define sprg7 0x117 /* special general purpose 7 */ +#define srr0 0x01a /* save/restore register 0 */ +#define srr1 0x01b /* save/restore register 1 */ +#define srr2 0x3de /* save/restore register 2 */ +#define srr3 0x3df /* save/restore register 3 */ +#define tbhi 0x11D +#define tblo 0x11C +#define tcr 0x3da /* timer control register */ +#define tsr 0x3d8 /* timer status register */ +#define xerreg 0x001 /* fixed point exception */ +#define xer 0x001 /* fixed point exception */ +#define zpr 0x3b0 /* zone protection reg */ + +/*----------------------------------------------------------------------------+ +| Decompression Controller ++----------------------------------------------------------------------------*/ +#define kiar 0x014 /* Decompression cntl addr reg */ +#define kidr 0x015 /* Decompression cntl data reg */ +#define kitor0 0x00 /* index table origin Reg 0 */ +#define kitor1 0x01 /* index table origin Reg 1 */ +#define kitor2 0x02 /* index table origin Reg 2 */ +#define kitor3 0x03 /* index table origin Reg 3 */ +#define kaddr0 0x04 /* addr decode Definition Reg 0 */ +#define kaddr1 0x05 /* addr decode Definition Reg 1 */ +#define kconf 0x40 /* Decompression cntl config reg */ +#define kid 0x41 /* Decompression cntl id reg */ +#define kver 0x42 /* Decompression cntl ver number */ +#define kpear 0x50 /* bus error addr reg (PLB) */ +#define kbear 0x51 /* bus error addr reg (DCP-EBC) */ +#define kesr0 0x52 /* bus error status reg 0 */ + +/*----------------------------------------------------------------------------+ +| Romeo Specific Device Control Register Numbers. ++----------------------------------------------------------------------------*/ +#ifndef VESTA +#define cdbcr 0x3d7 /* cache debug cntrl reg */ + +#define a_latcnt 0x1a9 /* PLB Latency count */ +#define a_tgval 0x1ac /* tone generation value */ +#define a_plb_pr 0x1bf /* PLB priority */ + +#define cic_sel1 0x031 /* select register 1 */ +#define cic_sel2 0x032 /* select register 2 */ + +#define clkgcrst 0x122 /* chip reset register */ + +#define cp_cpmsr 0x100 /*rstatus register */ +#define cp_cpmer 0x101 /* enable register */ + +#define dcp_kiar 0x190 /* indirect address register */ +#define dcp_kidr 0x191 /* indirect data register */ + +#define hsmc_mcgr 0x1c0 /* HSMC global register */ +#define hsmc_mcbesr 0x1c1 /* bus error status register */ +#define hsmc_mcbear 0x1c2 /* bus error address register*/ +#define hsmc_mcbr0 0x1c4 /* SDRAM sub-ctrl bank reg 0 */ +#define hsmc_mccr0 0x1c5 /* SDRAM sub-ctrl ctrl reg 0 */ +#define hsmc_mcbr1 0x1c7 /* SDRAM sub-ctrl bank reg 1 */ +#define hsmc_mccr1 0x1c8 /* SDRAM sub-ctrl ctrl reg 1 */ +#define hsmc_sysr 0x1d1 /* system register */ +#define hsmc_data 0x1d2 /* data register */ +#define hsmc_mccrr 0x1d3 /* refresh register */ + +#define ocm_pbar 0x1E0 /* base address register */ + +#define plb0_pacr0 0x057 /* PLB arbiter control reg */ +#define plb1_pacr1 0x067 /* PLB arbiter control reg */ + +#define v_displb 0x157 /* set left border of display*/ +#define v_disptb 0x158 /* top border of display */ +#define v_osd_la 0x159 /* first link address for OSD*/ +#define v_ptsdlta 0x15E /* PTS delta register */ +#define v_v0base 0x16C /* base mem add for VBI-0 */ +#define v_v1base 0x16D /* base mem add for VBI-1 */ +#define v_osbase 0x16E /* base mem add for OSD data */ +#endif + +/*----------------------------------------------------------------------------+ +| Vesta Device Control Register Numbers. ++----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------+ +| Cross bar switch. ++----------------------------------------------------------------------------*/ +#define cbs0_cr 0x010 /* CBS configuration register */ + +/*----------------------------------------------------------------------------+ +| DCR external master (DCRX). ++----------------------------------------------------------------------------*/ +#define dcrx0_icr 0x020 /* internal control register */ +#define dcrx0_isr 0x021 /* internal status register */ +#define dcrx0_ecr 0x022 /* external control register */ +#define dcrx0_esr 0x023 /* external status register */ +#define dcrx0_tar 0x024 /* target address register */ +#define dcrx0_tdr 0x025 /* target data register */ +#define dcrx0_igr 0x026 /* interrupt generation register */ +#define dcrx0_bcr 0x027 /* buffer control register */ + +/*----------------------------------------------------------------------------+ +| Chip interconnect configuration. ++----------------------------------------------------------------------------*/ +#define cic0_cr 0x030 /* CIC control register */ +#define cic0_vcr 0x033 /* video macro control reg */ +#define cic0_sel3 0x035 /* select register 3 */ + +/*----------------------------------------------------------------------------+ +| Chip interconnect configuration. ++----------------------------------------------------------------------------*/ +#define sgpo0_sgpO 0x036 /* simplified GPIO output */ +#define sgpo0_gpod 0x037 /* simplified GPIO open drain */ +#define sgpo0_gptc 0x038 /* simplified GPIO tristate cntl */ +#define sgpo0_gpi 0x039 /* simplified GPIO input */ + +/*----------------------------------------------------------------------------+ +| Universal interrupt controller. ++----------------------------------------------------------------------------*/ +#define uic0_sr 0x040 /* status register */ +#define uic0_srs 0x041 /* status register set */ +#define uic0_er 0x042 /* enable register */ +#define uic0_cr 0x043 /* critical register */ +#define uic0_pr 0x044 /* parity register */ +#define uic0_tr 0x045 /* triggering register */ +#define uic0_msr 0x046 /* masked status register */ +#define uic0_vr 0x047 /* vector register */ +#define uic0_vcr 0x048 /* enable config register */ + +/*----------------------------------------------------------------------------+ +| PLB 0 and 1. ++----------------------------------------------------------------------------*/ +#define pb0_pesr 0x054 /* PLB error status reg 0 */ +#define pb0_pesrs 0x055 /* PLB error status reg 0 set */ +#define pb0_pear 0x056 /* PLB error address reg */ + +#define pb1_pesr 0x064 /* PLB error status reg 1 */ +#define pb1_pesrs 0x065 /* PLB error status reg 1 set */ +#define pb1_pear 0x066 /* PLB error address reg */ + +/*----------------------------------------------------------------------------+ +| EBIU DCR registers. ++----------------------------------------------------------------------------*/ +#define ebiu0_brcrh0 0x070 /* bus region register 0 high */ +#define ebiu0_brcrh1 0x071 /* bus region register 1 high */ +#define ebiu0_brcrh2 0x072 /* bus region register 2 high */ +#define ebiu0_brcrh3 0x073 /* bus region register 3 high */ +#define ebiu0_brcrh4 0x074 /* bus region register 4 high */ +#define ebiu0_brcrh5 0x075 /* bus region register 5 high */ +#define ebiu0_brcrh6 0x076 /* bus region register 6 high */ +#define ebiu0_brcrh7 0x077 /* bus region register 7 high */ +#define ebiu0_brcr0 0x080 /* bus region register 0 */ +#define ebiu0_brcr1 0x081 /* bus region register 1 */ +#define ebiu0_brcr2 0x082 /* bus region register 2 */ +#define ebiu0_brcr3 0x083 /* bus region register 3 */ +#define ebiu0_brcr4 0x084 /* bus region register 4 */ +#define ebiu0_brcr5 0x085 /* bus region register 5 */ +#define ebiu0_brcr6 0x086 /* bus region register 6 */ +#define ebiu0_brcr7 0x087 /* bus region register 7 */ +#define ebiu0_bear 0x090 /* bus error address register */ +#define ebiu0_besr 0x091 /* bus error syndrome reg */ +#define ebiu0_besr0s 0x093 /* bus error syndrome reg */ +#define ebiu0_biucr 0x09a /* bus interface control reg */ + +/*----------------------------------------------------------------------------+ +| OPB bridge. ++----------------------------------------------------------------------------*/ +#define opbw0_gesr 0x0b0 /* error status reg */ +#define opbw0_gesrs 0x0b1 /* error status reg */ +#define opbw0_gear 0x0b2 /* error address reg */ + +/*----------------------------------------------------------------------------+ +| DMA. ++----------------------------------------------------------------------------*/ +#define dma0_cr0 0x0c0 /* DMA channel control reg 0 */ +#define dma0_ct0 0x0c1 /* DMA count register 0 */ +#define dma0_da0 0x0c2 /* DMA destination addr reg 0 */ +#define dma0_sa0 0x0c3 /* DMA source addr register 0 */ +#define dma0_cc0 0x0c4 /* DMA chained count 0 */ +#define dma0_cr1 0x0c8 /* DMA channel control reg 1 */ +#define dma0_ct1 0x0c9 /* DMA count register 1 */ +#define dma0_da1 0x0ca /* DMA destination addr reg 1 */ +#define dma0_sa1 0x0cb /* DMA source addr register 1 */ +#define dma0_cc1 0x0cc /* DMA chained count 1 */ +#define dma0_cr2 0x0d0 /* DMA channel control reg 2 */ +#define dma0_ct2 0x0d1 /* DMA count register 2 */ +#define dma0_da2 0x0d2 /* DMA destination addr reg 2 */ +#define dma0_sa2 0x0d3 /* DMA source addr register 2 */ +#define dma0_cc2 0x0d4 /* DMA chained count 2 */ +#define dma0_cr3 0x0d8 /* DMA channel control reg 3 */ +#define dma0_ct3 0x0d9 /* DMA count register 3 */ +#define dma0_da3 0x0da /* DMA destination addr reg 3 */ +#define dma0_sa3 0x0db /* DMA source addr register 3 */ +#define dma0_cc3 0x0dc /* DMA chained count 3 */ +#define dma0_sr 0x0e0 /* DMA status register */ +#define dma0_srs 0x0e1 /* DMA status register */ +#define dma0_s1 0x031 /* DMA select1 register */ +#define dma0_s2 0x032 /* DMA select2 register */ + +/*---------------------------------------------------------------------------+ +| Clock and power management. ++----------------------------------------------------------------------------*/ +#define cpm0_fr 0x102 /* force register */ + +/*----------------------------------------------------------------------------+ +| Serial Clock Control. ++----------------------------------------------------------------------------*/ +#define ser0_ccr 0x120 /* serial clock control register */ + +/*----------------------------------------------------------------------------+ +| Audio Clock Control. ++----------------------------------------------------------------------------*/ +#define aud0_apcr 0x121 /* audio clock ctrl register */ + +/*----------------------------------------------------------------------------+ +| DENC. ++----------------------------------------------------------------------------*/ +#define denc0_idr 0x130 /* DENC ID register */ +#define denc0_cr1 0x131 /* control register 1 */ +#define denc0_rr1 0x132 /* microvision 1 (reserved 1) */ +#define denc0_cr2 0x133 /* control register 2 */ +#define denc0_rr2 0x134 /* microvision 2 (reserved 2) */ +#define denc0_rr3 0x135 /* microvision 3 (reserved 3) */ +#define denc0_rr4 0x136 /* microvision 4 (reserved 4) */ +#define denc0_rr5 0x137 /* microvision 5 (reserved 5) */ +#define denc0_ccdr 0x138 /* closed caption data */ +#define denc0_cccr 0x139 /* closed caption control */ +#define denc0_trr 0x13A /* teletext request register */ +#define denc0_tosr 0x13B /* teletext odd field line se */ +#define denc0_tesr 0x13C /* teletext even field line s */ +#define denc0_rlsr 0x13D /* RGB rhift left register */ +#define denc0_vlsr 0x13E /* video level shift register */ +#define denc0_vsr 0x13F /* video scaling register */ + +/*----------------------------------------------------------------------------+ +| Video decoder. Suspect 0x179, 0x169, 0x16a, 0x152 (rc). ++----------------------------------------------------------------------------*/ +#define vid0_ccntl 0x140 /* control decoder operation */ +#define vid0_cmode 0x141 /* video operational mode */ +#define vid0_sstc0 0x142 /* STC high order bits 31:0 */ +#define vid0_sstc1 0x143 /* STC low order bit 32 */ +#define vid0_spts0 0x144 /* PTS high order bits 31:0 */ +#define vid0_spts1 0x145 /* PTS low order bit 32 */ +#define vid0_fifo 0x146 /* FIFO data port */ +#define vid0_fifos 0x147 /* FIFO status */ +#define vid0_cmd 0x148 /* send command to decoder */ +#define vid0_cmdd 0x149 /* port for command params */ +#define vid0_cmdst 0x14A /* command status */ +#define vid0_cmdad 0x14B /* command address */ +#define vid0_procia 0x14C /* instruction store */ +#define vid0_procid 0x14D /* data port for I_Store */ +#define vid0_osdm 0x151 /* OSD mode control */ +#define vid0_hosti 0x152 /* base interrupt register */ +#define vid0_mask 0x153 /* interrupt mask register */ +#define vid0_dispm 0x154 /* operational mode for Disp */ +#define vid0_dispd 0x155 /* setting for 'Sync' delay */ +#define vid0_vbctl 0x156 /* VBI */ +#define vid0_ttxctl 0x157 /* teletext control */ +#define vid0_disptb 0x158 /* display left/top border */ +#define vid0_osdgla 0x159 /* Graphics plane link addr */ +#define vid0_osdila 0x15A /* Image plane link addr */ +#define vid0_rbthr 0x15B /* rate buffer threshold */ +#define vid0_osdcla 0x15C /* Cursor link addr */ +#define vid0_stcca 0x15D /* STC common address */ +#define vid0_ptsctl 0x15F /* PTS Control */ +#define vid0_wprot 0x165 /* write protect for I_Store */ +#define vid0_vcqa 0x167 /* video clip queued block Ad */ +#define vid0_vcql 0x168 /* video clip queued block Le */ +#define vid0_blksz 0x169 /* block size bytes for copy op */ +#define vid0_srcad 0x16a /* copy source address bits 6-31 */ +#define vid0_udbas 0x16B /* base mem add for user data */ +#define vid0_vbibas 0x16C /* base mem add for VBI 0/1 */ +#define vid0_osdibas 0x16D /* Image plane base address */ +#define vid0_osdgbas 0x16E /* Graphic plane base address */ +#define vid0_rbbase 0x16F /* base mem add for video buf */ +#define vid0_dramad 0x170 /* DRAM address */ +#define vid0_dramdt 0x171 /* data port for DRAM access */ +#define vid0_dramcs 0x172 /* DRAM command and statusa */ +#define vid0_vcwa 0x173 /* v clip work address */ +#define vid0_vcwl 0x174 /* v clip work length */ +#define vid0_mseg0 0x175 /* segment address 0 */ +#define vid0_mseg1 0x176 /* segment address 1 */ +#define vid0_mseg2 0x177 /* segment address 2 */ +#define vid0_mseg3 0x178 /* segment address 3 */ +#define vid0_fbbase 0x179 /* frame buffer base memory */ +#define vid0_osdcbas 0x17A /* Cursor base addr */ +#define vid0_lboxtb 0x17B /* top left border */ +#define vid0_trdly 0x17C /* transparency gate delay */ +#define vid0_sbord 0x17D /* left/top small pict. bord. */ +#define vid0_zoffs 0x17E /* hor/ver zoom window */ +#define vid0_rbsz 0x17F /* rate buffer size read */ + +/*----------------------------------------------------------------------------+ +| Transport demultiplexer. ++----------------------------------------------------------------------------*/ +#define xpt0_lr 0x180 /* demux location register */ +#define xpt0_data 0x181 /* demux data register */ +#define xpt0_ir 0x182 /* demux interrupt register */ + +#define xpt0_config1 0x0000 /* configuration 1 */ +#define xpt0_control1 0x0001 /* control 1 */ +#define xpt0_festat 0x0002 /* Front-end status */ +#define xpt0_feimask 0x0003 /* Front_end interrupt Mask */ +#define xpt0_ocmcnfg 0x0004 /* OCM Address */ +#define xpt0_settapi 0x0005 /* Set TAP Interrupt */ + +#define xpt0_pcrhi 0x0010 /* PCR High */ +#define xpt0_pcrlow 0x0011 /* PCR Low */ +#define xpt0_lstchi 0x0012 /* Latched STC High */ +#define xpt0_lstclow 0x0013 /* Latched STC Low */ +#define xpt0_stchi 0x0014 /* STC High */ +#define xpt0_stclow 0x0015 /* STC Low */ +#define xpt0_pwm 0x0016 /* PWM */ +#define xpt0_pcrstct 0x0017 /* PCR-STC Threshold */ +#define xpt0_pcrstcd 0x0018 /* PCR-STC Delta */ +#define xpt0_stccomp 0x0019 /* STC Compare */ +#define xpt0_stccmpd 0x001a /* STC Compare Disarm */ + +#define xpt0_dsstat 0x0048 /* Descrambler Status */ +#define xpt0_dsimask 0x0049 /* Descrambler Interrupt Mask */ + +#define xpt0_vcchng 0x01f0 /* Video Channel Change */ +#define xpt0_acchng 0x01f1 /* Audio Channel Change */ +#define xpt0_axenable 0x01fe /* Aux PID Enables */ +#define xpt0_pcrpid 0x01ff /* PCR PID */ + +#define xpt0_config2 0x1000 /* Configuration 2 */ +#define xpt0_pbuflvl 0x1002 /* Packet Buffer Level */ +#define xpt0_intmask 0x1003 /* Interrupt Mask */ +#define xpt0_plbcnfg 0x1004 /* PLB Configuration */ + +#define xpt0_qint 0x1010 /* Queues Interrupts */ +#define xpt0_qintmsk 0x1011 /* Queues Interrupts Mask */ +#define xpt0_astatus 0x1012 /* Audio Status */ +#define xpt0_aintmask 0x1013 /* Audio Interrupt Mask */ +#define xpt0_vstatus 0x1014 /* Video Status */ +#define xpt0_vintmask 0x1015 /* Video Interrupt Mask */ + +#define xpt0_qbase 0x1020 /* Queue Base */ +#define xpt0_bucketq 0x1021 /* Bucket Queue */ +#define xpt0_qstops 0x1024 /* Queue Stops */ +#define xpt0_qresets 0x1025 /* Queue Resets */ +#define xpt0_sfchng 0x1026 /* Section Filter Change */ + +/*----------------------------------------------------------------------------+ +| Audio decoder. Suspect 0x1ad, 0x1b4, 0x1a3, 0x1a5 (read/write status) ++----------------------------------------------------------------------------*/ +#define aud0_ctrl0 0x1a0 /* control 0 */ +#define aud0_ctrl1 0x1a1 /* control 1 */ +#define aud0_ctrl2 0x1a2 /* control 2 */ +#define aud0_cmd 0x1a3 /* command register */ +#define aud0_isr 0x1a4 /* interrupt status register */ +#define aud0_imr 0x1a5 /* interrupt mask register */ +#define aud0_dsr 0x1a6 /* decoder status register */ +#define aud0_stc 0x1a7 /* system time clock */ +#define aud0_csr 0x1a8 /* channel status register */ +#define aud0_lcnt 0x1a9 /* queued address register 2 */ +#define aud0_pts 0x1aa /* presentation time stamp */ +#define aud0_tgctrl 0x1ab /* tone generation control */ +#define aud0_qlr2 0x1ac /* queued length register 2 */ +#define aud0_auxd 0x1ad /* aux data */ +#define aud0_strmid 0x1ae /* stream ID */ +#define aud0_qar 0x1af /* queued address register */ +#define aud0_dsps 0x1b0 /* DSP status */ +#define aud0_qlr 0x1b1 /* queued len address */ +#define aud0_dspc 0x1b2 /* DSP control */ +#define aud0_wlr2 0x1b3 /* working length register 2 */ +#define aud0_instd 0x1b4 /* instruction download */ +#define aud0_war 0x1b5 /* working address register */ +#define aud0_seg1 0x1b6 /* segment 1 base register */ +#define aud0_seg2 0x1b7 /* segment 2 base register */ +#define aud0_avf 0x1b9 /* audio att value front */ +#define aud0_avr 0x1ba /* audio att value rear */ +#define aud0_avc 0x1bb /* audio att value center */ +#define aud0_seg3 0x1bc /* segment 3 base register */ +#define aud0_offset 0x1bd /* offset address */ +#define aud0_wrl 0x1be /* working length register */ +#define aud0_war2 0x1bf /* working address register 2 */ + +/*----------------------------------------------------------------------------+ +| High speed memory controller 0 and 1. ++----------------------------------------------------------------------------*/ +#define hsmc0_gr 0x1e0 /* HSMC global register */ +#define hsmc0_besr 0x1e1 /* bus error status register */ +#define hsmc0_bear 0x1e2 /* bus error address register */ +#define hsmc0_br0 0x1e4 /* SDRAM sub-ctrl bank reg 0 */ +#define hsmc0_cr0 0x1e5 /* SDRAM sub-ctrl ctrl reg 0 */ +#define hsmc0_br1 0x1e7 /* SDRAM sub-ctrl bank reg 1 */ +#define hsmc0_cr1 0x1e8 /* SDRAM sub-ctrl ctrl reg 1 */ +#define hsmc0_sysr 0x1f1 /* system register */ +#define hsmc0_data 0x1f2 /* data register */ +#define hsmc0_crr 0x1f3 /* refresh register */ + +#define hsmc1_gr 0x1c0 /* HSMC global register */ +#define hsmc1_besr 0x1c1 /* bus error status register */ +#define hsmc1_bear 0x1c2 /* bus error address register */ +#define hsmc1_br0 0x1c4 /* SDRAM sub-ctrl bank reg 0 */ +#define hsmc1_cr0 0x1c5 /* SDRAM sub-ctrl ctrl reg 0 */ +#define hsmc1_br1 0x1c7 /* SDRAM sub-ctrl bank reg 1 */ +#define hsmc1_cr1 0x1c8 /* SDRAM sub-ctrl ctrl reg 1 */ +#define hsmc1_sysr 0x1d1 /* system register */ +#define hsmc1_data 0x1d2 /* data register */ +#define hsmc1_crr 0x1d3 /* refresh register */ + +/*----------------------------------------------------------------------------+ +| Machine State Register bit definitions. ++----------------------------------------------------------------------------*/ +#define msr_ape 0x00100000 +#define msr_apa 0x00080000 +#define msr_we 0x00040000 +#define msr_ce 0x00020000 +#define msr_ile 0x00010000 +#define msr_ee 0x00008000 +#define msr_pr 0x00004000 +#define msr_me 0x00001000 +#define msr_de 0x00000200 +#define msr_ir 0x00000020 +#define msr_dr 0x00000010 +#define msr_le 0x00000001 + +/*----------------------------------------------------------------------------+ +| Used during interrupt processing. ++----------------------------------------------------------------------------*/ +#define stack_reg_image_size 160 + +/*----------------------------------------------------------------------------+ +| Function prolog definition and other Metaware (EABI) defines. ++----------------------------------------------------------------------------*/ +#ifdef MW + +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + +#define function_prolog(func_name) .text; \ + .align 2; \ + .globl func_name; \ + func_name: +#define function_epilog(func_name) .type func_name,@function; \ + .size func_name,.-func_name + +#define function_call(func_name) bl func_name + +#define stack_frame_min 8 +#define stack_frame_bc 0 +#define stack_frame_lr 4 +#define stack_neg_off 0 + +#endif + +/*----------------------------------------------------------------------------+ +| Function prolog definition and other DIAB (Elf) defines. ++----------------------------------------------------------------------------*/ +#ifdef ELF_DIAB + +fprolog: macro f_name + .text + .align 2 + .globl f_name +f_name: + endm + +fepilog: macro f_name + .type f_name,@function + .size f_name,.-f_name + endm + +#define function_prolog(func_name) fprolog func_name +#define function_epilog(func_name) fepilog func_name +#define function_call(func_name) bl func_name + +#define stack_frame_min 8 +#define stack_frame_bc 0 +#define stack_frame_lr 4 +#define stack_neg_off 0 + +#endif + +/*----------------------------------------------------------------------------+ +| Function prolog definition and other Xlc (XCOFF) defines. ++----------------------------------------------------------------------------*/ +#ifdef XCOFF + +.machine "403ga" + +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + +#define function_prolog(func_name) .csect .func_name[PR]; \ + .globl .func_name[PR]; \ + func_name: + +#define function_epilog(func_name) .toc; \ + .csect func_name[DS]; \ + .globl func_name[DS]; \ + .long .func_name[PR]; \ + .long TOC[tc0] + +#define function_call(func_name) .extern .func_name[PR]; \ + stw r2,stack_frame_toc(r1); \ + mfspr r2,sprg0; \ + bl .func_name[PR]; \ + lwz r2,stack_frame_toc(r1) + +#define stack_frame_min 56 +#define stack_frame_bc 0 +#define stack_frame_lr 8 +#define stack_frame_toc 20 +#define stack_neg_off 276 + +#endif +#define function_prolog(func_name) .text; \ + .align 2; \ + .globl func_name; \ + func_name: +#define function_epilog(func_name) .type func_name,@function; \ + .size func_name,.-func_name + +#define function_call(func_name) bl func_name + +/*----------------------------------------------------------------------------+ +| Function prolog definition for GNU ++----------------------------------------------------------------------------*/ +#ifdef _GNU_TOOL + +#define function_prolog(func_name) .globl func_name; \ + func_name: +#define function_epilog(func_name) + +#endif diff --git a/arch/ppc/boot/simple/rw4/rw4_init.S b/arch/ppc/boot/simple/rw4/rw4_init.S new file mode 100644 index 00000000000..b1061962e46 --- /dev/null +++ b/arch/ppc/boot/simple/rw4/rw4_init.S @@ -0,0 +1,78 @@ +#define VESTA +#include "ppc_40x.h" +# + .align 2 + .text +# +# added by linguohui + .extern initb_ebiu0, initb_config, hdw_init_finish + .extern initb_hsmc0, initb_hsmc1, initb_cache +# end added + .globl HdwInit +# +HdwInit: +# +#-----------------------------------------------------------------------* +# If we are not executing from the FLASH get out * +#-----------------------------------------------------------------------* +# SAW keep this or comment out a la Hawthorne? +# r3 contains NIP when used with Linux +# rlwinm r28, r3, 8, 24, 31 # if MSB == 0xFF -> FLASH address +# cmpwi r28, 0xff +# bne locn01 +# +# +#------------------------------------------------------------------------ +# Init_cpu. Bank registers are setup for the IBM STB. +#------------------------------------------------------------------------ +# +# Setup processor core clock to be driven off chip. This is GPI4 bit +# twenty. Setup Open Drain, Output Select, Three-State Control, and +# Three-State Select registers. +# + + + pb0pesr = 0x054 + pb0pear = 0x056 + + mflr r30 + +#----------------------------------------------------------------------------- +# Vectors will be at 0x1F000000 +# Dummy Machine check handler just does RFI before true handler gets installed +#----------------------------------------------------------------------------- +#if 1 /* xuwentao added*/ +#ifdef SDRAM16MB + lis r10,0x0000 + addi r10,r10,0x0000 +#else + lis r10,0x1F00 + addi r10,r10,0x0000 +#endif + + mtspr evpr,r10 #EVPR: 0x0 or 0x1f000000 depending + isync # on SDRAM memory model used. + + lis r10,0xFFFF # clear PB0_PESR because some + ori r10,r10,0xFFFF # transitions from flash,changed by linguohui + mtdcr pb0pesr,r10 # to load RAM image via RiscWatch + lis r10,0x0000 # cause PB0_PESR machine checks + mtdcr pb0pear,r10 + addis r10,r10,0x0000 # clear the + mtxer r10 # XER just in case... +#endif /* xuwentao*/ + + bl initb_ebiu0 # init EBIU + + bl initb_config # config PPC and board + + + + +#------------------------------------------------------------------------ +# EVPR setup moved to top of this function. +#------------------------------------------------------------------------ +# + mtlr r30 + blr + .end diff --git a/arch/ppc/boot/simple/rw4/rw4_init_brd.S b/arch/ppc/boot/simple/rw4/rw4_init_brd.S new file mode 100644 index 00000000000..386afdaad6c --- /dev/null +++ b/arch/ppc/boot/simple/rw4/rw4_init_brd.S @@ -0,0 +1,1125 @@ +/*----------------------------------------------------------------------------+ +| This source code has been made available to you by IBM on an AS-IS +| basis. Anyone receiving this source is licensed under IBM +| copyrights to use it in any way he or she deems fit, including +| copying it, modifying it, compiling it, and redistributing it either +| with or without modifications. No license under IBM patents or +| patent applications is to be implied by the copyright license. +| +| Any user of this software should understand that IBM cannot provide +| technical support for this software and will not be responsible for +| any consequences resulting from the use of this software. +| +| Any person who transfers this source code or any derivative work +| must include the IBM copyright notice, this paragraph, and the +| preceding two paragraphs in the transferred software. +| +| COPYRIGHT I B M CORPORATION 1997 +| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M ++----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------+ +| Author: Tony J. Cerreto +| Component: BSPS +| File: init_brd.s +| Purpose: Vesta Evaluation Board initialization subroutines. The following +| routines are available: +| 1. INITB_EBIU0: Initialize EBIU0. +| 2. INITB_CONFIG: Configure board. +| 3. INITB_HSMC0: Initialize HSMC0 (SDRAM). +| 4. INITB_HSMC1: Initialize HSMC1 (SDRAM). +| 5. INITB_CACHE: Initialize Data and Instruction Cache. +| 6. INITB_DCACHE: Initialize Data Cache. +| 7. INITB_ICACHE: Initialize Instruction Cache. +| 8. INITB_GET_CSPD: Get CPU Speed (Bus Speed and Processor Speed) +| +| Changes: +| Date: Author Comment: +| --------- ------ -------- +| 01-Mar-00 tjc Created +| 04-Mar-00 jfh Modified CIC_SEL3_VAL to support 1284 (Mux3 & GPIO 21-28) +| 04-Mar-00 jfh Modified XILINIX Reg 0 to support 1284 (Mux3 & GPIO 21-28) +| 04-Mar-00 jfh Modified XILINIX Reg 1 to support 1284 (Mux3 & GPIO 21-28) +| 04-Mar-00 jfh Modified XILINIX Reg 4 to support 1284 (Mux3 & GPIO 21-28) +| 19-May-00 rlb Relcoated HSMC0 to 0x1F000000 to support 32MB of contiguous +| SDRAM space. Changed cache ctl regs to reflect this. +| 22-May-00 tjc Changed initb_get_cspd interface and eliminated +| initb_get_bspd routines. +| 26-May-00 tjc Added two nop instructions after all mtxxx/mfxxx +| instructions due to PPC405 bug. ++----------------------------------------------------------------------------*/ +#define VESTA +#include "ppc_40x.h" +#include "stb.h" + +/*----------------------------------------------------------------------------+ +| BOARD CONFIGURATION DEFINES ++----------------------------------------------------------------------------*/ +#define CBS0_CR_VAL 0x00000002 /* CBS control reg value */ +#define CIC0_CR_VAL 0xD0800448 /* CIC control reg value */ +#define CIC0_SEL3_VAL 0x11500000 /* CIC select 3 reg value */ +#define CIC0_VCR_VAL 0x00631700 /* CIC video cntl reg value */ + +/*----------------------------------------------------------------------------+ +| EBIU0 BANK REGISTERS DEFINES ++----------------------------------------------------------------------------*/ +#define EBIU0_BRCRH0_VAL 0x00000000 /* BR High 0 (Extension Reg)*/ +#define EBIU0_BRCRH1_VAL 0x00000000 /* BR High 1 (Extension Reg)*/ +#define EBIU0_BRCRH2_VAL 0x40000000 /* BR High 2 (Extension Reg)*/ +#define EBIU0_BRCRH3_VAL 0x40000000 /* BR High 3 (Extension Reg)*/ +#define EBIU0_BRCRH4_VAL 0x00000000 /* BR High 4 (Extension Reg)*/ +#define EBIU0_BRCRH5_VAL 0x00000000 /* BR High 5 (Extension Reg)*/ +#define EBIU0_BRCRH6_VAL 0x00000000 /* BR High 6 (Extension Reg)*/ +#define EBIU0_BRCRH7_VAL 0x40000000 /* BR High 7 (Extension Reg)*/ + +#define EBIU0_BRCR0_VAL 0xFC58BFFE /* BR 0: 16 bit Flash 4 MB */ +#define EBIU0_BRCR1_VAL 0xFF00BFFE /* BR 1: Ext Connector 1 MB */ +#if 1 +#define EBIU0_BRCR2_VAL 0x207CFFBE /* BR 2: Xilinx 8 MB */ + /* twt == 0x3f */ +#else +#define EBIU0_BRCR2_VAL 0x207CCFBE /* BR 2: Xilinx 8 MB */ + /* twt == 0x0f */ +#endif +#define EBIU0_BRCR3_VAL 0x407CBFBE /* BR 3: IDE Drive 8 MB */ +#define EBIU0_BRCR4_VAL 0xFF00BFFF /* BR 4: Disabled. 0 MB */ +#define EBIU0_BRCR5_VAL 0xFF00BFFF /* BR 5: Disabled. 0 MB */ +#define EBIU0_BRCR6_VAL 0xFF00BFFF /* BR 6: Disabled. 0 MB */ +#define EBIU0_BRCR7_VAL 0xCE3F0003 /* BR 7: Line Mode DMA 2 MB */ + +/*----------------------------------------------------------------------------+ +| GPIO DEFINES ++----------------------------------------------------------------------------*/ +#define STB_GPIO0_OUTPUT (STB_GPIO0_BASE_ADDRESS+ 0x00) +#define STB_GPIO0_TC (STB_GPIO0_BASE_ADDRESS+ 0x04) +#define STB_GPIO0_OS_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x08) +#define STB_GPIO0_OS_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x0C) +#define STB_GPIO0_TS_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x10) +#define STB_GPIO0_TS_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x14) +#define STB_GPIO0_OD (STB_GPIO0_BASE_ADDRESS+ 0x18) +#define STB_GPIO0_INPUT (STB_GPIO0_BASE_ADDRESS+ 0x1C) +#define STB_GPIO0_R1 (STB_GPIO0_BASE_ADDRESS+ 0x20) +#define STB_GPIO0_R2 (STB_GPIO0_BASE_ADDRESS+ 0x24) +#define STB_GPIO0_R3 (STB_GPIO0_BASE_ADDRESS+ 0x28) +#define STB_GPIO0_IS_1_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x30) +#define STB_GPIO0_IS_1_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x34) +#define STB_GPIO0_IS_2_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x38) +#define STB_GPIO0_IS_2_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x3C) +#define STB_GPIO0_IS_3_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x40) +#define STB_GPIO0_IS_3_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x44) +#define STB_GPIO0_SS_1 (STB_GPIO0_BASE_ADDRESS+ 0x50) +#define STB_GPIO0_SS_2 (STB_GPIO0_BASE_ADDRESS+ 0x54) +#define STB_GPIO0_SS_3 (STB_GPIO0_BASE_ADDRESS+ 0x58) + +#define GPIO0_TC_VAL 0x0C020004 /* three-state control val */ +#define GPIO0_OS_0_31_VAL 0x51A00004 /* output select 0-31 val */ +#define GPIO0_OS_32_63_VAL 0x0000002F /* output select 32-63 val */ +#define GPIO0_TS_0_31_VAL 0x51A00000 /* three-state sel 0-31 val*/ +#define GPIO0_TS_32_63_VAL 0x0000000F /* three-state sel 32-63 val*/ +#define GPIO0_OD_VAL 0xC0000004 /* open drain val */ +#define GPIO0_IS_1_0_31_VAL 0x50000151 /* input select 1 0-31 val */ +#define GPIO0_IS_1_32_63_VAL 0x00000000 /* input select 1 32-63 val */ +#define GPIO0_IS_2_0_31_VAL 0x00000000 /* input select 2 0-31 val */ +#define GPIO0_IS_2_32_63_VAL 0x00000000 /* input select 2 32-63 val */ +#define GPIO0_IS_3_0_31_VAL 0x00000440 /* input select 3 0-31 val */ +#define GPIO0_IS_3_32_63_VAL 0x00000000 /* input select 3 32-63 val */ +#define GPIO0_SS_1_VAL 0x00000000 /* sync select 1 val */ +#define GPIO0_SS_2_VAL 0x00000000 /* sync select 2 val */ +#define GPIO0_SS_3_VAL 0x00000000 /* sync select 3 val */ + +/*----------------------------------------------------------------------------+ +| XILINX DEFINES ++----------------------------------------------------------------------------*/ +#define STB_XILINX_LED (STB_FPGA_BASE_ADDRESS+ 0x0100) +#define STB_XILINX1_REG0 (STB_FPGA_BASE_ADDRESS+ 0x40000) +#define STB_XILINX1_REG1 (STB_FPGA_BASE_ADDRESS+ 0x40002) +#define STB_XILINX1_REG2 (STB_FPGA_BASE_ADDRESS+ 0x40004) +#define STB_XILINX1_REG3 (STB_FPGA_BASE_ADDRESS+ 0x40006) +#define STB_XILINX1_REG4 (STB_FPGA_BASE_ADDRESS+ 0x40008) +#define STB_XILINX1_REG5 (STB_FPGA_BASE_ADDRESS+ 0x4000A) +#define STB_XILINX1_REG6 (STB_FPGA_BASE_ADDRESS+ 0x4000C) +#define STB_XILINX1_ID (STB_FPGA_BASE_ADDRESS+ 0x4000E) +#define STB_XILINX1_FLUSH (STB_FPGA_BASE_ADDRESS+ 0x4000E) +#define STB_XILINX2_REG0 (STB_FPGA_BASE_ADDRESS+ 0x80000) +#define STB_XILINX2_REG1 (STB_FPGA_BASE_ADDRESS+ 0x80002) +#define STB_XILINX2_REG2 (STB_FPGA_BASE_ADDRESS+ 0x80004) + +#define XILINX1_R0_VAL 0x2440 /* Xilinx 1 Register 0 Val */ +#define XILINX1_R1_VAL 0x0025 /* Xilinx 1 Register 1 Val */ +#define XILINX1_R2_VAL 0x0441 /* Xilinx 1 Register 2 Val */ +#define XILINX1_R3_VAL 0x0008 /* Xilinx 1 Register 3 Val */ +#define XILINX1_R4_VAL 0x0100 /* Xilinx 1 Register 4 Val */ +#define XILINX1_R5_VAL 0x6810 /* Xilinx 1 Register 5 Val */ +#define XILINX1_R6_VAL 0x0000 /* Xilinx 1 Register 6 Val */ +#if 0 +#define XILINX2_R0_VAL 0x0008 /* Xilinx 2 Register 0 Val */ +#define XILINX2_R1_VAL 0x0000 /* Xilinx 2 Register 1 Val */ +#else +#define XILINX2_R0_VAL 0x0018 /* disable IBM IrDA RxD */ +#define XILINX2_R1_VAL 0x0008 /* enable SICC MAX chip */ +#endif +#define XILINX2_R2_VAL 0x0000 /* Xilinx 2 Register 2 Val */ + +/*----------------------------------------------------------------------------+ +| HSMC BANK REGISTERS DEFINES ++----------------------------------------------------------------------------*/ +#ifdef SDRAM16MB +#define HSMC0_BR0_VAL 0x000D2D55 /* 0x1F000000-007FFFFF R/W */ +#define HSMC0_BR1_VAL 0x008D2D55 /* 0x1F800000-1FFFFFFF R/W */ +#else +#define HSMC0_BR0_VAL 0x1F0D2D55 /* 0x1F000000-007FFFFF R/W */ +#define HSMC0_BR1_VAL 0x1F8D2D55 /* 0x1F800000-1FFFFFFF R/W */ +#endif +#define HSMC1_BR0_VAL 0xA00D2D55 /* 0xA0000000-A07FFFFF R/W */ +#define HSMC1_BR1_VAL 0xA08D2D55 /* 0xA0800000-A0FFFFFF R/W */ + +/*----------------------------------------------------------------------------+ +| CACHE DEFINES ++----------------------------------------------------------------------------*/ +#define DCACHE_NLINES 128 /* no. D-cache lines */ +#define DCACHE_NBYTES 32 /* no. bytes/ D-cache line */ +#define ICACHE_NLINES 256 /* no. I-cache lines */ +#define ICACHE_NBYTES 32 /* no. bytes/ I-cache line */ +#ifdef SDRAM16MB +#define DCACHE_ENABLE 0x80000000 /* D-cache regions to enable*/ +#define ICACHE_ENABLE 0x80000001 /* I-cache regions to enable*/ +#else +#define DCACHE_ENABLE 0x18000000 /* D-cache regions to enable*/ +#define ICACHE_ENABLE 0x18000001 /* I-cache regions to enable*/ +#endif + +/*----------------------------------------------------------------------------+ +| CPU CORE SPEED CALCULATION DEFINES ++----------------------------------------------------------------------------*/ +#define GCS_LCNT 500000 /* CPU speed loop count */ +#define GCS_TROW_BYTES 8 /* no. bytes in table row */ +#define GCS_CTICK_TOL 100 /* allowable clock tick tol */ +#define GCS_NMULT 4 /* no. of core speed mults */ + + /*--------------------------------------------------------------------+ + | No. 13.5Mhz + | Clock Ticks + | based on a + | loop count Bus + | of 100,000 Speed + +--------------------------------------------------------------------*/ +gcs_lookup_table: + .int 50000, 54000000 /* 54.0 Mhz */ + .int 66667, 40500000 /* 40.5 Mhz */ + .int 54545, 49500000 /* 49.5 Mhz */ + .int 46154, 58500000 /* 58.5 Mhz */ + .int 0, 0 /* end of table flag */ + + +/*****************************************************************************+ +| XXXXXXX XXX XXX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX +| XX X XX XX X XX X XX X XX XX XXX XX XXXX XX +| XX X XXX XX XX X XX XX XXXX XX XX XX XX +| XXXX X XX XXXX XXXXX XX XXXX XX XX XX +| XX X XXX XX XX X XX XX XX XXX XXXXXX XX +| XX X XX XX XX XX X XX XX XX XX XX XX XX XX +| XXXXXXX XXX XXX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX ++*****************************************************************************/ +/****************************************************************************** +| +| Routine: INITB_EBIU0. +| +| Purpose: Initialize all the EBIU0 Bank Registers +| Parameters: None. +| Returns: None. +| +******************************************************************************/ + function_prolog(initb_ebiu0) + /*--------------------------------------------------------------------+ + | Set EBIU0 Bank 0 + +--------------------------------------------------------------------*/ + lis r10,EBIU0_BRCR0_VAL@h + ori r10,r10,EBIU0_BRCR0_VAL@l + mtdcr ebiu0_brcr0,r10 + lis r10,EBIU0_BRCRH0_VAL@h + ori r10,r10,EBIU0_BRCRH0_VAL@l + mtdcr ebiu0_brcrh0,r10 + + /*--------------------------------------------------------------------+ + | Set EBIU0 Bank 1 + +--------------------------------------------------------------------*/ + lis r10,EBIU0_BRCR1_VAL@h + ori r10,r10,EBIU0_BRCR1_VAL@l + mtdcr ebiu0_brcr1,r10 + lis r10,EBIU0_BRCRH1_VAL@h + ori r10,r10,EBIU0_BRCRH1_VAL@l + mtdcr ebiu0_brcrh1,r10 + + /*--------------------------------------------------------------------+ + | Set EBIU0 Bank 2 + +--------------------------------------------------------------------*/ + lis r10,EBIU0_BRCR2_VAL@h + ori r10,r10,EBIU0_BRCR2_VAL@l + mtdcr ebiu0_brcr2,r10 + lis r10,EBIU0_BRCRH2_VAL@h + ori r10,r10,EBIU0_BRCRH2_VAL@l + mtdcr ebiu0_brcrh2,r10 + + /*--------------------------------------------------------------------+ + | Set EBIU0 Bank 3 + +--------------------------------------------------------------------*/ + lis r10,EBIU0_BRCR3_VAL@h + ori r10,r10,EBIU0_BRCR3_VAL@l + mtdcr ebiu0_brcr3,r10 + lis r10,EBIU0_BRCRH3_VAL@h + ori r10,r10,EBIU0_BRCRH3_VAL@l + mtdcr ebiu0_brcrh3,r10 + + /*--------------------------------------------------------------------+ + | Set EBIU0 Bank 4 + +--------------------------------------------------------------------*/ + lis r10,EBIU0_BRCR4_VAL@h + ori r10,r10,EBIU0_BRCR4_VAL@l + mtdcr ebiu0_brcr4,r10 + lis r10,EBIU0_BRCRH4_VAL@h + ori r10,r10,EBIU0_BRCRH4_VAL@l + mtdcr ebiu0_brcrh4,r10 + + /*--------------------------------------------------------------------+ + | Set EBIU0 Bank 5 + +--------------------------------------------------------------------*/ + lis r10,EBIU0_BRCR5_VAL@h + ori r10,r10,EBIU0_BRCR5_VAL@l + mtdcr ebiu0_brcr5,r10 + lis r10,EBIU0_BRCRH5_VAL@h + ori r10,r10,EBIU0_BRCRH5_VAL@l + mtdcr ebiu0_brcrh5,r10 + + /*--------------------------------------------------------------------+ + | Set EBIU0 Bank 6 + +--------------------------------------------------------------------*/ + lis r10,EBIU0_BRCR6_VAL@h + ori r10,r10,EBIU0_BRCR6_VAL@l + mtdcr ebiu0_brcr6,r10 + lis r10,EBIU0_BRCRH6_VAL@h + ori r10,r10,EBIU0_BRCRH6_VAL@l + mtdcr ebiu0_brcrh6,r10 + + /*--------------------------------------------------------------------+ + | Set EBIU0 Bank 7 + +--------------------------------------------------------------------*/ + lis r10,EBIU0_BRCR7_VAL@h + ori r10,r10,EBIU0_BRCR7_VAL@l + mtdcr ebiu0_brcr7,r10 + lis r10,EBIU0_BRCRH7_VAL@h + ori r10,r10,EBIU0_BRCRH7_VAL@l + mtdcr ebiu0_brcrh7,r10 + + blr + function_epilog(initb_ebiu0) + + +/****************************************************************************** +| +| Routine: INITB_CONFIG +| +| Purpose: Configure the Vesta Evaluation Board. The following items +| will be configured: +| 1. Cross-Bar Switch. +| 2. Chip Interconnect. +| 3. Clear/reset key PPC registers. +| 4. Xilinx and GPIO Registers. +| +| Returns: None. +| +******************************************************************************/ + function_prolog(initb_config) + /*--------------------------------------------------------------------+ + | Init CROSS-BAR SWITCH + +--------------------------------------------------------------------*/ + lis r10,CBS0_CR_VAL@h /* r10 <- CBS Cntl Reg val */ + ori r10,r10,CBS0_CR_VAL@l + mtdcr cbs0_cr,r10 + + /*--------------------------------------------------------------------+ + | Init Chip-Interconnect (CIC) Registers + +--------------------------------------------------------------------*/ + lis r10,CIC0_CR_VAL@h /* r10 <- CIC Cntl Reg val */ + ori r10,r10,CIC0_CR_VAL@l + mtdcr cic0_cr,r10 + + lis r10,CIC0_SEL3_VAL@h /* r10 <- CIC SEL3 Reg val */ + ori r10,r10,CIC0_SEL3_VAL@l + mtdcr cic0_sel3,r10 + + lis r10,CIC0_VCR_VAL@h /* r10 <- CIC Vid C-Reg val */ + ori r10,r10,CIC0_VCR_VAL@l + mtdcr cic0_vcr,r10 + + /*--------------------------------------------------------------------+ + | Clear SGR and DCWR + +--------------------------------------------------------------------*/ + li r10,0x0000 + mtspr sgr,r10 + mtspr dcwr,r10 + + /*--------------------------------------------------------------------+ + | Clear/set up some machine state registers. + +--------------------------------------------------------------------*/ + li r10,0x0000 /* r10 <- 0 */ + mtdcr ebiu0_besr,r10 /* clr Bus Err Syndrome Reg */ + mtspr esr,r10 /* clr Exceptn Syndrome Reg */ + mttcr r10 /* timer control register */ + + mtdcr uic0_er,r10 /* disable all interrupts */ + + /* UIC_IIC0 | UIC_IIC1 | UIC_U0 | UIC_IR_RCV | UIC_IR_XMIT */ + lis r10, 0x00600e00@h + ori r10,r10,0x00600e00@l + mtdcr uic0_pr,r10 + + li r10,0x00000020 /* UIC_EIR1 */ + mtdcr uic0_tr,r10 + + lis r10,0xFFFF /* r10 <- 0xFFFFFFFF */ + ori r10,r10,0xFFFF /* */ + mtdbsr r10 /* clear/reset the dbsr */ + mtdcr uic0_sr,r10 /* clear pending interrupts */ + + li r10,0x1000 /* set Machine Exception bit*/ + oris r10,r10,0x2 /* set Criticl Exception bit*/ + mtmsr r10 /* change MSR */ + + /*--------------------------------------------------------------------+ + | Clear XER. + +--------------------------------------------------------------------*/ + li r10,0x0000 + mtxer r10 + + /*--------------------------------------------------------------------+ + | Init GPIO0 Registers + +--------------------------------------------------------------------*/ + lis r10, STB_GPIO0_TC@h /* Three-state control */ + ori r10,r10,STB_GPIO0_TC@l + lis r11, GPIO0_TC_VAL@h + ori r11,r11,GPIO0_TC_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_OS_0_31@h /* output select 0-31 */ + ori r10,r10,STB_GPIO0_OS_0_31@l + lis r11, GPIO0_OS_0_31_VAL@h + ori r11,r11,GPIO0_OS_0_31_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_OS_32_63@h /* output select 32-63 */ + ori r10,r10,STB_GPIO0_OS_32_63@l + lis r11, GPIO0_OS_32_63_VAL@h + ori r11,r11,GPIO0_OS_32_63_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_TS_0_31@h /* three-state select 0-31 */ + ori r10,r10,STB_GPIO0_TS_0_31@l + lis r11, GPIO0_TS_0_31_VAL@h + ori r11,r11,GPIO0_TS_0_31_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_TS_32_63@h /* three-state select 32-63 */ + ori r10,r10,STB_GPIO0_TS_32_63@l + lis r11, GPIO0_TS_32_63_VAL@h + ori r11,r11,GPIO0_TS_32_63_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_OD@h /* open drain */ + ori r10,r10,STB_GPIO0_OD@l + lis r11, GPIO0_OD_VAL@h + ori r11,r11,GPIO0_OD_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_IS_1_0_31@h /* input select 1, 0-31 */ + ori r10,r10,STB_GPIO0_IS_1_0_31@l + lis r11, GPIO0_IS_1_0_31_VAL@h + ori r11,r11,GPIO0_IS_1_0_31_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_IS_1_32_63@h /* input select 1, 32-63 */ + ori r10,r10,STB_GPIO0_IS_1_32_63@l + lis r11, GPIO0_IS_1_32_63_VAL@h + ori r11,r11,GPIO0_IS_1_32_63_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_IS_2_0_31@h /* input select 2, 0-31 */ + ori r10,r10,STB_GPIO0_IS_2_0_31@l + lis r11, GPIO0_IS_2_0_31_VAL@h + ori r11,r11,GPIO0_IS_2_0_31_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_IS_2_32_63@h /* input select 2, 32-63 */ + ori r10,r10,STB_GPIO0_IS_2_32_63@l + lis r11, GPIO0_IS_2_32_63_VAL@h + ori r11,r11,GPIO0_IS_2_32_63_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_IS_3_0_31@h /* input select 3, 0-31 */ + ori r10,r10,STB_GPIO0_IS_3_0_31@l + lis r11, GPIO0_IS_3_0_31_VAL@h + ori r11,r11,GPIO0_IS_3_0_31_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_IS_3_32_63@h /* input select 3, 32-63 */ + ori r10,r10,STB_GPIO0_IS_3_32_63@l + lis r11, GPIO0_IS_3_32_63_VAL@h + ori r11,r11,GPIO0_IS_3_32_63_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_SS_1@h /* sync select 1 */ + ori r10,r10,STB_GPIO0_SS_1@l + lis r11, GPIO0_SS_1_VAL@h + ori r11,r11,GPIO0_SS_1_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_SS_2@h /* sync select 2 */ + ori r10,r10,STB_GPIO0_SS_2@l + lis r11, GPIO0_SS_2_VAL@h + ori r11,r11,GPIO0_SS_2_VAL@l + stw r11,0(r10) + + lis r10, STB_GPIO0_SS_3@h /* sync select 3 */ + ori r10,r10,STB_GPIO0_SS_3@l + lis r11, GPIO0_SS_3_VAL@h + ori r11,r11,GPIO0_SS_3_VAL@l + stw r11,0(r10) + + /*--------------------------------------------------------------------+ + | Init Xilinx #1 Registers + +--------------------------------------------------------------------*/ + lis r10, STB_XILINX1_REG0@h /* init Xilinx1 Reg 0 */ + ori r10,r10,STB_XILINX1_REG0@l + li r11,XILINX1_R0_VAL + sth r11,0(r10) + + lis r10, STB_XILINX1_REG1@h /* init Xilinx1 Reg 1 */ + ori r10,r10,STB_XILINX1_REG1@l + li r11,XILINX1_R1_VAL + sth r11,0(r10) + + lis r10, STB_XILINX1_REG2@h /* init Xilinx1 Reg 2 */ + ori r10,r10,STB_XILINX1_REG2@l + li r11,XILINX1_R2_VAL + sth r11,0(r10) + + lis r10, STB_XILINX1_REG3@h /* init Xilinx1 Reg 3 */ + ori r10,r10,STB_XILINX1_REG3@l + li r11,XILINX1_R3_VAL + sth r11,0(r10) + + lis r10, STB_XILINX1_REG4@h /* init Xilinx1 Reg 4 */ + ori r10,r10,STB_XILINX1_REG4@l + li r11,XILINX1_R4_VAL + sth r11,0(r10) + + lis r10, STB_XILINX1_REG5@h /* init Xilinx1 Reg 5 */ + ori r10,r10,STB_XILINX1_REG5@l + li r11,XILINX1_R5_VAL + sth r11,0(r10) + + lis r10, STB_XILINX1_REG6@h /* init Xilinx1 Reg 6 */ + ori r10,r10,STB_XILINX1_REG6@l + li r11,XILINX1_R6_VAL + sth r11,0(r10) + + lis r10, STB_XILINX1_FLUSH@h /* latch registers in Xilinx*/ + ori r10,r10,STB_XILINX1_FLUSH@l + li r11,0x0000 + sth r11,0(r10) + + /*--------------------------------------------------------------------+ + | Init Xilinx #2 Registers + +--------------------------------------------------------------------*/ + lis r10, STB_XILINX2_REG0@h /* init Xilinx2 Reg 0 */ + ori r10,r10,STB_XILINX2_REG0@l + li r11,XILINX2_R0_VAL + sth r11,0(r10) + + lis r10, STB_XILINX2_REG1@h /* init Xilinx2 Reg 1 */ + ori r10,r10,STB_XILINX2_REG1@l + li r11,XILINX2_R1_VAL + sth r11,0(r10) + + lis r10, STB_XILINX2_REG2@h /* init Xilinx2 Reg 2 */ + ori r10,r10,STB_XILINX2_REG2@l + li r11,XILINX2_R2_VAL + sth r11,0(r10) + + blr + function_epilog(initb_config) + + +/****************************************************************************** +| +| Routine: INITB_HSMC0. +| +| Purpose: Initialize the HSMC0 Registers for SDRAM +| Parameters: None. +| Returns: R3 = 0: Successful +| = -1: Unsuccessful, SDRAM did not reset properly. +| +******************************************************************************/ + function_prolog(initb_hsmc0) + mflr r0 /* Save return addr */ + + /*--------------------------------------------------------------------+ + | Set Global SDRAM Controller to recommended default + +--------------------------------------------------------------------*/ + lis r10,0x6C00 + ori r10,r10,0x0000 + mtdcr hsmc0_gr,r10 + + /*--------------------------------------------------------------------+ + | Set HSMC0 Data Register to recommended default + +--------------------------------------------------------------------*/ + lis r10,0x0037 + ori r10,r10,0x0000 + mtdcr hsmc0_data,r10 + + /*--------------------------------------------------------------------+ + | Init HSMC0 Bank Register 0 + +--------------------------------------------------------------------*/ + lis r10,HSMC0_BR0_VAL@h + ori r10,r10,HSMC0_BR0_VAL@l + mtdcr hsmc0_br0,r10 + + /*--------------------------------------------------------------------+ + | Init HSMC0 Bank Register 1 + +--------------------------------------------------------------------*/ + lis r10,HSMC0_BR1_VAL@h + ori r10,r10,HSMC0_BR1_VAL@l + mtdcr hsmc0_br1,r10 + + /*--------------------------------------------------------------------+ + | Set HSMC0 Control Reg 0 + +--------------------------------------------------------------------*/ + lis r10,0x8077 /* PRECHARGE ALL DEVICE BKS */ + ori r10,r10,0x0000 + mtdcr hsmc0_cr0,r10 + li r3,0x0000 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne cr0,hsmc0_err + + lis r10,0x8078 /* AUTO-REFRESH */ + ori r10,r10,0x0000 + mtdcr hsmc0_cr0,r10 + li r3,0x0000 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne cr0,hsmc0_err + + lis r10,0x8070 /* PROG MODE W/DATA REG VAL */ + ori r10,r10,0x8000 + mtdcr hsmc0_cr0,r10 + li r3,0x0000 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne hsmc0_err + + /*--------------------------------------------------------------------+ + | Set HSMC0 Control Reg 1 + +--------------------------------------------------------------------*/ + lis r10,0x8077 /* PRECHARGE ALL DEVICE BKS */ + ori r10,r10,0x0000 + mtdcr hsmc0_cr1,r10 + li r3,0x0001 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne cr0,hsmc0_err + + lis r10,0x8078 /* AUTO-REFRESH */ + ori r10,r10,0x0000 + mtdcr hsmc0_cr1,r10 + li r3,0x0001 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne cr0,hsmc0_err + + lis r10,0x8070 /* PROG MODE W/DATA REG VAL */ + ori r10,r10,0x8000 + mtdcr hsmc0_cr1,r10 + li r3,0x0001 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne cr0,hsmc0_err + + /*--------------------------------------------------------------------+ + | Set HSMC0 Refresh Register + +--------------------------------------------------------------------*/ + lis r10,0x0FE1 + ori r10,r10,0x0000 + mtdcr hsmc0_crr,r10 + li r3,0 + +hsmc0_err: + mtlr r0 + blr + function_epilog(initb_hsmc0) + + +/****************************************************************************** +| +| Routine: INITB_HSMC1. +| +| Purpose: Initialize the HSMC1 Registers for SDRAM +| Parameters: None. +| Returns: R3 = 0: Successful +| = -1: Unsuccessful, SDRAM did not reset properly. +| +******************************************************************************/ + function_prolog(initb_hsmc1) + mflr r0 /* Save return addr */ + + /*--------------------------------------------------------------------+ + | Set Global SDRAM Controller to recommended default + +--------------------------------------------------------------------*/ + lis r10,0x6C00 + ori r10,r10,0x0000 + mtdcr hsmc1_gr,r10 + + /*--------------------------------------------------------------------+ + | Set HSMC1 Data Register to recommended default + +--------------------------------------------------------------------*/ + lis r10,0x0037 + ori r10,r10,0x0000 + mtdcr hsmc1_data,r10 + + /*--------------------------------------------------------------------+ + | Init HSMC1 Bank Register 0 + +--------------------------------------------------------------------*/ + lis r10,HSMC1_BR0_VAL@h + ori r10,r10,HSMC1_BR0_VAL@l + mtdcr hsmc1_br0,r10 + + /*--------------------------------------------------------------------+ + | Init HSMC1 Bank Register 1 + +--------------------------------------------------------------------*/ + lis r10,HSMC1_BR1_VAL@h + ori r10,r10,HSMC1_BR1_VAL@l + mtdcr hsmc1_br1,r10 + + /*--------------------------------------------------------------------+ + | Set HSMC1 Control Reg 0 + +--------------------------------------------------------------------*/ + lis r10,0x8077 /* PRECHARGE ALL DEVICE BANKS */ + ori r10,r10,0x0000 + mtdcr hsmc1_cr0,r10 + li r3,0x0002 + bl hsmc_cr_wait /* wait for operation completion */ + cmpwi cr0,r3,0x0000 + bne hsmc1_err + + lis r10,0x8078 /* AUTO-REFRESH */ + ori r10,r10,0x0000 + mtdcr hsmc1_cr0,r10 + li r3,0x0002 + bl hsmc_cr_wait /* wait for operation completion */ + cmpwi cr0,r3,0x0000 + bne hsmc1_err + + lis r10,0x8070 /* PROGRAM MODE W/DATA REG VALUE */ + ori r10,r10,0x8000 + mtdcr hsmc1_cr0,r10 + li r3,0x0002 + bl hsmc_cr_wait /* wait for operation completion */ + cmpwi cr0,r3,0x0000 + bne hsmc1_err + + /*--------------------------------------------------------------------+ + | Set HSMC1 Control Reg 1 + +--------------------------------------------------------------------*/ + lis r10,0x8077 /* PRECHARGE ALL DEVICE BKS */ + ori r10,r10,0x0000 + mtdcr hsmc1_cr1,r10 + li r3,0x0003 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne hsmc1_err + + lis r10,0x8078 /* AUTO-REFRESH */ + ori r10,r10,0x0000 + mtdcr hsmc1_cr1,r10 + li r3,0x0003 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne hsmc1_err + + lis r10,0x8070 /* PROG MODE W/DATA REG VAL */ + ori r10,r10,0x8000 + mtdcr hsmc1_cr1,r10 + li r3,0x0003 + bl hsmc_cr_wait /* wait for op completion */ + cmpwi cr0,r3,0x0000 + bne hsmc1_err + + /*--------------------------------------------------------------------+ + | Set HSMC1 Refresh Register + +--------------------------------------------------------------------*/ + lis r10,0x0FE1 + ori r10,r10,0x0000 + mtdcr hsmc1_crr,r10 + xor r3,r3,r3 + +hsmc1_err: + mtlr r0 + blr + function_epilog(initb_hsmc1) + + +/****************************************************************************** +| +| Routine: INITB_CACHE +| +| Purpose: This routine will enable Data and Instruction Cache. +| The Data Cache is an 8K two-way set associative and the +| Instruction Cache is an 16K two-way set associative cache. +| +| Parameters: None. +| +| Returns: None. +| +******************************************************************************/ + function_prolog(initb_cache) + mflr r0 /* Save return addr */ + + bl initb_Dcache /* enable D-Cache */ + bl initb_Icache /* enable I-Cache */ + + mtlr r0 + blr + function_epilog(initb_cache) + + +/****************************************************************************** +| +| Routine: INITB_DCACHE +| +| Purpose: This routine will invalidate all data in the Data Cache and +| then enable D-Cache. If cache is enabled already, the D-Cache +| will be flushed before the data is invalidated. +| +| Parameters: None. +| +| Returns: None. +| +******************************************************************************/ + function_prolog(initb_Dcache) + /*--------------------------------------------------------------------+ + | Flush Data Cache if enabled + +--------------------------------------------------------------------*/ + mfdccr r10 /* r10 <- DCCR */ + isync /* ensure prev insts done */ + cmpwi r10,0x00 + beq ic_dcinv /* D-cache off, invalidate */ + + /*--------------------------------------------------------------------+ + | Data Cache enabled, force known memory addresses to be Cached + +--------------------------------------------------------------------*/ + lis r10,HSMC0_BR0_VAL@h /* r10 <- first memory loc */ + andis. r10,r10,0xFFF0 + li r11,DCACHE_NLINES /* r11 <- # A-way addresses */ + addi r11,r11,DCACHE_NLINES /* r11 <- # B-way addresses */ + mtctr r11 /* set loop counter */ + +ic_dcload: + lwz r12,0(r10) /* force cache of address */ + addi r10,r10,DCACHE_NBYTES /* r10 <- next memory loc */ + bdnz ic_dcload + sync /* ensure prev insts done */ + isync + + /*--------------------------------------------------------------------+ + | Flush the known memory addresses from Cache + +--------------------------------------------------------------------*/ + lis r10,HSMC0_BR0_VAL@h /* r10 <- first memory loc */ + andis. r10,r10,0xFFF0 + mtctr r11 /* set loop counter */ + +ic_dcflush: + dcbf 0,r10 /* flush D-cache line */ + addi r10,r10,DCACHE_NBYTES /* r10 <- next memory loc */ + bdnz ic_dcflush + sync /* ensure prev insts done */ + isync + + /*--------------------------------------------------------------------+ + | Disable then invalidate Data Cache + +--------------------------------------------------------------------*/ + li r10,0 /* r10 <- 0 */ + mtdccr r10 /* disable the D-Cache */ + isync /* ensure prev insts done */ + +ic_dcinv: + li r10,0 /* r10 <- line address */ + li r11,DCACHE_NLINES /* r11 <- # lines in cache */ + mtctr r11 /* set loop counter */ + +ic_dcloop: + dccci 0,r10 /* invalidate A/B cache lns */ + addi r10,r10,DCACHE_NBYTES /* bump to next line */ + bdnz ic_dcloop + sync /* ensure prev insts done */ + isync + + /*--------------------------------------------------------------------+ + | Enable Data Cache + +--------------------------------------------------------------------*/ + lis r10,DCACHE_ENABLE@h /* r10 <- D-cache enable msk*/ + ori r10,r10,DCACHE_ENABLE@l + mtdccr r10 + sync /* ensure prev insts done */ + isync + + blr + function_epilog(initb_Dcache) + + +/****************************************************************************** +| +| Routine: INITB_ICACHE +| +| Purpose: This routine will invalidate all data in the Instruction +| Cache then enable I-Cache. +| +| Parameters: None. +| +| Returns: None. +| +******************************************************************************/ + function_prolog(initb_Icache) + /*--------------------------------------------------------------------+ + | Invalidate Instruction Cache + +--------------------------------------------------------------------*/ + li r10,0 /* r10 <- lines address */ + iccci 0,r10 /* invalidate all I-cache */ + sync /* ensure prev insts done */ + isync + + /*--------------------------------------------------------------------+ + | Enable Instruction Cache + +--------------------------------------------------------------------*/ + lis r10,ICACHE_ENABLE@h /* r10 <- I-cache enable msk*/ + ori r10,r10,ICACHE_ENABLE@l + mticcr r10 + sync /* ensure prev insts done */ + isync + + blr + function_epilog(initb_Icache) + +#if 0 +/****************************************************************************** +| +| Routine: INITB_GET_CSPD +| +| Purpose: Determine the CPU Core Speed. The 13.5 Mhz Time Base +| Counter (TBC) is used to measure a conditional branch +| instruction. +| +| Parameters: R3 = Address of Bus Speed +| R4 = Address of Core Speed +| +| Returns: (R3) = >0: Bus Speed. +| 0: Bus Speed not found in Look-Up Table. +| (R4) = >0: Core Speed. +| 0: Core Speed not found in Look-Up Table. +| +| Note: 1. This routine assumes the bdnz branch instruction takes +| two instruction cycles to complete. +| 2. This routine must be called before interrupts are enabled. +| +******************************************************************************/ + function_prolog(initb_get_cspd) + mflr r0 /* Save return address */ + /*--------------------------------------------------------------------+ + | Set-up timed loop + +--------------------------------------------------------------------*/ + lis r9,gcs_time_loop@h /* r9 <- addr loop instr */ + ori r9,r9,gcs_time_loop@l + lis r10,GCS_LCNT@h /* r10 <- loop count */ + ori r10,r10,GCS_LCNT@l + mtctr r10 /* ctr <- loop count */ + lis r11,STB_TIMERS_TBC@h /* r11 <- TBC register addr */ + ori r11,r11,STB_TIMERS_TBC@l + li r12,0 /* r12 <- 0 */ + + /*--------------------------------------------------------------------+ + | Cache timed-loop instruction + +--------------------------------------------------------------------*/ + icbt 0,r9 + sync + isync + + /*--------------------------------------------------------------------+ + | Get number of 13.5 Mhz cycles to execute time-loop + +--------------------------------------------------------------------*/ + stw r12,0(r11) /* reset TBC */ +gcs_time_loop: + bdnz+ gcs_time_loop /* force branch pred taken */ + lwz r5,0(r11) /* r5 <- num 13.5 Mhz ticks */ + li r6,5 /* LUT based on 1/5th the...*/ + divw r5,r5,r6 /*..loop count used */ + sync + isync + + /*--------------------------------------------------------------------+ + | Look-up core speed based on TBC value + +--------------------------------------------------------------------*/ + lis r6,gcs_lookup_table@h /* r6 <- pts at core spd LUT*/ + ori r6,r6,gcs_lookup_table@l + bl gcs_cspd_lookup /* find core speed in LUT */ + + mtlr r0 /* set return address */ + blr + function_epilog(initb_get_cspd) + +#endif +/*****************************************************************************+ +| XXXX XX XX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX +| XX XXX XX X XX X XX X XX XX XXX XX XXXX XX +| XX XXXX XX XX XX X XX XX XXXX XX XX XX XX +| XX XX XXXX XX XXXX XXXXX XX XXXX XX XX XX +| XX XX XXX XX XX X XX XX XX XXX XXXXXX XX +| XX XX XX XX XX X XX XX XX XX XX XX XX XX +| XXXX XX XX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX ++*****************************************************************************/ +/****************************************************************************** +| +| Routine: HSMC_CR_WAIT +| +| Purpose: Wait for the HSMC Control Register (bits 12-16) to be reset +| after an auto-refresh, pre-charge or program mode register +| command execution. +| +| Parameters: R3 = HSMC Control Register ID. +| 0: HSMC0 CR0 +| 1: HSMC0 CR1 +| 2: HSMC1 CR0 +| 3: HSMC1 CR1 +| +| Returns: R3 = 0: Successful +| -1: Unsuccessful +| +******************************************************************************/ +hsmc_cr_wait: + + li r11,10 /* r11 <- retry counter */ + mtctr r11 /* set retry counter */ + mr r11,r3 /* r11 <- HSMC CR reg id */ + +hsmc_cr_rep: + bdz hsmc_cr_err /* branch if max retries hit*/ + + /*--------------------------------------------------------------------+ + | GET HSMCx_CRx value based on HSMC Control Register ID + +--------------------------------------------------------------------*/ +try_hsmc0_cr0: /* CHECK IF ID=HSMC0 CR0 REG*/ + cmpwi cr0,r11,0x0000 + bne cr0,try_hsmc0_cr1 + mfdcr r10,hsmc0_cr0 /* r11 <- HSMC0 CR0 value */ + b hsmc_cr_read + +try_hsmc0_cr1: /* CHECK IF ID=HSMC0 CR1 REG*/ + cmpwi cr0,r11,0x0001 + bne cr0,try_hsmc1_cr0 + mfdcr r10,hsmc0_cr1 /* r10 <- HSMC0 CR1 value */ + b hsmc_cr_read + +try_hsmc1_cr0: /* CHECK IF ID=HSMC1 CR0 REG*/ + cmpwi cr0,r11,0x0002 + bne cr0,try_hsmc1_cr1 + mfdcr r10,hsmc1_cr0 /* r10 <- HSMC1 CR0 value */ + b hsmc_cr_read + +try_hsmc1_cr1: /* CHECK IF ID=HSMC1 CR1 REG*/ + cmpwi cr0,r11,0x0003 + bne cr0,hsmc_cr_err + mfdcr r10,hsmc1_cr1 /* r10 <- HSMC1 CR1 value */ + + /*--------------------------------------------------------------------+ + | Check if HSMC CR register was reset after command execution + +--------------------------------------------------------------------*/ +hsmc_cr_read: + lis r12,0x000F /* create "AND" mask */ + ori r12,r12,0x8000 + and. r10,r10,r12 /* r10 <- HSMC CR bits 12-16*/ + bne cr0,hsmc_cr_rep /* wait for bits to reset */ + li r3,0 /* set return code = success*/ + b hsmc_cr_done + +hsmc_cr_err: /* ERROR: SDRAM didn't reset*/ + li r3,-1 /* set RC=unsuccessful */ + +hsmc_cr_done: + blr + +#if 0 +/****************************************************************************** +| +| Routine: GCS_CSPD_LOOKUP +| +| Purpose: Uses the number of 13.5 Mhz clock ticks found after executing +| the branch instruction time loop to look-up the CPU Core Speed +| in the Core Speed Look-up Table. +| +| Parameters: R3 = Address of Bus Speed +| R4 = Address of Core Speed +| R5 = Number of 13.5 Mhz clock ticks found in time loop. +| R6 = Pointer to Core-Speed Look-Up Table +| +| Returns: (R3) = >0: Bus Speed. +| 0: Bus Speed not found in Look-Up Table. +| (R4) = >0: Core Speed. +| 0: Core Speed not found in Look-Up Table. +| +| Note: Core Speed = Bus Speed * Mult Factor (1-4x). +| +******************************************************************************/ +gcs_cspd_lookup: + + li r9,1 /* r9 <- core speed mult */ + /*--------------------------------------------------------------------+ + | Get theoritical number 13.5 Mhz ticks for a given Bus Speed from + | Look-up Table. Check all mult factors to determine if calculated + | value matches theoretical value (within a tolerance). + +--------------------------------------------------------------------*/ +gcs_cspd_loop: + lwz r10,0(r6) /* r10 <- no. ticks from LUT*/ + divw r10,r10,r9 /* r10 <- div mult (1-4x) */ + subi r11,r10,GCS_CTICK_TOL /* r11 <- no. tks low range */ + addi r12,r10,GCS_CTICK_TOL /* r12 <- no. tks high range*/ + + cmpw cr0,r5,r11 /* calc value within range? */ + blt gcs_cspd_retry /* less than low range */ + cmpw cr0,r5,r12 + bgt gcs_cspd_retry /* greater than high range */ + b gcs_cspd_fnd /* calc value within range */ + + /*--------------------------------------------------------------------+ + | SO FAR CORE SPEED NOT FOUND: Check next mult factor + +--------------------------------------------------------------------*/ +gcs_cspd_retry: + addi r9,r9,1 /* bump mult factor (1-4x) */ + cmpwi cr0,r9,GCS_NMULT + ble gcs_cspd_loop + + /*--------------------------------------------------------------------+ + | SO FAR CORE SPEED NOT FOUND: Point at next Bus Speed in LUT + +--------------------------------------------------------------------*/ + li r9,1 /* reset mult factor */ + addi r6,r6,GCS_TROW_BYTES /* point at next table entry*/ + lwz r10,0(r6) + cmpwi cr0,r10,0 /* check for EOT flag */ + bne gcs_cspd_loop + + /*--------------------------------------------------------------------+ + | COMPUTE CORE SPEED AND GET BUS SPEED FROM LOOK-UP TABLE + +--------------------------------------------------------------------*/ +gcs_cspd_fnd: + lwz r5,4(r6) /* r5 <- Bus Speed in LUT */ + mullw r6,r5,r9 /* r6 <- Core speed */ + stw r5,0(r3) /* (r3) <- Bus Speed */ + stw r6,0(r4) /* (r4) <- Core Speed */ + + blr +#endif diff --git a/arch/ppc/boot/simple/rw4/stb.h b/arch/ppc/boot/simple/rw4/stb.h new file mode 100644 index 00000000000..fd98ee0f843 --- /dev/null +++ b/arch/ppc/boot/simple/rw4/stb.h @@ -0,0 +1,239 @@ +/*----------------------------------------------------------------------------+ +| This source code has been made available to you by IBM on an AS-IS +| basis. Anyone receiving this source is licensed under IBM +| copyrights to use it in any way he or she deems fit, including +| copying it, modifying it, compiling it, and redistributing it either +| with or without modifications. No license under IBM patents or +| patent applications is to be implied by the copyright license. +| +| Any user of this software should understand that IBM cannot provide +| technical support for this software and will not be responsible for +| any consequences resulting from the use of this software. +| +| Any person who transfers this source code or any derivative work +| must include the IBM copyright notice, this paragraph, and the +| preceding two paragraphs in the transferred software. +| +| COPYRIGHT I B M CORPORATION 1999 +| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M ++----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------+ +| Author: Maciej P. Tyrlik +| Component: Include file. +| File: stb.h +| Purpose: Common Set-tob-box definitions. +| Changes: +| Date: Comment: +| ----- -------- +| 14-Jan-97 Created for ElPaso pass 1 MPT +| 13-May-97 Added function prototype and global variables MPT +| 08-Dec-98 Added RAW IR task information MPT +| 19-Jan-99 Port to Romeo MPT +| 19-May-00 Changed SDRAM to 32MB contiguous 0x1F000000 - 0x20FFFFFF RLB ++----------------------------------------------------------------------------*/ + +#ifndef _stb_h_ +#define _stb_h_ + +/*----------------------------------------------------------------------------+ +| Read/write from I/O macros. ++----------------------------------------------------------------------------*/ +#define inbyte(port) (*((unsigned char volatile *)(port))) +#define outbyte(port,data) *(unsigned char volatile *)(port)=\ + (unsigned char)(data) + +#define inshort(port) (*((unsigned short volatile *)(port))) +#define outshort(port,data) *(unsigned short volatile *)(port)=\ + (unsigned short)(data) + +#define inword(port) (*((unsigned long volatile *)(port))) +#define outword(port,data) *(unsigned long volatile *)(port)=\ + (unsigned long)(data) + +/*----------------------------------------------------------------------------+ +| STB interrupts. ++----------------------------------------------------------------------------*/ +#define STB_XP_TP_INT 0 +#define STB_XP_APP_INT 1 +#define STB_AUD_INT 2 +#define STB_VID_INT 3 +#define STB_DMA0_INT 4 +#define STB_DMA1_INT 5 +#define STB_DMA2_INT 6 +#define STB_DMA3_INT 7 +#define STB_SCI_INT 8 +#define STB_I2C1_INT 9 +#define STB_I2C2_INT 10 +#define STB_GPT_PWM0 11 +#define STB_GPT_PWM1 12 +#define STB_SCP_INT 13 +#define STB_SSP_INT 14 +#define STB_GPT_PWM2 15 +#define STB_EXT5_INT 16 +#define STB_EXT6_INT 17 +#define STB_EXT7_INT 18 +#define STB_EXT8_INT 19 +#define STB_SCC_INT 20 +#define STB_SICC_RECV_INT 21 +#define STB_SICC_TRAN_INT 22 +#define STB_PPU_INT 23 +#define STB_DCRX_INT 24 +#define STB_EXT0_INT 25 +#define STB_EXT1_INT 26 +#define STB_EXT2_INT 27 +#define STB_EXT3_INT 28 +#define STB_EXT4_INT 29 +#define STB_REDWOOD_ENET_INT STB_EXT1_INT + +/*----------------------------------------------------------------------------+ +| STB tasks, task stack sizes, and task priorities. The actual task priority +| is 1 more than the specified number since priority 0 is reserved (system +| internaly adds 1 to supplied priority number). ++----------------------------------------------------------------------------*/ +#define STB_IDLE_TASK_SS (5* 1024) +#define STB_IDLE_TASK_PRIO 0 +#define STB_LEDTEST_SS (2* 1024) +#define STB_LEDTEST_PRIO 0 +#define STB_CURSOR_TASK_SS (10* 1024) +#define STB_CURSOR_TASK_PRIO 7 +#define STB_MPEG_TASK_SS (10* 1024) +#define STB_MPEG_TASK_PRIO 9 +#define STB_DEMUX_TASK_SS (10* 1024) +#define STB_DEMUX_TASK_PRIO 20 +#define RAW_STB_IR_TASK_SS (10* 1024) +#define RAW_STB_IR_TASK_PRIO 20 + +#define STB_SERIAL_ER_TASK_SS (10* 1024) +#define STB_SERIAL_ER_TASK_PRIO 1 +#define STB_CA_TASK_SS (10* 1024) +#define STB_CA_TASK_PRIO 8 + +#define INIT_DEFAULT_VIDEO_SS (10* 1024) +#define INIT_DEFAULT_VIDEO_PRIO 8 +#define INIT_DEFAULT_SERVI_SS (10* 1024) +#define INIT_DEFAULT_SERVI_PRIO 8 +#define INIT_DEFAULT_POST_SS (10* 1024) +#define INIT_DEFAULT_POST_PRIO 8 +#define INIT_DEFAULT_INTER_SS (10* 1024) +#define INIT_DEFAULT_INTER_PRIO 8 +#define INIT_DEFAULT_BR_SS (10* 1024) +#define INIT_DEFAULT_BR_PRIO 8 +#define INITIAL_TASK_STACK_SIZE (32* 1024) + +#ifdef VESTA +/*----------------------------------------------------------------------------+ +| Vesta Overall Address Map (all addresses are double mapped, bit 0 of the +| address is not decoded. Numbers below are dependent on board configuration. +| FLASH, SDRAM, DRAM numbers can be affected by actual board setup. +| +| FFE0,0000 - FFFF,FFFF FLASH +| F200,0000 - F210,FFFF FPGA logic +| Ethernet = F200,0000 +| LED Display = F200,0100 +| Xilinx #1 Regs = F204,0000 +| Xilinx #2 Regs = F208,0000 +| Spare = F20C,0000 +| IDE CS0 = F210,0000 +| F410,0000 - F410,FFFF IDE CS1 +| C000,0000 - C7FF,FFFF OBP +| C000,0000 - C000,0014 SICC (16550 + infra red) +| C001,0000 - C001,0018 PPU (Parallel Port) +| C002,0000 - C002,001B SC0 (Smart Card 0) +| C003,0000 - C003,000F I2C0 +| C004,0000 - C004,0009 SCC (16550 UART) +| C005,0000 - C005,0124 GPT (Timers) +| C006,0000 - C006,0058 GPIO0 +| C007,0000 - C007,001b SC1 (Smart Card 1) +| C008,0000 - C008,FFFF Unused +| C009,0000 - C009,FFFF Unused +| C00A,0000 - C00A,FFFF Unused +| C00B,0000 - C00B,000F I2C1 +| C00C,0000 - C00C,0006 SCP +| C00D,0000 - C00D,0010 SSP +| A000,0000 - A0FF,FFFF SDRAM1 (16M) +| 0000,0000 - 00FF,FFFF SDRAM0 (16M) ++----------------------------------------------------------------------------*/ +#define STB_FLASH_BASE_ADDRESS 0xFFE00000 +#define STB_FPGA_BASE_ADDRESS 0xF2000000 +#define STB_SICC_BASE_ADDRESS 0xC0000000 +#define STB_PPU_BASE_ADDR 0xC0010000 +#define STB_SC0_BASE_ADDRESS 0xC0020000 +#define STB_I2C1_BASE_ADDRESS 0xC0030000 +#define STB_SCC_BASE_ADDRESS 0xC0040000 +#define STB_TIMERS_BASE_ADDRESS 0xC0050000 +#define STB_GPIO0_BASE_ADDRESS 0xC0060000 +#define STB_SC1_BASE_ADDRESS 0xC0070000 +#define STB_I2C2_BASE_ADDRESS 0xC00B0000 +#define STB_SCP_BASE_ADDRESS 0xC00C0000 +#define STB_SSP_BASE_ADDRESS 0xC00D0000 +/*----------------------------------------------------------------------------+ +|The following are used by the IBM RTOS SW. +|15-May-00 Changed these values to reflect movement of base addresses in +|order to support 32MB of contiguous SDRAM space. +|Points to the cacheable region since these values are used in IBM RTOS +|to establish the vector address. ++----------------------------------------------------------------------------*/ +#define STB_SDRAM1_BASE_ADDRESS 0x20000000 +#define STB_SDRAM1_SIZE 0x01000000 +#define STB_SDRAM0_BASE_ADDRESS 0x1F000000 +#define STB_SDRAM0_SIZE 0x01000000 + +#else +/*----------------------------------------------------------------------------+ +| ElPaso Overall Address Map (all addresses are double mapped, bit 0 of the +| address is not decoded. Numbers below are dependent on board configuration. +| FLASH, SDRAM, DRAM numbers can be affected by actual board setup. OPB +| devices are inside the ElPaso chip. +| FFE0,0000 - FFFF,FFFF FLASH +| F144,0000 - F104,FFFF FPGA logic +| F140,0000 - F100,0000 ethernet (through FPGA logic) +| C000,0000 - C7FF,FFFF OBP +| C000,0000 - C000,0014 SICC (16550+ infra red) +| C001,0000 - C001,0016 PPU (parallel port) +| C002,0000 - C002,001B SC (smart card) +| C003,0000 - C003,000F I2C 1 +| C004,0000 - C004,0009 SCC (16550 UART) +| C005,0000 - C005,0124 Timers +| C006,0000 - C006,0058 GPIO0 +| C007,0000 - C007,0058 GPIO1 +| C008,0000 - C008,0058 GPIO2 +| C009,0000 - C009,0058 GPIO3 +| C00A,0000 - C00A,0058 GPIO4 +| C00B,0000 - C00B,000F I2C 2 +| C00C,0000 - C00C,0006 SCP +| C00D,0000 - C00D,0006 SSP +| A000,0000 - A0FF,FFFF SDRAM 16M +| 0000,0000 - 00FF,FFFF DRAM 16M ++----------------------------------------------------------------------------*/ +#define STB_FLASH_BASE_ADDRESS 0xFFE00000 +#define STB_FPGA_BASE_ADDRESS 0xF1440000 +#define STB_ENET_BASE_ADDRESS 0xF1400000 +#define STB_SICC_BASE_ADDRESS 0xC0000000 +#define STB_PPU_BASE_ADDR 0xC0010000 +#define STB_SC_BASE_ADDRESS 0xC0020000 +#define STB_I2C1_BASE_ADDRESS 0xC0030000 +#define STB_SCC_BASE_ADDRESS 0xC0040000 +#define STB_TIMERS_BASE_ADDRESS 0xC0050000 +#define STB_GPIO0_BASE_ADDRESS 0xC0060000 +#define STB_GPIO1_BASE_ADDRESS 0xC0070000 +#define STB_GPIO2_BASE_ADDRESS 0xC0080000 +#define STB_GPIO3_BASE_ADDRESS 0xC0090000 +#define STB_GPIO4_BASE_ADDRESS 0xC00A0000 +#define STB_I2C2_BASE_ADDRESS 0xC00B0000 +#define STB_SCP_BASE_ADDRESS 0xC00C0000 +#define STB_SSP_BASE_ADDRESS 0xC00D0000 +#define STB_SDRAM_BASE_ADDRESS 0xA0000000 +#endif + +/*----------------------------------------------------------------------------+ +| Other common defines. ++----------------------------------------------------------------------------*/ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#endif /* _stb_h_ */ -- cgit v1.2.3