From c2f02da21a3f37f0878554eebc785e04fdc4e128 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 28 Mar 2008 09:47:00 +0100 Subject: [PATCH 01/35] 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 2a872acd6a..9a2afe66fc 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 a7f886b489..7219e7a318 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 5d059e73c6..9160306c47 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 c5d629b68a..66b354daaf 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 0000000000..75925449ed --- /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 b9dbcf9065..ec5353216b 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 0000000000..bf6d70fece --- /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 0000000000..0c4cefdf40 --- /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 0000000000..636498d557 --- /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 0000000000..ceb39f2fe5 --- /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 0000000000..b9fc65663f --- /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 0000000000..03e8d94bb2 --- /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 0000000000..3a74f6fa47 --- /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 0000000000..7c29fc6840 --- /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 0000000000..2a27d06798 --- /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 0000000000..c5538c092d --- /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 0000000000..1e26195991 --- /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 0000000000..484953a86d --- /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 0000000000..8d98b2a6a1 --- /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 0000000000..31b44c5463 --- /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 0000000000..d55cc863da --- /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 0000000000..fc779477e5 --- /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 0000000000..12a9c569a2 --- /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 0000000000..5214d96a7e --- /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 0000000000..b40a9f355f --- /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 0000000000..c6bbc203d5 --- /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 0000000000..69f93d60b8 --- /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 0000000000..9c594e1f8c --- /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 0000000000..66fc639a7e --- /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 0000000000..1a354b6eab --- /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 0000000000..af301c046e --- /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 0000000000..8900b2e581 --- /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 0000000000..59d9bbe672 --- /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 0000000000..4c73b82a6f --- /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 0000000000..433f3eb5a0 --- /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 0000000000..87f745f614 --- /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/35] 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 bbb01921df..731c1d255d 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/35] 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 f04826a5c8..ce49bb24e0 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 36143e25ac..c1a6cbb481 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/35] 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 7219e7a318..bb8247cd1e 100644 --- a/Makefile +++ b/Makefile @@ -2898,6 +2898,9 @@ r2dplus_config : unconfig #======================================================================== # SPARC #======================================================================== +######################################################################### +## LEON3 +######################################################################### ######################################################################### ######################################################################### diff --git a/README b/README index 9160306c47..dfb51f7220 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 0000000000..182543dd10 --- /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 0000000000..60ff1a2aef --- /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 0000000000..30b224a068 --- /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 0000000000..306a210048 --- /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 0000000000..4fe7d4b8d1 --- /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 0000000000..26926321a5 --- /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 0000000000..9fa2d040e8 --- /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 0000000000..27d5cd3803 --- /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 0000000000..807f7e8dae --- /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 0000000000..7910bebe14 --- /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 0000000000..bf572a661b --- /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 0000000000..1e49d896ce --- /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 0000000000..700b3caa5e --- /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 0000000000..6036fb5e72 --- /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 0000000000..84d0e2ed27 --- /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 31b44c5463..d518389ad6 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/35] 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 0d67337d26..c71b228dc2 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 0000000000..738412b7fa --- /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 60ff1a2aef..efd41ae0a8 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 1e49d896ce..7494e594d8 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 69276a3894..d1b5ffb897 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/35] 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 bb8247cd1e..c97473f941 100644 --- a/Makefile +++ b/Makefile @@ -2902,6 +2902,10 @@ r2dplus_config : unconfig ## LEON3 ######################################################################### +######################################################################### +## LEON2 +######################################################################### + ######################################################################### ######################################################################### ######################################################################### diff --git a/README b/README index dfb51f7220..20751191bd 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 0000000000..7cc4420179 --- /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 0000000000..30b224a068 --- /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 0000000000..1c1e24b16c --- /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 0000000000..a24f778c6d --- /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 0000000000..35b375c782 --- /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 0000000000..b03199577f --- /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 0000000000..ce9457f5a9 --- /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 0000000000..937ea1ed77 --- /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 0000000000..38fdd5c8c7 --- /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 6036fb5e72..f7175eee9f 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 0000000000..fa55cade0b --- /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/35] 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 9a2afe66fc..6aa9a0484e 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 c97473f941..6afe4565e7 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 0000000000..d58f50d99f --- /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 0000000000..35cbc1bb21 --- /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 0000000000..1ee7024812 --- /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 0000000000..3848c684ab --- /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 0000000000..1fdef3d4ab --- /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/35] 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 6aa9a0484e..1626705ad3 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 6afe4565e7..9601f3beb0 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 0000000000..6295109563 --- /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 0000000000..81cd415e8d --- /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 0000000000..70a2f23c55 --- /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 0000000000..1e8bb69576 --- /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 0000000000..60ad396f5f --- /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/35] 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 1626705ad3..fb57589006 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 9601f3beb0..050972d0ad 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 0000000000..d58f50d99f --- /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 0000000000..2ee0957a37 --- /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 0000000000..e8617f0755 --- /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 0000000000..100350d7a1 --- /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 0000000000..710a082e97 --- /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/35] 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 fb57589006..7dbf1aac97 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 050972d0ad..fda7486175 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 0000000000..d58f50d99f --- /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 0000000000..6c4d56b90c --- /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 0000000000..d99b45523a --- /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 0000000000..3958670bb1 --- /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 0000000000..1276f4d83a --- /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/35] 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 7dbf1aac97..213cfcde40 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 fda7486175..0b9c6227e2 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 0000000000..6295109563 --- /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 0000000000..65eba1bb7b --- /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 0000000000..55dfe8286a --- /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 0000000000..2a22082a83 --- /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 0000000000..47f13d0bc1 --- /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 */ From cd2b75efb9cc037c74ecee9b3586f9bf9e1d4e57 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 10:58:15 +0100 Subject: [PATCH 12/35] microblaze: Clean Makefile from ancient emac driver Signed-off-by: Michal Simek --- board/xilinx/ml401/Makefile | 17 +---------------- board/xilinx/xupv2p/Makefile | 17 +---------------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/board/xilinx/ml401/Makefile b/board/xilinx/ml401/Makefile index 9ab5633626..ee9b6d5d29 100644 --- a/board/xilinx/ml401/Makefile +++ b/board/xilinx/ml401/Makefile @@ -22,25 +22,10 @@ # include $(TOPDIR)/config.mk -ifneq ($(OBJTREE),$(SRCTREE)) -$(shell mkdir -p $(obj)../common) -$(shell mkdir -p $(obj)../xilinx_enet) -endif - -INCS := -I../common -I../xilinx_enet -CFLAGS += $(INCS) -HOST_CFLAGS += $(INCS) LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o \ - ../xilinx_enet/emac_adapter.o ../xilinx_enet/xemac.o \ - ../xilinx_enet/xemac_options.o ../xilinx_enet/xemac_polled.o \ - ../xilinx_enet/xemac_intr.o ../xilinx_enet/xemac_g.o \ - ../xilinx_enet/xemac_intr_dma.o ../common/xipif_v1_23_b.o \ - ../common/xbasic_types.o ../common/xdma_channel.o \ - ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \ - ../common/xversion.o \ +COBJS = $(BOARD).o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/xilinx/xupv2p/Makefile b/board/xilinx/xupv2p/Makefile index 9ab5633626..ee9b6d5d29 100644 --- a/board/xilinx/xupv2p/Makefile +++ b/board/xilinx/xupv2p/Makefile @@ -22,25 +22,10 @@ # include $(TOPDIR)/config.mk -ifneq ($(OBJTREE),$(SRCTREE)) -$(shell mkdir -p $(obj)../common) -$(shell mkdir -p $(obj)../xilinx_enet) -endif - -INCS := -I../common -I../xilinx_enet -CFLAGS += $(INCS) -HOST_CFLAGS += $(INCS) LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o \ - ../xilinx_enet/emac_adapter.o ../xilinx_enet/xemac.o \ - ../xilinx_enet/xemac_options.o ../xilinx_enet/xemac_polled.o \ - ../xilinx_enet/xemac_intr.o ../xilinx_enet/xemac_g.o \ - ../xilinx_enet/xemac_intr_dma.o ../common/xipif_v1_23_b.o \ - ../common/xbasic_types.o ../common/xdma_channel.o \ - ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \ - ../common/xversion.o \ +COBJS = $(BOARD).o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) From 6bf3e982aefdb1daf9f5462d482c8f9d1cc90a57 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 10:59:32 +0100 Subject: [PATCH 13/35] microblaze: remove old setting for emac driver Signed-off-by: Michal Simek --- board/xilinx/ml401/xparameters.h | 8 +------- board/xilinx/xupv2p/xparameters.h | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/board/xilinx/ml401/xparameters.h b/board/xilinx/ml401/xparameters.h index 1a116ead1b..becafc8964 100644 --- a/board/xilinx/ml401/xparameters.h +++ b/board/xilinx/ml401/xparameters.h @@ -66,10 +66,4 @@ #define XILINX_SYSACE_MEM_WIDTH 16 /* Ethernet controller is Ethernet_MAC */ -#define XPAR_XEMAC_NUM_INSTANCES 1 -#define XPAR_OPB_ETHERNET_0_DEVICE_ID 0 -#define XPAR_OPB_ETHERNET_0_BASEADDR 0x40c00000 -#define XPAR_OPB_ETHERNET_0_HIGHADDR 0x40c0ffff -#define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1 -#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1 -#define XPAR_OPB_ETHERNET_0_MII_EXIST 1 +#define XILINX_EMACLITE_BASEADDR 0x40C00000 diff --git a/board/xilinx/xupv2p/xparameters.h b/board/xilinx/xupv2p/xparameters.h index a96c693c55..19b81fd889 100644 --- a/board/xilinx/xupv2p/xparameters.h +++ b/board/xilinx/xupv2p/xparameters.h @@ -55,10 +55,4 @@ #define XILINX_SYSACE_MEM_WIDTH 16 /* Ethernet controller is Ethernet_MAC */ -#define XPAR_XEMAC_NUM_INSTANCES 1 -#define XPAR_OPB_ETHERNET_0_DEVICE_ID 0 -#define XPAR_OPB_ETHERNET_0_BASEADDR 0x40c00000 -#define XPAR_OPB_ETHERNET_0_HIGHADDR 0x40c0ffff -#define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1 -#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1 -#define XPAR_OPB_ETHERNET_0_MII_EXIST 1 +#define XILINX_EMACLITE_BASEADDR 0x40C00000 From e5845e21224dbe2fe47b11f1cdf95de7f84be7cb Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 11:04:01 +0100 Subject: [PATCH 14/35] microblaze: ML401 and XUPV2P remove emac and emaclite reference Signed-off-by: Michal Simek --- include/configs/ml401.h | 10 ++++++++-- include/configs/xupv2p.h | 14 ++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/include/configs/ml401.h b/include/configs/ml401.h index b32043850e..6db1c1a831 100644 --- a/include/configs/ml401.h +++ b/include/configs/ml401.h @@ -41,8 +41,14 @@ /*#define CFG_RESET_ADDRESS TEXT_BASE*/ /* ethernet */ -#define CONFIG_EMACLITE 1 -#define XPAR_EMAC_0_DEVICE_ID XPAR_OPB_ETHERNET_0_DEVICE_ID +#ifdef XILINX_EMAC_BASEADDR +#define CONFIG_XILINX_EMAC 1 +#else +#ifdef XILINX_EMACLITE_BASEADDR +#define CONFIG_XILINX_EMACLITE 1 +#endif +#endif +#undef ET_DEBUG /* gpio */ #define CFG_GPIO_0 1 diff --git a/include/configs/xupv2p.h b/include/configs/xupv2p.h index c9320c287c..eef4f72e28 100644 --- a/include/configs/xupv2p.h +++ b/include/configs/xupv2p.h @@ -36,10 +36,6 @@ #define CONFIG_BAUDRATE XILINX_UART_BAUDRATE #define CFG_BAUDRATE_TABLE { CONFIG_BAUDRATE } -/* ethernet */ -#define CONFIG_EMAC 1 -#define XPAR_EMAC_0_DEVICE_ID XPAR_XEMAC_NUM_INSTANCES - /* * setting reset address * @@ -51,6 +47,16 @@ */ /* #define CFG_RESET_ADDRESS 0x36000000 */ +/* ethernet */ +#ifdef XILINX_EMAC_BASEADDR +#define CONFIG_XILINX_EMAC 1 +#else +#ifdef XILINX_EMACLITE_BASEADDR +#define CONFIG_XILINX_EMACLITE 1 +#endif +#endif +#undef ET_DEBUG + /* gpio */ #ifdef XILINX_GPIO_BASEADDR #define CFG_GPIO_0 1 From 89c53891b18cbafd29ab8931b40e27ad231b6085 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 12:41:56 +0100 Subject: [PATCH 15/35] microblaze: add Emaclite ethernet driver --- drivers/net/xilinx_emaclite.c | 351 ++++++++++++++++++++++++++++++++++ 1 file changed, 351 insertions(+) create mode 100644 drivers/net/xilinx_emaclite.c diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c new file mode 100644 index 0000000000..9ba4096e81 --- /dev/null +++ b/drivers/net/xilinx_emaclite.c @@ -0,0 +1,351 @@ +/****************************************************************************** + * + * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" + * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND + * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, + * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, + * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION + * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, + * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE + * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY + * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE + * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR + * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF + * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * (C) Copyright 2007-2008 Michal Simek + * Michal SIMEK + * + * (c) Copyright 2003 Xilinx Inc. + * All rights reserved. + * + ******************************************************************************/ + +#include +#include +#include +#include + +#undef DEBUG + +#define ENET_MAX_MTU PKTSIZE +#define ENET_MAX_MTU_ALIGNED PKTSIZE_ALIGN +#define ENET_ADDR_LENGTH 6 + +/* EmacLite constants */ +#define XEL_BUFFER_OFFSET 0x0800 /* Next buffer's offset */ +#define XEL_TPLR_OFFSET 0x07F4 /* Tx packet length */ +#define XEL_TSR_OFFSET 0x07FC /* Tx status */ +#define XEL_RSR_OFFSET 0x17FC /* Rx status */ +#define XEL_RXBUFF_OFFSET 0x1000 /* Receive Buffer */ + +/* Xmit complete */ +#define XEL_TSR_XMIT_BUSY_MASK 0x00000001UL +/* Xmit interrupt enable bit */ +#define XEL_TSR_XMIT_IE_MASK 0x00000008UL +/* Buffer is active, SW bit only */ +#define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000UL +/* Program the MAC address */ +#define XEL_TSR_PROGRAM_MASK 0x00000002UL +/* define for programming the MAC address into the EMAC Lite */ +#define XEL_TSR_PROG_MAC_ADDR (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK) + +/* Transmit packet length upper byte */ +#define XEL_TPLR_LENGTH_MASK_HI 0x0000FF00UL +/* Transmit packet length lower byte */ +#define XEL_TPLR_LENGTH_MASK_LO 0x000000FFUL + +/* Recv complete */ +#define XEL_RSR_RECV_DONE_MASK 0x00000001UL +/* Recv interrupt enable bit */ +#define XEL_RSR_RECV_IE_MASK 0x00000008UL + +typedef struct { + unsigned int baseaddress; /* Base address for device (IPIF) */ + unsigned int nexttxbuffertouse; /* Next TX buffer to write to */ + unsigned int nextrxbuffertouse; /* Next RX buffer to read from */ + unsigned char deviceid; /* Unique ID of device - for future */ +} xemaclite; + +static xemaclite emaclite; + +static char etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */ + +/* hardcoded MAC address for the Xilinx EMAC Core when env is nowhere*/ +#ifdef CFG_ENV_IS_NOWHERE +static u8 emacaddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 }; +#else +static u8 emacaddr[ENET_ADDR_LENGTH]; +#endif + +void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount) +{ + unsigned int i; + u32 alignbuffer; + u32 *to32ptr; + u32 *from32ptr; + u8 *to8ptr; + u8 *from8ptr; + + from32ptr = (u32 *) srcptr; + + /* Word aligned buffer, no correction needed. */ + to32ptr = (u32 *) destptr; + while (bytecount > 3) { + *to32ptr++ = *from32ptr++; + bytecount -= 4; + } + to8ptr = (u8 *) to32ptr; + + alignbuffer = *from32ptr++; + from8ptr = (u8 *) & alignbuffer; + + for (i = 0; i < bytecount; i++) { + *to8ptr++ = *from8ptr++; + } +} + +void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount) +{ + unsigned i; + u32 alignbuffer; + u32 *to32ptr = (u32 *) destptr; + u32 *from32ptr; + u8 *to8ptr; + u8 *from8ptr; + + from32ptr = (u32 *) srcptr; + while (bytecount > 3) { + + *to32ptr++ = *from32ptr++; + bytecount -= 4; + } + + alignbuffer = 0; + to8ptr = (u8 *) & alignbuffer; + from8ptr = (u8 *) from32ptr; + + for (i = 0; i < bytecount; i++) { + *to8ptr++ = *from8ptr++; + } + + *to32ptr++ = alignbuffer; +} + +void eth_halt (void) +{ + debug ("eth_halt\n"); +} + +int eth_init (bd_t * bis) +{ + debug ("EmacLite Initialization Started\n"); + memset (&emaclite, 0, sizeof (xemaclite)); + emaclite.baseaddress = XILINX_EMACLITE_BASEADDR; + + if (!getenv("ethaddr")) { + memcpy(bis->bi_enetaddr, emacaddr, ENET_ADDR_LENGTH); + } + +/* + * TX - TX_PING & TX_PONG initialization + */ + /* Restart PING TX */ + out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0); + /* Copy MAC address */ + xemaclite_alignedwrite (bis->bi_enetaddr, + emaclite.baseaddress, ENET_ADDR_LENGTH); + /* Set the length */ + out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); + /* Update the MAC address in the EMAC Lite */ + out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, XEL_TSR_PROG_MAC_ADDR); + /* Wait for EMAC Lite to finish with the MAC address update */ + while ((in_be32 (emaclite.baseaddress + XEL_TSR_OFFSET) & + XEL_TSR_PROG_MAC_ADDR) != 0) ; + +#ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG + /* The same operation with PONG TX */ + out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0); + xemaclite_alignedwrite (bis->bi_enetaddr, emaclite.baseaddress + + XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH); + out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); + out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, + XEL_TSR_PROG_MAC_ADDR); + while ((in_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + + XEL_BUFFER_OFFSET) & XEL_TSR_PROG_MAC_ADDR) != 0) ; +#endif + +/* + * RX - RX_PING & RX_PONG initialization + */ + /* Write out the value to flush the RX buffer */ + out_be32 (emaclite.baseaddress + XEL_RSR_OFFSET, XEL_RSR_RECV_IE_MASK); +#ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG + out_be32 (emaclite.baseaddress + XEL_RSR_OFFSET + XEL_BUFFER_OFFSET, + XEL_RSR_RECV_IE_MASK); +#endif + + debug ("EmacLite Initialization complete\n"); + return 0; +} + +int xemaclite_txbufferavailable (xemaclite * instanceptr) +{ + u32 reg; + u32 txpingbusy; + u32 txpongbusy; + /* + * Read the other buffer register + * and determine if the other buffer is available + */ + reg = in_be32 (instanceptr->baseaddress + + instanceptr->nexttxbuffertouse + 0); + txpingbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) == + XEL_TSR_XMIT_BUSY_MASK); + + reg = in_be32 (instanceptr->baseaddress + + (instanceptr->nexttxbuffertouse ^ XEL_TSR_OFFSET) + 0); + txpongbusy = ((reg & XEL_TSR_XMIT_BUSY_MASK) == + XEL_TSR_XMIT_BUSY_MASK); + + return (!(txpingbusy && txpongbusy)); +} + +int eth_send (volatile void *ptr, int len) { + + unsigned int reg; + unsigned int baseaddress; + + unsigned maxtry = 1000; + + if (len > ENET_MAX_MTU) + len = ENET_MAX_MTU; + + while (!xemaclite_txbufferavailable (&emaclite) && maxtry) { + udelay (10); + maxtry--; + } + + if (!maxtry) { + printf ("Error: Timeout waiting for ethernet TX buffer\n"); + /* Restart PING TX */ + out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0); +#ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG + out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + + XEL_BUFFER_OFFSET, 0); +#endif + return 0; + } + + /* Determine the expected TX buffer address */ + baseaddress = (emaclite.baseaddress + emaclite.nexttxbuffertouse); + + /* Determine if the expected buffer address is empty */ + reg = in_be32 (baseaddress + XEL_TSR_OFFSET); + if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) + && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET) + & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) { + +#ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG + emaclite.nexttxbuffertouse ^= XEL_BUFFER_OFFSET; +#endif + debug ("Send packet from 0x%x\n", baseaddress); + /* Write the frame to the buffer */ + xemaclite_alignedwrite ((void *) ptr, baseaddress, len); + out_be32 (baseaddress + XEL_TPLR_OFFSET,(len & + (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO))); + reg = in_be32 (baseaddress + XEL_TSR_OFFSET); + reg |= XEL_TSR_XMIT_BUSY_MASK; + if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) { + reg |= XEL_TSR_XMIT_ACTIVE_MASK; + } + out_be32 (baseaddress + XEL_TSR_OFFSET, reg); + return 1; + } +#ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG + /* Switch to second buffer */ + baseaddress ^= XEL_BUFFER_OFFSET; + /* Determine if the expected buffer address is empty */ + reg = in_be32 (baseaddress + XEL_TSR_OFFSET); + if (((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) + && ((in_be32 ((baseaddress) + XEL_TSR_OFFSET) + & XEL_TSR_XMIT_ACTIVE_MASK) == 0)) { + debug ("Send packet from 0x%x\n", baseaddress); + /* Write the frame to the buffer */ + xemaclite_alignedwrite ((void *) ptr, baseaddress, len); + out_be32 (baseaddress + XEL_TPLR_OFFSET,(len & + (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO))); + reg = in_be32 (baseaddress + XEL_TSR_OFFSET); + reg |= XEL_TSR_XMIT_BUSY_MASK; + if ((reg & XEL_TSR_XMIT_IE_MASK) != 0) { + reg |= XEL_TSR_XMIT_ACTIVE_MASK; + } + out_be32 (baseaddress + XEL_TSR_OFFSET, reg); + return 1; + } +#endif + puts ("Error while sending frame\n"); + return 0; +} + +int eth_rx (void) +{ + unsigned int length; + unsigned int reg; + unsigned int baseaddress; + + baseaddress = emaclite.baseaddress + emaclite.nextrxbuffertouse; + reg = in_be32 (baseaddress + XEL_RSR_OFFSET); + debug ("Testing data at address 0x%x\n", baseaddress); + if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { +#ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG + emaclite.nextrxbuffertouse ^= XEL_BUFFER_OFFSET; +#endif + } else { +#ifndef CONFIG_XILINX_EMACLITE_RX_PING_PONG + debug ("No data was available - address 0x%x\n", baseaddress); + return 0; +#else + baseaddress ^= XEL_BUFFER_OFFSET; + reg = in_be32 (baseaddress + XEL_RSR_OFFSET); + if ((reg & XEL_RSR_RECV_DONE_MASK) != + XEL_RSR_RECV_DONE_MASK) { + debug ("No data was available - address 0x%x\n", + baseaddress); + return 0; + } +#endif + } + /* Get the length of the frame that arrived */ + switch(((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC)) & + 0xFFFF0000 ) >> 16) { + case 0x806: + length = 42 + 20; /* FIXME size of ARP */ + debug ("ARP Packet\n"); + break; + case 0x800: + length = 14 + 14 + + (((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0x10)) & + 0xFFFF0000) >> 16); /* FIXME size of IP packet */ + debug ("IP Packet\n"); + break; + default: + debug ("Other Packet\n"); + length = ENET_MAX_MTU; + break; + } + + xemaclite_alignedread ((u32 *) (baseaddress + XEL_RXBUFF_OFFSET), + etherrxbuff, length); + + /* Acknowledge the frame */ + reg = in_be32 (baseaddress + XEL_RSR_OFFSET); + reg &= ~XEL_RSR_RECV_DONE_MASK; + out_be32 (baseaddress + XEL_RSR_OFFSET, reg); + + debug ("Packet receive from 0x%x, length %dB\n", baseaddress, length); + NetReceive ((uchar *) etherrxbuff, length); + return 1; + +} From 6f961b4f461f6cbb83a467d468a02e6078c2b327 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 12:42:29 +0100 Subject: [PATCH 16/35] microblaze: add Emac ethernet driver --- drivers/net/xilinx_emac.c | 462 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 462 insertions(+) create mode 100644 drivers/net/xilinx_emac.c diff --git a/drivers/net/xilinx_emac.c b/drivers/net/xilinx_emac.c new file mode 100644 index 0000000000..c7f1a2a8d7 --- /dev/null +++ b/drivers/net/xilinx_emac.c @@ -0,0 +1,462 @@ +/****************************************************************************** + * + * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" + * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND + * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, + * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, + * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION + * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, + * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE + * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY + * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE + * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR + * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF + * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * (C) Copyright 2007-2008 Michal Simek + * Michal SIMEK + * + * (c) Copyright 2003 Xilinx Inc. + * All rights reserved. + * + ******************************************************************************/ + +#include +#include +#include +#include + +#include + +#undef DEBUG + +typedef struct { + u32 regbaseaddress; /* Base address of registers */ + u32 databaseaddress; /* Base address of data for FIFOs */ +} xpacketfifov100b; + +typedef struct { + u32 baseaddress; /* Base address (of IPIF) */ + u32 isstarted; /* Device is currently started 0-no, 1-yes */ + xpacketfifov100b recvfifo; /* FIFO used to receive frames */ + xpacketfifov100b sendfifo; /* FIFO used to send frames */ +} xemac; + +#define XIIF_V123B_IISR_OFFSET 32UL /* IP interrupt status register */ +#define XIIF_V123B_RESET_MASK 0xAUL +#define XIIF_V123B_RESETR_OFFSET 64UL /* reset register */ + +/* This constant is used with the Reset Register */ +#define XPF_RESET_FIFO_MASK 0x0000000A +#define XPF_COUNT_STATUS_REG_OFFSET 4UL + +/* These constants are used with the Occupancy/Vacancy Count Register. This + * register also contains FIFO status */ +#define XPF_COUNT_MASK 0x0000FFFF +#define XPF_DEADLOCK_MASK 0x20000000 + +/* Offset of the MAC registers from the IPIF base address */ +#define XEM_REG_OFFSET 0x1100UL + +/* + * Register offsets for the Ethernet MAC. Each register is 32 bits. + */ +#define XEM_ECR_OFFSET (XEM_REG_OFFSET + 0x4) /* MAC Control */ +#define XEM_SAH_OFFSET (XEM_REG_OFFSET + 0xC) /* Station addr, high */ +#define XEM_SAL_OFFSET (XEM_REG_OFFSET + 0x10) /* Station addr, low */ +#define XEM_RPLR_OFFSET (XEM_REG_OFFSET + 0x1C) /* Rx packet length */ +#define XEM_TPLR_OFFSET (XEM_REG_OFFSET + 0x20) /* Tx packet length */ +#define XEM_TSR_OFFSET (XEM_REG_OFFSET + 0x24) /* Tx status */ + +#define XEM_PFIFO_OFFSET 0x2000UL +/* Tx registers */ +#define XEM_PFIFO_TXREG_OFFSET (XEM_PFIFO_OFFSET + 0x0) +/* Rx registers */ +#define XEM_PFIFO_RXREG_OFFSET (XEM_PFIFO_OFFSET + 0x10) +/* Tx keyhole */ +#define XEM_PFIFO_TXDATA_OFFSET (XEM_PFIFO_OFFSET + 0x100) +/* Rx keyhole */ +#define XEM_PFIFO_RXDATA_OFFSET (XEM_PFIFO_OFFSET + 0x200) + +/* + * EMAC Interrupt Registers (Status and Enable) masks. These registers are + * part of the IPIF IP Interrupt registers + */ +/* A mask for all transmit interrupts, used in polled mode */ +#define XEM_EIR_XMIT_ALL_MASK (XEM_EIR_XMIT_DONE_MASK |\ + XEM_EIR_XMIT_ERROR_MASK | \ + XEM_EIR_XMIT_SFIFO_EMPTY_MASK |\ + XEM_EIR_XMIT_LFIFO_FULL_MASK) + +/* Xmit complete */ +#define XEM_EIR_XMIT_DONE_MASK 0x00000001UL +/* Recv complete */ +#define XEM_EIR_RECV_DONE_MASK 0x00000002UL +/* Xmit error */ +#define XEM_EIR_XMIT_ERROR_MASK 0x00000004UL +/* Recv error */ +#define XEM_EIR_RECV_ERROR_MASK 0x00000008UL +/* Xmit status fifo empty */ +#define XEM_EIR_XMIT_SFIFO_EMPTY_MASK 0x00000010UL +/* Recv length fifo empty */ +#define XEM_EIR_RECV_LFIFO_EMPTY_MASK 0x00000020UL +/* Xmit length fifo full */ +#define XEM_EIR_XMIT_LFIFO_FULL_MASK 0x00000040UL +/* Recv length fifo overrun */ +#define XEM_EIR_RECV_LFIFO_OVER_MASK 0x00000080UL +/* Recv length fifo underrun */ +#define XEM_EIR_RECV_LFIFO_UNDER_MASK 0x00000100UL +/* Xmit status fifo overrun */ +#define XEM_EIR_XMIT_SFIFO_OVER_MASK 0x00000200UL +/* Transmit status fifo underrun */ +#define XEM_EIR_XMIT_SFIFO_UNDER_MASK 0x00000400UL +/* Transmit length fifo overrun */ +#define XEM_EIR_XMIT_LFIFO_OVER_MASK 0x00000800UL +/* Transmit length fifo underrun */ +#define XEM_EIR_XMIT_LFIFO_UNDER_MASK 0x00001000UL +/* Transmit pause pkt received */ +#define XEM_EIR_XMIT_PAUSE_MASK 0x00002000UL + +/* + * EMAC Control Register (ECR) + */ +/* Full duplex mode */ +#define XEM_ECR_FULL_DUPLEX_MASK 0x80000000UL +/* Reset transmitter */ +#define XEM_ECR_XMIT_RESET_MASK 0x40000000UL +/* Enable transmitter */ +#define XEM_ECR_XMIT_ENABLE_MASK 0x20000000UL +/* Reset receiver */ +#define XEM_ECR_RECV_RESET_MASK 0x10000000UL +/* Enable receiver */ +#define XEM_ECR_RECV_ENABLE_MASK 0x08000000UL +/* Enable PHY */ +#define XEM_ECR_PHY_ENABLE_MASK 0x04000000UL +/* Enable xmit pad insert */ +#define XEM_ECR_XMIT_PAD_ENABLE_MASK 0x02000000UL +/* Enable xmit FCS insert */ +#define XEM_ECR_XMIT_FCS_ENABLE_MASK 0x01000000UL +/* Enable unicast addr */ +#define XEM_ECR_UNICAST_ENABLE_MASK 0x00020000UL +/* Enable broadcast addr */ +#define XEM_ECR_BROAD_ENABLE_MASK 0x00008000UL + +/* + * Transmit Status Register (TSR) + */ +/* Transmit excess deferral */ +#define XEM_TSR_EXCESS_DEFERRAL_MASK 0x80000000UL +/* Transmit late collision */ +#define XEM_TSR_LATE_COLLISION_MASK 0x01000000UL + +#define ENET_MAX_MTU PKTSIZE +#define ENET_ADDR_LENGTH 6 + +static unsigned int etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */ + +static u8 emacaddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 }; + +static xemac emac; + +void eth_halt(void) +{ + debug ("eth_halt\n"); +} + +int eth_init(bd_t * bis) +{ + u32 helpreg; + debug ("EMAC Initialization Started\n\r"); + + if (emac.isstarted) { + puts("Emac is started\n"); + return 0; + } + + memset (&emac, 0, sizeof (xemac)); + + emac.baseaddress = XILINX_EMAC_BASEADDR; + + /* Setting up FIFOs */ + emac.recvfifo.regbaseaddress = emac.baseaddress + + XEM_PFIFO_RXREG_OFFSET; + emac.recvfifo.databaseaddress = emac.baseaddress + + XEM_PFIFO_RXDATA_OFFSET; + out_be32 (emac.recvfifo.regbaseaddress, XPF_RESET_FIFO_MASK); + + emac.sendfifo.regbaseaddress = emac.baseaddress + + XEM_PFIFO_TXREG_OFFSET; + emac.sendfifo.databaseaddress = emac.baseaddress + + XEM_PFIFO_TXDATA_OFFSET; + out_be32 (emac.sendfifo.regbaseaddress, XPF_RESET_FIFO_MASK); + + /* Reset the entire IPIF */ + out_be32 (emac.baseaddress + XIIF_V123B_RESETR_OFFSET, + XIIF_V123B_RESET_MASK); + + /* Stopping EMAC for setting up MAC */ + helpreg = in_be32 (emac.baseaddress + XEM_ECR_OFFSET); + helpreg &= ~(XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK); + out_be32 (emac.baseaddress + XEM_ECR_OFFSET, helpreg); + + if (!getenv("ethaddr")) { + memcpy(bis->bi_enetaddr, emacaddr, ENET_ADDR_LENGTH); + } + + /* Set the device station address high and low registers */ + helpreg = (bis->bi_enetaddr[0] << 8) | bis->bi_enetaddr[1]; + out_be32 (emac.baseaddress + XEM_SAH_OFFSET, helpreg); + helpreg = (bis->bi_enetaddr[2] << 24) | (bis->bi_enetaddr[3] << 16) | + (bis->bi_enetaddr[4] << 8) | bis->bi_enetaddr[5]; + out_be32 (emac.baseaddress + XEM_SAL_OFFSET, helpreg); + + helpreg = XEM_ECR_UNICAST_ENABLE_MASK | XEM_ECR_BROAD_ENABLE_MASK | + XEM_ECR_FULL_DUPLEX_MASK | XEM_ECR_XMIT_FCS_ENABLE_MASK | + XEM_ECR_XMIT_PAD_ENABLE_MASK | XEM_ECR_PHY_ENABLE_MASK; + out_be32 (emac.baseaddress + XEM_ECR_OFFSET, helpreg); + + emac.isstarted = 1; + + /* Enable the transmitter, and receiver */ + helpreg = in_be32 (emac.baseaddress + XEM_ECR_OFFSET); + helpreg &= ~(XEM_ECR_XMIT_RESET_MASK | XEM_ECR_RECV_RESET_MASK); + helpreg |= (XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK); + out_be32 (emac.baseaddress + XEM_ECR_OFFSET, helpreg); + + printf("EMAC Initialization complete\n\r"); + return 0; +} + +int eth_send(volatile void *ptr, int len) +{ + u32 intrstatus; + u32 xmitstatus; + u32 fifocount; + u32 wordcount; + u32 extrabytecount; + u32 *wordbuffer = (u32 *) ptr; + + if (len > ENET_MAX_MTU) + len = ENET_MAX_MTU; + + /* + * Check for overruns and underruns for the transmit status and length + * FIFOs and make sure the send packet FIFO is not deadlocked. + * Any of these conditions is bad enough that we do not want to + * continue. The upper layer software should reset the device to resolve + * the error. + */ + intrstatus = in_be32 ((emac.baseaddress) + XIIF_V123B_IISR_OFFSET); + if (intrstatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK | + XEM_EIR_XMIT_LFIFO_OVER_MASK)) { + debug ("Transmitting overrun error\n"); + return 0; + } else if (intrstatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK | + XEM_EIR_XMIT_LFIFO_UNDER_MASK)) { + debug ("Transmitting underrun error\n"); + return 0; + } else if (in_be32 (emac.sendfifo.regbaseaddress + + XPF_COUNT_STATUS_REG_OFFSET) & XPF_DEADLOCK_MASK) { + debug ("Transmitting fifo error\n"); + return 0; + } + + /* + * Before writing to the data FIFO, make sure the length FIFO is not + * full. The data FIFO might not be full yet even though the length FIFO + * is. This avoids an overrun condition on the length FIFO and keeps the + * FIFOs in sync. + * + * Clear the latched LFIFO_FULL bit so next time around the most + * current status is represented + */ + if (intrstatus & XEM_EIR_XMIT_LFIFO_FULL_MASK) { + out_be32 ((emac.baseaddress) + XIIF_V123B_IISR_OFFSET, + intrstatus & XEM_EIR_XMIT_LFIFO_FULL_MASK); + debug ("Fifo is full\n"); + return 0; + } + + /* get the count of how many words may be inserted into the FIFO */ + fifocount = in_be32 (emac.sendfifo.regbaseaddress + + XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK; + wordcount = len >> 2; + extrabytecount = len & 0x3; + + if (fifocount < wordcount) { + debug ("Sending packet is larger then size of FIFO\n"); + return 0; + } + + for (fifocount = 0; fifocount < wordcount; fifocount++) { + out_be32 (emac.sendfifo.databaseaddress, wordbuffer[fifocount]); + } + if (extrabytecount > 0) { + u32 lastword = 0; + u8 *extrabytesbuffer = (u8 *) (wordbuffer + wordcount); + + if (extrabytecount == 1) { + lastword = extrabytesbuffer[0] << 24; + } else if (extrabytecount == 2) { + lastword = extrabytesbuffer[0] << 24 | + extrabytesbuffer[1] << 16; + } else if (extrabytecount == 3) { + lastword = extrabytesbuffer[0] << 24 | + extrabytesbuffer[1] << 16 | + extrabytesbuffer[2] << 8; + } + out_be32 (emac.sendfifo.databaseaddress, lastword); + } + + /* Loop on the MAC's status to wait for any pause to complete */ + intrstatus = in_be32 ((emac.baseaddress) + XIIF_V123B_IISR_OFFSET); + while ((intrstatus & XEM_EIR_XMIT_PAUSE_MASK) != 0) { + intrstatus = in_be32 ((emac.baseaddress) + + XIIF_V123B_IISR_OFFSET); + /* Clear the pause status from the transmit status register */ + out_be32 ((emac.baseaddress) + XIIF_V123B_IISR_OFFSET, + intrstatus & XEM_EIR_XMIT_PAUSE_MASK); + } + + /* + * Set the MAC's transmit packet length register to tell it to transmit + */ + out_be32 (emac.baseaddress + XEM_TPLR_OFFSET, len); + + /* + * Loop on the MAC's status to wait for the transmit to complete. + * The transmit status is in the FIFO when the XMIT_DONE bit is set. + */ + do { + intrstatus = in_be32 ((emac.baseaddress) + + XIIF_V123B_IISR_OFFSET); + } + while ((intrstatus & XEM_EIR_XMIT_DONE_MASK) == 0); + + xmitstatus = in_be32 (emac.baseaddress + XEM_TSR_OFFSET); + + if (intrstatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK | + XEM_EIR_XMIT_LFIFO_OVER_MASK)) { + debug ("Transmitting overrun error\n"); + return 0; + } else if (intrstatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK | + XEM_EIR_XMIT_LFIFO_UNDER_MASK)) { + debug ("Transmitting underrun error\n"); + return 0; + } + + /* Clear the interrupt status register of transmit statuses */ + out_be32 ((emac.baseaddress) + XIIF_V123B_IISR_OFFSET, + intrstatus & XEM_EIR_XMIT_ALL_MASK); + + /* + * Collision errors are stored in the transmit status register + * instead of the interrupt status register + */ + if ((xmitstatus & XEM_TSR_EXCESS_DEFERRAL_MASK) || + (xmitstatus & XEM_TSR_LATE_COLLISION_MASK)) { + debug ("Transmitting collision error\n"); + return 0; + } + return 1; +} + +int eth_rx(void) +{ + u32 pktlength; + u32 intrstatus; + u32 fifocount; + u32 wordcount; + u32 extrabytecount; + u32 lastword; + u8 *extrabytesbuffer; + + if (in_be32 (emac.recvfifo.regbaseaddress + XPF_COUNT_STATUS_REG_OFFSET) + & XPF_DEADLOCK_MASK) { + out_be32 (emac.recvfifo.regbaseaddress, XPF_RESET_FIFO_MASK); + debug ("Receiving FIFO deadlock\n"); + return 0; + } + + /* + * Get the interrupt status to know what happened (whether an error + * occurred and/or whether frames have been received successfully). + * When clearing the intr status register, clear only statuses that + * pertain to receive. + */ + intrstatus = in_be32 ((emac.baseaddress) + XIIF_V123B_IISR_OFFSET); + /* + * Before reading from the length FIFO, make sure the length FIFO is not + * empty. We could cause an underrun error if we try to read from an + * empty FIFO. + */ + if (!(intrstatus & XEM_EIR_RECV_DONE_MASK)) { + /* debug ("Receiving FIFO is empty\n"); */ + return 0; + } + + /* + * Determine, from the MAC, the length of the next packet available + * in the data FIFO (there should be a non-zero length here) + */ + pktlength = in_be32 (emac.baseaddress + XEM_RPLR_OFFSET); + if (!pktlength) { + return 0; + } + + /* + * Write the RECV_DONE bit in the status register to clear it. This bit + * indicates the RPLR is non-empty, and we know it's set at this point. + * We clear it so that subsequent entry into this routine will reflect + * the current status. This is done because the non-empty bit is latched + * in the IPIF, which means it may indicate a non-empty condition even + * though there is something in the FIFO. + */ + out_be32 ((emac.baseaddress) + XIIF_V123B_IISR_OFFSET, + XEM_EIR_RECV_DONE_MASK); + + fifocount = in_be32 (emac.recvfifo.regbaseaddress + + XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK; + + if ((fifocount * 4) < pktlength) { + debug ("Receiving FIFO is smaller than packet size.\n"); + return 0; + } + + wordcount = pktlength >> 2; + extrabytecount = pktlength & 0x3; + + for (fifocount = 0; fifocount < wordcount; fifocount++) { + etherrxbuff[fifocount] = + in_be32 (emac.recvfifo.databaseaddress); + } + + /* + * if there are extra bytes to handle, read the last word from the FIFO + * and insert the extra bytes into the buffer + */ + if (extrabytecount > 0) { + extrabytesbuffer = (u8 *) (etherrxbuff + wordcount); + + lastword = in_be32 (emac.recvfifo.databaseaddress); + + /* + * one extra byte in the last word, put the byte into the next + * location of the buffer, bytes in a word of the FIFO are + * ordered from most significant byte to least + */ + if (extrabytecount == 1) { + extrabytesbuffer[0] = (u8) (lastword >> 24); + } else if (extrabytecount == 2) { + extrabytesbuffer[0] = (u8) (lastword >> 24); + extrabytesbuffer[1] = (u8) (lastword >> 16); + } else if (extrabytecount == 3) { + extrabytesbuffer[0] = (u8) (lastword >> 24); + extrabytesbuffer[1] = (u8) (lastword >> 16); + extrabytesbuffer[2] = (u8) (lastword >> 8); + } + } + NetReceive((uchar *)etherrxbuff, pktlength); + return 1; +} From 868cde5310f88234b774878e4f06e79df10a88b3 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 11:08:01 +0100 Subject: [PATCH 17/35] microblaze: Add Emac driver to Makefile Signed-off-by: Michal Simek --- drivers/net/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6f0225b586..5f6e195d01 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -61,6 +61,7 @@ COBJS-y += tsec.o COBJS-y += tsi108_eth.o COBJS-y += uli526x.o COBJS-y += vsc7385.o +COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) From 0b20f250877441460fb79d72192954abe8498834 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 11:08:31 +0100 Subject: [PATCH 18/35] microblaze: Add Emaclite driver to Makefile Signed-off-by: Michal Simek --- drivers/net/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 5f6e195d01..d5e413b79c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -62,6 +62,7 @@ COBJS-y += tsi108_eth.o COBJS-y += uli526x.o COBJS-y += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o +COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) From af7ae1a411c67ee9d17a66d17ce50b374f3dd4e7 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 12:13:03 +0100 Subject: [PATCH 19/35] microblaze: clean uart16550 and uartlite handling Signed-off-by: Michal Simek --- board/xilinx/ml401/xparameters.h | 4 ++-- board/xilinx/xupv2p/xparameters.h | 4 ++-- include/configs/ml401.h | 17 +++++++++++++++-- include/configs/xupv2p.h | 17 +++++++++++++++-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/board/xilinx/ml401/xparameters.h b/board/xilinx/ml401/xparameters.h index becafc8964..d805061c0d 100644 --- a/board/xilinx/ml401/xparameters.h +++ b/board/xilinx/ml401/xparameters.h @@ -41,8 +41,8 @@ #define XILINX_TIMER_IRQ 0 /* Uart pheriphery is RS232_Uart */ -#define XILINX_UART_BASEADDR 0x40600000 -#define XILINX_UART_BAUDRATE 115200 +#define XILINX_UARTLITE_BASEADDR 0x40600000 +#define XILINX_UARTLITE_BAUDRATE 115200 /* IIC pheriphery is IIC_EEPROM */ #define XILINX_IIC_0_BASEADDR 0x40800000 diff --git a/board/xilinx/xupv2p/xparameters.h b/board/xilinx/xupv2p/xparameters.h index 19b81fd889..9e5ebdabc1 100644 --- a/board/xilinx/xupv2p/xparameters.h +++ b/board/xilinx/xupv2p/xparameters.h @@ -37,8 +37,8 @@ #define XILINX_TIMER_IRQ 1 /* Uart pheriphery is RS232_Uart_1 */ -#define XILINX_UART_BASEADDR 0x40600000 -#define XILINX_UART_BAUDRATE 115200 +#define XILINX_UARTLITE_BASEADDR 0x40600000 +#define XILINX_UARTLITE_BAUDRATE 115200 /* GPIO is LEDs_4Bit*/ #define XILINX_GPIO_BASEADDR 0x40000000 diff --git a/include/configs/ml401.h b/include/configs/ml401.h index 6db1c1a831..1a2cb0aeed 100644 --- a/include/configs/ml401.h +++ b/include/configs/ml401.h @@ -32,10 +32,23 @@ #define CONFIG_ML401 1 /* ML401 Board */ /* uart */ +#ifdef XILINX_UARTLITE_BASEADDR #define CONFIG_XILINX_UARTLITE -#define CONFIG_SERIAL_BASE XILINX_UART_BASEADDR -#define CONFIG_BAUDRATE XILINX_UART_BAUDRATE +#define CONFIG_SERIAL_BASE XILINX_UARTLITE_BASEADDR +#define CONFIG_BAUDRATE XILINX_UARTLITE_BAUDRATE #define CFG_BAUDRATE_TABLE { CONFIG_BAUDRATE } +#else +#ifdef XILINX_UART16550_BASEADDR +#define CFG_NS16550 +#define CFG_NS16550_SERIAL +#define CFG_NS16550_REG_SIZE 4 +#define CONFIG_CONS_INDEX 1 +#define CFG_NS16550_COM1 XILINX_UART16550_BASEADDR +#define CFG_NS16550_CLK XILINX_UART16550_CLOCK_HZ +#define CONFIG_BAUDRATE 115200 +#define CFG_BAUDRATE_TABLE { 9600, 115200 } +#endif +#endif /* setting reset address */ /*#define CFG_RESET_ADDRESS TEXT_BASE*/ diff --git a/include/configs/xupv2p.h b/include/configs/xupv2p.h index eef4f72e28..f86b3b9549 100644 --- a/include/configs/xupv2p.h +++ b/include/configs/xupv2p.h @@ -31,10 +31,23 @@ #define CONFIG_XUPV2P 1 /* uart */ +#ifdef XILINX_UARTLITE_BASEADDR #define CONFIG_XILINX_UARTLITE -#define CONFIG_SERIAL_BASE XILINX_UART_BASEADDR -#define CONFIG_BAUDRATE XILINX_UART_BAUDRATE +#define CONFIG_SERIAL_BASE XILINX_UARTLITE_BASEADDR +#define CONFIG_BAUDRATE XILINX_UARTLITE_BAUDRATE #define CFG_BAUDRATE_TABLE { CONFIG_BAUDRATE } +#else +#ifdef XILINX_UART16550_BASEADDR +#define CFG_NS16550 +#define CFG_NS16550_SERIAL +#define CFG_NS16550_REG_SIZE 4 +#define CONFIG_CONS_INDEX 1 +#define CFG_NS16550_COM1 XILINX_UART16550_BASEADDR +#define CFG_NS16550_CLK XILINX_UART16550_CLOCK_HZ +#define CONFIG_BAUDRATE 115200 +#define CFG_BAUDRATE_TABLE { 9600, 115200 } +#endif +#endif /* * setting reset address From 4c6a6f02e239236261333759997eeaf86b30b54c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 11:22:48 +0100 Subject: [PATCH 20/35] microblaze: ml401 - add ifdef for GPIO Signed-off-by: Michal Simek --- include/configs/ml401.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/configs/ml401.h b/include/configs/ml401.h index 1a2cb0aeed..b167cb27fb 100644 --- a/include/configs/ml401.h +++ b/include/configs/ml401.h @@ -64,8 +64,10 @@ #undef ET_DEBUG /* gpio */ +#ifdef XILINX_GPIO_BASEADDR #define CFG_GPIO_0 1 #define CFG_GPIO_0_ADDR XILINX_GPIO_BASEADDR +#endif /* interrupt controller */ #define CFG_INTC_0 1 From 188dc16b189143573b1ed90e584bf866d75cdd12 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 11:53:02 +0100 Subject: [PATCH 21/35] microblaze: ml401 fix config file for supporting FDT Signed-off-by: Michal Simek --- include/configs/ml401.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/include/configs/ml401.h b/include/configs/ml401.h index b167cb27fb..360e2e11d2 100644 --- a/include/configs/ml401.h +++ b/include/configs/ml401.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2007 Michal Simek + * (C) Copyright 2007-2008 Michal Simek * * Michal SIMEK * @@ -83,8 +83,8 @@ #define CONFIG_XILINX_CLOCK_FREQ XILINX_CLOCK_FREQ /* FSL */ -#define CFG_FSL_2 -#define FSL_INTR_2 1 +/* #define CFG_FSL_2 */ +/* #define FSL_INTR_2 1 */ /* * memory layout - Example @@ -155,9 +155,9 @@ #else /* !RAMENV */ #define CFG_ENV_IS_IN_FLASH 1 - #define CFG_ENV_ADDR 0x40000 #define CFG_ENV_SECT_SIZE 0x40000 /* 256K(one sector) for env */ - #define CFG_ENV_SIZE 0x2000 + #define CFG_ENV_ADDR (CFG_FLASH_BASE + (2 * CFG_ENV_SECT_SIZE)) + #define CFG_ENV_SIZE 0x40000 #endif /* !RAMBOOT */ #else /* !FLASH */ /* ENV in RAM */ @@ -256,4 +256,7 @@ "256k(u-boot),256k(env),3m(kernel),"\ "1m(romfs),1m(cramfs),-(jffs2)\0" +#define CONFIG_CMDLINE_EDITING +#define CONFIG_OF_LIBFDT 1 + #endif /* __CONFIG_H */ From cf5c679ca04a6b54bf53a55b8b9c29335b387287 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 12:47:19 +0100 Subject: [PATCH 22/35] microblaze: xupv2p fix config file for supporting FDT --- include/configs/xupv2p.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/configs/xupv2p.h b/include/configs/xupv2p.h index f86b3b9549..30fb303c96 100644 --- a/include/configs/xupv2p.h +++ b/include/configs/xupv2p.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2007 Michal Simek + * (C) Copyright 2007-2008 Michal Simek * * Michal SIMEK * @@ -156,6 +156,7 @@ #include #undef CONFIG_CMD_FLASH +#undef CONFIG_CMD_JFFS2 #undef CONFIG_CMD_IMLS #define CONFIG_CMD_ASKENV @@ -203,4 +204,7 @@ #define CONFIG_DOS_PARTITION #endif +#define CONFIG_CMDLINE_EDITING +#define CONFIG_OF_LIBFDT 1 /* flat device tree */ + #endif /* __CONFIG_H */ From 62032deb7214c6d9b4396297e2aaa559bc2f8495 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 11:58:45 +0100 Subject: [PATCH 23/35] microblaze: clean microblaze_config.mk FLAGS are generated by U-BOOT generator. Board specific FLAGS are in board directory Signed-off-by: Michal Simek --- microblaze_config.mk | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/microblaze_config.mk b/microblaze_config.mk index 06ddefa4ce..e44c79e05a 100644 --- a/microblaze_config.mk +++ b/microblaze_config.mk @@ -1,6 +1,8 @@ # +# (C) Copyright 2007-2008 Michal Simek +# Michal SIMEK +# # (C) Copyright 2004 Atmark Techno, Inc. -# # Yasushi SHOJI # # See file CREDITS for list of people who contributed to this @@ -23,15 +25,3 @@ # PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__ - -ifdef CONFIG_MICROBLAZE_HARD_MULT -PLATFORM_CPPFLAGS += -mno-xl-soft-mul -endif - -ifdef CONFIG_MICROBLAZE_HARD_DIV -PLATFORM_CPPFLAGS += -mno-xl-soft-div -endif - -ifdef CONFIG_MICROBLAZE_HARD_BARREL -PLATFORM_CPPFLAGS += -mxl-barrel-shift -endif From f91374f65eae8b42cac329e06ba1c54728278efb Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 28 Mar 2008 12:49:52 +0100 Subject: [PATCH 24/35] microblaze: Sort microblaze boards in MAKEALL script --- MAKEALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAKEALL b/MAKEALL index 2a872acd6a..d1a29cb022 100755 --- a/MAKEALL +++ b/MAKEALL @@ -649,8 +649,8 @@ LIST_nios2=" \ ######################################################################### LIST_microblaze=" \ - suzaku \ ml401 \ + suzaku \ xupv2p \ " From dfc6c7b647dba7ab86749616f0e9e5740deed422 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 9 Apr 2008 11:54:11 +0200 Subject: [PATCH 25/35] ppc: Revert patch 70431e8a that used _start instead of CFG_MONITOR_BASE The patch 70431e8a7393b6b793f77957f95b999fc9a269b8 (Make MPC83xx one step closer to full relocation.) doesn't use CFG_MONITOR_BASE anymore. But on 4xx systems _start currently cannot be used for this calculation. So revert back to the original version for now. Signed-off-by: Stefan Roese --- lib_ppc/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_ppc/board.c b/lib_ppc/board.c index 7d33914492..b2bc4ebc5b 100644 --- a/lib_ppc/board.c +++ b/lib_ppc/board.c @@ -440,7 +440,7 @@ void board_init_f (ulong bootflag) * - monitor code * - board info struct */ - len = (ulong)&_end - (ulong)&_start + EXC_OFF_SYS_RESET; + len = (ulong)&_end - CFG_MONITOR_BASE; /* * Subtract specified amount of memory to hide so that it won't From 756f5dacda3810b094b94bcceffd3ce6c7ff9a28 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 9 Apr 2008 11:58:02 +0200 Subject: [PATCH 26/35] ppc4xx: Fix Canyonlands default environment to work with new image support Since the new image support checks for image overwriting, the default environment needs to get adjusted to use correct addresses. Signed-off-by: Stefan Roese --- include/configs/canyonlands.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/include/configs/canyonlands.h b/include/configs/canyonlands.h index a1c6674b1a..be9432b4cd 100644 --- a/include/configs/canyonlands.h +++ b/include/configs/canyonlands.h @@ -330,19 +330,17 @@ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ ":${hostname}:${netdev}:off panic=1\0" \ "addtty=setenv bootargs ${bootargs} console=ttyS0,${baudrate}\0"\ - "net_nfs=tftp 200000 ${bootfile};" \ - "run nfsargs addip addtty;" \ - "bootm 200000\0" \ - "net_nfs_fdt=tftp 200000 ${bootfile};" \ + "net_nfs=tftp 400000 ${bootfile};" \ "tftp ${fdt_addr} ${fdt_file};" \ "run nfsargs addip addtty;" \ - "bootm 200000 - ${fdt_addr}\0" \ + "bootm 400000 - ${fdt_addr}\0" \ + "net_nfs_fdt=net_nfs\0" \ "flash_nfs=run nfsargs addip addtty;" \ "bootm ${kernel_addr}\0" \ "flash_self=run ramargs addip addtty;" \ "bootm ${kernel_addr} ${ramdisk_addr}\0" \ "rootpath=/opt/eldk/ppc_4xxFP\0" \ - "fdt_addr=400000\0" \ + "fdt_addr=800000\0" \ "kernel_addr=fc000000\0" \ "ramdisk_addr=fc200000\0" \ "initrd_high=30000000\0" \ @@ -352,7 +350,7 @@ "setenv filesize;saveenv\0" \ "upd=run load update\0" \ "nload=tftp 200000 ${hostname}/u-boot-nand.bin\0" \ - "nupdate=nand erase 0 60000;nand write 200000 0 60000;" \ + "nupdate=nand erase 0 100000;nand write 200000 0 100000;" \ "setenv filesize;saveenv\0" \ "nupd=run nload nupdate\0" \ "pciconfighost=1\0" \ From 64e541f4c1b413dd84c7e409f5c2bf328db2ac13 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 11 Apr 2008 07:02:29 +0200 Subject: [PATCH 27/35] ppc4xx: Update Kilauea defconfig to use device-tree booting as default This patch reworks the default environment on Kilauea/Haleakala. Now "net_nfs" for exmaple uses the device-tree style booting formerly know as "net_nfs_fdt". Also the addresses in RAM were changed because of the new image booting support, which check for image overwriting. So the addresses needed togeet adjusted. Signed-off-by: Stefan Roese --- include/configs/kilauea.h | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/include/configs/kilauea.h b/include/configs/kilauea.h index 3f4b8e6906..f4cf42c311 100644 --- a/include/configs/kilauea.h +++ b/include/configs/kilauea.h @@ -243,22 +243,27 @@ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ ":${hostname}:${netdev}:off panic=1\0" \ "addtty=setenv bootargs ${bootargs} console=ttyS0,${baudrate}\0"\ - "net_nfs=tftp 200000 ${bootfile};" \ - "run nfsargs addip addtty;" \ - "bootm 200000\0" \ - "net_nfs_fdt=tftp 200000 ${bootfile};" \ - "tftp ${fdt_addr} ${fdt_file};" \ - "run nfsargs addip addtty;" \ - "bootm 200000 - ${fdt_addr}\0" \ - "flash_nfs=run nfsargs addip addtty;" \ - "bootm ${kernel_addr}\0" \ - "flash_self=run ramargs addip addtty;" \ + "flash_self_old=run ramargs addip addtty;" \ "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "flash_self=run ramargs addip addtty;" \ + "bootm ${kernel_addr} ${ramdisk_addr} ${fdt_addr}\0" \ + "flash_nfs_old=run nfsargs addip addtty;" \ + "bootm ${kernel_addr}\0" \ + "flash_nfs=run nfsargs addip addtty;" \ + "bootm ${kernel_addr} - ${fdt_addr}\0" \ + "net_nfs_old=tftp ${kernel_addr_r} ${bootfile};" \ + "run nfsargs addip addtty;bootm ${kernel_addr_r}\0" \ + "net_nfs=tftp ${kernel_addr_r} ${bootfile}; " \ + "tftp ${fdt_addr_r} ${fdt_file}; " \ + "run nfsargs addip addtty;" \ + "bootm ${kernel_addr_r} - ${fdt_addr_r}\0" \ "rootpath=/opt/eldk/ppc_4xx\0" \ "bootfile=kilauea/uImage\0" \ "fdt_file=kilauea/kilauea.dtb\0" \ - "fdt_addr=400000\0" \ + "kernel_addr_r=400000\0" \ + "fdt_addr_r=800000\0" \ "kernel_addr=fc000000\0" \ + "fdt_addr=fc1e0000\0" \ "ramdisk_addr=fc200000\0" \ "initrd_high=30000000\0" \ "load=tftp 200000 kilauea/u-boot.bin\0" \ From 5b2052e5f5fcce5dbd4d2750a29c0e45bce806e7 Mon Sep 17 00:00:00 2001 From: Eugene O'Brien Date: Fri, 11 Apr 2008 10:00:35 -0400 Subject: [PATCH 28/35] ppc4xx: Fix power mgt definitions for PPC440 Corrected DCR addresses of PPC440EP power management registers. Signed-off-by: Eugene O'Brien --- include/ppc440.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/include/ppc440.h b/include/ppc440.h index 642d1ded76..bb39ad6317 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -1731,17 +1731,10 @@ #else #define CNTRL_DCR_BASE 0x0b0 #endif -#if defined(CONFIG_440GX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) + #define cpc0_er (CNTRL_DCR_BASE+0x00) /* CPM enable register */ #define cpc0_fr (CNTRL_DCR_BASE+0x01) /* CPM force register */ #define cpc0_sr (CNTRL_DCR_BASE+0x02) /* CPM status register */ -#else -#define cpc0_sr (CNTRL_DCR_BASE+0x00) /* CPM status register */ -#define cpc0_er (CNTRL_DCR_BASE+0x01) /* CPM enable register */ -#define cpc0_fr (CNTRL_DCR_BASE+0x02) /* CPM force register */ -#endif #define cpc0_sys0 (CNTRL_DCR_BASE+0x30) /* System configuration reg 0 */ #define cpc0_sys1 (CNTRL_DCR_BASE+0x31) /* System configuration reg 1 */ From f3e04bdc3f360c66801a9048956e61e41a16edba Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 8 Apr 2008 10:45:50 -0500 Subject: [PATCH 29/35] 85xx: Use SVR_SOC_VER instead of SVR_VER The recent change introduced by 'Update SVR numbers to expand support' now requires that we use SVR_SOC_VER instead of SVR_VER if we want to compare against a particular processor id. Signed-off-by: Kumar Gala --- cpu/mpc85xx/cpu_init.c | 2 +- cpu/mpc85xx/spd_sdram.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpu/mpc85xx/cpu_init.c b/cpu/mpc85xx/cpu_init.c index fce0c4805a..e3240b519e 100644 --- a/cpu/mpc85xx/cpu_init.c +++ b/cpu/mpc85xx/cpu_init.c @@ -272,7 +272,7 @@ int cpu_init_r(void) uint l2srbar; svr = get_svr(); - ver = SVR_VER(svr); + ver = SVR_SOC_VER(svr); asm("msync;isync"); cache_ctl = l2cache->l2ctl; diff --git a/cpu/mpc85xx/spd_sdram.c b/cpu/mpc85xx/spd_sdram.c index abc63c414b..435458a189 100644 --- a/cpu/mpc85xx/spd_sdram.c +++ b/cpu/mpc85xx/spd_sdram.c @@ -306,7 +306,7 @@ spd_sdram(void) * Adjust DDR II IO voltage biasing. * Only 8548 rev 1 needs the fix */ - if ((SVR_VER(get_svr()) == SVR_8548_E) && + if ((SVR_SOC_VER(get_svr()) == SVR_8548_E) && (SVR_MJREV(get_svr()) == 1) && (spd.mem_type == SPD_MEMTYPE_DDR2)) { volatile ccsr_gur_t *gur = (void *)(CFG_MPC85xx_GUTS_ADDR); From 97b3ecb575a92fa34c1765229dbc06f2b662f139 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 9 Apr 2008 04:20:57 -0500 Subject: [PATCH 30/35] 85xx: Fix detection of MP cpu spin up We were looking at the wrong memory offset to determine of a secondary cpu had been spun up or not. Also added a warning message if the all the secondary cpus we expect don't spin up. Signed-off-by: Kumar Gala --- cpu/mpc85xx/mp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpu/mpc85xx/mp.c b/cpu/mpc85xx/mp.c index 7b10fba0a6..e733f7b00a 100644 --- a/cpu/mpc85xx/mp.c +++ b/cpu/mpc85xx/mp.c @@ -154,7 +154,7 @@ static void pq3_mp_up(unsigned long bootpg) while (timeout) { int i; for (i = 1; i < CONFIG_NR_CPUS; i++) { - if (table[i * NUM_BOOT_ENTRY]) + if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER]) cpu_up_mask |= (1 << i); }; @@ -165,6 +165,10 @@ static void pq3_mp_up(unsigned long bootpg) timeout--; } + if (timeout == 0) + printf("CPU up timeout. CPU up mask is %x should be %x\n", + cpu_up_mask, up); + /* enable time base at the platform */ if (whoami) devdisr |= MPC85xx_DEVDISR_TB1; From 1ac4f320bf0b593aa0a741f2d649a8ece8838672 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 2 Apr 2008 13:41:21 +0200 Subject: [PATCH 31/35] mpc837xerdb: Fix warning: implicit declaration of function 'fdt_fixup_dr_usb' Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Kim Phillips --- board/freescale/mpc837xerdb/mpc837xerdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/freescale/mpc837xerdb/mpc837xerdb.c b/board/freescale/mpc837xerdb/mpc837xerdb.c index e054f4e44d..f73fd5aa55 100644 --- a/board/freescale/mpc837xerdb/mpc837xerdb.c +++ b/board/freescale/mpc837xerdb/mpc837xerdb.c @@ -16,10 +16,10 @@ #include #include #include +#include #include #include - #if defined(CFG_DRAM_TEST) int testdram(void) From 2000784818f043db7ca60e2846a72d097766b894 Mon Sep 17 00:00:00 2001 From: Dave Liu Date: Thu, 3 Apr 2008 16:28:29 +0800 Subject: [PATCH 32/35] mpc83xx: Fix the SATA clock setting of 837x targets Currently the SATA controller clock is configured as CSB clock, usually the CSB clock is 400/333/266MHz. However, The SATA IP block is only guaranteed to operate up to 200 MHz as stated in the HW spec. The bug is reported by Joe D'Abbraccio This patch makes the SATA clock as half of CSB clock. Signed-off-by: Dave Liu Signed-off-by: Kim Phillips --- include/configs/MPC837XEMDS.h | 2 +- include/configs/MPC837XERDB.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/configs/MPC837XEMDS.h b/include/configs/MPC837XEMDS.h index 7c4e76e273..7fc0f7ef85 100644 --- a/include/configs/MPC837XEMDS.h +++ b/include/configs/MPC837XEMDS.h @@ -96,7 +96,7 @@ */ #define CFG_SCCR_TSEC1CM 1 /* CSB:eTSEC1 = 1:1 */ #define CFG_SCCR_TSEC2CM 1 /* CSB:eTSEC2 = 1:1 */ -#define CFG_SCCR_SATACM SCCR_SATACM_1 /* CSB:SATA[0:3] = 1:1 */ +#define CFG_SCCR_SATACM SCCR_SATACM_2 /* CSB:SATA[0:3] = 2:1 */ /* * System IO Config diff --git a/include/configs/MPC837XERDB.h b/include/configs/MPC837XERDB.h index eaac525a35..c698ff84c6 100644 --- a/include/configs/MPC837XERDB.h +++ b/include/configs/MPC837XERDB.h @@ -108,7 +108,7 @@ /* System Clock Configuration Register */ #define CFG_SCCR_TSEC1CM 1 /* eTSEC1 clock mode (0-3) */ #define CFG_SCCR_TSEC2CM 1 /* eTSEC2 clock mode (0-3) */ -#define CFG_SCCR_SATACM SCCR_SATACM_1 /* SATA1-4 clock mode (0-3) */ +#define CFG_SCCR_SATACM SCCR_SATACM_2 /* SATA1-4 clock mode (0-3) */ /* * System IO Config From 5fb5a689d822ca61e814bd523fc930af335242fa Mon Sep 17 00:00:00 2001 From: Dave Liu Date: Mon, 31 Mar 2008 17:05:12 +0800 Subject: [PATCH 33/35] mpc83xx: Fix the bug of serdes initialization Currently the serdes will not be initializated due to the partid's error. Signed-off-by: Dave Liu Signed-off-by: Kim Phillips --- board/freescale/mpc837xemds/mpc837xemds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/freescale/mpc837xemds/mpc837xemds.c b/board/freescale/mpc837xemds/mpc837xemds.c index f7cd5fe176..40a505b1d4 100644 --- a/board/freescale/mpc837xemds/mpc837xemds.c +++ b/board/freescale/mpc837xemds/mpc837xemds.c @@ -36,7 +36,7 @@ int board_early_init_f(void) u32 spridr = in_be32(&immr->sysconf.spridr); /* we check only part num, and don't look for CPU revisions */ - switch (spridr) { + switch (PARTID_NO_E(spridr)) { case SPR_8377: fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA, FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); From 3f9c542d3d69b1a10a5e193e779133a0454d1f44 Mon Sep 17 00:00:00 2001 From: Lee Nipper Date: Thu, 10 Apr 2008 09:35:06 -0500 Subject: [PATCH 34/35] mpc83xx: Update DIMM data bus width test to support 40-bit width 32-bit wide ECC memory modules report 40-bit width. Changed the DIMM data bus width test to 'less than 64' instead of 'equal 32'. Signed-off-by: Lee Nipper Signed-off-by: Kim Phillips --- cpu/mpc83xx/spd_sdram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index 97ac7bb3d9..70cd410298 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -601,7 +601,7 @@ long int spd_sdram() debug("DDR:timing_cfg_2=0x%08x\n", ddr->timing_cfg_2); /* Check DIMM data bus width */ - if (spd.dataw_lsb == 0x20) { + if (spd.dataw_lsb < 64) { if (spd.mem_type == SPD_MEMTYPE_DDR) burstlen = 0x03; /* 32 bit data bus, burst len is 8 */ else @@ -763,7 +763,7 @@ long int spd_sdram() sdram_cfg |= SDRAM_CFG_RD_EN; /* The DIMM is 32bit width */ - if (spd.dataw_lsb == 0x20) { + if (spd.dataw_lsb < 64) { if (spd.mem_type == SPD_MEMTYPE_DDR) sdram_cfg |= SDRAM_CFG_32_BE | SDRAM_CFG_8_BE; if (spd.mem_type == SPD_MEMTYPE_DDR2) From 96ef831f713289afba19da0c8f905e99da2b23e0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 3 Apr 2008 13:36:02 +0200 Subject: [PATCH 35/35] cfi_flash: Support buffered writes on non-standard Spansion NOR flash Some NOR flash chip from Spansion, for example, the s29ws-n MirrorBit series require different addresses for buffered write commands. Define a configuration option to support buffered writes on those chips. A more elegant solution would be to automatically detect those chips by parsing their CFI records, but that would require introduction of a fixup table into the cfi_flash driver. Signed-off-by: Guennadi Liakhovetski --- README | 7 +++++++ drivers/mtd/cfi_flash.c | 46 ++++++++++++++--------------------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/README b/README index 5d059e73c6..b29a0d2581 100644 --- a/README +++ b/README @@ -2040,6 +2040,13 @@ Configuration Settings: This option also enables the building of the cfi_flash driver in the drivers directory +- CFG_FLASH_USE_BUFFER_WRITE + Use buffered writes to flash. + +- CONFIG_FLASH_SPANSION_S29WS_N + s29ws-n MirrorBit flash has non-standard addresses for buffered + write commands. + - CFG_FLASH_QUIET_TEST If this option is defined, the common CFI flash doesn't print it's warning upon not recognized FLASH banks. This diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index 40fddcddad..e3cfb8a1ac 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -844,25 +844,29 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, void *dst = map_physmem(dest, len, MAP_NOCACHE); void *dst2 = dst; int flag = 0; + uint offset = 0; + unsigned int shift; switch (info->portwidth) { case FLASH_CFI_8BIT: - cnt = len; + shift = 0; break; case FLASH_CFI_16BIT: - cnt = len >> 1; + shift = 1; break; case FLASH_CFI_32BIT: - cnt = len >> 2; + shift = 2; break; case FLASH_CFI_64BIT: - cnt = len >> 3; + shift = 3; break; default: retcode = ERR_INVAL; goto out_unmap; } + cnt = len >> shift; + while ((cnt-- > 0) && (flag == 0)) { switch (info->portwidth) { case FLASH_CFI_8BIT: @@ -906,23 +910,7 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, if (retcode == ERR_OK) { /* reduce the number of loops by the width of * the port */ - switch (info->portwidth) { - case FLASH_CFI_8BIT: - cnt = len; - break; - case FLASH_CFI_16BIT: - cnt = len >> 1; - break; - case FLASH_CFI_32BIT: - cnt = len >> 2; - break; - case FLASH_CFI_64BIT: - cnt = len >> 3; - break; - default: - retcode = ERR_INVAL; - goto out_unmap; - } + cnt = len >> shift; flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) { switch (info->portwidth) { @@ -959,36 +947,34 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, case CFI_CMDSET_AMD_STANDARD: case CFI_CMDSET_AMD_EXTENDED: flash_unlock_seq(info,0); - flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER); + +#ifdef CONFIG_FLASH_SPANSION_S29WS_N + offset = ((unsigned long)dst - info->start[sector]) >> shift; +#endif + flash_write_cmd(info, sector, offset, AMD_CMD_WRITE_TO_BUFFER); + cnt = len >> shift; + flash_write_cmd(info, sector, offset, (uchar)cnt - 1); switch (info->portwidth) { case FLASH_CFI_8BIT: - cnt = len; - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) { flash_write8(flash_read8(src), dst); src += 1, dst += 1; } break; case FLASH_CFI_16BIT: - cnt = len >> 1; - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) { flash_write16(flash_read16(src), dst); src += 2, dst += 2; } break; case FLASH_CFI_32BIT: - cnt = len >> 2; - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) { flash_write32(flash_read32(src), dst); src += 4, dst += 4; } break; case FLASH_CFI_64BIT: - cnt = len >> 3; - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); while (cnt-- > 0) { flash_write64(flash_read64(src), dst); src += 8, dst += 8;