From c2f02da21a3f37f0878554eebc785e04fdc4e128 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 28 Mar 2008 09:47:00 +0100 Subject: [PATCH 01/11] SPARC: Added generic support for SPARC architecture. Signed-off-by: Daniel Hellstrom --- MAKEALL | 7 + Makefile | 9 +- README | 1 + examples/Makefile | 3 + examples/sparc.lds | 61 ++++ examples/stubs.c | 16 + include/asm-sparc/asi.h | 32 ++ include/asm-sparc/asmmacro.h | 45 +++ include/asm-sparc/atomic.h | 29 ++ include/asm-sparc/bitops.h | 29 ++ include/asm-sparc/byteorder.h | 37 +++ include/asm-sparc/cache.h | 31 ++ include/asm-sparc/errno.h | 162 ++++++++++ include/asm-sparc/global_data.h | 85 ++++++ include/asm-sparc/io.h | 94 ++++++ include/asm-sparc/irq.h | 49 +++ include/asm-sparc/machines.h | 92 ++++++ include/asm-sparc/page.h | 43 +++ include/asm-sparc/posix_types.h | 139 +++++++++ include/asm-sparc/processor.h | 109 +++++++ include/asm-sparc/prom.h | 297 ++++++++++++++++++ include/asm-sparc/psr.h | 97 ++++++ include/asm-sparc/ptrace.h | 181 +++++++++++ include/asm-sparc/srmmu.h | 301 ++++++++++++++++++ include/asm-sparc/stack.h | 162 ++++++++++ include/asm-sparc/string.h | 55 ++++ include/asm-sparc/types.h | 71 +++++ include/asm-sparc/u-boot.h | 74 +++++ include/asm-sparc/winmacro.h | 151 +++++++++ lib_sparc/Makefile | 45 +++ lib_sparc/board.c | 521 ++++++++++++++++++++++++++++++++ lib_sparc/bootm.c | 226 ++++++++++++++ lib_sparc/cache.c | 33 ++ lib_sparc/interrupts.c | 122 ++++++++ lib_sparc/time.c | 78 +++++ sparc_config.mk | 24 ++ 36 files changed, 3510 insertions(+), 1 deletion(-) create mode 100644 examples/sparc.lds create mode 100644 include/asm-sparc/asi.h create mode 100644 include/asm-sparc/asmmacro.h create mode 100644 include/asm-sparc/atomic.h create mode 100644 include/asm-sparc/bitops.h create mode 100644 include/asm-sparc/byteorder.h create mode 100644 include/asm-sparc/cache.h create mode 100644 include/asm-sparc/errno.h create mode 100644 include/asm-sparc/global_data.h create mode 100644 include/asm-sparc/io.h create mode 100644 include/asm-sparc/irq.h create mode 100644 include/asm-sparc/machines.h create mode 100644 include/asm-sparc/page.h create mode 100644 include/asm-sparc/posix_types.h create mode 100644 include/asm-sparc/processor.h create mode 100644 include/asm-sparc/prom.h create mode 100644 include/asm-sparc/psr.h create mode 100644 include/asm-sparc/ptrace.h create mode 100644 include/asm-sparc/srmmu.h create mode 100644 include/asm-sparc/stack.h create mode 100644 include/asm-sparc/string.h create mode 100644 include/asm-sparc/types.h create mode 100644 include/asm-sparc/u-boot.h create mode 100644 include/asm-sparc/winmacro.h create mode 100644 lib_sparc/Makefile create mode 100644 lib_sparc/board.c create mode 100644 lib_sparc/bootm.c create mode 100644 lib_sparc/cache.c create mode 100644 lib_sparc/interrupts.c create mode 100644 lib_sparc/time.c create mode 100644 sparc_config.mk diff --git a/MAKEALL b/MAKEALL index 2a872acd6..9a2afe66f 100755 --- a/MAKEALL +++ b/MAKEALL @@ -723,6 +723,12 @@ LIST_sh=" \ ${LIST_sh4} \ " +######################################################################### +## SPARC Systems +######################################################################### + +LIST_sparc="" + #----------------------------------------------------------------------- #----- for now, just run PPC by default ----- @@ -751,6 +757,7 @@ do case "$arg" in arm|SA|ARM7|ARM9|ARM10|ARM11|ixp|pxa| \ avr32| \ + sparc| \ blackfin| \ coldfire| \ microblaze| \ diff --git a/Makefile b/Makefile index a7f886b48..7219e7a31 100644 --- a/Makefile +++ b/Makefile @@ -165,7 +165,10 @@ CROSS_COMPILE = avr32-linux- endif ifeq ($(ARCH),sh) CROSS_COMPILE = sh4-linux- -endif # sh +endif +ifeq ($(ARCH),sparc) +CROSS_COMPILE = sparc-elf- +endif # sparc endif # HOSTARCH,ARCH endif # CROSS_COMPILE @@ -2892,6 +2895,10 @@ r2dplus_config : unconfig @echo "#define CONFIG_R2DPLUS 1" >> include/config.h @./mkconfig -a $(@:_config=) sh sh4 r2dplus +#======================================================================== +# SPARC +#======================================================================== + ######################################################################### ######################################################################### ######################################################################### diff --git a/README b/README index 5d059e73c..9160306c4 100644 --- a/README +++ b/README @@ -186,6 +186,7 @@ Directory Hierarchy: - lib_mips Files generic to MIPS architecture - lib_nios Files generic to NIOS architecture - lib_ppc Files generic to PowerPC architecture +- lib_sparc Files generic to SPARC architecture - libfdt Library files to support flattened device trees - net Networking code - post Power On Self Test diff --git a/examples/Makefile b/examples/Makefile index c5d629b68..66b354daa 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -69,6 +69,9 @@ ifeq ($(ARCH),sh) LOAD_ADDR = 0x8C000000 endif +ifeq ($(ARCH),sparc) +LOAD_ADDR = 0x00000000 -L $(gcclibdir) -T sparc.lds +endif include $(TOPDIR)/config.mk diff --git a/examples/sparc.lds b/examples/sparc.lds new file mode 100644 index 000000000..75925449e --- /dev/null +++ b/examples/sparc.lds @@ -0,0 +1,61 @@ +/* + * (C) Copyright 2003, Psyent Corporation + * Scott McNutt + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) + +SECTIONS +{ + .text : + { + *(.text) + } + __text_end = .; + + . = ALIGN(4); + .rodata : + { + *(.rodata) + } + __rodata_end = .; + + . = ALIGN(4); + .data : + { + *(.data) + } + . = ALIGN(4); + __data_end = .; + + __bss_start = .; + . = ALIGN(4); + .bss : + { + *(.bss) + } + . = ALIGN(4); + __bss_end = .; + _end = .; +} diff --git a/examples/stubs.c b/examples/stubs.c index b9dbcf906..ec5353216 100644 --- a/examples/stubs.c +++ b/examples/stubs.c @@ -167,6 +167,22 @@ gd_t *global_data; " nop\n" \ " nop\n" \ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r1"); +#elif defined(CONFIG_SPARC) +/* + * g7 holds the pointer to the global_data. g1 is call clobbered. + */ +#define EXPORT_FUNC(x) \ + asm volatile( \ +" .globl\t" #x "\n" \ +#x ":\n" \ +" set %0, %%g1\n" \ +" or %%g1, %%g7, %%g1\n" \ +" ld [%%g1], %%g1\n" \ +" ld [%%g1 + %1], %%g1\n" \ +" call %%g1\n" \ +" nop\n" \ + : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x) : "g1" ); + #else #error stubs definition missing for this architecture #endif diff --git a/include/asm-sparc/asi.h b/include/asm-sparc/asi.h new file mode 100644 index 000000000..bf6d70fec --- /dev/null +++ b/include/asm-sparc/asi.h @@ -0,0 +1,32 @@ +/* Address Space Identifier (ASI) values for sparc processors. + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _SPARC_ASI_H +#define _SPARC_ASI_H + +/* ASI numbers are processor implementation specific */ +#include + +#endif /* _SPARC_ASI_H */ diff --git a/include/asm-sparc/asmmacro.h b/include/asm-sparc/asmmacro.h new file mode 100644 index 000000000..0c4cefdf4 --- /dev/null +++ b/include/asm-sparc/asmmacro.h @@ -0,0 +1,45 @@ +/* Assembler macros for SPARC + * + * (C) Copyright 2007, taken from linux asm-sparc/asmmacro.h + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_ASMMACRO_H__ +#define __SPARC_ASMMACRO_H__ + +#include + +/* All trap entry points _must_ begin with this macro or else you + * lose. It makes sure the kernel has a proper window so that + * c-code can be called. + */ +#define SAVE_ALL_HEAD \ + sethi %hi(trap_setup+(CFG_RELOC_MONITOR_BASE-TEXT_BASE)), %l4; \ + jmpl %l4 + %lo(trap_setup+(CFG_RELOC_MONITOR_BASE-TEXT_BASE)), %l6; +#define SAVE_ALL \ + SAVE_ALL_HEAD \ + nop; + +/* All traps low-level code here must end with this macro. */ +#define RESTORE_ALL b ret_trap_entry; clr %l6; + +#endif diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h new file mode 100644 index 000000000..636498d55 --- /dev/null +++ b/include/asm-sparc/atomic.h @@ -0,0 +1,29 @@ +/* SPARC atomic operations + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _ASM_SPARC_ATOMIC_H_ +#define _ASM_SPARC_ATOMIC_H_ + +#endif /* _ASM_SPARC_ATOMIC_H_ */ diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h new file mode 100644 index 000000000..ceb39f2fe --- /dev/null +++ b/include/asm-sparc/bitops.h @@ -0,0 +1,29 @@ +/* Bit string operations on the SPARC + * + * (C) Copyright 2007, taken from asm-ppc/bitops.h + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _SPARC_BITOPS_H +#define _SPARC_BITOPS_H + +#endif /* _SPARC_BITOPS_H */ diff --git a/include/asm-sparc/byteorder.h b/include/asm-sparc/byteorder.h new file mode 100644 index 000000000..b9fc65663 --- /dev/null +++ b/include/asm-sparc/byteorder.h @@ -0,0 +1,37 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _SPARC_BYTEORDER_H +#define _SPARC_BYTEORDER_H + +#include + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define __BYTEORDER_HAS_U64__ +#endif +#include +#endif /* _SPARC_BYTEORDER_H */ diff --git a/include/asm-sparc/cache.h b/include/asm-sparc/cache.h new file mode 100644 index 000000000..03e8d94bb --- /dev/null +++ b/include/asm-sparc/cache.h @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2008, + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_CACHE_H__ +#define __SPARC_CACHE_H__ + +#include +#include + +#endif diff --git a/include/asm-sparc/errno.h b/include/asm-sparc/errno.h new file mode 100644 index 000000000..3a74f6fa4 --- /dev/null +++ b/include/asm-sparc/errno.h @@ -0,0 +1,162 @@ +/* SPARC errno definitions, taken from asm-ppc/errno.h + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __SPARC_ERRNO_H__ +#define __SPARC_ERRNO_H__ + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ +#define EDEADLOCK 58 /* File locking deadlock error */ +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 +#define ERESTARTNOHAND 514 /* restart if no handler.. */ +#define ENOIOCTLCMD 515 /* No ioctl command */ + +#define _LAST_ERRNO 515 + +#endif diff --git a/include/asm-sparc/global_data.h b/include/asm-sparc/global_data.h new file mode 100644 index 000000000..7c29fc684 --- /dev/null +++ b/include/asm-sparc/global_data.h @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_GBL_DATA_H +#define __ASM_GBL_DATA_H + +#include "asm/types.h" + +/* + * The following data structure is placed in some memory wich is + * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or + * some locked parts of the data cache) to allow for a minimum set of + * global variables during system initialization (until we have set + * up the memory controller so that we can use RAM). + * + * Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t) + */ + +typedef struct global_data { + bd_t *bd; + unsigned long flags; + unsigned long baudrate; + unsigned long cpu_clk; /* CPU clock in Hz! */ + unsigned long bus_clk; + + unsigned long ram_size; /* RAM size */ + unsigned long reloc_off; /* Relocation Offset */ + unsigned long reset_status; /* reset status register at boot */ + unsigned long env_addr; /* Address of Environment struct */ + unsigned long env_valid; /* Checksum of Environment valid? */ + unsigned long have_console; /* serial_init() was called */ + +#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) + unsigned long fb_base; /* Base address of framebuffer memory */ +#endif +#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) + unsigned long post_log_word; /* Record POST activities */ + unsigned long post_init_f_time; /* When post_init_f started */ +#endif +#ifdef CONFIG_BOARD_TYPES + unsigned long board_type; +#endif +#ifdef CONFIG_MODEM_SUPPORT + unsigned long do_mdm_init; + unsigned long be_quiet; +#endif +#ifdef CONFIG_LWMON + unsigned long kbd_status; +#endif + void **jt; /* jump table */ +} gd_t; + +/* + * Global Data Flags + */ +#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ +#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ +#define GD_FLG_SILENT 0x00004 /* Silent mode */ + +#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("%g7") + +#endif /* __ASM_GBL_DATA_H */ diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h new file mode 100644 index 000000000..2a27d0679 --- /dev/null +++ b/include/asm-sparc/io.h @@ -0,0 +1,94 @@ +/* SPARC I/O definitions + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _SPARC_IO_H +#define _SPARC_IO_H + +/* Nothing to sync, total store ordering (TSO)... */ +#define sync() + +/* Forces a cache miss on read/load. + * On some architectures we need to bypass the cache when reading + * I/O registers so that we are not reading the same status word + * over and over again resulting in a hang (until an IRQ if lucky) + * + */ +#ifndef CFG_HAS_NO_CACHE +#define READ_BYTE(var) SPARC_NOCACHE_READ_BYTE((unsigned int)(var)) +#define READ_HWORD(var) SPARC_NOCACHE_READ_HWORD((unsigned int)(var)) +#define READ_WORD(var) SPARC_NOCACHE_READ((unsigned int)(var)) +#define READ_DWORD(var) SPARC_NOCACHE_READ_DWORD((unsigned int)(var)) +#else +#define READ_BYTE(var) (var) +#define READ_HWORD(var) (var) +#define READ_WORD(var) (var) +#define READ_DWORD(var) (var) +#endif + +/* + * Generic virtual read/write. + */ +#define __arch_getb(a) (READ_BYTE(a)) +#define __arch_getw(a) (READ_HWORD(a)) +#define __arch_getl(a) (READ_WORD(a)) +#define __arch_getq(a) (READ_DWORD(a)) + +#define __arch_putb(v,a) (*(volatile unsigned char *)(a) = (v)) +#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v)) +#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v)) + +#define __raw_writeb(v,a) __arch_putb(v,a) +#define __raw_writew(v,a) __arch_putw(v,a) +#define __raw_writel(v,a) __arch_putl(v,a) + +#define __raw_readb(a) __arch_getb(a) +#define __raw_readw(a) __arch_getw(a) +#define __raw_readl(a) __arch_getl(a) +#define __raw_readq(a) __arch_getq(a) + +/* + * Given a physical address and a length, return a virtual address + * that can be used to access the memory range with the caching + * properties specified by "flags". + */ +typedef unsigned long phys_addr_t; + +#define MAP_NOCACHE (0) +#define MAP_WRCOMBINE (0) +#define MAP_WRBACK (0) +#define MAP_WRTHROUGH (0) + +static inline void *map_physmem(phys_addr_t paddr, unsigned long len, + unsigned long flags) +{ + return (void *)paddr; +} + +/* + * Take down a mapping set up by map_physmem(). + */ +static inline void unmap_physmem(void *vaddr, unsigned long flags) +{ + +} + +#endif diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h new file mode 100644 index 000000000..c5538c092 --- /dev/null +++ b/include/asm-sparc/irq.h @@ -0,0 +1,49 @@ +/* IRQ functions + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_IRQ_H__ +#define __SPARC_IRQ_H__ + +#include + +/* Set SPARC Processor Interrupt Level */ +extern inline void set_pil(unsigned int level) +{ + unsigned int psr = get_psr(); + + put_psr((psr & ~PSR_PIL) | ((level & 0xf) << PSR_PIL_OFS)); +} + +/* Get SPARC Processor Interrupt Level */ +extern inline unsigned int get_pil(void) +{ + unsigned int psr = get_psr(); + return (psr & PSR_PIL) >> PSR_PIL_OFS; +} + +/* Disables interrupts and return current PIL value */ +extern int intLock(void); + +/* Sets the PIL to oldLevel */ +extern void intUnlock(int oldLevel); + +#endif diff --git a/include/asm-sparc/machines.h b/include/asm-sparc/machines.h new file mode 100644 index 000000000..1e2619599 --- /dev/null +++ b/include/asm-sparc/machines.h @@ -0,0 +1,92 @@ +/* machines.h: Defines for taking apart the machine type value in the + * idprom and determining the kind of machine we are on. + * + * Taken from the SPARC port of Linux. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_MACHINES_H__ +#define __SPARC_MACHINES_H__ + +struct Sun_Machine_Models { + char *name; + unsigned char id_machtype; +}; + +/* Current number of machines we know about that has an IDPROM + * machtype entry including one entry for the 0x80 OBP machines. + */ +#define NUM_SUN_MACHINES 16 + +extern struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES]; + +/* The machine type in the idprom area looks like this: + * + * --------------- + * | ARCH | MACH | + * --------------- + * 7 4 3 0 + * + * The ARCH field determines the architecture line (sun4, sun4c, etc). + * The MACH field determines the machine make within that architecture. + */ + +#define SM_ARCH_MASK 0xf0 +#define SM_SUN4 0x20 +#define M_LEON2 0x30 +#define SM_SUN4C 0x50 +#define SM_SUN4M 0x70 +#define SM_SUN4M_OBP 0x80 + +#define SM_TYP_MASK 0x0f +/* Sun4 machines */ +#define SM_4_260 0x01 /* Sun 4/200 series */ +#define SM_4_110 0x02 /* Sun 4/100 series */ +#define SM_4_330 0x03 /* Sun 4/300 series */ +#define SM_4_470 0x04 /* Sun 4/400 series */ + +/* Leon machines */ +#define M_LEON2_SOC 0x01 /* Leon2 SoC */ + +/* Sun4c machines Full Name - PROM NAME */ +#define SM_4C_SS1 0x01 /* Sun4c SparcStation 1 - Sun 4/60 */ +#define SM_4C_IPC 0x02 /* Sun4c SparcStation IPC - Sun 4/40 */ +#define SM_4C_SS1PLUS 0x03 /* Sun4c SparcStation 1+ - Sun 4/65 */ +#define SM_4C_SLC 0x04 /* Sun4c SparcStation SLC - Sun 4/20 */ +#define SM_4C_SS2 0x05 /* Sun4c SparcStation 2 - Sun 4/75 */ +#define SM_4C_ELC 0x06 /* Sun4c SparcStation ELC - Sun 4/25 */ +#define SM_4C_IPX 0x07 /* Sun4c SparcStation IPX - Sun 4/50 */ + +/* Sun4m machines, these predate the OpenBoot. These values only mean + * something if the value in the ARCH field is SM_SUN4M, if it is + * SM_SUN4M_OBP then you have the following situation: + * 1) You either have a sun4d, a sun4e, or a recently made sun4m. + * 2) You have to consult OpenBoot to determine which machine this is. + */ +#define SM_4M_SS60 0x01 /* Sun4m SparcSystem 600 */ +#define SM_4M_SS50 0x02 /* Sun4m SparcStation 10 */ +#define SM_4M_SS40 0x03 /* Sun4m SparcStation 5 */ + +/* Sun4d machines -- N/A */ +/* Sun4e machines -- N/A */ +/* Sun4u machines -- N/A */ + +#endif /* !(_SPARC_MACHINES_H) */ diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h new file mode 100644 index 000000000..484953a86 --- /dev/null +++ b/include/asm-sparc/page.h @@ -0,0 +1,43 @@ +/* page.h: Various defines and such for MMU operations on the Sparc for + * the Linux kernel. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _SPARC_PAGE_H +#define _SPARC_PAGE_H + +#include +#ifdef CONFIG_SUN4 +#define PAGE_SHIFT 13 +#else +#define PAGE_SHIFT 12 +#endif + +#ifndef __ASSEMBLY__ +/* I have my suspicions... -DaveM */ +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#else +#define PAGE_SIZE (1 << PAGE_SHIFT) +#endif + +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _SPARC_PAGE_H */ diff --git a/include/asm-sparc/posix_types.h b/include/asm-sparc/posix_types.h new file mode 100644 index 000000000..8d98b2a6a --- /dev/null +++ b/include/asm-sparc/posix_types.h @@ -0,0 +1,139 @@ +/* + * (C) Copyright 2000 - 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007, taken from asm-ppc/posix_types.h + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_POSIX_TYPES_H__ +#define __SPARC_POSIX_TYPES_H__ + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char *__kernel_caddr_t; +typedef short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#ifndef __GNUC__ + +#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) +#define __FD_ZERO(set) \ + ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) + +#else /* __GNUC__ */ + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \ + || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) +/* With GNU C, use inline functions instead so args are evaluated only once: */ + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set * fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] |= (1UL << _rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set * fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] &= ~(1UL << _rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set * p) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + return (p->fds_bits[_tmp] & (1UL << _rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set * p) +{ + unsigned int *tmp = (unsigned int *)p->fds_bits; + int i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 8: + tmp[0] = 0; + tmp[1] = 0; + tmp[2] = 0; + tmp[3] = 0; + tmp[4] = 0; + tmp[5] = 0; + tmp[6] = 0; + tmp[7] = 0; + return; + } + } + i = __FDSET_LONGS; + while (i) { + i--; + *tmp = 0; + tmp++; + } +} + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ +#endif /* __GNUC__ */ +#endif /* _SPARC_POSIX_TYPES_H */ diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h new file mode 100644 index 000000000..31b44c546 --- /dev/null +++ b/include/asm-sparc/processor.h @@ -0,0 +1,109 @@ +/* SPARC Processor specifics + * taken from the SPARC port of Linux (ptrace.h). + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __ASM_SPARC_PROCESSOR_H +#define __ASM_SPARC_PROCESSOR_H + +#include + +/* Includeprocessor specific header file here */ +#error Unknown SPARC Processor + +#ifndef __ASSEMBLY__ + +/* flush data cache */ +static __inline__ void sparc_dcache_flush_all(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory"); +} + +/* flush instruction cache */ +static __inline__ void sparc_icache_flush_all(void) +{ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_IFLUSH):"memory"); +} + +/* do a cache miss load */ +static __inline__ unsigned long long sparc_load_reg_cachemiss_qword(unsigned + long paddr) +{ + unsigned long long retval; + __asm__ __volatile__("ldda [%1] %2, %0\n\t": + "=r"(retval):"r"(paddr), "i"(ASI_CACHEMISS)); + return retval; +} + +static __inline__ unsigned long sparc_load_reg_cachemiss(unsigned long paddr) +{ + unsigned long retval; + __asm__ __volatile__("lda [%1] %2, %0\n\t": + "=r"(retval):"r"(paddr), "i"(ASI_CACHEMISS)); + return retval; +} + +static __inline__ unsigned short sparc_load_reg_cachemiss_word(unsigned long + paddr) +{ + unsigned short retval; + __asm__ __volatile__("lduha [%1] %2, %0\n\t": + "=r"(retval):"r"(paddr), "i"(ASI_CACHEMISS)); + return retval; +} + +static __inline__ unsigned char sparc_load_reg_cachemiss_byte(unsigned long + paddr) +{ + unsigned char retval; + __asm__ __volatile__("lduba [%1] %2, %0\n\t": + "=r"(retval):"r"(paddr), "i"(ASI_CACHEMISS)); + return retval; +} + +/* do a physical address bypass write, i.e. for 0x80000000 */ +static __inline__ void sparc_store_reg_bypass(unsigned long paddr, + unsigned long value) +{ + __asm__ __volatile__("sta %0, [%1] %2\n\t"::"r"(value), "r"(paddr), + "i"(ASI_BYPASS):"memory"); +} + +static __inline__ unsigned long sparc_load_reg_bypass(unsigned long paddr) +{ + unsigned long retval; + __asm__ __volatile__("lda [%1] %2, %0\n\t": + "=r"(retval):"r"(paddr), "i"(ASI_BYPASS)); + return retval; +} + +/* Macros for bypassing cache when reading */ +#define SPARC_NOCACHE_READ_DWORD(address) sparc_load_reg_cachemiss_qword((unsigned int)(address)) +#define SPARC_NOCACHE_READ(address) sparc_load_reg_cachemiss((unsigned int)(address)) +#define SPARC_NOCACHE_READ_HWORD(address) sparc_load_reg_cachemiss_word((unsigned int)(address)) +#define SPARC_NOCACHE_READ_BYTE(address) sparc_load_reg_cachemiss_byte((unsigned int)(address)) + +#define SPARC_BYPASS_READ(address) sparc_load_reg_bypass((unsigned int)(address)) +#define SPARC_BYPASS_WRITE(address,value) sparc_store_reg_bypass((unsigned int)(address),(unsigned int)(value)) + +#endif + +#endif /* __ASM_SPARC_PROCESSOR_H */ diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h new file mode 100644 index 000000000..d55cc863d --- /dev/null +++ b/include/asm-sparc/prom.h @@ -0,0 +1,297 @@ +/* OpenProm defines mainly taken from linux kernel header files + * + * openprom.h: Prom structures and defines for access to the OPENBOOT + * prom routines and data areas. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_OPENPROM_H__ +#define __SPARC_OPENPROM_H__ + +/* Empirical constants... */ +#define LINUX_OPPROM_MAGIC 0x10010407 + +#ifndef __ASSEMBLY__ +/* V0 prom device operations. */ +struct linux_dev_v0_funcs { + int (*v0_devopen) (char *device_str); + int (*v0_devclose) (int dev_desc); + int (*v0_rdblkdev) (int dev_desc, int num_blks, int blk_st, char *buf); + int (*v0_wrblkdev) (int dev_desc, int num_blks, int blk_st, char *buf); + int (*v0_wrnetdev) (int dev_desc, int num_bytes, char *buf); + int (*v0_rdnetdev) (int dev_desc, int num_bytes, char *buf); + int (*v0_rdchardev) (int dev_desc, int num_bytes, int dummy, char *buf); + int (*v0_wrchardev) (int dev_desc, int num_bytes, int dummy, char *buf); + int (*v0_seekdev) (int dev_desc, long logical_offst, int from); +}; + +/* V2 and later prom device operations. */ +struct linux_dev_v2_funcs { + int (*v2_inst2pkg) (int d); /* Convert ihandle to phandle */ + char *(*v2_dumb_mem_alloc) (char *va, unsigned sz); + void (*v2_dumb_mem_free) (char *va, unsigned sz); + + /* To map devices into virtual I/O space. */ + char *(*v2_dumb_mmap) (char *virta, int which_io, unsigned paddr, + unsigned sz); + void (*v2_dumb_munmap) (char *virta, unsigned size); + + int (*v2_dev_open) (char *devpath); + void (*v2_dev_close) (int d); + int (*v2_dev_read) (int d, char *buf, int nbytes); + int (*v2_dev_write) (int d, char *buf, int nbytes); + int (*v2_dev_seek) (int d, int hi, int lo); + + /* Never issued (multistage load support) */ + void (*v2_wheee2) (void); + void (*v2_wheee3) (void); +}; + +struct linux_mlist_v0 { + struct linux_mlist_v0 *theres_more; + char *start_adr; + unsigned num_bytes; +}; + +struct linux_mem_v0 { + struct linux_mlist_v0 **v0_totphys; + struct linux_mlist_v0 **v0_prommap; + struct linux_mlist_v0 **v0_available; /* What we can use */ +}; + +/* Arguments sent to the kernel from the boot prompt. */ +struct linux_arguments_v0 { + char *argv[8]; + char args[100]; + char boot_dev[2]; + int boot_dev_ctrl; + int boot_dev_unit; + int dev_partition; + char *kernel_file_name; + void *aieee1; /* XXX */ +}; + +/* V2 and up boot things. */ +struct linux_bootargs_v2 { + char **bootpath; + char **bootargs; + int *fd_stdin; + int *fd_stdout; +}; + +/* The top level PROM vector. */ +struct linux_romvec { + /* Version numbers. */ + unsigned int pv_magic_cookie; + unsigned int pv_romvers; + unsigned int pv_plugin_revision; + unsigned int pv_printrev; + + /* Version 0 memory descriptors. */ + struct linux_mem_v0 pv_v0mem; + + /* Node operations. */ + struct linux_nodeops *pv_nodeops; + + char **pv_bootstr; + struct linux_dev_v0_funcs pv_v0devops; + + char *pv_stdin; + char *pv_stdout; +#define PROMDEV_KBD 0 /* input from keyboard */ +#define PROMDEV_SCREEN 0 /* output to screen */ +#define PROMDEV_TTYA 1 /* in/out to ttya */ +#define PROMDEV_TTYB 2 /* in/out to ttyb */ + + /* Blocking getchar/putchar. NOT REENTRANT! (grr) */ + int (*pv_getchar) (void); + void (*pv_putchar) (int ch); + + /* Non-blocking variants. */ + int (*pv_nbgetchar) (void); + int (*pv_nbputchar) (int ch); + + void (*pv_putstr) (char *str, int len); + + /* Miscellany. */ + void (*pv_reboot) (char *bootstr); + void (*pv_printf) (__const__ char *fmt, ...); + void (*pv_abort) (void); + __volatile__ int *pv_ticks; + void (*pv_halt) (void); + void (**pv_synchook) (void); + + /* Evaluate a forth string, not different proto for V0 and V2->up. */ + union { + void (*v0_eval) (int len, char *str); + void (*v2_eval) (char *str); + } pv_fortheval; + + struct linux_arguments_v0 **pv_v0bootargs; + + /* Get ether address. */ + unsigned int (*pv_enaddr) (int d, char *enaddr); + + struct linux_bootargs_v2 pv_v2bootargs; + struct linux_dev_v2_funcs pv_v2devops; + + int filler[15]; + + /* This one is sun4c/sun4 only. */ + void (*pv_setctxt) (int ctxt, char *va, int pmeg); + + /* Prom version 3 Multiprocessor routines. This stuff is crazy. + * No joke. Calling these when there is only one cpu probably + * crashes the machine, have to test this. :-) + */ + + /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context + * 'thiscontext' executing at address 'prog_counter' + */ + int (*v3_cpustart) (unsigned int whichcpu, int ctxtbl_ptr, + int thiscontext, char *prog_counter); + + /* v3_cpustop() will cause cpu 'whichcpu' to stop executing + * until a resume cpu call is made. + */ + int (*v3_cpustop) (unsigned int whichcpu); + + /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or + * resume cpu call is made. + */ + int (*v3_cpuidle) (unsigned int whichcpu); + + /* v3_cpuresume() will resume processor 'whichcpu' executing + * starting with whatever 'pc' and 'npc' were left at the + * last 'idle' or 'stop' call. + */ + int (*v3_cpuresume) (unsigned int whichcpu); +}; + +/* Routines for traversing the prom device tree. */ +struct linux_nodeops { + int (*no_nextnode) (int node); + int (*no_child) (int node); + int (*no_proplen) (int node, char *name); + int (*no_getprop) (int node, char *name, char *val); + int (*no_setprop) (int node, char *name, char *val, int len); + char *(*no_nextprop) (int node, char *name); +}; + +/* More fun PROM structures for device probing. */ +#define PROMREG_MAX 16 +#define PROMVADDR_MAX 16 +#define PROMINTR_MAX 15 + +struct linux_prom_registers { + unsigned int which_io; /* is this in OBIO space? */ + unsigned int phys_addr; /* The physical address of this register */ + unsigned int reg_size; /* How many bytes does this register take up? */ +}; + +struct linux_prom_irqs { + int pri; /* IRQ priority */ + int vector; /* This is foobar, what does it do? */ +}; + +/* Element of the "ranges" vector */ +struct linux_prom_ranges { + unsigned int ot_child_space; + unsigned int ot_child_base; /* Bus feels this */ + unsigned int ot_parent_space; + unsigned int ot_parent_base; /* CPU looks from here */ + unsigned int or_size; +}; + +/* Ranges and reg properties are a bit different for PCI. */ +struct linux_prom_pci_registers { + /* + * We don't know what information this field contain. + * We guess, PCI device function is in bits 15:8 + * So, ... + */ + unsigned int which_io; /* Let it be which_io */ + + unsigned int phys_hi; + unsigned int phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_pci_ranges { + unsigned int child_phys_hi; /* Only certain bits are encoded here. */ + unsigned int child_phys_mid; + unsigned int child_phys_lo; + + unsigned int parent_phys_hi; + unsigned int parent_phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_pci_assigned_addresses { + unsigned int which_io; + + unsigned int phys_hi; + unsigned int phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_ebus_ranges { + unsigned int child_phys_hi; + unsigned int child_phys_lo; + + unsigned int parent_phys_hi; + unsigned int parent_phys_mid; + unsigned int parent_phys_lo; + + unsigned int size; +}; + +/* Offset into the EEPROM where the id PROM is located on the 4c */ +#define IDPROM_OFFSET 0x7d8 + +/* On sun4m; physical. */ +/* MicroSPARC(-II) does not decode 31rd bit, but it works. */ +#define IDPROM_OFFSET_M 0xfd8 + +struct idprom { + unsigned char id_format; /* Format identifier (always 0x01) */ + unsigned char id_machtype; /* Machine type */ + unsigned char id_ethaddr[6]; /* Hardware ethernet address */ + long id_date; /* Date of manufacture */ + unsigned int id_sernum:24; /* Unique serial number */ + unsigned char id_cksum; /* Checksum - xor of the data bytes */ + unsigned char reserved[16]; +}; + +extern struct idprom *idprom; +extern void idprom_init(void); + +#define IDPROM_SIZE (sizeof(struct idprom)) + +#endif /* !(__ASSEMBLY__) */ + +#endif diff --git a/include/asm-sparc/psr.h b/include/asm-sparc/psr.h new file mode 100644 index 000000000..fc779477e --- /dev/null +++ b/include/asm-sparc/psr.h @@ -0,0 +1,97 @@ +/* psr.h: This file holds the macros for masking off various parts of + * the processor status register on the Sparc. This is valid + * for Version 8. On the V9 this is renamed to the PSTATE + * register and its members are accessed as fields like + * PSTATE.PRIV for the current CPU privilege level. + * + * taken from the SPARC port of Linux, + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_PSR_H__ +#define __SPARC_PSR_H__ + +/* The Sparc PSR fields are laid out as the following: + * + * ------------------------------------------------------------------------ + * | impl | vers | icc | resv | EC | EF | PIL | S | PS | ET | CWP | + * | 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 | + * ------------------------------------------------------------------------ + */ +#define PSR_CWP 0x0000001f /* current window pointer */ +#define PSR_ET 0x00000020 /* enable traps field */ +#define PSR_PS 0x00000040 /* previous privilege level */ +#define PSR_S 0x00000080 /* current privilege level */ +#define PSR_PIL 0x00000f00 /* processor interrupt level */ +#define PSR_EF 0x00001000 /* enable floating point */ +#define PSR_EC 0x00002000 /* enable co-processor */ +#define PSR_LE 0x00008000 /* SuperSparcII little-endian */ +#define PSR_ICC 0x00f00000 /* integer condition codes */ +#define PSR_C 0x00100000 /* carry bit */ +#define PSR_V 0x00200000 /* overflow bit */ +#define PSR_Z 0x00400000 /* zero bit */ +#define PSR_N 0x00800000 /* negative bit */ +#define PSR_VERS 0x0f000000 /* cpu-version field */ +#define PSR_IMPL 0xf0000000 /* cpu-implementation field */ + +#define PSR_PIL_OFS 8 + +#ifndef __ASSEMBLY__ +/* Get the %psr register. */ +extern __inline__ unsigned int get_psr(void) +{ + unsigned int psr; + __asm__ __volatile__("rd %%psr, %0\n\t" + "nop\n\t" "nop\n\t" "nop\n\t":"=r"(psr) + : /* no inputs */ + :"memory"); + + return psr; +} + +extern __inline__ void put_psr(unsigned int new_psr) +{ + __asm__ __volatile__("wr %0, 0x0, %%psr\n\t" "nop\n\t" "nop\n\t" "nop\n\t": /* no outputs */ + :"r"(new_psr) + :"memory", "cc"); +} + +/* Get the %fsr register. Be careful, make sure the floating point + * enable bit is set in the %psr when you execute this or you will + * incur a trap. + */ + +extern unsigned int fsr_storage; + +extern __inline__ unsigned int get_fsr(void) +{ + unsigned int fsr = 0; + + __asm__ __volatile__("st %%fsr, %1\n\t" + "ld %1, %0\n\t":"=r"(fsr) + :"m"(fsr_storage)); + + return fsr; +} + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(__SPARC_PSR_H__) */ diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h new file mode 100644 index 000000000..12a9c569a --- /dev/null +++ b/include/asm-sparc/ptrace.h @@ -0,0 +1,181 @@ +/* Contain the Stack frame layout on interrupt. pt_regs. + * taken from the SPARC port of Linux (ptrace.h). + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_PTRACE_H__ +#define __SPARC_PTRACE_H__ + +#include + +/* This struct defines the way the registers are stored on the + * stack during a system call and basically all traps. + */ + +#ifndef __ASSEMBLY__ + +struct pt_regs { + unsigned long psr; + unsigned long pc; + unsigned long npc; + unsigned long y; + unsigned long u_regs[16]; /* globals and ins */ +}; + +#define UREG_G0 0 +#define UREG_G1 1 +#define UREG_G2 2 +#define UREG_G3 3 +#define UREG_G4 4 +#define UREG_G5 5 +#define UREG_G6 6 +#define UREG_G7 7 +#define UREG_I0 8 +#define UREG_I1 9 +#define UREG_I2 10 +#define UREG_I3 11 +#define UREG_I4 12 +#define UREG_I5 13 +#define UREG_I6 14 +#define UREG_I7 15 +#define UREG_WIM UREG_G0 +#define UREG_FADDR UREG_G0 +#define UREG_FP UREG_I6 +#define UREG_RETPC UREG_I7 + +/* A register window */ +struct reg_window { + unsigned long locals[8]; + unsigned long ins[8]; +}; + +/* A Sparc stack frame */ +struct sparc_stackf { + unsigned long locals[8]; + unsigned long ins[6]; + struct sparc_stackf *fp; + unsigned long callers_pc; + char *structptr; + unsigned long xargs[6]; + unsigned long xxargs[1]; +}; + +#define TRACEREG_SZ sizeof(struct pt_regs) +#define STACKFRAME_SZ sizeof(struct sparc_stackf) + +#else /* __ASSEMBLY__ */ +/* For assembly code. */ +#define TRACEREG_SZ 0x50 +#define STACKFRAME_SZ 0x60 +#endif + +/* + * The asm_offsets.h is a generated file, so we cannot include it. + * It may be OK for glibc headers, but it's utterly pointless for C code. + * The assembly code using those offsets has to include it explicitly. + */ +/* #include */ + +/* These are for pt_regs. */ +#define PT_PSR 0x0 +#define PT_PC 0x4 +#define PT_NPC 0x8 +#define PT_Y 0xc +#define PT_G0 0x10 +#define PT_WIM PT_G0 +#define PT_G1 0x14 +#define PT_G2 0x18 +#define PT_G3 0x1c +#define PT_G4 0x20 +#define PT_G5 0x24 +#define PT_G6 0x28 +#define PT_G7 0x2c +#define PT_I0 0x30 +#define PT_I1 0x34 +#define PT_I2 0x38 +#define PT_I3 0x3c +#define PT_I4 0x40 +#define PT_I5 0x44 +#define PT_I6 0x48 +#define PT_FP PT_I6 +#define PT_I7 0x4c + +/* Reg_window offsets */ +#define RW_L0 0x00 +#define RW_L1 0x04 +#define RW_L2 0x08 +#define RW_L3 0x0c +#define RW_L4 0x10 +#define RW_L5 0x14 +#define RW_L6 0x18 +#define RW_L7 0x1c +#define RW_I0 0x20 +#define RW_I1 0x24 +#define RW_I2 0x28 +#define RW_I3 0x2c +#define RW_I4 0x30 +#define RW_I5 0x34 +#define RW_I6 0x38 +#define RW_I7 0x3c + +/* Stack_frame offsets */ +#define SF_L0 0x00 +#define SF_L1 0x04 +#define SF_L2 0x08 +#define SF_L3 0x0c +#define SF_L4 0x10 +#define SF_L5 0x14 +#define SF_L6 0x18 +#define SF_L7 0x1c +#define SF_I0 0x20 +#define SF_I1 0x24 +#define SF_I2 0x28 +#define SF_I3 0x2c +#define SF_I4 0x30 +#define SF_I5 0x34 +#define SF_FP 0x38 +#define SF_PC 0x3c +#define SF_RETP 0x40 +#define SF_XARG0 0x44 +#define SF_XARG1 0x48 +#define SF_XARG2 0x4c +#define SF_XARG3 0x50 +#define SF_XARG4 0x54 +#define SF_XARG5 0x58 +#define SF_XXARG 0x5c + +/* Stuff for the ptrace system call */ +#define PTRACE_SUNATTACH 10 +#define PTRACE_SUNDETACH 11 +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 +#define PTRACE_READDATA 16 +#define PTRACE_WRITEDATA 17 +#define PTRACE_READTEXT 18 +#define PTRACE_WRITETEXT 19 +#define PTRACE_GETFPAREGS 20 +#define PTRACE_SETFPAREGS 21 + +#define PTRACE_GETUCODE 29 /* stupid bsd-ism */ + +#endif /* !(_SPARC_PTRACE_H) */ diff --git a/include/asm-sparc/srmmu.h b/include/asm-sparc/srmmu.h new file mode 100644 index 000000000..5214d96a7 --- /dev/null +++ b/include/asm-sparc/srmmu.h @@ -0,0 +1,301 @@ +/* SRMMU page table defines and code, + * taken from the SPARC port of Linux + * + * Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_SRMMU_H__ +#define __SPARC_SRMMU_H__ + +#include +#include + +/* Number of contexts is implementation-dependent; 64k is the most we support */ +#define SRMMU_MAX_CONTEXTS 65536 + +/* PMD_SHIFT determines the size of the area a second-level page table entry can map */ +#define SRMMU_REAL_PMD_SHIFT 18 +#define SRMMU_REAL_PMD_SIZE (1UL << SRMMU_REAL_PMD_SHIFT) +#define SRMMU_REAL_PMD_MASK (~(SRMMU_REAL_PMD_SIZE-1)) +#define SRMMU_REAL_PMD_ALIGN(__addr) (((__addr)+SRMMU_REAL_PMD_SIZE-1)&SRMMU_REAL_PMD_MASK) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define SRMMU_PGDIR_SHIFT 24 +#define SRMMU_PGDIR_SIZE (1UL << SRMMU_PGDIR_SHIFT) +#define SRMMU_PGDIR_MASK (~(SRMMU_PGDIR_SIZE-1)) +#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK) + +#define SRMMU_REAL_PTRS_PER_PTE 64 +#define SRMMU_REAL_PTRS_PER_PMD 64 +#define SRMMU_PTRS_PER_PGD 256 + +#define SRMMU_REAL_PTE_TABLE_SIZE (SRMMU_REAL_PTRS_PER_PTE*4) +#define SRMMU_PMD_TABLE_SIZE (SRMMU_REAL_PTRS_PER_PMD*4) +#define SRMMU_PGD_TABLE_SIZE (SRMMU_PTRS_PER_PGD*4) + +/* + * To support pagetables in highmem, Linux introduces APIs which + * return struct page* and generally manipulate page tables when + * they are not mapped into kernel space. Our hardware page tables + * are smaller than pages. We lump hardware tabes into big, page sized + * software tables. + * + * PMD_SHIFT determines the size of the area a second-level page table entry + * can map, and our pmd_t is 16 times larger than normal. The values which + * were once defined here are now generic for 4c and srmmu, so they're + * found in pgtable.h. + */ +#define SRMMU_PTRS_PER_PMD 4 + +/* Definition of the values in the ET field of PTD's and PTE's */ +#define SRMMU_ET_MASK 0x3 +#define SRMMU_ET_INVALID 0x0 +#define SRMMU_ET_PTD 0x1 +#define SRMMU_ET_PTE 0x2 +#define SRMMU_ET_REPTE 0x3 /* AIEEE, SuperSparc II reverse endian page! */ + +/* Physical page extraction from PTP's and PTE's. */ +#define SRMMU_CTX_PMASK 0xfffffff0 +#define SRMMU_PTD_PMASK 0xfffffff0 +#define SRMMU_PTE_PMASK 0xffffff00 + +/* The pte non-page bits. Some notes: + * 1) cache, dirty, valid, and ref are frobbable + * for both supervisor and user pages. + * 2) exec and write will only give the desired effect + * on user pages + * 3) use priv and priv_readonly for changing the + * characteristics of supervisor ptes + */ +#define SRMMU_CACHE 0x80 +#define SRMMU_DIRTY 0x40 +#define SRMMU_REF 0x20 +#define SRMMU_NOREAD 0x10 +#define SRMMU_EXEC 0x08 +#define SRMMU_WRITE 0x04 +#define SRMMU_VALID 0x02 /* SRMMU_ET_PTE */ +#define SRMMU_PRIV 0x1c +#define SRMMU_PRIV_RDONLY 0x18 + +#define SRMMU_FILE 0x40 /* Implemented in software */ + +#define SRMMU_PTE_FILE_SHIFT 8 /* == 32-PTE_FILE_MAX_BITS */ + +#define SRMMU_CHG_MASK (0xffffff00 | SRMMU_REF | SRMMU_DIRTY) + +/* SRMMU swap entry encoding + * + * We use 5 bits for the type and 19 for the offset. This gives us + * 32 swapfiles of 4GB each. Encoding looks like: + * + * oooooooooooooooooootttttRRRRRRRR + * fedcba9876543210fedcba9876543210 + * + * The bottom 8 bits are reserved for protection and status bits, especially + * FILE and PRESENT. + */ +#define SRMMU_SWP_TYPE_MASK 0x1f +#define SRMMU_SWP_TYPE_SHIFT SRMMU_PTE_FILE_SHIFT +#define SRMMU_SWP_OFF_MASK 0x7ffff +#define SRMMU_SWP_OFF_SHIFT (SRMMU_PTE_FILE_SHIFT + 5) + +/* Some day I will implement true fine grained access bits for + * user pages because the SRMMU gives us the capabilities to + * enforce all the protection levels that vma's can have. + * XXX But for now... + */ +#define SRMMU_PAGE_NONE __pgprot(SRMMU_CACHE | \ + SRMMU_PRIV | SRMMU_REF) +#define SRMMU_PAGE_SHARED __pgprot(SRMMU_VALID | SRMMU_CACHE | \ + SRMMU_EXEC | SRMMU_WRITE | SRMMU_REF) +#define SRMMU_PAGE_COPY __pgprot(SRMMU_VALID | SRMMU_CACHE | \ + SRMMU_EXEC | SRMMU_REF) +#define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \ + SRMMU_EXEC | SRMMU_REF) +#define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \ + SRMMU_DIRTY | SRMMU_REF) + +/* SRMMU Register addresses in ASI 0x4. These are valid for all + * current SRMMU implementations that exist. + */ +#define SRMMU_CTRL_REG 0x00000000 +#define SRMMU_CTXTBL_PTR 0x00000100 +#define SRMMU_CTX_REG 0x00000200 +#define SRMMU_FAULT_STATUS 0x00000300 +#define SRMMU_FAULT_ADDR 0x00000400 + +#define WINDOW_FLUSH(tmp1, tmp2) \ + mov 0, tmp1; \ +98: ld [%g6 + TI_UWINMASK], tmp2; \ + orcc %g0, tmp2, %g0; \ + add tmp1, 1, tmp1; \ + bne 98b; \ + save %sp, -64, %sp; \ +99: subcc tmp1, 1, tmp1; \ + bne 99b; \ + restore %g0, %g0, %g0; + +#ifndef __ASSEMBLY__ + +/* This makes sense. Honest it does - Anton */ +/* XXX Yes but it's ugly as sin. FIXME. -KMW */ +extern void *srmmu_nocache_pool; +#define __nocache_pa(VADDR) (((unsigned long)VADDR) - SRMMU_NOCACHE_VADDR + __pa((unsigned long)srmmu_nocache_pool)) +#define __nocache_va(PADDR) (__va((unsigned long)PADDR) - (unsigned long)srmmu_nocache_pool + SRMMU_NOCACHE_VADDR) +#define __nocache_fix(VADDR) __va(__nocache_pa(VADDR)) + +/* Accessing the MMU control register. */ +extern __inline__ unsigned int srmmu_get_mmureg(void) +{ + unsigned int retval; + __asm__ __volatile__("lda [%%g0] %1, %0\n\t": + "=r"(retval):"i"(ASI_M_MMUREGS)); + return retval; +} + +extern __inline__ void srmmu_set_mmureg(unsigned long regval) +{ + __asm__ __volatile__("sta %0, [%%g0] %1\n\t"::"r"(regval), + "i"(ASI_M_MMUREGS):"memory"); + +} + +extern __inline__ void srmmu_set_ctable_ptr(unsigned long paddr) +{ + paddr = ((paddr >> 4) & SRMMU_CTX_PMASK); + __asm__ __volatile__("sta %0, [%1] %2\n\t"::"r"(paddr), + "r"(SRMMU_CTXTBL_PTR), + "i"(ASI_M_MMUREGS):"memory"); +} + +extern __inline__ unsigned long srmmu_get_ctable_ptr(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t": + "=r"(retval): + "r"(SRMMU_CTXTBL_PTR), "i"(ASI_M_MMUREGS)); + return (retval & SRMMU_CTX_PMASK) << 4; +} + +extern __inline__ void srmmu_set_context(int context) +{ + __asm__ __volatile__("sta %0, [%1] %2\n\t"::"r"(context), + "r"(SRMMU_CTX_REG), "i"(ASI_M_MMUREGS):"memory"); +} + +extern __inline__ int srmmu_get_context(void) +{ + register int retval; + __asm__ __volatile__("lda [%1] %2, %0\n\t": + "=r"(retval): + "r"(SRMMU_CTX_REG), "i"(ASI_M_MMUREGS)); + return retval; +} + +extern __inline__ unsigned int srmmu_get_fstatus(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t": + "=r"(retval): + "r"(SRMMU_FAULT_STATUS), "i"(ASI_M_MMUREGS)); + return retval; +} + +extern __inline__ unsigned int srmmu_get_faddr(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t": + "=r"(retval): + "r"(SRMMU_FAULT_ADDR), "i"(ASI_M_MMUREGS)); + return retval; +} + +/* This is guaranteed on all SRMMU's. */ +extern __inline__ void srmmu_flush_whole_tlb(void) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400), /* Flush entire TLB!! */ + "i"(ASI_M_FLUSH_PROBE):"memory"); + +} + +/* These flush types are not available on all chips... */ +extern __inline__ void srmmu_flush_tlb_ctx(void) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x300), /* Flush TLB ctx.. */ + "i"(ASI_M_FLUSH_PROBE):"memory"); + +} + +extern __inline__ void srmmu_flush_tlb_region(unsigned long addr) +{ + addr &= SRMMU_PGDIR_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(addr | 0x200), /* Flush TLB region.. */ + "i"(ASI_M_FLUSH_PROBE):"memory"); + +} + +extern __inline__ void srmmu_flush_tlb_segment(unsigned long addr) +{ + addr &= SRMMU_REAL_PMD_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(addr | 0x100), /* Flush TLB segment.. */ + "i"(ASI_M_FLUSH_PROBE):"memory"); + +} + +extern __inline__ void srmmu_flush_tlb_page(unsigned long page) +{ + page &= PAGE_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(page), /* Flush TLB page.. */ + "i"(ASI_M_FLUSH_PROBE):"memory"); + +} + +extern __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr) +{ + unsigned long retval; + + vaddr &= PAGE_MASK; + __asm__ __volatile__("lda [%1] %2, %0\n\t": + "=r"(retval): + "r"(vaddr | 0x400), "i"(ASI_M_FLUSH_PROBE)); + + return retval; +} + +extern __inline__ int srmmu_get_pte(unsigned long addr) +{ + register unsigned long entry; + + __asm__ __volatile__("\n\tlda [%1] %2,%0\n\t": + "=r"(entry): + "r"((addr & 0xfffff000) | 0x400), + "i"(ASI_M_FLUSH_PROBE)); + return entry; +} + +extern unsigned long (*srmmu_read_physical) (unsigned long paddr); +extern void (*srmmu_write_physical) (unsigned long paddr, unsigned long word); + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(__SPARC_SRMMU_H__) */ diff --git a/include/asm-sparc/stack.h b/include/asm-sparc/stack.h new file mode 100644 index 000000000..b40a9f355 --- /dev/null +++ b/include/asm-sparc/stack.h @@ -0,0 +1,162 @@ +/* SPARC stack layout Macros and structures, + * mainly taken from BCC (the Bare C compiler for + * SPARC LEON2/3) sources. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __SPARC_STACK_H__ +#define __SPARC_STACK_H__ + +#include + +#ifndef __ASSEMBLER__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PT_REGS_SZ sizeof(struct pt_regs) + +/* A Sparc stack frame */ + struct sparc_stackframe_regs { + unsigned long sf_locals[8]; + unsigned long sf_ins[6]; + struct sparc_stackframe_regs *sf_fp; + unsigned long sf_callers_pc; + char *sf_structptr; + unsigned long sf_xargs[6]; + unsigned long sf_xxargs[1]; + }; +#define SF_REGS_SZ sizeof(struct sparc_stackframe_regs) + +/* A register window */ + struct sparc_regwindow_regs { + unsigned long locals[8]; + unsigned long ins[8]; + }; +#define RW_REGS_SZ sizeof(struct sparc_regwindow_regs) + +/* A fpu window */ + struct sparc_fpuwindow_regs { + unsigned long locals[32]; + unsigned long fsr; + unsigned long lastctx; + }; +#define FW_REGS_SZ sizeof(struct sparc_fpuwindow_regs) + +#ifdef __cplusplus +} +#endif +#else +#define PT_REGS_SZ 0x50 /* 20*4 */ +#define SF_REGS_SZ 0x60 /* 24*4 */ +#define RW_REGS_SZ 0x20 /* 16*4 */ +#define FW_REGS_SZ 0x88 /* 34*4 */ +#endif /* !ASM */ + +/* These are for pt_regs. */ +#define PT_PSR 0x0 +#define PT_PC 0x4 +#define PT_NPC 0x8 +#define PT_Y 0xc +#define PT_G0 0x10 +#define PT_WIM PT_G0 +#define PT_G1 0x14 +#define PT_G2 0x18 +#define PT_G3 0x1c +#define PT_G4 0x20 +#define PT_G5 0x24 +#define PT_G6 0x28 +#define PT_G7 0x2c +#define PT_I0 0x30 +#define PT_I1 0x34 +#define PT_I2 0x38 +#define PT_I3 0x3c +#define PT_I4 0x40 +#define PT_I5 0x44 +#define PT_I6 0x48 +#define PT_FP PT_I6 +#define PT_I7 0x4c + +/* Stack_frame offsets */ +#define SF_L0 0x00 +#define SF_L1 0x04 +#define SF_L2 0x08 +#define SF_L3 0x0c +#define SF_L4 0x10 +#define SF_L5 0x14 +#define SF_L6 0x18 +#define SF_L7 0x1c +#define SF_I0 0x20 +#define SF_I1 0x24 +#define SF_I2 0x28 +#define SF_I3 0x2c +#define SF_I4 0x30 +#define SF_I5 0x34 +#define SF_FP 0x38 +#define SF_PC 0x3c +#define SF_RETP 0x40 +#define SF_XARG0 0x44 +#define SF_XARG1 0x48 +#define SF_XARG2 0x4c +#define SF_XARG3 0x50 +#define SF_XARG4 0x54 +#define SF_XARG5 0x58 +#define SF_XXARG 0x5c + +/* Reg_window offsets */ +#define RW_L0 0x00 +#define RW_L1 0x04 +#define RW_L2 0x08 +#define RW_L3 0x0c +#define RW_L4 0x10 +#define RW_L5 0x14 +#define RW_L6 0x18 +#define RW_L7 0x1c +#define RW_I0 0x20 +#define RW_I1 0x24 +#define RW_I2 0x28 +#define RW_I3 0x2c +#define RW_I4 0x30 +#define RW_I5 0x34 +#define RW_I6 0x38 +#define RW_I7 0x3c + +/* Fpu_window offsets */ +#define FW_F0 0x00 +#define FW_F2 0x08 +#define FW_F4 0x10 +#define FW_F6 0x18 +#define FW_F8 0x20 +#define FW_F10 0x28 +#define FW_F12 0x30 +#define FW_F14 0x38 +#define FW_F16 0x40 +#define FW_F18 0x48 +#define FW_F20 0x50 +#define FW_F22 0x58 +#define FW_F24 0x60 +#define FW_F26 0x68 +#define FW_F28 0x70 +#define FW_F30 0x78 +#define FW_FSR 0x80 + +#endif diff --git a/include/asm-sparc/string.h b/include/asm-sparc/string.h new file mode 100644 index 000000000..c6bbc203d --- /dev/null +++ b/include/asm-sparc/string.h @@ -0,0 +1,55 @@ +/* + * (C) Copyright 2000 - 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _SPARC_STRING_H_ +#define _SPARC_STRING_H_ + +/* +#define __HAVE_ARCH_STRCPY +#define __HAVE_ARCH_STRNCPY +#define __HAVE_ARCH_STRLEN +#define __HAVE_ARCH_STRCMP +#define __HAVE_ARCH_STRCAT +#define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_BCOPY +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE +#define __HAVE_ARCH_MEMCMP +#define __HAVE_ARCH_MEMCHR +*/ + +extern int strcasecmp(const char *, const char *); +extern int strncasecmp(const char *, const char *, int); +extern char *strcpy(char *, const char *); +extern char *strncpy(char *, const char *, __kernel_size_t); +extern __kernel_size_t strlen(const char *); +extern int strcmp(const char *, const char *); +extern char *strcat(char *, const char *); +extern void *memset(void *, int, __kernel_size_t); +extern void *memcpy(void *, const void *, __kernel_size_t); +extern void *memmove(void *, const void *, __kernel_size_t); +extern int memcmp(const void *, const void *, __kernel_size_t); +extern void *memchr(const void *, int, __kernel_size_t); + +#endif diff --git a/include/asm-sparc/types.h b/include/asm-sparc/types.h new file mode 100644 index 000000000..69f93d60b --- /dev/null +++ b/include/asm-sparc/types.h @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2000 - 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _SPARC_TYPES_H +#define _SPARC_TYPES_H + +#ifndef __ASSEMBLY__ + +typedef unsigned short umode_t; + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +typedef struct { + __u32 u[4]; +} __attribute((aligned(16))) vector128; + +#ifdef __KERNEL__ +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define BITS_PER_LONG 32 + +/* DMA addresses are 32-bits wide */ +typedef u32 dma_addr_t; + +#endif /* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/include/asm-sparc/u-boot.h b/include/asm-sparc/u-boot.h new file mode 100644 index 000000000..9c594e1f8 --- /dev/null +++ b/include/asm-sparc/u-boot.h @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2000 - 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007, From asm-ppc/u-boot.h + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ******************************************************************** + * NOTE: This header file defines an interface to U-Boot. Including + * this (unmodified) header file in another file is considered normal + * use of U-Boot, and does *not* fall under the heading of "derived + * work". + ******************************************************************** + */ + +#ifndef __U_BOOT_H__ +#define __U_BOOT_H__ + +/* + * Currently, this Board information is not passed to + * Linux kernel from U-Boot, but may be passed to other + * Operating systems. This is because U-boot emulates + * a SUN PROM loader (from Linux point of view). + * + * include/asm-sparc/u-boot.h + */ + +#ifndef __ASSEMBLY__ + +typedef struct bd_info { + unsigned long bi_memstart; /* start of DRAM memory */ + unsigned long bi_memsize; /* size of DRAM memory in bytes */ + unsigned long bi_flashstart; /* start of FLASH memory */ + unsigned long bi_flashsize; /* size of FLASH memory */ + unsigned long bi_flashoffset; /* reserved area for startup monitor */ + unsigned long bi_sramstart; /* start of SRAM memory */ + unsigned long bi_sramsize; /* size of SRAM memory */ + unsigned long bi_bootflags; /* boot / reboot flag (for LynxOS) */ + unsigned long bi_ip_addr; /* IP Address */ + unsigned char bi_enetaddr[6]; /* Ethernet adress */ + unsigned short bi_ethspeed; /* Ethernet speed in Mbps */ + unsigned long bi_intfreq; /* Internal Freq, in MHz */ + unsigned long bi_busfreq; /* Bus Freq, in MHz */ + unsigned long bi_baudrate; /* Console Baudrate */ +#ifdef CONFIG_HAS_ETH1 + /* second onboard ethernet port */ + unsigned char bi_enet1addr[6]; +#endif +#ifdef CONFIG_HAS_ETH2 + /* third onboard ethernet port */ + unsigned char bi_enet2addr[6]; +#endif +#ifdef CONFIG_HAS_ETH3 + unsigned char bi_enet3addr[6]; +#endif +} bd_t; + +#endif /* __ASSEMBLY__ */ +#endif /* __U_BOOT_H__ */ diff --git a/include/asm-sparc/winmacro.h b/include/asm-sparc/winmacro.h new file mode 100644 index 000000000..66fc639a7 --- /dev/null +++ b/include/asm-sparc/winmacro.h @@ -0,0 +1,151 @@ +/* + * Added to U-boot, + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * Copyright (C) 2007 + * + * LEON2/3 LIBIO low-level routines + * Written by Jiri Gaisler. + * Copyright (C) 2004 Gaisler Research AB + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#ifndef __SPARC_WINMACRO_H__ +#define __SPARC_WINMACRO_H__ + +#include +#include + +/* Store the register window onto the 8-byte aligned area starting + * at %reg. It might be %sp, it might not, we don't care. + */ +#define RW_STORE(reg) \ + std %l0, [%reg + RW_L0]; \ + std %l2, [%reg + RW_L2]; \ + std %l4, [%reg + RW_L4]; \ + std %l6, [%reg + RW_L6]; \ + std %i0, [%reg + RW_I0]; \ + std %i2, [%reg + RW_I2]; \ + std %i4, [%reg + RW_I4]; \ + std %i6, [%reg + RW_I6]; + +/* Load a register window from the area beginning at %reg. */ +#define RW_LOAD(reg) \ + ldd [%reg + RW_L0], %l0; \ + ldd [%reg + RW_L2], %l2; \ + ldd [%reg + RW_L4], %l4; \ + ldd [%reg + RW_L6], %l6; \ + ldd [%reg + RW_I0], %i0; \ + ldd [%reg + RW_I2], %i2; \ + ldd [%reg + RW_I4], %i4; \ + ldd [%reg + RW_I6], %i6; + +/* Loading and storing struct pt_reg trap frames. */ +#define PT_LOAD_INS(base_reg) \ + ldd [%base_reg + SF_REGS_SZ + PT_I0], %i0; \ + ldd [%base_reg + SF_REGS_SZ + PT_I2], %i2; \ + ldd [%base_reg + SF_REGS_SZ + PT_I4], %i4; \ + ldd [%base_reg + SF_REGS_SZ + PT_I6], %i6; + +#define PT_LOAD_GLOBALS(base_reg) \ + ld [%base_reg + SF_REGS_SZ + PT_G1], %g1; \ + ldd [%base_reg + SF_REGS_SZ + PT_G2], %g2; \ + ldd [%base_reg + SF_REGS_SZ + PT_G4], %g4; \ + ldd [%base_reg + SF_REGS_SZ + PT_G6], %g6; + +#define PT_LOAD_YREG(base_reg, scratch) \ + ld [%base_reg + SF_REGS_SZ + PT_Y], %scratch; \ + wr %scratch, 0x0, %y; + +#define PT_LOAD_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \ + ld [%base_reg + SF_REGS_SZ + PT_PSR], %pt_psr; \ + ld [%base_reg + SF_REGS_SZ + PT_PC], %pt_pc; \ + ld [%base_reg + SF_REGS_SZ + PT_NPC], %pt_npc; + +#define PT_LOAD_ALL(base_reg, pt_psr, pt_pc, pt_npc, scratch) \ + PT_LOAD_YREG(base_reg, scratch) \ + PT_LOAD_INS(base_reg) \ + PT_LOAD_GLOBALS(base_reg) \ + PT_LOAD_PRIV(base_reg, pt_psr, pt_pc, pt_npc) + +#define PT_STORE_INS(base_reg) \ + std %i0, [%base_reg + SF_REGS_SZ + PT_I0]; \ + std %i2, [%base_reg + SF_REGS_SZ + PT_I2]; \ + std %i4, [%base_reg + SF_REGS_SZ + PT_I4]; \ + std %i6, [%base_reg + SF_REGS_SZ + PT_I6]; + +#define PT_STORE_GLOBALS(base_reg) \ + st %g1, [%base_reg + SF_REGS_SZ + PT_G1]; \ + std %g2, [%base_reg + SF_REGS_SZ + PT_G2]; \ + std %g4, [%base_reg + SF_REGS_SZ + PT_G4]; \ + std %g6, [%base_reg + SF_REGS_SZ + PT_G6]; + +#define PT_STORE_YREG(base_reg, scratch) \ + rd %y, %scratch; \ + st %scratch, [%base_reg + SF_REGS_SZ + PT_Y]; + +#define PT_STORE_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \ + st %pt_psr, [%base_reg + SF_REGS_SZ + PT_PSR]; \ + st %pt_pc, [%base_reg + SF_REGS_SZ + PT_PC]; \ + st %pt_npc, [%base_reg + SF_REGS_SZ + PT_NPC]; + +#define PT_STORE_ALL(base_reg, reg_psr, reg_pc, reg_npc, g_scratch) \ + PT_STORE_PRIV(base_reg, reg_psr, reg_pc, reg_npc) \ + PT_STORE_GLOBALS(base_reg) \ + PT_STORE_YREG(base_reg, g_scratch) \ + PT_STORE_INS(base_reg) + +/* Store the fpu register window*/ +#define FW_STORE(reg) \ + std %f0, [reg + FW_F0]; \ + std %f2, [reg + FW_F2]; \ + std %f4, [reg + FW_F4]; \ + std %f6, [reg + FW_F6]; \ + std %f8, [reg + FW_F8]; \ + std %f10, [reg + FW_F10]; \ + std %f12, [reg + FW_F12]; \ + std %f14, [reg + FW_F14]; \ + std %f16, [reg + FW_F16]; \ + std %f18, [reg + FW_F18]; \ + std %f20, [reg + FW_F20]; \ + std %f22, [reg + FW_F22]; \ + std %f24, [reg + FW_F24]; \ + std %f26, [reg + FW_F26]; \ + std %f28, [reg + FW_F28]; \ + std %f30, [reg + FW_F30]; \ + st %fsr, [reg + FW_FSR]; + +/* Load a fpu register window from the area beginning at reg. */ +#define FW_LOAD(reg) \ + ldd [reg + FW_F0], %f0; \ + ldd [reg + FW_F2], %f2; \ + ldd [reg + FW_F4], %f4; \ + ldd [reg + FW_F6], %f6; \ + ldd [reg + FW_F8], %f8; \ + ldd [reg + FW_F10], %f10; \ + ldd [reg + FW_F12], %f12; \ + ldd [reg + FW_F14], %f14; \ + ldd [reg + FW_F16], %f16; \ + ldd [reg + FW_F18], %f18; \ + ldd [reg + FW_F20], %f20; \ + ldd [reg + FW_F22], %f22; \ + ldd [reg + FW_F24], %f24; \ + ldd [reg + FW_F26], %f26; \ + ldd [reg + FW_F28], %f28; \ + ldd [reg + FW_F30], %f30; \ + ld [reg + FW_FSR], %fsr; + +#endif diff --git a/lib_sparc/Makefile b/lib_sparc/Makefile new file mode 100644 index 000000000..1a354b6ea --- /dev/null +++ b/lib_sparc/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(ARCH).a + +SOBJS = + +COBJS = board.o cache.o interrupts.o time.o bootm.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/lib_sparc/board.c b/lib_sparc/board.c new file mode 100644 index 000000000..af301c046 --- /dev/null +++ b/lib_sparc/board.c @@ -0,0 +1,521 @@ +/* SPARC Board initialization + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#if defined(CONFIG_CMD_IDE) +#include +#endif +#ifdef CONFIG_STATUS_LED +#include +#endif +#include +#include +#include +#if defined(CONFIG_POST) +#include +#endif +#ifdef CONFIG_PS2KBD +#include +#endif +#ifdef CONFIG_CMD_AMBAPP +#include +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* Debug options +#define DEBUG_INIT_SEQUENCE +#define DEBUG_MEM_LAYOUT +#define DEBUG_COMMANDS +*/ + +extern void timer_interrupt_init(void); +extern void malloc_bin_reloc(void); +extern int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]); +extern int prom_init(void); + +#if defined(CONFIG__CMD_DOC) +void doc_init(void); +#endif + +#if !defined(CFG_NO_FLASH) +static char *failed = "*** failed ***\n"; +#endif + +#include + +ulong monitor_flash_len; + +/* + * Begin and End of memory area for malloc(), and current "brk" + */ +static ulong mem_malloc_start = 0; +static ulong mem_malloc_end = 0; +static ulong mem_malloc_brk = 0; + +/************************************************************************ + * Utilities * + ************************************************************************ + */ + +/* + * The Malloc area is immediately below the monitor copy in RAM + */ +static void mem_malloc_init(void) +{ + mem_malloc_start = CFG_MALLOC_BASE; + mem_malloc_end = CFG_MALLOC_END; + mem_malloc_brk = mem_malloc_start; + memset((void *)mem_malloc_start, 0, mem_malloc_end - mem_malloc_start); +} + +void *sbrk(ptrdiff_t increment) +{ + ulong old = mem_malloc_brk; + ulong new = old + increment; + + if ((new < mem_malloc_start) || (new > mem_malloc_end)) { + return (NULL); + } + mem_malloc_brk = new; + return ((void *)old); +} + +/***********************************************************************/ + +/************************************************************************ + * Init Utilities * + ************************************************************************ + * Some of this code should be moved into the core functions, + * but let's get it working (again) first... + */ + +static int init_baudrate(void) +{ + char tmp[64]; /* long enough for environment variables */ + int i = getenv_r("baudrate", tmp, sizeof(tmp)); + + gd->baudrate = (i > 0) + ? (int)simple_strtoul(tmp, NULL, 10) + : CONFIG_BAUDRATE; + return (0); +} + +/***********************************************************************/ + +/* + * All attempts to come up with a "common" initialization sequence + * that works for all boards and architectures failed: some of the + * requirements are just _too_ different. To get rid of the resulting + * mess of board dependend #ifdef'ed code we now make the whole + * initialization sequence configurable to the user. + * + * The requirements for any new initalization function is simple: it + * receives a pointer to the "global data" structure as it's only + * argument, and returns an integer return code, where 0 means + * "continue" and != 0 means "fatal error, hang the system". + */ +typedef int (init_fnc_t) (void); + +#define WATCHDOG_RESET(x) + +/************************************************************************ + * Initialization sequence * + ************************************************************************ + */ + +init_fnc_t *init_sequence[] = { + +#if defined(CONFIG_BOARD_EARLY_INIT_F) + board_early_init_f, +#endif + serial_init, + + init_timebase, + +#if defined(CONFIG_CMD_AMBAPP) + ambapp_init_reloc, +#endif + + env_init, + + init_baudrate, + + console_init_f, + display_options, + + checkcpu, + checkboard, +#if defined(CONFIG_MISC_INIT_F) + misc_init_f, +#endif + +#ifdef CONFIG_POST + post_init_f, +#endif + + NULL, /* Terminate this list, + * beware: this list will be relocated + * which means that NULL will become + * NULL+RELOC_OFFSET. We simply make + * NULL be -RELOC_OFFSET instead. + */ +}; + +/************************************************************************ + * + * This is the SPARC board initialization routine, running from RAM. + * + ************************************************************************ + */ +#ifdef DEBUG_INIT_SEQUENCE +char *str_init_seq = "INIT_SEQ 00\n"; +char *str_init_seq_done = "\n\rInit sequence done...\r\n\r\n"; +#endif + +void board_init_f(ulong bootflag) +{ + cmd_tbl_t *cmdtp; + bd_t *bd; + unsigned char *s; + init_fnc_t **init_fnc_ptr; + int j; + int i; + char *e; + +#ifndef CFG_NO_FLASH + ulong flash_size; +#endif + + gd = (gd_t *) (CFG_GBL_DATA_OFFSET); + + /* Clear initial global data */ + memset((void *)gd, 0, sizeof(gd_t)); + + gd->bd = (bd_t *) (gd + 1); /* At end of global data */ + gd->baudrate = CONFIG_BAUDRATE; + gd->cpu_clk = CONFIG_SYS_CLK_FREQ; + + bd = gd->bd; + bd->bi_memstart = CFG_RAM_BASE; + bd->bi_memsize = CFG_RAM_SIZE; + bd->bi_flashstart = CFG_FLASH_BASE; +#if defined(CFG_SRAM_BASE) && defined(CFG_SRAM_SIZE) + bd->bi_sramstart = CFG_SRAM_BASE; + bd->bi_sramsize = CFG_SRAM_SIZE; +#endif + bd->bi_baudrate = CONFIG_BAUDRATE; + bd->bi_bootflags = bootflag; /* boot / reboot flag (for LynxOS) */ + + gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ + gd->reloc_off = CFG_RELOC_MONITOR_BASE - CFG_MONITOR_BASE; + + for (init_fnc_ptr = init_sequence, j = 0; *init_fnc_ptr; + ++init_fnc_ptr, j++) { +#ifdef DEBUG_INIT_SEQUENCE + if (j > 9) + str_init_seq[9] = '0' + (j / 10); + str_init_seq[10] = '0' + (j - (j / 10) * 10); + serial_puts(str_init_seq); +#endif + if ((*init_fnc_ptr + gd->reloc_off) () != 0) { + hang(); + } + } +#ifdef DEBUG_INIT_SEQUENCE + serial_puts(str_init_seq_done); +#endif + + /* + * Now that we have DRAM mapped and working, we can + * relocate the code and continue running from DRAM. + * + * Reserve memory at end of RAM for (top down in that order): + * - kernel log buffer + * - protected RAM + * - LCD framebuffer + * - monitor code + * - board info struct + */ +#ifdef DEBUG_MEM_LAYOUT + printf("CFG_MONITOR_BASE: 0x%lx\n", CFG_MONITOR_BASE); + printf("CFG_ENV_ADDR: 0x%lx\n", CFG_ENV_ADDR); + printf("CFG_RELOC_MONITOR_BASE: 0x%lx (%d)\n", CFG_RELOC_MONITOR_BASE, + CFG_MONITOR_LEN); + printf("CFG_MALLOC_BASE: 0x%lx (%d)\n", CFG_MALLOC_BASE, + CFG_MALLOC_LEN); + printf("CFG_INIT_SP_OFFSET: 0x%lx (%d)\n", CFG_INIT_SP_OFFSET, + CFG_STACK_SIZE); + printf("CFG_PROM_OFFSET: 0x%lx (%d)\n", CFG_PROM_OFFSET, + CFG_PROM_SIZE); + printf("CFG_GBL_DATA_OFFSET: 0x%lx (%d)\n", CFG_GBL_DATA_OFFSET, + CFG_GBL_DATA_SIZE); +#endif + +#ifdef CONFIG_POST + post_bootmode_init(); + post_run(NULL, POST_ROM | post_bootmode_get(0)); +#endif + + /* + * We have to relocate the command table manually + */ + for (cmdtp = &__u_boot_cmd_start; cmdtp != &__u_boot_cmd_end; cmdtp++) { + ulong addr; + addr = (ulong) (cmdtp->cmd) + gd->reloc_off; +#if DEBUG_COMMANDS + printf("Command \"%s\": 0x%08lx => 0x%08lx\n", + cmdtp->name, (ulong) (cmdtp->cmd), addr); +#endif + cmdtp->cmd = + (int (*)(struct cmd_tbl_s *, int, int, char *[]))addr; + + addr = (ulong) (cmdtp->name) + gd->reloc_off; + cmdtp->name = (char *)addr; + + if (cmdtp->usage) { + addr = (ulong) (cmdtp->usage) + gd->reloc_off; + cmdtp->usage = (char *)addr; + } +#ifdef CFG_LONGHELP + if (cmdtp->help) { + addr = (ulong) (cmdtp->help) + gd->reloc_off; + cmdtp->help = (char *)addr; + } +#endif + } + +#if defined(CONFIG_CMD_AMBAPP) && defined(CFG_AMBAPP_PRINT_ON_STARTUP) + puts("AMBA:\n"); + do_ambapp_print(NULL, 0, 0, NULL); +#endif + + /* initialize higher level parts of CPU like time base and timers */ + cpu_init_r(); + + /* start timer */ + timer_interrupt_init(); + + /* + * Enable Interrupts before any calls to udelay, + * the flash driver may use udelay resulting in + * a hang if not timer0 IRQ is enabled. + */ + interrupt_init(); + +#if !defined(CFG_NO_FLASH) + puts("FLASH: "); + + if ((flash_size = flash_init()) > 0) { +# ifdef CFG_FLASH_CHECKSUM + print_size(flash_size, ""); + /* + * Compute and print flash CRC if flashchecksum is set to 'y' + * + * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX + */ + s = getenv("flashchecksum"); + if (s && (*s == 'y')) { + printf(" CRC: %08lX", + crc32(0, (const unsigned char *)CFG_FLASH_BASE, + flash_size) + ); + } + putc('\n'); +# else /* !CFG_FLASH_CHECKSUM */ + print_size(flash_size, "\n"); +# endif /* CFG_FLASH_CHECKSUM */ + } else { + puts(failed); + hang(); + } + + bd->bi_flashstart = CFG_FLASH_BASE; /* update start of FLASH memory */ + bd->bi_flashsize = flash_size; /* size of FLASH memory (final value) */ +#if CFG_MONITOR_BASE == CFG_FLASH_BASE + bd->bi_flashoffset = monitor_flash_len; /* reserved area for startup monitor */ +#else + bd->bi_flashoffset = 0; +#endif +#else /* CFG_NO_FLASH */ + bd->bi_flashsize = 0; + bd->bi_flashstart = 0; + bd->bi_flashoffset = 0; +#endif /* !CFG_NO_FLASH */ + + /* initialize malloc() area */ + mem_malloc_init(); + + malloc_bin_reloc(); + +#ifdef CONFIG_SPI +# if !defined(CFG_ENV_IS_IN_EEPROM) + spi_init_f(); +# endif + spi_init_r(); +#endif + + /* relocate environment function pointers etc. */ + env_relocate(); + +#if defined(CONFIG_BOARD_LATE_INIT) + board_late_init(); +#endif + + s = getenv("ethaddr"); + for (i = 0; i < 6; ++i) { + bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + +#ifdef CONFIG_HAS_ETH1 + /* handle the 2nd ethernet address */ + + s = getenv("eth1addr"); + + for (i = 0; i < 6; ++i) { + bd->bi_enet1addr[i] = s ? simple_strtoul(s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } +#endif + +#ifdef CFG_ID_EEPROM + mac_read_from_eeprom(); +#endif + + /* IP Address */ + bd->bi_ip_addr = getenv_IPaddr("ipaddr"); +#if defined(CONFIG_PCI) + /* + * Do pci configuration + */ + pci_init(); +#endif + + /* Initialize devices */ + devices_init(); + + /* Initialize the jump table for applications */ + jumptable_init(); + + /* Initialize the console (after the relocation and devices init) */ + console_init_r(); + +#ifdef CONFIG_SERIAL_SOFTWARE_FIFO + serial_buffered_init(); +#endif + +#ifdef CONFIG_STATUS_LED + status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); +#endif + + udelay(20); + + set_timer(0); + + /* Initialize from environment */ + if ((s = getenv("loadaddr")) != NULL) { + load_addr = simple_strtoul(s, NULL, 16); + } +#if defined(CONFIG_CMD_NET) + if ((s = getenv("bootfile")) != NULL) { + copy_filename(BootFile, s, sizeof(BootFile)); + } +#endif /* CFG_CMD_NET */ + + WATCHDOG_RESET(); + +#if defined(CONFIG_CMD_DOC) + WATCHDOG_RESET(); + puts("DOC: "); + doc_init(); +#endif + +#if defined(CONFIG_CMD_NET) +#if defined(CONFIG_NET_MULTI) + WATCHDOG_RESET(); + puts("Net: "); +#endif + eth_initialize(bd); +#endif + +#if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R) + WATCHDOG_RESET(); + debug("Reset Ethernet PHY\n"); + reset_phy(); +#endif + +#ifdef CONFIG_POST + post_run(NULL, POST_RAM | post_bootmode_get(0)); +#endif + +#if defined(CONFIG_CMD_IDE) + WATCHDOG_RESET(); + puts("IDE: "); + ide_init(); +#endif /* CFG_CMD_IDE */ + +#ifdef CONFIG_LAST_STAGE_INIT + WATCHDOG_RESET(); + /* + * Some parts can be only initialized if all others (like + * Interrupts) are up and running (i.e. the PC-style ISA + * keyboard). + */ + last_stage_init(); +#endif + +#ifdef CONFIG_PS2KBD + puts("PS/2: "); + kbd_init(); +#endif + prom_init(); + + /* main_loop */ + for (;;) { + WATCHDOG_RESET(); + main_loop(); + } + +} + +void hang(void) +{ + puts("### ERROR ### Please RESET the board ###\n"); +#ifdef CONFIG_SHOW_BOOT_PROGRESS + show_boot_progress(-30); +#endif + for (;;) ; +} + +/************************************************************************/ diff --git a/lib_sparc/bootm.c b/lib_sparc/bootm.c new file mode 100644 index 000000000..8900b2e58 --- /dev/null +++ b/lib_sparc/bootm.c @@ -0,0 +1,226 @@ +/* SPARC code for booting linux 2.6 + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#define PRINT_KERNEL_HEADER + +extern image_header_t header; +extern void srmmu_init_cpu(unsigned int entry); +extern void prepare_bootargs(char *bootargs); +extern int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]); + +#ifdef CONFIG_USB_UHCI +extern int usb_lowlevel_stop(void); +#endif + +/* sparc kernel argument (the ROM vector) */ +struct linux_romvec *kernel_arg_promvec; + +/* page szie is 4k */ +#define PAGE_SIZE 0x1000 +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 +struct __attribute__ ((packed)) { + char traptable[PAGE_SIZE]; + char swapper_pg_dir[PAGE_SIZE]; + char pg0[PAGE_SIZE]; + char pg1[PAGE_SIZE]; + char pg2[PAGE_SIZE]; + char pg3[PAGE_SIZE]; + char empty_bad_page[PAGE_SIZE]; + char empty_bad_page_table[PAGE_SIZE]; + char empty_zero_page[PAGE_SIZE]; + unsigned char hdr[4]; /* ascii "HdrS" */ + /* 00.02.06.0b is for Linux kernel 2.6.11 */ + unsigned char linuxver_mega_major; + unsigned char linuxver_major; + unsigned char linuxver_minor; + unsigned char linuxver_revision; + /* header version 0x0203 */ + unsigned short hdr_ver; + union __attribute__ ((packed)) { + struct __attribute__ ((packed)) { + unsigned short root_flags; + unsigned short root_dev; + unsigned short ram_flags; + unsigned int sparc_ramdisk_image; + unsigned int sparc_ramdisk_size; + unsigned int reboot_command; + unsigned int resv[3]; + unsigned int end; + } ver_0203; + } hdr_input; +} *linux_hdr; + +/* temporary initrd image holder */ +image_header_t ihdr; + +/* boot the linux kernel */ +void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], + bootm_headers_t * images) +{ + char *bootargs; + ulong ep, load; + ulong initrd_start, initrd_end; + ulong rd_data_start, rd_data_end, rd_len; + unsigned int data, len, checksum; + unsigned int initrd_addr, kernend; + void (*kernel) (struct linux_romvec *, void *); + struct lmb *lmb = images->lmb; + int ret; + + if (images->legacy_hdr_valid) { + ep = image_get_ep(images->legacy_hdr_os); + load = image_get_load(images->legacy_hdr_os); +#if defined(CONFIG_FIT) + } else if (images->fit_uname_os) { + int ret = fit_image_get_entry(images->fit_hdr_os, + images->fit_noffset_os, &ep); + if (ret) { + puts("Can't get entry point property!\n"); + goto error; + } + + ret = fit_image_get_load(images->fit_hdr_os, + images->fit_noffset_os, &load); + if (ret) { + puts("Can't get load address property!\n"); + goto error; + } +#endif + } else { + puts("Could not find kernel entry point!\n"); + goto error; + } + + /* Get virtual address of kernel start */ + linux_hdr = (void *)load; + + /* */ + kernel = (void (*)(struct linux_romvec *, void *))ep; + + /* check for a SPARC kernel */ + if ((linux_hdr->hdr[0] != 'H') || + (linux_hdr->hdr[1] != 'd') || + (linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) { + puts("Error reading header of SPARC Linux kernel, aborting\n"); + goto error; + } +#ifdef PRINT_KERNEL_HEADER + printf("## Found SPARC Linux kernel %d.%d.%d ...\n", + linux_hdr->linuxver_major, + linux_hdr->linuxver_minor, linux_hdr->linuxver_revision); +#endif + +#ifdef CONFIG_USB_UHCI + usb_lowlevel_stop(); +#endif + + /* set basic boot params in kernel header now that it has been + * extracted and is writeable. + */ + + /* + * Are we going to use an initrd image? + */ + ret = boot_get_ramdisk(argc, argv, images, IH_ARCH_SPARC, + &rd_data_start, &rd_data_end); + if (ret) { + /* RAM disk found but was corrupt */ + puts("RAM Disk corrupt\n"); + goto error; + } + + /* Calc length of RAM disk, if zero no ramdisk available */ + rd_len = rd_data_end - rd_data_start; + + if (rd_len) { + + /* Reserve the space used by PROM and stack. This is done + * to avoid that the RAM image is copied over stack or + * PROM. + */ + lmb_reserve(lmb, CFG_RELOC_MONITOR_BASE, CFG_RAM_END); + + ret = boot_ramdisk_high(lmb, rd_data_start, rd_len, + &initrd_start, &initrd_end); + if (ret) { + puts("### Failed to relocate RAM disk\n"); + goto error; + } + + /* Update SPARC kernel header so that Linux knows + * what is going on and where to find RAM disk. + * + * Set INITRD Image address relative to RAM Start + */ + linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image = + initrd_start - CFG_RAM_BASE; + linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = rd_len; + /* Clear READ ONLY flag if set to non-zero */ + linux_hdr->hdr_input.ver_0203.root_flags = 1; + /* Set root device to: Root_RAM0 */ + linux_hdr->hdr_input.ver_0203.root_dev = 0x100; + linux_hdr->hdr_input.ver_0203.ram_flags = 0; + } else { + /* NOT using RAMDISK image, overwriting kernel defaults */ + linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image = 0; + linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = 0; + /* Leave to kernel defaults + linux_hdr->hdr_input.ver_0203.root_flags = 1; + linux_hdr->hdr_input.ver_0203.root_dev = 0; + linux_hdr->hdr_input.ver_0203.ram_flags = 0; + */ + } + + /* Copy bootargs from bootargs variable to kernel readable area */ + bootargs = getenv("bootargs"); + prepare_bootargs(bootargs); + + if (!images->autostart) + return; + + /* turn on mmu & setup context table & page table for process 0 (kernel) */ + srmmu_init_cpu((unsigned int)kernel); + + /* Enter SPARC Linux kernel + * From now on the only code in u-boot that will be + * executed is the PROM code. + */ + kernel(kernel_arg_promvec, (void *)ep); + + /* It will never come to this... */ + while (1) ; + + error: + if (images->autostart) + do_reset(cmdtp, flag, argc, argv); + return; +} diff --git a/lib_sparc/cache.c b/lib_sparc/cache.c new file mode 100644 index 000000000..59d9bbe67 --- /dev/null +++ b/lib_sparc/cache.c @@ -0,0 +1,33 @@ +/* Sparc cache library + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +void flush_cache(ulong start_addr, ulong size) +{ + /* Flush All Cache */ + sparc_dcache_flush_all(); + sparc_icache_flush_all(); +} diff --git a/lib_sparc/interrupts.c b/lib_sparc/interrupts.c new file mode 100644 index 000000000..4c73b82a6 --- /dev/null +++ b/lib_sparc/interrupts.c @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2003 + * Gleb Natapov + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +/* Implemented by SPARC CPUs */ +extern int interrupt_init_cpu(void); +extern void timer_interrupt_cpu(void *arg); +extern int timer_interrupt_init_cpu(void); + +int intLock(void) +{ + unsigned int pil; + + pil = get_pil(); + + /* set PIL to 15 ==> no pending interrupts will interrupt CPU */ + set_pil(15); + + return pil; +} + +void intUnlock(int oldLevel) +{ + set_pil(oldLevel); +} + +void enable_interrupts(void) +{ + set_pil(0); /* enable all interrupts */ +} + +int disable_interrupts(void) +{ + return intLock(); +} + +int interrupt_init(void) +{ + int ret; + + /* call cpu specific function from $(CPU)/interrupts.c */ + ret = interrupt_init_cpu(); + + /* enable global interrupts */ + enable_interrupts(); + + return ret; +} + +/* timer interrupt/overflow counter */ +static volatile ulong timestamp = 0; + +/* regs can not be used here! regs is actually the pointer given in + * irq_install_handler + */ +void timer_interrupt(struct pt_regs *regs) +{ + /* call cpu specific function from $(CPU)/interrupts.c */ + timer_interrupt_cpu((void *)regs); + + timestamp++; +} + +void reset_timer(void) +{ + timestamp = 0; +} + +ulong get_timer(ulong base) +{ + return (timestamp - base); +} + +void set_timer(ulong t) +{ + timestamp = t; +} + +void timer_interrupt_init(void) +{ + int irq; + + reset_timer(); + + irq = timer_interrupt_init_cpu(); + + if (irq < 0) { + /* cpu specific code handled the interrupt registration it self */ + return; + } + /* register interrupt handler for timer */ + irq_install_handler(irq, (void (*)(void *))timer_interrupt, NULL); +} diff --git a/lib_sparc/time.c b/lib_sparc/time.c new file mode 100644 index 000000000..433f3eb5a --- /dev/null +++ b/lib_sparc/time.c @@ -0,0 +1,78 @@ +/* + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* Implemented by SPARC CPUs */ +extern void cpu_wait_ticks(unsigned long ticks); +extern unsigned long cpu_usec2ticks(unsigned long usec); +extern unsigned long cpu_ticks2usec(unsigned long ticks); + +/* ------------------------------------------------------------------------- */ + +void wait_ticks(unsigned long ticks) +{ + cpu_wait_ticks(ticks); +} + +/* + * This function is intended for SHORT delays only. + */ +unsigned long usec2ticks(unsigned long usec) +{ + return cpu_usec2ticks(usec); +} + +/* ------------------------------------------------------------------------- */ + +/* + * We implement the delay by converting the delay (the number of + * microseconds to wait) into a number of time base ticks; then we + * watch the time base until it has incremented by that amount. + */ +void udelay(unsigned long usec) +{ + ulong ticks = usec2ticks(usec); + + wait_ticks(ticks); +} + +/* ------------------------------------------------------------------------- */ + +unsigned long ticks2usec(unsigned long ticks) +{ + return cpu_ticks2usec(ticks); +} + +/* ------------------------------------------------------------------------- */ + +int init_timebase(void) +{ + + return (0); +} + +/* ------------------------------------------------------------------------- */ diff --git a/sparc_config.mk b/sparc_config.mk new file mode 100644 index 000000000..87f745f61 --- /dev/null +++ b/sparc_config.mk @@ -0,0 +1,24 @@ +# +# (C) Copyright 2007 +# Daniel Hellstrom, Gaisler Research, daniel@gaisler.com +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_CPPFLAGS += -DCONFIG_SPARC -D__sparc__ From 00ab32c85405a4fe65fd4128243086210fc90a21 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Wed, 26 Mar 2008 22:36:03 +0100 Subject: [PATCH 02/11] SPARC: added SPARC board information to the command bdinfo. Signed-off-by: Daniel Hellstrom --- common/cmd_bdinfo.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index bbb01921d..731c1d255 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -208,6 +208,45 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 0; } +#elif defined(CONFIG_SPARC) /* SPARC */ +int do_bdinfo(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + bd_t *bd = gd->bd; +#if defined(CONFIG_CMD_NET) + int i; +#endif + +#ifdef DEBUG + print_num("bd address ", (ulong) bd); +#endif + print_num("memstart ", bd->bi_memstart); + print_num("memsize ", bd->bi_memsize); + print_num("flashstart ", bd->bi_flashstart); + print_num("CFG_MONITOR_BASE ", CFG_MONITOR_BASE); + print_num("CFG_ENV_ADDR ", CFG_ENV_ADDR); + printf("CFG_RELOC_MONITOR_BASE = 0x%lx (%d)\n", CFG_RELOC_MONITOR_BASE, + CFG_MONITOR_LEN); + printf("CFG_MALLOC_BASE = 0x%lx (%d)\n", CFG_MALLOC_BASE, + CFG_MALLOC_LEN); + printf("CFG_INIT_SP_OFFSET = 0x%lx (%d)\n", CFG_INIT_SP_OFFSET, + CFG_STACK_SIZE); + printf("CFG_PROM_OFFSET = 0x%lx (%d)\n", CFG_PROM_OFFSET, + CFG_PROM_SIZE); + printf("CFG_GBL_DATA_OFFSET = 0x%lx (%d)\n", CFG_GBL_DATA_OFFSET, + CFG_GBL_DATA_SIZE); + +#if defined(CONFIG_CMD_NET) + puts("ethaddr ="); + for (i = 0; i < 6; ++i) { + printf("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]); + } + puts("\nIP addr = "); + print_IPaddr(bd->bi_ip_addr); +#endif + printf("\nbaudrate = %6ld bps\n", bd->bi_baudrate); + return 0; +} + #elif defined(CONFIG_M68K) /* M68K */ static void print_str(const char *, const char *); From bf3d8b31169546fcddb4737391e1893fb12d033a Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 28 Mar 2008 08:29:26 +0100 Subject: [PATCH 03/11] SPARC: added SPARC support for new uimage in common code. Signed-off-by: Daniel Hellstrom --- common/image.c | 2 +- include/image.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/common/image.c b/common/image.c index f04826a5c..ce49bb24e 100644 --- a/common/image.c +++ b/common/image.c @@ -1014,7 +1014,7 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, return 0; } -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) /** * boot_ramdisk_high - relocate init ramdisk * @lmb: pointer to lmb handle, will be used for memory mgmt diff --git a/include/image.h b/include/image.h index 36143e25a..c1a6cbb48 100644 --- a/include/image.h +++ b/include/image.h @@ -419,6 +419,8 @@ static inline int image_check_target_arch (image_header_t *hdr) if (!image_check_arch (hdr, IH_ARCH_PPC)) #elif defined(__sh__) if (!image_check_arch (hdr, IH_ARCH_SH)) +#elif defined(__sparc__) + if (!image_check_arch (hdr, IH_ARCH_SPARC)) #else # error Unknown CPU type #endif @@ -571,6 +573,8 @@ static inline int fit_image_check_target_arch (const void *fdt, int node) if (!fit_image_check_arch (fdt, node, IH_ARCH_PPC)) #elif defined(__sh__) if (!fit_image_check_arch (fdt, node, IH_ARCH_SH)) +#elif defined(__sparc__) + if (!fit_image_check_arch (fdt, node, IH_ARCH_SPARC)) #else # error Unknown CPU type #endif From 1e9a164e22976933002c5e4b0b79b09fcede9cd4 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Wed, 26 Mar 2008 22:51:29 +0100 Subject: [PATCH 04/11] SPARC: Added support for SPARC LEON3 SOC processor. Signed-off-by: Daniel Hellstrom --- Makefile | 3 + README | 1 + cpu/leon3/Makefile | 54 ++ cpu/leon3/ambapp.c | 339 +++++++ cpu/leon3/config.mk | 26 + cpu/leon3/cpu.c | 67 ++ cpu/leon3/cpu_init.c | 254 ++++++ cpu/leon3/interrupts.c | 219 +++++ cpu/leon3/prom.c | 1078 +++++++++++++++++++++++ cpu/leon3/serial.c | 139 +++ cpu/leon3/start.S | 616 +++++++++++++ cpu/leon3/usb_uhci.c | 1313 ++++++++++++++++++++++++++++ cpu/leon3/usb_uhci.h | 184 ++++ include/ambapp.h | 380 ++++++++ include/asm-sparc/arch-leon3/asi.h | 36 + include/asm-sparc/leon.h | 38 + include/asm-sparc/leon3.h | 37 + include/asm-sparc/processor.h | 9 +- 18 files changed, 4792 insertions(+), 1 deletion(-) create mode 100644 cpu/leon3/Makefile create mode 100644 cpu/leon3/ambapp.c create mode 100644 cpu/leon3/config.mk create mode 100644 cpu/leon3/cpu.c create mode 100644 cpu/leon3/cpu_init.c create mode 100644 cpu/leon3/interrupts.c create mode 100644 cpu/leon3/prom.c create mode 100644 cpu/leon3/serial.c create mode 100644 cpu/leon3/start.S create mode 100644 cpu/leon3/usb_uhci.c create mode 100644 cpu/leon3/usb_uhci.h create mode 100644 include/ambapp.h create mode 100644 include/asm-sparc/arch-leon3/asi.h create mode 100644 include/asm-sparc/leon.h create mode 100644 include/asm-sparc/leon3.h diff --git a/Makefile b/Makefile index 7219e7a31..bb8247cd1 100644 --- a/Makefile +++ b/Makefile @@ -2898,6 +2898,9 @@ r2dplus_config : unconfig #======================================================================== # SPARC #======================================================================== +######################################################################### +## LEON3 +######################################################################### ######################################################################### ######################################################################### diff --git a/README b/README index 9160306c4..dfb51f722 100644 --- a/README +++ b/README @@ -153,6 +153,7 @@ Directory Hierarchy: - at32ap Files specific to Atmel AVR32 AP CPUs - i386 Files specific to i386 CPUs - ixp Files specific to Intel XScale IXP CPUs + - leon3 Files specific to Gaisler LEON3 SPARC CPU - mcf52x2 Files specific to Freescale ColdFire MCF52x2 CPUs - mcf5227x Files specific to Freescale ColdFire MCF5227x CPUs - mcf532x Files specific to Freescale ColdFire MCF5329 CPUs diff --git a/cpu/leon3/Makefile b/cpu/leon3/Makefile new file mode 100644 index 000000000..182543dd1 --- /dev/null +++ b/cpu/leon3/Makefile @@ -0,0 +1,54 @@ +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(CPU).a + +START = start.o +SOBJS = +COBJS = cpu_init.o serial.o cpu.o ambapp.o interrupts.o prom.o usb_uhci.o + +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +$(START): $(START:.o=.S) + $(CC) -D__ASSEMBLY__ $(DBGFLAGS) $(OPTFLAGS) -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE) \ + -I$(TOPDIR)/include -fno-builtin -ffreestanding -nostdinc -isystem $(gccincdir) -pipe \ + $(PLATFORM_CPPFLAGS) -Wall -Wstrict-prototypes \ + -I$(TOPDIR)/board -c -o $(START) $(START:.o=.S) + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/leon3/ambapp.c b/cpu/leon3/ambapp.c new file mode 100644 index 000000000..60ff1a2ae --- /dev/null +++ b/cpu/leon3/ambapp.c @@ -0,0 +1,339 @@ +/* Gaisler AMBA Plug&Play bus scanning. Functions + * ending on _nomem is inteded to be used only during + * initialization, only registers are used (no ram). + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +static int ambapp_apb_scan(unsigned int vendor, /* Plug&Play Vendor ID */ + unsigned int driver, /* Plug&Play Device ID */ + ambapp_apbdev * dev, /* Result(s) is placed here */ + int index, /* Index of device to start copying Plug&Play + * info into dev + */ + int max_cnt /* Maximal count that dev can hold, if dev + * is NULL function will stop scanning after + * max_cnt devices are found. + */ + ) +{ + int i, cnt = 0; + unsigned int apbmst_base; + ambapp_ahbdev apbmst; + apbctrl_pp_dev *apb; + + if (max_cnt == 0) + return 0; + + /* Get AMBA APB Master */ + if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_APBMST, &apbmst) != 1) { + return 0; + } + + /* Get APB CTRL Plug&Play info area */ + apbmst_base = apbmst.address[0] & LEON3_IO_AREA; + apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA); + + for (i = 0; i < LEON3_APB_SLAVES; i++) { + if ((amba_vendor(apb->conf) == vendor) && + (amba_device(apb->conf) == driver) && ((index < 0) + || (index-- == 0))) { + /* Convert Plug&Play info into a more readable format */ + cnt++; + if (dev) { + dev->irq = amba_irq(apb->conf); + dev->ver = amba_ver(apb->conf); + dev->address = + (apbmst_base | + (((apb-> + bar & 0xfff00000) >> 12))) & (((apb-> + bar & + 0x0000fff0) + << 4) | + 0xfff00000); + dev++; + } + /* found max devices? */ + if (cnt >= max_cnt) + return cnt; + } + /* Get next Plug&Play entry */ + apb++; + } + return cnt; +} + +unsigned int ambapp_apb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */ + register unsigned int driver, /* Plug&Play Device ID */ + register int index) +{ + register int i; + register ahbctrl_pp_dev *apbmst; + register apbctrl_pp_dev *apb; + register unsigned int apbmst_base; + + /* APBMST is a AHB Slave */ + apbmst = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0); + if (!apbmst) + return 0; + + apbmst_base = amba_membar_start(apbmst->bars[0]); + if (amba_membar_type(apbmst->bars[0]) == AMBA_TYPE_AHBIO) + apbmst_base = AMBA_TYPE_AHBIO_ADDR(apbmst_base); + apbmst_base &= LEON3_IO_AREA; + + /* Find the vendor/driver device on the first APB bus */ + apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA); + + for (i = 0; i < LEON3_APB_SLAVES; i++) { + if ((amba_vendor(apb->conf) == vendor) && + (amba_device(apb->conf) == driver) && ((index < 0) + || (index-- == 0))) { + /* Convert Plug&Play info info a more readable format */ + return (apbmst_base | (((apb->bar & 0xfff00000) >> 12))) + & (((apb->bar & 0x0000fff0) << 4) | 0xfff00000); + } + /* Get next Plug&Play entry */ + apb++; + } + return 0; +} + +/****************************** APB SLAVES ******************************/ + +int ambapp_apb_count(unsigned int vendor, unsigned int driver) +{ + return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES); +} + +int ambapp_apb_first(unsigned int vendor, + unsigned int driver, ambapp_apbdev * dev) +{ + return ambapp_apb_scan(vendor, driver, dev, 0, 1); +} + +int ambapp_apb_next(unsigned int vendor, + unsigned int driver, ambapp_apbdev * dev, int index) +{ + return ambapp_apb_scan(vendor, driver, dev, index, 1); +} + +int ambapp_apbs_first(unsigned int vendor, + unsigned int driver, ambapp_apbdev * dev, int max_cnt) +{ + return ambapp_apb_scan(vendor, driver, dev, 0, max_cnt); +} + +enum { + AHB_SCAN_MASTER = 0, + AHB_SCAN_SLAVE = 1 +}; + +/* Scan AMBA Plug&Play bus for AMBA AHB Masters or AHB Slaves + * for a certain matching Vendor and Device ID. + * + * Return number of devices found. + * + * Compact edition... + */ +static int ambapp_ahb_scan(unsigned int vendor, /* Plug&Play Vendor ID */ + unsigned int driver, /* Plug&Play Device ID */ + ambapp_ahbdev * dev, /* Result(s) is placed here */ + int index, /* Index of device to start copying Plug&Play + * info into dev + */ + int max_cnt, /* Maximal count that dev can hold, if dev + * is NULL function will stop scanning after + * max_cnt devices are found. + */ + int type /* Selectes what type of devices to scan. + * 0=AHB Masters + * 1=AHB Slaves + */ + ) +{ + int i, j, cnt = 0, max_pp_devs; + unsigned int addr; + ahbctrl_info *info = (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA); + ahbctrl_pp_dev *ahb; + + if (max_cnt == 0) + return 0; + + if (type == 0) { + max_pp_devs = LEON3_AHB_MASTERS; + ahb = info->masters; + } else { + max_pp_devs = LEON3_AHB_SLAVES; + ahb = info->slaves; + } + + for (i = 0; i < max_pp_devs; i++) { + if ((amba_vendor(ahb->conf) == vendor) && + (amba_device(ahb->conf) == driver) && + ((index < 0) || (index-- == 0))) { + /* Convert Plug&Play info info a more readable format */ + cnt++; + if (dev) { + dev->irq = amba_irq(ahb->conf); + dev->ver = amba_ver(ahb->conf); + dev->userdef[0] = ahb->userdef[0]; + dev->userdef[1] = ahb->userdef[1]; + dev->userdef[2] = ahb->userdef[2]; + for (j = 0; j < 4; j++) { + addr = amba_membar_start(ahb->bars[j]); + if (amba_membar_type(ahb->bars[j]) == + AMBA_TYPE_AHBIO) + addr = + AMBA_TYPE_AHBIO_ADDR(addr); + dev->address[j] = addr; + } + dev++; + } + /* found max devices? */ + if (cnt >= max_cnt) + return cnt; + } + /* Get next Plug&Play entry */ + ahb++; + } + return cnt; +} + +unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info) +{ + register unsigned int ret; + + if (!ahb) + return 0; + + switch (info) { + default: + info = 0; + case 0: + case 1: + case 2: + case 3: + /* Get Address from PnP Info */ + ret = amba_membar_start(ahb->bars[info]); + if (amba_membar_type(ahb->bars[info]) == AMBA_TYPE_AHBIO) + ret = AMBA_TYPE_AHBIO_ADDR(ret); + return ret; + } + return 0; + +} + +ahbctrl_pp_dev *ambapp_ahb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */ + register unsigned int driver, /* Plug&Play Device ID */ + register unsigned int opts, /* 1=slave, 0=master */ + register int index) +{ + register ahbctrl_pp_dev *ahb; + register ahbctrl_info *info = + (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA); + register int i; + register int max_pp_devs; + + if (opts == 0) { + max_pp_devs = LEON3_AHB_MASTERS; + ahb = info->masters; + } else { + max_pp_devs = LEON3_AHB_SLAVES; + ahb = info->slaves; + } + + for (i = 0; i < max_pp_devs; i++) { + if ((amba_vendor(ahb->conf) == vendor) && + (amba_device(ahb->conf) == driver) && + ((index < 0) || (index-- == 0))) { + /* Convert Plug&Play info info a more readable format */ + return ahb; + } + /* Get next Plug&Play entry */ + ahb++; + } + return 0; +} + +/****************************** AHB MASTERS ******************************/ +int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver) +{ + /* Get number of devices of this vendor&device ID */ + return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_MASTERS, + AHB_SCAN_MASTER); +} + +int ambapp_ahbmst_first(unsigned int vendor, unsigned int driver, + ambapp_ahbdev * dev) +{ + /* find first device of this */ + return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_MASTER); +} + +int ambapp_ahbmst_next(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev, int index) +{ + /* find first device of this */ + return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_MASTER); +} + +int ambapp_ahbmsts_first(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev, int max_cnt) +{ + /* find first device of this */ + return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt, + AHB_SCAN_MASTER); +} + +/****************************** AHB SLAVES ******************************/ +int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver) +{ + /* Get number of devices of this vendor&device ID */ + return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_SLAVES, + AHB_SCAN_SLAVE); +} + +int ambapp_ahbslv_first(unsigned int vendor, unsigned int driver, + ambapp_ahbdev * dev) +{ + /* find first device of this */ + return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_SLAVE); +} + +int ambapp_ahbslv_next(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev, int index) +{ + /* find first device of this */ + return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_SLAVE); +} + +int ambapp_ahbslvs_first(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev, int max_cnt) +{ + /* find first device of this */ + return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt, AHB_SCAN_SLAVE); +} diff --git a/cpu/leon3/config.mk b/cpu/leon3/config.mk new file mode 100644 index 000000000..30b224a06 --- /dev/null +++ b/cpu/leon3/config.mk @@ -0,0 +1,26 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_RELFLAGS += -fPIC + +PLATFORM_CPPFLAGS += -DCONFIG_LEON diff --git a/cpu/leon3/cpu.c b/cpu/leon3/cpu.c new file mode 100644 index 000000000..306a21004 --- /dev/null +++ b/cpu/leon3/cpu.c @@ -0,0 +1,67 @@ +/* CPU specific code for the LEON3 CPU + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +extern void _reset_reloc(void); + +int checkcpu(void) +{ + /* check LEON version here */ + printf("CPU: LEON3\n"); + return 0; +} + +/* ------------------------------------------------------------------------- */ + +void cpu_reset(void) +{ + /* Interrupts off */ + disable_interrupts(); + + /* jump to restart in flash */ + _reset_reloc(); +} + +int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + cpu_reset(); + + return 1; + +} + +u64 flash_read64(void *addr) +{ + return __raw_readq(addr); +} + +/* ------------------------------------------------------------------------- */ diff --git a/cpu/leon3/cpu_init.c b/cpu/leon3/cpu_init.c new file mode 100644 index 000000000..4fe7d4b8d --- /dev/null +++ b/cpu/leon3/cpu_init.c @@ -0,0 +1,254 @@ +/* Initializes CPU and basic hardware such as memory + * controllers, IRQ controller and system timer 0. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include +#include + +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* reset CPU (jump to 0, without reset) */ +void start(void); + +/* find & initialize the memory controller */ +int init_memory_ctrl(void); + +ambapp_dev_irqmp *irqmp = NULL; +ambapp_dev_mctrl memctrl; +ambapp_dev_gptimer *gptimer = NULL; +unsigned int gptimer_irq = 0; +int leon3_snooping_avail = 0; + +struct { + gd_t gd_area; + bd_t bd; +} global_data; + +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers. + * + * Run from FLASH/PROM: + * - until memory controller is set up, only registers avaiable + * - no global variables available for writing + * - constants avaiable + */ + +void cpu_init_f(void) +{ + /* these varaiable must not be initialized */ + ambapp_dev_irqmp *irqmp; + ambapp_apbdev apbdev; + register unsigned int apbmst; + + /* find AMBA APB Master */ + apbmst = (unsigned int) + ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0); + if (!apbmst) { + /* + * no AHB/APB bridge, something is wrong + * ==> jump to start (or hang) + */ + while (1) ; + } + /* Init memory controller */ + if (init_memory_ctrl()) { + while (1) ; + } + + /**************************************************** + * From here we can use the main memory and the stack. + */ + + /* Find AMBA APB IRQMP Controller */ + if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev) != 1) { + /* no IRQ controller, something is wrong + * ==> jump to start (or hang) + */ + while (1) ; + } + irqmp = (ambapp_dev_irqmp *) apbdev.address; + + /* initialize the IRQMP */ + irqmp->ilevel = 0xf; /* all IRQ off */ + irqmp->iforce = 0; + irqmp->ipend = 0; + irqmp->iclear = 0xfffe; /* clear all old pending interrupts */ + irqmp->cpu_mask[0] = 0; /* mask all IRQs on CPU 0 */ + irqmp->cpu_force[0] = 0; /* no force IRQ on CPU 0 */ + + /* cache */ +} + +void cpu_init_f2(void) +{ + +} + +/* + * initialize higher level parts of CPU like time base and timers + */ +int cpu_init_r(void) +{ + ambapp_apbdev apbdev; + + /* + * Find AMBA APB IRQMP Controller, + * When we come so far we know there is a IRQMP available + */ + ambapp_apb_first(VENDOR_GAISLER, GAISLER_IRQMP, &apbdev); + irqmp = (ambapp_dev_irqmp *) apbdev.address; + + /* timer */ + if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_GPTIMER, &apbdev) != 1) { + printf("cpu_init_r: gptimer not found!\n"); + return 1; + } + gptimer = (ambapp_dev_gptimer *) apbdev.address; + gptimer_irq = apbdev.irq; + + /* initialize prescaler common to all timers to 1MHz */ + gptimer->scalar = gptimer->scalar_reload = + (((CONFIG_SYS_CLK_FREQ / 1000) + 500) / 1000) - 1; + + return (0); +} + +/* find & setup memory controller */ +int init_memory_ctrl() +{ + register ambapp_dev_mctrl *mctrl; + register ambapp_dev_sdctrl *sdctrl; + register ambapp_dev_ddrspa *ddrspa; + register ambapp_dev_ddr2spa *ddr2spa; + register ahbctrl_pp_dev *ahb; + register unsigned int base; + register int not_found_mctrl = -1; + + /* find ESA Memory controller */ + base = ambapp_apb_next_nomem(VENDOR_ESA, ESA_MCTRL, 0); + if (base) { + mctrl = (ambapp_dev_mctrl *) base; + + /* config MCTRL memory controller */ + mctrl->mcfg1 = CFG_GRLIB_MEMCFG1 | (mctrl->mcfg1 & 0x300); + mctrl->mcfg2 = CFG_GRLIB_MEMCFG2; + mctrl->mcfg3 = CFG_GRLIB_MEMCFG3; + not_found_mctrl = 0; + } + + /* find Gaisler Fault Tolerant Memory controller */ + base = ambapp_apb_next_nomem(VENDOR_GAISLER, GAISLER_FTMCTRL, 0); + if (base) { + mctrl = (ambapp_dev_mctrl *) base; + + /* config MCTRL memory controller */ + mctrl->mcfg1 = CFG_GRLIB_FT_MEMCFG1 | (mctrl->mcfg1 & 0x300); + mctrl->mcfg2 = CFG_GRLIB_FT_MEMCFG2; + mctrl->mcfg3 = CFG_GRLIB_FT_MEMCFG3; + not_found_mctrl = 0; + } + + /* find SDRAM controller */ + base = ambapp_apb_next_nomem(VENDOR_GAISLER, GAISLER_SDCTRL, 0); + if (base) { + sdctrl = (ambapp_dev_sdctrl *) base; + + /* config memory controller */ + sdctrl->sdcfg = CFG_GRLIB_SDRAM; + not_found_mctrl = 0; + } + + ahb = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_DDR2SPA, 1, 0); + if (ahb) { + ddr2spa = (ambapp_dev_ddr2spa *) ambapp_ahb_get_info(ahb, 1); + + /* Config DDR2 memory controller */ + ddr2spa->cfg1 = CFG_GRLIB_DDR2_CFG1; + ddr2spa->cfg3 = CFG_GRLIB_DDR2_CFG3; + not_found_mctrl = 0; + } + + ahb = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_DDRSPA, 1, 0); + if (ahb) { + ddrspa = (ambapp_dev_ddrspa *) ambapp_ahb_get_info(ahb, 1); + + /* Config DDR memory controller */ + ddrspa->ctrl = CFG_GRLIB_DDR_CFG; + not_found_mctrl = 0; + } + + /* failed to find any memory controller */ + return not_found_mctrl; +} + +/* Uses Timer 0 to get accurate + * pauses. Max 2 raised to 32 ticks + * + */ +void cpu_wait_ticks(unsigned long ticks) +{ + unsigned long start = get_timer(0); + while (get_timer(start) < ticks) ; +} + +/* initiate and setup timer0 interrupt to 1MHz + * Return irq number for timer int or a negative number for + * dealing with self + */ +int timer_interrupt_init_cpu(void) +{ + /* 1ms ticks */ + gptimer->e[0].val = 0; + gptimer->e[0].rld = 999; /* (((1000000 / 100) - 1)) */ + gptimer->e[0].ctrl = + (LEON3_GPTIMER_EN | + LEON3_GPTIMER_RL | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); + + return gptimer_irq; +} + +/* + * This function is intended for SHORT delays only. + */ +unsigned long cpu_usec2ticks(unsigned long usec) +{ + /* timer set to 1kHz ==> 1 clk tick = 1 msec */ + if (usec < 1000) + return 1; + return (usec / 1000); +} + +unsigned long cpu_ticks2usec(unsigned long ticks) +{ + /* 1tick = 1usec */ + return ticks * 1000; +} diff --git a/cpu/leon3/interrupts.c b/cpu/leon3/interrupts.c new file mode 100644 index 000000000..26926321a --- /dev/null +++ b/cpu/leon3/interrupts.c @@ -0,0 +1,219 @@ +/* + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * + * (C) Copyright 2006 + * Detlev Zundel, DENX Software Engineering, dzu@denx.de + * + * (C) Copyright -2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* 15 normal irqs and a non maskable interrupt */ +#define NR_IRQS 15 + +struct irq_action { + interrupt_handler_t *handler; + void *arg; + unsigned int count; +}; + +extern ambapp_dev_irqmp *irqmp; +extern ambapp_dev_gptimer *gptimer; + +static struct irq_action irq_handlers[NR_IRQS] = { {0}, }; +static int spurious_irq_cnt = 0; +static int spurious_irq = 0; + +static inline unsigned int irqmp_get_irqmask(unsigned int irq) +{ + if ((irq < 0) || (irq >= NR_IRQS)) { + return 0; + } else { + return (1 << irq); + } + +} + +static void leon3_ic_disable(unsigned int irq) +{ + unsigned int mask, pil; + if (!irqmp) + return; + + pil = intLock(); + + /* get mask of interrupt */ + mask = irqmp_get_irqmask(irq); + + /* set int level */ + irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) & (~mask); + + intUnlock(pil); +} + +static void leon3_ic_enable(unsigned int irq) +{ + unsigned int mask, pil; + if (!irqmp) + return; + + pil = intLock(); + + /* get mask of interrupt */ + mask = irqmp_get_irqmask(irq); + + /* set int level */ + irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) | mask; + + intUnlock(pil); + +} + +void handler_irq(int irq, struct pt_regs *regs) +{ + if (irq_handlers[irq].handler) { + if (((unsigned int)irq_handlers[irq].handler > CFG_RAM_END) || + ((unsigned int)irq_handlers[irq].handler < CFG_RAM_BASE) + ) { + printf("handler_irq: bad handler: %x, irq number %d\n", + (unsigned int)irq_handlers[irq].handler, irq); + return; + } + irq_handlers[irq].handler(irq_handlers[irq].arg); + irq_handlers[irq].count++; + } else { + spurious_irq_cnt++; + spurious_irq = irq; + } +} + +void leon3_force_int(int irq) +{ + if (!irqmp || (irq >= NR_IRQS) || (irq < 0)) + return; + printf("Forcing interrupt %d\n", irq); + + irqmp->iforce = SPARC_NOCACHE_READ(&irqmp->iforce) | (1 << irq); +} + +/****************************************************************************/ + +int interrupt_init_cpu(void) +{ + + return (0); +} + +/****************************************************************************/ + +/* Handle Timer 0 IRQ */ +void timer_interrupt_cpu(void *arg) +{ + gptimer->e[0].ctrl = (LEON3_GPTIMER_EN | + LEON3_GPTIMER_RL | + LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); + /* nothing to do here */ + return; +} + +/****************************************************************************/ + +/* + * Install and free a interrupt handler. + */ + +void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg) +{ + if (irq < 0 || irq >= NR_IRQS) { + printf("irq_install_handler: bad irq number %d\n", irq); + return; + } + + if (irq_handlers[irq].handler != NULL) + printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n", + (ulong) handler, (ulong) irq_handlers[irq].handler); + + if (((unsigned int)handler > CFG_RAM_END) || + ((unsigned int)handler < CFG_RAM_BASE) + ) { + printf("irq_install_handler: bad handler: %x, irq number %d\n", + (unsigned int)handler, irq); + return; + } + irq_handlers[irq].handler = handler; + irq_handlers[irq].arg = arg; + + /* enable irq on IRQMP hardware */ + leon3_ic_enable(irq); + +} + +void irq_free_handler(int irq) +{ + if (irq < 0 || irq >= NR_IRQS) { + printf("irq_free_handler: bad irq number %d\n", irq); + return; + } + + /* disable irq on IRQMP hardware */ + leon3_ic_disable(irq); + + irq_handlers[irq].handler = NULL; + irq_handlers[irq].arg = NULL; +} + +/****************************************************************************/ + +#if defined(CONFIG_CMD_IRQ) +void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[]) +{ + int irq; + unsigned int pil = get_pil(); + printf("PIL level: %u\n\r", pil); + printf("Spurious IRQ: %u, last unknown IRQ: %d\n", + spurious_irq_cnt, spurious_irq); + + puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n"); + + for (irq = 0; irq < NR_IRQS; irq++) { + if (irq_handlers[irq].handler != NULL) { + printf("%02d %08lx %08lx %ld\n", irq, + (unsigned int)irq_handlers[irq].handler, + (unsigned int)irq_handlers[irq].arg, + irq_handlers[irq].count); + } + } +} +#endif diff --git a/cpu/leon3/prom.c b/cpu/leon3/prom.c new file mode 100644 index 000000000..9fa2d040e --- /dev/null +++ b/cpu/leon3/prom.c @@ -0,0 +1,1078 @@ +/* prom.c - emulates a sparc v0 PROM for the linux kernel. + * + * Copyright (C) 2003 Konrad Eisele + * Copyright (C) 2004 Stefan Holst + * Copyright (C) 2007 Daniel Hellstrom + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +/* +#define PRINT_ROM_VEC +*/ +extern struct linux_romvec *kernel_arg_promvec; +extern ambapp_dev_apbuart *leon3_apbuart; + +#define PROM_PGT __attribute__ ((__section__ (".prom.pgt"))) +#define PROM_TEXT __attribute__ ((__section__ (".prom.text"))) +#define PROM_DATA __attribute__ ((__section__ (".prom.data"))) + +ambapp_dev_gptimer *gptimer; + +/* for __va */ +extern int __prom_start; +#define PAGE_OFFSET 0xf0000000 +#define phys_base CFG_SDRAM_BASE +#define PROM_OFFS 8192 +#define PROM_SIZE_MASK (PROM_OFFS-1) +#define __va(x) ( \ + (void *)( ((unsigned long)(x))-PROM_OFFS+ \ + (CFG_PROM_OFFSET-phys_base)+PAGE_OFFSET-TEXT_BASE ) \ + ) +#define __phy(x) ((void *)(((unsigned long)(x))-PROM_OFFS+CFG_PROM_OFFSET-TEXT_BASE)) + +struct property { + char *name; + char *value; + int length; +}; + +struct node { + int level; + struct property *properties; +}; + +static void leon_reboot(char *bcommand); +static void leon_halt(void); +static int leon_nbputchar(int c); +static int leon_nbgetchar(void); + +static int no_nextnode(int node); +static int no_child(int node); +static int no_proplen(int node, char *name); +static int no_getprop(int node, char *name, char *value); +static int no_setprop(int node, char *name, char *value, int len); +static char *no_nextprop(int node, char *name); + +static struct property PROM_TEXT *find_property(int node, char *name); +static int PROM_TEXT leon_strcmp(const char *s1, const char *s2); +static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n); +static void PROM_TEXT leon_reboot_physical(char *bcommand); + +void __inline__ leon_flush_cache_all(void) +{ + __asm__ __volatile__(" flush "); + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory"); +} + +void __inline__ leon_flush_tlb_all(void) +{ + leon_flush_cache_all(); + __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400), + "i"(ASI_MMUFLUSH):"memory"); +} + +typedef struct { + unsigned int ctx_table[256]; + unsigned int pgd_table[256]; +} sparc_srmmu_setup; + +sparc_srmmu_setup srmmu_tables PROM_PGT = { + {0}, + {0x1e, + 0x10001e, + 0x20001e, + 0x30001e, + 0x40001e, + 0x50001e, + 0x60001e, + 0x70001e, + 0x80001e, + 0x90001e, + 0xa0001e, + 0xb0001e, + 0xc0001e, + 0xd0001e, + 0xe0001e, + 0xf0001e, + 0x100001e, + 0x110001e, + 0x120001e, + 0x130001e, + 0x140001e, + 0x150001e, + 0x160001e, + 0x170001e, + 0x180001e, + 0x190001e, + 0x1a0001e, + 0x1b0001e, + 0x1c0001e, + 0x1d0001e, + 0x1e0001e, + 0x1f0001e, + 0x200001e, + 0x210001e, + 0x220001e, + 0x230001e, + 0x240001e, + 0x250001e, + 0x260001e, + 0x270001e, + 0x280001e, + 0x290001e, + 0x2a0001e, + 0x2b0001e, + 0x2c0001e, + 0x2d0001e, + 0x2e0001e, + 0x2f0001e, + 0x300001e, + 0x310001e, + 0x320001e, + 0x330001e, + 0x340001e, + 0x350001e, + 0x360001e, + 0x370001e, + 0x380001e, + 0x390001e, + 0x3a0001e, + 0x3b0001e, + 0x3c0001e, + 0x3d0001e, + 0x3e0001e, + 0x3f0001e, + 0x400001e, + 0x410001e, + 0x420001e, + 0x430001e, + 0x440001e, + 0x450001e, + 0x460001e, + 0x470001e, + 0x480001e, + 0x490001e, + 0x4a0001e, + 0x4b0001e, + 0x4c0001e, + 0x4d0001e, + 0x4e0001e, + 0x4f0001e, + 0x500001e, + 0x510001e, + 0x520001e, + 0x530001e, + 0x540001e, + 0x550001e, + 0x560001e, + 0x570001e, + 0x580001e, + 0x590001e, + 0x5a0001e, + 0x5b0001e, + 0x5c0001e, + 0x5d0001e, + 0x5e0001e, + 0x5f0001e, + 0x600001e, + 0x610001e, + 0x620001e, + 0x630001e, + 0x640001e, + 0x650001e, + 0x660001e, + 0x670001e, + 0x680001e, + 0x690001e, + 0x6a0001e, + 0x6b0001e, + 0x6c0001e, + 0x6d0001e, + 0x6e0001e, + 0x6f0001e, + 0x700001e, + 0x710001e, + 0x720001e, + 0x730001e, + 0x740001e, + 0x750001e, + 0x760001e, + 0x770001e, + 0x780001e, + 0x790001e, + 0x7a0001e, + 0x7b0001e, + 0x7c0001e, + 0x7d0001e, + 0x7e0001e, + 0x7f0001e, + 0x800001e, + 0x810001e, + 0x820001e, + 0x830001e, + 0x840001e, + 0x850001e, + 0x860001e, + 0x870001e, + 0x880001e, + 0x890001e, + 0x8a0001e, + 0x8b0001e, + 0x8c0001e, + 0x8d0001e, + 0x8e0001e, + 0x8f0001e, + 0x900001e, + 0x910001e, + 0x920001e, + 0x930001e, + 0x940001e, + 0x950001e, + 0x960001e, + 0x970001e, + 0x980001e, + 0x990001e, + 0x9a0001e, + 0x9b0001e, + 0x9c0001e, + 0x9d0001e, + 0x9e0001e, + 0x9f0001e, + 0xa00001e, + 0xa10001e, + 0xa20001e, + 0xa30001e, + 0xa40001e, + 0xa50001e, + 0xa60001e, + 0xa70001e, + 0xa80001e, + 0xa90001e, + 0xaa0001e, + 0xab0001e, + 0xac0001e, + 0xad0001e, + 0xae0001e, + 0xaf0001e, + 0xb00001e, + 0xb10001e, + 0xb20001e, + 0xb30001e, + 0xb40001e, + 0xb50001e, + 0xb60001e, + 0xb70001e, + 0xb80001e, + 0xb90001e, + 0xba0001e, + 0xbb0001e, + 0xbc0001e, + 0xbd0001e, + 0xbe0001e, + 0xbf0001e, + 0xc00001e, + 0xc10001e, + 0xc20001e, + 0xc30001e, + 0xc40001e, + 0xc50001e, + 0xc60001e, + 0xc70001e, + 0xc80001e, + 0xc90001e, + 0xca0001e, + 0xcb0001e, + 0xcc0001e, + 0xcd0001e, + 0xce0001e, + 0xcf0001e, + 0xd00001e, + 0xd10001e, + 0xd20001e, + 0xd30001e, + 0xd40001e, + 0xd50001e, + 0xd60001e, + 0xd70001e, + 0xd80001e, + 0xd90001e, + 0xda0001e, + 0xdb0001e, + 0xdc0001e, + 0xdd0001e, + 0xde0001e, + 0xdf0001e, + 0xe00001e, + 0xe10001e, + 0xe20001e, + 0xe30001e, + 0xe40001e, + 0xe50001e, + 0xe60001e, + 0xe70001e, + 0xe80001e, + 0xe90001e, + 0xea0001e, + 0xeb0001e, + 0xec0001e, + 0xed0001e, + 0xee0001e, + 0xef0001e, + 0x400001e /* default */ + } +}; + +/* a self contained prom info structure */ +struct leon_reloc_func { + struct property *(*find_property) (int node, char *name); + int (*strcmp) (char *s1, char *s2); + void *(*memcpy) (void *dest, const void *src, size_t n); + void (*reboot_physical) (char *cmd); + ambapp_dev_apbuart *leon3_apbuart; +}; + +struct leon_prom_info { + int freq_khz; + int leon_nctx; + int mids[32]; + int baudrates[2]; + struct leon_reloc_func reloc_funcs; + struct property root_properties[4]; + struct property cpu_properties[7]; +#undef CPUENTRY +#define CPUENTRY(idx) struct property cpu_properties##idx[4] + CPUENTRY(1); + CPUENTRY(2); + CPUENTRY(3); + CPUENTRY(4); + CPUENTRY(5); + CPUENTRY(6); + CPUENTRY(7); + CPUENTRY(8); + CPUENTRY(9); + CPUENTRY(10); + CPUENTRY(11); + CPUENTRY(12); + CPUENTRY(13); + CPUENTRY(14); + CPUENTRY(15); + CPUENTRY(16); + CPUENTRY(17); + CPUENTRY(18); + CPUENTRY(19); + CPUENTRY(20); + CPUENTRY(21); + CPUENTRY(22); + CPUENTRY(23); + CPUENTRY(24); + CPUENTRY(25); + CPUENTRY(26); + CPUENTRY(27); + CPUENTRY(28); + CPUENTRY(29); + CPUENTRY(30); + CPUENTRY(31); + struct idprom idprom; + struct linux_nodeops nodeops; + struct linux_mlist_v0 *totphys_p; + struct linux_mlist_v0 totphys; + struct linux_mlist_v0 *avail_p; + struct linux_mlist_v0 avail; + struct linux_mlist_v0 *prommap_p; + void (*synchook) (void); + struct linux_arguments_v0 *bootargs_p; + struct linux_arguments_v0 bootargs; + struct linux_romvec romvec; + struct node nodes[35]; + char s_device_type[12]; + char s_cpu[4]; + char s_mid[4]; + char s_idprom[7]; + char s_compatability[14]; + char s_leon2[6]; + char s_mmu_nctx[9]; + char s_frequency[16]; + char s_uart1_baud[11]; + char s_uart2_baud[11]; + char arg[256]; +}; + +/* static prom info */ +static struct leon_prom_info PROM_DATA spi = { + CONFIG_SYS_CLK_FREQ / 1000, + 256, + { +#undef CPUENTRY +#define CPUENTRY(idx) idx + CPUENTRY(0), + CPUENTRY(1), + CPUENTRY(2), + CPUENTRY(3), + CPUENTRY(4), + CPUENTRY(5), + CPUENTRY(6), + CPUENTRY(7), + CPUENTRY(8), + CPUENTRY(9), + CPUENTRY(10), + CPUENTRY(11), + CPUENTRY(12), + CPUENTRY(13), + CPUENTRY(14), + CPUENTRY(15), + CPUENTRY(16), + CPUENTRY(17), + CPUENTRY(18), + CPUENTRY(19), + CPUENTRY(20), + CPUENTRY(21), + CPUENTRY(22), + CPUENTRY(23), + CPUENTRY(24), + CPUENTRY(25), + CPUENTRY(26), + CPUENTRY(27), + CPUENTRY(28), + CPUENTRY(29), + CPUENTRY(30), + 31}, + {38400, 38400}, + { + __va(find_property), + __va(leon_strcmp), + __va(leon_memcpy), + __phy(leon_reboot_physical), + }, + { + {__va(spi.s_device_type), __va(spi.s_idprom), 4}, + {__va(spi.s_idprom), (char *)__va(&spi.idprom), sizeof(struct idprom)}, + {__va(spi.s_compatability), __va(spi.s_leon2), 5}, + {NULL, NULL, -1} + }, + { + {__va(spi.s_device_type), __va(spi.s_cpu), 4}, + {__va(spi.s_mid), __va(&spi.mids[0]), 4}, + {__va(spi.s_mmu_nctx), (char *)__va(&spi.leon_nctx), 4}, + {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, + {__va(spi.s_uart1_baud), (char *)__va(&spi.baudrates[0]), 4}, + {__va(spi.s_uart2_baud), (char *)__va(&spi.baudrates[1]), 4}, + {NULL, NULL, -1} + }, +#undef CPUENTRY +#define CPUENTRY(idx) \ + { /* cpu_properties */ \ + {__va(spi.s_device_type), __va(spi.s_cpu), 4}, \ + {__va(spi.s_mid), __va(&spi.mids[idx]), 4}, \ + {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, \ + {NULL, NULL, -1} \ + } + CPUENTRY(1), + CPUENTRY(2), + CPUENTRY(3), + CPUENTRY(4), + CPUENTRY(5), + CPUENTRY(6), + CPUENTRY(7), + CPUENTRY(8), + CPUENTRY(9), + CPUENTRY(10), + CPUENTRY(11), + CPUENTRY(12), + CPUENTRY(13), + CPUENTRY(14), + CPUENTRY(15), + CPUENTRY(16), + CPUENTRY(17), + CPUENTRY(18), + CPUENTRY(19), + CPUENTRY(20), + CPUENTRY(21), + CPUENTRY(22), + CPUENTRY(23), + CPUENTRY(24), + CPUENTRY(25), + CPUENTRY(26), + CPUENTRY(27), + CPUENTRY(28), + CPUENTRY(29), + CPUENTRY(30), + CPUENTRY(31), + { + 0x01, /* format */ + M_LEON2 | M_LEON2_SOC, /* machine type */ + {0, 0, 0, 0, 0, 0}, /* eth */ + 0, /* date */ + 0, /* sernum */ + 0, /* checksum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* reserved */ + }, + { + __va(no_nextnode), + __va(no_child), + __va(no_proplen), + __va(no_getprop), + __va(no_setprop), + __va(no_nextprop) + }, + __va(&spi.totphys), + { + NULL, + (char *)CFG_SDRAM_BASE, + 0, + }, + __va(&spi.avail), + { + NULL, + (char *)CFG_SDRAM_BASE, + 0, + }, + NULL, /* prommap_p */ + NULL, + __va(&spi.bootargs), + { + {NULL, __va(spi.arg), NULL /*... */ }, + /*... */ + }, + { + 0, + 0, /* sun4c v0 prom */ + 0, 0, + {__va(&spi.totphys_p), __va(&spi.prommap_p), __va(&spi.avail_p)}, + __va(&spi.nodeops), + NULL, {NULL /* ... */ }, + NULL, NULL, + NULL, NULL, /* pv_getchar, pv_putchar */ + __va(leon_nbgetchar), __va(leon_nbputchar), + NULL, + __va(leon_reboot), + NULL, + NULL, + NULL, + __va(leon_halt), + __va(&spi.synchook), + {NULL}, + __va(&spi.bootargs_p) + /*... */ + }, + { + {0, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ }, + {0, __va(spi.root_properties)}, + /* cpu 0, must be spi.nodes[2] see leon_prom_init() */ + {1, __va(spi.cpu_properties)}, + +#undef CPUENTRY +#define CPUENTRY(idx) \ + {1, __va(spi.cpu_properties##idx) } /* cpu */ + CPUENTRY(1), + CPUENTRY(2), + CPUENTRY(3), + CPUENTRY(4), + CPUENTRY(5), + CPUENTRY(6), + CPUENTRY(7), + CPUENTRY(8), + CPUENTRY(9), + CPUENTRY(10), + CPUENTRY(11), + CPUENTRY(12), + CPUENTRY(13), + CPUENTRY(14), + CPUENTRY(15), + CPUENTRY(16), + CPUENTRY(17), + CPUENTRY(18), + CPUENTRY(19), + CPUENTRY(20), + CPUENTRY(21), + CPUENTRY(22), + CPUENTRY(23), + CPUENTRY(24), + CPUENTRY(25), + CPUENTRY(26), + CPUENTRY(27), + CPUENTRY(28), + CPUENTRY(29), + CPUENTRY(30), + CPUENTRY(31), + {-1, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ } + }, + "device_type", + "cpu", + "mid", + "idprom", + "compatability", + "leon2", + "mmu-nctx", + "clock-frequency", + "uart1_baud", + "uart2_baud", + CONFIG_DEFAULT_KERNEL_COMMAND_LINE +}; + +/* from arch/sparc/kernel/setup.c */ +#define RAMDISK_LOAD_FLAG 0x4000 +extern unsigned short root_flags; +extern unsigned short root_dev; +extern unsigned short ram_flags; +extern unsigned int sparc_ramdisk_image; +extern unsigned int sparc_ramdisk_size; +extern int root_mountflags; + +extern char initrd_end, initrd_start; + +/* Reboot the CPU = jump to beginning of flash again. + * + * Make sure that all function are inlined here. + */ +static void PROM_TEXT leon_reboot(char *bcommand) +{ + register char *arg = bcommand; + void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd); + + /* get physical address */ + struct leon_prom_info *pspi = + (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + unsigned int *srmmu_ctx_table; + + /* Turn of Interrupts */ + set_pil(0xf); + + /* Set kernel's context, context zero */ + srmmu_set_context(0); + + /* Get physical address of the MMU shutdown routine */ + reboot_physical = (void *) + SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical); + + /* Now that we know the physical address of the function + * we can make the MMU allow jumping to it. + */ + srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr(); + + srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table); + + /* get physical address of kernel's context table (assume ptd) */ + srmmu_ctx_table = (unsigned int *) + (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4); + + /* enable access to physical address of MMU shutdown function */ + SPARC_BYPASS_WRITE(&srmmu_ctx_table + [((unsigned int)reboot_physical) >> 24], + (((unsigned int)reboot_physical & 0xff000000) >> 4) | + 0x1e); + + /* flush TLB cache */ + leon_flush_tlb_all(); + + /* flash instruction & data cache */ + sparc_icache_flush_all(); + sparc_dcache_flush_all(); + + /* jump to physical address function + * so that when the MMU is disabled + * we can continue to execute + */ + reboot_physical(arg); +} + +static void PROM_TEXT leon_reboot_physical(char *bcommand) +{ + void __attribute__ ((noreturn)) (*reset) (void); + + /* Turn off MMU */ + srmmu_set_mmureg(0); + + /* Hardcoded start address */ + reset = CFG_MONITOR_BASE; + + /* flush data cache */ + sparc_dcache_flush_all(); + + /* flush instruction cache */ + sparc_icache_flush_all(); + + /* Jump to start in Flash */ + reset(); +} + +static void PROM_TEXT leon_halt(void) +{ + while (1) ; +} + +/* get single char, don't care for blocking*/ +static int PROM_TEXT leon_nbgetchar(void) +{ + return -1; +} + +/* put single char, don't care for blocking*/ +static int PROM_TEXT leon_nbputchar(int c) +{ + ambapp_dev_apbuart *uart; + + /* get physical address */ + struct leon_prom_info *pspi = + (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + uart = (ambapp_dev_apbuart *) + SPARC_BYPASS_READ(&pspi->reloc_funcs.leon3_apbuart); + + /* no UART? */ + if (!uart) + return 0; + + /***** put char in buffer... *********** + * Make sure all functions are inline! * + ***************************************/ + + /* Wait for last character to go. */ + while (!(SPARC_BYPASS_READ(&uart->status) + & LEON_REG_UART_STATUS_THE)) ; + + /* Send data */ + SPARC_BYPASS_WRITE(&uart->data, c); + + /* Wait for data to be sent */ + while (!(SPARC_BYPASS_READ(&uart->status) + & LEON_REG_UART_STATUS_TSE)) ; + + return 0; +} + +/* node ops */ + +/*#define nodes ((struct node *)__va(&pspi->nodes))*/ +#define nodes ((struct node *)(pspi->nodes)) + +static int PROM_TEXT no_nextnode(int node) +{ + /* get physical address */ + struct leon_prom_info *pspi = + (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + if (nodes[node].level == nodes[node + 1].level) + return node + 1; + return -1; +} + +static int PROM_TEXT no_child(int node) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + if (nodes[node].level == nodes[node + 1].level - 1) + return node + 1; + return -1; +} + +static struct property PROM_TEXT *find_property(int node, char *name) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + struct property *prop = &nodes[node].properties[0]; + while (prop && prop->name) { + if (pspi->reloc_funcs.strcmp(prop->name, name) == 0) + return prop; + prop++; + } + return NULL; +} + +static int PROM_TEXT no_proplen(int node, char *name) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + struct property *prop = pspi->reloc_funcs.find_property(node, name); + if (prop) + return prop->length; + return -1; +} + +static int PROM_TEXT no_getprop(int node, char *name, char *value) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + struct property *prop = pspi->reloc_funcs.find_property(node, name); + if (prop) { + pspi->reloc_funcs.memcpy(value, prop->value, prop->length); + return 1; + } + return -1; +} + +static int PROM_TEXT no_setprop(int node, char *name, char *value, int len) +{ + return -1; +} + +static char PROM_TEXT *no_nextprop(int node, char *name) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + struct property *prop; + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + if (!name || !name[0]) + return nodes[node].properties[0].name; + + prop = pspi->reloc_funcs.find_property(node, name); + if (prop) + return prop[1].name; + return NULL; +} + +static int PROM_TEXT leon_strcmp(const char *s1, const char *s2) +{ + register char result; + + while (1) { + result = *s1 - *s2; + if (result || !*s1) + break; + s2++; + s1++; + } + + return result; +} + +static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n) +{ + char *dst = (char *)dest, *source = (char *)src; + + while (n--) { + *dst = *source; + dst++; + source++; + } + return dest; +} + +#define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp)) + +void leon_prom_init(struct leon_prom_info *pspi) +{ + unsigned long i; + unsigned char cksum, *ptr; + char *addr_str, *end; + unsigned long sp; + GETREGSP(sp); + + pspi->freq_khz = CONFIG_SYS_CLK_FREQ / 1000; + + /* Set Available main memory size */ + pspi->totphys.num_bytes = CFG_PROM_OFFSET - CFG_SDRAM_BASE; + pspi->avail.num_bytes = pspi->totphys.num_bytes; + + /* Set the pointer to the Console UART in romvec */ + pspi->reloc_funcs.leon3_apbuart = leon3_apbuart; + + { + int j = 1; +#ifdef CONFIG_SMP + ambapp_dev_irqmp *b; + b = (ambapp_dev_irqmp *) leon3_getapbbase(VENDOR_GAISLER, + GAISLER_IRQMP); + if (b) { + j = 1 + ((LEON3_BYPASS_LOAD_PA(&(b->mpstatus)) + >> LEON3_IRQMPSTATUS_CPUNR) & 0xf); + } +#endif +#undef nodes + pspi->nodes[2 + j].level = -1; + pspi->nodes[2 + j].properties = __va(spi.root_properties + 3); + } + + /* Set Ethernet MAC address from environment */ + if ((addr_str = getenv("ethaddr")) != NULL) { + for (i = 0; i < 6; i++) { + pspi->idprom.id_ethaddr[i] = addr_str ? + simple_strtoul(addr_str, &end, 16) : 0; + if (addr_str) { + addr_str = (*end) ? end + 1 : end; + } + } + } else { + /* HW Address not found in environment, + * Set default HW address + */ + pspi->idprom.id_ethaddr[0] = 0; + pspi->idprom.id_ethaddr[1] = 0; + pspi->idprom.id_ethaddr[2] = 0; + pspi->idprom.id_ethaddr[3] = 0; + pspi->idprom.id_ethaddr[4] = 0; + pspi->idprom.id_ethaddr[5] = 0; + } + + ptr = (unsigned char *)&pspi->idprom; + for (i = cksum = 0; i <= 0x0E; i++) + cksum ^= *ptr++; + pspi->idprom.id_cksum = cksum; +} + +static inline void set_cache(unsigned long regval) +{ + asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval), "i"(2):"memory"); +} + +extern unsigned short bss_start, bss_end; + +/* mark as section .img.main.text, to be referenced in linker script */ +int prom_init(void) +{ + struct leon_prom_info *pspi = (void *) + ((((unsigned int)&spi) & PROM_SIZE_MASK) + CFG_PROM_OFFSET); + + /* disable mmu */ + srmmu_set_mmureg(0x00000000); + __asm__ __volatile__("flush\n\t"); + + /* init prom info struct */ + leon_prom_init(pspi); + + kernel_arg_promvec = &pspi->romvec; +#ifdef PRINT_ROM_VEC + printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi->romvec)); +#endif + return 0; +} + +/* Copy current kernel boot argument to ROMvec */ +void prepare_bootargs(char *bootargs) +{ + struct leon_prom_info *pspi; + char *src, *dst; + int left; + + /* if no bootargs set, skip copying ==> default bootline */ + if (bootargs && (*bootargs != '\0')) { + pspi = (void *)((((unsigned int)&spi) & PROM_SIZE_MASK) + + CFG_PROM_OFFSET); + src = bootargs; + dst = &pspi->arg[0]; + left = 255; /* max len */ + while (*src && left > 0) { + *dst++ = *src++; + left--; + } + /* terminate kernel command line string */ + *dst = 0; + } +} + +void srmmu_init_cpu(unsigned int entry) +{ + sparc_srmmu_setup *psrmmu_tables = (void *) + ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) + + CFG_PROM_OFFSET); + + /* Make context 0 (kernel's context) point + * to our prepared memory mapping + */ +#define PTD 1 + psrmmu_tables->ctx_table[0] = + ((unsigned int)&psrmmu_tables->pgd_table[0x00]) >> 4 | PTD; + + /* Set virtual kernel address 0xf0000000 + * to SRAM/SDRAM address. + * Make it READ/WRITE/EXEC to SuperUser + */ +#define PTE 2 +#define ACC_SU_ALL 0x1c + psrmmu_tables->pgd_table[0xf0] = + (CFG_SDRAM_BASE >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf1] = + ((CFG_SDRAM_BASE + 0x1000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf2] = + ((CFG_SDRAM_BASE + 0x2000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf3] = + ((CFG_SDRAM_BASE + 0x3000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf4] = + ((CFG_SDRAM_BASE + 0x4000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf5] = + ((CFG_SDRAM_BASE + 0x5000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf6] = + ((CFG_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf7] = + ((CFG_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE; + + /* convert rom vec pointer to virtual address */ + kernel_arg_promvec = (struct linux_romvec *) + (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000); + + /* Set Context pointer to point to context table + * 256 contexts supported. + */ + srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables->ctx_table[0]); + + /* Set kernel's context, context zero */ + srmmu_set_context(0); + + /* Invalidate all Cache */ + __asm__ __volatile__("flush\n\t"); + + srmmu_set_mmureg(0x00000001); + leon_flush_tlb_all(); + leon_flush_cache_all(); +} diff --git a/cpu/leon3/serial.c b/cpu/leon3/serial.c new file mode 100644 index 000000000..27d5cd380 --- /dev/null +++ b/cpu/leon3/serial.c @@ -0,0 +1,139 @@ +/* GRLIB APBUART Serial controller driver + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Force cache miss each time a serial controller reg is read */ +#define CACHE_BYPASS 1 + +#ifdef CACHE_BYPASS +#define READ_BYTE(var) SPARC_NOCACHE_READ_BYTE((unsigned int)&(var)) +#define READ_HWORD(var) SPARC_NOCACHE_READ_HWORD((unsigned int)&(var)) +#define READ_WORD(var) SPARC_NOCACHE_READ((unsigned int)&(var)) +#define READ_DWORD(var) SPARC_NOCACHE_READ_DWORD((unsigned int)&(var)) +#endif + +ambapp_dev_apbuart *leon3_apbuart = NULL; + +int serial_init(void) +{ + ambapp_apbdev apbdev; + unsigned int tmp; + + /* find UART */ + if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_APBUART, &apbdev) == 1) { + + leon3_apbuart = (ambapp_dev_apbuart *) apbdev.address; + + /* found apbuart, let's init... + * + * Set scaler / baud rate + * + * Receiver & transmitter enable + */ + leon3_apbuart->scaler = CFG_GRLIB_APBUART_SCALER; + + /* Let bit 11 be unchanged (debug bit for GRMON) */ + tmp = READ_WORD(leon3_apbuart->ctrl); + + leon3_apbuart->ctrl = ((tmp & LEON_REG_UART_CTRL_DBG) | + LEON_REG_UART_CTRL_RE | + LEON_REG_UART_CTRL_TE); + + return 0; + } + return -1; /* didn't find hardware */ +} + +void serial_putc(const char c) +{ + if (c == '\n') + serial_putc_raw('\r'); + + serial_putc_raw(c); +} + +void serial_putc_raw(const char c) +{ + if (!leon3_apbuart) + return; + + /* Wait for last character to go. */ + while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_THE)) ; + + /* Send data */ + leon3_apbuart->data = c; + +#ifdef LEON_DEBUG + /* Wait for data to be sent */ + while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_TSE)) ; +#endif +} + +void serial_puts(const char *s) +{ + while (*s) { + serial_putc(*s++); + } +} + +int serial_getc(void) +{ + if (!leon3_apbuart) + return 0; + + /* Wait for a character to arrive. */ + while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_DR)) ; + + /* read data */ + return READ_WORD(leon3_apbuart->data); +} + +int serial_tstc(void) +{ + if (leon3_apbuart) + return (READ_WORD(leon3_apbuart->status) & + LEON_REG_UART_STATUS_DR); + return 0; +} + +/* set baud rate for uart */ +void serial_setbrg(void) +{ + /* update baud rate settings, read it from gd->baudrate */ + unsigned int scaler; + if (leon3_apbuart && (gd->baudrate > 0)) { + scaler = + (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) - + 5) / 10; + leon3_apbuart->scaler = scaler; + } + return; +} diff --git a/cpu/leon3/start.S b/cpu/leon3/start.S new file mode 100644 index 000000000..807f7e8da --- /dev/null +++ b/cpu/leon3/start.S @@ -0,0 +1,616 @@ +/* This is where the SPARC/LEON3 starts + * Copyright (C) 2007, + * Daniel Hellstrom, daniel@gaisler.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Entry for traps which jump to a programmer-specified trap handler. */ +#define TRAPR(H) \ + wr %g0, 0xfe0, %psr; \ + mov %g0, %tbr; \ + ba (H); \ + mov %g0, %wim; + +#define TRAP(H) \ + mov %psr, %l0; \ + ba (H); \ + nop; nop; + +#define TRAPI(ilevel) \ + mov ilevel, %l7; \ + mov %psr, %l0; \ + b _irq_entry; \ + mov %wim, %l3 + +/* Unexcpected trap will halt the processor by forcing it to error state */ +#undef BAD_TRAP +#define BAD_TRAP ta 0; nop; nop; nop; + +/* Software trap. Treat as BAD_TRAP for the time being... */ +#define SOFT_TRAP TRAP(_hwerr) + +#define PSR_INIT 0x1FC0 /* Disable traps, set s and ps */ +#define WIM_INIT 2 + +/* All traps low-level code here must end with this macro. */ +#define RESTORE_ALL b ret_trap_entry; clr %l6; + +#define WRITE_PAUSE nop;nop;nop + +WINDOWSIZE = (16 * 4) +ARGPUSHSIZE = (6 * 4) +ARGPUSH = (WINDOWSIZE + 4) +MINFRAME = (WINDOWSIZE + ARGPUSHSIZE + 4) + +/* Number of register windows */ +#ifndef CFG_SPARC_NWINDOWS +#error Must define number of SPARC register windows, default is 8 +#endif + +#define STACK_ALIGN 8 +#define SA(X) (((X)+(STACK_ALIGN-1)) & ~(STACK_ALIGN-1)) + + .section ".start", "ax" + .globl _start, start, _trap_table + .globl _irq_entry, nmi_trap + .globl _reset_reloc + +/* at address 0 + * Hardware traps + */ +start: +_start: +_trap_table: + TRAPR(_hardreset); ! 00 reset trap + BAD_TRAP; ! 01 instruction_access_exception + BAD_TRAP; ! 02 illegal_instruction + BAD_TRAP; ! 03 priveleged_instruction + BAD_TRAP; ! 04 fp_disabled + TRAP(_window_overflow); ! 05 window_overflow + TRAP(_window_underflow); ! 06 window_underflow + BAD_TRAP; ! 07 Memory Address Not Aligned + BAD_TRAP; ! 08 Floating Point Exception + BAD_TRAP; ! 09 Data Miss Exception + BAD_TRAP; ! 0a Tagged Instruction Ovrflw + BAD_TRAP; ! 0b Watchpoint Detected + BAD_TRAP; ! 0c + BAD_TRAP; ! 0d + BAD_TRAP; ! 0e + BAD_TRAP; ! 0f + BAD_TRAP; ! 10 + TRAPI(1); ! 11 IRQ level 1 + TRAPI(2); ! 12 IRQ level 2 + TRAPI(3); ! 13 IRQ level 3 + TRAPI(4); ! 14 IRQ level 4 + TRAPI(5); ! 15 IRQ level 5 + TRAPI(6); ! 16 IRQ level 6 + TRAPI(7); ! 17 IRQ level 7 + TRAPI(8); ! 18 IRQ level 8 + TRAPI(9); ! 19 IRQ level 9 + TRAPI(10); ! 1a IRQ level 10 + TRAPI(11); ! 1b IRQ level 11 + TRAPI(12); ! 1c IRQ level 12 + TRAPI(13); ! 1d IRQ level 13 + TRAPI(14); ! 1e IRQ level 14 + TRAP(_nmi_trap); ! 1f IRQ level 15 / + ! NMI (non maskable interrupt) + BAD_TRAP; ! 20 r_register_access_error + BAD_TRAP; ! 21 instruction access error + BAD_TRAP; ! 22 + BAD_TRAP; ! 23 + BAD_TRAP; ! 24 co-processor disabled + BAD_TRAP; ! 25 uniplemented FLUSH + BAD_TRAP; ! 26 + BAD_TRAP; ! 27 + BAD_TRAP; ! 28 co-processor exception + BAD_TRAP; ! 29 data access error + BAD_TRAP; ! 2a division by zero + BAD_TRAP; ! 2b data store error + BAD_TRAP; ! 2c data access MMU miss + BAD_TRAP; ! 2d + BAD_TRAP; ! 2e + BAD_TRAP; ! 2f + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30-33 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34-37 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38-3b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3c-3f + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40-43 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44-47 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48-4b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4c-4f + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50-53 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54-57 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58-5b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5c-5f + + /* implementaion dependent */ + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60-63 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64-67 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68-6b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6c-6f + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70-73 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74-77 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78-7b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7c-7f + + /* Software traps, not handled */ + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 80-83 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84-87 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 88-8b + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8c-8f + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90-93 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94-97 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98-9b + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9c-9f + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a0-a3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a4-a7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a8-ab + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! ac-af + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b0-b3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b4-b7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b8-bb + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! bc-bf + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c0-c3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c4-c7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c8-cb + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! cc-cf + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d0-d3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d4-d7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d8-db + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! dc-df + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e0-e3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e4-e7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e8-eb + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! ec-ef + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f0-f3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f4-f7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f8-fb + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! fc-ff +/* + * Version string + */ + + .data + .extern leon3_snooping_avail + .globl version_string +version_string: + .ascii U_BOOT_VERSION + .ascii " (", __DATE__, " - ", __TIME__, ")" + .ascii CONFIG_IDENT_STRING, "\0" + + .section ".text" + .align 4 + +_hardreset: +1000: + flush + + /* Enable I/D-Cache and Snooping */ + set 0x0081000f, %g2 + sta %g2, [%g0] 2 + + mov %g0, %y + clr %g1 + clr %g2 + clr %g3 + clr %g4 + clr %g5 + clr %g6 + clr %g7 + + mov %asr17, %g3 + and %g3, 0x1f, %g3 +clear_window: + mov %g0, %l0 + mov %g0, %l1 + mov %g0, %l2 + mov %g0, %l3 + mov %g0, %l4 + mov %g0, %l5 + mov %g0, %l6 + mov %g0, %l7 + mov %g0, %o0 + mov %g0, %o1 + mov %g0, %o2 + mov %g0, %o3 + mov %g0, %o4 + mov %g0, %o5 + mov %g0, %o6 + mov %g0, %o7 + subcc %g3, 1, %g3 + bge clear_window + save + +wininit: + set WIM_INIT, %g3 + mov %g3, %wim + +stackp: + set CFG_INIT_SP_OFFSET, %fp + andn %fp, 0x0f, %fp + sub %fp, 64, %sp + +cpu_init_unreloc: + call cpu_init_f + nop + +/* un relocated start address of monitor */ +#define TEXT_START _text + +/* un relocated end address of monitor */ +#define DATA_END __init_end + +reloc: + set TEXT_START,%g2 + set DATA_END,%g3 + set CFG_RELOC_MONITOR_BASE,%g4 +reloc_loop: + ldd [%g2],%l0 + ldd [%g2+8],%l2 + std %l0,[%g4] + std %l2,[%g4+8] + inc 16,%g2 + subcc %g3,%g2,%g0 + bne reloc_loop + inc 16,%g4 + + clr %l0 + clr %l1 + clr %l2 + clr %l3 + clr %g2 + +/* register g4 contain address to start + * This means that BSS must be directly after data and code segments + * + * g3 is length of bss = (__bss_end-__bss_start) + * + */ + +clr_bss: +/* clear bss area (the relocated) */ + set __bss_start,%g2 + set __bss_end,%g3 + sub %g3,%g2,%g3 + add %g3,%g4,%g3 + clr %g1 /* std %g0 uses g0 and g1 */ +/* clearing 16byte a time ==> linker script need to align to 16 byte offset */ +clr_bss_16: + std %g0,[%g4] + std %g0,[%g4+8] + inc 16,%g4 + cmp %g3,%g4 + bne clr_bss_16 + nop + +/* add offsets to GOT table */ +fixup_got: + set __got_start,%g4 + set __got_end,%g3 +/* + * new got offset = (old GOT-PTR (read with ld) - + * CFG_RELOC_MONITOR_BASE(from define) ) + + * Destination Address (from define) + */ + set CFG_RELOC_MONITOR_BASE,%g2 + set TEXT_START, %g1 + add %g4,%g2,%g4 + sub %g4,%g1,%g4 + add %g3,%g2,%g3 + sub %g3,%g1,%g3 + sub %g2,%g1,%g2 ! prepare register with (new base address) - + ! (old base address) +got_loop: + ld [%g4],%l0 ! load old GOT-PTR + add %l0,%g2,%l0 ! increase with (new base address) - + ! (old base) + st %l0,[%g4] + inc 4,%g4 + cmp %g3,%g4 + bne got_loop + nop + +prom_relocate: + set __prom_start, %g2 + set __prom_end, %g3 + set CFG_PROM_OFFSET, %g4 + +prom_relocate_loop: + ldd [%g2],%l0 + ldd [%g2+8],%l2 + std %l0,[%g4] + std %l2,[%g4+8] + inc 16,%g2 + subcc %g3,%g2,%g0 + bne prom_relocate_loop + inc 16,%g4 + +/* Trap table has been moved, lets tell CPU about + * the new trap table address + */ + + set CFG_RELOC_MONITOR_BASE, %g2 + wr %g0, %g2, %tbr + nop + nop + nop + +/* If CACHE snooping is available in hardware the + * variable leon3_snooping_avail will be set to + * 0x800000 else 0. + */ +snoop_detect: + sethi %hi(0x00800000), %o0 + lda [%g0] 2, %o1 + and %o0, %o1, %o0 + sethi %hi(leon3_snooping_avail+CFG_RELOC_MONITOR_BASE-TEXT_BASE), %o1 + st %o0, [%lo(leon3_snooping_avail+CFG_RELOC_MONITOR_BASE-TEXT_BASE)+%o1] + +/* call relocate*/ + nop +/* Call relocated init functions */ +jump: + set cpu_init_f2,%o1 + set CFG_RELOC_MONITOR_BASE,%o2 + add %o1,%o2,%o1 + sub %o1,%g1,%o1 + call %o1 + clr %o0 + + set board_init_f,%o1 + set CFG_RELOC_MONITOR_BASE,%o2 + add %o1,%o2,%o1 + sub %o1,%g1,%o1 + call %o1 + clr %o0 + +dead: ta 0 ! if call returns... + nop + +/* Interrupt handler caller, + * reg L7: interrupt number + * reg L0: psr after interrupt + * reg L1: PC + * reg L2: next PC + * reg L3: wim + */ +_irq_entry: + SAVE_ALL + + or %l0, PSR_PIL, %g2 + wr %g2, 0x0, %psr + WRITE_PAUSE + wr %g2, PSR_ET, %psr + WRITE_PAUSE + mov %l7, %o0 ! irq level + set handler_irq, %o1 + set (CFG_RELOC_MONITOR_BASE-TEXT_BASE), %o2 + add %o1, %o2, %o1 + call %o1 + add %sp, SF_REGS_SZ, %o1 ! pt_regs ptr + or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq + wr %g2, PSR_ET, %psr ! keep ET up + WRITE_PAUSE + + RESTORE_ALL + +!Window overflow trap handler. + .global _window_overflow + +_window_overflow: + + mov %wim, %l3 ! Calculate next WIM + mov %g1, %l7 + srl %l3, 1, %g1 + sll %l3, (CFG_SPARC_NWINDOWS-1) , %l4 + or %l4, %g1, %g1 + + save ! Get into window to be saved. + mov %g1, %wim + nop; + nop; + nop + st %l0, [%sp + 0]; + st %l1, [%sp + 4]; + st %l2, [%sp + 8]; + st %l3, [%sp + 12]; + st %l4, [%sp + 16]; + st %l5, [%sp + 20]; + st %l6, [%sp + 24]; + st %l7, [%sp + 28]; + st %i0, [%sp + 32]; + st %i1, [%sp + 36]; + st %i2, [%sp + 40]; + st %i3, [%sp + 44]; + st %i4, [%sp + 48]; + st %i5, [%sp + 52]; + st %i6, [%sp + 56]; + st %i7, [%sp + 60]; + restore ! Go back to trap window. + mov %l7, %g1 + jmp %l1 ! Re-execute save. + rett %l2 + +/* Window underflow trap handler. */ + + .global _window_underflow + +_window_underflow: + + mov %wim, %l3 ! Calculate next WIM + sll %l3, 1, %l4 + srl %l3, (CFG_SPARC_NWINDOWS-1), %l5 + or %l5, %l4, %l5 + mov %l5, %wim + nop; nop; nop + restore ! Two restores to get into the + restore ! window to restore + ld [%sp + 0], %l0; ! Restore window from the stack + ld [%sp + 4], %l1; + ld [%sp + 8], %l2; + ld [%sp + 12], %l3; + ld [%sp + 16], %l4; + ld [%sp + 20], %l5; + ld [%sp + 24], %l6; + ld [%sp + 28], %l7; + ld [%sp + 32], %i0; + ld [%sp + 36], %i1; + ld [%sp + 40], %i2; + ld [%sp + 44], %i3; + ld [%sp + 48], %i4; + ld [%sp + 52], %i5; + ld [%sp + 56], %i6; + ld [%sp + 60], %i7; + save ! Get back to the trap window. + save + jmp %l1 ! Re-execute restore. + rett %l2 + + retl + +_nmi_trap: + nop + jmp %l1 + rett %l2 + +_hwerr: + ta 0 + nop + nop + b _hwerr ! loop infinite + nop + +/* Registers to not touch at all. */ +#define t_psr l0 /* Set by caller */ +#define t_pc l1 /* Set by caller */ +#define t_npc l2 /* Set by caller */ +#define t_wim l3 /* Set by caller */ +#define t_twinmask l4 /* Set at beginning of this entry routine. */ +#define t_kstack l5 /* Set right before pt_regs frame is built */ +#define t_retpc l6 /* If you change this, change winmacro.h header file */ +#define t_systable l7 /* Never touch this, could be the syscall table ptr. */ +#define curptr g6 /* Set after pt_regs frame is built */ + +trap_setup: +/* build a pt_regs trap frame. */ + sub %fp, (SF_REGS_SZ + PT_REGS_SZ), %t_kstack + PT_STORE_ALL(t_kstack, t_psr, t_pc, t_npc, g2) + + /* See if we are in the trap window. */ + mov 1, %t_twinmask + sll %t_twinmask, %t_psr, %t_twinmask ! t_twinmask = (1 << psr) + andcc %t_twinmask, %t_wim, %g0 + beq 1f ! in trap window, clean up + nop + + /*------------------------------------------------- + * Spill , adjust %wim and go. + */ + srl %t_wim, 0x1, %g2 ! begin computation of new %wim + + set (CFG_SPARC_NWINDOWS-1), %g3 !NWINDOWS-1 + + sll %t_wim, %g3, %t_wim ! NWINDOWS-1 + or %t_wim, %g2, %g2 + and %g2, 0xff, %g2 + + save %g0, %g0, %g0 ! get in window to be saved + + /* Set new %wim value */ + wr %g2, 0x0, %wim + + /* Save the kernel window onto the corresponding stack. */ + RW_STORE(sp) + + restore %g0, %g0, %g0 + /*-------------------------------------------------*/ + +1: + /* Trap from kernel with a window available. + * Just do it... + */ + jmpl %t_retpc + 0x8, %g0 ! return to caller + mov %t_kstack, %sp ! jump onto new stack + +#define twin_tmp1 l4 +#define glob_tmp g4 +#define curptr g6 +ret_trap_entry: + wr %t_psr, 0x0, %psr ! enable nesting again, clear ET + + /* Will the rett land us in the invalid window? */ + mov 2, %g1 + sll %g1, %t_psr, %g1 + + set CFG_SPARC_NWINDOWS, %g2 !NWINDOWS + + srl %g1, %g2, %g2 + or %g1, %g2, %g1 + rd %wim, %g2 + andcc %g2, %g1, %g0 + be 1f ! Nope, just return from the trap + sll %g2, 0x1, %g1 + + /* We have to grab a window before returning. */ + set (CFG_SPARC_NWINDOWS-1), %g3 !NWINDOWS-1 + + srl %g2, %g3, %g2 + or %g1, %g2, %g1 + and %g1, 0xff, %g1 + + wr %g1, 0x0, %wim + + /* Grrr, make sure we load from the right %sp... */ + PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1) + + restore %g0, %g0, %g0 + RW_LOAD(sp) + b 2f + save %g0, %g0, %g0 + + /* Reload the entire frame in case this is from a + * kernel system call or whatever... + */ +1: + PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1) +2: + wr %t_psr, 0x0, %psr + nop; + nop; + nop + + jmp %t_pc + rett %t_npc + +/* This is called from relocated C-code. + * It resets the system by jumping to _start + */ +_reset_reloc: + set start, %l0 + call %l0 + nop diff --git a/cpu/leon3/usb_uhci.c b/cpu/leon3/usb_uhci.c new file mode 100644 index 000000000..7910bebe1 --- /dev/null +++ b/cpu/leon3/usb_uhci.c @@ -0,0 +1,1313 @@ +/* + * Part of this code has been derived from linux: + * Universal Host Controller Interface driver for USB (take II). + * + * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar) + * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) + * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) + * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) + * (c) 2000 Yggdrasil Computing, Inc. (port of new PCI interface support + * from usb-ohci.c by Adam Richter, adam@yggdrasil.com). + * (C) 2000 David Brownell, david-b@pacbell.net (usb-ohci.c) + * + * HW-initalization based on material of + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Randy Dunlap + * (C) Copyright 1999 Gregory P. Smith + * + * + * Adapted for U-Boot: + * (C) Copyright 2001 Denis Peter, MPL AG Switzerland + * (C) Copyright 2008, Daniel Hellström, daniel@gaisler.com + * Added AMBA Plug&Play detection of GRUSB, modified interrupt handler. + * Added cache flushes where needed. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + */ + +/********************************************************************** + * How it works: + * ------------- + * The framelist / Transfer descriptor / Queue Heads are similar like + * in the linux usb_uhci.c. + * + * During initialization, the following skeleton is allocated in init_skel: + * + * framespecific | common chain + * + * framelist[] + * [ 0 ]-----> TD ---------\ + * [ 1 ]-----> TD ----------> TD ------> QH -------> QH -------> QH ---> NULL + * ... TD ---------/ + * [1023]-----> TD --------/ + * + * ^^ ^^ ^^ ^^ ^^ + * 7 TDs for 1 TD for Start of Start of End Chain + * INT (2-128ms) 1ms-INT CTRL Chain BULK Chain + * + * + * Since this is a bootloader, the isochronous transfer descriptor have been removed. + * + * Interrupt Transfers. + * -------------------- + * For Interupt transfers USB_MAX_TEMP_INT_TD Transfer descriptor are available. They + * will be inserted after the appropriate (depending the interval setting) skeleton TD. + * If an interrupt has been detected the dev->irqhandler is called. The status and number + * of transfered bytes is stored in dev->irq_status resp. dev->irq_act_len. If the + * dev->irqhandler returns 0, the interrupt TD is removed and disabled. If an 1 is returned, + * the interrupt TD will be reactivated. + * + * Control Transfers + * ----------------- + * Control Transfers are issued by filling the tmp_td with the appropriate data and connect + * them to the qh_cntrl queue header. Before other control/bulk transfers can be issued, + * the programm has to wait for completion. This does not allows asynchronous data transfer. + * + * Bulk Transfers + * -------------- + * Bulk Transfers are issued by filling the tmp_td with the appropriate data and connect + * them to the qh_bulk queue header. Before other control/bulk transfers can be issued, + * the programm has to wait for completion. This does not allows asynchronous data transfer. + * + * + */ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_UHCI + +#include +#include "usb_uhci.h" + +#define USB_MAX_TEMP_TD 128 /* number of temporary TDs for bulk and control transfers */ +#define USB_MAX_TEMP_INT_TD 32 /* number of temporary TDs for Interrupt transfers */ + +extern int leon3_snooping_avail; +/* +#define out16r(address,data) (*(unsigned short *)(address) = \ + (unsigned short)( \ + (((unsigned short)(data)&0xff)<<8) | \ + (((unsigned short)(data)&0xff00)>>8) \ + )) + */ +#define out16r(address,data) _out16r((unsigned int)(address), (unsigned short)(data)) +void _out16r(unsigned int address, unsigned short data) +{ + unsigned short val = (unsigned short)((((unsigned short)(data) & 0xff) + << 8) | (((unsigned short)(data) + & 0xff00) >> 8)); +#ifdef UHCI_DEBUG_REGS + printf("out16r(0x%lx,0x%04x = 0x%04x)\n", address, val, data); +#endif + *(unsigned short *)(address) = val; +} + +#define out32r(address,data) _out32r((unsigned int)(address), (unsigned int)(data)) +void _out32r(unsigned int address, unsigned int data) +{ + unsigned int val = (unsigned int)((((unsigned int)(data) & 0x000000ff) + << 24) | (((unsigned int)(data) & + 0x0000ff00) << 8) | + (((unsigned int)(data) & 0x00ff0000) + >> 8) | (((unsigned int)(data) & + 0xff000000) >> 24)); +#ifdef UHCI_DEBUG_REGS + printf("out32r(0x%lx,0x%lx = 0x%lx)\n", address, val, data); +#endif + *(unsigned int *)address = val; +} + +#define in16r(address) _in16r((unsigned int)(address)) +unsigned short _in16r(unsigned int address) +{ + unsigned short val = sparc_load_reg_cachemiss_word(address); + val = ((val << 8) & 0xff00) | ((val >> 8) & 0xff); +#ifdef UHCI_DEBUG_REGS + printf("in16r(0x%lx): 0x%04x\n", address, val); +#endif + return val; +} + +#define in32r(address) _in32r((unsigned int)(address)) +unsigned int _in32r(unsigned int address) +{ + unsigned int val = sparc_load_reg_cachemiss(address); + val = + ((val << 24) & 0xff000000) | ((val << 8) & 0xff0000) | ((val >> 8) & + 0xff00) | + ((val >> 24) & 0xff); +#ifdef UHCI_DEBUG_REGS + printf("in32r(0x%lx): 0x%08x\n", address, val); +#endif + return val; +} + +#define READ32(address) sparc_load_reg_cachemiss((unsigned int)(address)) + +/*#define USB_UHCI_DEBUG*/ +#undef USB_UHCI_DEBUG + +void usb_show_td(int max); +#ifdef USB_UHCI_DEBUG +void grusb_show_regs(void); +#define USB_UHCI_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define USB_UHCI_PRINTF(fmt,args...) +#endif + +static int grusb_irq = -1; /* irq vector, if -1 uhci is stopped / reseted */ +unsigned int usb_base_addr; /* base address */ + +static uhci_td_t td_int[8] __attribute__ ((aligned(16))); /* Interrupt Transfer descriptors */ +static uhci_qh_t qh_cntrl __attribute__ ((aligned(16))); /* control Queue Head */ +static uhci_qh_t qh_bulk __attribute__ ((aligned(16))); /* bulk Queue Head */ +static uhci_qh_t qh_end __attribute__ ((aligned(16))); /* end Queue Head */ +static uhci_td_t td_last __attribute__ ((aligned(16))); /* last TD (linked with end chain) */ + +/* temporary tds */ +static uhci_td_t tmp_td[USB_MAX_TEMP_TD] __attribute__ ((aligned(16))); /* temporary bulk/control td's */ +static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD] __attribute__ ((aligned(16))); /* temporary interrupt td's */ + +static unsigned long framelist[1024] __attribute__ ((aligned(0x1000))); /* frame list */ + +static struct virt_root_hub rh; /* struct for root hub */ + +/********************************************************************** + * some forward decleration + */ +int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup); + +/* fill a td with the approproiate data. Link, status, info and buffer + * are used by the USB controller itselfes, dev is used to identify the + * "connected" device + */ +void usb_fill_td(uhci_td_t * td, unsigned long link, unsigned long status, + unsigned long info, unsigned long buffer, unsigned long dev) +{ + td->link = swap_32(link); + td->status = swap_32(status); + if ((info & UHCI_PID) == 0) + info |= USB_PID_OUT; + td->info = swap_32(info); + td->buffer = swap_32(buffer); + td->dev_ptr = dev; +} + +/* fill a qh with the approproiate data. Head and element are used by the USB controller + * itselfes. As soon as a valid dev_ptr is filled, a td chain is connected to the qh. + * Please note, that after completion of the td chain, the entry element is removed / + * marked invalid by the USB controller. + */ +void usb_fill_qh(uhci_qh_t * qh, unsigned long head, unsigned long element) +{ + qh->head = swap_32(head); + qh->element = swap_32(element); + qh->dev_ptr = 0L; +} + +/* get the status of a td->status + */ +unsigned long usb_uhci_td_stat(unsigned long status) +{ + unsigned long result = 0; + result |= (status & TD_CTRL_NAK) ? USB_ST_NAK_REC : 0; + result |= (status & TD_CTRL_STALLED) ? USB_ST_STALLED : 0; + result |= (status & TD_CTRL_DBUFERR) ? USB_ST_BUF_ERR : 0; + result |= (status & TD_CTRL_BABBLE) ? USB_ST_BABBLE_DET : 0; + result |= (status & TD_CTRL_CRCTIMEO) ? USB_ST_CRC_ERR : 0; + result |= (status & TD_CTRL_BITSTUFF) ? USB_ST_BIT_ERR : 0; + result |= (status & TD_CTRL_ACTIVE) ? USB_ST_NOT_PROC : 0; + return result; +} + +/* get the status and the transfered len of a td chain. + * called from the completion handler + */ +int usb_get_td_status(uhci_td_t * td, struct usb_device *dev) +{ + unsigned long temp, info; + unsigned long stat; + uhci_td_t *mytd = td; + + if (dev->devnum == rh.devnum) + return 0; + dev->act_len = 0; + stat = 0; + do { + temp = swap_32((unsigned long)READ32(&mytd->status)); + stat = usb_uhci_td_stat(temp); + info = swap_32((unsigned long)READ32(&mytd->info)); + if (((info & 0xff) != USB_PID_SETUP) && (((info >> 21) & 0x7ff) != 0x7ff) && (temp & 0x7FF) != 0x7ff) { /* if not setup and not null data pack */ + dev->act_len += (temp & 0x7FF) + 1; /* the transfered len is act_len + 1 */ + } + if (stat) { /* status no ok */ + dev->status = stat; + return -1; + } + temp = swap_32((unsigned long)READ32(&mytd->link)); + mytd = (uhci_td_t *) (temp & 0xfffffff0); + } while ((temp & 0x1) == 0); /* process all TDs */ + dev->status = stat; + return 0; /* Ok */ +} + +/*------------------------------------------------------------------- + * LOW LEVEL STUFF + * assembles QHs und TDs for control, bulk and iso + *-------------------------------------------------------------------*/ +int dummy(void) +{ + USB_UHCI_PRINTF("DUMMY\n"); + return 0; +} + +/* Submits a control message. That is a Setup, Data and Status transfer. + * Routine does not wait for completion. + */ +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup) +{ + unsigned long destination, status; + int maxsze = usb_maxpacket(dev, pipe); + unsigned long dataptr; + int len; + int pktsze; + int i = 0; + + if (!maxsze) { + USB_UHCI_PRINTF + ("uhci_submit_control_urb: pipesize for pipe %lx is zero\n", + pipe); + return -1; + } + if (((pipe >> 8) & 0x7f) == rh.devnum) { + /* this is the root hub -> redirect it */ + return uhci_submit_rh_msg(dev, pipe, buffer, transfer_len, + setup); + } + USB_UHCI_PRINTF("uhci_submit_control start len %x, maxsize %x\n", + transfer_len, maxsze); + /* The "pipe" thing contains the destination in bits 8--18 */ + destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; /* Setup stage */ + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27); + /* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD); */ + /* Build the TD for the control request, try forever, 8 bytes of data */ + usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, destination | (7 << 21), + (unsigned long)setup, (unsigned long)dev); +#ifdef DEBUG_EXTRA + { + char *sp = (char *)setup; + printf("SETUP to pipe %lx: %x %x %x %x %x %x %x %x\n", pipe, + sp[0], sp[1], sp[2], sp[3], sp[4], sp[5], sp[6], sp[7]); + } +#endif + dataptr = (unsigned long)buffer; + len = transfer_len; + + /* If direction is "send", change the frame from SETUP (0x2D) + to OUT (0xE1). Else change it from SETUP to IN (0x69). */ + destination = + (pipe & PIPE_DEVEP_MASK) | ((pipe & USB_DIR_IN) == + 0 ? USB_PID_OUT : USB_PID_IN); + while (len > 0) { + /* data stage */ + pktsze = len; + i++; + if (pktsze > maxsze) + pktsze = maxsze; + destination ^= 1 << TD_TOKEN_TOGGLE; /* toggle DATA0/1 */ + usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, destination | ((pktsze - 1) << 21), dataptr, (unsigned long)dev); /* Status, pktsze bytes of data */ + tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]); + + dataptr += pktsze; + len -= pktsze; + } + + /* Build the final TD for control status */ + /* It's only IN if the pipe is out AND we aren't expecting data */ + + destination &= ~UHCI_PID; + if (((pipe & USB_DIR_IN) == 0) || (transfer_len == 0)) + destination |= USB_PID_IN; + else + destination |= USB_PID_OUT; + destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ + i++; + status &= ~TD_CTRL_SPD; + /* no limit on errors on final packet , 0 bytes of data */ + usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status | TD_CTRL_IOC, + destination | (UHCI_NULL_DATA_SIZE << 21), 0, + (unsigned long)dev); + tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]); /* queue status td */ + /* usb_show_td(i+1); */ + USB_UHCI_PRINTF("uhci_submit_control end (%d tmp_tds used)\n", i); + /* first mark the control QH element terminated */ + qh_cntrl.element = 0xffffffffL; + /* set qh active */ + qh_cntrl.dev_ptr = (unsigned long)dev; + /* fill in tmp_td_chain */ + dummy(); + qh_cntrl.element = swap_32((unsigned long)&tmp_td[0]); + return 0; +} + +/*------------------------------------------------------------------- + * Prepare TDs for bulk transfers. + */ +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len) +{ + unsigned long destination, status, info; + unsigned long dataptr; + int maxsze = usb_maxpacket(dev, pipe); + int len; + int i = 0; + + if (transfer_len < 0) { + printf("Negative transfer length in submit_bulk\n"); + return -1; + } + if (!maxsze) + return -1; + /* The "pipe" thing contains the destination in bits 8--18. */ + destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe); + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27); + /* ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); */ + /* Build the TDs for the bulk request */ + len = transfer_len; + dataptr = (unsigned long)buffer; + do { + int pktsze = len; + if (pktsze > maxsze) + pktsze = maxsze; + /* pktsze bytes of data */ + info = + destination | (((pktsze - 1) & UHCI_NULL_DATA_SIZE) << 21) | + (usb_gettoggle + (dev, usb_pipeendpoint(pipe), + usb_pipeout(pipe)) << TD_TOKEN_TOGGLE); + + if ((len - pktsze) == 0) + status |= TD_CTRL_IOC; /* last one generates INT */ + + usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, info, dataptr, (unsigned long)dev); /* Status, pktsze bytes of data */ + if (i > 0) + tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]); + i++; + dataptr += pktsze; + len -= pktsze; + usb_dotoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); + } while (len > 0); + /* first mark the bulk QH element terminated */ + qh_bulk.element = 0xffffffffL; + /* set qh active */ + qh_bulk.dev_ptr = (unsigned long)dev; + /* fill in tmp_td_chain */ + qh_bulk.element = swap_32((unsigned long)&tmp_td[0]); + return 0; +} + +/* search a free interrupt td + */ +uhci_td_t *uhci_alloc_int_td(void) +{ + int i; + for (i = 0; i < USB_MAX_TEMP_INT_TD; i++) { + if (tmp_int_td[i].dev_ptr == 0) /* no device assigned -> free TD */ + return &tmp_int_td[i]; + } + return NULL; +} + +/*------------------------------------------------------------------- + * submits USB interrupt (ie. polling ;-) + */ +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval) +{ + int nint, n; + unsigned long status, destination; + unsigned long info, tmp; + uhci_td_t *mytd; + if (interval < 0 || interval >= 256) + return -1; + + if (interval == 0) + nint = 0; + else { + for (nint = 0, n = 1; nint <= 8; nint++, n += n) { /* round interval down to 2^n */ + if (interval < n) { + interval = n / 2; + break; + } + } + nint--; + } + + USB_UHCI_PRINTF("Rounded interval to %i, chain %i\n", interval, nint); + mytd = uhci_alloc_int_td(); + if (mytd == NULL) { + printf("No free INT TDs found\n"); + return -1; + } + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27); +/* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); +*/ + + destination = + (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe) | + (((transfer_len - 1) & 0x7ff) << 21); + + info = + destination | + (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << + TD_TOKEN_TOGGLE); + tmp = swap_32(td_int[nint].link); + usb_fill_td(mytd, tmp, status, info, (unsigned long)buffer, + (unsigned long)dev); + /* Link it */ + tmp = swap_32((unsigned long)mytd); + td_int[nint].link = tmp; + + usb_dotoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); + + return 0; +} + +/********************************************************************** + * Low Level functions + */ + +void reset_hc(void) +{ + + /* Global reset for 100ms */ + out16r(usb_base_addr + USBPORTSC1, 0x0204); + out16r(usb_base_addr + USBPORTSC2, 0x0204); + out16r(usb_base_addr + USBCMD, USBCMD_GRESET | USBCMD_RS); + /* Turn off all interrupts */ + out16r(usb_base_addr + USBINTR, 0); + wait_ms(50); + out16r(usb_base_addr + USBCMD, 0); + wait_ms(10); +} + +void start_hc(void) +{ + int timeout = 1000; + + while (in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) { + if (!--timeout) { + printf("USBCMD_HCRESET timed out!\n"); + break; + } + } + /* Turn on all interrupts */ + out16r(usb_base_addr + USBINTR, + USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP); + /* Start at frame 0 */ + out16r(usb_base_addr + USBFRNUM, 0); + /* set Framebuffer base address */ + out32r(usb_base_addr + USBFLBASEADD, (unsigned long)&framelist); + /* Run and mark it configured with a 64-byte max packet */ + out16r(usb_base_addr + USBCMD, USBCMD_RS | USBCMD_CF | USBCMD_MAXP); +} + +/* Initialize the skeleton + */ +void usb_init_skel(void) +{ + unsigned long temp; + int n; + + for (n = 0; n < USB_MAX_TEMP_INT_TD; n++) + tmp_int_td[n].dev_ptr = 0L; /* no devices connected */ + /* last td */ + usb_fill_td(&td_last, UHCI_PTR_TERM, TD_CTRL_IOC, USB_PID_OUT, 0, 0L); + /* usb_fill_td(&td_last,UHCI_PTR_TERM,0,0,0); */ + /* End Queue Header */ + usb_fill_qh(&qh_end, UHCI_PTR_TERM, (unsigned long)&td_last); + /* Bulk Queue Header */ + temp = (unsigned long)&qh_end; + usb_fill_qh(&qh_bulk, temp | UHCI_PTR_QH, UHCI_PTR_TERM); + /* Control Queue Header */ + temp = (unsigned long)&qh_bulk; + usb_fill_qh(&qh_cntrl, temp | UHCI_PTR_QH, UHCI_PTR_TERM); + /* 1ms Interrupt td */ + temp = (unsigned long)&qh_cntrl; + usb_fill_td(&td_int[0], temp | UHCI_PTR_QH, 0, USB_PID_OUT, 0, 0L); + temp = (unsigned long)&td_int[0]; + for (n = 1; n < 8; n++) + usb_fill_td(&td_int[n], temp, 0, USB_PID_OUT, 0, 0L); + for (n = 0; n < 1024; n++) { + /* link all framelist pointers to one of the interrupts */ + int m, o; + if ((n & 127) == 127) + framelist[n] = swap_32((unsigned long)&td_int[0]); + else + for (o = 1, m = 2; m <= 128; o++, m += m) + if ((n & (m - 1)) == ((m - 1) / 2)) + framelist[n] = + swap_32((unsigned long)&td_int[o]); + + } +} + +/* check the common skeleton for completed transfers, and update the status + * of the "connected" device. Called from the IRQ routine. + */ +void usb_check_skel(void) +{ + struct usb_device *dev; + /* start with the control qh */ + if (qh_cntrl.dev_ptr != 0) { /* it's a device assigned check if this caused IRQ */ + dev = (struct usb_device *)qh_cntrl.dev_ptr; + /* Flush cache now that hardware updated DATA and TDs/QHs */ + if (!leon3_snooping_avail) + sparc_dcache_flush_all(); + usb_get_td_status(&tmp_td[0], dev); /* update status */ + if (!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */ + qh_cntrl.dev_ptr = 0; + } + } + /* now process the bulk */ + if (qh_bulk.dev_ptr != 0) { /* it's a device assigned check if this caused IRQ */ + dev = (struct usb_device *)qh_bulk.dev_ptr; + /* Flush cache now that hardware updated DATA and TDs/QHs */ + if (!leon3_snooping_avail) + sparc_dcache_flush_all(); + usb_get_td_status(&tmp_td[0], dev); /* update status */ + if (!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */ + qh_bulk.dev_ptr = 0; + } + } +} + +/* check the interrupt chain, ubdate the status of the appropriate device, + * call the appropriate irqhandler and reactivate the TD if the irqhandler + * returns with 1 + */ +void usb_check_int_chain(void) +{ + int i, res; + unsigned long link, status; + struct usb_device *dev; + uhci_td_t *td, *prevtd; + + for (i = 0; i < 8; i++) { + prevtd = &td_int[i]; /* the first previous td is the skeleton td */ + link = swap_32(READ32(&td_int[i].link)) & 0xfffffff0; /* next in chain */ + td = (uhci_td_t *) link; /* assign it */ + /* all interrupt TDs are finally linked to the td_int[0]. + * so we process all until we find the td_int[0]. + * if int0 chain points to a QH, we're also done + */ + while (((i > 0) && (link != (unsigned long)&td_int[0])) || + ((i == 0) + && !(swap_32(READ32(&td->link)) & UHCI_PTR_QH))) { + /* check if a device is assigned with this td */ + status = swap_32(READ32(&td->status)); + if ((td->dev_ptr != 0L) && !(status & TD_CTRL_ACTIVE)) { + /* td is not active and a device is assigned -> call irqhandler */ + dev = (struct usb_device *)td->dev_ptr; + dev->irq_act_len = ((status & 0x7FF) == 0x7FF) ? 0 : (status & 0x7FF) + 1; /* transfered length */ + dev->irq_status = usb_uhci_td_stat(status); /* get status */ + res = dev->irq_handle(dev); /* call irqhandler */ + if (res == 1) { + /* reactivate */ + status |= TD_CTRL_ACTIVE; + td->status = swap_32(status); + prevtd = td; /* previous td = this td */ + } else { + prevtd->link = READ32(&td->link); /* link previous td directly to the nex td -> unlinked */ + /* remove device pointer */ + td->dev_ptr = 0L; + } + } /* if we call the irq handler */ + link = swap_32(READ32(&td->link)) & 0xfffffff0; /* next in chain */ + td = (uhci_td_t *) link; /* assign it */ + } /* process all td in this int chain */ + } /* next interrupt chain */ +} + +/* usb interrupt service routine. + */ +void handle_usb_interrupt(void) +{ + unsigned short status; + static int error = 0; + + /* + * Read the interrupt status, and write it back to clear the + * interrupt cause + */ + + status = in16r(usb_base_addr + USBSTS); + + if (!status) /* shared interrupt, not mine */ + return; + if (status != 1) { + /* remove host controller halted state */ + if ((status & (USBSTS_HCPE | USBSTS_HCH)) == + (USBSTS_HCPE | USBSTS_HCH)) { + /* Stop due to bug in driver, or hardware */ + out16r(usb_base_addr + USBSTS, status); + out16r(usb_base_addr + USBCMD, + USBCMD_HCRESET | USBCMD_GRESET); + printf + ("GRUSB: HW detected error(s) in USB Descriptors (STS: 0x%x)\n", + status); + usb_show_td(8); + return; + } else if ((status & 0x20) + && ((in16r(usb_base_addr + USBCMD) & USBCMD_RS) == + 0)) { + if (error < 10) { + out16r(usb_base_addr + USBCMD, + USBCMD_RS | in16r(usb_base_addr + + USBCMD)); + error++; + } + } else + error = 0; + } + usb_check_int_chain(); /* call interrupt handlers for int tds */ + usb_check_skel(); /* call completion handler for common transfer routines */ + out16r(usb_base_addr + USBSTS, status); +} + +/* init uhci + */ +int usb_lowlevel_init(void) +{ + unsigned char temp; + ambapp_ahbdev ahbdev; + + /* Find GRUSB core using AMBA Plug&Play information */ + if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_UHCI, &ahbdev) != 1) { + printf("USB UHCI: Failed to find GRUSB controller\n"); + return -1; + } + usb_base_addr = ahbdev.address[0]; + grusb_irq = ahbdev.irq; + /* + usb_base_addr = 0xfffa0000; + grusb_irq = 10; + */ +#ifdef USB_UHCI_DEBUG + grusb_show_regs(); +#endif + memset(td_int, 0, sizeof(td_int)); + memset(tmp_td, 0, sizeof(tmp_td)); + memset(tmp_int_td, 0, sizeof(tmp_int_td)); + memset(&qh_cntrl, 0, sizeof(qh_cntrl)); + memset(&qh_end, 0, sizeof(qh_end)); + memset(&td_last, 0, sizeof(td_last)); + + irq_free_handler(grusb_irq); + USB_UHCI_PRINTF("GRUSB: at 0x%lx irq %d\n", usb_base_addr, grusb_irq); + rh.devnum = 0; + usb_init_skel(); + reset_hc(); + start_hc(); + irq_install_handler(grusb_irq, + (interrupt_handler_t *) handle_usb_interrupt, NULL); + return 0; +} + +/* stop uhci + */ +int usb_lowlevel_stop(void) +{ + if (grusb_irq == -1) + return 1; + irq_free_handler(grusb_irq); + reset_hc(); + grusb_irq = -1; + return 0; +} + +/******************************************************************************************* + * Virtual Root Hub + * Since the uhci does not have a real HUB, we simulate one ;-) + */ +#undef USB_RH_DEBUG + +#ifdef USB_RH_DEBUG +#define USB_RH_PRINTF(fmt,args...) printf (fmt ,##args) +static void usb_display_wValue(unsigned short wValue, unsigned short wIndex); +static void usb_display_Req(unsigned short req); +#else +#define USB_RH_PRINTF(fmt,args...) +static void usb_display_wValue(unsigned short wValue, unsigned short wIndex) +{ +} +static void usb_display_Req(unsigned short req) +{ +} +#endif + +static unsigned char root_hub_dev_des[] = { + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, /* __u16 bcdUSB; v1.0 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x01, /* __u8 iManufacturer; */ + 0x00, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + +/* Configuration descriptor */ +static unsigned char root_hub_config_des[] = { + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +static unsigned char root_hub_hub_des[] = { + 0x09, /* __u8 bLength; */ + 0x29, /* __u8 bDescriptorType; Hub-descriptor */ + 0x02, /* __u8 bNbrPorts; */ + 0x00, /* __u16 wHubCharacteristics; */ + 0x00, + 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ + 0x00, /* __u8 bHubContrCurrent; 0 mA */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ +}; + +static unsigned char root_hub_str_index0[] = { + 0x04, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 0x09, /* __u8 lang ID */ + 0x04, /* __u8 lang ID */ +}; + +static unsigned char root_hub_str_index1[] = { + 28, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 'U', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'C', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'I', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'R', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'u', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'b', /* __u8 Unicode */ + 0, /* __u8 Unicode */ +}; + +/* + * Root Hub Control Pipe (interrupt Pipes are not supported) + */ + +int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *cmd) +{ + void *data = buffer; + int leni = transfer_len; + int len = 0; + int status = 0; + int stat = 0; + int i; + + unsigned short cstatus; + + unsigned short bmRType_bReq; + unsigned short wValue; + unsigned short wIndex; + unsigned short wLength; + + if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + printf("Root-Hub submit IRQ: NOT implemented\n"); + return 0; + } + bmRType_bReq = cmd->requesttype | cmd->request << 8; + wValue = swap_16(cmd->value); + wIndex = swap_16(cmd->index); + wLength = swap_16(cmd->length); + usb_display_Req(bmRType_bReq); + for (i = 0; i < 8; i++) + rh.c_p_r[i] = 0; + USB_RH_PRINTF("Root-Hub: adr: %2x cmd(%1x): %02x%02x %04x %04x %04x\n", + dev->devnum, 8, cmd->requesttype, cmd->request, wValue, + wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(unsigned short *)data = swap_16(1); + len = 2; + break; + case RH_GET_STATUS | RH_INTERFACE: + *(unsigned short *)data = swap_16(0); + len = 2; + break; + case RH_GET_STATUS | RH_ENDPOINT: + *(unsigned short *)data = swap_16(0); + len = 2; + break; + case RH_GET_STATUS | RH_CLASS: + *(unsigned long *)data = swap_32(0); + len = 4; + break; /* hub power ** */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + + status = in16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1)); + cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | + ((status & USBPORTSC_PEC) >> (3 - 1)) | + (rh.c_p_r[wIndex - 1] << (0 + 4)); + status = (status & USBPORTSC_CCS) | ((status & USBPORTSC_PE) >> (2 - 1)) | ((status & USBPORTSC_SUSP) >> (12 - 2)) | ((status & USBPORTSC_PR) >> (9 - 4)) | (1 << 8) | /* power on ** */ + ((status & USBPORTSC_LSDA) << (-8 + 9)); + + *(unsigned short *)data = swap_16(status); + *(unsigned short *)(data + 2) = swap_16(cstatus); + len = 4; + break; + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): + len = 0; + break; + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case (RH_C_HUB_OVER_CURRENT): + len = 0; /* hub power over current ** */ + break; + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + usb_display_wValue(wValue, wIndex); + switch (wValue) { + case (RH_PORT_ENABLE): + status = + in16r(usb_base_addr + USBPORTSC1 + + 2 * (wIndex - 1)); + status = (status & 0xfff5) & ~USBPORTSC_PE; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + len = 0; + break; + case (RH_PORT_SUSPEND): + status = + in16r(usb_base_addr + USBPORTSC1 + + 2 * (wIndex - 1)); + status = (status & 0xfff5) & ~USBPORTSC_SUSP; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + len = 0; + break; + case (RH_PORT_POWER): + len = 0; /* port power ** */ + break; + case (RH_C_PORT_CONNECTION): + status = + in16r(usb_base_addr + USBPORTSC1 + + 2 * (wIndex - 1)); + status = (status & 0xfff5) | USBPORTSC_CSC; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + len = 0; + break; + case (RH_C_PORT_ENABLE): + status = + in16r(usb_base_addr + USBPORTSC1 + + 2 * (wIndex - 1)); + status = (status & 0xfff5) | USBPORTSC_PEC; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + len = 0; + break; + case (RH_C_PORT_SUSPEND): +/*** WR_RH_PORTSTAT(RH_PS_PSSC); */ + len = 0; + break; + case (RH_C_PORT_OVER_CURRENT): + len = 0; + break; + case (RH_C_PORT_RESET): + rh.c_p_r[wIndex - 1] = 0; + len = 0; + break; + } + break; + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + usb_display_wValue(wValue, wIndex); + switch (wValue) { + case (RH_PORT_SUSPEND): + status = + in16r(usb_base_addr + USBPORTSC1 + + 2 * (wIndex - 1)); + status = (status & 0xfff5) | USBPORTSC_SUSP; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + len = 0; + break; + case (RH_PORT_RESET): + status = + in16r(usb_base_addr + USBPORTSC1 + + 2 * (wIndex - 1)); + status = (status & 0xfff5) | USBPORTSC_PR; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + wait_ms(10); + status = (status & 0xfff5) & ~USBPORTSC_PR; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + udelay(10); + status = (status & 0xfff5) | USBPORTSC_PE; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + wait_ms(10); + status = (status & 0xfff5) | 0xa; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + len = 0; + break; + case (RH_PORT_POWER): + len = 0; /* port power ** */ + break; + case (RH_PORT_ENABLE): + status = + in16r(usb_base_addr + USBPORTSC1 + + 2 * (wIndex - 1)); + status = (status & 0xfff5) | USBPORTSC_PE; + out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1), + status); + len = 0; + break; + } + break; + + case RH_SET_ADDRESS: + rh.devnum = wValue; + len = 0; + break; + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + i = sizeof(root_hub_config_des); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy(data, root_hub_dev_des, len); + break; + case (0x02): /* configuration descriptor */ + i = sizeof(root_hub_config_des); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy(data, root_hub_config_des, len); + break; + case (0x03): /*string descriptors */ + if (wValue == 0x0300) { + i = sizeof(root_hub_str_index0); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy(data, root_hub_str_index0, len); + break; + } + if (wValue == 0x0301) { + i = sizeof(root_hub_str_index1); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy(data, root_hub_str_index1, len); + break; + } + stat = USB_ST_STALLED; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + root_hub_hub_des[2] = 2; + i = sizeof(root_hub_hub_des); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy(data, root_hub_hub_des, len); + break; + case RH_GET_CONFIGURATION: + *(unsigned char *)data = 0x01; + len = 1; + break; + case RH_SET_CONFIGURATION: + len = 0; + break; + default: + stat = USB_ST_STALLED; + } + USB_RH_PRINTF("Root-Hub stat %lx port1: %x port2: %x\n\n", stat, + in16r(usb_base_addr + USBPORTSC1), + in16r(usb_base_addr + USBPORTSC2)); + dev->act_len = len; + dev->status = stat; + return stat; + +} + +/******************************************************************************** + * Some Debug Routines + */ + +#ifdef USB_RH_DEBUG + +static void usb_display_Req(unsigned short req) +{ + USB_RH_PRINTF("- Root-Hub Request: "); + switch (req) { + case RH_GET_STATUS: + USB_RH_PRINTF("Get Status "); + break; + case RH_GET_STATUS | RH_INTERFACE: + USB_RH_PRINTF("Get Status Interface "); + break; + case RH_GET_STATUS | RH_ENDPOINT: + USB_RH_PRINTF("Get Status Endpoint "); + break; + case RH_GET_STATUS | RH_CLASS: + USB_RH_PRINTF("Get Status Class"); + break; /* hub power ** */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Get Status Class Others"); + break; + case RH_CLEAR_FEATURE | RH_ENDPOINT: + USB_RH_PRINTF("Clear Feature Endpoint "); + break; + case RH_CLEAR_FEATURE | RH_CLASS: + USB_RH_PRINTF("Clear Feature Class "); + break; + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Clear Feature Other Class "); + break; + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Set Feature Other Class "); + break; + case RH_SET_ADDRESS: + USB_RH_PRINTF("Set Address "); + break; + case RH_GET_DESCRIPTOR: + USB_RH_PRINTF("Get Descriptor "); + break; + case RH_GET_DESCRIPTOR | RH_CLASS: + USB_RH_PRINTF("Get Descriptor Class "); + break; + case RH_GET_CONFIGURATION: + USB_RH_PRINTF("Get Configuration "); + break; + case RH_SET_CONFIGURATION: + USB_RH_PRINTF("Get Configuration "); + break; + default: + USB_RH_PRINTF("****UNKNOWN**** 0x%04X ", req); + } + USB_RH_PRINTF("\n"); + +} + +static void usb_display_wValue(unsigned short wValue, unsigned short wIndex) +{ + switch (wValue) { + case (RH_PORT_ENABLE): + USB_RH_PRINTF("Root-Hub: Enable Port %d\n", wIndex); + break; + case (RH_PORT_SUSPEND): + USB_RH_PRINTF("Root-Hub: Suspend Port %d\n", wIndex); + break; + case (RH_PORT_POWER): + USB_RH_PRINTF("Root-Hub: Port Power %d\n", wIndex); + break; + case (RH_C_PORT_CONNECTION): + USB_RH_PRINTF("Root-Hub: C Port Connection Port %d\n", wIndex); + break; + case (RH_C_PORT_ENABLE): + USB_RH_PRINTF("Root-Hub: C Port Enable Port %d\n", wIndex); + break; + case (RH_C_PORT_SUSPEND): + USB_RH_PRINTF("Root-Hub: C Port Suspend Port %d\n", wIndex); + break; + case (RH_C_PORT_OVER_CURRENT): + USB_RH_PRINTF("Root-Hub: C Port Over Current Port %d\n", + wIndex); + break; + case (RH_C_PORT_RESET): + USB_RH_PRINTF("Root-Hub: C Port reset Port %d\n", wIndex); + break; + default: + USB_RH_PRINTF("Root-Hub: unknown %x %x\n", wValue, wIndex); + break; + } +} + +#endif + +/*#ifdef USB_UHCI_DEBUG*/ + +static int usb_display_td(uhci_td_t * td) +{ + unsigned long tmp; + int valid; + + printf("TD at %p:\n", td); + + tmp = swap_32(READ32(&td->link)); + printf("Link points to 0x%08lX, %s first, %s, %s\n", tmp & 0xfffffff0, + ((tmp & 0x4) == 0x4) ? "Depth" : "Breath", + ((tmp & 0x2) == 0x2) ? "QH" : "TD", + ((tmp & 0x1) == 0x1) ? "invalid" : "valid"); + valid = ((tmp & 0x1) == 0x0); + tmp = swap_32(READ32(&td->status)); + printf + (" %s %ld Errors %s %s %s \n %s %s %s %s %s %s\n Len 0x%lX\n", + (((tmp >> 29) & 0x1) == 0x1) ? "SPD Enable" : "SPD Disable", + ((tmp >> 28) & 0x3), + (((tmp >> 26) & 0x1) == 0x1) ? "Low Speed" : "Full Speed", + (((tmp >> 25) & 0x1) == 0x1) ? "ISO " : "", + (((tmp >> 24) & 0x1) == 0x1) ? "IOC " : "", + (((tmp >> 23) & 0x1) == 0x1) ? "Active " : "Inactive ", + (((tmp >> 22) & 0x1) == 0x1) ? "Stalled" : "", + (((tmp >> 21) & 0x1) == 0x1) ? "Data Buffer Error" : "", + (((tmp >> 20) & 0x1) == 0x1) ? "Babble" : "", + (((tmp >> 19) & 0x1) == 0x1) ? "NAK" : "", + (((tmp >> 18) & 0x1) == 0x1) ? "Bitstuff Error" : "", + (tmp & 0x7ff)); + tmp = swap_32(READ32(&td->info)); + printf(" MaxLen 0x%lX\n", ((tmp >> 21) & 0x7FF)); + printf(" %sEndpoint 0x%lX Dev Addr 0x%lX PID 0x%lX\n", + ((tmp >> 19) & 0x1) == 0x1 ? "TOGGLE " : "", ((tmp >> 15) & 0xF), + ((tmp >> 8) & 0x7F), tmp & 0xFF); + tmp = swap_32(READ32(&td->buffer)); + printf(" Buffer 0x%08lX\n", tmp); + printf(" DEV %08lX\n", td->dev_ptr); + return valid; +} + +void usb_show_td(int max) +{ + int i; + if (max > 0) { + for (i = 0; i < max; i++) { + usb_display_td(&tmp_td[i]); + } + } else { + i = 0; + do { + printf("tmp_td[%d]\n", i); + } while (usb_display_td(&tmp_td[i++])); + } +} + +void grusb_show_regs(void) +{ + unsigned int tmp; + + tmp = in16r(usb_base_addr + USBCMD); + printf(" USBCMD: 0x%04x\n", tmp); + tmp = in16r(usb_base_addr + USBSTS); + printf(" USBSTS: 0x%04x\n", tmp); + tmp = in16r(usb_base_addr + USBINTR); + printf(" USBINTR: 0x%04x\n", tmp); + tmp = in16r(usb_base_addr + USBFRNUM); + printf(" FRNUM: 0x%04x\n", tmp); + tmp = in32r(usb_base_addr + USBFLBASEADD); + printf(" FLBASEADD: 0x%08x\n", tmp); + tmp = in16r(usb_base_addr + USBSOF); + printf(" SOFMOD: 0x%04x\n", tmp); + tmp = in16r(usb_base_addr + USBPORTSC1); + printf(" PORTSC1: 0x%04x\n", tmp); +} + +/*#endif*/ +#endif /* CONFIG_USB_UHCI */ + +/* EOF */ diff --git a/cpu/leon3/usb_uhci.h b/cpu/leon3/usb_uhci.h new file mode 100644 index 000000000..bf572a661 --- /dev/null +++ b/cpu/leon3/usb_uhci.h @@ -0,0 +1,184 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Note: Part of this code has been derived from linux + * + */ +#ifndef _USB_UHCI_H_ +#define _USB_UHCI_H_ + +/* Command register */ +#define USBCMD 0 +#define USBCMD_RS 0x0001 /* Run/Stop */ +#define USBCMD_HCRESET 0x0002 /* Host reset */ +#define USBCMD_GRESET 0x0004 /* Global reset */ +#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define USBCMD_FGR 0x0010 /* Force Global Resume */ +#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ +#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ +#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ + +/* Status register */ +#define USBSTS 2 +#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ +#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ +#define USBSTS_RD 0x0004 /* Resume Detect */ +#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ +#define USBSTS_HCH 0x0020 /* HC Halted */ + +/* Interrupt enable register */ +#define USBINTR 4 +#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ +#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ +#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ +#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ + +#define USBFRNUM 6 +#define USBFLBASEADD 8 +#define USBSOF 12 + +/* USB port status and control registers */ +#define USBPORTSC1 16 +#define USBPORTSC2 18 +#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ +#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ +#define USBPORTSC_PE 0x0004 /* Port Enable */ +#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ +#define USBPORTSC_LS 0x0030 /* Line Status */ +#define USBPORTSC_RD 0x0040 /* Resume Detect */ +#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ +#define USBPORTSC_PR 0x0200 /* Port Reset */ +#define USBPORTSC_SUSP 0x1000 /* Suspend */ + +/* Legacy support register */ +#define USBLEGSUP 0xc0 +#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ + +#define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */ +#define UHCI_PID 0xff /* PID MASK */ + +#define UHCI_PTR_BITS 0x000F +#define UHCI_PTR_TERM 0x0001 +#define UHCI_PTR_QH 0x0002 +#define UHCI_PTR_DEPTH 0x0004 + +/* for TD : */ +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ +#define TD_CTRL_ACTLEN_MASK 0x7ff /* actual length, encoded as n - 1 */ + +#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) + +#define TD_TOKEN_TOGGLE 19 + +/* ------------------------------------------------------------------------------------ + Virtual Root HUB + ------------------------------------------------------------------------------------ */ +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +/* Our Vendor Specific feature */ +#define RH_REMOVE_EP 0x00 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + +/* Transfer descriptor structure */ +typedef struct { + unsigned long link; /* next td/qh (LE) */ + unsigned long status; /* status of the td */ + unsigned long info; /* Max Lenght / Endpoint / device address and PID */ + unsigned long buffer; /* pointer to data buffer (LE) */ + unsigned long dev_ptr; /* pointer to the assigned device (BE) */ + unsigned long res[3]; /* reserved (TDs must be 8Byte aligned) */ +} uhci_td_t, *puhci_td_t; + +/* Queue Header structure */ +typedef struct { + unsigned long head; /* Next QH (LE) */ + unsigned long element; /* Queue element pointer (LE) */ + unsigned long res[5]; /* reserved */ + unsigned long dev_ptr; /* if 0 no tds have been assigned to this qh */ +} uhci_qh_t, *puhci_qh_t; + +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + int numports; /* number of ports */ + int c_p_r[8]; /* C_PORT_RESET */ +}; + +#endif /* _USB_UHCI_H_ */ diff --git a/include/ambapp.h b/include/ambapp.h new file mode 100644 index 000000000..1e49d896c --- /dev/null +++ b/include/ambapp.h @@ -0,0 +1,380 @@ +/* Interface for accessing Gaisler AMBA Plug&Play Bus. + * The AHB bus can be interfaced with a simpler bus - + * the APB bus, also freely available in GRLIB at + * www.gaisler.com. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __AMBAPP_H__ +#define __AMBAPP_H__ + +/* Default location of Plug&Play info + * normally 0xfffff000 for AHB masters + * and 0xfffff800 for AHB slaves. + * Normally no need to change this. + */ +#define LEON3_IO_AREA 0xfff00000 +#define LEON3_CONF_AREA 0xff000 +#define LEON3_AHB_SLAVE_CONF_AREA (1 << 11) + +/* Max devices this software will support */ +#define LEON3_AHB_MASTERS 16 +#define LEON3_AHB_SLAVES 16 + /*#define LEON3_APB_MASTERS 1*//* Number of APB buses that has Plug&Play */ +#define LEON3_APB_SLAVES 16 /* Total number of APB slaves per APB bus */ + +/* Vendor codes */ +#define VENDOR_GAISLER 1 +#define VENDOR_PENDER 2 +#define VENDOR_ESA 4 +#define VENDOR_ASTRIUM 6 +#define VENDOR_OPENCHIP 7 +#define VENDOR_OPENCORES 8 +#define VENDOR_CONTRIB 9 +#define VENDOR_EONIC 11 +#define VENDOR_RADIONOR 15 +#define VENDOR_GLEICHMANN 16 +#define VENDOR_MENTA 17 +#define VENDOR_SUN 19 +#define VENDOR_EMBEDDIT 234 +#define VENDOR_CAL 202 + +/* Gaisler Research device id's */ +#define GAISLER_LEON3 0x003 +#define GAISLER_LEON3DSU 0x004 +#define GAISLER_ETHAHB 0x005 +#define GAISLER_APBMST 0x006 +#define GAISLER_AHBUART 0x007 +#define GAISLER_SRCTRL 0x008 +#define GAISLER_SDCTRL 0x009 +#define GAISLER_APBUART 0x00C +#define GAISLER_IRQMP 0x00D +#define GAISLER_AHBRAM 0x00E +#define GAISLER_GPTIMER 0x011 +#define GAISLER_PCITRG 0x012 +#define GAISLER_PCISBRG 0x013 +#define GAISLER_PCIFBRG 0x014 +#define GAISLER_PCITRACE 0x015 +#define GAISLER_PCIDMA 0x016 +#define GAISLER_AHBTRACE 0x017 +#define GAISLER_ETHDSU 0x018 +#define GAISLER_PIOPORT 0x01A +#define GAISLER_AHBJTAG 0x01c +#define GAISLER_SPW 0x01f +#define GAISLER_ATACTRL 0x024 +#define GAISLER_VGA 0x061 +#define GAISLER_KBD 0X060 +#define GAISLER_ETHMAC 0x01D +#define GAISLER_DDRSPA 0x025 +#define GAISLER_EHCI 0x026 +#define GAISLER_UHCI 0x027 +#define GAISLER_SPW2 0x029 +#define GAISLER_DDR2SPA 0x02E +#define GAISLER_AHBSTAT 0x052 +#define GAISLER_FTMCTRL 0x054 + +#define GAISLER_L2TIME 0xffd /* internal device: leon2 timer */ +#define GAISLER_L2C 0xffe /* internal device: leon2compat */ +#define GAISLER_PLUGPLAY 0xfff /* internal device: plug & play configarea */ + +/* European Space Agency device id's */ +#define ESA_LEON2 0x2 +#define ESA_MCTRL 0xF + +/* Opencores device id's */ +#define OPENCORES_PCIBR 0x4 +#define OPENCORES_ETHMAC 0x5 + +/* Vendor codes */ + +/* + * + * Macros for manipulating Configuration registers + * + */ + +#define amba_vendor(x) (((x) >> 24) & 0xff) + +#define amba_device(x) (((x) >> 12) & 0xfff) + +#define amba_membar_start(mbar) \ + (((mbar) & 0xfff00000) & (((mbar) & 0xfff0) << 16)) + +#define amba_iobar_start(base, iobar) \ + ((base) | ((((iobar) & 0xfff00000)>>12) & (((iobar) & 0xfff0)<<4)) ) + +#define amba_irq(conf) ((conf) & 0xf) + +#define amba_ver(conf) (((conf)>>5) & 0x1f) + +#define amba_membar_type(mbar) ((mbar) & 0xf) + +#define amba_membar_mask(mbar) (((mbar)>>4) & 0xfff) + +#define AMBA_TYPE_APBIO 0x1 +#define AMBA_TYPE_MEM 0x2 +#define AMBA_TYPE_AHBIO 0x3 + +#define AMBA_TYPE_AHBIO_ADDR(addr) (LEON3_IO_AREA | ((addr) >> 12)) + +#ifndef __ASSEMBLER__ + +/* + * Types and structure used for AMBA Plug & Play bus scanning + */ + +/* AMBA Plug&Play AHB information layout */ +typedef struct { + unsigned int conf; + unsigned int userdef[3]; + unsigned int bars[4]; +} ahbctrl_pp_dev; + +/* Prototypes for scanning AMBA Plug&Play bus for AMBA + * i) AHB Masters + * ii) AHB Slaves + * iii) APB Slaves (APB MST is a AHB Slave) + */ + +typedef struct { + unsigned char irq; + unsigned char ver; + unsigned int address; +} ambapp_apbdev; + +typedef struct { + unsigned char irq; + unsigned char ver; + unsigned int userdef[3]; + unsigned int address[4]; +} ambapp_ahbdev; + +/* AMBA Plug&Play AHB Masters & Slaves information locations + * Max devices is 64 supported by HW, however often only 8 + * are used. + */ +typedef struct { + ahbctrl_pp_dev masters[64]; + ahbctrl_pp_dev slaves[64]; +} ahbctrl_info; + +/* AMBA Plug&Play AHB information layout */ +typedef struct { + unsigned int conf; + unsigned int bar; +} apbctrl_pp_dev; + +/* All functions return the number of found devices + * 0 = no devices found + */ + +/****************************** APB SLAVES ******************************/ +int ambapp_apb_count(unsigned int vendor, unsigned int driver); + +int ambapp_apb_first(unsigned int vendor, + unsigned int driver, ambapp_apbdev * dev); + +int ambapp_apb_next(unsigned int vendor, + unsigned int driver, ambapp_apbdev * dev, int index); + +int ambapp_apbs_first(unsigned int vendor, + unsigned int driver, ambapp_apbdev * dev, int max_cnt); + +/****************************** AHB MASTERS ******************************/ +int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver); + +int ambapp_ahbmst_first(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev); + +int ambapp_ahbmst_next(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev, int index); + +int ambapp_ahbmsts_first(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev, int max_cnt); + +/****************************** AHB SLAVES ******************************/ +int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver); + +int ambapp_ahbslv_first(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev); + +int ambapp_ahbslv_next(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev, int index); + +int ambapp_ahbslvs_first(unsigned int vendor, + unsigned int driver, ambapp_ahbdev * dev, int max_cnt); + +/*************************** AHB/APB only regs functions ************************* + * During start up, no memory is available we can use the simplified functions + * to get to the memory controller. + * + * Functions uses no stack/memory, only registers. + */ +unsigned int ambapp_apb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */ + register unsigned int driver, /* Plug&Play Device ID */ + register int index); + +ahbctrl_pp_dev *ambapp_ahb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */ + register unsigned int driver, /* Plug&Play Device ID */ + register unsigned int opts, /* scan for AHB 1=slave, 0=masters */ + register int index); + +unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info); + +/*************************** AMBA Plug&Play device register MAPS *****************/ + +/* + * The following defines the bits in the LEON UART Status Registers. + */ + +#define LEON_REG_UART_STATUS_DR 0x00000001 /* Data Ready */ +#define LEON_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */ +#define LEON_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */ +#define LEON_REG_UART_STATUS_BR 0x00000008 /* Break Error */ +#define LEON_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */ +#define LEON_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */ +#define LEON_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */ +#define LEON_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */ + +/* + * The following defines the bits in the LEON UART Ctrl Registers. + */ + +#define LEON_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */ +#define LEON_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */ +#define LEON_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */ +#define LEON_REG_UART_CTRL_TI 0x00000008 /* Transmitter interrupt enable */ +#define LEON_REG_UART_CTRL_PS 0x00000010 /* Parity select */ +#define LEON_REG_UART_CTRL_PE 0x00000020 /* Parity enable */ +#define LEON_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */ +#define LEON_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */ +#define LEON_REG_UART_CTRL_DBG (1<<11) /* Debug Bit used by GRMON */ + +#define LEON3_GPTIMER_EN 1 +#define LEON3_GPTIMER_RL 2 +#define LEON3_GPTIMER_LD 4 +#define LEON3_GPTIMER_IRQEN 8 + +/* + * The following defines the bits in the LEON PS/2 Status Registers. + */ + +#define LEON_REG_PS2_STATUS_DR 0x00000001 /* Data Ready */ +#define LEON_REG_PS2_STATUS_PE 0x00000002 /* Parity error */ +#define LEON_REG_PS2_STATUS_FE 0x00000004 /* Framing error */ +#define LEON_REG_PS2_STATUS_KI 0x00000008 /* Keyboard inhibit */ + +/* + * The following defines the bits in the LEON PS/2 Ctrl Registers. + */ + +#define LEON_REG_PS2_CTRL_RE 0x00000001 /* Receiver enable */ +#define LEON_REG_PS2_CTRL_TE 0x00000002 /* Transmitter enable */ +#define LEON_REG_PS2_CTRL_RI 0x00000004 /* Keyboard receive interrupt */ +#define LEON_REG_PS2_CTRL_TI 0x00000008 /* Keyboard transmit interrupt */ + +typedef struct { + volatile unsigned int ilevel; + volatile unsigned int ipend; + volatile unsigned int iforce; + volatile unsigned int iclear; + volatile unsigned int mstatus; + volatile unsigned int notused[11]; + volatile unsigned int cpu_mask[16]; + volatile unsigned int cpu_force[16]; +} ambapp_dev_irqmp; + +typedef struct { + volatile unsigned int data; + volatile unsigned int status; + volatile unsigned int ctrl; + volatile unsigned int scaler; +} ambapp_dev_apbuart; + +typedef struct { + volatile unsigned int val; + volatile unsigned int rld; + volatile unsigned int ctrl; + volatile unsigned int unused; +} ambapp_dev_gptimer_element; + +#define LEON3_GPTIMER_CTRL_EN 0x1 /* Timer enable */ +#define LEON3_GPTIMER_CTRL_RS 0x2 /* Timer reStart */ +#define LEON3_GPTIMER_CTRL_LD 0x4 /* Timer reLoad */ +#define LEON3_GPTIMER_CTRL_IE 0x8 /* interrupt enable */ +#define LEON3_GPTIMER_CTRL_IP 0x10 /* interrupt flag/pending */ +#define LEON3_GPTIMER_CTRL_CH 0x20 /* Chain with previous timer */ + +typedef struct { + volatile unsigned int scalar; + volatile unsigned int scalar_reload; + volatile unsigned int config; + volatile unsigned int unused; + volatile ambapp_dev_gptimer_element e[8]; +} ambapp_dev_gptimer; + +typedef struct { + volatile unsigned int iodata; + volatile unsigned int ioout; + volatile unsigned int iodir; + volatile unsigned int irqmask; + volatile unsigned int irqpol; + volatile unsigned int irqedge; +} ambapp_dev_ioport; + +typedef struct { + volatile unsigned int write; + volatile unsigned int dummy; + volatile unsigned int txcolor; + volatile unsigned int bgcolor; +} ambapp_dev_textvga; + +typedef struct { + volatile unsigned int data; + volatile unsigned int status; + volatile unsigned int ctrl; +} ambapp_dev_apbps2; + +typedef struct { + unsigned int mcfg1, mcfg2, mcfg3; +} ambapp_dev_mctrl; + +typedef struct { + unsigned int sdcfg; +} ambapp_dev_sdctrl; + +typedef struct { + unsigned int cfg1; + unsigned int cfg2; + unsigned int cfg3; +} ambapp_dev_ddr2spa; + +typedef struct { + unsigned int ctrl; + unsigned int cfg; +} ambapp_dev_ddrspa; + +#endif + +#endif diff --git a/include/asm-sparc/arch-leon3/asi.h b/include/asm-sparc/arch-leon3/asi.h new file mode 100644 index 000000000..700b3caa5 --- /dev/null +++ b/include/asm-sparc/arch-leon3/asi.h @@ -0,0 +1,36 @@ +/* asi.h: Address Space Identifier values for the LEON3 sparc. + * + * Copyright (C) 2008 Daniel Hellstrom (daniel@gaisler.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _LEON3_ASI_H +#define _LEON3_ASI_H + +#define ASI_CACHEMISS 0x01 /* Force D-Cache miss on load (lda) */ +#define ASI_M_FLUSH_PROBE 0x03 /* MMU Flush/Probe */ +#define ASI_IFLUSH 0x10 /* Flush I-Cache */ +#define ASI_DFLUSH 0x11 /* Flush D-Cache */ +#define ASI_BYPASS 0x1c /* Bypass MMU (Physical address) */ +#define ASI_MMUFLUSH 0x18 /* FLUSH TLB */ +#define ASI_M_MMUREGS 0x19 /* READ/Write MMU Registers */ + +#endif /* _LEON3_ASI_H */ diff --git a/include/asm-sparc/leon.h b/include/asm-sparc/leon.h new file mode 100644 index 000000000..6036fb5e7 --- /dev/null +++ b/include/asm-sparc/leon.h @@ -0,0 +1,38 @@ +/* LEON Header File select + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __ASM_LEON_H__ +#define __ASM_LEON_H__ + +#if defined(CONFIG_LEON3) + +#include + +#else + +#error Unknown LEON processor + +#endif + +/* Common stuff */ + +#endif diff --git a/include/asm-sparc/leon3.h b/include/asm-sparc/leon3.h new file mode 100644 index 000000000..84d0e2ed2 --- /dev/null +++ b/include/asm-sparc/leon3.h @@ -0,0 +1,37 @@ +/* LEON3 header file. LEON3 is a free GPL SOC processor available + * at www.gaisler.com. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __LEON3_H__ +#define __LEON3_H__ + +#ifndef CONFIG_LEON3 +#error Include LEON3 header file only if LEON3 processor +#endif + +/* Not much to define, most is Plug and Play and GRLIB dependent + * not LEON3 dependent. See for GRLIB timers, interrupt + * ctrl, memory controllers etc. + */ + + +#endif diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h index 31b44c546..d518389ad 100644 --- a/include/asm-sparc/processor.h +++ b/include/asm-sparc/processor.h @@ -26,8 +26,15 @@ #include -/* Includeprocessor specific header file here */ +#ifdef CONFIG_LEON + +/* All LEON processors supported */ +#include + +#else +/* other processors */ #error Unknown SPARC Processor +#endif #ifndef __ASSEMBLY__ From 2a2fa797e63b1e3cd4d570318ca5fbf8723ef53a Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Wed, 26 Mar 2008 23:00:38 +0100 Subject: [PATCH 05/11] SPARC/LEON3: Added AMBA Bus Plug&Play information print command (ambapp). It can print available cores (type: AHB Master, AHB Slave, APB Slave), their address ranges, IRQ number and version. Signed-off-by: Daniel Hellstrom --- common/Makefile | 1 + common/cmd_ambapp.c | 278 +++++++++++++++++++++++++++++++++++++++ cpu/leon3/ambapp.c | 20 +++ include/ambapp.h | 14 ++ include/config_cmd_all.h | 1 + 5 files changed, 314 insertions(+) create mode 100644 common/cmd_ambapp.c diff --git a/common/Makefile b/common/Makefile index 0d67337d2..c71b228dc 100644 --- a/common/Makefile +++ b/common/Makefile @@ -32,6 +32,7 @@ COBJS-y += ACEX1K.o COBJS-y += altera.o COBJS-y += bedbug.o COBJS-y += circbuf.o +COBJS-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o COBJS-y += cmd_autoscript.o COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o COBJS-$(CONFIG_CMD_BEDBUG) += cmd_bedbug.o diff --git a/common/cmd_ambapp.c b/common/cmd_ambapp.c new file mode 100644 index 000000000..738412b7f --- /dev/null +++ b/common/cmd_ambapp.c @@ -0,0 +1,278 @@ +/* + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * AMBA Plug&Play information list command + * + */ +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* We put these variables into .data section so that they are zero + * when entering the AMBA Plug & Play routines (in cpu/cpu/ambapp.c) + * the first time. BSS is not garantueed to be zero since BSS + * hasn't been cleared the first times entering the CPU AMBA functions. + * + * The AMBA PnP routines call these functions if ambapp_???_print is set. + * + */ +int ambapp_apb_print __attribute__ ((section(".data"))) = 0; +int ambapp_ahb_print __attribute__ ((section(".data"))) = 0; + +typedef struct { + int device_id; + char *name; +} ambapp_device_name; + +static ambapp_device_name gaisler_devices[] = { + {GAISLER_LEON3, "GAISLER_LEON3"}, + {GAISLER_LEON3DSU, "GAISLER_LEON3DSU"}, + {GAISLER_ETHAHB, "GAISLER_ETHAHB"}, + {GAISLER_ETHMAC, "GAISLER_ETHMAC"}, + {GAISLER_APBMST, "GAISLER_APBMST"}, + {GAISLER_AHBUART, "GAISLER_AHBUART"}, + {GAISLER_SRCTRL, "GAISLER_SRCTRL"}, + {GAISLER_SDCTRL, "GAISLER_SDCTRL"}, + {GAISLER_APBUART, "GAISLER_APBUART"}, + {GAISLER_IRQMP, "GAISLER_IRQMP"}, + {GAISLER_AHBRAM, "GAISLER_AHBRAM"}, + {GAISLER_GPTIMER, "GAISLER_GPTIMER"}, + {GAISLER_PCITRG, "GAISLER_PCITRG"}, + {GAISLER_PCISBRG, "GAISLER_PCISBRG"}, + {GAISLER_PCIFBRG, "GAISLER_PCIFBRG"}, + {GAISLER_PCITRACE, "GAISLER_PCITRACE"}, + {GAISLER_AHBTRACE, "GAISLER_AHBTRACE"}, + {GAISLER_ETHDSU, "GAISLER_ETHDSU"}, + {GAISLER_PIOPORT, "GAISLER_PIOPORT"}, + {GAISLER_AHBJTAG, "GAISLER_AHBJTAG"}, + {GAISLER_ATACTRL, "GAISLER_ATACTRL"}, + {GAISLER_VGA, "GAISLER_VGA"}, + {GAISLER_KBD, "GAISLER_KBD"}, + {GAISLER_L2TIME, "GAISLER_L2TIME"}, + {GAISLER_L2C, "GAISLER_L2C"}, + {GAISLER_PLUGPLAY, "GAISLER_PLUGPLAY"}, + {GAISLER_SPW, "GAISLER_SPW"}, + {GAISLER_SPW2, "GAISLER_SPW2"}, + {GAISLER_EHCI, "GAISLER_EHCI"}, + {GAISLER_UHCI, "GAISLER_UHCI"}, + {GAISLER_AHBSTAT, "GAISLER_AHBSTAT"}, + {GAISLER_DDR2SPA, "GAISLER_DDR2SPA"}, + {GAISLER_DDRSPA, "GAISLER_DDRSPA"}, + {0, NULL} +}; + +static ambapp_device_name esa_devices[] = { + {ESA_LEON2, "ESA_LEON2"}, + {ESA_MCTRL, "ESA_MCTRL"}, + {0, NULL} +}; + +static ambapp_device_name opencores_devices[] = { + {OPENCORES_PCIBR, "OPENCORES_PCIBR"}, + {OPENCORES_ETHMAC, "OPENCORES_ETHMAC"}, + {0, NULL} +}; + +typedef struct { + unsigned int vendor_id; + char *name; + ambapp_device_name *devices; +} ambapp_vendor_devnames; + +static ambapp_vendor_devnames vendors[] = { + {VENDOR_GAISLER, "VENDOR_GAISLER", gaisler_devices}, + {VENDOR_ESA, "VENDOR_ESA", esa_devices}, + {VENDOR_OPENCORES, "VENDOR_OPENCORES", opencores_devices}, + {0, NULL, 0} +}; + +static char *ambapp_get_devname(ambapp_device_name * devs, int id) +{ + if (!devs) + return NULL; + + while (devs->device_id > 0) { + if (devs->device_id == id) + return devs->name; + devs++; + } + return NULL; +} + +char *ambapp_device_id2str(int vendor, int id) +{ + ambapp_vendor_devnames *ven = &vendors[0]; + + while (ven->vendor_id > 0) { + if (ven->vendor_id == vendor) { + return ambapp_get_devname(ven->devices, id); + } + ven++; + } + return NULL; +} + +char *ambapp_vendor_id2str(int vendor) +{ + ambapp_vendor_devnames *ven = &vendors[0]; + + while (ven->vendor_id > 0) { + if (ven->vendor_id == vendor) { + return ven->name; + } + ven++; + } + return NULL; +} + +static char *unknown = "unknown"; + +/* Print one APB device */ +void ambapp_print_apb(apbctrl_pp_dev * apb, ambapp_ahbdev * apbmst, int index) +{ + char *dev_str, *ven_str; + int irq, ver, vendor, deviceid; + unsigned int address, apbmst_base, mask; + + vendor = amba_vendor(apb->conf); + deviceid = amba_device(apb->conf); + irq = amba_irq(apb->conf); + ver = amba_ver(apb->conf); + apbmst_base = apbmst->address[0] & LEON3_IO_AREA; + address = (apbmst_base | (((apb->bar & 0xfff00000) >> 12))) & + (((apb->bar & 0x0000fff0) << 4) | 0xfff00000); + + mask = amba_membar_mask(apb->bar) << 8; + mask = ((~mask) & 0x000fffff) + 1; + + ven_str = ambapp_vendor_id2str(vendor); + if (!ven_str) { + ven_str = unknown; + dev_str = unknown; + } else { + dev_str = ambapp_device_id2str(vendor, deviceid); + if (!dev_str) + dev_str = unknown; + } + + printf("0x%02x:0x%02x:0x%02x: %s %s\n" + " apb: 0x%08x - 0x%08x\n" + " irq: %-2d (ver: %-2d)\n", + index, vendor, deviceid, ven_str, dev_str, address, + address + mask, irq, ver); +} + +void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index) +{ + char *dev_str, *ven_str; + int irq, ver, vendor, deviceid; + unsigned int addr, mask; + int j; + + vendor = amba_vendor(ahb->conf); + deviceid = amba_device(ahb->conf); + irq = amba_irq(ahb->conf); + ver = amba_ver(ahb->conf); + + ven_str = ambapp_vendor_id2str(vendor); + if (!ven_str) { + ven_str = unknown; + dev_str = unknown; + } else { + dev_str = ambapp_device_id2str(vendor, deviceid); + if (!dev_str) + dev_str = unknown; + } + + printf("0x%02x:0x%02x:0x%02x: %s %s\n", + index, vendor, deviceid, ven_str, dev_str); + + for (j = 0; j < 4; j++) { + addr = amba_membar_start(ahb->bars[j]); + if (amba_membar_type(ahb->bars[j]) == 0) + continue; + if (amba_membar_type(ahb->bars[j]) == AMBA_TYPE_AHBIO) + addr = AMBA_TYPE_AHBIO_ADDR(addr); + mask = amba_membar_mask(ahb->bars[j]) << 20; + printf(" mem: 0x%08x - 0x%08x\n", addr, addr + ((~mask) + 1)); + } + + printf(" irq: %-2d (ver: %d)\n", irq, ver); +} + +int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + + /* Print AHB Masters */ + puts("--------- AHB Masters ---------\n"); + ambapp_apb_print = 0; + ambapp_ahb_print = 1; + ambapp_ahbmst_count(99, 99); /* Get vendor&device 99 = nonexistent... */ + + /* Print AHB Slaves */ + puts("--------- AHB Slaves ---------\n"); + ambapp_ahbslv_count(99, 99); /* Get vendor&device 99 = nonexistent... */ + + /* Print APB Slaves */ + puts("--------- APB Slaves ---------\n"); + ambapp_apb_print = 1; + ambapp_ahb_print = 0; + ambapp_apb_count(99, 99); /* Get vendor&device 99 = nonexistent... */ + + /* Reset, no futher printing */ + ambapp_apb_print = 0; + ambapp_ahb_print = 0; + puts("\n"); + return 0; +} + +int ambapp_init_reloc(void) +{ + ambapp_vendor_devnames *vend = vendors; + ambapp_device_name *dev; + + while (vend->vendor_id && vend->name) { + vend->name = (char *)((unsigned int)vend->name + gd->reloc_off); + vend->devices = + (ambapp_device_name *) ((unsigned int)vend->devices + + gd->reloc_off);; + dev = vend->devices; + vend++; + if (!dev) + continue; + while (dev->device_id && dev->name) { + dev->name = + (char *)((unsigned int)dev->name + gd->reloc_off);; + dev++; + } + } + return 0; +} + +U_BOOT_CMD(ambapp, 1, 1, do_ambapp_print, + "ambapp - list AMBA Plug&Play information\n", + "ambapp\n" + " - lists AMBA (AHB & APB) Plug&Play devices present on the system\n"); diff --git a/cpu/leon3/ambapp.c b/cpu/leon3/ambapp.c index 60ff1a2ae..efd41ae0a 100644 --- a/cpu/leon3/ambapp.c +++ b/cpu/leon3/ambapp.c @@ -28,6 +28,14 @@ #include #include +#if defined(CONFIG_CMD_AMBAPP) +extern void ambapp_print_apb(apbctrl_pp_dev * apb, + ambapp_ahbdev * apbmst, int index); +extern void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index); +extern int ambapp_apb_print; +extern int ambapp_ahb_print; +#endif + static int ambapp_apb_scan(unsigned int vendor, /* Plug&Play Vendor ID */ unsigned int driver, /* Plug&Play Device ID */ ambapp_apbdev * dev, /* Result(s) is placed here */ @@ -58,6 +66,12 @@ static int ambapp_apb_scan(unsigned int vendor, /* Plug&Play Vendor ID */ apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA); for (i = 0; i < LEON3_APB_SLAVES; i++) { +#if defined(CONFIG_CMD_AMBAPP) + if (ambapp_apb_print && amba_vendor(apb->conf) + && amba_device(apb->conf)) { + ambapp_print_apb(apb, &apbmst, i); + } +#endif if ((amba_vendor(apb->conf) == vendor) && (amba_device(apb->conf) == driver) && ((index < 0) || (index-- == 0))) { @@ -192,6 +206,12 @@ static int ambapp_ahb_scan(unsigned int vendor, /* Plug&Play Vendor ID */ } for (i = 0; i < max_pp_devs; i++) { +#if defined(CONFIG_CMD_AMBAPP) + if (ambapp_ahb_print && amba_vendor(ahb->conf) && + amba_device(ahb->conf)) { + ambapp_print_ahb(ahb, i); + } +#endif if ((amba_vendor(ahb->conf) == vendor) && (amba_device(ahb->conf) == driver) && ((index < 0) || (index-- == 0))) { diff --git a/include/ambapp.h b/include/ambapp.h index 1e49d896c..7494e594d 100644 --- a/include/ambapp.h +++ b/include/ambapp.h @@ -140,6 +140,20 @@ #ifndef __ASSEMBLER__ +#ifdef CONFIG_CMD_AMBAPP + +/* AMBA Plug&Play relocation & initialization */ +int ambapp_init_reloc(void); + +/* AMBA Plug&Play Name of Vendors and devices */ + +/* Return name of device */ +char *ambapp_device_id2str(int vendor, int id); + +/* Return name of vendor */ +char *ambapp_vendor_id2str(int vendor); +#endif + /* * Types and structure used for AMBA Plug & Play bus scanning */ diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h index 69276a389..d1b5ffb89 100644 --- a/include/config_cmd_all.h +++ b/include/config_cmd_all.h @@ -13,6 +13,7 @@ * Alphabetical list of all possible commands. */ +#define CONFIG_CMD_AMBAPP /* AMBA Plug & Play Bus print utility */ #define CONFIG_CMD_ASKENV /* ask for env variable */ #define CONFIG_CMD_AUTOSCRIPT /* Autoscript Support */ #define CONFIG_CMD_BDI /* bdinfo */ From b330990c2f36ee4a8bb318360e1c8ba965269ab6 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 28 Mar 2008 10:00:33 +0100 Subject: [PATCH 06/11] SPARC: Added support for SPARC LEON2 SOC Processor. Signed-off-by: Daniel Hellstrom --- Makefile | 4 + README | 1 + cpu/leon2/Makefile | 54 ++ cpu/leon2/config.mk | 26 + cpu/leon2/cpu.c | 58 ++ cpu/leon2/cpu_init.c | 142 ++++ cpu/leon2/interrupts.c | 217 ++++++ cpu/leon2/prom.c | 1047 ++++++++++++++++++++++++++++ cpu/leon2/serial.c | 165 +++++ cpu/leon2/start.S | 661 ++++++++++++++++++ include/asm-sparc/arch-leon2/asi.h | 36 + include/asm-sparc/leon.h | 4 + include/asm-sparc/leon2.h | 236 +++++++ 13 files changed, 2651 insertions(+) create mode 100644 cpu/leon2/Makefile create mode 100644 cpu/leon2/config.mk create mode 100644 cpu/leon2/cpu.c create mode 100644 cpu/leon2/cpu_init.c create mode 100644 cpu/leon2/interrupts.c create mode 100644 cpu/leon2/prom.c create mode 100644 cpu/leon2/serial.c create mode 100644 cpu/leon2/start.S create mode 100644 include/asm-sparc/arch-leon2/asi.h create mode 100644 include/asm-sparc/leon2.h diff --git a/Makefile b/Makefile index bb8247cd1..c97473f94 100644 --- a/Makefile +++ b/Makefile @@ -2902,6 +2902,10 @@ r2dplus_config : unconfig ## LEON3 ######################################################################### +######################################################################### +## LEON2 +######################################################################### + ######################################################################### ######################################################################### ######################################################################### diff --git a/README b/README index dfb51f722..20751191b 100644 --- a/README +++ b/README @@ -153,6 +153,7 @@ Directory Hierarchy: - at32ap Files specific to Atmel AVR32 AP CPUs - i386 Files specific to i386 CPUs - ixp Files specific to Intel XScale IXP CPUs + - leon2 Files specific to Gaisler LEON2 SPARC CPU - leon3 Files specific to Gaisler LEON3 SPARC CPU - mcf52x2 Files specific to Freescale ColdFire MCF52x2 CPUs - mcf5227x Files specific to Freescale ColdFire MCF5227x CPUs diff --git a/cpu/leon2/Makefile b/cpu/leon2/Makefile new file mode 100644 index 000000000..7cc442017 --- /dev/null +++ b/cpu/leon2/Makefile @@ -0,0 +1,54 @@ +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(CPU).a + +START = start.o +SOBJS = +COBJS = cpu_init.o serial.o cpu.o interrupts.o prom.o + +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +$(START): $(START:.o=.S) + $(CC) -D__ASSEMBLY__ $(DBGFLAGS) $(OPTFLAGS) -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE) \ + -I$(TOPDIR)/include -fno-builtin -ffreestanding -nostdinc -isystem $(gccincdir) -pipe \ + $(PLATFORM_CPPFLAGS) -Wall -Wstrict-prototypes \ + -I$(TOPDIR)/board -c -o $(START) $(START:.o=.S) + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/leon2/config.mk b/cpu/leon2/config.mk new file mode 100644 index 000000000..30b224a06 --- /dev/null +++ b/cpu/leon2/config.mk @@ -0,0 +1,26 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_RELFLAGS += -fPIC + +PLATFORM_CPPFLAGS += -DCONFIG_LEON diff --git a/cpu/leon2/cpu.c b/cpu/leon2/cpu.c new file mode 100644 index 000000000..1c1e24b16 --- /dev/null +++ b/cpu/leon2/cpu.c @@ -0,0 +1,58 @@ +/* CPU specific code for the LEON2 CPU + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +extern void _reset_reloc(void); + +int checkcpu(void) +{ + /* check LEON version here */ + printf("CPU: LEON2\n"); + return 0; +} + +/* ------------------------------------------------------------------------- */ + +void cpu_reset(void) +{ + /* Interrupts off */ + disable_interrupts(); + + /* jump to restart in flash */ + _reset_reloc(); +} + +int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + cpu_reset(); + + return 1; +} + +/* ------------------------------------------------------------------------- */ diff --git a/cpu/leon2/cpu_init.c b/cpu/leon2/cpu_init.c new file mode 100644 index 000000000..a24f778c6 --- /dev/null +++ b/cpu/leon2/cpu_init.c @@ -0,0 +1,142 @@ +/* Initializes CPU and basic hardware such as memory + * controllers, IRQ controller and system timer 0. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include + +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* reset CPU (jump to 0, without reset) */ +void start(void); + +struct { + gd_t gd_area; + bd_t bd; +} global_data; + +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers. + * + * Run from FLASH/PROM: + * - until memory controller is set up, only registers avaiable + * - no global variables available for writing + * - constants avaiable + */ + +void cpu_init_f(void) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + + /* initialize the IRQMP */ + leon2->Interrupt_Force = 0; + leon2->Interrupt_Pending = 0; + leon2->Interrupt_Clear = 0xfffe; /* clear all old pending interrupts */ + leon2->Interrupt_Mask = 0xfffe0000; /* mask all IRQs */ + + /* cache */ + + /* I/O port setup */ +#ifdef LEON2_IO_PORT_DIR + leon2->PIO_Direction = LEON2_IO_PORT_DIR; +#endif +#ifdef LEON2_IO_PORT_DATA + leon2->PIO_Data = LEON2_IO_PORT_DATA; +#endif +#ifdef LEON2_IO_PORT_INT + leon2->PIO_Interrupt = LEON2_IO_PORT_INT; +#else + leon2->PIO_Interrupt = 0; +#endif +} + +void cpu_init_f2(void) +{ + +} + +/* + * initialize higher level parts of CPU like time base and timers + */ +int cpu_init_r(void) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + + /* initialize prescaler common to all timers to 1MHz */ + leon2->Scaler_Counter = leon2->Scaler_Reload = + (((CONFIG_SYS_CLK_FREQ / 1000) + 500) / 1000) - 1; + + return (0); +} + +/* Uses Timer 0 to get accurate + * pauses. Max 2 raised to 32 ticks + * + */ +void cpu_wait_ticks(unsigned long ticks) +{ + unsigned long start = get_timer(0); + while (get_timer(start) < ticks) ; +} + +/* initiate and setup timer0 interrupt to 1MHz + * Return irq number for timer int or a negative number for + * dealing with self + */ +int timer_interrupt_init_cpu(void) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + + /* 1ms ticks */ + leon2->Timer_Counter_1 = 0; + leon2->Timer_Reload_1 = 999; /* (((1000000 / 100) - 1)) */ + leon2->Timer_Control_1 = + (LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS | LEON2_TIMER_CTRL_LD); + + return LEON2_TIMER1_IRQNO; +} + +/* + * This function is intended for SHORT delays only. + */ +unsigned long cpu_usec2ticks(unsigned long usec) +{ + /* timer set to 1kHz ==> 1 clk tick = 1 msec */ + if (usec < 1000) + return 1; + return (usec / 1000); +} + +unsigned long cpu_ticks2usec(unsigned long ticks) +{ + /* 1tick = 1usec */ + return ticks * 1000; +} diff --git a/cpu/leon2/interrupts.c b/cpu/leon2/interrupts.c new file mode 100644 index 000000000..35b375c78 --- /dev/null +++ b/cpu/leon2/interrupts.c @@ -0,0 +1,217 @@ +/* + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * + * (C) Copyright 2006 + * Detlev Zundel, DENX Software Engineering, dzu@denx.de + * + * (C) Copyright -2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include + +/* 15 normal irqs and a non maskable interrupt */ +#define NR_IRQS 15 + +struct irq_action { + interrupt_handler_t *handler; + void *arg; + unsigned int count; +}; + +static struct irq_action irq_handlers[NR_IRQS] = { {0}, }; +static int spurious_irq_cnt = 0; +static int spurious_irq = 0; + +static inline unsigned int leon2_get_irqmask(unsigned int irq) +{ + if ((irq < 0) || (irq >= NR_IRQS)) { + return 0; + } else { + return (1 << irq); + } +} + +static void leon2_ic_disable(unsigned int irq) +{ + unsigned int mask, pil; + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + + pil = intLock(); + + /* get mask of interrupt */ + mask = leon2_get_irqmask(irq); + + /* set int level */ + leon2->Interrupt_Mask = + SPARC_NOCACHE_READ(&leon2->Interrupt_Mask) & (~mask); + + intUnlock(pil); +} + +static void leon2_ic_enable(unsigned int irq) +{ + unsigned int mask, pil; + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + + pil = intLock(); + + /* get mask of interrupt */ + mask = leon2_get_irqmask(irq); + + /* set int level */ + leon2->Interrupt_Mask = + SPARC_NOCACHE_READ(&leon2->Interrupt_Mask) | mask; + + intUnlock(pil); +} + +void handler_irq(int irq, struct pt_regs *regs) +{ + if (irq_handlers[irq].handler) { + if (((unsigned int)irq_handlers[irq].handler > CFG_RAM_END) || + ((unsigned int)irq_handlers[irq].handler < CFG_RAM_BASE) + ) { + printf("handler_irq: bad handler: %x, irq number %d\n", + (unsigned int)irq_handlers[irq].handler, irq); + return; + } + irq_handlers[irq].handler(irq_handlers[irq].arg); + irq_handlers[irq].count++; + } else { + spurious_irq_cnt++; + spurious_irq = irq; + } +} + +void leon2_force_int(int irq) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + + if ((irq >= NR_IRQS) || (irq < 0)) + return; + printf("Forcing interrupt %d\n", irq); + + leon2->Interrupt_Force = + SPARC_NOCACHE_READ(&leon2->Interrupt_Force) | (1 << irq); +} + +/****************************************************************************/ + +int interrupt_init_cpu(void) +{ + return (0); +} + +/****************************************************************************/ + +/* Handle Timer 0 IRQ */ +void timer_interrupt_cpu(void *arg) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + + leon2->Timer_Control_1 = + (LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS | LEON2_TIMER_CTRL_LD); + + /* nothing to do here */ + return; +} + +/****************************************************************************/ + +/* + * Install and free a interrupt handler. + */ + +void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg) +{ + if (irq < 0 || irq >= NR_IRQS) { + printf("irq_install_handler: bad irq number %d\n", irq); + return; + } + + if (irq_handlers[irq].handler != NULL) + printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n", + (ulong) handler, (ulong) irq_handlers[irq].handler); + + if (((unsigned int)handler > CFG_RAM_END) || + ((unsigned int)handler < CFG_RAM_BASE) + ) { + printf("irq_install_handler: bad handler: %x, irq number %d\n", + (unsigned int)handler, irq); + return; + } + irq_handlers[irq].handler = handler; + irq_handlers[irq].arg = arg; + + /* enable irq on LEON2 hardware */ + leon2_ic_enable(irq); + +} + +void irq_free_handler(int irq) +{ + if (irq < 0 || irq >= NR_IRQS) { + printf("irq_free_handler: bad irq number %d\n", irq); + return; + } + + /* disable irq on LEON2 hardware */ + leon2_ic_disable(irq); + + irq_handlers[irq].handler = NULL; + irq_handlers[irq].arg = NULL; +} + +/****************************************************************************/ + +#if defined(CONFIG_CMD_IRQ) +void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[]) +{ + int irq; + unsigned int pil = get_pil(); + printf("PIL level: %u\n\r", pil); + printf("Spurious IRQ: %u, last unknown IRQ: %d\n", + spurious_irq_cnt, spurious_irq); + + puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n"); + + for (irq = 0; irq < NR_IRQS; irq++) { + if (irq_handlers[irq].handler != NULL) { + printf("%02d %08lx %08lx %ld\n", irq, + (unsigned int)irq_handlers[irq].handler, + (unsigned int)irq_handlers[irq].arg, + irq_handlers[irq].count); + } + } +} +#endif diff --git a/cpu/leon2/prom.c b/cpu/leon2/prom.c new file mode 100644 index 000000000..b03199577 --- /dev/null +++ b/cpu/leon2/prom.c @@ -0,0 +1,1047 @@ +/* prom.c - emulates a sparc v0 PROM for the linux kernel. + * + * Copyright (C) 2003 Konrad Eisele + * Copyright (C) 2004 Stefan Holst + * Copyright (C) 2007 Daniel Hellstrom + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +/* +#define PRINT_ROM_VEC +*/ +extern struct linux_romvec *kernel_arg_promvec; + +#define PROM_PGT __attribute__ ((__section__ (".prom.pgt"))) +#define PROM_TEXT __attribute__ ((__section__ (".prom.text"))) +#define PROM_DATA __attribute__ ((__section__ (".prom.data"))) + +/* for __va */ +extern int __prom_start; +#define PAGE_OFFSET 0xf0000000 +#define phys_base CFG_SDRAM_BASE +#define PROM_OFFS 8192 +#define PROM_SIZE_MASK (PROM_OFFS-1) +#define __va(x) ( \ + (void *)( ((unsigned long)(x))-PROM_OFFS+ \ + (CFG_PROM_OFFSET-phys_base)+PAGE_OFFSET-TEXT_BASE ) \ + ) +#define __phy(x) ((void *)(((unsigned long)(x))-PROM_OFFS+CFG_PROM_OFFSET-TEXT_BASE)) + +struct property { + char *name; + char *value; + int length; +}; + +struct node { + int level; + struct property *properties; +}; + +static void leon_reboot(char *bcommand); +static void leon_halt(void); +static int leon_nbputchar(int c); +static int leon_nbgetchar(void); + +static int no_nextnode(int node); +static int no_child(int node); +static int no_proplen(int node, char *name); +static int no_getprop(int node, char *name, char *value); +static int no_setprop(int node, char *name, char *value, int len); +static char *no_nextprop(int node, char *name); + +static struct property PROM_TEXT *find_property(int node, char *name); +static int PROM_TEXT leon_strcmp(const char *s1, const char *s2); +static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n); +static void PROM_TEXT leon_reboot_physical(char *bcommand); + +void __inline__ leon_flush_cache_all(void) +{ + __asm__ __volatile__(" flush "); + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory"); +} + +void __inline__ leon_flush_tlb_all(void) +{ + leon_flush_cache_all(); + __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400), + "i"(ASI_MMUFLUSH):"memory"); +} + +typedef struct { + unsigned int ctx_table[256]; + unsigned int pgd_table[256]; +} sparc_srmmu_setup; + +sparc_srmmu_setup srmmu_tables PROM_PGT = { + {0}, + {0x1e, + 0x10001e, + 0x20001e, + 0x30001e, + 0x40001e, + 0x50001e, + 0x60001e, + 0x70001e, + 0x80001e, + 0x90001e, + 0xa0001e, + 0xb0001e, + 0xc0001e, + 0xd0001e, + 0xe0001e, + 0xf0001e, + 0x100001e, + 0x110001e, + 0x120001e, + 0x130001e, + 0x140001e, + 0x150001e, + 0x160001e, + 0x170001e, + 0x180001e, + 0x190001e, + 0x1a0001e, + 0x1b0001e, + 0x1c0001e, + 0x1d0001e, + 0x1e0001e, + 0x1f0001e, + 0x200001e, + 0x210001e, + 0x220001e, + 0x230001e, + 0x240001e, + 0x250001e, + 0x260001e, + 0x270001e, + 0x280001e, + 0x290001e, + 0x2a0001e, + 0x2b0001e, + 0x2c0001e, + 0x2d0001e, + 0x2e0001e, + 0x2f0001e, + 0x300001e, + 0x310001e, + 0x320001e, + 0x330001e, + 0x340001e, + 0x350001e, + 0x360001e, + 0x370001e, + 0x380001e, + 0x390001e, + 0x3a0001e, + 0x3b0001e, + 0x3c0001e, + 0x3d0001e, + 0x3e0001e, + 0x3f0001e, + 0x400001e, + 0x410001e, + 0x420001e, + 0x430001e, + 0x440001e, + 0x450001e, + 0x460001e, + 0x470001e, + 0x480001e, + 0x490001e, + 0x4a0001e, + 0x4b0001e, + 0x4c0001e, + 0x4d0001e, + 0x4e0001e, + 0x4f0001e, + 0x500001e, + 0x510001e, + 0x520001e, + 0x530001e, + 0x540001e, + 0x550001e, + 0x560001e, + 0x570001e, + 0x580001e, + 0x590001e, + 0x5a0001e, + 0x5b0001e, + 0x5c0001e, + 0x5d0001e, + 0x5e0001e, + 0x5f0001e, + 0x600001e, + 0x610001e, + 0x620001e, + 0x630001e, + 0x640001e, + 0x650001e, + 0x660001e, + 0x670001e, + 0x680001e, + 0x690001e, + 0x6a0001e, + 0x6b0001e, + 0x6c0001e, + 0x6d0001e, + 0x6e0001e, + 0x6f0001e, + 0x700001e, + 0x710001e, + 0x720001e, + 0x730001e, + 0x740001e, + 0x750001e, + 0x760001e, + 0x770001e, + 0x780001e, + 0x790001e, + 0x7a0001e, + 0x7b0001e, + 0x7c0001e, + 0x7d0001e, + 0x7e0001e, + 0x7f0001e, + 0x800001e, + 0x810001e, + 0x820001e, + 0x830001e, + 0x840001e, + 0x850001e, + 0x860001e, + 0x870001e, + 0x880001e, + 0x890001e, + 0x8a0001e, + 0x8b0001e, + 0x8c0001e, + 0x8d0001e, + 0x8e0001e, + 0x8f0001e, + 0x900001e, + 0x910001e, + 0x920001e, + 0x930001e, + 0x940001e, + 0x950001e, + 0x960001e, + 0x970001e, + 0x980001e, + 0x990001e, + 0x9a0001e, + 0x9b0001e, + 0x9c0001e, + 0x9d0001e, + 0x9e0001e, + 0x9f0001e, + 0xa00001e, + 0xa10001e, + 0xa20001e, + 0xa30001e, + 0xa40001e, + 0xa50001e, + 0xa60001e, + 0xa70001e, + 0xa80001e, + 0xa90001e, + 0xaa0001e, + 0xab0001e, + 0xac0001e, + 0xad0001e, + 0xae0001e, + 0xaf0001e, + 0xb00001e, + 0xb10001e, + 0xb20001e, + 0xb30001e, + 0xb40001e, + 0xb50001e, + 0xb60001e, + 0xb70001e, + 0xb80001e, + 0xb90001e, + 0xba0001e, + 0xbb0001e, + 0xbc0001e, + 0xbd0001e, + 0xbe0001e, + 0xbf0001e, + 0xc00001e, + 0xc10001e, + 0xc20001e, + 0xc30001e, + 0xc40001e, + 0xc50001e, + 0xc60001e, + 0xc70001e, + 0xc80001e, + 0xc90001e, + 0xca0001e, + 0xcb0001e, + 0xcc0001e, + 0xcd0001e, + 0xce0001e, + 0xcf0001e, + 0xd00001e, + 0xd10001e, + 0xd20001e, + 0xd30001e, + 0xd40001e, + 0xd50001e, + 0xd60001e, + 0xd70001e, + 0xd80001e, + 0xd90001e, + 0xda0001e, + 0xdb0001e, + 0xdc0001e, + 0xdd0001e, + 0xde0001e, + 0xdf0001e, + 0xe00001e, + 0xe10001e, + 0xe20001e, + 0xe30001e, + 0xe40001e, + 0xe50001e, + 0xe60001e, + 0xe70001e, + 0xe80001e, + 0xe90001e, + 0xea0001e, + 0xeb0001e, + 0xec0001e, + 0xed0001e, + 0xee0001e, + 0xef0001e, + 0x400001e /* default */ + } +}; + +/* a self contained prom info structure */ +struct leon_reloc_func { + struct property *(*find_property) (int node, char *name); + int (*strcmp) (char *s1, char *s2); + void *(*memcpy) (void *dest, const void *src, size_t n); + void (*reboot_physical) (char *cmd); +}; + +struct leon_prom_info { + int freq_khz; + int leon_nctx; + int mids[32]; + int baudrates[2]; + struct leon_reloc_func reloc_funcs; + struct property root_properties[4]; + struct property cpu_properties[7]; +#undef CPUENTRY +#define CPUENTRY(idx) struct property cpu_properties##idx[4] + CPUENTRY(1); + CPUENTRY(2); + CPUENTRY(3); + CPUENTRY(4); + CPUENTRY(5); + CPUENTRY(6); + CPUENTRY(7); + CPUENTRY(8); + CPUENTRY(9); + CPUENTRY(10); + CPUENTRY(11); + CPUENTRY(12); + CPUENTRY(13); + CPUENTRY(14); + CPUENTRY(15); + CPUENTRY(16); + CPUENTRY(17); + CPUENTRY(18); + CPUENTRY(19); + CPUENTRY(20); + CPUENTRY(21); + CPUENTRY(22); + CPUENTRY(23); + CPUENTRY(24); + CPUENTRY(25); + CPUENTRY(26); + CPUENTRY(27); + CPUENTRY(28); + CPUENTRY(29); + CPUENTRY(30); + CPUENTRY(31); + struct idprom idprom; + struct linux_nodeops nodeops; + struct linux_mlist_v0 *totphys_p; + struct linux_mlist_v0 totphys; + struct linux_mlist_v0 *avail_p; + struct linux_mlist_v0 avail; + struct linux_mlist_v0 *prommap_p; + void (*synchook) (void); + struct linux_arguments_v0 *bootargs_p; + struct linux_arguments_v0 bootargs; + struct linux_romvec romvec; + struct node nodes[35]; + char s_device_type[12]; + char s_cpu[4]; + char s_mid[4]; + char s_idprom[7]; + char s_compatability[14]; + char s_leon2[6]; + char s_mmu_nctx[9]; + char s_frequency[16]; + char s_uart1_baud[11]; + char s_uart2_baud[11]; + char arg[256]; +}; + +/* static prom info */ +static struct leon_prom_info PROM_DATA spi = { + CONFIG_SYS_CLK_FREQ / 1000, + 256, + { +#undef CPUENTRY +#define CPUENTRY(idx) idx + CPUENTRY(0), + CPUENTRY(1), + CPUENTRY(2), + CPUENTRY(3), + CPUENTRY(4), + CPUENTRY(5), + CPUENTRY(6), + CPUENTRY(7), + CPUENTRY(8), + CPUENTRY(9), + CPUENTRY(10), + CPUENTRY(11), + CPUENTRY(12), + CPUENTRY(13), + CPUENTRY(14), + CPUENTRY(15), + CPUENTRY(16), + CPUENTRY(17), + CPUENTRY(18), + CPUENTRY(19), + CPUENTRY(20), + CPUENTRY(21), + CPUENTRY(22), + CPUENTRY(23), + CPUENTRY(24), + CPUENTRY(25), + CPUENTRY(26), + CPUENTRY(27), + CPUENTRY(28), + CPUENTRY(29), + CPUENTRY(30), + 31}, + {38400, 38400}, + { + __va(find_property), + __va(leon_strcmp), + __va(leon_memcpy), + __phy(leon_reboot_physical), + }, + { + {__va(spi.s_device_type), __va(spi.s_idprom), 4}, + {__va(spi.s_idprom), (char *)__va(&spi.idprom), sizeof(struct idprom)}, + {__va(spi.s_compatability), __va(spi.s_leon2), 5}, + {NULL, NULL, -1} + }, + { + {__va(spi.s_device_type), __va(spi.s_cpu), 4}, + {__va(spi.s_mid), __va(&spi.mids[0]), 4}, + {__va(spi.s_mmu_nctx), (char *)__va(&spi.leon_nctx), 4}, + {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, + {__va(spi.s_uart1_baud), (char *)__va(&spi.baudrates[0]), 4}, + {__va(spi.s_uart2_baud), (char *)__va(&spi.baudrates[1]), 4}, + {NULL, NULL, -1} + }, +#undef CPUENTRY +#define CPUENTRY(idx) \ + { /* cpu_properties */ \ + {__va(spi.s_device_type), __va(spi.s_cpu), 4}, \ + {__va(spi.s_mid), __va(&spi.mids[idx]), 4}, \ + {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, \ + {NULL, NULL, -1} \ + } + CPUENTRY(1), + CPUENTRY(2), + CPUENTRY(3), + CPUENTRY(4), + CPUENTRY(5), + CPUENTRY(6), + CPUENTRY(7), + CPUENTRY(8), + CPUENTRY(9), + CPUENTRY(10), + CPUENTRY(11), + CPUENTRY(12), + CPUENTRY(13), + CPUENTRY(14), + CPUENTRY(15), + CPUENTRY(16), + CPUENTRY(17), + CPUENTRY(18), + CPUENTRY(19), + CPUENTRY(20), + CPUENTRY(21), + CPUENTRY(22), + CPUENTRY(23), + CPUENTRY(24), + CPUENTRY(25), + CPUENTRY(26), + CPUENTRY(27), + CPUENTRY(28), + CPUENTRY(29), + CPUENTRY(30), + CPUENTRY(31), + { + 0x01, /* format */ + M_LEON2 | M_LEON2_SOC, /* machine type */ + {0, 0, 0, 0, 0, 0}, /* eth */ + 0, /* date */ + 0, /* sernum */ + 0, /* checksum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* reserved */ + }, + { + __va(no_nextnode), + __va(no_child), + __va(no_proplen), + __va(no_getprop), + __va(no_setprop), + __va(no_nextprop) + }, + __va(&spi.totphys), + { + NULL, + (char *)CFG_SDRAM_BASE, + 0, + }, + __va(&spi.avail), + { + NULL, + (char *)CFG_SDRAM_BASE, + 0, + }, + NULL, /* prommap_p */ + NULL, + __va(&spi.bootargs), + { + {NULL, __va(spi.arg), NULL /*... */ }, + /*... */ + }, + { + 0, + 0, /* sun4c v0 prom */ + 0, 0, + {__va(&spi.totphys_p), __va(&spi.prommap_p), __va(&spi.avail_p)}, + __va(&spi.nodeops), + NULL, {NULL /* ... */ }, + NULL, NULL, + NULL, NULL, /* pv_getchar, pv_putchar */ + __va(leon_nbgetchar), __va(leon_nbputchar), + NULL, + __va(leon_reboot), + NULL, + NULL, + NULL, + __va(leon_halt), + __va(&spi.synchook), + {NULL}, + __va(&spi.bootargs_p) + /*... */ + }, + { + {0, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ }, + {0, __va(spi.root_properties)}, + /* cpu 0, must be spi.nodes[2] see leon_prom_init() */ + {1, __va(spi.cpu_properties)}, + +#undef CPUENTRY +#define CPUENTRY(idx) \ + {1, __va(spi.cpu_properties##idx) } /* cpu */ + CPUENTRY(1), + CPUENTRY(2), + CPUENTRY(3), + CPUENTRY(4), + CPUENTRY(5), + CPUENTRY(6), + CPUENTRY(7), + CPUENTRY(8), + CPUENTRY(9), + CPUENTRY(10), + CPUENTRY(11), + CPUENTRY(12), + CPUENTRY(13), + CPUENTRY(14), + CPUENTRY(15), + CPUENTRY(16), + CPUENTRY(17), + CPUENTRY(18), + CPUENTRY(19), + CPUENTRY(20), + CPUENTRY(21), + CPUENTRY(22), + CPUENTRY(23), + CPUENTRY(24), + CPUENTRY(25), + CPUENTRY(26), + CPUENTRY(27), + CPUENTRY(28), + CPUENTRY(29), + CPUENTRY(30), + CPUENTRY(31), + {-1, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ } + }, + "device_type", + "cpu", + "mid", + "idprom", + "compatability", + "leon2", + "mmu-nctx", + "clock-frequency", + "uart1_baud", + "uart2_baud", + CONFIG_DEFAULT_KERNEL_COMMAND_LINE +}; + +/* from arch/sparc/kernel/setup.c */ +#define RAMDISK_LOAD_FLAG 0x4000 +extern unsigned short root_flags; +extern unsigned short root_dev; +extern unsigned short ram_flags; +extern unsigned int sparc_ramdisk_image; +extern unsigned int sparc_ramdisk_size; +extern int root_mountflags; + +extern char initrd_end, initrd_start; + +/* Reboot the CPU = jump to beginning of flash again. + * + * Make sure that all function are inlined here. + */ +static void PROM_TEXT leon_reboot(char *bcommand) +{ + register char *arg = bcommand; + void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd); + + /* get physical address */ + struct leon_prom_info *pspi = + (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + unsigned int *srmmu_ctx_table; + + /* Turn of Interrupts */ + set_pil(0xf); + + /* Set kernel's context, context zero */ + srmmu_set_context(0); + + /* Get physical address of the MMU shutdown routine */ + reboot_physical = (void *) + SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical); + + /* Now that we know the physical address of the function + * we can make the MMU allow jumping to it. + */ + srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr(); + + srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table); + + /* get physical address of kernel's context table (assume ptd) */ + srmmu_ctx_table = (unsigned int *) + (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4); + + /* enable access to physical address of MMU shutdown function */ + SPARC_BYPASS_WRITE(&srmmu_ctx_table + [((unsigned int)reboot_physical) >> 24], + (((unsigned int)reboot_physical & 0xff000000) >> 4) | + 0x1e); + + /* flush TLB cache */ + leon_flush_tlb_all(); + + /* flash instruction & data cache */ + sparc_icache_flush_all(); + sparc_dcache_flush_all(); + + /* jump to physical address function + * so that when the MMU is disabled + * we can continue to execute + */ + reboot_physical(arg); +} + +static void PROM_TEXT leon_reboot_physical(char *bcommand) +{ + void __attribute__ ((noreturn)) (*reset) (void); + + /* Turn off MMU */ + srmmu_set_mmureg(0); + + /* Hardcoded start address */ + reset = CFG_MONITOR_BASE; + + /* flush data cache */ + sparc_dcache_flush_all(); + + /* flush instruction cache */ + sparc_icache_flush_all(); + + /* Jump to start in Flash */ + reset(); +} + +static void PROM_TEXT leon_halt(void) +{ + while (1) ; +} + +/* get single char, don't care for blocking*/ +static int PROM_TEXT leon_nbgetchar(void) +{ + return -1; +} + +/* put single char, don't care for blocking*/ +static int PROM_TEXT leon_nbputchar(int c) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + + /***** put char in buffer... *********** + * Make sure all functions are inline! * + ***************************************/ + + /* Wait for last character to go. */ + while (!(SPARC_BYPASS_READ(&leon2->UART_Status_1) + & LEON2_UART_STAT_THE)) ; + + /* Send data */ + SPARC_BYPASS_WRITE(&leon2->UART_Channel_1, c); + + /* Wait for data to be sent */ + while (!(SPARC_BYPASS_READ(&leon2->UART_Status_1) + & LEON2_UART_STAT_TSE)) ; + + return 0; +} + +/* node ops */ + +/*#define nodes ((struct node *)__va(&pspi->nodes))*/ +#define nodes ((struct node *)(pspi->nodes)) + +static int PROM_TEXT no_nextnode(int node) +{ + /* get physical address */ + struct leon_prom_info *pspi = + (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + if (nodes[node].level == nodes[node + 1].level) + return node + 1; + return -1; +} + +static int PROM_TEXT no_child(int node) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + if (nodes[node].level == nodes[node + 1].level - 1) + return node + 1; + return -1; +} + +static struct property PROM_TEXT *find_property(int node, char *name) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + struct property *prop = &nodes[node].properties[0]; + while (prop && prop->name) { + if (pspi->reloc_funcs.strcmp(prop->name, name) == 0) + return prop; + prop++; + } + return NULL; +} + +static int PROM_TEXT no_proplen(int node, char *name) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + struct property *prop = pspi->reloc_funcs.find_property(node, name); + if (prop) + return prop->length; + return -1; +} + +static int PROM_TEXT no_getprop(int node, char *name, char *value) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + struct property *prop = pspi->reloc_funcs.find_property(node, name); + if (prop) { + pspi->reloc_funcs.memcpy(value, prop->value, prop->length); + return 1; + } + return -1; +} + +static int PROM_TEXT no_setprop(int node, char *name, char *value, int len) +{ + return -1; +} + +static char PROM_TEXT *no_nextprop(int node, char *name) +{ + /* get physical address */ + struct leon_prom_info *pspi = (struct leon_prom_info *) + (CFG_PROM_OFFSET + sizeof(srmmu_tables)); + struct property *prop; + + /* convert into virtual address */ + pspi = (struct leon_prom_info *) + (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET); + + if (!name || !name[0]) + return nodes[node].properties[0].name; + + prop = pspi->reloc_funcs.find_property(node, name); + if (prop) + return prop[1].name; + return NULL; +} + +static int PROM_TEXT leon_strcmp(const char *s1, const char *s2) +{ + register char result; + + while (1) { + result = *s1 - *s2; + if (result || !*s1) + break; + s2++; + s1++; + } + + return result; +} + +static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n) +{ + char *dst = (char *)dest, *source = (char *)src; + + while (n--) { + *dst = *source; + dst++; + source++; + } + return dest; +} + +#define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp)) + +void leon_prom_init(struct leon_prom_info *pspi) +{ + unsigned long i; + unsigned char cksum, *ptr; + char *addr_str, *end; + unsigned long sp; + GETREGSP(sp); + + pspi->freq_khz = CONFIG_SYS_CLK_FREQ / 1000; + + /* Set Available main memory size */ + pspi->totphys.num_bytes = CFG_PROM_OFFSET - CFG_SDRAM_BASE; + pspi->avail.num_bytes = pspi->totphys.num_bytes; + +#undef nodes + pspi->nodes[3].level = -1; + pspi->nodes[3].properties = __va(spi.root_properties + 3); + + /* Set Ethernet MAC address from environment */ + if ((addr_str = getenv("ethaddr")) != NULL) { + for (i = 0; i < 6; i++) { + pspi->idprom.id_ethaddr[i] = addr_str ? + simple_strtoul(addr_str, &end, 16) : 0; + if (addr_str) { + addr_str = (*end) ? end + 1 : end; + } + } + } else { + /* HW Address not found in environment, + * Set default HW address + */ + pspi->idprom.id_ethaddr[0] = 0; + pspi->idprom.id_ethaddr[1] = 0; + pspi->idprom.id_ethaddr[2] = 0; + pspi->idprom.id_ethaddr[3] = 0; + pspi->idprom.id_ethaddr[4] = 0; + pspi->idprom.id_ethaddr[5] = 0; + } + + ptr = (unsigned char *)&pspi->idprom; + for (i = cksum = 0; i <= 0x0E; i++) + cksum ^= *ptr++; + pspi->idprom.id_cksum = cksum; +} + +static inline void set_cache(unsigned long regval) +{ + asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval), "i"(2):"memory"); +} + +extern unsigned short bss_start, bss_end; + +/* mark as section .img.main.text, to be referenced in linker script */ +int prom_init(void) +{ + struct leon_prom_info *pspi = (void *) + ((((unsigned int)&spi) & PROM_SIZE_MASK) + CFG_PROM_OFFSET); + + /* disable mmu */ + srmmu_set_mmureg(0x00000000); + __asm__ __volatile__("flush\n\t"); + + /* init prom info struct */ + leon_prom_init(pspi); + + kernel_arg_promvec = &pspi->romvec; +#ifdef PRINT_ROM_VEC + printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi->romvec)); +#endif + return 0; +} + +/* Copy current kernel boot argument to ROMvec */ +void prepare_bootargs(char *bootargs) +{ + struct leon_prom_info *pspi; + char *src, *dst; + int left; + + /* if no bootargs set, skip copying ==> default bootline */ + if (bootargs && (*bootargs != '\0')) { + pspi = (void *)((((unsigned int)&spi) & PROM_SIZE_MASK) + + CFG_PROM_OFFSET); + src = bootargs; + dst = &pspi->arg[0]; + left = 255; /* max len */ + while (*src && left > 0) { + *dst++ = *src++; + left--; + } + /* terminate kernel command line string */ + *dst = 0; + } +} + +void srmmu_init_cpu(unsigned int entry) +{ + sparc_srmmu_setup *psrmmu_tables = (void *) + ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) + + CFG_PROM_OFFSET); + + /* Make context 0 (kernel's context) point + * to our prepared memory mapping + */ +#define PTD 1 + psrmmu_tables->ctx_table[0] = + ((unsigned int)&psrmmu_tables->pgd_table[0x00]) >> 4 | PTD; + + /* Set virtual kernel address 0xf0000000 + * to SRAM/SDRAM address. + * Make it READ/WRITE/EXEC to SuperUser + */ +#define PTE 2 +#define ACC_SU_ALL 0x1c + psrmmu_tables->pgd_table[0xf0] = + (CFG_SDRAM_BASE >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf1] = + ((CFG_SDRAM_BASE + 0x1000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf2] = + ((CFG_SDRAM_BASE + 0x2000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf3] = + ((CFG_SDRAM_BASE + 0x3000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf4] = + ((CFG_SDRAM_BASE + 0x4000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf5] = + ((CFG_SDRAM_BASE + 0x5000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf6] = + ((CFG_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE; + psrmmu_tables->pgd_table[0xf7] = + ((CFG_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE; + + /* convert rom vec pointer to virtual address */ + kernel_arg_promvec = (struct linux_romvec *) + (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000); + + /* Set Context pointer to point to context table + * 256 contexts supported. + */ + srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables->ctx_table[0]); + + /* Set kernel's context, context zero */ + srmmu_set_context(0); + + /* Invalidate all Cache */ + __asm__ __volatile__("flush\n\t"); + + srmmu_set_mmureg(0x00000001); + leon_flush_tlb_all(); + leon_flush_cache_all(); +} diff --git a/cpu/leon2/serial.c b/cpu/leon2/serial.c new file mode 100644 index 000000000..ce9457f5a --- /dev/null +++ b/cpu/leon2/serial.c @@ -0,0 +1,165 @@ +/* GRLIB APBUART Serial controller driver + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Force cache miss each time a serial controller reg is read */ +#define CACHE_BYPASS 1 + +#ifdef CACHE_BYPASS +#define READ_BYTE(var) SPARC_NOCACHE_READ_BYTE((unsigned int)&(var)) +#define READ_HWORD(var) SPARC_NOCACHE_READ_HWORD((unsigned int)&(var)) +#define READ_WORD(var) SPARC_NOCACHE_READ((unsigned int)&(var)) +#define READ_DWORD(var) SPARC_NOCACHE_READ_DWORD((unsigned int)&(var)) +#endif + +int serial_init(void) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + LEON2_Uart_regs *regs; + unsigned int tmp; + + /* Init LEON2 UART + * + * Set scaler / baud rate + * + * Receiver & transmitter enable + */ +#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; +#else + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; +#endif + + regs->UART_Scaler = CFG_LEON2_UART1_SCALER; + + /* Let bit 11 be unchanged (debug bit for GRMON) */ + tmp = READ_WORD(regs->UART_Control); + + regs->UART_Control = ((tmp & LEON2_UART_CTRL_DBG) | + (LEON2_UART1_LOOPBACK_ENABLE << 7) | + (LEON2_UART1_FLOWCTRL_ENABLE << 6) | + (LEON2_UART1_PARITY_ENABLE << 5) | + (LEON2_UART1_ODDPAR_ENABLE << 4) | + LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE); + + return 0; +} + +void serial_putc(const char c) +{ + if (c == '\n') + serial_putc_raw('\r'); + + serial_putc_raw(c); +} + +void serial_putc_raw(const char c) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + LEON2_Uart_regs *regs; + +#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; +#else + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; +#endif + + /* Wait for last character to go. */ + while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_THE)) ; + + /* Send data */ + regs->UART_Channel = c; + +#ifdef LEON_DEBUG + /* Wait for data to be sent */ + while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_TSE)) ; +#endif +} + +void serial_puts(const char *s) +{ + while (*s) { + serial_putc(*s++); + } +} + +int serial_getc(void) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + LEON2_Uart_regs *regs; + +#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; +#else + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; +#endif + + /* Wait for a character to arrive. */ + while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR)) ; + + /* read data */ + return READ_WORD(regs->UART_Channel); +} + +int serial_tstc(void) +{ + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + LEON2_Uart_regs *regs; + +#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; +#else + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; +#endif + + return (READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR); +} + +/* set baud rate for uart */ +void serial_setbrg(void) +{ + /* update baud rate settings, read it from gd->baudrate */ + unsigned int scaler; + LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + LEON2_Uart_regs *regs; + +#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; +#else + regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; +#endif + + if (gd->baudrate > 0) { + scaler = + (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) - + 5) / 10; + regs->UART_Scaler = scaler; + } +} diff --git a/cpu/leon2/start.S b/cpu/leon2/start.S new file mode 100644 index 000000000..937ea1ed7 --- /dev/null +++ b/cpu/leon2/start.S @@ -0,0 +1,661 @@ +/* This is where the SPARC/LEON3 starts + * Copyright (C) 2007, + * Daniel Hellstrom, daniel@gaisler.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Entry for traps which jump to a programmer-specified trap handler. */ +#define TRAPR(H) \ + wr %g0, 0xfe0, %psr; \ + mov %g0, %tbr; \ + ba (H); \ + mov %g0, %wim; + +#define TRAP(H) \ + mov %psr, %l0; \ + ba (H); \ + nop; nop; + +#define TRAPI(ilevel) \ + mov ilevel, %l7; \ + mov %psr, %l0; \ + b _irq_entry; \ + mov %wim, %l3 + +/* Unexcpected trap will halt the processor by forcing it to error state */ +#undef BAD_TRAP +#define BAD_TRAP ta 0; nop; nop; nop; + +/* Software trap. Treat as BAD_TRAP for the time being... */ +#define SOFT_TRAP TRAP(_hwerr) + +#define PSR_INIT 0x1FC0 /* Disable traps, set s and ps */ +#define WIM_INIT 2 + +/* All traps low-level code here must end with this macro. */ +#define RESTORE_ALL b ret_trap_entry; clr %l6; + +#define WRITE_PAUSE nop;nop;nop + +WINDOWSIZE = (16 * 4) +ARGPUSHSIZE = (6 * 4) +ARGPUSH = (WINDOWSIZE + 4) +MINFRAME = (WINDOWSIZE + ARGPUSHSIZE + 4) + +/* Number of register windows */ +#ifndef CFG_SPARC_NWINDOWS +#error Must define number of SPARC register windows, default is 8 +#endif + +#define STACK_ALIGN 8 +#define SA(X) (((X)+(STACK_ALIGN-1)) & ~(STACK_ALIGN-1)) + + .section ".start", "ax" + .globl _start, start, _trap_table + .globl _irq_entry, nmi_trap + .globl _reset_reloc + +/* at address 0 + * Hardware traps + */ +start: +_start: +_trap_table: + TRAPR(_hardreset); ! 00 reset trap + BAD_TRAP; ! 01 instruction_access_exception + BAD_TRAP; ! 02 illegal_instruction + BAD_TRAP; ! 03 priveleged_instruction + BAD_TRAP; ! 04 fp_disabled + TRAP(_window_overflow); ! 05 window_overflow + TRAP(_window_underflow); ! 06 window_underflow + BAD_TRAP; ! 07 Memory Address Not Aligned + BAD_TRAP; ! 08 Floating Point Exception + BAD_TRAP; ! 09 Data Miss Exception + BAD_TRAP; ! 0a Tagged Instruction Ovrflw + BAD_TRAP; ! 0b Watchpoint Detected + BAD_TRAP; ! 0c + BAD_TRAP; ! 0d + BAD_TRAP; ! 0e + BAD_TRAP; ! 0f + BAD_TRAP; ! 10 + TRAPI(1); ! 11 IRQ level 1 + TRAPI(2); ! 12 IRQ level 2 + TRAPI(3); ! 13 IRQ level 3 + TRAPI(4); ! 14 IRQ level 4 + TRAPI(5); ! 15 IRQ level 5 + TRAPI(6); ! 16 IRQ level 6 + TRAPI(7); ! 17 IRQ level 7 + TRAPI(8); ! 18 IRQ level 8 + TRAPI(9); ! 19 IRQ level 9 + TRAPI(10); ! 1a IRQ level 10 + TRAPI(11); ! 1b IRQ level 11 + TRAPI(12); ! 1c IRQ level 12 + TRAPI(13); ! 1d IRQ level 13 + TRAPI(14); ! 1e IRQ level 14 + TRAP(_nmi_trap); ! 1f IRQ level 15 / + ! NMI (non maskable interrupt) + BAD_TRAP; ! 20 r_register_access_error + BAD_TRAP; ! 21 instruction access error + BAD_TRAP; ! 22 + BAD_TRAP; ! 23 + BAD_TRAP; ! 24 co-processor disabled + BAD_TRAP; ! 25 uniplemented FLUSH + BAD_TRAP; ! 26 + BAD_TRAP; ! 27 + BAD_TRAP; ! 28 co-processor exception + BAD_TRAP; ! 29 data access error + BAD_TRAP; ! 2a division by zero + BAD_TRAP; ! 2b data store error + BAD_TRAP; ! 2c data access MMU miss + BAD_TRAP; ! 2d + BAD_TRAP; ! 2e + BAD_TRAP; ! 2f + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30-33 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34-37 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38-3b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3c-3f + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40-43 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44-47 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48-4b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4c-4f + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50-53 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54-57 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58-5b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5c-5f + + /* implementaion dependent */ + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60-63 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64-67 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68-6b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6c-6f + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70-73 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74-77 + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78-7b + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7c-7f + + /* Software traps, not handled */ + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 80-83 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84-87 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 88-8b + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8c-8f + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90-93 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94-97 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98-9b + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9c-9f + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a0-a3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a4-a7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a8-ab + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! ac-af + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b0-b3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b4-b7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b8-bb + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! bc-bf + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c0-c3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c4-c7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c8-cb + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! cc-cf + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d0-d3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d4-d7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d8-db + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! dc-df + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e0-e3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e4-e7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e8-eb + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! ec-ef + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f0-f3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f4-f7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f8-fb + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! fc-ff +/* + * Version string + */ + + .data + .globl version_string +version_string: + .ascii U_BOOT_VERSION + .ascii " (", __DATE__, " - ", __TIME__, ")" + .ascii CONFIG_IDENT_STRING, "\0" + + .section ".text" + .align 4 + +_hardreset: +1000: + flush + nop + nop + nop + + /* Init Cache */ + set (LEON2_PREGS+LEON_REG_CACHECTRL_OFFSET), %g1 + set 0x0081000f, %g2 + st %g2, [%g1] + + mov %g0, %y + clr %g1 + clr %g2 + clr %g3 + clr %g4 + clr %g5 + clr %g6 + clr %g7 + + mov %asr17, %g3 + and %g3, 0x1f, %g3 +clear_window: + mov %g0, %l0 + mov %g0, %l1 + mov %g0, %l2 + mov %g0, %l3 + mov %g0, %l4 + mov %g0, %l5 + mov %g0, %l6 + mov %g0, %l7 + mov %g0, %o0 + mov %g0, %o1 + mov %g0, %o2 + mov %g0, %o3 + mov %g0, %o4 + mov %g0, %o5 + mov %g0, %o6 + mov %g0, %o7 + subcc %g3, 1, %g3 + bge clear_window + save + +leon2_init: + /* LEON2 Register Base in g1 */ + set LEON2_PREGS, %g1 + +leon2_init_cache: + /* Set Cache control register */ + set 0x1000f, %g2 + st %g2, [%g1 + 0x14] + +leon2_init_clear: + + /* Clear LEON2 registers */ + st %g0, [%g1 + LEON2_ECTRL] + st %g0, [%g1 + LEON2_IMASK] + st %g0, [%g1 + LEON2_IPEND] + st %g0, [%g1 + LEON2_IFORCE] + st %g0, [%g1 + LEON2_ICLEAR] + st %g0, [%g1 + LEON2_IOREG] + st %g0, [%g1 + LEON2_IODIR] + st %g0, [%g1 + LEON2_IOICONF] + st %g0, [%g1 + LEON2_UCTRL0] + st %g0, [%g1 + LEON2_UCTRL1] + +leon2_init_ioport: + /* I/O port initialization */ + set 0xaa00, %g2 + st %g2, [%g1 + LEON2_IOREG] + +leon2_init_mctrl: + + /* memory config register 1 */ + set CFG_GRLIB_MEMCFG1, %g2 + ld [%g1], %g3 ! + and %g3, 0x300, %g3 + or %g2, %g3, %g2 + st %g2, [%g1 + LEON2_MCFG1] + set CFG_GRLIB_MEMCFG2, %g2 ! Load memory config register 2 +#if !( defined(TSIM) || !defined(BZIMAGE)) + st %g2, [%g1 + LEON2_MCFG2] ! only for prom version, else done by "dumon -i" +#endif + set CFG_GRLIB_MEMCFG3, %g2 ! Init FT register + st %g2, [%g1 + LEON2_ECTRL] + ld [%g1 + LEON2_ECTRL], %g2 + srl %g2, 30, %g2 + andcc %g2, 3, %g6 + bne,a leon2_init_wim + mov %g0, %asr16 ! clear err_reg + +leon2_init_wim: + set WIM_INIT, %g3 + mov %g3, %wim + +leon2_init_psr: + set 0x1000, %g3 + mov %psr, %g2 + wr %g2, %g3, %psr + nop + nop + nop + +leon2_init_stackp: + set CFG_INIT_SP_OFFSET, %fp + andn %fp, 0x0f, %fp + sub %fp, 64, %sp + +cpu_init_unreloc: + call cpu_init_f + nop + +/* un relocated start address of monitor */ +#define TEXT_START _text + +/* un relocated end address of monitor */ +#define DATA_END __init_end + +reloc: + set TEXT_START,%g2 + set DATA_END,%g3 + set CFG_RELOC_MONITOR_BASE,%g4 +reloc_loop: + ldd [%g2],%l0 + ldd [%g2+8],%l2 + std %l0,[%g4] + std %l2,[%g4+8] + inc 16,%g2 + subcc %g3,%g2,%g0 + bne reloc_loop + inc 16,%g4 + + clr %l0 + clr %l1 + clr %l2 + clr %l3 + clr %g2 + +/* register g4 contain address to start + * This means that BSS must be directly after data and code segments + * + * g3 is length of bss = (__bss_end-__bss_start) + * + */ + +clr_bss: +/* clear bss area (the relocated) */ + set __bss_start,%g2 + set __bss_end,%g3 + sub %g3,%g2,%g3 + add %g3,%g4,%g3 + clr %g1 /* std %g0 uses g0 and g1 */ +/* clearing 16byte a time ==> linker script need to align to 16 byte offset */ +clr_bss_16: + std %g0,[%g4] + std %g0,[%g4+8] + inc 16,%g4 + cmp %g3,%g4 + bne clr_bss_16 + nop + +/* add offsets to GOT table */ +fixup_got: + set __got_start,%g4 + set __got_end,%g3 +/* + * new got offset = (old GOT-PTR (read with ld) - + * CFG_RELOC_MONITOR_BASE(from define) ) + + * Destination Address (from define) + */ + set CFG_RELOC_MONITOR_BASE,%g2 + set TEXT_START, %g1 + add %g4,%g2,%g4 + sub %g4,%g1,%g4 + add %g3,%g2,%g3 + sub %g3,%g1,%g3 + sub %g2,%g1,%g2 ! prepare register with (new base address) - + ! (old base address) +got_loop: + ld [%g4],%l0 ! load old GOT-PTR + add %l0,%g2,%l0 ! increase with (new base address) - + ! (old base) + st %l0,[%g4] + inc 4,%g4 + cmp %g3,%g4 + bne got_loop + nop + +prom_relocate: + set __prom_start, %g2 + set __prom_end, %g3 + set CFG_PROM_OFFSET, %g4 + +prom_relocate_loop: + ldd [%g2],%l0 + ldd [%g2+8],%l2 + std %l0,[%g4] + std %l2,[%g4+8] + inc 16,%g2 + subcc %g3,%g2,%g0 + bne prom_relocate_loop + inc 16,%g4 + +/* Trap table has been moved, lets tell CPU about + * the new trap table address + */ + + set CFG_RELOC_MONITOR_BASE, %g2 + wr %g0, %g2, %tbr + +/* call relocate*/ + nop +/* Call relocated init functions */ +jump: + set cpu_init_f2,%o1 + set CFG_RELOC_MONITOR_BASE,%o2 + add %o1,%o2,%o1 + sub %o1,%g1,%o1 + call %o1 + clr %o0 + + set board_init_f,%o1 + set CFG_RELOC_MONITOR_BASE,%o2 + add %o1,%o2,%o1 + sub %o1,%g1,%o1 + call %o1 + clr %o0 + +dead: ta 0 ! if call returns... + nop + +/* Interrupt handler caller, + * reg L7: interrupt number + * reg L0: psr after interrupt + * reg L1: PC + * reg L2: next PC + * reg L3: wim + */ +_irq_entry: + SAVE_ALL + + or %l0, PSR_PIL, %g2 + wr %g2, 0x0, %psr + WRITE_PAUSE + wr %g2, PSR_ET, %psr + WRITE_PAUSE + mov %l7, %o0 ! irq level + set handler_irq, %o1 + set (CFG_RELOC_MONITOR_BASE-TEXT_BASE), %o2 + add %o1, %o2, %o1 + call %o1 + add %sp, SF_REGS_SZ, %o1 ! pt_regs ptr + or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq + wr %g2, PSR_ET, %psr ! keep ET up + WRITE_PAUSE + + RESTORE_ALL + +!Window overflow trap handler. + .global _window_overflow + +_window_overflow: + + mov %wim, %l3 ! Calculate next WIM + mov %g1, %l7 + srl %l3, 1, %g1 + sll %l3, (CFG_SPARC_NWINDOWS-1) , %l4 + or %l4, %g1, %g1 + + save ! Get into window to be saved. + mov %g1, %wim + nop; + nop; + nop + st %l0, [%sp + 0]; + st %l1, [%sp + 4]; + st %l2, [%sp + 8]; + st %l3, [%sp + 12]; + st %l4, [%sp + 16]; + st %l5, [%sp + 20]; + st %l6, [%sp + 24]; + st %l7, [%sp + 28]; + st %i0, [%sp + 32]; + st %i1, [%sp + 36]; + st %i2, [%sp + 40]; + st %i3, [%sp + 44]; + st %i4, [%sp + 48]; + st %i5, [%sp + 52]; + st %i6, [%sp + 56]; + st %i7, [%sp + 60]; + restore ! Go back to trap window. + mov %l7, %g1 + jmp %l1 ! Re-execute save. + rett %l2 + +/* Window underflow trap handler. */ + + .global _window_underflow + +_window_underflow: + + mov %wim, %l3 ! Calculate next WIM + sll %l3, 1, %l4 + srl %l3, (CFG_SPARC_NWINDOWS-1), %l5 + or %l5, %l4, %l5 + mov %l5, %wim + nop; nop; nop + restore ! Two restores to get into the + restore ! window to restore + ld [%sp + 0], %l0; ! Restore window from the stack + ld [%sp + 4], %l1; + ld [%sp + 8], %l2; + ld [%sp + 12], %l3; + ld [%sp + 16], %l4; + ld [%sp + 20], %l5; + ld [%sp + 24], %l6; + ld [%sp + 28], %l7; + ld [%sp + 32], %i0; + ld [%sp + 36], %i1; + ld [%sp + 40], %i2; + ld [%sp + 44], %i3; + ld [%sp + 48], %i4; + ld [%sp + 52], %i5; + ld [%sp + 56], %i6; + ld [%sp + 60], %i7; + save ! Get back to the trap window. + save + jmp %l1 ! Re-execute restore. + rett %l2 + + retl + +_nmi_trap: + nop + jmp %l1 + rett %l2 + +_hwerr: + ta 0 + nop + nop + b _hwerr ! loop infinite + nop + +/* Registers to not touch at all. */ +#define t_psr l0 /* Set by caller */ +#define t_pc l1 /* Set by caller */ +#define t_npc l2 /* Set by caller */ +#define t_wim l3 /* Set by caller */ +#define t_twinmask l4 /* Set at beginning of this entry routine. */ +#define t_kstack l5 /* Set right before pt_regs frame is built */ +#define t_retpc l6 /* If you change this, change winmacro.h header file */ +#define t_systable l7 /* Never touch this, could be the syscall table ptr. */ +#define curptr g6 /* Set after pt_regs frame is built */ + +trap_setup: +/* build a pt_regs trap frame. */ + sub %fp, (SF_REGS_SZ + PT_REGS_SZ), %t_kstack + PT_STORE_ALL(t_kstack, t_psr, t_pc, t_npc, g2) + + /* See if we are in the trap window. */ + mov 1, %t_twinmask + sll %t_twinmask, %t_psr, %t_twinmask ! t_twinmask = (1 << psr) + andcc %t_twinmask, %t_wim, %g0 + beq 1f ! in trap window, clean up + nop + + /*------------------------------------------------- + * Spill , adjust %wim and go. + */ + srl %t_wim, 0x1, %g2 ! begin computation of new %wim + + set (CFG_SPARC_NWINDOWS-1), %g3 !NWINDOWS-1 + + sll %t_wim, %g3, %t_wim ! NWINDOWS-1 + or %t_wim, %g2, %g2 + and %g2, 0xff, %g2 + + save %g0, %g0, %g0 ! get in window to be saved + + /* Set new %wim value */ + wr %g2, 0x0, %wim + + /* Save the kernel window onto the corresponding stack. */ + RW_STORE(sp) + + restore %g0, %g0, %g0 + /*-------------------------------------------------*/ + +1: + /* Trap from kernel with a window available. + * Just do it... + */ + jmpl %t_retpc + 0x8, %g0 ! return to caller + mov %t_kstack, %sp ! jump onto new stack + +#define twin_tmp1 l4 +#define glob_tmp g4 +#define curptr g6 +ret_trap_entry: + wr %t_psr, 0x0, %psr ! enable nesting again, clear ET + + /* Will the rett land us in the invalid window? */ + mov 2, %g1 + sll %g1, %t_psr, %g1 + + set CFG_SPARC_NWINDOWS, %g2 !NWINDOWS + + srl %g1, %g2, %g2 + or %g1, %g2, %g1 + rd %wim, %g2 + andcc %g2, %g1, %g0 + be 1f ! Nope, just return from the trap + sll %g2, 0x1, %g1 + + /* We have to grab a window before returning. */ + set (CFG_SPARC_NWINDOWS-1), %g3 !NWINDOWS-1 + + srl %g2, %g3, %g2 + or %g1, %g2, %g1 + and %g1, 0xff, %g1 + + wr %g1, 0x0, %wim + + /* Grrr, make sure we load from the right %sp... */ + PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1) + + restore %g0, %g0, %g0 + RW_LOAD(sp) + b 2f + save %g0, %g0, %g0 + + /* Reload the entire frame in case this is from a + * kernel system call or whatever... + */ +1: + PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1) +2: + wr %t_psr, 0x0, %psr + nop; + nop; + nop + + jmp %t_pc + rett %t_npc + +/* This is called from relocated C-code. + * It resets the system by jumping to _start + */ +_reset_reloc: + set start, %l0 + call %l0 + nop diff --git a/include/asm-sparc/arch-leon2/asi.h b/include/asm-sparc/arch-leon2/asi.h new file mode 100644 index 000000000..38fdd5c8c --- /dev/null +++ b/include/asm-sparc/arch-leon2/asi.h @@ -0,0 +1,36 @@ +/* asi.h: Address Space Identifier values for the LEON2 sparc. + * + * Copyright (C) 2008 Daniel Hellstrom (daniel@gaisler.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _LEON2_ASI_H +#define _LEON2_ASI_H + +#define ASI_CACHEMISS 0x01 /* Force D-Cache miss on load (lda) */ +#define ASI_M_FLUSH_PROBE 0x03 /* MMU Flush/Probe */ +#define ASI_IFLUSH 0x05 /* Flush I-Cache */ +#define ASI_DFLUSH 0x06 /* Flush D-Cache */ +#define ASI_BYPASS 0x1c /* Bypass MMU (Physical address) */ +#define ASI_MMUFLUSH 0x18 /* FLUSH TLB */ +#define ASI_M_MMUREGS 0x19 /* READ/Write MMU Registers */ + +#endif /* _LEON2_ASI_H */ diff --git a/include/asm-sparc/leon.h b/include/asm-sparc/leon.h index 6036fb5e7..f7175eee9 100644 --- a/include/asm-sparc/leon.h +++ b/include/asm-sparc/leon.h @@ -27,6 +27,10 @@ #include +#elif defined(CONFIG_LEON2) + +#include + #else #error Unknown LEON processor diff --git a/include/asm-sparc/leon2.h b/include/asm-sparc/leon2.h new file mode 100644 index 000000000..fa55cade0 --- /dev/null +++ b/include/asm-sparc/leon2.h @@ -0,0 +1,236 @@ +/* LEON2 header file. LEON2 is a SOC processor. + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __LEON2_H__ +#define __LEON2_H__ + +#ifdef CONFIG_LEON2 + +/* LEON 2 I/O register definitions */ +#define LEON2_PREGS 0x80000000 +#define LEON2_MCFG1 0x00 +#define LEON2_MCFG2 0x04 +#define LEON2_ECTRL 0x08 +#define LEON2_FADDR 0x0C +#define LEON2_MSTAT 0x10 +#define LEON2_CCTRL 0x14 +#define LEON2_PWDOWN 0x18 +#define LEON2_WPROT1 0x1C +#define LEON2_WPROT2 0x20 +#define LEON2_LCONF 0x24 +#define LEON2_TCNT0 0x40 +#define LEON2_TRLD0 0x44 +#define LEON2_TCTRL0 0x48 +#define LEON2_TCNT1 0x50 +#define LEON2_TRLD1 0x54 +#define LEON2_TCTRL1 0x58 +#define LEON2_SCNT 0x60 +#define LEON2_SRLD 0x64 +#define LEON2_UART0 0x70 +#define LEON2_UDATA0 0x70 +#define LEON2_USTAT0 0x74 +#define LEON2_UCTRL0 0x78 +#define LEON2_USCAL0 0x7C +#define LEON2_UART1 0x80 +#define LEON2_UDATA1 0x80 +#define LEON2_USTAT1 0x84 +#define LEON2_UCTRL1 0x88 +#define LEON2_USCAL1 0x8C +#define LEON2_IMASK 0x90 +#define LEON2_IPEND 0x94 +#define LEON2_IFORCE 0x98 +#define LEON2_ICLEAR 0x9C +#define LEON2_IOREG 0xA0 +#define LEON2_IODIR 0xA4 +#define LEON2_IOICONF 0xA8 +#define LEON2_IPEND2 0xB0 +#define LEON2_IMASK2 0xB4 +#define LEON2_ISTAT2 0xB8 +#define LEON2_ICLEAR2 0xBC + +#ifndef __ASSEMBLER__ +/* + * Structure for LEON memory mapped registers. + * + * Source: Section 6.1 - On-chip registers + * + * NOTE: There is only one of these structures per CPU, its base address + * is 0x80000000, and the variable LEON_REG is placed there by the + * linkcmds file. + */ +typedef struct { + volatile unsigned int Memory_Config_1; + volatile unsigned int Memory_Config_2; + volatile unsigned int Edac_Control; + volatile unsigned int Failed_Address; + volatile unsigned int Memory_Status; + volatile unsigned int Cache_Control; + volatile unsigned int Power_Down; + volatile unsigned int Write_Protection_1; + volatile unsigned int Write_Protection_2; + volatile unsigned int Leon_Configuration; + volatile unsigned int dummy2; + volatile unsigned int dummy3; + volatile unsigned int dummy4; + volatile unsigned int dummy5; + volatile unsigned int dummy6; + volatile unsigned int dummy7; + volatile unsigned int Timer_Counter_1; + volatile unsigned int Timer_Reload_1; + volatile unsigned int Timer_Control_1; + volatile unsigned int Watchdog; + volatile unsigned int Timer_Counter_2; + volatile unsigned int Timer_Reload_2; + volatile unsigned int Timer_Control_2; + volatile unsigned int dummy8; + volatile unsigned int Scaler_Counter; + volatile unsigned int Scaler_Reload; + volatile unsigned int dummy9; + volatile unsigned int dummy10; + volatile unsigned int UART_Channel_1; + volatile unsigned int UART_Status_1; + volatile unsigned int UART_Control_1; + volatile unsigned int UART_Scaler_1; + volatile unsigned int UART_Channel_2; + volatile unsigned int UART_Status_2; + volatile unsigned int UART_Control_2; + volatile unsigned int UART_Scaler_2; + volatile unsigned int Interrupt_Mask; + volatile unsigned int Interrupt_Pending; + volatile unsigned int Interrupt_Force; + volatile unsigned int Interrupt_Clear; + volatile unsigned int PIO_Data; + volatile unsigned int PIO_Direction; + volatile unsigned int PIO_Interrupt; +} LEON2_regs; + +typedef struct { + volatile unsigned int UART_Channel; + volatile unsigned int UART_Status; + volatile unsigned int UART_Control; + volatile unsigned int UART_Scaler; +} LEON2_Uart_regs; + +#endif + +/* + * The following constants are intended to be used ONLY in assembly + * language files. + * + * NOTE: The intended style of usage is to load the address of LEON REGS + * into a register and then use these as displacements from + * that register. + */ +#define LEON_REG_MEMCFG1_OFFSET 0x00 +#define LEON_REG_MEMCFG2_OFFSET 0x04 +#define LEON_REG_EDACCTRL_OFFSET 0x08 +#define LEON_REG_FAILADDR_OFFSET 0x0C +#define LEON_REG_MEMSTATUS_OFFSET 0x10 +#define LEON_REG_CACHECTRL_OFFSET 0x14 +#define LEON_REG_POWERDOWN_OFFSET 0x18 +#define LEON_REG_WRITEPROT1_OFFSET 0x1C +#define LEON_REG_WRITEPROT2_OFFSET 0x20 +#define LEON_REG_LEONCONF_OFFSET 0x24 +#define LEON_REG_UNIMPLEMENTED_2_OFFSET 0x28 +#define LEON_REG_UNIMPLEMENTED_3_OFFSET 0x2C +#define LEON_REG_UNIMPLEMENTED_4_OFFSET 0x30 +#define LEON_REG_UNIMPLEMENTED_5_OFFSET 0x34 +#define LEON_REG_UNIMPLEMENTED_6_OFFSET 0x38 +#define LEON_REG_UNIMPLEMENTED_7_OFFSET 0x3C +#define LEON_REG_TIMERCNT1_OFFSET 0x40 +#define LEON_REG_TIMERLOAD1_OFFSET 0x44 +#define LEON_REG_TIMERCTRL1_OFFSET 0x48 +#define LEON_REG_WDOG_OFFSET 0x4C +#define LEON_REG_TIMERCNT2_OFFSET 0x50 +#define LEON_REG_TIMERLOAD2_OFFSET 0x54 +#define LEON_REG_TIMERCTRL2_OFFSET 0x58 +#define LEON_REG_UNIMPLEMENTED_8_OFFSET 0x5C +#define LEON_REG_SCALERCNT_OFFSET 0x60 +#define LEON_REG_SCALER_LOAD_OFFSET 0x64 +#define LEON_REG_UNIMPLEMENTED_9_OFFSET 0x68 +#define LEON_REG_UNIMPLEMENTED_10_OFFSET 0x6C +#define LEON_REG_UARTDATA1_OFFSET 0x70 +#define LEON_REG_UARTSTATUS1_OFFSET 0x74 +#define LEON_REG_UARTCTRL1_OFFSET 0x78 +#define LEON_REG_UARTSCALER1_OFFSET 0x7C +#define LEON_REG_UARTDATA2_OFFSET 0x80 +#define LEON_REG_UARTSTATUS2_OFFSET 0x84 +#define LEON_REG_UARTCTRL2_OFFSET 0x88 +#define LEON_REG_UARTSCALER2_OFFSET 0x8C +#define LEON_REG_IRQMASK_OFFSET 0x90 +#define LEON_REG_IRQPEND_OFFSET 0x94 +#define LEON_REG_IRQFORCE_OFFSET 0x98 +#define LEON_REG_IRQCLEAR_OFFSET 0x9C +#define LEON_REG_PIODATA_OFFSET 0xA0 +#define LEON_REG_PIODIR_OFFSET 0xA4 +#define LEON_REG_PIOIRQ_OFFSET 0xA8 +#define LEON_REG_SIM_RAM_SIZE_OFFSET 0xF4 +#define LEON_REG_SIM_ROM_SIZE_OFFSET 0xF8 + +/* + * Interrupt Sources + * + * The interrupt source numbers directly map to the trap type and to + * the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask, + * and the Interrupt Pending Registers. + */ +#define LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR 1 +#define LEON_INTERRUPT_UART_1_RX_TX 2 +#define LEON_INTERRUPT_UART_0_RX_TX 3 +#define LEON_INTERRUPT_EXTERNAL_0 4 +#define LEON_INTERRUPT_EXTERNAL_1 5 +#define LEON_INTERRUPT_EXTERNAL_2 6 +#define LEON_INTERRUPT_EXTERNAL_3 7 +#define LEON_INTERRUPT_TIMER1 8 +#define LEON_INTERRUPT_TIMER2 9 +#define LEON_INTERRUPT_EMPTY1 10 +#define LEON_INTERRUPT_EMPTY2 11 +#define LEON_INTERRUPT_OPEN_ETH 12 +#define LEON_INTERRUPT_EMPTY4 13 +#define LEON_INTERRUPT_EMPTY5 14 +#define LEON_INTERRUPT_EMPTY6 15 + +/* Timer Bits */ +#define LEON2_TIMER_CTRL_EN 0x1 /* Timer enable */ +#define LEON2_TIMER_CTRL_RS 0x2 /* Timer reStart */ +#define LEON2_TIMER_CTRL_LD 0x4 /* Timer reLoad */ +#define LEON2_TIMER1_IRQNO 8 /* Timer 1 IRQ number */ +#define LEON2_TIMER2_IRQNO 9 /* Timer 2 IRQ number */ +#define LEON2_TIMER1_IE (1< Date: Wed, 26 Mar 2008 23:26:48 +0100 Subject: [PATCH 07/11] SPARC/LEON3: added support for GR-XC3S-1500 board with GRLIB template design. See www.gaisler.com for board information. Signed-off-by: Daniel Hellstrom --- MAKEALL | 2 +- Makefile | 4 + board/gaisler/gr_xc3s_1500/Makefile | 52 ++++ board/gaisler/gr_xc3s_1500/config.mk | 34 +++ board/gaisler/gr_xc3s_1500/gr_xc3s_1500.c | 39 +++ board/gaisler/gr_xc3s_1500/u-boot.lds | 162 +++++++++++ include/configs/gr_xc3s_1500.h | 321 ++++++++++++++++++++++ 7 files changed, 613 insertions(+), 1 deletion(-) create mode 100644 board/gaisler/gr_xc3s_1500/Makefile create mode 100644 board/gaisler/gr_xc3s_1500/config.mk create mode 100644 board/gaisler/gr_xc3s_1500/gr_xc3s_1500.c create mode 100644 board/gaisler/gr_xc3s_1500/u-boot.lds create mode 100644 include/configs/gr_xc3s_1500.h diff --git a/MAKEALL b/MAKEALL index 9a2afe66f..6aa9a0484 100755 --- a/MAKEALL +++ b/MAKEALL @@ -727,7 +727,7 @@ LIST_sh=" \ ## SPARC Systems ######################################################################### -LIST_sparc="" +LIST_sparc="gr_xc3s_1500" #----------------------------------------------------------------------- diff --git a/Makefile b/Makefile index c97473f94..6afe4565e 100644 --- a/Makefile +++ b/Makefile @@ -2902,6 +2902,10 @@ r2dplus_config : unconfig ## LEON3 ######################################################################### +# Gaisler GR-XC3S-1500 board +gr_xc3s_1500_config : unconfig + @$(MKCONFIG) $(@:_config=) sparc leon3 gr_xc3s_1500 gaisler + ######################################################################### ## LEON2 ######################################################################### diff --git a/board/gaisler/gr_xc3s_1500/Makefile b/board/gaisler/gr_xc3s_1500/Makefile new file mode 100644 index 000000000..d58f50d99 --- /dev/null +++ b/board/gaisler/gr_xc3s_1500/Makefile @@ -0,0 +1,52 @@ + +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +#flash.o +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/gaisler/gr_xc3s_1500/config.mk b/board/gaisler/gr_xc3s_1500/config.mk new file mode 100644 index 000000000..35cbc1bb2 --- /dev/null +++ b/board/gaisler/gr_xc3s_1500/config.mk @@ -0,0 +1,34 @@ +# +# (C) Copyright 2007 +# Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# GR-XC3S-1500 board +# + +# U-BOOT IN FLASH +TEXT_BASE = 0x00000000 + +# U-BOOT IN RAM +#TEXT_BASE = 0x40000000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/gaisler/gr_xc3s_1500/gr_xc3s_1500.c b/board/gaisler/gr_xc3s_1500/gr_xc3s_1500.c new file mode 100644 index 000000000..1ee702481 --- /dev/null +++ b/board/gaisler/gr_xc3s_1500/gr_xc3s_1500.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2007 + * Daniel Hellstrom, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +long int initdram(int board_type) +{ + return 1; +} + +int checkboard(void) +{ + puts("Board: GR-XC3S-1500\n"); + return 0; +} + +int misc_init_r(void) +{ + return 0; +} diff --git a/board/gaisler/gr_xc3s_1500/u-boot.lds b/board/gaisler/gr_xc3s_1500/u-boot.lds new file mode 100644 index 000000000..3848c684a --- /dev/null +++ b/board/gaisler/gr_xc3s_1500/u-boot.lds @@ -0,0 +1,162 @@ +/* Linker script for Gaisler Research AB's GR-XC3S-1500 board + * with template design. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) +SECTIONS +{ + +/* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + + .text : { + _load_addr = .; + _text = .; + + *(.start) + cpu/leon3/start.o (.text) +/* 8k is the same as the PROM offset from end of main memory, (CFG_PROM_SIZE) */ + . = ALIGN(8192); +/* PROM CODE, Will be relocated to the end of memory, + * no global data accesses please. + */ + __prom_start = .; + *(.prom.pgt) + *(.prom.data) + *(.prom.text) + . = ALIGN(16); + __prom_end = .; + *(.text) + *(.fixup) + *(.gnu.warning) +/* *(.got1)*/ + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.eh_frame) + } + . = ALIGN(4); + _etext = .; + + /* CMD Table */ + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + . = ALIGN(4); + __u_boot_cmd_end = .; + + .data : + { + *(.data) + *(.data1) + *(.data.rel) + *(.data.rel.*) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = ALIGN(4); + __got_start = .; + .got : { + *(.got) +/* *(.data.rel) + *(.data.rel.local)*/ + . = ALIGN(16); + } + __got_end = .; + +/* .data.rel : { } */ + + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(16); /* to speed clearing of bss up */ + } + __bss_end = . ; + _end = . ; + PROVIDE (end = .); + +/* Relocated into main memory */ + + /* Start of main memory */ + /*. = 0x40000000;*/ + + .stack (NOLOAD) : { *(.stack) } + + /* PROM CODE */ + + /* global data in RAM passed to kernel after booting */ + + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + +} diff --git a/include/configs/gr_xc3s_1500.h b/include/configs/gr_xc3s_1500.h new file mode 100644 index 000000000..1fdef3d4a --- /dev/null +++ b/include/configs/gr_xc3s_1500.h @@ -0,0 +1,321 @@ +/* Configuration header file for Gaisler GR-XC3S-1500 + * spartan board. + * + * (C) Copyright 2003-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_LEON3 /* This is an LEON3 CPU */ +#define CONFIG_LEON 1 /* This is an LEON CPU */ +#define CONFIG_GRXC3S1500 1 /* ... on GR-XC3S-1500 board */ + +/* CPU / AMBA BUS configuration */ +#define CONFIG_SYS_CLK_FREQ 40000000 /* 40MHz */ + +/* Number of SPARC register windows */ +#define CFG_SPARC_NWINDOWS 8 + +/* + * Serial console configuration + */ +#define CONFIG_BAUDRATE 38400 /* ... at 38400 bps */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } + +/* Partitions */ +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION + +/* + * Supported commands + */ +#include + +#define CONFIG_CMD_REGINFO +#define CONFIG_CMD_AMBAPP +#define CONFIG_CMD_PING +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_IRQ + +/* + * Autobooting + */ +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ + +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "nfsargs=setenv bootargs console=ttyS0,38400 root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs console=ttyS0,${baudrate} root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "net_nfs=tftp 40000000 ${bootfile};run nfsargs addip;bootm\0" \ + "scratch=40200000\0" \ + "getkernel=tftpboot \$\(scratch\)\ \$\(bootfile\)\0" \ + "bootargs=console=ttyS0,38400 root=/dev/nfs rw nfsroot=192.168.0.20:/export/rootfs ip=192.168.0.206:192.168.0.20:192.168.0.1:255.255.255.0:grxc3s1500_daniel:eth0\0" \ + "" + +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_GATEWAYIP 192.168.0.1 +#define CONFIG_SERVERIP 192.168.0.20 +#define CONFIG_IPADDR 192.168.0.206 +#define CONFIG_ROOTPATH /export/rootfs +#define CONFIG_HOSTNAME grxc3s1500 +#define CONFIG_BOOTFILE /uImage + +#define CONFIG_BOOTCOMMAND "run flash_self" + +/* Memory MAP + * + * Flash: + * |--------------------------------| + * | 0x00000000 Text & Data & BSS | * + * | for Monitor | * + * | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| * + * | UNUSED / Growth | * 256kb + * |--------------------------------| + * | 0x00050000 Base custom area | * + * | kernel / FS | * + * | | * Rest of Flash + * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + * | END-0x00008000 Environment | * 32kb + * |--------------------------------| + * + * + * + * Main Memory: + * |--------------------------------| + * | UNUSED / scratch area | + * | | + * | | + * | | + * | | + * |--------------------------------| + * | Monitor .Text / .DATA / .BSS | * 256kb + * | Relocated! | * + * |--------------------------------| + * | Monitor Malloc | * 128kb (contains relocated environment) + * |--------------------------------| + * | Monitor/kernel STACK | * 64kb + * |--------------------------------| + * | Page Table for MMU systems | * 2k + * |--------------------------------| + * | PROM Code accessed from Linux | * 6kb-128b + * |--------------------------------| + * | Global data (avail from kernel)| * 128b + * |--------------------------------| + * + */ + +/* + * Flash configuration (8,16 or 32 MB) + * TEXT base always at 0xFFF00000 + * ENV_ADDR always at 0xFFF40000 + * FLASH_BASE at 0xFC000000 for 64 MB + * 0xFE000000 for 32 MB + * 0xFF000000 for 16 MB + * 0xFF800000 for 8 MB + */ +/*#define CFG_NO_FLASH 1*/ +#define CFG_FLASH_BASE 0x00000000 +#define CFG_FLASH_SIZE 0x00800000 + +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 128 KB sectors */ +#define CFG_MAX_FLASH_SECT 64 /* max num of sects on one chip */ +#define CFG_MAX_FLASH_BANKS 1 /* max num of memory banks */ + +#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */ +#define CFG_FLASH_LOCK_TOUT 5 /* Timeout for Flash Set Lock Bit (in ms) */ +#define CFG_FLASH_UNLOCK_TOUT 10000 /* Timeout for Flash Clear Lock Bits (in ms) */ +#define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */ + +/*** CFI CONFIG ***/ +#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +/* Bypass cache when reading regs from flash memory */ +#define CFG_FLASH_CFI_BYPASS_READ +/* Buffered writes (32byte/go) instead of single accesses */ +#define CFG_FLASH_USE_BUFFER_WRITE + +/* + * Environment settings + */ +/*#define CFG_ENV_IS_NOWHERE 1*/ +#define CFG_ENV_IS_IN_FLASH 1 +/* CFG_ENV_ADDR need to be at sector boundary */ +#define CFG_ENV_SIZE 0x8000 +#define CFG_ENV_SECT_SIZE 0x20000 +#define CFG_ENV_ADDR (CFG_FLASH_BASE+CFG_FLASH_SIZE-CFG_ENV_SECT_SIZE) +#define CONFIG_ENV_OVERWRITE 1 + +/* + * Memory map + */ +#define CFG_SDRAM_BASE 0x40000000 +#define CFG_SDRAM_SIZE 0x4000000 +#define CFG_SDRAM_END (CFG_SDRAM_BASE+CFG_SDRAM_SIZE) + +/* no SRAM available */ +#undef CFG_SRAM_BASE +#undef CFG_SRAM_SIZE + +/* Always Run U-Boot from SDRAM */ +#define CFG_RAM_BASE CFG_SDRAM_BASE +#define CFG_RAM_SIZE CFG_SDRAM_SIZE +#define CFG_RAM_END CFG_SDRAM_END + +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_RAM_END - CFG_GBL_DATA_SIZE) + +#define CFG_PROM_SIZE (8192-CFG_GBL_DATA_SIZE) +#define CFG_PROM_OFFSET (CFG_GBL_DATA_OFFSET-CFG_PROM_SIZE) + +#define CFG_INIT_SP_OFFSET (CFG_PROM_OFFSET-32) +#define CFG_STACK_SIZE (0x10000-32) + +#define CFG_MONITOR_BASE TEXT_BASE +#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) +# define CFG_RAMBOOT 1 +#endif + +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +#define CFG_MALLOC_END (CFG_INIT_SP_OFFSET-CFG_STACK_SIZE) +#define CFG_MALLOC_BASE (CFG_MALLOC_END-CFG_MALLOC_LEN) + +/* relocated monitor area */ +#define CFG_RELOC_MONITOR_MAX_END CFG_MALLOC_BASE +#define CFG_RELOC_MONITOR_BASE (CFG_RELOC_MONITOR_MAX_END-CFG_MONITOR_LEN) + +/* make un relocated address from relocated address */ +#define UN_RELOC(address) (address-(CFG_RELOC_MONITOR_BASE-TEXT_BASE)) + +/* + * Ethernet configuration + */ +#define CONFIG_GRETH 1 +#define CONFIG_NET_MULTI 1 + +/* Default GRETH Ethernet HARDWARE address */ +#define GRETH_HWADDR_0 0x00 +#define GRETH_HWADDR_1 0x00 +#define GRETH_HWADDR_2 0x7a +#define GRETH_HWADDR_3 0xcc +#define GRETH_HWADDR_4 0x00 +#define GRETH_HWADDR_5 0x12 + +#define CONFIG_ETHADDR 00:00:7a:cc:00:12 +#define CONFIG_PHY_ADDR 0x00 + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if defined(CONFIG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00100000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00f00000 /* 1 ... 15 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/* + * Various low-level settings + */ + +/*----------------------------------------------------------------------- + * USB stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_USB_CLOCK 0x0001BBBB +#define CONFIG_USB_CONFIG 0x00005000 + +/***** Gaisler GRLIB IP-Cores Config ********/ + +/* AMBA Plug & Play info display on startup */ +/*#define CFG_AMBAPP_PRINT_ON_STARTUP*/ + +#define CFG_GRLIB_SDRAM 0 + +/* See, GRLIB Docs (grip.pdf) on how to set up + * These the memory controller registers. + */ +#define CFG_GRLIB_MEMCFG1 (0x000000ff | (1<<11)) +#define CFG_GRLIB_MEMCFG2 0x82206000 +#define CFG_GRLIB_MEMCFG3 0x00136000 + +#define CFG_GRLIB_FT_MEMCFG1 (0x000000ff | (1<<11)) +#define CFG_GRLIB_FT_MEMCFG2 0x82206000 +#define CFG_GRLIB_FT_MEMCFG3 0x00136000 + +/* no DDR controller */ +#define CFG_GRLIB_DDR_CFG 0x00000000 + +/* no DDR2 Controller */ +#define CFG_GRLIB_DDR2_CFG1 0x00000000 +#define CFG_GRLIB_DDR2_CFG3 0x00000000 + +/* Calculate scaler register value from default baudrate */ +#define CFG_GRLIB_APBUART_SCALER \ + ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10) + +/* Identification string */ +#define CONFIG_IDENT_STRING "GAISLER LEON3 GR-XC3S-1500" + +/* default kernel command line */ +#define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0" + +#endif /* __CONFIG_H */ From 823edd8a66ed50af5aaba0c79567f67061e4d79a Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 28 Mar 2008 10:06:52 +0100 Subject: [PATCH 08/11] SPARC/LEON3: added support for Gaisler GRSIM/TSIM2 SPARC/LEON3 simulatorn. See www.gaisler.com for information. Signed-off-by: Daniel Hellstrom --- MAKEALL | 2 +- Makefile | 4 + board/gaisler/grsim/Makefile | 50 +++++ board/gaisler/grsim/config.mk | 34 ++++ board/gaisler/grsim/grsim.c | 43 +++++ board/gaisler/grsim/u-boot.lds | 161 ++++++++++++++++ include/configs/grsim.h | 340 +++++++++++++++++++++++++++++++++ 7 files changed, 633 insertions(+), 1 deletion(-) create mode 100644 board/gaisler/grsim/Makefile create mode 100644 board/gaisler/grsim/config.mk create mode 100644 board/gaisler/grsim/grsim.c create mode 100644 board/gaisler/grsim/u-boot.lds create mode 100644 include/configs/grsim.h diff --git a/MAKEALL b/MAKEALL index 6aa9a0484..1626705ad 100755 --- a/MAKEALL +++ b/MAKEALL @@ -727,7 +727,7 @@ LIST_sh=" \ ## SPARC Systems ######################################################################### -LIST_sparc="gr_xc3s_1500" +LIST_sparc="gr_xc3s_1500 grsim" #----------------------------------------------------------------------- diff --git a/Makefile b/Makefile index 6afe4565e..9601f3beb 100644 --- a/Makefile +++ b/Makefile @@ -2906,6 +2906,10 @@ r2dplus_config : unconfig gr_xc3s_1500_config : unconfig @$(MKCONFIG) $(@:_config=) sparc leon3 gr_xc3s_1500 gaisler +# Gaisler LEON3 GRSIM simulator +grsim_config : unconfig + @$(MKCONFIG) $(@:_config=) sparc leon3 grsim gaisler + ######################################################################### ## LEON2 ######################################################################### diff --git a/board/gaisler/grsim/Makefile b/board/gaisler/grsim/Makefile new file mode 100644 index 000000000..629510956 --- /dev/null +++ b/board/gaisler/grsim/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2003-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/gaisler/grsim/config.mk b/board/gaisler/grsim/config.mk new file mode 100644 index 000000000..81cd415e8 --- /dev/null +++ b/board/gaisler/grsim/config.mk @@ -0,0 +1,34 @@ +# +# (C) Copyright 2007 +# Daniel Hellstrom, Gaisler Research, daniel@gaisler.com +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# GRSIM simulating a LEON3 GR-XC3S-1500 board +# + +# U-BOOT IN FLASH +TEXT_BASE = 0x00000000 + +# U-BOOT IN RAM +#TEXT_BASE = 0x40000000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/gaisler/grsim/grsim.c b/board/gaisler/grsim/grsim.c new file mode 100644 index 000000000..70a2f23c5 --- /dev/null +++ b/board/gaisler/grsim/grsim.c @@ -0,0 +1,43 @@ +/* GRSIM/TSIM board + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include + +long int initdram(int board_type) +{ + return 1; +} + +int checkboard(void) +{ + puts("Board: GRSIM/TSIM\n"); + return 0; +} + +int misc_init_r(void) +{ + return 0; +} diff --git a/board/gaisler/grsim/u-boot.lds b/board/gaisler/grsim/u-boot.lds new file mode 100644 index 000000000..1e8bb6957 --- /dev/null +++ b/board/gaisler/grsim/u-boot.lds @@ -0,0 +1,161 @@ +/* Linker script for Gaisler Research AB's GRSIM LEON3 simulator. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) +SECTIONS +{ + +/* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + + .text : { + _load_addr = .; + _text = .; + + *(.start) + cpu/leon3/start.o (.text) +/* 8k is the same as the PROM offset from end of main memory, (CFG_PROM_SIZE) */ + . = ALIGN(8192); +/* PROM CODE, Will be relocated to the end of memory, + * no global data accesses please. + */ + __prom_start = .; + *(.prom.pgt) + *(.prom.data) + *(.prom.text) + . = ALIGN(16); + __prom_end = .; + *(.text) + *(.fixup) + *(.gnu.warning) +/* *(.got1)*/ + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.eh_frame) + } + . = ALIGN(4); + _etext = .; + + /* CMD Table */ + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + . = ALIGN(4); + __u_boot_cmd_end = .; + + .data : + { + *(.data) + *(.data1) + *(.data.rel) + *(.data.rel.*) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = ALIGN(4); + __got_start = .; + .got : { + *(.got) +/* *(.data.rel) + *(.data.rel.local)*/ + . = ALIGN(16); + } + __got_end = .; + +/* .data.rel : { } */ + + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(16); /* to speed clearing of bss up */ + } + __bss_end = . ; + _end = . ; + PROVIDE (end = .); + +/* Relocated into main memory */ + + /* Start of main memory */ + /*. = 0x40000000;*/ + + .stack (NOLOAD) : { *(.stack) } + + /* PROM CODE */ + + /* global data in RAM passed to kernel after booting */ + + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + +} diff --git a/include/configs/grsim.h b/include/configs/grsim.h new file mode 100644 index 000000000..60ad396f5 --- /dev/null +++ b/include/configs/grsim.h @@ -0,0 +1,340 @@ +/* Configuration header file for LEON3 GRSIM, trying to be similar + * to Gaisler's GR-XC3S-1500 board. + * + * (C) Copyright 2003-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +/* + * High Level Configuration Options + * (easy to change) + * + * Select between TSIM or GRSIM by setting CONFIG_GRSIM or CONFIG_TSIM to 1. + * + * TSIM command + * tsim-leon3 -sdram 0 -ram 32000 -rom 8192 -mmu + * + */ + +#define CONFIG_LEON3 /* This is an LEON3 CPU */ +#define CONFIG_LEON 1 /* This is an LEON CPU */ +#define CONFIG_GRSIM 0 /* ... not running on GRSIM */ +#define CONFIG_TSIM 1 /* ... running on TSIM */ + +/* CPU / AMBA BUS configuration */ +#define CONFIG_SYS_CLK_FREQ 40000000 /* 40MHz */ + +/* Number of SPARC register windows */ +#define CFG_SPARC_NWINDOWS 8 + +/* + * Serial console configuration + */ +#define CONFIG_BAUDRATE 38400 /* ... at 38400 bps */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } + +/* Partitions */ +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION + +/* + * Supported commands + */ +#define CONFIG_CMD_AMBAPP /* AMBA Plyg&Play information */ +#define CONFIG_CMD_AUTOSCRIPT /* Autoscript Support */ +#define CONFIG_CMD_BDI /* bdinfo */ +#define CONFIG_CMD_CONSOLE /* coninfo */ +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_ECHO /* echo arguments */ +#define CONFIG_CMD_FPGA /* FPGA configuration Support */ +#define CONFIG_CMD_IRQ +#define CONFIG_CMD_ITEST /* Integer (and string) test */ +#define CONFIG_CMD_LOADB /* loadb */ +#define CONFIG_CMD_LOADS /* loads */ +#define CONFIG_CMD_MISC /* Misc functions like sleep etc */ +#define CONFIG_CMD_NET /* bootp, tftpboot, rarpboot */ +#define CONFIG_CMD_REGINFO +#define CONFIG_CMD_RUN /* run command in env variable */ +#define CONFIG_CMD_SETGETDCR /* DCR support on 4xx */ +#define CONFIG_CMD_XIMG /* Load part of Multi Image */ + +/* + * Autobooting + */ +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ + +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS +/*#define CFG_HUSH_PARSER 0*/ +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "net_nfs=tftp 40000000 ${bootfile};run nfsargs addip;bootm\0" \ + "rootpath=/export/roofs\0" \ + "scratch=40000000\0" \ + "getkernel=tftpboot \$\(scratch\)\ \$\(bootfile\)\0" \ + "ethaddr=00:00:7A:CC:00:12\0" \ + "bootargs=console=ttyS0,38400" \ + "" +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_GATEWAYIP 192.168.0.1 +#define CONFIG_SERVERIP 192.168.0.81 +#define CONFIG_IPADDR 192.168.0.80 +#define CONFIG_ROOTPATH /export/rootfs +#define CONFIG_HOSTNAME grxc3s1500 +#define CONFIG_BOOTFILE /uImage + +#define CONFIG_BOOTCOMMAND "run flash_self" + +/* Memory MAP + * + * Flash: + * |--------------------------------| + * | 0x00000000 Text & Data & BSS | * + * | for Monitor | * + * | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| * + * | UNUSED / Growth | * 256kb + * |--------------------------------| + * | 0x00050000 Base custom area | * + * | kernel / FS | * + * | | * Rest of Flash + * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + * | END-0x00008000 Environment | * 32kb + * |--------------------------------| + * + * + * + * Main Memory: + * |--------------------------------| + * | UNUSED / scratch area | + * | | + * | | + * | | + * | | + * |--------------------------------| + * | Monitor .Text / .DATA / .BSS | * 256kb + * | Relocated! | * + * |--------------------------------| + * | Monitor Malloc | * 128kb (contains relocated environment) + * |--------------------------------| + * | Monitor/kernel STACK | * 64kb + * |--------------------------------| + * | Page Table for MMU systems | * 2k + * |--------------------------------| + * | PROM Code accessed from Linux | * 6kb-128b + * |--------------------------------| + * | Global data (avail from kernel)| * 128b + * |--------------------------------| + * + */ + +/* + * Flash configuration (8,16 or 32 MB) + * TEXT base always at 0xFFF00000 + * ENV_ADDR always at 0xFFF40000 + * FLASH_BASE at 0xFC000000 for 64 MB + * 0xFE000000 for 32 MB + * 0xFF000000 for 16 MB + * 0xFF800000 for 8 MB + */ +#define CFG_NO_FLASH 1 +#define CFG_FLASH_BASE 0x00000000 +#define CFG_FLASH_SIZE 0x00800000 +#define CFG_ENV_SIZE 0x8000 + +#define CFG_ENV_ADDR (CFG_FLASH_BASE+CFG_FLASH_SIZE-CFG_ENV_SIZE) + +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 128 KB sectors */ +#define CFG_MAX_FLASH_SECT 64 /* max num of sects on one chip */ +#define CFG_MAX_FLASH_BANKS 1 /* max num of memory banks */ + +#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */ +#define CFG_FLASH_LOCK_TOUT 5 /* Timeout for Flash Set Lock Bit (in ms) */ +#define CFG_FLASH_UNLOCK_TOUT 10000 /* Timeout for Flash Clear Lock Bits (in ms) */ + +#ifdef ENABLE_FLASH_SUPPORT +/* For use with grsim FLASH emulation extension */ +#define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */ + +#undef CONFIG_FLASH_8BIT /* Flash is 32-bit */ + +/*** CFI CONFIG ***/ +#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +#endif + +/* + * Environment settings + */ +#define CFG_ENV_IS_NOWHERE 1 +/*#define CFG_ENV_IS_IN_FLASH 0*/ +/*#define CFG_ENV_SIZE 0x8000*/ +#define CFG_ENV_SECT_SIZE 0x40000 +#define CONFIG_ENV_OVERWRITE 1 + +/* + * Memory map + */ +#define CFG_SDRAM_BASE 0x40000000 +#define CFG_SDRAM_SIZE 0x02000000 +#define CFG_SDRAM_END (CFG_SDRAM_BASE+CFG_SDRAM_SIZE) + +/* no SRAM available */ +#undef CFG_SRAM_BASE +#undef CFG_SRAM_SIZE + +/* Always Run U-Boot from SDRAM */ +#define CFG_RAM_BASE CFG_SDRAM_BASE +#define CFG_RAM_SIZE CFG_SDRAM_SIZE +#define CFG_RAM_END CFG_SDRAM_END + +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_RAM_END - CFG_GBL_DATA_SIZE) + +#define CFG_PROM_SIZE (8192-CFG_GBL_DATA_SIZE) +#define CFG_PROM_OFFSET (CFG_GBL_DATA_OFFSET-CFG_PROM_SIZE) + +#define CFG_INIT_SP_OFFSET (CFG_PROM_OFFSET-32) +#define CFG_STACK_SIZE (0x10000-32) + +#define CFG_MONITOR_BASE TEXT_BASE +#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) +# define CFG_RAMBOOT 1 +#endif + +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +#define CFG_MALLOC_END (CFG_INIT_SP_OFFSET-CFG_STACK_SIZE) +#define CFG_MALLOC_BASE (CFG_MALLOC_END-CFG_MALLOC_LEN) + +/* relocated monitor area */ +#define CFG_RELOC_MONITOR_MAX_END CFG_MALLOC_BASE +#define CFG_RELOC_MONITOR_BASE (CFG_RELOC_MONITOR_MAX_END-CFG_MONITOR_LEN) + +/* make un relocated address from relocated address */ +#define UN_RELOC(address) (address-(CFG_RELOC_MONITOR_BASE-TEXT_BASE)) + +/* + * Ethernet configuration + */ +#define CONFIG_GRETH 1 +#define CONFIG_NET_MULTI 1 + +/* Default HARDWARE address */ +#define GRETH_HWADDR_0 0x00 +#define GRETH_HWADDR_1 0x00 +#define GRETH_HWADDR_2 0x7A +#define GRETH_HWADDR_3 0xcc +#define GRETH_HWADDR_4 0x00 +#define GRETH_HWADDR_5 0x12 + +#define CONFIG_ETHADDR 00:00:7a:cc:00:12 + +/* + * Define CONFIG_GRETH_10MBIT to force GRETH at 10Mb/s + */ +/* #define CONFIG_GRETH_10MBIT 1 */ +#define CONFIG_PHY_ADDR 0x00 + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if defined(CONFIG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00100000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00f00000 /* 1 ... 15 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/***** Gaisler GRLIB IP-Cores Config ********/ + +/* AMBA Plug & Play info display on startup */ +/*#define CFG_AMBAPP_PRINT_ON_STARTUP*/ + +#define CFG_GRLIB_SDRAM 0 +#define CFG_GRLIB_MEMCFG1 (0x000000ff | (1<<11)) +#if CONFIG_GRSIM +/* GRSIM configuration */ +#define CFG_GRLIB_MEMCFG2 0x82206000 +#else +/* TSIM configuration */ +#define CFG_GRLIB_MEMCFG2 0x00001820 +#endif +#define CFG_GRLIB_MEMCFG3 0x00136000 + +#define CFG_GRLIB_FT_MEMCFG1 (0x000000ff | (1<<11)) +#define CFG_GRLIB_FT_MEMCFG2 0x82206000 +#define CFG_GRLIB_FT_MEMCFG3 0x00136000 + +/* no DDR controller */ +#define CFG_GRLIB_DDR_CFG 0x00000000 + +/* no DDR2 Controller */ +#define CFG_GRLIB_DDR2_CFG1 0x00000000 +#define CFG_GRLIB_DDR2_CFG3 0x00000000 + +#define CFG_GRLIB_APBUART_SCALER \ + ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10) + +/* default kernel command line */ +#define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0" + +#define CONFIG_IDENT_STRING "Gaisler GRSIM" + +#endif /* __CONFIG_H */ From 6940383d9ec1bfe2f13e339e6f723e8d34af2b12 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Wed, 26 Mar 2008 23:34:47 +0100 Subject: [PATCH 09/11] SPARC/LEON3: added support for Altera NIOS Development kit (STRATIX II Edition) with GRLIB template design. See www.gaisler.com for information. Signed-off-by: Daniel Hellstrom --- MAKEALL | 2 +- Makefile | 5 + board/gaisler/gr_ep2s60/Makefile | 52 ++++ board/gaisler/gr_ep2s60/config.mk | 35 +++ board/gaisler/gr_ep2s60/gr_ep2s60.c | 39 +++ board/gaisler/gr_ep2s60/u-boot.lds | 160 +++++++++++++ include/configs/gr_ep2s60.h | 356 ++++++++++++++++++++++++++++ 7 files changed, 648 insertions(+), 1 deletion(-) create mode 100644 board/gaisler/gr_ep2s60/Makefile create mode 100644 board/gaisler/gr_ep2s60/config.mk create mode 100644 board/gaisler/gr_ep2s60/gr_ep2s60.c create mode 100644 board/gaisler/gr_ep2s60/u-boot.lds create mode 100644 include/configs/gr_ep2s60.h diff --git a/MAKEALL b/MAKEALL index 1626705ad..fb5758900 100755 --- a/MAKEALL +++ b/MAKEALL @@ -727,7 +727,7 @@ LIST_sh=" \ ## SPARC Systems ######################################################################### -LIST_sparc="gr_xc3s_1500 grsim" +LIST_sparc="gr_xc3s_1500 gr_ep2s60 grsim" #----------------------------------------------------------------------- diff --git a/Makefile b/Makefile index 9601f3beb..050972d0a 100644 --- a/Makefile +++ b/Makefile @@ -2906,6 +2906,11 @@ r2dplus_config : unconfig gr_xc3s_1500_config : unconfig @$(MKCONFIG) $(@:_config=) sparc leon3 gr_xc3s_1500 gaisler +# Gaisler GRLIB template design (GPL SPARC/LEON3) for Altera NIOS +# Development board Stratix II edition, FPGA Device EP2S60. +gr_ep2s60_config: unconfig + @$(MKCONFIG) $(@:_config=) sparc leon3 gr_ep2s60 gaisler + # Gaisler LEON3 GRSIM simulator grsim_config : unconfig @$(MKCONFIG) $(@:_config=) sparc leon3 grsim gaisler diff --git a/board/gaisler/gr_ep2s60/Makefile b/board/gaisler/gr_ep2s60/Makefile new file mode 100644 index 000000000..d58f50d99 --- /dev/null +++ b/board/gaisler/gr_ep2s60/Makefile @@ -0,0 +1,52 @@ + +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +#flash.o +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/gaisler/gr_ep2s60/config.mk b/board/gaisler/gr_ep2s60/config.mk new file mode 100644 index 000000000..2ee0957a3 --- /dev/null +++ b/board/gaisler/gr_ep2s60/config.mk @@ -0,0 +1,35 @@ +# +# (C) Copyright 2008 +# Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# Altera NIOS delopment board Stratix II edition, FPGA device EP2S60, +# with GRLIB Template design (GPL Open Source SPARC/LEON3) +# + +# U-BOOT IN FLASH +TEXT_BASE = 0x00000000 + +# U-BOOT IN SDRAM +#TEXT_BASE = 0x40000000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/gaisler/gr_ep2s60/gr_ep2s60.c b/board/gaisler/gr_ep2s60/gr_ep2s60.c new file mode 100644 index 000000000..e8617f075 --- /dev/null +++ b/board/gaisler/gr_ep2s60/gr_ep2s60.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2008 + * Daniel Hellstrom, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +long int initdram(int board_type) +{ + return 1; +} + +int checkboard(void) +{ + puts("Board: EP2S60 GRLIB\n"); + return 0; +} + +int misc_init_r(void) +{ + return 0; +} diff --git a/board/gaisler/gr_ep2s60/u-boot.lds b/board/gaisler/gr_ep2s60/u-boot.lds new file mode 100644 index 000000000..100350d7a --- /dev/null +++ b/board/gaisler/gr_ep2s60/u-boot.lds @@ -0,0 +1,160 @@ +/* Linker script for Gaisler Research AB's Template design + * for Altera NIOS Development board Stratix II Edition, EP2S60 FPGA. + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) +SECTIONS +{ + +/* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + + .text : { + _load_addr = .; + _text = .; + + *(.start) + cpu/leon3/start.o (.text) +/* 8k is the same as the PROM offset from end of main memory, (CFG_PROM_SIZE) */ + . = ALIGN(8192); +/* PROM CODE, Will be relocated to the end of memory, + * no global data accesses please. + */ + __prom_start = .; + *(.prom.pgt) + *(.prom.data) + *(.prom.text) + . = ALIGN(16); + __prom_end = .; + *(.text) + *(.fixup) + *(.gnu.warning) +/* *(.got1)*/ + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.eh_frame) + } + . = ALIGN(4); + _etext = .; + + /* CMD Table */ + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + . = ALIGN(4); + __u_boot_cmd_end = .; + + .data : + { + *(.data) + *(.data1) + *(.data.rel) + *(.data.rel.*) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = ALIGN(4); + __got_start = .; + .got : { + *(.got) +/* *(.data.rel) + *(.data.rel.local)*/ + . = ALIGN(16); + } + __got_end = .; + +/* .data.rel : { } */ + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(16); /* to speed clearing of bss up */ + } + __bss_end = . ; + _end = . ; + PROVIDE (end = .); + +/* Relocated into main memory */ + + /* Start of main memory */ + /*. = 0x40000000;*/ + + .stack (NOLOAD) : { *(.stack) } + + /* PROM CODE */ + + /* global data in RAM passed to kernel after booting */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + +} diff --git a/include/configs/gr_ep2s60.h b/include/configs/gr_ep2s60.h new file mode 100644 index 000000000..710a082e9 --- /dev/null +++ b/include/configs/gr_ep2s60.h @@ -0,0 +1,356 @@ +/* Configuration header file for Gaisler Research AB's Template + * design (GPL Open Source SPARC/LEON3 96MHz) for Altera NIOS + * Development board Stratix II edition, with the FPGA device + * EP2S60. + * + * (C) Copyright 2003-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_LEON3 /* This is an LEON3 CPU */ +#define CONFIG_LEON 1 /* This is an LEON CPU */ +/* Altera NIOS Development board, Stratix II board */ +#define CONFIG_GR_EP2S60 1 + +/* CPU / AMBA BUS configuration */ +#define CONFIG_SYS_CLK_FREQ 96000000 /* 96MHz */ + +/* Number of SPARC register windows */ +#define CFG_SPARC_NWINDOWS 8 + +/* Define this is the GR-2S60-MEZZ mezzanine is available and you + * want to use the USB and GRETH functionality of the board + */ +#undef GR_2S60_MEZZ + +#ifdef GR_2S60_MEZZ +#define USE_GRETH 1 +#define USE_GRUSB 1 +#endif + +/* + * Serial console configuration + */ +#define CONFIG_BAUDRATE 38400 /* ... at 38400 bps */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } + +/* Partitions */ +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION + +/* + * Supported commands + */ +#include + +#define CONFIG_CMD_REGINFO +#define CONFIG_CMD_AMBAPP +#define CONFIG_CMD_PING +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_IRQ + +/* USB support */ +#if USE_GRUSB +#define CONFIG_USB_UHCI +#define CONFIG_CMD_FAT +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_USB +#define CONFIG_USB_STORAGE +/* Enable needed helper functions */ +#define CFG_DEVICE_DEREGISTER /* needs device_deregister */ +#endif + +/* + * Autobooting + */ +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ + +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "nfsargs=setenv bootargs console=ttyS0,38400 root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs console=ttyS0,${baudrate} root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "net_nfs=tftp 40000000 ${bootfile};run nfsargs addip;bootm\0" \ + "scratch=40800000\0" \ + "getkernel=tftpboot \$\(scratch\)\ \$\(bootfile\)\0" \ + "bootargs=console=ttyS0,38400 root=/dev/nfs rw nfsroot=192.168.0.20:/export/rootfs ip=192.168.0.207:192.168.0.20:192.168.0.1:255.255.255.0:ml401:eth0\0" \ + "" + +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_GATEWAYIP 192.168.0.1 +#define CONFIG_SERVERIP 192.168.0.20 +#define CONFIG_IPADDR 192.168.0.207 +#define CONFIG_ROOTPATH /export/rootfs +#define CONFIG_HOSTNAME ml401 +#define CONFIG_BOOTFILE /uImage + +#define CONFIG_BOOTCOMMAND "run flash_self" + +/* Memory MAP + * + * Flash: + * |--------------------------------| + * | 0x00000000 Text & Data & BSS | * + * | for Monitor | * + * | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| * + * | UNUSED / Growth | * 256kb + * |--------------------------------| + * | 0x00050000 Base custom area | * + * | kernel / FS | * + * | | * Rest of Flash + * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + * | END-0x00008000 Environment | * 32kb + * |--------------------------------| + * + * + * + * Main Memory: + * |--------------------------------| + * | UNUSED / scratch area | + * | | + * | | + * | | + * | | + * |--------------------------------| + * | Monitor .Text / .DATA / .BSS | * 512kb + * | Relocated! | * + * |--------------------------------| + * | Monitor Malloc | * 128kb (contains relocated environment) + * |--------------------------------| + * | Monitor/kernel STACK | * 64kb + * |--------------------------------| + * | Page Table for MMU systems | * 2k + * |--------------------------------| + * | PROM Code accessed from Linux | * 6kb-128b + * |--------------------------------| + * | Global data (avail from kernel)| * 128b + * |--------------------------------| + * + */ + +/* + * Flash configuration (8,16 or 32 MB) + * TEXT base always at 0xFFF00000 + * ENV_ADDR always at 0xFFF40000 + * FLASH_BASE at 0xFC000000 for 64 MB + * 0xFE000000 for 32 MB + * 0xFF000000 for 16 MB + * 0xFF800000 for 8 MB + */ +/*#define CFG_NO_FLASH 1*/ +#define CFG_FLASH_BASE 0x00000000 +#define CFG_FLASH_SIZE 0x00400000 /* FPGA Bit file is in top of FLASH, we only ues the bottom 4Mb */ + +#define PHYS_FLASH_SECT_SIZE 0x00010000 /* 64 KB sectors */ +#define CFG_MAX_FLASH_SECT 256 /* max num of sects on one chip */ +#define CFG_MAX_FLASH_BANKS 1 /* max num of memory banks */ + +#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */ +#define CFG_FLASH_LOCK_TOUT 5 /* Timeout for Flash Set Lock Bit (in ms) */ +#define CFG_FLASH_UNLOCK_TOUT 10000 /* Timeout for Flash Clear Lock Bits (in ms) */ +#define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */ + +/*** CFI CONFIG ***/ +#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +/* Bypass cache when reading regs from flash memory */ +#define CFG_FLASH_CFI_BYPASS_READ +/* Buffered writes (32byte/go) instead of single accesses */ +#define CFG_FLASH_USE_BUFFER_WRITE + +/* + * Environment settings + */ +/*#define CFG_ENV_IS_NOWHERE 1*/ +#define CFG_ENV_IS_IN_FLASH 1 +/* CFG_ENV_ADDR need to be at sector boundary */ +#define CFG_ENV_SIZE 0x8000 +#define CFG_ENV_SECT_SIZE 0x20000 +#define CFG_ENV_ADDR (CFG_FLASH_BASE+CFG_FLASH_SIZE-CFG_ENV_SECT_SIZE) +#define CONFIG_ENV_OVERWRITE 1 + +/* + * Memory map + */ +#define CFG_SDRAM_BASE 0x40000000 +#define CFG_SDRAM_SIZE 0x02000000 +#define CFG_SDRAM_END (CFG_SDRAM_BASE+CFG_SDRAM_SIZE) + +/* no SRAM available */ +#undef CFG_SRAM_BASE +#undef CFG_SRAM_SIZE + +#define CFG_RAM_BASE CFG_SDRAM_BASE +#define CFG_RAM_SIZE CFG_SDRAM_SIZE +#define CFG_RAM_END CFG_SDRAM_END + +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_SDRAM_END - CFG_GBL_DATA_SIZE) + +#define CFG_PROM_SIZE (8192-CFG_GBL_DATA_SIZE) +#define CFG_PROM_OFFSET (CFG_GBL_DATA_OFFSET-CFG_PROM_SIZE) + +#define CFG_INIT_SP_OFFSET (CFG_PROM_OFFSET-32) +#define CFG_STACK_SIZE (0x10000-32) + +#define CFG_MONITOR_BASE TEXT_BASE +#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) +# define CFG_RAMBOOT 1 +#endif + +#define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +#define CFG_MALLOC_END (CFG_INIT_SP_OFFSET-CFG_STACK_SIZE) +#define CFG_MALLOC_BASE (CFG_MALLOC_END-CFG_MALLOC_LEN) + +/* relocated monitor area */ +#define CFG_RELOC_MONITOR_MAX_END CFG_MALLOC_BASE +#define CFG_RELOC_MONITOR_BASE (CFG_RELOC_MONITOR_MAX_END-CFG_MONITOR_LEN) + +/* make un relocated address from relocated address */ +#define UN_RELOC(address) (address-(CFG_RELOC_MONITOR_BASE-TEXT_BASE)) + +/* + * Ethernet configuration uses on board SMC91C111, however if a mezzanine + * with a PHY is attached the GRETH can be used on this board. + * Define USE_GRETH in order to use the mezzanine provided PHY with the + * onchip GRETH network MAC, note that this is not supported by the + * template design. + */ +#ifndef USE_GRETH + +/* USE SMC91C111 MAC */ +#define CONFIG_DRIVER_SMC91111 1 +#define CONFIG_SMC91111_BASE 0x20000300 /* chip select 3 */ +#define CONFIG_SMC_USE_32_BIT 1 /* 32 bit bus */ +#undef CONFIG_SMC_91111_EXT_PHY /* we use internal phy */ +/*#define CONFIG_SHOW_ACTIVITY*/ +#define CONFIG_NET_RETRY_COUNT 10 /* # of retries */ + +#else + +/* USE GRETH Ethernet Driver */ +#define CONFIG_NET_MULTI 1 +#define CONFIG_GRETH 1 + +/* Default GRETH Ethernet HARDWARE address */ +#define GRETH_HWADDR_0 0x00 +#define GRETH_HWADDR_1 0x00 +#define GRETH_HWADDR_2 0x7a +#define GRETH_HWADDR_3 0xcc +#define GRETH_HWADDR_4 0x00 +#define GRETH_HWADDR_5 0x13 +#endif + +#define CONFIG_ETHADDR 00:00:7a:cc:00:13 +#define CONFIG_PHY_ADDR 0x00 + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if defined(CONFIG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00100000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00f00000 /* 1 ... 15 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/*----------------------------------------------------------------------- + * USB stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_USB_CLOCK 0x0001BBBB +#define CONFIG_USB_CONFIG 0x00005000 + +/***** Gaisler GRLIB IP-Cores Config ********/ + +/* AMBA Plug & Play info display on startup */ +/*#define CFG_AMBAPP_PRINT_ON_STARTUP*/ + +#define CFG_GRLIB_SDRAM 0 + +/* See, GRLIB Docs (grip.pdf) on how to set up + * These the memory controller registers. + */ +#define CFG_GRLIB_MEMCFG1 (0x10f800ff | (1<<11)) +#define CFG_GRLIB_MEMCFG2 0x00000000 +#define CFG_GRLIB_MEMCFG3 0x00000000 + +#define CFG_GRLIB_FT_MEMCFG1 (0x10f800ff | (1<<11)) +#define CFG_GRLIB_FT_MEMCFG2 0x00000000 +#define CFG_GRLIB_FT_MEMCFG3 0x00000000 + +#define CFG_GRLIB_DDR_CFG 0xa900830a + +#define CFG_GRLIB_DDR2_CFG1 0x00000000 +#define CFG_GRLIB_DDR2_CFG3 0x00000000 + +/* Calculate scaler register value from default baudrate */ +#define CFG_GRLIB_APBUART_SCALER \ + ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10) + +/* Identification string */ +#define CONFIG_IDENT_STRING "GAISLER LEON3 EP2S60" + +/* default kernel command line */ +#define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0" + +#endif /* __CONFIG_H */ From 6ed8a43a19bb0275501bc286007daafa923552cf Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Wed, 26 Mar 2008 23:38:48 +0100 Subject: [PATCH 10/11] SPARC/LEON3: added support for GR-CPCI-AX2000 FPGA AX board. The FPGA is exchangeable but a standard LEON3 design is assumed. See www.gaisler.com for information. Signed-off-by: Daniel Hellstrom --- MAKEALL | 2 +- Makefile | 4 + board/gaisler/gr_cpci_ax2000/Makefile | 52 +++ board/gaisler/gr_cpci_ax2000/config.mk | 37 ++ board/gaisler/gr_cpci_ax2000/gr_cpci_ax2000.c | 39 ++ board/gaisler/gr_cpci_ax2000/u-boot.lds | 160 ++++++++ include/configs/gr_cpci_ax2000.h | 380 ++++++++++++++++++ 7 files changed, 673 insertions(+), 1 deletion(-) create mode 100644 board/gaisler/gr_cpci_ax2000/Makefile create mode 100644 board/gaisler/gr_cpci_ax2000/config.mk create mode 100644 board/gaisler/gr_cpci_ax2000/gr_cpci_ax2000.c create mode 100644 board/gaisler/gr_cpci_ax2000/u-boot.lds create mode 100644 include/configs/gr_cpci_ax2000.h diff --git a/MAKEALL b/MAKEALL index fb5758900..7dbf1aac9 100755 --- a/MAKEALL +++ b/MAKEALL @@ -727,7 +727,7 @@ LIST_sh=" \ ## SPARC Systems ######################################################################### -LIST_sparc="gr_xc3s_1500 gr_ep2s60 grsim" +LIST_sparc="gr_xc3s_1500 gr_cpci_ax2000 gr_ep2s60 grsim" #----------------------------------------------------------------------- diff --git a/Makefile b/Makefile index 050972d0a..fda748617 100644 --- a/Makefile +++ b/Makefile @@ -2906,6 +2906,10 @@ r2dplus_config : unconfig gr_xc3s_1500_config : unconfig @$(MKCONFIG) $(@:_config=) sparc leon3 gr_xc3s_1500 gaisler +# Gaisler GR-CPCI-AX2000 board, a General purpose FPGA-AX system +gr_cpci_ax2000_config : unconfig + @$(MKCONFIG) $(@:_config=) sparc leon3 gr_cpci_ax2000 gaisler + # Gaisler GRLIB template design (GPL SPARC/LEON3) for Altera NIOS # Development board Stratix II edition, FPGA Device EP2S60. gr_ep2s60_config: unconfig diff --git a/board/gaisler/gr_cpci_ax2000/Makefile b/board/gaisler/gr_cpci_ax2000/Makefile new file mode 100644 index 000000000..d58f50d99 --- /dev/null +++ b/board/gaisler/gr_cpci_ax2000/Makefile @@ -0,0 +1,52 @@ + +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +#flash.o +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/gaisler/gr_cpci_ax2000/config.mk b/board/gaisler/gr_cpci_ax2000/config.mk new file mode 100644 index 000000000..6c4d56b90 --- /dev/null +++ b/board/gaisler/gr_cpci_ax2000/config.mk @@ -0,0 +1,37 @@ +# +# (C) Copyright 2008 +# Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# GR-CPCI-AX2000 board +# + +# U-BOOT IN FLASH +TEXT_BASE = 0x00000000 + +# U-BOOT IN RAM or SDRAM with -nosram flag set when starting GRMON +#TEXT_BASE = 0x40000000 + +# U-BOOT IN SDRAM +#TEXT_BASE = 0x60000000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/gaisler/gr_cpci_ax2000/gr_cpci_ax2000.c b/board/gaisler/gr_cpci_ax2000/gr_cpci_ax2000.c new file mode 100644 index 000000000..d99b45523 --- /dev/null +++ b/board/gaisler/gr_cpci_ax2000/gr_cpci_ax2000.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2008 + * Daniel Hellstrom, daniel@gaisler.com. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +long int initdram(int board_type) +{ + return 1; +} + +int checkboard(void) +{ + puts("Board: GR-CPCI-AX2000\n"); + return 0; +} + +int misc_init_r(void) +{ + return 0; +} diff --git a/board/gaisler/gr_cpci_ax2000/u-boot.lds b/board/gaisler/gr_cpci_ax2000/u-boot.lds new file mode 100644 index 000000000..3958670bb --- /dev/null +++ b/board/gaisler/gr_cpci_ax2000/u-boot.lds @@ -0,0 +1,160 @@ +/* Linker script for Gaisler Research AB's GR-CPCI-AX2000 board + * with template design. + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) +SECTIONS +{ + +/* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + + .text : { + _load_addr = .; + _text = .; + + *(.start) + cpu/leon3/start.o (.text) +/* 8k is the same as the PROM offset from end of main memory, (CFG_PROM_SIZE) */ + . = ALIGN(8192); +/* PROM CODE, Will be relocated to the end of memory, + * no global data accesses please. + */ + __prom_start = .; + *(.prom.pgt) + *(.prom.data) + *(.prom.text) + . = ALIGN(16); + __prom_end = .; + *(.text) + *(.fixup) + *(.gnu.warning) +/* *(.got1)*/ + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.eh_frame) + } + . = ALIGN(4); + _etext = .; + + /* CMD Table */ + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + . = ALIGN(4); + __u_boot_cmd_end = .; + + .data : + { + *(.data) + *(.data1) + *(.data.rel) + *(.data.rel.*) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = ALIGN(4); + __got_start = .; + .got : { + *(.got) +/* *(.data.rel) + *(.data.rel.local)*/ + . = ALIGN(16); + } + __got_end = .; + +/* .data.rel : { } */ + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(16); /* to speed clearing of bss up */ + } + __bss_end = . ; + _end = . ; + PROVIDE (end = .); + +/* Relocated into main memory */ + + /* Start of main memory */ + /*. = 0x40000000;*/ + + .stack (NOLOAD) : { *(.stack) } + + /* PROM CODE */ + + /* global data in RAM passed to kernel after booting */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + +} diff --git a/include/configs/gr_cpci_ax2000.h b/include/configs/gr_cpci_ax2000.h new file mode 100644 index 000000000..1276f4d83 --- /dev/null +++ b/include/configs/gr_cpci_ax2000.h @@ -0,0 +1,380 @@ +/* Configuration header file for Gaisler GR-CPCI-AX2000 + * AX board. Note that since the AX is removable the configuration + * for this board must be edited below. + * + * (C) Copyright 2003-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2008 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_LEON3 /* This is an LEON3 CPU */ +#define CONFIG_LEON 1 /* This is an LEON CPU */ +#define CONFIG_CPCI_AX2000 1 /* ... on GR-CPCI-AX2000 board */ + +#define CONFIG_LEON_RAM_SRAM 1 +#define CONFIG_LEON_RAM_SDRAM 2 +#define CONFIG_LEON_RAM_SDRAM_NOSRAM 3 + +/* Select Memory to run from + * + * SRAM - UBoot is run in SRAM, SRAM-0x40000000, SDRAM-0x60000000 + * SDRAM - UBoot is run in SDRAM, SRAM-0x40000000 and SDRAM-0x60000000 + * SDRAM_NOSRAM - UBoot is run in SDRAM, SRAM not available, SDRAM at 0x40000000 + * + * Note, if Linux is to be used, SDRAM or SDRAM_NOSRAM is required since + * it doesn't fit into the 4Mb SRAM. + * + * SRAM is default since it will work for all systems, however will not + * be able to boot linux. + */ +#define CONFIG_LEON_RAM_SELECT CONFIG_LEON_RAM_SRAM + +/* CPU / AMBA BUS configuration */ +#define CONFIG_SYS_CLK_FREQ 20000000 /* 20MHz */ + +/* Number of SPARC register windows */ +#define CFG_SPARC_NWINDOWS 8 + +/* + * Serial console configuration + */ +#define CONFIG_BAUDRATE 38400 /* ... at 38400 bps */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } + +/* Partitions */ +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION + +/* + * Supported commands + */ +#include + +#define CONFIG_CMD_REGINFO +#define CONFIG_CMD_AMBAPP +#define CONFIG_CMD_PING +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_IRQ + +/* + * Autobooting + */ +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ + +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS + +#define CONFIG_EXTRA_ENV_SETTINGS_BASE \ + "netdev=eth0\0" \ + "nfsargs=setenv bootargs console=ttyS0,38400 root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs console=ttyS0,${baudrate} root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "getkernel=tftpboot \$\(scratch\)\ \$\(bootfile\)\0" \ + "bootargs=console=ttyS0,38400 root=/dev/nfs rw nfsroot=192.168.0.20:/export/rootfs ip=192.168.0.206:192.168.0.20:192.168.0.1:255.255.255.0:ax2000:eth0\0" + +#if CONFIG_LEON_RAM_SELECT == CONFIG_LEON_RAM_SRAM +#define CONFIG_EXTRA_ENV_SETTINGS_SELECT \ + "net_nfs=tftp 40000000 ${bootfile};run nfsargs addip;bootm\0" \ + "scratch=40200000\0" \ + "" +#elif CONFIG_LEON_RAM_SELECT == CONFIG_LEON_RAM_SDRAM +#define CONFIG_EXTRA_ENV_SETTINGS_SELECT \ + "net_nfs=tftp 60000000 ${bootfile};run nfsargs addip;bootm\0" \ + "scratch=60800000\0" \ + "" +#else +/* More than 4Mb is assumed when running from SDRAM */ +#define CONFIG_EXTRA_ENV_SETTINGS_SELECT \ + "net_nfs=tftp 40000000 ${bootfile};run nfsargs addip;bootm\0" \ + "scratch=40800000\0" \ + "" +#endif + +#define CONFIG_EXTRA_ENV_SETTINGS CONFIG_EXTRA_ENV_SETTINGS_BASE CONFIG_EXTRA_ENV_SETTINGS_SELECT + +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_GATEWAYIP 192.168.0.1 +#define CONFIG_SERVERIP 192.168.0.20 +#define CONFIG_IPADDR 192.168.0.206 +#define CONFIG_ROOTPATH /export/rootfs +#define CONFIG_HOSTNAME ax2000 +#define CONFIG_BOOTFILE /uImage + +#define CONFIG_BOOTCOMMAND "run flash_self" + +/* Memory MAP + * + * Flash: + * |--------------------------------| + * | 0x00000000 Text & Data & BSS | * + * | for Monitor | * + * | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| * + * | UNUSED / Growth | * 256kb + * |--------------------------------| + * | 0x00050000 Base custom area | * + * | kernel / FS | * + * | | * Rest of Flash + * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + * | END-0x00008000 Environment | * 32kb + * |--------------------------------| + * + * + * + * Main Memory (4Mb SRAM or XMb SDRAM): + * |--------------------------------| + * | UNUSED / scratch area | + * | | + * | | + * | | + * | | + * |--------------------------------| + * | Monitor .Text / .DATA / .BSS | * 256kb + * | Relocated! | * + * |--------------------------------| + * | Monitor Malloc | * 128kb (contains relocated environment) + * |--------------------------------| + * | Monitor/kernel STACK | * 64kb + * |--------------------------------| + * | Page Table for MMU systems | * 2k + * |--------------------------------| + * | PROM Code accessed from Linux | * 6kb-128b + * |--------------------------------| + * | Global data (avail from kernel)| * 128b + * |--------------------------------| + * + */ + +/* + * Flash configuration (8,16 or 32 MB) + * TEXT base always at 0xFFF00000 + * ENV_ADDR always at 0xFFF40000 + * FLASH_BASE at 0xFC000000 for 64 MB + * 0xFE000000 for 32 MB + * 0xFF000000 for 16 MB + * 0xFF800000 for 8 MB + */ +/*#define CFG_NO_FLASH 1*/ +#define CFG_FLASH_BASE 0x00000000 +#define CFG_FLASH_SIZE 0x00800000 + +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 128 KB sectors */ +#define CFG_MAX_FLASH_SECT 64 /* max num of sects on one chip */ +#define CFG_MAX_FLASH_BANKS 1 /* max num of memory banks */ + +#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */ +#define CFG_FLASH_LOCK_TOUT 5 /* Timeout for Flash Set Lock Bit (in ms) */ +#define CFG_FLASH_UNLOCK_TOUT 10000 /* Timeout for Flash Clear Lock Bits (in ms) */ +#define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */ + +/*** CFI CONFIG ***/ +#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +/* Bypass cache when reading regs from flash memory */ +#define CFG_FLASH_CFI_BYPASS_READ +/* Buffered writes (32byte/go) instead of single accesses */ +#define CFG_FLASH_USE_BUFFER_WRITE + +/* + * Environment settings + */ +/*#define CFG_ENV_IS_NOWHERE 1*/ +#define CFG_ENV_IS_IN_FLASH 1 +/* CFG_ENV_ADDR need to be at sector boundary */ +#define CFG_ENV_SIZE 0x8000 +#define CFG_ENV_SECT_SIZE 0x20000 +#define CFG_ENV_ADDR (CFG_FLASH_BASE+CFG_FLASH_SIZE-CFG_ENV_SECT_SIZE) +#define CONFIG_ENV_OVERWRITE 1 + +/* + * Memory map + * + * Always 4Mb SRAM available + * SDRAM module may be available on 0x60000000, SDRAM + * is configured as if a 128Mb SDRAM module is available. + */ + +#if CONFIG_LEON_RAM_SELECT == CONFIG_LEON_RAM_SDRAM_NOSRAM +#define CFG_SDRAM_BASE 0x40000000 +#else +#define CFG_SDRAM_BASE 0x60000000 +#endif + +#define CFG_SDRAM_SIZE 0x08000000 +#define CFG_SDRAM_END (CFG_SDRAM_BASE+CFG_SDRAM_SIZE) + +/* 4Mb SRAM available */ +#if CONFIG_LEON_RAM_SELECT != CONFIG_LEON_RAM_SDRAM_NOSRAM +#define CFG_SRAM_BASE 0x40000000 +#define CFG_SRAM_SIZE 0x400000 +#define CFG_SRAM_END (CFG_SRAM_BASE+CFG_SRAM_SIZE) +#endif + +/* Select RAM used to run U-BOOT from... */ +#if CONFIG_LEON_RAM_SELECT == CONFIG_LEON_RAM_SRAM +#define CFG_RAM_BASE CFG_SRAM_BASE +#define CFG_RAM_SIZE CFG_SRAM_SIZE +#define CFG_RAM_END CFG_SRAM_END +#else +#define CFG_RAM_BASE CFG_SDRAM_BASE +#define CFG_RAM_SIZE CFG_SDRAM_SIZE +#define CFG_RAM_END CFG_SDRAM_END +#endif + +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_RAM_END - CFG_GBL_DATA_SIZE) + +#define CFG_PROM_SIZE (8192-CFG_GBL_DATA_SIZE) +#define CFG_PROM_OFFSET (CFG_GBL_DATA_OFFSET-CFG_PROM_SIZE) + +#define CFG_INIT_SP_OFFSET (CFG_PROM_OFFSET-32) +#define CFG_STACK_SIZE (0x10000-32) + +#define CFG_MONITOR_BASE TEXT_BASE +#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) +# define CFG_RAMBOOT 1 +#endif + +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +#define CFG_MALLOC_END (CFG_INIT_SP_OFFSET-CFG_STACK_SIZE) +#define CFG_MALLOC_BASE (CFG_MALLOC_END-CFG_MALLOC_LEN) + +/* relocated monitor area */ +#define CFG_RELOC_MONITOR_MAX_END CFG_MALLOC_BASE +#define CFG_RELOC_MONITOR_BASE (CFG_RELOC_MONITOR_MAX_END-CFG_MONITOR_LEN) + +/* make un relocated address from relocated address */ +#define UN_RELOC(address) (address-(CFG_RELOC_MONITOR_BASE-TEXT_BASE)) + +/* + * Ethernet configuration uses on board SMC91C111 + */ +#define CONFIG_DRIVER_SMC91111 1 +#define CONFIG_SMC91111_BASE 0x20000300 /* chip select 3 */ +#define CONFIG_SMC_USE_32_BIT 1 /* 32 bit bus */ +#undef CONFIG_SMC_91111_EXT_PHY /* we use internal phy */ +/*#define CONFIG_SHOW_ACTIVITY*/ +#define CONFIG_NET_RETRY_COUNT 10 /* # of retries */ + +#define CONFIG_ETHADDR 00:00:7a:cc:00:13 +#define CONFIG_PHY_ADDR 0x00 + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if defined(CONFIG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00100000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00f00000 /* 1 ... 15 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/* + * Various low-level settings + */ + +/*----------------------------------------------------------------------- + * USB stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_USB_CLOCK 0x0001BBBB +#define CONFIG_USB_CONFIG 0x00005000 + +/***** Gaisler GRLIB IP-Cores Config ********/ + +/* AMBA Plug & Play info display on startup */ +/*#define CFG_AMBAPP_PRINT_ON_STARTUP*/ + +#define CFG_GRLIB_SDRAM 0 + +/* See, GRLIB Docs (grip.pdf) on how to set up + * These the memory controller registers. + */ +#define CFG_GRLIB_MEMCFG1 (0x10f800ff | (1<<11)) +#if CONFIG_LEON_RAM_SELECT == CONFIG_LEON_RAM_SDRAM_NOSRAM +#define CFG_GRLIB_MEMCFG2 0x82206000 +#else +#define CFG_GRLIB_MEMCFG2 0x82205260 +#endif +#define CFG_GRLIB_MEMCFG3 0x0809a000 + +#define CFG_GRLIB_FT_MEMCFG1 (0x10f800ff | (1<<11)) +#if CONFIG_LEON_RAM_SELECT == CONFIG_LEON_RAM_SDRAM_NOSRAM +#define CFG_GRLIB_FT_MEMCFG2 0x82206000 +#else +#define CFG_GRLIB_FT_MEMCFG2 0x82205260 +#endif +#define CFG_GRLIB_FT_MEMCFG3 0x0809a000 + +/* no DDR controller */ +#define CFG_GRLIB_DDR_CFG 0x00000000 + +/* no DDR2 Controller */ +#define CFG_GRLIB_DDR2_CFG1 0x00000000 +#define CFG_GRLIB_DDR2_CFG3 0x00000000 + +/* Calculate scaler register value from default baudrate */ +#define CFG_GRLIB_APBUART_SCALER \ + ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10) + +/* Identification string */ +#define CONFIG_IDENT_STRING "GAISLER LEON3 GR-CPCI-AX2000" + +/* default kernel command line */ +#define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0" + +#endif /* __CONFIG_H */ From ab68f921d9c741830f721c3d879c13a0c5597183 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 28 Mar 2008 10:20:43 +0100 Subject: [PATCH 11/11] SPARC/LEON2: added support for Gaisler simulator GRSIM/TSIM for SPARC/LEON2 targets. See www.gaisler.com for information. Signed-off-by: Daniel Hellstrom --- MAKEALL | 2 +- Makefile | 4 + board/gaisler/grsim_leon2/Makefile | 50 ++++ board/gaisler/grsim_leon2/config.mk | 34 +++ board/gaisler/grsim_leon2/grsim_leon2.c | 43 +++ board/gaisler/grsim_leon2/u-boot.lds | 159 +++++++++++ include/configs/grsim_leon2.h | 349 ++++++++++++++++++++++++ 7 files changed, 640 insertions(+), 1 deletion(-) create mode 100644 board/gaisler/grsim_leon2/Makefile create mode 100644 board/gaisler/grsim_leon2/config.mk create mode 100644 board/gaisler/grsim_leon2/grsim_leon2.c create mode 100644 board/gaisler/grsim_leon2/u-boot.lds create mode 100644 include/configs/grsim_leon2.h diff --git a/MAKEALL b/MAKEALL index 7dbf1aac9..213cfcde4 100755 --- a/MAKEALL +++ b/MAKEALL @@ -727,7 +727,7 @@ LIST_sh=" \ ## SPARC Systems ######################################################################### -LIST_sparc="gr_xc3s_1500 gr_cpci_ax2000 gr_ep2s60 grsim" +LIST_sparc="gr_xc3s_1500 gr_cpci_ax2000 gr_ep2s60 grsim grsim_leon2" #----------------------------------------------------------------------- diff --git a/Makefile b/Makefile index fda748617..0b9c6227e 100644 --- a/Makefile +++ b/Makefile @@ -2923,6 +2923,10 @@ grsim_config : unconfig ## LEON2 ######################################################################### +# Gaisler LEON2 GRSIM simulator +grsim_leon2_config : unconfig + @$(MKCONFIG) $(@:_config=) sparc leon2 grsim_leon2 gaisler + ######################################################################### ######################################################################### ######################################################################### diff --git a/board/gaisler/grsim_leon2/Makefile b/board/gaisler/grsim_leon2/Makefile new file mode 100644 index 000000000..629510956 --- /dev/null +++ b/board/gaisler/grsim_leon2/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2003-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/gaisler/grsim_leon2/config.mk b/board/gaisler/grsim_leon2/config.mk new file mode 100644 index 000000000..65eba1bb7 --- /dev/null +++ b/board/gaisler/grsim_leon2/config.mk @@ -0,0 +1,34 @@ +# +# (C) Copyright 2007 +# Daniel Hellstrom, Gaisler Research, daniel@gaisler.com +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# GRSIM simulating a LEON2 board +# + +# RUN U-BOOT FROM PROM +TEXT_BASE = 0x00000000 + +# RUN U-BOOT FROM RAM +#TEXT_BASE = 0x40000000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/gaisler/grsim_leon2/grsim_leon2.c b/board/gaisler/grsim_leon2/grsim_leon2.c new file mode 100644 index 000000000..55dfe8286 --- /dev/null +++ b/board/gaisler/grsim_leon2/grsim_leon2.c @@ -0,0 +1,43 @@ +/* GRSIM/TSIM board + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include + +long int initdram(int board_type) +{ + return 1; +} + +int checkboard(void) +{ + puts("Board: GRSIM/TSIM LEON2\n"); + return 0; +} + +int misc_init_r(void) +{ + return 0; +} diff --git a/board/gaisler/grsim_leon2/u-boot.lds b/board/gaisler/grsim_leon2/u-boot.lds new file mode 100644 index 000000000..2a22082a8 --- /dev/null +++ b/board/gaisler/grsim_leon2/u-boot.lds @@ -0,0 +1,159 @@ +/* Linker script for Gaisler Research AB's GRSIM LEON2 simulator. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) +SECTIONS +{ + +/* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + + .text : { + _load_addr = .; + _text = .; + + *(.start) + cpu/leon2/start.o (.text) +/* 8k is the same as the PROM offset from end of main memory, (CFG_PROM_SIZE) */ + . = ALIGN(8192); +/* PROM CODE, Will be relocated to the end of memory, + * no global data accesses please. + */ + __prom_start = .; + *(.prom.pgt) + *(.prom.data) + *(.prom.text) + . = ALIGN(16); + __prom_end = .; + *(.text) + *(.fixup) + *(.gnu.warning) +/* *(.got1)*/ + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.eh_frame) + } + . = ALIGN(4); + _etext = .; + + /* CMD Table */ + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + . = ALIGN(4); + __u_boot_cmd_end = .; + + .data : + { + *(.data) + *(.data1) + *(.data.rel) + *(.data.rel.*) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = ALIGN(4); + __got_start = .; + .got : { + *(.got) +/* *(.data.rel) + *(.data.rel.local)*/ + . = ALIGN(16); + } + __got_end = .; + +/* .data.rel : { } */ + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(16); /* to speed clearing of bss up */ + } + __bss_end = . ; + _end = . ; + PROVIDE (end = .); + +/* Relocated into main memory */ + + /* Start of main memory */ + /*. = 0x40000000;*/ + + .stack (NOLOAD) : { *(.stack) } + + /* PROM CODE */ + + /* global data in RAM passed to kernel after booting */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + +} diff --git a/include/configs/grsim_leon2.h b/include/configs/grsim_leon2.h new file mode 100644 index 000000000..47f13d0bc --- /dev/null +++ b/include/configs/grsim_leon2.h @@ -0,0 +1,349 @@ +/* Configuration header file for LEON2 GRSIM. + * + * (C) Copyright 2003-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +/* + * High Level Configuration Options + * (easy to change) + * + * Select between TSIM or GRSIM by setting CONFIG_GRSIM or CONFIG_TSIM to 1. + * + * TSIM command + * tsim-leon -sdram 0 -ram 32000 -rom 8192 -mmu + * + */ + +#define CONFIG_LEON2 /* This is an LEON2 CPU */ +#define CONFIG_LEON 1 /* This is an LEON CPU */ +#define CONFIG_GRSIM 0 /* ... not running on GRSIM */ +#define CONFIG_TSIM 1 /* ... running on TSIM */ + +/* CPU / AMBA BUS configuration */ +#define CONFIG_SYS_CLK_FREQ 40000000 /* 40MHz */ + +/* Number of SPARC register windows */ +#define CFG_SPARC_NWINDOWS 8 + +/* + * Serial console configuration + */ +#define CONFIG_BAUDRATE 38400 /* ... at 38400 bps */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } + +/* Partitions */ +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION + +/* + * Supported commands + */ +#define CONFIG_CMD_AUTOSCRIPT /* Autoscript Support */ +#define CONFIG_CMD_BDI /* bdinfo */ +#define CONFIG_CMD_CONSOLE /* coninfo */ +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_ECHO /* echo arguments */ +#define CONFIG_CMD_FPGA /* FPGA configuration Support */ +#define CONFIG_CMD_IRQ +#define CONFIG_CMD_ITEST /* Integer (and string) test */ +#define CONFIG_CMD_LOADB /* loadb */ +#define CONFIG_CMD_LOADS /* loads */ +#define CONFIG_CMD_MISC /* Misc functions like sleep etc */ +#define CONFIG_CMD_REGINFO +#define CONFIG_CMD_RUN /* run command in env variable */ +#define CONFIG_CMD_SETGETDCR /* DCR support on 4xx */ +#define CONFIG_CMD_XIMG /* Load part of Multi Image */ + +/* + * Autobooting + */ +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ + +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS +/*#define CFG_HUSH_PARSER 0*/ +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm ${kernel_addr}\0" \ + "flash_self=run ramargs addip;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "net_nfs=tftp 40000000 ${bootfile};run nfsargs addip;bootm\0" \ + "rootpath=/export/roofs\0" \ + "scratch=40000000\0" \ + "getkernel=tftpboot \$\(scratch\)\ \$\(bootfile\)\0" \ + "ethaddr=00:00:7A:CC:00:12\0" \ + "bootargs=console=ttyS0,38400" \ + "" +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_GATEWAYIP 192.168.0.1 +#define CONFIG_SERVERIP 192.168.0.81 +#define CONFIG_IPADDR 192.168.0.80 +#define CONFIG_ROOTPATH /export/rootfs +#define CONFIG_HOSTNAME grxc3s1500 +#define CONFIG_BOOTFILE /uImage + +#define CONFIG_BOOTCOMMAND "run flash_self" + +/* Memory MAP + * + * Flash: + * |--------------------------------| + * | 0x00000000 Text & Data & BSS | * + * | for Monitor | * + * | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| * + * | UNUSED / Growth | * 256kb + * |--------------------------------| + * | 0x00050000 Base custom area | * + * | kernel / FS | * + * | | * Rest of Flash + * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + * | END-0x00008000 Environment | * 32kb + * |--------------------------------| + * + * + * + * Main Memory: + * |--------------------------------| + * | UNUSED / scratch area | + * | | + * | | + * | | + * | | + * |--------------------------------| + * | Monitor .Text / .DATA / .BSS | * 256kb + * | Relocated! | * + * |--------------------------------| + * | Monitor Malloc | * 128kb (contains relocated environment) + * |--------------------------------| + * | Monitor/kernel STACK | * 64kb + * |--------------------------------| + * | Page Table for MMU systems | * 2k + * |--------------------------------| + * | PROM Code accessed from Linux | * 6kb-128b + * |--------------------------------| + * | Global data (avail from kernel)| * 128b + * |--------------------------------| + * + */ + +/* + * Flash configuration (8,16 or 32 MB) + * TEXT base always at 0xFFF00000 + * ENV_ADDR always at 0xFFF40000 + * FLASH_BASE at 0xFC000000 for 64 MB + * 0xFE000000 for 32 MB + * 0xFF000000 for 16 MB + * 0xFF800000 for 8 MB + */ +#define CFG_NO_FLASH 1 +#define CFG_FLASH_BASE 0x00000000 +#define CFG_FLASH_SIZE 0x00800000 +#define CFG_ENV_SIZE 0x8000 + +#define CFG_ENV_ADDR (CFG_FLASH_BASE+CFG_FLASH_SIZE-CFG_ENV_SIZE) + +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 128 KB sectors */ +#define CFG_MAX_FLASH_SECT 64 /* max num of sects on one chip */ +#define CFG_MAX_FLASH_BANKS 1 /* max num of memory banks */ + +#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */ +#define CFG_FLASH_LOCK_TOUT 5 /* Timeout for Flash Set Lock Bit (in ms) */ +#define CFG_FLASH_UNLOCK_TOUT 10000 /* Timeout for Flash Clear Lock Bits (in ms) */ + +#ifdef ENABLE_FLASH_SUPPORT +/* For use with grsim FLASH emulation extension */ +#define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */ + +#undef CONFIG_FLASH_8BIT /* Flash is 32-bit */ + +/*** CFI CONFIG ***/ +#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +#endif + +/* + * Environment settings + */ +#define CFG_ENV_IS_NOWHERE 1 +/*#define CFG_ENV_IS_IN_FLASH 0*/ +/*#define CFG_ENV_SIZE 0x8000*/ +#define CFG_ENV_SECT_SIZE 0x40000 +#define CONFIG_ENV_OVERWRITE 1 + +/* + * Memory map + */ +#define CFG_SDRAM_BASE 0x40000000 +#define CFG_SDRAM_SIZE 0x00800000 +#define CFG_SDRAM_END (CFG_SDRAM_BASE+CFG_SDRAM_SIZE) + +/* no SRAM available */ +#undef CFG_SRAM_BASE +#undef CFG_SRAM_SIZE + + +/* Always Run U-Boot from SDRAM */ +#define CFG_RAM_BASE CFG_SDRAM_BASE +#define CFG_RAM_SIZE CFG_SDRAM_SIZE +#define CFG_RAM_END CFG_SDRAM_END + +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_RAM_END - CFG_GBL_DATA_SIZE) + +#define CFG_PROM_SIZE (8192-CFG_GBL_DATA_SIZE) +#define CFG_PROM_OFFSET (CFG_GBL_DATA_OFFSET-CFG_PROM_SIZE) + +#define CFG_INIT_SP_OFFSET (CFG_PROM_OFFSET-32) +#define CFG_STACK_SIZE (0x10000-32) + +#define CFG_MONITOR_BASE TEXT_BASE +#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) +# define CFG_RAMBOOT 1 +#endif + +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +#define CFG_MALLOC_END (CFG_INIT_SP_OFFSET-CFG_STACK_SIZE) +#define CFG_MALLOC_BASE (CFG_MALLOC_END-CFG_MALLOC_LEN) + +/* relocated monitor area */ +#define CFG_RELOC_MONITOR_MAX_END CFG_MALLOC_BASE +#define CFG_RELOC_MONITOR_BASE (CFG_RELOC_MONITOR_MAX_END-CFG_MONITOR_LEN) + +/* make un relocated address from relocated address */ +#define UN_RELOC(address) (address-(CFG_RELOC_MONITOR_BASE-TEXT_BASE)) + +/* + * Ethernet configuration + */ +/*#define CONFIG_GRETH 1*/ +/*#define CONFIG_NET_MULTI 1*/ + +/* Default HARDWARE address */ +#define GRETH_HWADDR_0 0x00 +#define GRETH_HWADDR_1 0x00 +#define GRETH_HWADDR_2 0x7A +#define GRETH_HWADDR_3 0xcc +#define GRETH_HWADDR_4 0x00 +#define GRETH_HWADDR_5 0x12 + +#define CONFIG_ETHADDR 00:00:7a:cc:00:12 + +/* + * Define CONFIG_GRETH_10MBIT to force GRETH at 10Mb/s + */ +/* #define CONFIG_GRETH_10MBIT 1 */ +#define CONFIG_PHY_ADDR 0x00 + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if defined(CONFIG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00100000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00f00000 /* 1 ... 15 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/***** Gaisler GRLIB IP-Cores Config ********/ + +#define CFG_GRLIB_SDRAM 0 +#define CFG_GRLIB_MEMCFG1 (0x000000ff | (1<<11)) +#if CONFIG_GRSIM +#define CFG_GRLIB_MEMCFG2 0x82206000 +#else +#define CFG_GRLIB_MEMCFG2 0x00001820 +#endif +#define CFG_GRLIB_MEMCFG3 0x00136000 + +/*** LEON2 UART 1 ***/ +#define CFG_LEON2_UART1_SCALER \ + ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10) + +/* UART1 Define to 1 or 0 */ +#define LEON2_UART1_LOOPBACK_ENABLE 0 +#define LEON2_UART1_FLOWCTRL_ENABLE 0 +#define LEON2_UART1_PARITY_ENABLE 0 +#define LEON2_UART1_ODDPAR_ENABLE 0 + +/*** LEON2 UART 2 ***/ + +#define CFG_LEON2_UART2_SCALER \ + ((((CONFIG_SYS_CLK_FREQ*10)/(CONFIG_BAUDRATE*8))-5)/10) + +/* UART2 Define to 1 or 0 */ +#define LEON2_UART2_LOOPBACK_ENABLE 0 +#define LEON2_UART2_FLOWCTRL_ENABLE 0 +#define LEON2_UART2_PARITY_ENABLE 0 +#define LEON2_UART2_ODDPAR_ENABLE 0 + +#define LEON_CONSOLE_UART1 1 +#define LEON_CONSOLE_UART2 2 + +/* Use UART2 as console */ +#define LEON2_CONSOLE_SELECT LEON_CONSOLE_UART1 + +/* LEON2 I/O Port */ +/*#define LEON2_IO_PORT_DIR 0x0000aa00*/ + +/* default kernel command line */ +#define CONFIG_DEFAULT_KERNEL_COMMAND_LINE "console=ttyS0,38400\0\0" + +#define CONFIG_IDENT_STRING "Gaisler GRSIM LEON2" + +#endif /* __CONFIG_H */