summaryrefslogtreecommitdiff
path: root/board/trab
diff options
context:
space:
mode:
authorKevin2014-11-15 11:48:36 +0800
committerKevin2014-11-15 11:48:36 +0800
commitd04075478d378d9e15f3e1abfd14b0bd124077d4 (patch)
tree733dd964582f388b9e3e367c249946cd32a2851f /board/trab
downloadFOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.gz
FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.bz2
FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.zip
init commit via android 4.4 uboot
Diffstat (limited to 'board/trab')
-rwxr-xr-xboard/trab/Makefile65
-rwxr-xr-xboard/trab/Pt1000_temp_data.h71
-rwxr-xr-xboard/trab/README.kbd44
-rwxr-xr-xboard/trab/auto_update.c656
-rwxr-xr-xboard/trab/cmd_trab.c895
-rwxr-xr-xboard/trab/config.mk26
-rwxr-xr-xboard/trab/flash.c568
-rwxr-xr-xboard/trab/lowlevel_init.S182
-rwxr-xr-xboard/trab/memory.c485
-rwxr-xr-xboard/trab/rs485.c203
-rwxr-xr-xboard/trab/rs485.h37
-rwxr-xr-xboard/trab/trab.c412
-rwxr-xr-xboard/trab/trab_fkt.c1411
-rwxr-xr-xboard/trab/tsc2000.c362
-rwxr-xr-xboard/trab/tsc2000.h145
-rwxr-xr-xboard/trab/u-boot.lds65
-rwxr-xr-xboard/trab/vfd.c571
17 files changed, 6198 insertions, 0 deletions
diff --git a/board/trab/Makefile b/board/trab/Makefile
new file mode 100755
index 0000000..ced9bc5
--- /dev/null
+++ b/board/trab/Makefile
@@ -0,0 +1,65 @@
+#
+# (C) Copyright 2000-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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS := trab.o flash.o vfd.o cmd_trab.o memory.o tsc2000.o auto_update.o
+SOBJS := lowlevel_init.o
+
+gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`)
+
+LOAD_ADDR = 0xc100000
+
+#########################################################################
+
+all: $(LIB) trab_fkt.srec trab_fkt.bin
+
+$(LIB): $(OBJS) $(SOBJS)
+ $(AR) crv $@ $(OBJS) $(SOBJS)
+
+trab_fkt.srec: trab_fkt.o rs485.o tsc2000.o $(LIB)
+ $(LD) -g -Ttext $(LOAD_ADDR) -o $(<:.o=) -e $(<:.o=) $^ $(LIB) \
+ -L../../examples -lstubs \
+ -L../../lib_generic -lgeneric \
+ -L$(gcclibdir) -lgcc
+ $(OBJCOPY) -O srec $(<:.o=) $@
+
+trab_fkt.bin: trab_fkt.srec
+ $(OBJCOPY) -O binary $< $@ 2>/dev/null
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+-include .depend
+
+#########################################################################
diff --git a/board/trab/Pt1000_temp_data.h b/board/trab/Pt1000_temp_data.h
new file mode 100755
index 0000000..17e9ed7
--- /dev/null
+++ b/board/trab/Pt1000_temp_data.h
@@ -0,0 +1,71 @@
+/*
+ * Data file for tsc2000 driver.
+ * Copyright (C) 2002, 2003 DENX Software Engineering, Wolfgang Denk, wd@denx.de
+ */
+
+#ifndef _PT1000_TEMP_DATA_H
+#define _PT1000_TEMP_DATA_H
+
+long Pt1000_temp_table[][2] = {
+ /* For quick range checking the largest element
+ * is placed at index 0.
+ * U, nV T, C*100
+ */
+ { 44000000 , 12165 },
+ { -10000000 , -2644 },
+ { -9000000 , -2381 },
+ { -8000000 , -2118 },
+ { -7000000 , -1855 },
+ { -6000000 , -1591 },
+ { -5000000 , -1327 },
+ { -4000000 , -1063 },
+ { -3000000 , -798 },
+ { -2000000 , -532 },
+ { -1000000 , -266 },
+ { 0 , 000 },
+ { 1000000 , 267 },
+ { 2000000 , 534 },
+ { 3000000 , 802 },
+ { 4000000 , 1070 },
+ { 5000000 , 1338 },
+ { 6000000 , 1607 },
+ { 7000000 , 1876 },
+ { 8000000 , 2146 },
+ { 9000000 , 2416 },
+ { 10000000 , 2687 },
+ { 11000000 , 2958 },
+ { 12000000 , 3230 },
+ { 13000000 , 3502 },
+ { 14000000 , 3774 },
+ { 15000000 , 4047 },
+ { 16000000 , 4321 },
+ { 17000000 , 4595 },
+ { 18000000 , 4869 },
+ { 19000000 , 5144 },
+ { 20000000 , 5419 },
+ { 21000000 , 5694 },
+ { 22000000 , 5971 },
+ { 23000000 , 6247 },
+ { 24000000 , 6524 },
+ { 25000000 , 6802 },
+ { 26000000 , 7080 },
+ { 27000000 , 7358 },
+ { 28000000 , 7637 },
+ { 29000000 , 7916 },
+ { 30000000 , 8196 },
+ { 31000000 , 8476 },
+ { 32000000 , 8757 },
+ { 33000000 , 9039 },
+ { 34000000 , 9320 },
+ { 35000000 , 9602 },
+ { 36000000 , 9885 },
+ { 37000000 , 10168 },
+ { 38000000 , 10452 },
+ { 39000000 , 10736 },
+ { 40000000 , 11021 },
+ { 41000000 , 11306 },
+ { 42000000 , 11592 },
+ { 43000000 , 11879 },
+ { 44000000 , 12165 },
+};
+#endif /* _PT1000_TEMP_DATA_H */
diff --git a/board/trab/README.kbd b/board/trab/README.kbd
new file mode 100755
index 0000000..3db00bc
--- /dev/null
+++ b/board/trab/README.kbd
@@ -0,0 +1,44 @@
+
+The TRAB keyboard implementation is similar to that for LWMON and
+R360MPI boards. The only difference concerns key naming. There are 4
+keys on TRAB: 1, 2, 3, 4.
+
+1) The "kbd" command provides information about the current state of
+ the keys. For example,
+
+ TRAB # kbd
+ Keys: 1 0 1 0
+
+ means that keys 1 and 3 are pressed. The keyboard status is also
+ stored in the "keybd" environment variable. In this example we get
+
+ keybd=1010
+
+2) The "preboot" variable is set according to current environment
+ settings and keys pressed. This is an example:
+
+ TRAB # setenv magic_keys XY
+ TRAB # setenv key_magicX 12
+ TRAB # setenv key_cmdX echo ## Keys 1 + 2 pressed ##\;echo
+ TRAB # setenv key_magicY 13
+ TRAB # setenv key_cmdY echo ## Keys 1 + 3 pressed ##\;echo
+
+ Here "magic_keys=XY" means that the "key_magicX" and "key_magicY"
+ variables will be checked for a match. Each variable "key_magic*"
+ defines a set of keys. In the our example, if keys 1 and 3 are
+ pressed during reset, then "key_magicY" matches, so the "preboot"
+ variable will be set to the contents of "key_cmdY":
+
+ preboot=echo ## Keys 1 + 3 pressed ##;echo
+
+3) The TRAB board has optional modem support. When a certain key
+ combination is pressed on the keyboard at power-on, the firmware
+ performs the necessary initialization of the modem and allows for
+ dial-in. The key combination is specified in the
+ "include/configs/trab.h" file. For example:
+
+ #define CONFIG_MODEM_KEY_MAGIC "23"
+
+ means that modem will be initialized if and only if both keys 2, 3
+ are pressed. Note that the format of this string is similar to the
+ format of "key_magic*" environment variables described above.
diff --git a/board/trab/auto_update.c b/board/trab/auto_update.c
new file mode 100755
index 0000000..056e562
--- /dev/null
+++ b/board/trab/auto_update.c
@@ -0,0 +1,656 @@
+/*
+ * (C) Copyright 2003
+ * Gary Jennejohn, DENX Software Engineering, gj@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 <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <image.h>
+#include <asm/byteorder.h>
+#include <usb.h>
+
+#ifdef CFG_HUSH_PARSER
+#include <hush.h>
+#endif
+
+#ifdef CONFIG_AUTO_UPDATE
+
+#ifndef CONFIG_USB_OHCI
+#error "must define CONFIG_USB_OHCI"
+#endif
+
+#ifndef CONFIG_USB_STORAGE
+#error "must define CONFIG_USB_STORAGE"
+#endif
+
+#ifndef CFG_HUSH_PARSER
+#error "must define CFG_HUSH_PARSER"
+#endif
+
+#if !(CONFIG_COMMANDS & CFG_CMD_FAT)
+#error "must define CFG_CMD_FAT"
+#endif
+
+/*
+ * Check whether a USB memory stick is plugged in.
+ * If one is found:
+ * 1) if prepare.img ist found load it into memory. If it is
+ * valid then run it.
+ * 2) if preinst.img is found load it into memory. If it is
+ * valid then run it. Update the EEPROM.
+ * 3) if firmware.img is found load it into memory. If it is valid,
+ * burn it into FLASH and update the EEPROM.
+ * 4) if kernel.img is found load it into memory. If it is valid,
+ * burn it into FLASH and update the EEPROM.
+ * 5) if app.img is found load it into memory. If it is valid,
+ * burn it into FLASH and update the EEPROM.
+ * 6) if disk.img is found load it into memory. If it is valid,
+ * burn it into FLASH and update the EEPROM.
+ * 7) if postinst.img is found load it into memory. If it is
+ * valid then run it. Update the EEPROM.
+ */
+
+#undef AU_DEBUG
+
+#undef debug
+#ifdef AU_DEBUG
+#define debug(fmt,args...) printf (fmt ,##args)
+#else
+#define debug(fmt,args...)
+#endif /* AU_DEBUG */
+
+/* possible names of files on the USB stick. */
+#define AU_PREPARE "prepare.img"
+#define AU_PREINST "preinst.img"
+#define AU_FIRMWARE "firmware.img"
+#define AU_KERNEL "kernel.img"
+#define AU_APP "app.img"
+#define AU_DISK "disk.img"
+#define AU_POSTINST "postinst.img"
+
+struct flash_layout
+{
+ long start;
+ long end;
+};
+
+/* layout of the FLASH. ST = start address, ND = end address. */
+#ifndef CONFIG_FLASH_8MB /* 16 MB Flash, 32 MB RAM */
+#define AU_FL_FIRMWARE_ST 0x00000000
+#define AU_FL_FIRMWARE_ND 0x0009FFFF
+#define AU_FL_VFD_ST 0x000A0000
+#define AU_FL_VFD_ND 0x000BFFFF
+#define AU_FL_KERNEL_ST 0x000C0000
+#define AU_FL_KERNEL_ND 0x001BFFFF
+#define AU_FL_APP_ST 0x001C0000
+#define AU_FL_APP_ND 0x005BFFFF
+#define AU_FL_DISK_ST 0x005C0000
+#define AU_FL_DISK_ND 0x00FFFFFF
+#else /* 8 MB Flash, 32 MB RAM */
+#define AU_FL_FIRMWARE_ST 0x00000000
+#define AU_FL_FIRMWARE_ND 0x0005FFFF
+#define AU_FL_KERNEL_ST 0x00060000
+#define AU_FL_KERNEL_ND 0x0013FFFF
+#define AU_FL_APP_ST 0x00140000
+#define AU_FL_APP_ND 0x0067FFFF
+#define AU_FL_DISK_ST 0x00680000
+#define AU_FL_DISK_ND 0x007DFFFF
+#define AU_FL_VFD_ST 0x007E0000
+#define AU_FL_VFD_ND 0x007FFFFF
+#endif /* CONFIG_FLASH_8MB */
+
+/* a structure with the offsets to values in the EEPROM */
+struct eeprom_layout
+{
+ int time;
+ int size;
+ int dcrc;
+};
+
+/* layout of the EEPROM - offset from the start. All entries are 32 bit. */
+#define AU_EEPROM_TIME_PREINST 64
+#define AU_EEPROM_SIZE_PREINST 68
+#define AU_EEPROM_DCRC_PREINST 72
+#define AU_EEPROM_TIME_FIRMWARE 76
+#define AU_EEPROM_SIZE_FIRMWARE 80
+#define AU_EEPROM_DCRC_FIRMWARE 84
+#define AU_EEPROM_TIME_KERNEL 88
+#define AU_EEPROM_SIZE_KERNEL 92
+#define AU_EEPROM_DCRC_KERNEL 96
+#define AU_EEPROM_TIME_APP 100
+#define AU_EEPROM_SIZE_APP 104
+#define AU_EEPROM_DCRC_APP 108
+#define AU_EEPROM_TIME_DISK 112
+#define AU_EEPROM_SIZE_DISK 116
+#define AU_EEPROM_DCRC_DISK 120
+#define AU_EEPROM_TIME_POSTINST 124
+#define AU_EEPROM_SIZE_POSTINST 128
+#define AU_EEPROM_DCRC_POSTINST 132
+
+static int au_usb_stor_curr_dev; /* current device */
+
+/* index of each file in the following arrays */
+#define IDX_PREPARE 0
+#define IDX_PREINST 1
+#define IDX_FIRMWARE 2
+#define IDX_KERNEL 3
+#define IDX_APP 4
+#define IDX_DISK 5
+#define IDX_POSTINST 6
+/* max. number of files which could interest us */
+#define AU_MAXFILES 7
+/* pointers to file names */
+char *aufile[AU_MAXFILES];
+/* sizes of flash areas for each file */
+long ausize[AU_MAXFILES];
+/* offsets into the EEEPROM */
+struct eeprom_layout auee_off[AU_MAXFILES] = { \
+ {0}, \
+ {AU_EEPROM_TIME_PREINST, AU_EEPROM_SIZE_PREINST, AU_EEPROM_DCRC_PREINST,}, \
+ {AU_EEPROM_TIME_FIRMWARE, AU_EEPROM_SIZE_FIRMWARE, AU_EEPROM_DCRC_FIRMWARE,}, \
+ {AU_EEPROM_TIME_KERNEL, AU_EEPROM_SIZE_KERNEL, AU_EEPROM_DCRC_KERNEL,}, \
+ {AU_EEPROM_TIME_APP, AU_EEPROM_SIZE_APP, AU_EEPROM_DCRC_APP,}, \
+ {AU_EEPROM_TIME_DISK, AU_EEPROM_SIZE_DISK, AU_EEPROM_DCRC_DISK,}, \
+ {AU_EEPROM_TIME_POSTINST, AU_EEPROM_SIZE_POSTINST, AU_EEPROM_DCRC_POSTINST,} \
+ };
+/* array of flash areas start and end addresses */
+struct flash_layout aufl_layout[AU_MAXFILES - 3] = { \
+ {AU_FL_FIRMWARE_ST, AU_FL_FIRMWARE_ND,}, \
+ {AU_FL_KERNEL_ST, AU_FL_KERNEL_ND,}, \
+ {AU_FL_APP_ST, AU_FL_APP_ND,}, \
+ {AU_FL_DISK_ST, AU_FL_DISK_ND,}, \
+};
+/* convert the index into aufile[] to an index into aufl_layout[] */
+#define FIDX_TO_LIDX(idx) ((idx) - 2)
+
+/* where to load files into memory */
+#define LOAD_ADDR ((unsigned char *)0x0C100000)
+/* the app is the largest image */
+#define MAX_LOADSZ ausize[IDX_APP]
+
+/* externals */
+extern int fat_register_device(block_dev_desc_t *, int);
+extern int file_fat_detectfs(void);
+extern long file_fat_read(const char *, void *, unsigned long);
+extern int i2c_read (unsigned char, unsigned int, int , unsigned char* , int);
+extern int i2c_write (uchar, uint, int , uchar* , int);
+#ifdef CONFIG_VFD
+extern int trab_vfd (ulong);
+extern int transfer_pic(unsigned char, unsigned char *, int, int);
+#endif
+extern int flash_sect_erase(ulong, ulong);
+extern int flash_sect_protect (int, ulong, ulong);
+extern int flash_write (char *, ulong, ulong);
+/* change char* to void* to shutup the compiler */
+extern int i2c_write_multiple (uchar, uint, int, void *, int);
+extern int i2c_read_multiple (uchar, uint, int, void *, int);
+extern block_dev_desc_t *get_dev (char*, int);
+extern int u_boot_hush_start(void);
+
+int
+au_check_cksum_valid(int idx, long nbytes)
+{
+ image_header_t *hdr;
+ unsigned long checksum;
+
+ hdr = (image_header_t *)LOAD_ADDR;
+
+ if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size)))
+ {
+ printf ("Image %s bad total SIZE\n", aufile[idx]);
+ return -1;
+ }
+ /* check the data CRC */
+ checksum = ntohl(hdr->ih_dcrc);
+
+ if (crc32 (0, (char *)(LOAD_ADDR + sizeof(*hdr)), ntohl(hdr->ih_size))
+ != checksum)
+ {
+ printf ("Image %s bad data checksum\n", aufile[idx]);
+ return -1;
+ }
+ return 0;
+}
+
+int
+au_check_header_valid(int idx, long nbytes)
+{
+ image_header_t *hdr;
+ unsigned long checksum;
+ unsigned char buf[4];
+
+ hdr = (image_header_t *)LOAD_ADDR;
+ /* check the easy ones first */
+#undef CHECK_VALID_DEBUG
+#ifdef CHECK_VALID_DEBUG
+ printf("magic %#x %#x ", ntohl(hdr->ih_magic), IH_MAGIC);
+ printf("arch %#x %#x ", hdr->ih_arch, IH_CPU_ARM);
+ printf("size %#x %#lx ", ntohl(hdr->ih_size), nbytes);
+ printf("type %#x %#x ", hdr->ih_type, IH_TYPE_KERNEL);
+#endif
+ if (nbytes < sizeof(*hdr))
+ {
+ printf ("Image %s bad header SIZE\n", aufile[idx]);
+ return -1;
+ }
+ if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_CPU_ARM)
+ {
+ printf ("Image %s bad MAGIC or ARCH\n", aufile[idx]);
+ return -1;
+ }
+ /* check the hdr CRC */
+ checksum = ntohl(hdr->ih_hcrc);
+ hdr->ih_hcrc = 0;
+
+ if (crc32 (0, (char *)hdr, sizeof(*hdr)) != checksum) {
+ printf ("Image %s bad header checksum\n", aufile[idx]);
+ return -1;
+ }
+ hdr->ih_hcrc = htonl(checksum);
+ /* check the type - could do this all in one gigantic if() */
+ if ((idx == IDX_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) {
+ printf ("Image %s wrong type\n", aufile[idx]);
+ return -1;
+ }
+ if ((idx == IDX_KERNEL) && (hdr->ih_type != IH_TYPE_KERNEL)) {
+ printf ("Image %s wrong type\n", aufile[idx]);
+ return -1;
+ }
+ if ((idx == IDX_DISK) && (hdr->ih_type != IH_TYPE_FILESYSTEM)) {
+ printf ("Image %s wrong type\n", aufile[idx]);
+ return -1;
+ }
+ if ((idx == IDX_APP) && (hdr->ih_type != IH_TYPE_RAMDISK)
+ && (hdr->ih_type != IH_TYPE_FILESYSTEM)) {
+ printf ("Image %s wrong type\n", aufile[idx]);
+ return -1;
+ }
+ if ((idx == IDX_PREPARE || idx == IDX_PREINST || idx == IDX_POSTINST)
+ && (hdr->ih_type != IH_TYPE_SCRIPT))
+ {
+ printf ("Image %s wrong type\n", aufile[idx]);
+ return -1;
+ }
+ /* special case for prepare.img */
+ if (idx == IDX_PREPARE)
+ return 0;
+ /* recycle checksum */
+ checksum = ntohl(hdr->ih_size);
+ /* for kernel and app the image header must also fit into flash */
+ if ((idx != IDX_DISK) && (idx != IDX_FIRMWARE))
+ checksum += sizeof(*hdr);
+ /* check the size does not exceed space in flash. HUSH scripts */
+ /* all have ausize[] set to 0 */
+ if ((ausize[idx] != 0) && (ausize[idx] < checksum)) {
+ printf ("Image %s is bigger than FLASH\n", aufile[idx]);
+ return -1;
+ }
+ /* check the time stamp from the EEPROM */
+ /* read it in */
+ i2c_read_multiple(0x54, auee_off[idx].time, 1, buf, sizeof(buf));
+#ifdef CHECK_VALID_DEBUG
+ printf ("buf[0] %#x buf[1] %#x buf[2] %#x buf[3] %#x "
+ "as int %#x time %#x\n",
+ buf[0], buf[1], buf[2], buf[3],
+ *((unsigned int *)buf), ntohl(hdr->ih_time));
+#endif
+ /* check it */
+ if (*((unsigned int *)buf) >= ntohl(hdr->ih_time)) {
+ printf ("Image %s is too old\n", aufile[idx]);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* power control defines */
+#define CPLD_VFD_BK ((volatile char *)0x04038002)
+#define POWER_OFF (1 << 1)
+
+int
+au_do_update(int idx, long sz)
+{
+ image_header_t *hdr;
+ char *addr;
+ long start, end;
+ int off, rc;
+ uint nbytes;
+
+ hdr = (image_header_t *)LOAD_ADDR;
+
+ /* disable the power switch */
+ *CPLD_VFD_BK |= POWER_OFF;
+
+ /* execute a script */
+ if (hdr->ih_type == IH_TYPE_SCRIPT) {
+ addr = (char *)((char *)hdr + sizeof(*hdr));
+ /* stick a NULL at the end of the script, otherwise */
+ /* parse_string_outer() runs off the end. */
+ addr[ntohl(hdr->ih_size)] = 0;
+ addr += 8;
+ parse_string_outer(addr, FLAG_PARSE_SEMICOLON);
+ return 0;
+ }
+
+ start = aufl_layout[FIDX_TO_LIDX(idx)].start;
+ end = aufl_layout[FIDX_TO_LIDX(idx)].end;
+
+ /* unprotect the address range */
+ /* this assumes that ONLY the firmware is protected! */
+ if (idx == IDX_FIRMWARE) {
+#undef AU_UPDATE_TEST
+#ifdef AU_UPDATE_TEST
+ /* erase it where Linux goes */
+ start = aufl_layout[1].start;
+ end = aufl_layout[1].end;
+#endif
+ flash_sect_protect(0, start, end);
+ }
+
+ /*
+ * erase the address range.
+ */
+ debug ("flash_sect_erase(%lx, %lx);\n", start, end);
+ flash_sect_erase(start, end);
+ wait_ms(100);
+ /* strip the header - except for the kernel and ramdisk */
+ if (hdr->ih_type == IH_TYPE_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) {
+ addr = (char *)hdr;
+ off = sizeof(*hdr);
+ nbytes = sizeof(*hdr) + ntohl(hdr->ih_size);
+ } else {
+ addr = (char *)((char *)hdr + sizeof(*hdr));
+#ifdef AU_UPDATE_TEST
+ /* copy it to where Linux goes */
+ if (idx == IDX_FIRMWARE)
+ start = aufl_layout[1].start;
+#endif
+ off = 0;
+ nbytes = ntohl(hdr->ih_size);
+ }
+
+ /* copy the data from RAM to FLASH */
+ debug ("flash_write(%p, %lx %x)\n", addr, start, nbytes);
+ rc = flash_write(addr, start, nbytes);
+ if (rc != 0) {
+ printf("Flashing failed due to error %d\n", rc);
+ return -1;
+ }
+
+ /* check the dcrc of the copy */
+ if (crc32 (0, (char *)(start + off), ntohl(hdr->ih_size)) != ntohl(hdr->ih_dcrc)) {
+ printf ("Image %s Bad Data Checksum After COPY\n", aufile[idx]);
+ return -1;
+ }
+
+ /* protect the address range */
+ /* this assumes that ONLY the firmware is protected! */
+ if (idx == IDX_FIRMWARE)
+ flash_sect_protect(1, start, end);
+ return 0;
+}
+
+int
+au_update_eeprom(int idx)
+{
+ image_header_t *hdr;
+ int off;
+ uint32_t val;
+
+ /* special case for prepare.img */
+ if (idx == IDX_PREPARE) {
+ /* enable the power switch */
+ *CPLD_VFD_BK &= ~POWER_OFF;
+ return 0;
+ }
+
+ hdr = (image_header_t *)LOAD_ADDR;
+ /* write the time field into EEPROM */
+ off = auee_off[idx].time;
+ val = ntohl(hdr->ih_time);
+ i2c_write_multiple(0x54, off, 1, &val, sizeof(val));
+ /* write the size field into EEPROM */
+ off = auee_off[idx].size;
+ val = ntohl(hdr->ih_size);
+ i2c_write_multiple(0x54, off, 1, &val, sizeof(val));
+ /* write the dcrc field into EEPROM */
+ off = auee_off[idx].dcrc;
+ val = ntohl(hdr->ih_dcrc);
+ i2c_write_multiple(0x54, off, 1, &val, sizeof(val));
+ /* enable the power switch */
+ *CPLD_VFD_BK &= ~POWER_OFF;
+ return 0;
+}
+
+/*
+ * this is called from board_init() after the hardware has been set up
+ * and is usable. That seems like a good time to do this.
+ * Right now the return value is ignored.
+ */
+int
+do_auto_update(void)
+{
+ block_dev_desc_t *stor_dev;
+ long sz;
+ int i, res, bitmap_first, cnt, old_ctrlc, got_ctrlc;
+ char *env;
+ long start, end;
+
+#undef ERASE_EEPROM
+#ifdef ERASE_EEPROM
+ int arr[18];
+ memset(arr, 0, sizeof(arr));
+ i2c_write_multiple(0x54, 64, 1, arr, sizeof(arr));
+#endif
+ au_usb_stor_curr_dev = -1;
+ /* start USB */
+ if (usb_stop() < 0) {
+ debug ("usb_stop failed\n");
+ return -1;
+ }
+ if (usb_init() < 0) {
+ debug ("usb_init failed\n");
+ return -1;
+ }
+ /*
+ * check whether a storage device is attached (assume that it's
+ * a USB memory stick, since nothing else should be attached).
+ */
+ au_usb_stor_curr_dev = usb_stor_scan(0);
+ if (au_usb_stor_curr_dev == -1) {
+ debug ("No device found. Not initialized?\n");
+ return -1;
+ }
+ /* check whether it has a partition table */
+ stor_dev = get_dev("usb", 0);
+ if (stor_dev == NULL) {
+ debug ("uknown device type\n");
+ return -1;
+ }
+ if (fat_register_device(stor_dev, 1) != 0) {
+ debug ("Unable to use USB %d:%d for fatls\n",
+ au_usb_stor_curr_dev, 1);
+ return -1;
+ }
+ if (file_fat_detectfs() != 0) {
+ debug ("file_fat_detectfs failed\n");
+ }
+
+ /* initialize the array of file names */
+ memset(aufile, 0, sizeof(aufile));
+ aufile[IDX_PREPARE] = AU_PREPARE;
+ aufile[IDX_PREINST] = AU_PREINST;
+ aufile[IDX_FIRMWARE] = AU_FIRMWARE;
+ aufile[IDX_KERNEL] = AU_KERNEL;
+ aufile[IDX_APP] = AU_APP;
+ aufile[IDX_DISK] = AU_DISK;
+ aufile[IDX_POSTINST] = AU_POSTINST;
+ /* initialize the array of flash sizes */
+ memset(ausize, 0, sizeof(ausize));
+ ausize[IDX_FIRMWARE] = (AU_FL_FIRMWARE_ND + 1) - AU_FL_FIRMWARE_ST;
+ ausize[IDX_KERNEL] = (AU_FL_KERNEL_ND + 1) - AU_FL_KERNEL_ST;
+ ausize[IDX_APP] = (AU_FL_APP_ND + 1) - AU_FL_APP_ST;
+ ausize[IDX_DISK] = (AU_FL_DISK_ND + 1) - AU_FL_DISK_ST;
+ /*
+ * now check whether start and end are defined using environment
+ * variables.
+ */
+ start = -1;
+ end = 0;
+ env = getenv("firmware_st");
+ if (env != NULL)
+ start = simple_strtoul(env, NULL, 16);
+ env = getenv("firmware_nd");
+ if (env != NULL)
+ end = simple_strtoul(env, NULL, 16);
+ if (start >= 0 && end && end > start) {
+ ausize[IDX_FIRMWARE] = (end + 1) - start;
+ aufl_layout[0].start = start;
+ aufl_layout[0].end = end;
+ }
+ start = -1;
+ end = 0;
+ env = getenv("kernel_st");
+ if (env != NULL)
+ start = simple_strtoul(env, NULL, 16);
+ env = getenv("kernel_nd");
+ if (env != NULL)
+ end = simple_strtoul(env, NULL, 16);
+ if (start >= 0 && end && end > start) {
+ ausize[IDX_KERNEL] = (end + 1) - start;
+ aufl_layout[1].start = start;
+ aufl_layout[1].end = end;
+ }
+ start = -1;
+ end = 0;
+ env = getenv("app_st");
+ if (env != NULL)
+ start = simple_strtoul(env, NULL, 16);
+ env = getenv("app_nd");
+ if (env != NULL)
+ end = simple_strtoul(env, NULL, 16);
+ if (start >= 0 && end && end > start) {
+ ausize[IDX_APP] = (end + 1) - start;
+ aufl_layout[2].start = start;
+ aufl_layout[2].end = end;
+ }
+ start = -1;
+ end = 0;
+ env = getenv("disk_st");
+ if (env != NULL)
+ start = simple_strtoul(env, NULL, 16);
+ env = getenv("disk_nd");
+ if (env != NULL)
+ end = simple_strtoul(env, NULL, 16);
+ if (start >= 0 && end && end > start) {
+ ausize[IDX_DISK] = (end + 1) - start;
+ aufl_layout[3].start = start;
+ aufl_layout[3].end = end;
+ }
+ /* make certain that HUSH is runnable */
+ u_boot_hush_start();
+ /* make sure that we see CTRL-C and save the old state */
+ old_ctrlc = disable_ctrlc(0);
+
+ bitmap_first = 0;
+ /* just loop thru all the possible files */
+ for (i = 0; i < AU_MAXFILES; i++) {
+ /* just read the header */
+ sz = file_fat_read(aufile[i], LOAD_ADDR, sizeof(image_header_t));
+ debug ("read %s sz %ld hdr %d\n",
+ aufile[i], sz, sizeof(image_header_t));
+ if (sz <= 0 || sz < sizeof(image_header_t)) {
+ debug ("%s not found\n", aufile[i]);
+ continue;
+ }
+ if (au_check_header_valid(i, sz) < 0) {
+ debug ("%s header not valid\n", aufile[i]);
+ continue;
+ }
+ sz = file_fat_read(aufile[i], LOAD_ADDR, MAX_LOADSZ);
+ debug ("read %s sz %ld hdr %d\n",
+ aufile[i], sz, sizeof(image_header_t));
+ if (sz <= 0 || sz <= sizeof(image_header_t)) {
+ debug ("%s not found\n", aufile[i]);
+ continue;
+ }
+ if (au_check_cksum_valid(i, sz) < 0) {
+ debug ("%s checksum not valid\n", aufile[i]);
+ continue;
+ }
+#ifdef CONFIG_VFD
+ /* now that we have a valid file we can display the */
+ /* bitmap. */
+ if (bitmap_first == 0) {
+ env = getenv("bitmap2");
+ if (env == NULL) {
+ trab_vfd(0);
+ } else {
+ /* not so simple - bitmap2 is supposed to */
+ /* contain the address of the bitmap */
+ env = (char *)simple_strtoul(env, NULL, 16);
+/* NOTE: these are taken from vfd_logo.h. If that file changes then */
+/* these defines MUST also be updated! These may be wrong for bitmap2. */
+#define VFD_LOGO_WIDTH 112
+#define VFD_LOGO_HEIGHT 72
+ /* must call transfer_pic directly */
+ transfer_pic(3, env, VFD_LOGO_HEIGHT, VFD_LOGO_WIDTH);
+ }
+ bitmap_first = 1;
+ }
+#endif
+ /* this is really not a good idea, but it's what the */
+ /* customer wants. */
+ cnt = 0;
+ got_ctrlc = 0;
+ do {
+ res = au_do_update(i, sz);
+ /* let the user break out of the loop */
+ if (ctrlc() || had_ctrlc()) {
+ clear_ctrlc();
+ if (res < 0)
+ got_ctrlc = 1;
+ break;
+ }
+ cnt++;
+#ifdef AU_TEST_ONLY
+ } while (res < 0 && cnt < 3);
+ if (cnt < 3)
+#else
+ } while (res < 0);
+#endif
+ /*
+ * it doesn't make sense to update the EEPROM if the
+ * update was interrupted by the user due to errors.
+ */
+ if (got_ctrlc == 0)
+ au_update_eeprom(i);
+ else
+ /* enable the power switch */
+ *CPLD_VFD_BK &= ~POWER_OFF;
+ }
+ usb_stop();
+ /* restore the old state */
+ disable_ctrlc(old_ctrlc);
+ return 0;
+}
+#endif /* CONFIG_AUTO_UPDATE */
diff --git a/board/trab/cmd_trab.c b/board/trab/cmd_trab.c
new file mode 100755
index 0000000..00eb385
--- /dev/null
+++ b/board/trab/cmd_trab.c
@@ -0,0 +1,895 @@
+/*
+ * (C) Copyright 2003
+ * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.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
+ */
+
+#undef DEBUG
+
+#include <common.h>
+#include <command.h>
+#include <s3c2400.h>
+#include <rtc.h>
+
+/*
+ * TRAB board specific commands. Especially commands for burn-in and function
+ * test.
+ */
+#if (CONFIG_COMMANDS & CFG_CMD_BSP)
+
+/* limits for valid range of VCC5V in mV */
+#define VCC5V_MIN 4500
+#define VCC5V_MAX 5500
+
+/*
+ * Test strings for EEPROM test. Length of string 2 must not exceed length of
+ * string 1. Otherwise a buffer overrun could occur!
+ */
+#define EEPROM_TEST_STRING_1 "0987654321 :tset a si siht"
+#define EEPROM_TEST_STRING_2 "this is a test: 1234567890"
+
+/*
+ * min/max limits for valid contact temperature during burn in test (in
+ * degree Centigrade * 100)
+ */
+#define MIN_CONTACT_TEMP -1000
+#define MAX_CONTACT_TEMP +9000
+
+/* blinking frequency of status LED */
+#define LED_BLINK_FREQ 5
+
+/* delay time between burn in cycles in seconds */
+#ifndef BURN_IN_CYCLE_DELAY /* if not defined in include/configs/trab.h */
+#define BURN_IN_CYCLE_DELAY 5
+#endif
+
+/* physical SRAM parameters */
+#define SRAM_ADDR 0x02000000 /* GCS1 */
+#define SRAM_SIZE 0x40000 /* 256 kByte */
+
+/* CPLD-Register for controlling TRAB hardware functions */
+#define CPLD_BUTTONS ((volatile unsigned long *)0x04020000)
+#define CPLD_FILL_LEVEL ((volatile unsigned long *)0x04008000)
+#define CPLD_ROTARY_SWITCH ((volatile unsigned long *)0x04018000)
+#define CPLD_RS485_RE ((volatile unsigned long *)0x04028000)
+
+/* I2C EEPROM device address */
+#define I2C_EEPROM_DEV_ADDR 0x54
+
+/* EEPROM address map */
+#define EE_ADDR_TEST 192
+#define EE_ADDR_MAX_CYCLES 256
+#define EE_ADDR_STATUS 258
+#define EE_ADDR_PASS_CYCLES 259
+#define EE_ADDR_FIRST_ERROR_CYCLE 261
+#define EE_ADDR_FIRST_ERROR_NUM 263
+#define EE_ADDR_FIRST_ERROR_NAME 264
+#define EE_ADDR_ACT_CYCLE 280
+
+/* Bit definitions for ADCCON */
+#define ADC_ENABLE_START 0x1
+#define ADC_READ_START 0x2
+#define ADC_STDBM 0x4
+#define ADC_INP_AIN0 (0x0 << 3)
+#define ADC_INP_AIN1 (0x1 << 3)
+#define ADC_INP_AIN2 (0x2 << 3)
+#define ADC_INP_AIN3 (0x3 << 3)
+#define ADC_INP_AIN4 (0x4 << 3)
+#define ADC_INP_AIN5 (0x5 << 3)
+#define ADC_INP_AIN6 (0x6 << 3)
+#define ADC_INP_AIN7 (0x7 << 3)
+#define ADC_PRSCEN 0x4000
+#define ADC_ECFLG 0x800
+
+/* misc */
+
+/* externals */
+extern int memory_post_tests (unsigned long start, unsigned long size);
+extern int i2c_write (uchar, uint, int , uchar* , int);
+extern int i2c_read (uchar, uint, int , uchar* , int);
+extern void tsc2000_reg_init (void);
+extern s32 tsc2000_contact_temp (void);
+extern void spi_init(void);
+
+/* function declarations */
+int do_dip (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_vcc5v (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_burn_in (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_contact_temp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_burn_in_status (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int i2c_write_multiple (uchar chip, uint addr, int alen,
+ uchar *buffer, int len);
+int i2c_read_multiple (uchar chip, uint addr, int alen,
+ uchar *buffer, int len);
+int do_temp_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+/* helper functions */
+static void adc_init (void);
+static int adc_read (unsigned int channel);
+static int read_dip (void);
+static int read_vcc5v (void);
+static int test_dip (void);
+static int test_vcc5v (void);
+static int test_rotary_switch (void);
+static int test_sram (void);
+static int test_eeprom (void);
+static int test_contact_temp (void);
+static void led_set (unsigned int);
+static void led_blink (void);
+static void led_init (void);
+static void sdelay (unsigned long seconds); /* delay in seconds */
+static int dummy (void);
+static int read_max_cycles(void);
+static void test_function_table_init (void);
+static void global_vars_init (void);
+static int global_vars_write_to_eeprom (void);
+
+/* globals */
+u16 max_cycles;
+u8 status;
+u16 pass_cycles;
+u16 first_error_cycle;
+u8 first_error_num;
+unsigned char first_error_name[16];
+u16 act_cycle;
+
+typedef struct test_function_s {
+ unsigned char *name;
+ int (*pf)(void);
+} test_function_t;
+
+/* max number of Burn In Functions */
+#define BIF_MAX 6
+
+/* table with burn in functions */
+test_function_t test_function[BIF_MAX];
+
+
+int do_burn_in (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int i;
+ int cycle_status;
+
+ if (argc > 1) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ led_init ();
+ global_vars_init ();
+ test_function_table_init ();
+ spi_init ();
+
+ if (global_vars_write_to_eeprom () != 0) {
+ printf ("%s: error writing global_vars to eeprom\n",
+ __FUNCTION__);
+ return (1);
+ }
+
+ if (read_max_cycles () != 0) {
+ printf ("%s: error reading max_cycles from eeprom\n",
+ __FUNCTION__);
+ return (1);
+ }
+
+ if (max_cycles == 0) {
+ printf ("%s: error, burn in max_cycles = 0\n", __FUNCTION__);
+ return (1);
+ }
+
+ status = 0;
+ for (act_cycle = 1; act_cycle <= max_cycles; act_cycle++) {
+
+ cycle_status = 0;
+
+ /*
+ * avoid timestamp overflow problem after about 68 minutes of
+ * udelay() time.
+ */
+ reset_timer_masked ();
+ for (i = 0; i < BIF_MAX; i++) {
+
+ /* call test function */
+ if ((*test_function[i].pf)() != 0) {
+ printf ("error in %s test\n",
+ test_function[i].name);
+
+ /* is it the first error? */
+ if (status == 0) {
+ status = 1;
+ first_error_cycle = act_cycle;
+
+ /* do not use error_num 0 */
+ first_error_num = i+1;
+ strncpy (first_error_name,
+ test_function[i].name,
+ sizeof (first_error_name));
+ led_set (0);
+ }
+ cycle_status = 1;
+ }
+ }
+ /* were all tests of actual cycle OK? */
+ if (cycle_status == 0)
+ pass_cycles++;
+
+ /* set status LED if no error is occoured since yet */
+ if (status == 0)
+ led_set (1);
+
+ printf ("%s: cycle %d finished\n", __FUNCTION__, act_cycle);
+
+ /* pause between cycles */
+ sdelay (BURN_IN_CYCLE_DELAY);
+ }
+
+ if (global_vars_write_to_eeprom () != 0) {
+ led_set (0);
+ printf ("%s: error writing global_vars to eeprom\n",
+ __FUNCTION__);
+ status = 1;
+ }
+
+ if (status == 0) {
+ led_blink (); /* endless loop!! */
+ return (0);
+ } else {
+ led_set (0);
+ return (1);
+ }
+}
+
+U_BOOT_CMD(
+ burn_in, 1, 1, do_burn_in,
+ "burn_in - start burn-in test application on TRAB\n",
+ "\n"
+ " - start burn-in test application\n"
+ " The burn-in test could took a while to finish!\n"
+ " The content of the onboard EEPROM is modified!\n"
+);
+
+
+int do_dip (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int i, dip;
+
+ if (argc > 1) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ if ((dip = read_dip ()) == -1) {
+ return 1;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if ((dip & (1 << i)) == 0)
+ printf("0");
+ else
+ printf("1");
+ }
+ printf("\n");
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ dip, 1, 1, do_dip,
+ "dip - read dip switch on TRAB\n",
+ "\n"
+ " - read state of dip switch (S1) on TRAB board\n"
+ " read sequence: 1-2-3-4; ON=1; OFF=0; e.g.: \"0100\"\n"
+);
+
+
+int do_vcc5v (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int vcc5v;
+
+ if (argc > 1) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ if ((vcc5v = read_vcc5v ()) == -1) {
+ return (1);
+ }
+
+ printf ("%d", (vcc5v / 1000));
+ printf (".%d", (vcc5v % 1000) / 100);
+ printf ("%d V\n", (vcc5v % 100) / 10) ;
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ vcc5v, 1, 1, do_vcc5v,
+ "vcc5v - read VCC5V on TRAB\n",
+ "\n"
+ " - read actual value of voltage VCC5V\n"
+);
+
+
+int do_contact_temp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int contact_temp;
+
+ if (argc > 1) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ spi_init ();
+
+ contact_temp = tsc2000_contact_temp();
+ printf ("%d degree C * 100\n", contact_temp) ;
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ c_temp, 1, 1, do_contact_temp,
+ "c_temp - read contact temperature on TRAB\n",
+ "\n"
+ " - reads the onboard temperature (=contact temperature)\n"
+);
+
+
+int do_burn_in_status (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ if (argc > 1) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_STATUS, 1,
+ (unsigned char*) &status, 1)) {
+ return (1);
+ }
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_PASS_CYCLES, 1,
+ (unsigned char*) &pass_cycles, 2)) {
+ return (1);
+ }
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_CYCLE,
+ 1, (unsigned char*) &first_error_cycle, 2)) {
+ return (1);
+ }
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NUM,
+ 1, (unsigned char*) &first_error_num, 1)) {
+ return (1);
+ }
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NAME,
+ 1, first_error_name,
+ sizeof (first_error_name))) {
+ return (1);
+ }
+
+ if (read_max_cycles () != 0) {
+ return (1);
+ }
+
+ printf ("max_cycles = %d\n", max_cycles);
+ printf ("status = %d\n", status);
+ printf ("pass_cycles = %d\n", pass_cycles);
+ printf ("first_error_cycle = %d\n", first_error_cycle);
+ printf ("first_error_num = %d\n", first_error_num);
+ printf ("first_error_name = %.*s\n",(int) sizeof(first_error_name),
+ first_error_name);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ bis, 1, 1, do_burn_in_status,
+ "bis - print burn in status on TRAB\n",
+ "\n"
+ " - prints the status variables of the last burn in test\n"
+ " stored in the onboard EEPROM on TRAB board\n"
+);
+
+static int read_dip (void)
+{
+ unsigned int result = 0;
+ int adc_val;
+ int i;
+
+ /***********************************************************
+ DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
+ SW1 - AIN4
+ SW2 - AIN5
+ SW3 - AIN6
+ SW4 - AIN7
+
+ "On" DIP switch position short-circuits the voltage from
+ the input channel (i.e. '0' conversion result means "on").
+ *************************************************************/
+
+ for (i = 7; i > 3; i--) {
+
+ if ((adc_val = adc_read (i)) == -1) {
+ printf ("%s: Channel %d could not be read\n",
+ __FUNCTION__, i);
+ return (-1);
+ }
+
+ /*
+ * Input voltage (switch open) is 1.8 V.
+ * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
+ * Set trigger at halve that value.
+ */
+ if (adc_val < 368)
+ result |= (1 << (i-4));
+ }
+ return (result);
+}
+
+
+static int read_vcc5v (void)
+{
+ s32 result;
+
+ /* VCC5V is connected to channel 2 */
+
+ if ((result = adc_read (2)) == -1) {
+ printf ("%s: VCC5V could not be read\n", __FUNCTION__);
+ return (-1);
+ }
+ /*
+ * Calculate voltage value. Split in two parts because there is no
+ * floating point support. VCC5V is connected over an resistor divider:
+ * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
+ */
+ result = result * 10 * 1000 / 1023; /* result in mV */
+
+ return (result);
+}
+
+
+static int test_dip (void)
+{
+ static int first_run = 1;
+ static int first_dip;
+
+ if (first_run) {
+ if ((first_dip = read_dip ()) == -1) {
+ return (1);
+ }
+ first_run = 0;
+ debug ("%s: first_dip=%d\n", __FUNCTION__, first_dip);
+ }
+ if (first_dip != read_dip ()) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+
+static int test_vcc5v (void)
+{
+ int vcc5v;
+
+ if ((vcc5v = read_vcc5v ()) == -1) {
+ return (1);
+ }
+
+ if ((vcc5v > VCC5V_MAX) || (vcc5v < VCC5V_MIN)) {
+ printf ("%s: vcc5v[V/100]=%d\n", __FUNCTION__, vcc5v);
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+
+static int test_rotary_switch (void)
+{
+ static int first_run = 1;
+ static int first_rs;
+
+ if (first_run) {
+ /*
+ * clear bits in CPLD, because they have random values after
+ * power-up or reset.
+ */
+ *CPLD_ROTARY_SWITCH |= (1 << 16) | (1 << 17);
+
+ first_rs = ((*CPLD_ROTARY_SWITCH >> 16) & 0x7);
+ first_run = 0;
+ debug ("%s: first_rs=%d\n", __FUNCTION__, first_rs);
+ }
+
+ if (first_rs != ((*CPLD_ROTARY_SWITCH >> 16) & 0x7)) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+
+static int test_sram (void)
+{
+ return (memory_post_tests (SRAM_ADDR, SRAM_SIZE));
+}
+
+
+static int test_eeprom (void)
+{
+ unsigned char temp[sizeof (EEPROM_TEST_STRING_1)];
+ int result = 0;
+
+ /* write test string 1, read back and verify */
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
+ EEPROM_TEST_STRING_1,
+ sizeof (EEPROM_TEST_STRING_1))) {
+ return (1);
+ }
+
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
+ temp, sizeof (EEPROM_TEST_STRING_1))) {
+ return (1);
+ }
+
+ if (strcmp (temp, EEPROM_TEST_STRING_1) != 0) {
+ result = 1;
+ printf ("%s: error; read_str = \"%s\"\n", __FUNCTION__, temp);
+ }
+
+ /* write test string 2, read back and verify */
+ if (result == 0) {
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
+ EEPROM_TEST_STRING_2,
+ sizeof (EEPROM_TEST_STRING_2))) {
+ return (1);
+ }
+
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
+ temp, sizeof (EEPROM_TEST_STRING_2))) {
+ return (1);
+ }
+
+ if (strcmp (temp, EEPROM_TEST_STRING_2) != 0) {
+ result = 1;
+ printf ("%s: error; read str = \"%s\"\n",
+ __FUNCTION__, temp);
+ }
+ }
+ return (result);
+}
+
+
+static int test_contact_temp (void)
+{
+ int contact_temp;
+
+ contact_temp = tsc2000_contact_temp ();
+
+ if ((contact_temp < MIN_CONTACT_TEMP)
+ || (contact_temp > MAX_CONTACT_TEMP))
+ return (1);
+ else
+ return (0);
+}
+
+
+int i2c_write_multiple (uchar chip, uint addr, int alen,
+ uchar *buffer, int len)
+{
+ int i;
+
+ if (alen != 1) {
+ printf ("%s: addr len other than 1 not supported\n",
+ __FUNCTION__);
+ return (1);
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
+ printf ("%s: could not write to i2c device %d"
+ ", addr %d\n", __FUNCTION__, chip, addr);
+ return (1);
+ }
+#if 0
+ printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
+ "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
+ alen, buffer, i, buffer+i, buffer+i);
+#endif
+
+ udelay (30000);
+ }
+ return (0);
+}
+
+
+int i2c_read_multiple ( uchar chip, uint addr, int alen,
+ uchar *buffer, int len)
+{
+ int i;
+
+ if (alen != 1) {
+ printf ("%s: addr len other than 1 not supported\n",
+ __FUNCTION__);
+ return (1);
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
+ printf ("%s: could not read from i2c device %#x"
+ ", addr %d\n", __FUNCTION__, chip, addr);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+
+static int adc_read (unsigned int channel)
+{
+ int j = 1000; /* timeout value for wait loop in us */
+ int result;
+ S3C2400_ADC *padc;
+
+ padc = S3C2400_GetBase_ADC();
+ channel &= 0x7;
+
+ adc_init ();
+
+ padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
+ padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
+ padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
+
+ while (j--) {
+ if ((padc->ADCCON & ADC_ENABLE_START) == 0)
+ break;
+ udelay (1);
+ }
+
+ if (j == 0) {
+ printf("%s: ADC timeout\n", __FUNCTION__);
+ padc->ADCCON |= ADC_STDBM; /* select standby mode */
+ return -1;
+ }
+
+ result = padc->ADCDAT & 0x3FF;
+
+ padc->ADCCON |= ADC_STDBM; /* select standby mode */
+
+ debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
+ (padc->ADCCON >> 3) & 0x7, result);
+
+ /*
+ * Wait for ADC to be ready for next conversion. This delay value was
+ * estimated, because the datasheet does not specify a value.
+ */
+ udelay (1000);
+
+ return (result);
+}
+
+
+static void adc_init (void)
+{
+ S3C2400_ADC *padc;
+
+ padc = S3C2400_GetBase_ADC();
+
+ padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
+ padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
+
+ /*
+ * Wait some time to avoid problem with very first call of
+ * adc_read(). Without this delay, sometimes the first read
+ * adc value is 0. Perhaps because the adjustment of prescaler
+ * takes some clock cycles?
+ */
+ udelay (1000);
+
+ return;
+}
+
+
+static void led_set (unsigned int state)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ led_init ();
+
+ switch (state) {
+ case 0: /* turn LED off */
+ gpio->PADAT |= (1 << 12);
+ break;
+ case 1: /* turn LED on */
+ gpio->PADAT &= ~(1 << 12);
+ break;
+ default:
+ break;
+ }
+}
+
+static void led_blink (void)
+{
+ led_init ();
+
+ /* blink LED. This function does not return! */
+ while (1) {
+ led_set (1);
+ udelay (1000000 / LED_BLINK_FREQ / 2);
+ led_set (0);
+ udelay (1000000 / LED_BLINK_FREQ / 2);
+ }
+}
+
+
+static void led_init (void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* configure GPA12 as output and set to High -> LED off */
+ gpio->PACON &= ~(1 << 12);
+ gpio->PADAT |= (1 << 12);
+}
+
+
+static void sdelay (unsigned long seconds)
+{
+ unsigned long i;
+
+ for (i = 0; i < seconds; i++) {
+ udelay (1000000);
+ }
+}
+
+
+static int global_vars_write_to_eeprom (void)
+{
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_STATUS, 1,
+ (unsigned char*) &status, 1)) {
+ return (1);
+ }
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_PASS_CYCLES, 1,
+ (unsigned char*) &pass_cycles, 2)) {
+ return (1);
+ }
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_CYCLE,
+ 1, (unsigned char*) &first_error_cycle, 2)) {
+ return (1);
+ }
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NUM,
+ 1, (unsigned char*) &first_error_num, 1)) {
+ return (1);
+ }
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NAME,
+ 1, first_error_name,
+ sizeof(first_error_name))) {
+ return (1);
+ }
+ return (0);
+}
+
+static void global_vars_init (void)
+{
+ status = 1; /* error */
+ pass_cycles = 0;
+ first_error_cycle = 0;
+ first_error_num = 0;
+ first_error_name[0] = '\0';
+ act_cycle = 0;
+ max_cycles = 0;
+}
+
+
+static void test_function_table_init (void)
+{
+ int i;
+
+ for (i = 0; i < BIF_MAX; i++)
+ test_function[i].pf = dummy;
+
+ /*
+ * the length of "name" must not exceed 16, including the '\0'
+ * termination. See also the EEPROM address map.
+ */
+ test_function[0].pf = test_dip;
+ test_function[0].name = "dip";
+
+ test_function[1].pf = test_vcc5v;
+ test_function[1].name = "vcc5v";
+
+ test_function[2].pf = test_rotary_switch;
+ test_function[2].name = "rotary_switch";
+
+ test_function[3].pf = test_sram;
+ test_function[3].name = "sram";
+
+ test_function[4].pf = test_eeprom;
+ test_function[4].name = "eeprom";
+
+ test_function[5].pf = test_contact_temp;
+ test_function[5].name = "contact_temp";
+}
+
+
+static int read_max_cycles (void)
+{
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_MAX_CYCLES, 1,
+ (unsigned char *) &max_cycles, 2) != 0) {
+ return (1);
+ }
+
+ return (0);
+}
+
+static int dummy(void)
+{
+ return (0);
+}
+
+int do_temp_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int contact_temp;
+ int delay = 0;
+#if (CONFIG_COMMANDS & CFG_CMD_DATE)
+ struct rtc_time tm;
+#endif
+
+ if (argc > 2) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ if (argc > 1) {
+ delay = simple_strtoul(argv[1], NULL, 10);
+ }
+
+ spi_init ();
+ while (1) {
+
+#if (CONFIG_COMMANDS & CFG_CMD_DATE)
+ rtc_get (&tm);
+ printf ("%4d-%02d-%02d %2d:%02d:%02d - ",
+ tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+#endif
+
+ contact_temp = tsc2000_contact_temp();
+ printf ("%d\n", contact_temp) ;
+
+ if (delay != 0)
+ /*
+ * reset timer to avoid timestamp overflow problem
+ * after about 68 minutes of udelay() time.
+ */
+ reset_timer_masked ();
+ sdelay (delay);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ tlog, 2, 1, do_temp_log,
+ "tlog - log contact temperature [1/100 C] to console (endlessly)\n",
+ "delay\n"
+ " - contact temperature [1/100 C] is printed endlessly to console\n"
+ " <delay> specifies the seconds to wait between two measurements\n"
+ " For each measurment a timestamp is printeted\n"
+);
+
+#endif /* CFG_CMD_BSP */
diff --git a/board/trab/config.mk b/board/trab/config.mk
new file mode 100755
index 0000000..f2411d0
--- /dev/null
+++ b/board/trab/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+#
+# TRAB board with S3C2400X (arm920t) cpu
+#
+# see http://www.samsung.com/ for more information on SAMSUNG
+#
+
+#
+# TRAB has 1 bank of 16 MB or 32 MB DRAM
+#
+# 0c00'0000 to 0e00'0000
+#
+# Linux-Kernel is expected to be at 0c00'8000, entry 0c00'8000
+#
+# we load ourself to 0CF0'0000 / 0DF0'0000
+#
+# download areas is 0C80'0000
+#
+
+sinclude $(TOPDIR)/board/$(BOARDDIR)/config.tmp
+
+ifndef TEXT_BASE
+TEXT_BASE = 0x0DF40000
+endif
diff --git a/board/trab/flash.c b/board/trab/flash.c
new file mode 100755
index 0000000..b4435e3
--- /dev/null
+++ b/board/trab/flash.c
@@ -0,0 +1,568 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+#include <environment.h>
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+#define CMD_READ_ARRAY 0x00F000F0
+#define CMD_UNLOCK1 0x00AA00AA
+#define CMD_UNLOCK2 0x00550055
+#define CMD_ERASE_SETUP 0x00800080
+#define CMD_ERASE_CONFIRM 0x00300030
+#define CMD_PROGRAM 0x00A000A0
+#define CMD_UNLOCK_BYPASS 0x00200020
+#define CMD_READ_MANF_ID 0x00900090
+#define CMD_UNLOCK_BYPASS_RES1 0x00900090
+#define CMD_UNLOCK_BYPASS_RES2 0x00000000
+
+#define MEM_FLASH_ADDR (*(volatile u32 *)CFG_FLASH_BASE)
+#define MEM_FLASH_ADDR1 (*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2)))
+#define MEM_FLASH_ADDR2 (*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2)))
+
+#define BIT_ERASE_DONE 0x00800080
+#define BIT_RDY_MASK 0x00800080
+#define BIT_PROGRAM_ERROR 0x00200020
+#define BIT_TIMEOUT 0x80000000 /* our flag */
+
+#define READY 1
+#define ERR 2
+#define TMO 4
+
+/*-----------------------------------------------------------------------
+ */
+
+ulong flash_init (void)
+{
+ int i, j;
+ ulong size = 0;
+
+ for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+ ulong flashbase = 0;
+ flash_info_t *info = &flash_info[i];
+
+ /* Init: no FLASHes known */
+ info->flash_id = FLASH_UNKNOWN;
+
+ size += flash_get_size (CFG_FLASH_BASE, info);
+
+ if (i == 0)
+ flashbase = CFG_FLASH_BASE;
+ else
+ panic ("configured too many flash banks!\n");
+ for (j = 0; j < info->sector_count; j++) {
+
+ info->protect[j] = 0;
+ info->start[j] = flashbase;
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case (FLASH_AM320B & FLASH_TYPEMASK):
+ case (FLASH_MXLV320B & FLASH_TYPEMASK):
+ /* Boot sector type: 8 x 8 + N x 128 kB */
+ flashbase += (j < 8) ? 0x4000 : 0x20000;
+ break;
+ case (FLASH_AM640U & FLASH_TYPEMASK):
+ /* Uniform sector type: 128 kB */
+ flashbase += 0x20000;
+ break;
+ default:
+ printf ("## Bad flash chip type 0x%04lX\n",
+ info->flash_id & FLASH_TYPEMASK);
+ }
+ }
+ }
+
+ /*
+ * Protect monitor and environment sectors
+ */
+ flash_protect ( FLAG_PROTECT_SET,
+ CFG_FLASH_BASE,
+ CFG_FLASH_BASE + monitor_flash_len - 1,
+ &flash_info[0]);
+
+ flash_protect ( FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
+
+#ifdef CFG_ENV_ADDR_REDUND
+ flash_protect ( FLAG_PROTECT_SET,
+ CFG_ENV_ADDR_REDUND,
+ CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
+ &flash_info[0]);
+#endif
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+ int i;
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case (FLASH_MAN_AMD & FLASH_VENDMASK):
+ printf ("AMD "); break;
+ case (FLASH_MAN_FUJ & FLASH_VENDMASK):
+ printf ("FUJITSU "); break;
+ case (FLASH_MAN_MX & FLASH_VENDMASK):
+ printf ("MACRONIX "); break;
+ default: printf ("Unknown Vendor "); break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case (FLASH_AM320B & FLASH_TYPEMASK):
+ printf ("2x Am29LV320DB (32Mbit)\n");
+ break;
+ case (FLASH_MXLV320B & FLASH_TYPEMASK):
+ printf ("2x MX29LV320DB (32Mbit)\n");
+ break;
+ case (FLASH_AM640U & FLASH_TYPEMASK):
+ printf ("2x Am29LV640D (64Mbit)\n");
+ break;
+ default:
+ printf ("Unknown Chip Type\n");
+ goto Done;
+ break;
+ }
+
+ printf (" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ printf (" Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; i++) {
+ if ((i % 5) == 0) {
+ printf ("\n ");
+ }
+ printf (" %08lX%s",
+ info->start[i],
+ info->protect[i] ? " (RO)" : " ");
+ }
+ printf ("\n");
+
+Done: ;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+ ulong result;
+
+#if 0
+ int cflag;
+#endif
+ int iflag, prot, sect;
+ int rc = ERR_OK;
+ int chip1, chip2;
+
+ debug ("flash_erase: s_first %d s_last %d\n", s_first, s_last);
+
+ /* first look for protection bits */
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ return ERR_UNKNOWN_FLASH_TYPE;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ return ERR_INVAL;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case (FLASH_MAN_AMD & FLASH_VENDMASK): break; /* OK */
+ case (FLASH_MAN_FUJ & FLASH_VENDMASK): break; /* OK */
+ case (FLASH_MAN_MX & FLASH_VENDMASK): break; /* OK */
+ default:
+ debug ("## flash_erase: unknown manufacturer\n");
+ return (ERR_UNKNOWN_FLASH_VENDOR);
+ }
+
+ prot = 0;
+ for (sect = s_first; sect <= s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+
+ if (prot) {
+ printf ("- Warning: %d protected sectors will not be erased!\n",
+ prot);
+ } else {
+ printf ("\n");
+ }
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+#if 0
+ cflag = icache_status ();
+ icache_disable ();
+#endif
+ iflag = disable_interrupts ();
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
+
+ debug ("Erasing sector %2d @ %08lX... ",
+ sect, info->start[sect]);
+
+ /* arm simple, non interrupt dependent timer */
+ reset_timer_masked ();
+
+ if (info->protect[sect] == 0) { /* not protected */
+ vu_long *addr = (vu_long *) (info->start[sect]);
+
+ MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+ MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+ MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
+
+ MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+ MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+ *addr = CMD_ERASE_CONFIRM;
+
+ /* wait until flash is ready */
+ chip1 = chip2 = 0;
+
+ do {
+ result = *addr;
+
+ /* check timeout */
+ if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
+ MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
+ chip1 = TMO;
+ break;
+ }
+
+ if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
+ chip1 = READY;
+
+ if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
+ chip1 = ERR;
+
+ if (!chip2 && (result >> 16) & BIT_ERASE_DONE)
+ chip2 = READY;
+
+ if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR)
+ chip2 = ERR;
+
+ } while (!chip1 || !chip2);
+
+ MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
+
+ if (chip1 == ERR || chip2 == ERR) {
+ rc = ERR_PROG_ERROR;
+ goto outahere;
+ }
+ if (chip1 == TMO) {
+ rc = ERR_TIMOUT;
+ goto outahere;
+ }
+ }
+ }
+
+outahere:
+ /* allow flash to settle - wait 10 ms */
+ udelay_masked (10000);
+
+ if (iflag)
+ enable_interrupts ();
+
+#if 0
+ if (cflag)
+ icache_enable ();
+#endif
+ return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash
+ */
+
+volatile static int write_word (flash_info_t * info, ulong dest,
+ ulong data)
+{
+ vu_long *addr = (vu_long *) dest;
+ ulong result;
+ int rc = ERR_OK;
+
+#if 0
+ int cflag;
+#endif
+ int iflag;
+ int chip1, chip2;
+
+ /*
+ * Check if Flash is (sufficiently) erased
+ */
+ result = *addr;
+ if ((result & data) != data)
+ return ERR_NOT_ERASED;
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+#if 0
+ cflag = icache_status ();
+ icache_disable ();
+#endif
+ iflag = disable_interrupts ();
+
+ *addr = CMD_PROGRAM;
+ *addr = data;
+
+ /* arm simple, non interrupt dependent timer */
+ reset_timer_masked ();
+
+ /* wait until flash is ready */
+ chip1 = chip2 = 0;
+ do {
+ result = *addr;
+
+ /* check timeout */
+ if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
+ chip1 = ERR | TMO;
+ break;
+ }
+ if (!chip1 && ((result & 0x80) == (data & 0x80)))
+ chip1 = READY;
+
+ if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
+ result = *addr;
+
+ if ((result & 0x80) == (data & 0x80))
+ chip1 = READY;
+ else
+ chip1 = ERR;
+ }
+
+ if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16))))
+ chip2 = READY;
+
+ if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR)) {
+ result = *addr;
+
+ if ((result & (0x80 << 16)) == (data & (0x80 << 16)))
+ chip2 = READY;
+ else
+ chip2 = ERR;
+ }
+
+ } while (!chip1 || !chip2);
+
+ *addr = CMD_READ_ARRAY;
+
+ if (chip1 == ERR || chip2 == ERR || *addr != data)
+ rc = ERR_PROG_ERROR;
+
+ if (iflag)
+ enable_interrupts ();
+
+#if 0
+ if (cflag)
+ icache_enable ();
+#endif
+
+ return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ */
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+ ulong cp, wp, data;
+ int l;
+ int i, rc;
+
+ MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+ MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+ MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
+
+ wp = (addr & ~3); /* get lower word aligned address */
+
+ /*
+ * handle unaligned start bytes
+ */
+ if ((l = addr - wp) != 0) {
+ data = 0;
+ for (i = 0, cp = wp; i < l; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *) cp << 24);
+ }
+ for (; i < 4 && cnt > 0; ++i) {
+ data = (data >> 8) | (*src++ << 24);
+ --cnt;
+ ++cp;
+ }
+ for (; cnt == 0 && i < 4; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *) cp << 24);
+ }
+
+ if ((rc = write_word (info, wp, data)) != 0) {
+ goto Done;
+ }
+ wp += 4;
+ }
+
+ /*
+ * handle word aligned part
+ */
+ while (cnt >= 4) {
+ if (((ulong)src) & 0x3) {
+ for (i = 0; i < 4; i++) {
+ ((char *)&data)[i] = ((vu_char *)src)[i];
+ }
+ }
+ else {
+ data = *((vu_long *) src);
+ }
+
+ if ((rc = write_word (info, wp, data)) != 0) {
+ goto Done;
+ }
+ src += 4;
+ wp += 4;
+ cnt -= 4;
+ }
+
+ if (cnt == 0) {
+ rc = ERR_OK;
+ goto Done;
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ data = 0;
+ for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
+ data = (data >> 8) | (*src++ << 24);
+ --cnt;
+ }
+ for (; i < 4; ++i, ++cp) {
+ data = (data >> 8) | (*(uchar *) cp << 24);
+ }
+
+ rc = write_word (info, wp, data);
+
+ Done:
+
+ MEM_FLASH_ADDR = CMD_UNLOCK_BYPASS_RES1;
+ MEM_FLASH_ADDR = CMD_UNLOCK_BYPASS_RES2;
+
+ return (rc);
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+ ulong value;
+
+ /* Write auto select command sequence and read Manufacturer ID */
+ addr[0x0555] = CMD_UNLOCK1;
+ addr[0x02AA] = CMD_UNLOCK2;
+ addr[0x0555] = CMD_READ_MANF_ID;
+
+ value = addr[0];
+
+ debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value);
+
+ switch (value) {
+ case AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+ case FUJ_MANUFACT:
+ info->flash_id = FLASH_MAN_FUJ;
+ break;
+ case MX_MANUFACT:
+ info->flash_id = FLASH_MAN_MX;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ addr[0] = 0x00FF00FF; /* restore read mode */
+ debug ("## flash_init: unknown manufacturer\n");
+ return (0); /* no or unknown flash */
+ }
+
+ value = addr[1]; /* device ID */
+
+ debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value);
+
+ switch (value) {
+ case AMD_ID_LV320B:
+ info->flash_id += FLASH_AM320B;
+ info->sector_count = 71;
+ info->size = 0x00800000;
+
+ addr[0] = 0x00FF00FF; /* restore read mode */
+ break; /* => 8 MB */
+
+ case AMD_ID_LV640U:
+ info->flash_id += FLASH_AM640U;
+ info->sector_count = 128;
+ info->size = 0x01000000;
+
+ addr[0] = 0x00F000F0; /* restore read mode */
+ break; /* => 16 MB */
+
+ case MX_ID_LV320B:
+ info->flash_id += FLASH_MXLV320B;
+ info->sector_count = 71;
+ info->size = 0x00800000;
+
+ addr[0] = 0x00FF00FF; /* restore read mode */
+ break; /* => 8 MB */
+
+ default:
+ debug ("## flash_init: unknown flash chip\n");
+ info->flash_id = FLASH_UNKNOWN;
+ addr[0] = 0x00FF00FF; /* restore read mode */
+ return (0); /* => no or unknown flash */
+
+ }
+
+ if (info->sector_count > CFG_MAX_FLASH_SECT) {
+ printf ("** ERROR: sector count %d > max (%d) **\n",
+ info->sector_count, CFG_MAX_FLASH_SECT);
+ info->sector_count = CFG_MAX_FLASH_SECT;
+ }
+
+ return (info->size);
+}
diff --git a/board/trab/lowlevel_init.S b/board/trab/lowlevel_init.S
new file mode 100755
index 0000000..128ae7e
--- /dev/null
+++ b/board/trab/lowlevel_init.S
@@ -0,0 +1,182 @@
+/*
+ * Memory Setup stuff - taken from blob memsetup.S
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
+ * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+ *
+ * Modified for the TRAB board by
+ * (C) Copyright 2002-2003
+ * Gary Jennejohn, DENX Software Engineering, <gj@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 <config.h>
+#include <version.h>
+
+
+/* some parameters for the board */
+
+/*
+ *
+ * Copied from linux/arch/arm/boot/compressed/head-s3c2400.S
+ *
+ * Copyright (C) 2001 Samsung Electronics by chc, 010406
+ *
+ * TRAB specific tweaks.
+ *
+ */
+
+/* memory controller */
+#define BWSCON 0x14000000
+
+/* Bank0 */
+#define B0_Tacs 0x1 /* 1 clk */
+#define B0_Tcos 0x1 /* 1 clk */
+#define B0_Tacc 0x5 /* 8 clk */
+#define B0_Tcoh 0x1 /* 1 clk */
+#define B0_Tah 0x1 /* 1 clk */
+#define B0_Tacp 0x0
+#define B0_PMC 0x0 /* normal */
+
+/* Bank1 - SRAM */
+#define B1_Tacs 0x1 /* 1 clk */
+#define B1_Tcos 0x1 /* 1 clk */
+#define B1_Tacc 0x5 /* 8 clk */
+#define B1_Tcoh 0x1 /* 1 clk */
+#define B1_Tah 0x1 /* 1 clk */
+#define B1_Tacp 0x0
+#define B1_PMC 0x0 /* normal */
+
+/* Bank2 - CPLD */
+#define B2_Tacs 0x1 /* 1 clk */
+#define B2_Tcos 0x1 /* 1 clk */
+#define B2_Tacc 0x5 /* 8 clk */
+#define B2_Tcoh 0x1 /* 1 clk */
+#define B2_Tah 0x1 /* 1 clk */
+#define B2_Tacp 0x0
+#define B2_PMC 0x0 /* normal */
+
+/* Bank3 - setup for the cs8900 */
+#define B3_Tacs 0x3 /* 4 clk */
+#define B3_Tcos 0x3 /* 4 clk */
+#define B3_Tacc 0x7 /* 14 clk */
+#define B3_Tcoh 0x1 /* 1 clk */
+#define B3_Tah 0x0 /* 0 clk */
+#define B3_Tacp 0x3 /* 6 clk */
+#define B3_PMC 0x0 /* normal */
+
+/* Bank4 */
+#define B4_Tacs 0x0 /* 0 clk */
+#define B4_Tcos 0x0 /* 0 clk */
+#define B4_Tacc 0x7 /* 14 clk */
+#define B4_Tcoh 0x0 /* 0 clk */
+#define B4_Tah 0x0 /* 0 clk */
+#define B4_Tacp 0x0
+#define B4_PMC 0x0 /* normal */
+
+/* Bank5 */
+#define B5_Tacs 0x0 /* 0 clk */
+#define B5_Tcos 0x0 /* 0 clk */
+#define B5_Tacc 0x7 /* 14 clk */
+#define B5_Tcoh 0x0 /* 0 clk */
+#define B5_Tah 0x0 /* 0 clk */
+#define B5_Tacp 0x0
+#define B5_PMC 0x0 /* normal */
+
+#ifndef CONFIG_RAM_16MB /* 32 MB RAM */
+/* Bank6 */
+#define B6_MT 0x3 /* SDRAM */
+#define B6_Trcd 0x0 /* 2clk */
+#define B6_SCAN 0x1 /* 9 bit */
+
+/* Bank7 */
+#define B7_MT 0x3 /* SDRAM */
+#define B7_Trcd 0x0 /* 2clk */
+#define B7_SCAN 0x1 /* 9 bit */
+#else /* CONFIG_RAM_16MB = 16 MB RAM */
+/* Bank6 */
+#define B6_MT 0x3 /* SDRAM */
+#define B6_Trcd 0x1 /* 2clk */
+#define B6_SCAN 0x0 /* 8 bit */
+
+/* Bank7 */
+#define B7_MT 0x3 /* SDRAM */
+#define B7_Trcd 0x1 /* 2clk */
+#define B7_SCAN 0x0 /* 8 bit */
+#endif /* CONFIG_RAM_16MB */
+
+/* refresh parameter */
+#define REFEN 0x1 /* enable refresh */
+#define TREFMD 0x0 /* CBR(CAS before RAS)/auto refresh */
+#define Trp 0x0 /* 2 clk */
+#define Trc 0x3 /* 7 clk */
+#define Tchr 0x2 /* 3 clk */
+
+#ifdef CONFIG_TRAB_50MHZ
+#define REFCNT 1269 /* period=15.6 us, HCLK=50Mhz, (2048+1-15.6*50) */
+#else
+#define REFCNT 1011 /* period=15.6 us, HCLK=66.5Mhz, (2048+1-15.6*66.5) */
+#endif
+
+
+_TEXT_BASE:
+ .word TEXT_BASE
+
+.globl lowlevel_init
+lowlevel_init:
+ /* memory control configuration */
+ /* make r0 relative the current location so that it */
+ /* reads SMRDATA out of FLASH rather than memory ! */
+ ldr r0, =SMRDATA
+ ldr r1, _TEXT_BASE
+ sub r0, r0, r1
+ ldr r1, =BWSCON /* Bus Width Status Controller */
+ add r2, r0, #52
+0:
+ ldr r3, [r0], #4
+ str r3, [r1], #4
+ cmp r2, r0
+ bne 0b
+
+ /* everything is fine now */
+ mov pc, lr
+
+ .ltorg
+/* the literal pools origin */
+
+SMRDATA:
+ .word 0x2211d644 /* d->Ethernet, 6->CPLD, 4->SRAM, 4->FLASH */
+ .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) /* GCS0 */
+ .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) /* GCS1 */
+ .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) /* GCS2 */
+ .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) /* GCS3 */
+ .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) /* GCS4 */
+ .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) /* GCS5 */
+ .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) /* GCS6 */
+ .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) /* GCS7 */
+ .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+#ifndef CONFIG_RAM_16MB /* 32 MB RAM */
+ .word 0x10 /* BUSWIDTH=32, SCLK power saving mode, BANKSIZE 32M/32M */
+#else /* CONFIG_RAM_16MB = 16 MB RAM */
+ .word 0x17 /* BUSWIDTH=32, SCLK power saving mode, BANKSIZE 16M/16M */
+#endif /* CONFIG_RAM_16MB */
+ .word 0x20 /* MRSR6, CL=2clk */
+ .word 0x20 /* MRSR7 */
diff --git a/board/trab/memory.c b/board/trab/memory.c
new file mode 100755
index 0000000..9104413
--- /dev/null
+++ b/board/trab/memory.c
@@ -0,0 +1,485 @@
+/*
+ * (C) Copyright 2002-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
+ */
+
+#include <common.h>
+
+/* Memory test
+ *
+ * General observations:
+ * o The recommended test sequence is to test the data lines: if they are
+ * broken, nothing else will work properly. Then test the address
+ * lines. Finally, test the cells in the memory now that the test
+ * program knows that the address and data lines work properly.
+ * This sequence also helps isolate and identify what is faulty.
+ *
+ * o For the address line test, it is a good idea to use the base
+ * address of the lowest memory location, which causes a '1' bit to
+ * walk through a field of zeros on the address lines and the highest
+ * memory location, which causes a '0' bit to walk through a field of
+ * '1's on the address line.
+ *
+ * o Floating buses can fool memory tests if the test routine writes
+ * a value and then reads it back immediately. The problem is, the
+ * write will charge the residual capacitance on the data bus so the
+ * bus retains its state briefely. When the test program reads the
+ * value back immediately, the capacitance of the bus can allow it
+ * to read back what was written, even though the memory circuitry
+ * is broken. To avoid this, the test program should write a test
+ * pattern to the target location, write a different pattern elsewhere
+ * to charge the residual capacitance in a differnt manner, then read
+ * the target location back.
+ *
+ * o Always read the target location EXACTLY ONCE and save it in a local
+ * variable. The problem with reading the target location more than
+ * once is that the second and subsequent reads may work properly,
+ * resulting in a failed test that tells the poor technician that
+ * "Memory error at 00000000, wrote aaaaaaaa, read aaaaaaaa" which
+ * doesn't help him one bit and causes puzzled phone calls. Been there,
+ * done that.
+ *
+ * Data line test:
+ * ---------------
+ * This tests data lines for shorts and opens by forcing adjacent data
+ * to opposite states. Because the data lines could be routed in an
+ * arbitrary manner the must ensure test patterns ensure that every case
+ * is tested. By using the following series of binary patterns every
+ * combination of adjacent bits is test regardless of routing.
+ *
+ * ...101010101010101010101010
+ * ...110011001100110011001100
+ * ...111100001111000011110000
+ * ...111111110000000011111111
+ *
+ * Carrying this out, gives us six hex patterns as follows:
+ *
+ * 0xaaaaaaaaaaaaaaaa
+ * 0xcccccccccccccccc
+ * 0xf0f0f0f0f0f0f0f0
+ * 0xff00ff00ff00ff00
+ * 0xffff0000ffff0000
+ * 0xffffffff00000000
+ *
+ * To test for short and opens to other signals on our boards, we
+ * simply test with the 1's complemnt of the paterns as well, resulting
+ * in twelve patterns total.
+ *
+ * After writing a test pattern. a special pattern 0x0123456789ABCDEF is
+ * written to a different address in case the data lines are floating.
+ * Thus, if a byte lane fails, you will see part of the special
+ * pattern in that byte lane when the test runs. For example, if the
+ * xx__xxxxxxxxxxxx byte line fails, you will see aa23aaaaaaaaaaaa
+ * (for the 'a' test pattern).
+ *
+ * Address line test:
+ * ------------------
+ * This function performs a test to verify that all the address lines
+ * hooked up to the RAM work properly. If there is an address line
+ * fault, it usually shows up as two different locations in the address
+ * map (related by the faulty address line) mapping to one physical
+ * memory storage location. The artifact that shows up is writing to
+ * the first location "changes" the second location.
+ *
+ * To test all address lines, we start with the given base address and
+ * xor the address with a '1' bit to flip one address line. For each
+ * test, we shift the '1' bit left to test the next address line.
+ *
+ * In the actual code, we start with address sizeof(ulong) since our
+ * test pattern we use is a ulong and thus, if we tried to test lower
+ * order address bits, it wouldn't work because our pattern would
+ * overwrite itself.
+ *
+ * Example for a 4 bit address space with the base at 0000:
+ * 0000 <- base
+ * 0001 <- test 1
+ * 0010 <- test 2
+ * 0100 <- test 3
+ * 1000 <- test 4
+ * Example for a 4 bit address space with the base at 0010:
+ * 0010 <- base
+ * 0011 <- test 1
+ * 0000 <- (below the base address, skipped)
+ * 0110 <- test 2
+ * 1010 <- test 3
+ *
+ * The test locations are successively tested to make sure that they are
+ * not "mirrored" onto the base address due to a faulty address line.
+ * Note that the base and each test location are related by one address
+ * line flipped. Note that the base address need not be all zeros.
+ *
+ * Memory tests 1-4:
+ * -----------------
+ * These tests verify RAM using sequential writes and reads
+ * to/from RAM. There are several test cases that use different patterns to
+ * verify RAM. Each test case fills a region of RAM with one pattern and
+ * then reads the region back and compares its contents with the pattern.
+ * The following patterns are used:
+ *
+ * 1a) zero pattern (0x00000000)
+ * 1b) negative pattern (0xffffffff)
+ * 1c) checkerboard pattern (0x55555555)
+ * 1d) checkerboard pattern (0xaaaaaaaa)
+ * 2) bit-flip pattern ((1 << (offset % 32))
+ * 3) address pattern (offset)
+ * 4) address pattern (~offset)
+ *
+ * Being run in normal mode, the test verifies only small 4Kb
+ * regions of RAM around each 1Mb boundary. For example, for 64Mb
+ * RAM the following areas are verified: 0x00000000-0x00000800,
+ * 0x000ff800-0x00100800, 0x001ff800-0x00200800, ..., 0x03fff800-
+ * 0x04000000. If the test is run in slow-test mode, it verifies
+ * the whole RAM.
+ */
+
+/* #ifdef CONFIG_POST */
+
+#include <post.h>
+#include <watchdog.h>
+
+/* #if CONFIG_POST & CFG_POST_MEMORY */
+
+/*
+ * Define INJECT_*_ERRORS for testing error detection in the presence of
+ * _good_ hardware.
+ */
+#undef INJECT_DATA_ERRORS
+#undef INJECT_ADDRESS_ERRORS
+
+#ifdef INJECT_DATA_ERRORS
+#warning "Injecting data line errors for testing purposes"
+#endif
+
+#ifdef INJECT_ADDRESS_ERRORS
+#warning "Injecting address line errors for testing purposes"
+#endif
+
+
+/*
+ * This function performs a double word move from the data at
+ * the source pointer to the location at the destination pointer.
+ * This is helpful for testing memory on processors which have a 64 bit
+ * wide data bus.
+ *
+ * On those PowerPC with FPU, use assembly and a floating point move:
+ * this does a 64 bit move.
+ *
+ * For other processors, let the compiler generate the best code it can.
+ */
+static void move64(unsigned long long *src, unsigned long long *dest)
+{
+#if defined(CONFIG_MPC8260) || defined(CONFIG_MPC824X)
+ asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */
+ "stfd 0, 0(4)" /* *dest = fpr0 */
+ : : : "fr0" ); /* Clobbers fr0 */
+ return;
+#else
+ *dest = *src;
+#endif
+}
+
+/*
+ * This is 64 bit wide test patterns. Note that they reside in ROM
+ * (which presumably works) and the tests write them to RAM which may
+ * not work.
+ *
+ * The "otherpattern" is written to drive the data bus to values other
+ * than the test pattern. This is for detecting floating bus lines.
+ *
+ */
+const static unsigned long long pattern[] = {
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0xccccccccccccccccULL,
+ 0xf0f0f0f0f0f0f0f0ULL,
+ 0xff00ff00ff00ff00ULL,
+ 0xffff0000ffff0000ULL,
+ 0xffffffff00000000ULL,
+ 0x00000000ffffffffULL,
+ 0x0000ffff0000ffffULL,
+ 0x00ff00ff00ff00ffULL,
+ 0x0f0f0f0f0f0f0f0fULL,
+ 0x3333333333333333ULL,
+ 0x5555555555555555ULL,
+};
+const unsigned long long otherpattern = 0x0123456789abcdefULL;
+
+
+static int memory_post_dataline(unsigned long long * pmem)
+{
+ unsigned long long temp64;
+ int num_patterns = sizeof(pattern)/ sizeof(pattern[0]);
+ int i;
+ unsigned int hi, lo, pathi, patlo;
+ int ret = 0;
+
+ for ( i = 0; i < num_patterns; i++) {
+ move64((unsigned long long *)&(pattern[i]), pmem++);
+ /*
+ * Put a different pattern on the data lines: otherwise they
+ * may float long enough to read back what we wrote.
+ */
+ move64((unsigned long long *)&otherpattern, pmem--);
+ move64(pmem, &temp64);
+
+#ifdef INJECT_DATA_ERRORS
+ temp64 ^= 0x00008000;
+#endif
+
+ if (temp64 != pattern[i]){
+ pathi = (pattern[i]>>32) & 0xffffffff;
+ patlo = pattern[i] & 0xffffffff;
+
+ hi = (temp64>>32) & 0xffffffff;
+ lo = temp64 & 0xffffffff;
+
+ printf ("Memory (date line) error at %08lx, "
+ "wrote %08x%08x, read %08x%08x !\n",
+ (ulong)pmem, pathi, patlo, hi, lo);
+ ret = -1;
+ }
+ }
+ return ret;
+}
+
+static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size)
+{
+ ulong *target;
+ ulong *end;
+ ulong readback;
+ ulong xor;
+ int ret = 0;
+
+ end = (ulong *)((ulong)base + size); /* pointer arith! */
+ xor = 0;
+ for(xor = sizeof(ulong); xor > 0; xor <<= 1) {
+ target = (ulong *)((ulong)testaddr ^ xor);
+ if((target >= base) && (target < end)) {
+ *testaddr = ~*target;
+ readback = *target;
+
+#ifdef INJECT_ADDRESS_ERRORS
+ if(xor == 0x00008000) {
+ readback = *testaddr;
+ }
+#endif
+ if(readback == *testaddr) {
+ printf ("Memory (address line) error at %08lx<->%08lx, "
+ "XOR value %08lx !\n",
+ (ulong)testaddr, (ulong)target,
+ xor);
+ ret = -1;
+ }
+ }
+ }
+ return ret;
+}
+
+static int memory_post_test1 (unsigned long start,
+ unsigned long size,
+ unsigned long val)
+{
+ unsigned long i;
+ ulong *mem = (ulong *) start;
+ ulong readback;
+ int ret = 0;
+
+ for (i = 0; i < size / sizeof (ulong); i++) {
+ mem[i] = val;
+ if (i % 1024 == 0)
+ WATCHDOG_RESET ();
+ }
+
+ for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+ readback = mem[i];
+ if (readback != val) {
+ printf ("Memory error at %08lx, "
+ "wrote %08lx, read %08lx !\n",
+ (ulong)(mem + i), val, readback);
+
+ ret = -1;
+ break;
+ }
+ if (i % 1024 == 0)
+ WATCHDOG_RESET ();
+ }
+
+ return ret;
+}
+
+static int memory_post_test2 (unsigned long start, unsigned long size)
+{
+ unsigned long i;
+ ulong *mem = (ulong *) start;
+ ulong readback;
+ int ret = 0;
+
+ for (i = 0; i < size / sizeof (ulong); i++) {
+ mem[i] = 1 << (i % 32);
+ if (i % 1024 == 0)
+ WATCHDOG_RESET ();
+ }
+
+ for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+ readback = mem[i];
+ if (readback != (1 << (i % 32))) {
+ printf ("Memory error at %08lx, "
+ "wrote %08x, read %08lx !\n",
+ (ulong)(mem + i), 1 << (i % 32), readback);
+
+ ret = -1;
+ break;
+ }
+ if (i % 1024 == 0)
+ WATCHDOG_RESET ();
+ }
+
+ return ret;
+}
+
+static int memory_post_test3 (unsigned long start, unsigned long size)
+{
+ unsigned long i;
+ ulong *mem = (ulong *) start;
+ ulong readback;
+ int ret = 0;
+
+ for (i = 0; i < size / sizeof (ulong); i++) {
+ mem[i] = i;
+ if (i % 1024 == 0)
+ WATCHDOG_RESET ();
+ }
+
+ for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+ readback = mem[i];
+ if (readback != i) {
+ printf ("Memory error at %08lx, "
+ "wrote %08lx, read %08lx !\n",
+ (ulong)(mem + i), i, readback);
+
+ ret = -1;
+ break;
+ }
+ if (i % 1024 == 0)
+ WATCHDOG_RESET ();
+ }
+
+ return ret;
+}
+
+static int memory_post_test4 (unsigned long start, unsigned long size)
+{
+ unsigned long i;
+ ulong *mem = (ulong *) start;
+ ulong readback;
+ int ret = 0;
+
+ for (i = 0; i < size / sizeof (ulong); i++) {
+ mem[i] = ~i;
+ if (i % 1024 == 0)
+ WATCHDOG_RESET ();
+ }
+
+ for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+ readback = mem[i];
+ if (readback != ~i) {
+ printf ("Memory error at %08lx, "
+ "wrote %08lx, read %08lx !\n",
+ (ulong)(mem + i), ~i, readback);
+
+ ret = -1;
+ break;
+ }
+ if (i % 1024 == 0)
+ WATCHDOG_RESET ();
+ }
+
+ return ret;
+}
+
+int memory_post_tests (unsigned long start, unsigned long size)
+{
+ int ret = 0;
+
+ if (ret == 0)
+ ret = memory_post_dataline ((long long *)start);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_addrline ((long *)start, (long *)start, size);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_addrline ((long *)(start + size - 8),
+ (long *)start, size);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_test1 (start, size, 0x00000000);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_test1 (start, size, 0xffffffff);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_test1 (start, size, 0x55555555);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_test1 (start, size, 0xaaaaaaaa);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_test2 (start, size);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_test3 (start, size);
+ WATCHDOG_RESET ();
+ if (ret == 0)
+ ret = memory_post_test4 (start, size);
+ WATCHDOG_RESET ();
+
+ return ret;
+}
+
+#if 0
+int memory_post_test (int flags)
+{
+ int ret = 0;
+ DECLARE_GLOBAL_DATA_PTR;
+ bd_t *bd = gd->bd;
+ unsigned long memsize = (bd->bi_memsize >= 256 << 20 ?
+ 256 << 20 : bd->bi_memsize) - (1 << 20);
+
+
+ if (flags & POST_SLOWTEST) {
+ ret = memory_post_tests (CFG_SDRAM_BASE, memsize);
+ } else { /* POST_NORMAL */
+
+ unsigned long i;
+
+ for (i = 0; i < (memsize >> 20) && ret == 0; i++) {
+ if (ret == 0)
+ ret = memory_post_tests (i << 20, 0x800);
+ if (ret == 0)
+ ret = memory_post_tests ((i << 20) + 0xff800, 0x800);
+ }
+ }
+
+ return ret;
+}
+#endif /* 0 */
+
+/* #endif */ /* CONFIG_POST & CFG_POST_MEMORY */
+/* #endif */ /* CONFIG_POST */
diff --git a/board/trab/rs485.c b/board/trab/rs485.c
new file mode 100755
index 0000000..2aedd2d
--- /dev/null
+++ b/board/trab/rs485.c
@@ -0,0 +1,203 @@
+/*
+ * (C) Copyright 2003
+ * Martin Krause, TQ-Systems GmbH, <martin.krause@tqs.de>
+ *
+ * Based on cpu/arm920t/serial.c, by Gary Jennejohn
+ * (C) Copyright 2002 Gary Jennejohn, DENX Software Engineering, <gj@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
+ *
+ */
+
+#include <common.h>
+#include <s3c2400.h>
+#include "rs485.h"
+
+static void rs485_setbrg (void);
+static void rs485_cfgio (void);
+static void set_rs485re(unsigned char rs485re_state);
+static void set_rs485de(unsigned char rs485de_state);
+static void rs485_setbrg (void);
+#ifdef NOT_USED
+static void trab_rs485_disable_tx(void);
+static void trab_rs485_disable_rx(void);
+#endif
+
+#define UART_NR S3C24X0_UART1
+
+/* CPLD-Register for controlling TRAB hardware functions */
+#define CPLD_RS485_RE ((volatile unsigned long *)0x04028000)
+
+static void rs485_setbrg (void)
+{
+ S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+ int i;
+ unsigned int reg = 0;
+
+ /* value is calculated so : (int)(PCLK/16./baudrate) -1 */
+ /* reg = (33000000 / (16 * gd->baudrate)) - 1; */
+ reg = (33000000 / (16 * 38400)) - 1;
+
+ /* FIFO enable, Tx/Rx FIFO clear */
+ uart->UFCON = 0x07;
+ uart->UMCON = 0x0;
+ /* Normal,No parity,1 stop,8 bit */
+ uart->ULCON = 0x3;
+ /*
+ * tx=level,rx=edge,disable timeout int.,enable rx error int.,
+ * normal,interrupt or polling
+ */
+ uart->UCON = 0x245;
+ uart->UBRDIV = reg;
+
+ for (i = 0; i < 100; i++);
+}
+
+static void rs485_cfgio (void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ gpio->PFCON &= ~(0x3 << 2);
+ gpio->PFCON |= (0x2 << 2); /* configure GPF1 as RXD1 */
+
+ gpio->PFCON &= ~(0x3 << 6);
+ gpio->PFCON |= (0x2 << 6); /* configure GPF3 as TXD1 */
+
+ gpio->PFUP |= (1 << 1); /* disable pullup on GPF1 */
+ gpio->PFUP |= (1 << 3); /* disable pullup on GPF3 */
+
+ gpio->PACON &= ~(1 << 11); /* set GPA11 (RS485_DE) to output */
+}
+
+/*
+ * Initialise the rs485 port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int rs485_init (void)
+{
+ rs485_cfgio ();
+ rs485_setbrg ();
+
+ return (0);
+}
+
+/*
+ * Read a single byte from the rs485 port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int rs485_getc (void)
+{
+ S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+
+ /* wait for character to arrive */
+ while (!(uart->UTRSTAT & 0x1));
+
+ return uart->URXH & 0xff;
+}
+
+/*
+ * Output a single byte to the rs485 port.
+ */
+void rs485_putc (const char c)
+{
+ S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+
+ /* wait for room in the tx FIFO */
+ while (!(uart->UTRSTAT & 0x2));
+
+ uart->UTXH = c;
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ rs485_putc ('\r');
+}
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+int rs485_tstc (void)
+{
+ S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+
+ return uart->UTRSTAT & 0x1;
+}
+
+void rs485_puts (const char *s)
+{
+ while (*s) {
+ rs485_putc (*s++);
+ }
+}
+
+
+/*
+ * State table:
+ * RE DE Result
+ * 1 1 XMIT
+ * 0 0 RCV
+ * 1 0 Shutdown
+ */
+
+/* function that controls the receiver enable for the rs485 */
+/* rs485re_state reflects the level (0/1) of the RE pin */
+
+static void set_rs485re(unsigned char rs485re_state)
+{
+ if(rs485re_state)
+ *CPLD_RS485_RE = 0x010000;
+ else
+ *CPLD_RS485_RE = 0x0;
+}
+
+/* function that controls the sender enable for the rs485 */
+/* rs485de_state reflects the level (0/1) of the DE pin */
+
+static void set_rs485de(unsigned char rs485de_state)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* This is on PORT A bit 11 */
+ if(rs485de_state)
+ gpio->PADAT |= (1 << 11);
+ else
+ gpio->PADAT &= ~(1 << 11);
+}
+
+
+void trab_rs485_enable_tx(void)
+{
+ set_rs485de(1);
+ set_rs485re(1);
+}
+
+void trab_rs485_enable_rx(void)
+{
+ set_rs485re(0);
+ set_rs485de(0);
+}
+
+#ifdef NOT_USED
+static void trab_rs485_disable_tx(void)
+{
+ set_rs485de(0);
+}
+
+static void trab_rs485_disable_rx(void)
+{
+ set_rs485re(1);
+}
+#endif
diff --git a/board/trab/rs485.h b/board/trab/rs485.h
new file mode 100755
index 0000000..d4a008a
--- /dev/null
+++ b/board/trab/rs485.h
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2003
+ * Martin Krause, TQ-Systems GmbH, <martin.krause@tqs.de>
+ *
+ * Based on cpu/arm920t/serial.c, by Gary Jennejohn
+ * (C) Copyright 2002 Gary Jennejohn, DENX Software Engineering, <gj@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 _RS485_H_
+#define _RS485_H_
+
+#include <s3c2400.h>
+
+int rs485_init (void);
+int rs485_getc (void);
+void rs485_putc (const char c);
+int rs485_tstc (void);
+void rs485_puts (const char *s);
+void trab_rs485_enable_tx(void);
+void trab_rs485_enable_rx(void);
+
+#endif /* _RS485_H_ */
diff --git a/board/trab/trab.c b/board/trab/trab.c
new file mode 100755
index 0000000..e8dfd2c
--- /dev/null
+++ b/board/trab/trab.c
@@ -0,0 +1,412 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+#include <malloc.h>
+#include <s3c2400.h>
+#include <command.h>
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CFG_BRIGHTNESS
+static void spi_init(void);
+static void wait_transmit_done(void);
+static void tsc2000_write(unsigned int page, unsigned int reg,
+ unsigned int data);
+static void tsc2000_set_brightness(void);
+#endif
+#ifdef CONFIG_MODEM_SUPPORT
+static int key_pressed(void);
+extern void disable_putc(void);
+extern int do_mdm_init; /* defined in common/main.c */
+
+/*
+ * We need a delay of at least 500 us after turning on the VFD clock
+ * before we can read any useful information for the CPLD controlling
+ * the keyboard switches. Let's play safe and wait 5 ms. The problem
+ * is that timers are not available yet, so we use a manually timed
+ * loop.
+ */
+#define KBD_MDELAY 5000
+static void udelay_no_timer (int usec)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int i;
+ int delay = usec * 3;
+
+ for (i = 0; i < delay; i ++) gd->bd->bi_arch_number = MACH_TYPE_TRAB;
+}
+#endif /* CONFIG_MODEM_SUPPORT */
+
+/*
+ * Miscellaneous platform dependent initialisations
+ */
+
+int board_init ()
+{
+#if defined(CONFIG_VFD)
+ extern int vfd_init_clocks(void);
+#endif
+ DECLARE_GLOBAL_DATA_PTR;
+ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* memory and cpu-speed are setup before relocation */
+#ifdef CONFIG_TRAB_50MHZ
+ /* change the clock to be 50 MHz 1:1:1 */
+ /* MDIV:0x5c PDIV:4 SDIV:2 */
+ clk_power->MPLLCON = 0x5c042;
+ clk_power->CLKDIVN = 0;
+#else
+ /* change the clock to be 133 MHz 1:2:4 */
+ /* MDIV:0x7d PDIV:4 SDIV:1 */
+ clk_power->MPLLCON = 0x7d041;
+ clk_power->CLKDIVN = 3;
+#endif
+
+ /* set up the I/O ports */
+ gpio->PACON = 0x3ffff;
+ gpio->PBCON = 0xaaaaaaaa;
+ gpio->PBUP = 0xffff;
+ /* INPUT nCTS0 nRTS0 TXD[1] TXD[0] RXD[1] RXD[0] */
+ /* 00, 10, 10, 10, 10, 10, 10 */
+ gpio->PFCON = (2<<0) | (2<<2) | (2<<4) | (2<<6) | (2<<8) | (2<<10);
+#ifdef CONFIG_HWFLOW
+ /* do not pull up RXD0, RXD1, TXD0, TXD1, CTS0, RTS0 */
+ gpio->PFUP = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5);
+#else
+ /* do not pull up RXD0, RXD1, TXD0, TXD1 */
+ gpio->PFUP = (1<<0) | (1<<1) | (1<<2) | (1<<3);
+#endif
+ gpio->PGCON = 0x0;
+ gpio->PGUP = 0x0;
+ gpio->OPENCR= 0x0;
+
+ /* suppress flicker of the VFDs */
+ gpio->MISCCR = 0x40;
+ gpio->PFCON |= (2<<12);
+
+ gd->bd->bi_arch_number = MACH_TYPE_TRAB;
+
+ /* adress of boot parameters */
+ gd->bd->bi_boot_params = 0x0c000100;
+
+ /* Make sure both buzzers are turned off */
+ gpio->PDCON |= 0x5400;
+ gpio->PDDAT &= ~0xE0;
+
+#ifdef CONFIG_VFD
+ vfd_init_clocks();
+#endif /* CONFIG_VFD */
+
+#ifdef CONFIG_MODEM_SUPPORT
+ udelay_no_timer (KBD_MDELAY);
+
+ if (key_pressed()) {
+ disable_putc(); /* modem doesn't understand banner etc */
+ do_mdm_init = 1;
+ }
+#endif /* CONFIG_MODEM_SUPPORT */
+
+#ifdef CONFIG_DRIVER_S3C24X0_I2C
+ /* Configure I/O ports PG5 und PG6 for I2C */
+ gpio->PGCON = (gpio->PGCON & 0x003c00) | 0x003c00;
+#endif /* CONFIG_DRIVER_S3C24X0_I2C */
+
+ return 0;
+}
+
+int dram_init (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Keyboard Controller
+ */
+
+/* Maximum key number */
+#define KEYBD_KEY_NUM 4
+
+#define KBD_DATA (((*(volatile ulong *)0x04020000) >> 16) & 0xF)
+
+static uchar *key_match (ulong);
+
+int misc_init_r (void)
+{
+ ulong kbd_data = KBD_DATA;
+ uchar keybd_env[KEYBD_KEY_NUM + 1];
+ uchar *str;
+ int i;
+
+#ifdef CONFIG_AUTO_UPDATE
+ extern int do_auto_update(void);
+ /* this has priority over all else */
+ do_auto_update();
+#endif
+
+ for (i = 0; i < KEYBD_KEY_NUM; ++i) {
+ keybd_env[i] = '0' + ((kbd_data >> i) & 1);
+ }
+ keybd_env[i] = '\0';
+ debug ("** Setting keybd=\"%s\"\n", keybd_env);
+ setenv ("keybd", keybd_env);
+
+ str = strdup (key_match (kbd_data)); /* decode keys */
+
+#ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */
+ debug ("** Setting preboot=\"%s\"\n", str);
+ setenv ("preboot", str); /* set or delete definition */
+#endif /* CONFIG_PREBOOT */
+ if (str != NULL) {
+ free (str);
+ }
+
+#ifdef CFG_BRIGHTNESS
+ tsc2000_set_brightness();
+#endif
+ return (0);
+}
+
+#ifdef CONFIG_PREBOOT
+
+static uchar kbd_magic_prefix[] = "key_magic";
+static uchar kbd_command_prefix[] = "key_cmd";
+
+static int compare_magic (ulong kbd_data, uchar *str)
+{
+ uchar key_mask;
+
+ debug ("compare_magic: kbd: %04lx str: \"%s\"\n",kbd_data,str);
+ for (; *str; str++)
+ {
+ uchar c = *str - '1';
+
+ if (c >= KEYBD_KEY_NUM) /* bad key number */
+ return -1;
+
+ key_mask = 1 << c;
+
+ if (!(kbd_data & key_mask)) { /* key not pressed */
+ debug ( "compare_magic: "
+ "kbd: %04lx mask: %04lx - key not pressed\n",
+ kbd_data, key_mask );
+ return -1;
+ }
+
+ kbd_data &= ~key_mask;
+ }
+
+ if (kbd_data) { /* key(s) not released */
+ debug ( "compare_magic: "
+ "kbd: %04lx - key(s) not released\n", kbd_data);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Check if pressed key(s) match magic sequence,
+ * and return the command string associated with that key(s).
+ *
+ * If no key press was decoded, NULL is returned.
+ *
+ * Note: the first character of the argument will be overwritten with
+ * the "magic charcter code" of the decoded key(s), or '\0'.
+ *
+ *
+ * Note: the string points to static environment data and must be
+ * saved before you call any function that modifies the environment.
+ */
+static uchar *key_match (ulong kbd_data)
+{
+ uchar magic[sizeof (kbd_magic_prefix) + 1];
+ uchar cmd_name[sizeof (kbd_command_prefix) + 1];
+ uchar *suffix;
+ uchar *kbd_magic_keys;
+
+ /*
+ * The following string defines the characters that can pe appended
+ * to "key_magic" to form the names of environment variables that
+ * hold "magic" key codes, i. e. such key codes that can cause
+ * pre-boot actions. If the string is empty (""), then only
+ * "key_magic" is checked (old behaviour); the string "125" causes
+ * checks for "key_magic1", "key_magic2" and "key_magic5", etc.
+ */
+ if ((kbd_magic_keys = getenv ("magic_keys")) == NULL)
+ kbd_magic_keys = "";
+
+ debug ("key_match: magic_keys=\"%s\"\n", kbd_magic_keys);
+
+ /* loop over all magic keys;
+ * use '\0' suffix in case of empty string
+ */
+ for (suffix=kbd_magic_keys; *suffix || suffix==kbd_magic_keys; ++suffix)
+ {
+ sprintf (magic, "%s%c", kbd_magic_prefix, *suffix);
+
+ debug ("key_match: magic=\"%s\"\n",
+ getenv(magic) ? getenv(magic) : "<UNDEFINED>");
+
+ if (compare_magic(kbd_data, getenv(magic)) == 0)
+ {
+ sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix);
+ debug ("key_match: cmdname %s=\"%s\"\n",
+ cmd_name,
+ getenv (cmd_name) ?
+ getenv (cmd_name) :
+ "<UNDEFINED>");
+ return (getenv (cmd_name));
+ }
+ }
+ debug ("key_match: no match\n");
+ return (NULL);
+}
+#endif /* CONFIG_PREBOOT */
+
+/* Read Keyboard status */
+int do_kbd (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ ulong kbd_data = KBD_DATA;
+ uchar keybd_env[KEYBD_KEY_NUM + 1];
+ int i;
+
+ puts ("Keys:");
+ for (i = 0; i < KEYBD_KEY_NUM; ++i) {
+ keybd_env[i] = '0' + ((kbd_data >> i) & 1);
+ printf (" %c", keybd_env[i]);
+ }
+ keybd_env[i] = '\0';
+ putc ('\n');
+ setenv ("keybd", keybd_env);
+ return 0;
+}
+
+U_BOOT_CMD(
+ kbd, 1, 1, do_kbd,
+ "kbd - read keyboard status\n",
+ NULL
+);
+
+#ifdef CONFIG_MODEM_SUPPORT
+static int key_pressed(void)
+{
+ return (compare_magic(KBD_DATA, CONFIG_MODEM_KEY_MAGIC) == 0);
+}
+#endif /* CONFIG_MODEM_SUPPORT */
+
+#ifdef CFG_BRIGHTNESS
+
+static inline void SET_CS_TOUCH(void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ gpio->PDDAT &= 0x5FF;
+}
+
+static inline void CLR_CS_TOUCH(void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ gpio->PDDAT |= 0x200;
+}
+
+static void spi_init(void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+ S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
+ int i;
+
+ /* Configure I/O ports. */
+ gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;
+ gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;
+ gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;
+ gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;
+
+ CLR_CS_TOUCH();
+
+ spi->ch[0].SPPRE = 0x1F; /* Baudrate ca. 514kHz */
+ spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */
+ spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0, CPHA=1 */
+
+ /* Dummy byte ensures clock to be low. */
+ for (i = 0; i < 10; i++) {
+ spi->ch[0].SPTDAT = 0xFF;
+ }
+ wait_transmit_done();
+}
+
+static void wait_transmit_done(void)
+{
+ S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
+
+ while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
+}
+
+static void tsc2000_write(unsigned int page, unsigned int reg,
+ unsigned int data)
+{
+ S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
+ unsigned int command;
+
+ SET_CS_TOUCH();
+ command = 0x0000;
+ command |= (page << 11);
+ command |= (reg << 5);
+
+ spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
+ wait_transmit_done();
+ spi->ch[0].SPTDAT = (command & 0x00FF);
+ wait_transmit_done();
+ spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;
+ wait_transmit_done();
+ spi->ch[0].SPTDAT = (data & 0x00FF);
+ wait_transmit_done();
+
+ CLR_CS_TOUCH();
+}
+
+static void tsc2000_set_brightness(void)
+{
+ uchar tmp[10];
+ int i, br;
+
+ spi_init();
+ tsc2000_write(1, 2, 0x0); /* Power up DAC */
+
+ i = getenv_r("brightness", tmp, sizeof(tmp));
+ br = (i > 0)
+ ? (int) simple_strtoul (tmp, NULL, 10)
+ : CFG_BRIGHTNESS;
+
+ tsc2000_write(0, 0xb, br & 0xff);
+}
+#endif
diff --git a/board/trab/trab_fkt.c b/board/trab/trab_fkt.c
new file mode 100755
index 0000000..abb3b29
--- /dev/null
+++ b/board/trab/trab_fkt.c
@@ -0,0 +1,1411 @@
+/*
+ * (C) Copyright 2003
+ * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.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
+ */
+
+#define DEBUG
+
+#include <common.h>
+#include <exports.h>
+#include <s3c2400.h>
+#include "tsc2000.h"
+#include "rs485.h"
+
+/*
+ * define, to wait for the touch to be pressed, before reading coordinates in
+ * command do_touch. If not defined, an error message is printed, when the
+ * command do_touch is invoked and the touch is not pressed within an specific
+ * interval.
+ */
+#undef CONFIG_TOUCH_WAIT_PRESSED
+
+/* max time to wait for touch is pressed */
+#ifndef CONFIG_TOUCH_WAIT_PRESSED
+#define TOUCH_TIMEOUT 5
+#endif /* !CONFIG_TOUCH_WAIT_PRESSED */
+
+/* assignment of CPU internal ADC channels with TRAB hardware */
+#define VCC5V 2
+#define VCC12V 3
+
+/* CPLD-Register for controlling TRAB hardware functions */
+#define CPLD_BUTTONS ((volatile unsigned long *)0x04020000)
+#define CPLD_FILL_LEVEL ((volatile unsigned long *)0x04008000)
+#define CPLD_ROTARY_SWITCH ((volatile unsigned long *)0x04018000)
+#define CPLD_RS485_RE ((volatile unsigned long *)0x04028000)
+
+/* timer configuration bits for buzzer and PWM */
+#define START2 (1 << 12)
+#define UPDATE2 (1 << 13)
+#define INVERT2 (1 << 14)
+#define RELOAD2 (1 << 15)
+#define START3 (1 << 16)
+#define UPDATE3 (1 << 17)
+#define INVERT3 (1 << 18)
+#define RELOAD3 (1 << 19)
+
+#define PCLK 66000000
+#define BUZZER_FREQ 1000 /* frequency in Hz */
+#define PWM_FREQ 500
+
+
+/* definitions of I2C EEPROM device address */
+#define I2C_EEPROM_DEV_ADDR 0x54
+
+/* definition for touch panel calibration points */
+#define CALIB_TL 0 /* calibration point in (T)op (L)eft corner */
+#define CALIB_DR 1 /* calibration point in (D)own (R)ight corner */
+
+/* EEPROM address map */
+#define SERIAL_NUMBER 8
+#define TOUCH_X0 52
+#define TOUCH_Y0 54
+#define TOUCH_X1 56
+#define TOUCH_Y1 58
+#define CRC16 60
+
+/* EEPROM stuff */
+#define EEPROM_MAX_CRC_BUF 64
+
+/* RS485 stuff */
+#define RS485_MAX_RECEIVE_BUF_LEN 100
+
+/* Bit definitions for ADCCON */
+#define ADC_ENABLE_START 0x1
+#define ADC_READ_START 0x2
+#define ADC_STDBM 0x4
+#define ADC_INP_AIN0 (0x0 << 3)
+#define ADC_INP_AIN1 (0x1 << 3)
+#define ADC_INP_AIN2 (0x2 << 3)
+#define ADC_INP_AIN3 (0x3 << 3)
+#define ADC_INP_AIN4 (0x4 << 3)
+#define ADC_INP_AIN5 (0x5 << 3)
+#define ADC_INP_AIN6 (0x6 << 3)
+#define ADC_INP_AIN7 (0x7 << 3)
+#define ADC_PRSCEN 0x4000
+#define ADC_ECFLG 0x8000
+
+/* function test functions */
+int do_dip (void);
+int do_info (void);
+int do_vcc5v (void);
+int do_vcc12v (void);
+int do_buttons (void);
+int do_fill_level (void);
+int do_rotary_switch (void);
+int do_pressure (void);
+int do_v_bat (void);
+int do_vfd_id (void);
+int do_buzzer (char **);
+int do_led (char **);
+int do_full_bridge (char **);
+int do_dac (char **);
+int do_motor_contact (void);
+int do_motor (char **);
+int do_pwm (char **);
+int do_thermo (char **);
+int do_touch (char **);
+int do_rs485 (char **);
+int do_serial_number (char **);
+int do_crc16 (void);
+int do_power_switch (void);
+int do_gain (char **);
+int do_eeprom (char **);
+
+/* helper functions */
+static void adc_init (void);
+static int adc_read (unsigned int channel);
+static void print_identifier (void);
+
+#ifdef CONFIG_TOUCH_WAIT_PRESSED
+static void touch_wait_pressed (void);
+#else
+static int touch_check_pressed (void);
+#endif /* CONFIG_TOUCH_WAIT_PRESSED */
+
+static void touch_read_x_y (int *x, int *y);
+static int touch_write_clibration_values (int calib_point, int x, int y);
+static int rs485_send_line (const char *data);
+static int rs485_receive_chars (char *data, int timeout);
+static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
+ unsigned int icnt);
+
+#if (CONFIG_COMMANDS & CFG_CMD_I2C)
+static int trab_eeprom_read (char **argv);
+static int trab_eeprom_write (char **argv);
+int i2c_write_multiple (uchar chip, uint addr, int alen, uchar *buffer,
+ int len);
+int i2c_read_multiple ( uchar chip, uint addr, int alen, uchar *buffer,
+ int len);
+#endif /* CFG_CMD_I2C */
+
+/*
+ * TRAB board specific commands. Especially commands for burn-in and function
+ * test.
+ */
+
+int trab_fkt (int argc, char *argv[])
+{
+ int i;
+
+ app_startup(argv);
+ if (get_version () != XF_VERSION) {
+ printf ("Wrong XF_VERSION. Please re-compile with actual "
+ "u-boot sources\n");
+ printf ("Example expects ABI version %d\n", XF_VERSION);
+ printf ("Actual U-Boot ABI version %d\n", (int)get_version());
+ return 1;
+ }
+
+ debug ("argc = %d\n", argc);
+
+ for (i=0; i<=argc; ++i) {
+ debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
+ }
+
+ adc_init ();
+
+ switch (argc) {
+
+ case 0:
+ case 1:
+ break;
+
+ case 2:
+ if (strcmp (argv[1], "info") == 0) {
+ return (do_info ());
+ }
+ if (strcmp (argv[1], "dip") == 0) {
+ return (do_dip ());
+ }
+ if (strcmp (argv[1], "vcc5v") == 0) {
+ return (do_vcc5v ());
+ }
+ if (strcmp (argv[1], "vcc12v") == 0) {
+ return (do_vcc12v ());
+ }
+ if (strcmp (argv[1], "buttons") == 0) {
+ return (do_buttons ());
+ }
+ if (strcmp (argv[1], "fill_level") == 0) {
+ return (do_fill_level ());
+ }
+ if (strcmp (argv[1], "rotary_switch") == 0) {
+ return (do_rotary_switch ());
+ }
+ if (strcmp (argv[1], "pressure") == 0) {
+ return (do_pressure ());
+ }
+ if (strcmp (argv[1], "v_bat") == 0) {
+ return (do_v_bat ());
+ }
+ if (strcmp (argv[1], "vfd_id") == 0) {
+ return (do_vfd_id ());
+ }
+ if (strcmp (argv[1], "motor_contact") == 0) {
+ return (do_motor_contact ());
+ }
+ if (strcmp (argv[1], "crc16") == 0) {
+ return (do_crc16 ());
+ }
+ if (strcmp (argv[1], "power_switch") == 0) {
+ return (do_power_switch ());
+ }
+ break;
+
+ case 3:
+ if (strcmp (argv[1], "full_bridge") == 0) {
+ return (do_full_bridge (argv));
+ }
+ if (strcmp (argv[1], "dac") == 0) {
+ return (do_dac (argv));
+ }
+ if (strcmp (argv[1], "motor") == 0) {
+ return (do_motor (argv));
+ }
+ if (strcmp (argv[1], "pwm") == 0) {
+ return (do_pwm (argv));
+ }
+ if (strcmp (argv[1], "thermo") == 0) {
+ return (do_thermo (argv));
+ }
+ if (strcmp (argv[1], "touch") == 0) {
+ return (do_touch (argv));
+ }
+ if (strcmp (argv[1], "serial_number") == 0) {
+ return (do_serial_number (argv));
+ }
+ if (strcmp (argv[1], "buzzer") == 0) {
+ return (do_buzzer (argv));
+ }
+ if (strcmp (argv[1], "gain") == 0) {
+ return (do_gain (argv));
+ }
+ break;
+
+ case 4:
+ if (strcmp (argv[1], "led") == 0) {
+ return (do_led (argv));
+ }
+ if (strcmp (argv[1], "rs485") == 0) {
+ return (do_rs485 (argv));
+ }
+ if (strcmp (argv[1], "serial_number") == 0) {
+ return (do_serial_number (argv));
+ }
+ break;
+
+ case 5:
+ if (strcmp (argv[1], "eeprom") == 0) {
+ return (do_eeprom (argv));
+ }
+ break;
+
+ case 6:
+ if (strcmp (argv[1], "eeprom") == 0) {
+ return (do_eeprom (argv));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
+ return 1;
+}
+
+int do_info (void)
+{
+ printf ("Stand-alone application for TRAB board function test\n");
+ printf ("Built: %s at %s\n", __DATE__ , __TIME__ );
+
+ return 0;
+}
+
+int do_dip (void)
+{
+ unsigned int result = 0;
+ int adc_val;
+ int i;
+
+ /***********************************************************
+ DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
+ SW1 - AIN4
+ SW2 - AIN5
+ SW3 - AIN6
+ SW4 - AIN7
+
+ "On" DIP switch position short-circuits the voltage from
+ the input channel (i.e. '0' conversion result means "on").
+ *************************************************************/
+
+ for (i = 7; i > 3; i--) {
+
+ if ((adc_val = adc_read (i)) == -1) {
+ printf ("Channel %d could not be read\n", i);
+ return 1;
+ }
+
+ /*
+ * Input voltage (switch open) is 1.8 V.
+ * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
+ * Set trigger at halve that value.
+ */
+ if (adc_val < 368)
+ result |= (1 << (i-4));
+ }
+
+ /* print result to console */
+ print_identifier ();
+ for (i = 0; i < 4; i++) {
+ if ((result & (1 << i)) == 0)
+ printf("0");
+ else
+ printf("1");
+ }
+ printf("\n");
+
+ return 0;
+}
+
+
+int do_vcc5v (void)
+{
+ int result;
+
+ /* VCC5V is connected to channel 2 */
+
+ if ((result = adc_read (VCC5V)) == -1) {
+ printf ("VCC5V could not be read\n");
+ return 1;
+ }
+
+ /*
+ * Calculate voltage value. Split in two parts because there is no
+ * floating point support. VCC5V is connected over an resistor divider:
+ * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
+ */
+ print_identifier ();
+ printf ("%d", (result & 0x3FF)* 10 / 1023);
+ printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
+ printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
+ * 10 / 1024);
+
+ return 0;
+}
+
+
+int do_vcc12v (void)
+{
+ int result;
+
+ if ((result = adc_read (VCC12V)) == -1) {
+ printf ("VCC12V could not be read\n");
+ return 1;
+ }
+
+ /*
+ * Calculate voltage value. Split in two parts because there is no
+ * floating point support. VCC5V is connected over an resistor divider:
+ * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
+ */
+ print_identifier ();
+ printf ("%d", (result & 0x3FF)* 25 / 1023);
+ printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
+
+ return 0;
+}
+
+static int adc_read (unsigned int channel)
+{
+ int j = 1000; /* timeout value for wait loop in us */
+ int result;
+ S3C2400_ADC *padc;
+
+ padc = S3C2400_GetBase_ADC();
+ channel &= 0x7;
+
+ padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
+ padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
+ padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
+
+ while (j--) {
+ if ((padc->ADCCON & ADC_ENABLE_START) == 0)
+ break;
+ udelay (1);
+ }
+
+ if (j == 0) {
+ printf("%s: ADC timeout\n", __FUNCTION__);
+ padc->ADCCON |= ADC_STDBM; /* select standby mode */
+ return -1;
+ }
+
+ result = padc->ADCDAT & 0x3FF;
+
+ padc->ADCCON |= ADC_STDBM; /* select standby mode */
+
+ debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
+ (padc->ADCCON >> 3) & 0x7, result);
+
+ /*
+ * Wait for ADC to be ready for next conversion. This delay value was
+ * estimated, because the datasheet does not specify a value.
+ */
+ udelay (1000);
+
+ return (result);
+}
+
+
+static void adc_init (void)
+{
+ S3C2400_ADC *padc;
+
+ padc = S3C2400_GetBase_ADC();
+
+ padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
+ padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
+
+ /*
+ * Wait some time to avoid problem with very first call of
+ * adc_read(). Without * this delay, sometimes the first read adc
+ * value is 0. Perhaps because the * adjustment of prescaler takes
+ * some clock cycles?
+ */
+ udelay (1000);
+
+ return;
+}
+
+
+int do_buttons (void)
+{
+ int result;
+ int i;
+
+ result = *CPLD_BUTTONS; /* read CPLD */
+ debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
+
+ /* print result to console */
+ print_identifier ();
+ for (i = 16; i <= 19; i++) {
+ if ((result & (1 << i)) == 0)
+ printf("0");
+ else
+ printf("1");
+ }
+ printf("\n");
+ return 0;
+}
+
+
+int do_power_switch (void)
+{
+ int result;
+
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* configure GPE7 as input */
+ gpio->PECON &= ~(0x3 << (2 * 7));
+
+ /* signal GPE7 from power switch is low active: 0=on , 1=off */
+ result = ((gpio->PEDAT & (1 << 7)) == (1 << 7)) ? 0 : 1;
+
+ print_identifier ();
+ printf("%d\n", result);
+ return 0;
+}
+
+
+int do_fill_level (void)
+{
+ int result;
+
+ result = *CPLD_FILL_LEVEL; /* read CPLD */
+ debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
+
+ /* print result to console */
+ print_identifier ();
+ if ((result & (1 << 16)) == 0)
+ printf("0\n");
+ else
+ printf("1\n");
+ return 0;
+}
+
+
+int do_rotary_switch (void)
+{
+ int result;
+ /*
+ * Please note, that the default values of the direction bits are
+ * undefined after reset. So it is a good idea, to make first a dummy
+ * call to this function, to clear the direction bits and set so to
+ * proper values.
+ */
+
+ result = *CPLD_ROTARY_SWITCH; /* read CPLD */
+ debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
+
+ *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
+
+ /* print result to console */
+ print_identifier ();
+ if ((result & (1 << 16)) == (1 << 16))
+ printf("R");
+ if ((result & (1 << 17)) == (1 << 17))
+ printf("L");
+ if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
+ printf("0");
+ if ((result & (1 << 18)) == 0)
+ printf("0\n");
+ else
+ printf("1\n");
+ return 0;
+}
+
+
+int do_vfd_id (void)
+{
+ int i;
+ long int pcup_old, pccon_old;
+ int vfd_board_id;
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* try to red vfd board id from the value defined by pull-ups */
+
+ pcup_old = gpio->PCUP;
+ pccon_old = gpio->PCCON;
+
+ gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pull-ups */
+ gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
+ * inputs */
+ udelay (10); /* allow signals to settle */
+ vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
+
+ gpio->PCCON = pccon_old;
+ gpio->PCUP = pcup_old;
+
+ /* print vfd_board_id to console */
+ print_identifier ();
+ for (i = 0; i < 4; i++) {
+ if ((vfd_board_id & (1 << i)) == 0)
+ printf("0");
+ else
+ printf("1");
+ }
+ printf("\n");
+ return 0;
+}
+
+int do_buzzer (char **argv)
+{
+ int counter;
+
+ S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* set prescaler for timer 2, 3 and 4 */
+ timers->TCFG0 &= ~0xFF00;
+ timers->TCFG0 |= 0x0F00;
+
+ /* set divider for timer 2 */
+ timers->TCFG1 &= ~0xF00;
+ timers->TCFG1 |= 0x300;
+
+ /* set frequency */
+ counter = (PCLK / BUZZER_FREQ) >> 9;
+ timers->ch[2].TCNTB = counter;
+ timers->ch[2].TCMPB = counter / 2;
+
+ if (strcmp (argv[2], "on") == 0) {
+ debug ("%s: frequency: %d\n", __FUNCTION__,
+ BUZZER_FREQ);
+
+ /* configure pin GPD7 as TOUT2 */
+ gpio->PDCON &= ~0xC000;
+ gpio->PDCON |= 0x8000;
+
+ /* start */
+ timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) &
+ ~INVERT2;
+ timers->TCON = (timers->TCON | START2) & ~UPDATE2;
+ return (0);
+ }
+ else if (strcmp (argv[2], "off") == 0) {
+ /* stop */
+ timers->TCON &= ~(START2 | RELOAD2);
+
+ /* configure GPD7 as output and set to low */
+ gpio->PDCON &= ~0xC000;
+ gpio->PDCON |= 0x4000;
+ gpio->PDDAT &= ~0x80;
+ return (0);
+ }
+
+ printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
+ return 1;
+}
+
+
+int do_led (char **argv)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* configure PC14 and PC15 as output */
+ gpio->PCCON &= ~(0xF << 28);
+ gpio->PCCON |= (0x5 << 28);
+
+ /* configure PD0 and PD4 as output */
+ gpio->PDCON &= ~((0x3 << 8) | 0x3);
+ gpio->PDCON |= ((0x1 << 8) | 0x1);
+
+ switch (simple_strtoul(argv[2], NULL, 10)) {
+
+ case 0:
+ case 1:
+ break;
+
+ case 2:
+ if (strcmp (argv[3], "on") == 0)
+ gpio->PCDAT |= (1 << 14);
+ else
+ gpio->PCDAT &= ~(1 << 14);
+ return 0;
+
+ case 3:
+ if (strcmp (argv[3], "on") == 0)
+ gpio->PCDAT |= (1 << 15);
+ else
+ gpio->PCDAT &= ~(1 << 15);
+ return 0;
+
+ case 4:
+ if (strcmp (argv[3], "on") == 0)
+ gpio->PDDAT |= (1 << 0);
+ else
+ gpio->PDDAT &= ~(1 << 0);
+ return 0;
+
+ case 5:
+ if (strcmp (argv[3], "on") == 0)
+ gpio->PDDAT |= (1 << 4);
+ else
+ gpio->PDDAT &= ~(1 << 4);
+ return 0;
+
+ default:
+ break;
+
+ }
+ printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
+ return 1;
+}
+
+
+int do_full_bridge (char **argv)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* configure PD5 and PD6 as output */
+ gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
+ gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
+
+ if (strcmp (argv[2], "+") == 0) {
+ gpio->PDDAT |= (1 << 5);
+ gpio->PDDAT |= (1 << 6);
+ return 0;
+ }
+ else if (strcmp (argv[2], "-") == 0) {
+ gpio->PDDAT &= ~(1 << 5);
+ gpio->PDDAT |= (1 << 6);
+ return 0;
+ }
+ else if (strcmp (argv[2], "off") == 0) {
+ gpio->PDDAT &= ~(1 << 5);
+ gpio->PDDAT &= ~(1 << 6);
+ return 0;
+ }
+ printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
+ return 1;
+}
+
+/* val must be in [0, 4095] */
+static inline unsigned long tsc2000_to_uv (u16 val)
+{
+ return ((250000 * val) / 4096) * 10;
+}
+
+
+int do_dac (char **argv)
+{
+ int brightness;
+
+ /* initialize SPI */
+ spi_init ();
+
+ if (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
+ (brightness > 255)) {
+ printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
+ return 1;
+ }
+ tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
+ tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
+
+ return 0;
+}
+
+
+int do_v_bat (void)
+{
+ unsigned long ret, res;
+
+ /* initialize SPI */
+ spi_init ();
+
+ tsc2000_write(TSC2000_REG_ADC, 0x1836);
+
+ /* now wait for data available */
+ adc_wait_conversion_done();
+
+ ret = tsc2000_read(TSC2000_REG_BAT1);
+ res = (tsc2000_to_uv(ret) + 1250) / 2500;
+ res += (ERROR_BATTERY * res) / 1000;
+
+ print_identifier ();
+ printf ("%ld", (res / 100));
+ printf (".%ld", ((res % 100) / 10));
+ printf ("%ld V\n", (res % 10));
+ return 0;
+}
+
+
+int do_pressure (void)
+{
+ /* initialize SPI */
+ spi_init ();
+
+ tsc2000_write(TSC2000_REG_ADC, 0x2436);
+
+ /* now wait for data available */
+ adc_wait_conversion_done();
+
+ print_identifier ();
+ printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
+ return 0;
+}
+
+
+int do_motor_contact (void)
+{
+ int result;
+
+ result = *CPLD_FILL_LEVEL; /* read CPLD */
+ debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
+
+ /* print result to console */
+ print_identifier ();
+ if ((result & (1 << 17)) == 0)
+ printf("0\n");
+ else
+ printf("1\n");
+ return 0;
+}
+
+int do_motor (char **argv)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ /* Configure I/O port */
+ gpio->PGCON &= ~(0x3 << 0);
+ gpio->PGCON |= (0x1 << 0);
+
+ if (strcmp (argv[2], "on") == 0) {
+ gpio->PGDAT &= ~(1 << 0);
+ return 0;
+ }
+ if (strcmp (argv[2], "off") == 0) {
+ gpio->PGDAT |= (1 << 0);
+ return 0;
+ }
+ printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
+ return 1;
+}
+
+static void print_identifier (void)
+{
+ printf ("## FKT: ");
+}
+
+int do_pwm (char **argv)
+{
+ int counter;
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+ S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
+
+ if (strcmp (argv[2], "on") == 0) {
+ /* configure pin GPD8 as TOUT3 */
+ gpio->PDCON &= ~(0x3 << 8*2);
+ gpio->PDCON |= (0x2 << 8*2);
+
+ /* set prescaler for timer 2, 3 and 4 */
+ timers->TCFG0 &= ~0xFF00;
+ timers->TCFG0 |= 0x0F00;
+
+ /* set divider for timer 3 */
+ timers->TCFG1 &= ~(0xf << 12);
+ timers->TCFG1 |= (0x3 << 12);
+
+ /* set frequency */
+ counter = (PCLK / PWM_FREQ) >> 9;
+ timers->ch[3].TCNTB = counter;
+ timers->ch[3].TCMPB = counter / 2;
+
+ /* start timer */
+ timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
+ timers->TCON = (timers->TCON | START3) & ~UPDATE3;
+ return 0;
+ }
+ if (strcmp (argv[2], "off") == 0) {
+
+ /* stop timer */
+ timers->TCON &= ~(START2 | RELOAD2);
+
+ /* configure pin GPD8 as output and set to 0 */
+ gpio->PDCON &= ~(0x3 << 8*2);
+ gpio->PDCON |= (0x1 << 8*2);
+ gpio->PDDAT &= ~(1 << 8);
+ return 0;
+ }
+ printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
+ return 1;
+}
+
+
+int do_thermo (char **argv)
+{
+ int channel, res;
+
+ tsc2000_reg_init ();
+
+ if (strcmp (argv[2], "all") == 0) {
+ int i;
+ for (i=0; i <= 15; i++) {
+ res = tsc2000_read_channel(i);
+ print_identifier ();
+ printf ("c%d: %d\n", i, res);
+ }
+ return 0;
+ }
+ channel = simple_strtoul (argv[2], NULL, 10);
+ res = tsc2000_read_channel(channel);
+ print_identifier ();
+ printf ("%d\n", res);
+ return 0; /* return OK */
+}
+
+
+int do_touch (char **argv)
+{
+ int x, y;
+
+ if (strcmp (argv[2], "tl") == 0) {
+#ifdef CONFIG_TOUCH_WAIT_PRESSED
+ touch_wait_pressed();
+#else
+ {
+ int i;
+ for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
+ if (touch_check_pressed ()) {
+ break;
+ }
+ udelay (1000); /* pause 1 ms */
+ }
+ }
+ if (!touch_check_pressed()) {
+ print_identifier ();
+ printf ("error: touch not pressed\n");
+ return 1;
+ }
+#endif /* CONFIG_TOUCH_WAIT_PRESSED */
+ touch_read_x_y (&x, &y);
+
+ print_identifier ();
+ printf ("x=%d y=%d\n", x, y);
+ return touch_write_clibration_values (CALIB_TL, x, y);
+ }
+ else if (strcmp (argv[2], "dr") == 0) {
+#ifdef CONFIG_TOUCH_WAIT_PRESSED
+ touch_wait_pressed();
+#else
+ {
+ int i;
+ for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
+ if (touch_check_pressed ()) {
+ break;
+ }
+ udelay (1000); /* pause 1 ms */
+ }
+ }
+ if (!touch_check_pressed()) {
+ print_identifier ();
+ printf ("error: touch not pressed\n");
+ return 1;
+ }
+#endif /* CONFIG_TOUCH_WAIT_PRESSED */
+ touch_read_x_y (&x, &y);
+
+ print_identifier ();
+ printf ("x=%d y=%d\n", x, y);
+
+ return touch_write_clibration_values (CALIB_DR, x, y);
+ }
+ return 1; /* not "tl", nor "dr", so return error */
+}
+
+
+#ifdef CONFIG_TOUCH_WAIT_PRESSED
+static void touch_wait_pressed (void)
+{
+ while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
+}
+
+#else
+static int touch_check_pressed (void)
+{
+ return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
+}
+#endif /* CONFIG_TOUCH_WAIT_PRESSED */
+
+static int touch_write_clibration_values (int calib_point, int x, int y)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_I2C)
+ int x_verify = 0;
+ int y_verify = 0;
+
+ tsc2000_reg_init ();
+
+ if (calib_point == CALIB_TL) {
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
+ (char *)&x, 2)) {
+ return 1;
+ }
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
+ (char *)&y, 2)) {
+ return 1;
+ }
+
+ /* verify written values */
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
+ (char *)&x_verify, 2)) {
+ return 1;
+ }
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
+ (char *)&y_verify, 2)) {
+ return 1;
+ }
+ if ((y != y_verify) || (x != x_verify)) {
+ print_identifier ();
+ printf ("error: verify error\n");
+ return 1;
+ }
+ return 0; /* no error */
+ }
+ else if (calib_point == CALIB_DR) {
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
+ (char *)&x, 2)) {
+ return 1;
+ }
+ if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
+ (char *)&y, 2)) {
+ return 1;
+ }
+
+ /* verify written values */
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
+ (char *)&x_verify, 2)) {
+ return 1;
+ }
+ if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
+ (char *)&y_verify, 2)) {
+ return 1;
+ }
+ if ((y != y_verify) || (x != x_verify)) {
+ print_identifier ();
+ printf ("error: verify error\n");
+ return 1;
+ }
+ return 0;
+ }
+ return 1;
+#else
+ printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
+ "to EEPROM\n");
+ return (1);
+#endif /* CFG_CMD_I2C */
+}
+
+
+static void touch_read_x_y (int *px, int *py)
+{
+ tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
+ adc_wait_conversion_done();
+ *px = tsc2000_read(TSC2000_REG_X);
+
+ tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
+ adc_wait_conversion_done();
+ *py = tsc2000_read(TSC2000_REG_Y);
+}
+
+
+int do_rs485 (char **argv)
+{
+ int timeout;
+ char data[RS485_MAX_RECEIVE_BUF_LEN];
+
+ if (strcmp (argv[2], "send") == 0) {
+ return (rs485_send_line (argv[3]));
+ }
+ else if (strcmp (argv[2], "receive") == 0) {
+ timeout = simple_strtoul(argv[3], NULL, 10);
+ if (rs485_receive_chars (data, timeout) != 0) {
+ print_identifier ();
+ printf ("## nothing received\n");
+ return (1);
+ }
+ else {
+ print_identifier ();
+ printf ("%s\n", data);
+ return (0);
+ }
+ }
+ printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
+ return (1); /* unknown command, return error */
+}
+
+
+static int rs485_send_line (const char *data)
+{
+ rs485_init ();
+ trab_rs485_enable_tx ();
+ rs485_puts (data);
+ rs485_putc ('\n');
+
+ return (0);
+}
+
+
+static int rs485_receive_chars (char *data, int timeout)
+{
+ int i;
+ int receive_count = 0;
+
+ rs485_init ();
+ trab_rs485_enable_rx ();
+
+ /* test every 1 ms for received characters to avoid a receive FIFO
+ * overrun (@ 38.400 Baud) */
+ for (i = 0; i < (timeout * 1000); i++) {
+ while (rs485_tstc ()) {
+ if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
+ break;
+ *data++ = rs485_getc ();
+ receive_count++;
+ }
+ udelay (1000); /* pause 1 ms */
+ }
+ *data = '\0'; /* terminate string */
+
+ if (receive_count == 0)
+ return (1);
+ else
+ return (0);
+}
+
+
+int do_serial_number (char **argv)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_I2C)
+ unsigned int serial_number;
+
+ if (strcmp (argv[2], "read") == 0) {
+ if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
+ (char *)&serial_number, 4)) {
+ printf ("could not read from eeprom\n");
+ return (1);
+ }
+ print_identifier ();
+ printf ("%08d\n", serial_number);
+ return (0);
+ }
+ else if (strcmp (argv[2], "write") == 0) {
+ serial_number = simple_strtoul(argv[3], NULL, 10);
+ if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
+ (char *)&serial_number, 4)) {
+ printf ("could not write to eeprom\n");
+ return (1);
+ }
+ return (0);
+ }
+ printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
+ return (1); /* unknown command, return error */
+#else
+ printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
+ "to EEPROM\n");
+ return (1);
+#endif /* CFG_CMD_I2C */
+}
+
+
+int do_crc16 (void)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_I2C)
+ int crc;
+ char buf[EEPROM_MAX_CRC_BUF];
+
+ if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
+ printf ("could not read from eeprom\n");
+ return (1);
+ }
+ crc = 0; /* start value of crc calculation */
+ crc = updcrc (crc, buf, 60);
+
+ print_identifier ();
+ printf ("crc16=%#04x\n", crc);
+
+ if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (char *)&crc,
+ sizeof (crc))) {
+ printf ("could not read from eeprom\n");
+ return (1);
+ }
+ return (0);
+#else
+ printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
+ "to EEPROM\n");
+ return (1);
+#endif /* CFG_CMD_I2C */
+}
+
+
+/*
+ * Calculate, intelligently, the CRC of a dataset incrementally given a
+ * buffer full at a time.
+ * Initialize crc to 0 for XMODEM, -1 for CCITT.
+ *
+ * Usage:
+ * newcrc = updcrc( oldcrc, bufadr, buflen )
+ * unsigned int oldcrc, buflen;
+ * char *bufadr;
+ *
+ * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
+ * Compile with -DMAKETAB to print values for crctab to stdout
+ */
+
+ /* the CRC polynomial. This is used by XMODEM (almost CCITT).
+ * If you change P, you must change crctab[]'s initial value to what is
+ * printed by initcrctab()
+ */
+#define P 0x1021
+
+ /* number of bits in CRC: don't change it. */
+#define W 16
+
+ /* this the number of bits per char: don't change it. */
+#define B 8
+
+static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+ };
+
+static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
+ unsigned int icnt )
+{
+ register unsigned short crc = icrc;
+ register unsigned char *cp = icp;
+ register unsigned int cnt = icnt;
+
+ while (cnt--)
+ crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
+
+ return (crc);
+}
+
+
+int do_gain (char **argv)
+{
+ int range;
+
+ range = simple_strtoul (argv[2], NULL, 10);
+ if ((range < 1) || (range > 3))
+ {
+ printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
+ return 1;
+ }
+
+ tsc2000_set_range (range);
+ return (0);
+}
+
+
+int do_eeprom (char **argv)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_I2C)
+ if (strcmp (argv[2], "read") == 0) {
+ return (trab_eeprom_read (argv));
+ }
+
+ else if (strcmp (argv[2], "write") == 0) {
+ return (trab_eeprom_write (argv));
+ }
+
+ printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
+ return (1);
+#else
+ printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
+ "to EEPROM\n");
+ return (1);
+#endif /* CFG_CMD_I2C */
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_I2C)
+static int trab_eeprom_read (char **argv)
+{
+ int i;
+ int len;
+ unsigned int addr;
+ long int value = 0;
+ uchar *buffer;
+
+ buffer = (uchar *) &value;
+ addr = simple_strtoul (argv[3], NULL, 10);
+ addr &= 0xfff;
+ len = simple_strtoul (argv[4], NULL, 10);
+ if ((len < 1) || (len > 4)) {
+ printf ("%s: invalid parameter %s\n", __FUNCTION__,
+ argv[4]);
+ return (1);
+ }
+ for (i = 0; i < len; i++) {
+ if (i2c_read (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
+ printf ("%s: could not read from i2c device %#x"
+ ", addr %d\n", __FUNCTION__,
+ I2C_EEPROM_DEV_ADDR, addr);
+ return (1);
+ }
+ }
+ print_identifier ();
+ if (strcmp (argv[5], "-") == 0) {
+ if (len == 1)
+ printf ("%d\n", (signed char) value);
+ else if (len == 2)
+ printf ("%d\n", (signed short int) value);
+ else
+ printf ("%ld\n", value);
+ }
+ else {
+ if (len == 1)
+ printf ("%d\n", (unsigned char) value);
+ else if (len == 2)
+ printf ("%d\n", (unsigned short int) value);
+ else
+ printf ("%ld\n", (unsigned long int) value);
+ }
+ return (0);
+}
+
+static int trab_eeprom_write (char **argv)
+{
+ int i;
+ int len;
+ unsigned int addr;
+ long int value = 0;
+ uchar *buffer;
+
+ buffer = (uchar *) &value;
+ addr = simple_strtoul (argv[3], NULL, 10);
+ addr &= 0xfff;
+ len = simple_strtoul (argv[4], NULL, 10);
+ if ((len < 1) || (len > 4)) {
+ printf ("%s: invalid parameter %s\n", __FUNCTION__,
+ argv[4]);
+ return (1);
+ }
+ value = simple_strtol (argv[5], NULL, 10);
+ debug ("value=%ld\n", value);
+ for (i = 0; i < len; i++) {
+ if (i2c_write (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
+ printf ("%s: could not write to i2c device %d"
+ ", addr %d\n", __FUNCTION__,
+ I2C_EEPROM_DEV_ADDR, addr);
+ return (1);
+ }
+#if 0
+ printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
+ "%#x+%d=%p=%#x \n",I2C_EEPROM_DEV_ADDR_DEV_ADDR , addr,
+ i, addr+i, 1, buffer, i, buffer+i, *(buffer+i));
+#endif
+ udelay (30000); /* wait for EEPROM ready */
+ }
+ return (0);
+}
+
+int i2c_write_multiple (uchar chip, uint addr, int alen,
+ uchar *buffer, int len)
+{
+ int i;
+
+ if (alen != 1) {
+ printf ("%s: addr len other than 1 not supported\n",
+ __FUNCTION__);
+ return (1);
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
+ printf ("%s: could not write to i2c device %d"
+ ", addr %d\n", __FUNCTION__, chip, addr);
+ return (1);
+ }
+#if 0
+ printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
+ "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
+ alen, buffer, i, buffer+i, buffer+i);
+#endif
+
+ udelay (30000);
+ }
+ return (0);
+}
+
+int i2c_read_multiple ( uchar chip, uint addr, int alen,
+ uchar *buffer, int len)
+{
+ int i;
+
+ if (alen != 1) {
+ printf ("%s: addr len other than 1 not supported\n",
+ __FUNCTION__);
+ return (1);
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
+ printf ("%s: could not read from i2c device %#x"
+ ", addr %d\n", __FUNCTION__, chip, addr);
+ return (1);
+ }
+ }
+ return (0);
+}
+#endif /* CFG_CMD_I2C */
diff --git a/board/trab/tsc2000.c b/board/trab/tsc2000.c
new file mode 100755
index 0000000..ca68682
--- /dev/null
+++ b/board/trab/tsc2000.c
@@ -0,0 +1,362 @@
+/*
+ * Functions to access the TSC2000 controller on TRAB board (used for scanning
+ * thermo sensors)
+ *
+ * Copyright (C) 2003 Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
+ *
+ * Copyright (C) 2002 DENX Software Engineering, Wolfgang Denk, 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 <common.h>
+#include <s3c2400.h>
+#include "tsc2000.h"
+
+#include "Pt1000_temp_data.h"
+
+/* helper function */
+#define abs(value) (((value) < 0) ? ((value)*-1) : (value))
+
+/*
+ * Maximal allowed deviation between two immediate meassurments of an analog
+ * thermo channel. 1 DIGIT = 0.0276 °C. This is used to filter sporadic
+ * "jumps" in measurment.
+ */
+#define MAX_DEVIATION 18 /* unit: DIGITs of adc; 18 DIGIT = 0.5 °C */
+
+void spi_init(void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+ S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
+ int i;
+
+ /* Configure I/O ports. */
+ gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;
+ gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;
+ gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;
+ gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;
+
+ CLR_CS_TOUCH();
+
+ spi->ch[0].SPPRE = 0x1F; /* Baud-rate ca. 514kHz */
+ spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */
+ spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0,
+ CPHA=1 */
+
+ /* Dummy byte ensures clock to be low. */
+ for (i = 0; i < 10; i++) {
+ spi->ch[0].SPTDAT = 0xFF;
+ }
+ spi_wait_transmit_done();
+}
+
+
+void spi_wait_transmit_done(void)
+{
+ S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
+
+ while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
+}
+
+
+void tsc2000_write(unsigned short reg, unsigned short data)
+{
+ S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
+ unsigned int command;
+
+ SET_CS_TOUCH();
+ command = reg;
+ spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
+ spi_wait_transmit_done();
+ spi->ch[0].SPTDAT = (command & 0x00FF);
+ spi_wait_transmit_done();
+ spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;
+ spi_wait_transmit_done();
+ spi->ch[0].SPTDAT = (data & 0x00FF);
+ spi_wait_transmit_done();
+
+ CLR_CS_TOUCH();
+}
+
+
+unsigned short tsc2000_read (unsigned short reg)
+{
+ unsigned short command, data;
+ S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
+
+ SET_CS_TOUCH();
+ command = 0x8000 | reg;
+
+ spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
+ spi_wait_transmit_done();
+ spi->ch[0].SPTDAT = (command & 0x00FF);
+ spi_wait_transmit_done();
+
+ spi->ch[0].SPTDAT = 0xFF;
+ spi_wait_transmit_done();
+ data = spi->ch[0].SPRDAT;
+ spi->ch[0].SPTDAT = 0xFF;
+ spi_wait_transmit_done();
+
+ CLR_CS_TOUCH();
+ return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);
+}
+
+
+void tsc2000_set_mux (unsigned int channel)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;
+ CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;
+ switch (channel) {
+ case 0:
+ CLR_MUX0; CLR_MUX1;
+ SET_MUX1_ENABLE;
+ break;
+ case 1:
+ SET_MUX0; CLR_MUX1;
+ SET_MUX1_ENABLE;
+ break;
+ case 2:
+ CLR_MUX0; SET_MUX1;
+ SET_MUX1_ENABLE;
+ break;
+ case 3:
+ SET_MUX0; SET_MUX1;
+ SET_MUX1_ENABLE;
+ break;
+ case 4:
+ CLR_MUX0; CLR_MUX1;
+ SET_MUX2_ENABLE;
+ break;
+ case 5:
+ SET_MUX0; CLR_MUX1;
+ SET_MUX2_ENABLE;
+ break;
+ case 6:
+ CLR_MUX0; SET_MUX1;
+ SET_MUX2_ENABLE;
+ break;
+ case 7:
+ SET_MUX0; SET_MUX1;
+ SET_MUX2_ENABLE;
+ break;
+ case 8:
+ CLR_MUX0; CLR_MUX1;
+ SET_MUX3_ENABLE;
+ break;
+ case 9:
+ SET_MUX0; CLR_MUX1;
+ SET_MUX3_ENABLE;
+ break;
+ case 10:
+ CLR_MUX0; SET_MUX1;
+ SET_MUX3_ENABLE;
+ break;
+ case 11:
+ SET_MUX0; SET_MUX1;
+ SET_MUX3_ENABLE;
+ break;
+ case 12:
+ CLR_MUX0; CLR_MUX1;
+ SET_MUX4_ENABLE;
+ break;
+ case 13:
+ SET_MUX0; CLR_MUX1;
+ SET_MUX4_ENABLE;
+ break;
+ case 14:
+ CLR_MUX0; SET_MUX1;
+ SET_MUX4_ENABLE;
+ break;
+ case 15:
+ SET_MUX0; SET_MUX1;
+ SET_MUX4_ENABLE;
+ break;
+ default:
+ CLR_MUX0; CLR_MUX1;
+ }
+}
+
+
+void tsc2000_set_range (unsigned int range)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ switch (range) {
+ case 1:
+ CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;
+ CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
+ break;
+ case 2:
+ CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
+ CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;
+ break;
+ case 3:
+ SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
+ SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
+ break;
+ }
+}
+
+
+u16 tsc2000_read_channel (unsigned int channel)
+{
+ u16 res;
+
+ tsc2000_set_mux(channel);
+ udelay(3 * TSC2000_DELAY_BASE);
+
+ tsc2000_write(TSC2000_REG_ADC, 0x2036);
+ adc_wait_conversion_done ();
+ res = tsc2000_read(TSC2000_REG_AUX1);
+ return res;
+}
+
+
+s32 tsc2000_contact_temp (void)
+{
+ long adc_pt1000, offset;
+ long u_pt1000;
+ long contact_temp;
+ long temp1, temp2;
+
+ tsc2000_reg_init ();
+ tsc2000_set_range (3);
+
+ /*
+ * Because of sporadic "jumps" in the measured adc values every
+ * channel is read two times. If there is a significant difference
+ * between the two measurements, then print an error and do a third
+ * measurement, because it is very unlikely that a successive third
+ * measurement goes also wrong.
+ */
+ temp1 = tsc2000_read_channel (14);
+ temp2 = tsc2000_read_channel (14);
+ if (abs(temp2 - temp1) < MAX_DEVIATION)
+ adc_pt1000 = temp2;
+ else {
+ printf ("%s: read adc value (channel 14) exceeded max allowed "
+ "deviation: %d * 0.0276 °C\n",
+ __FUNCTION__, MAX_DEVIATION);
+ printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
+ temp1, temp2);
+ adc_pt1000 = tsc2000_read_channel (14);
+ printf ("use (third read) adc value: adc_pt1000 = "
+ "%ld DIGITs\n", adc_pt1000);
+ }
+ debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);
+
+ temp1 = tsc2000_read_channel (15);
+ temp2 = tsc2000_read_channel (15);
+ if (abs(temp2 - temp1) < MAX_DEVIATION)
+ offset = temp2;
+ else {
+ printf ("%s: read adc value (channel 15) exceeded max allowed "
+ "deviation: %d * 0.0276 °C\n",
+ __FUNCTION__, MAX_DEVIATION);
+ printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
+ temp1, temp2);
+ offset = tsc2000_read_channel (15);
+ printf ("use (third read) adc value: offset = %ld DIGITs\n",
+ offset);
+ }
+ debug ("read channel 15 (offset): %ld\n", offset);
+
+ /*
+ * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =
+ * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:
+ * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The
+ * error correction Values err_vref and err_amp3 are assumed as 0 in
+ * u-boot, because this could cause only a very small error (< 1%).
+ */
+ u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;
+ debug ("u_pt1000: %ld\n", u_pt1000);
+
+ if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,
+ &contact_temp) == -1) {
+ printf ("%s: error interpolating PT1000 vlaue\n",
+ __FUNCTION__);
+ return (-1000);
+ }
+ debug ("contact_temp: %ld\n", contact_temp);
+
+ return contact_temp;
+}
+
+
+void tsc2000_reg_init (void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ tsc2000_write(TSC2000_REG_ADC, 0x2036);
+ tsc2000_write(TSC2000_REG_REF, 0x0011);
+ tsc2000_write(TSC2000_REG_DACCTL, 0x0000);
+
+ CON_MUX0;
+ CON_MUX1;
+
+ CON_MUX1_ENABLE;
+ CON_MUX2_ENABLE;
+ CON_MUX3_ENABLE;
+ CON_MUX4_ENABLE;
+
+ CON_SEL_TEMP_V_0;
+ CON_SEL_TEMP_V_1;
+ CON_SEL_TEMP_V_2;
+ CON_SEL_TEMP_V_3;
+
+ tsc2000_set_mux(0);
+ tsc2000_set_range(0);
+}
+
+
+int tsc2000_interpolate(long value, long data[][2], long *result)
+{
+ int i;
+
+ /* the data is sorted and the first element is upper
+ * limit so we can easily check for out-of-band values
+ */
+ if (data[0][0] < value || data[1][0] > value)
+ return -1;
+
+ i = 1;
+ while (data[i][0] < value)
+ i++;
+
+ /* To prevent overflow we have to store the intermediate
+ result in 'long long'.
+ */
+
+ *result = data[i-1][1] +
+ ((unsigned long long)(data[i][1] - data[i-1][1])
+ * (unsigned long long)(value - data[i-1][0]))
+ / (data[i][0] - data[i-1][0]);
+
+ return 0;
+}
+
+
+void adc_wait_conversion_done(void)
+{
+ while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));
+}
diff --git a/board/trab/tsc2000.h b/board/trab/tsc2000.h
new file mode 100755
index 0000000..aac9c0c
--- /dev/null
+++ b/board/trab/tsc2000.h
@@ -0,0 +1,145 @@
+/*
+ * Functions to access the TSC2000 controller on TRAB board (used for scanning
+ * thermo sensors)
+ *
+ * Copyright (C) 2003 Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
+ *
+ * Copyright (C) 2002 DENX Software Engineering, Wolfgang Denk, 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 _TSC2000_H_
+#define _TSC2000_H_
+
+/* temperature channel multiplexer definitions */
+#define CON_MUX0 (gpio->PCCON = (gpio->PCCON & 0x0FFFFFCFF) | 0x00000100)
+#define CLR_MUX0 (gpio->PCDAT &= 0x0FFEF)
+#define SET_MUX0 (gpio->PCDAT |= 0x00010)
+
+#define CON_MUX1 (gpio->PCCON = (gpio->PCCON & 0x0FFFFF3FF) | 0x00000400)
+#define CLR_MUX1 (gpio->PCDAT &= 0x0FFDF)
+#define SET_MUX1 (gpio->PCDAT |= 0x00020)
+
+#define CON_MUX1_ENABLE (gpio->PCCON = (gpio->PCCON & 0x0FFFFCFFF) | 0x00001000)
+#define CLR_MUX1_ENABLE (gpio->PCDAT |= 0x00040)
+#define SET_MUX1_ENABLE (gpio->PCDAT &= 0x0FFBF)
+
+#define CON_MUX2_ENABLE (gpio->PCCON = (gpio->PCCON & 0x0FFFF3FFF) | 0x00004000)
+#define CLR_MUX2_ENABLE (gpio->PCDAT |= 0x00080)
+#define SET_MUX2_ENABLE (gpio->PCDAT &= 0x0FF7F)
+
+#define CON_MUX3_ENABLE (gpio->PCCON = (gpio->PCCON & 0x0FFFCFFFF) | 0x00010000)
+#define CLR_MUX3_ENABLE (gpio->PCDAT |= 0x00100)
+#define SET_MUX3_ENABLE (gpio->PCDAT &= 0x0FEFF)
+
+#define CON_MUX4_ENABLE (gpio->PCCON = (gpio->PCCON & 0x0FFF3FFFF) | 0x00040000)
+#define CLR_MUX4_ENABLE (gpio->PCDAT |= 0x00200)
+#define SET_MUX4_ENABLE (gpio->PCDAT &= 0x0FDFF)
+
+#define CON_SEL_TEMP_V_0 (gpio->PCCON = (gpio->PCCON & 0x0FFCFFFFF) | 0x00100000)
+#define CLR_SEL_TEMP_V_0 (gpio->PCDAT &= 0x0FBFF)
+#define SET_SEL_TEMP_V_0 (gpio->PCDAT |= 0x00400)
+
+#define CON_SEL_TEMP_V_1 (gpio->PCCON = (gpio->PCCON & 0x0FF3FFFFF) | 0x00400000)
+#define CLR_SEL_TEMP_V_1 (gpio->PCDAT &= 0x0F7FF)
+#define SET_SEL_TEMP_V_1 (gpio->PCDAT |= 0x00800)
+
+#define CON_SEL_TEMP_V_2 (gpio->PCCON = (gpio->PCCON & 0x0FCFFFFFF) | 0x01000000)
+#define CLR_SEL_TEMP_V_2 (gpio->PCDAT &= 0x0EFFF)
+#define SET_SEL_TEMP_V_2 (gpio->PCDAT |= 0x01000)
+
+#define CON_SEL_TEMP_V_3 (gpio->PCCON = (gpio->PCCON & 0x0F3FFFFFF) | 0x04000000)
+#define CLR_SEL_TEMP_V_3 (gpio->PCDAT &= 0x0DFFF)
+#define SET_SEL_TEMP_V_3 (gpio->PCDAT |= 0x02000)
+
+/* TSC2000 register definition */
+#define TSC2000_REG_X ((0 << 11) | (0 << 5))
+#define TSC2000_REG_Y ((0 << 11) | (1 << 5))
+#define TSC2000_REG_Z1 ((0 << 11) | (2 << 5))
+#define TSC2000_REG_Z2 ((0 << 11) | (3 << 5))
+#define TSC2000_REG_BAT1 ((0 << 11) | (5 << 5))
+#define TSC2000_REG_BAT2 ((0 << 11) | (6 << 5))
+#define TSC2000_REG_AUX1 ((0 << 11) | (7 << 5))
+#define TSC2000_REG_AUX2 ((0 << 11) | (8 << 5))
+#define TSC2000_REG_TEMP1 ((0 << 11) | (9 << 5))
+#define TSC2000_REG_TEMP2 ((0 << 11) | (0xA << 5))
+#define TSC2000_REG_DAC ((0 << 11) | (0xB << 5))
+#define TSC2000_REG_ZERO ((0 << 11) | (0x10 << 5))
+#define TSC2000_REG_ADC ((1 << 11) | (0 << 5))
+#define TSC2000_REG_DACCTL ((1 << 11) | (2 << 5))
+#define TSC2000_REG_REF ((1 << 11) | (3 << 5))
+#define TSC2000_REG_RESET ((1 << 11) | (4 << 5))
+#define TSC2000_REG_CONFIG ((1 << 11) | (5 << 5))
+
+/* bit definition of TSC2000 ADC register */
+#define TC_PSM (1 << 15)
+#define TC_STS (1 << 14)
+#define TC_AD3 (1 << 13)
+#define TC_AD2 (1 << 12)
+#define TC_AD1 (1 << 11)
+#define TC_AD0 (1 << 10)
+#define TC_RS1 (1 << 9)
+#define TC_RS0 (1 << 8)
+#define TC_AV1 (1 << 7)
+#define TC_AV0 (1 << 6)
+#define TC_CL1 (1 << 5)
+#define TC_CL0 (1 << 4)
+#define TC_PV2 (1 << 3)
+#define TC_PV1 (1 << 2)
+#define TC_PV0 (1 << 1)
+
+/* default value for TSC2000 ADC register for use with touch functions */
+#define DEFAULT_ADC (TC_PV1 | TC_AV0 | TC_AV1 | TC_RS0)
+
+#define TSC2000_DELAY_BASE 500
+#define TSC2000_NO_SENSOR -0x10000
+
+#define ERROR_BATTERY 220 /* must be adjusted, if R68 is changed on
+ * TRAB */
+
+void tsc2000_write(unsigned short, unsigned short);
+unsigned short tsc2000_read (unsigned short);
+u16 tsc2000_read_channel (unsigned int);
+void tsc2000_set_mux (unsigned int);
+void tsc2000_set_range (unsigned int);
+void tsc2000_reg_init (void);
+s32 tsc2000_contact_temp (void);
+void spi_wait_transmit_done (void);
+void spi_init(void);
+int tsc2000_interpolate(long value, long data[][2], long *result);
+void adc_wait_conversion_done(void);
+
+
+static inline void SET_CS_TOUCH(void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ gpio->PDDAT &= 0x5FF;
+}
+
+
+static inline void CLR_CS_TOUCH(void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ gpio->PDDAT |= 0x200;
+}
+
+#endif /* _TSC2000_H_ */
diff --git a/board/trab/u-boot.lds b/board/trab/u-boot.lds
new file mode 100755
index 0000000..e56cdd3
--- /dev/null
+++ b/board/trab/u-boot.lds
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ cpu/arm920t/start.o (.text)
+ lib_arm/_umodsi3.o (.text)
+ lib_generic/zlib.o (.text)
+ lib_generic/crc32.o (.text)
+ lib_generic/string.o (.text)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/environment.o (.ppcenv)
+
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .got : { *(.got) }
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ . = ALIGN(4);
+ __bss_start = .;
+ .bss : { *(.bss) }
+ _end = .;
+}
diff --git a/board/trab/vfd.c b/board/trab/vfd.c
new file mode 100755
index 0000000..f510ee5
--- /dev/null
+++ b/board/trab/vfd.c
@@ -0,0 +1,571 @@
+/*
+ * (C) Copyright 2001
+ * 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
+ */
+
+/************************************************************************/
+/* ** DEBUG SETTINGS */
+/************************************************************************/
+
+/* #define DEBUG */
+
+/************************************************************************/
+/* ** HEADER FILES */
+/************************************************************************/
+
+#include <config.h>
+#include <common.h>
+#include <version.h>
+#include <stdarg.h>
+#include <linux/types.h>
+#include <devices.h>
+#include <s3c2400.h>
+
+#ifdef CONFIG_VFD
+
+/************************************************************************/
+/* ** CONFIG STUFF -- should be moved to board config file */
+/************************************************************************/
+
+/************************************************************************/
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+#define ROT 0x09
+#define BLAU 0x0C
+#define VIOLETT 0X0D
+
+/* MAGIC */
+#define FRAME_BUF_SIZE ((256*4*56)/8)
+#define frame_buf_offs 4
+
+/* defines for starting Timer3 as CPLD-Clk */
+#define START3 (1 << 16)
+#define UPDATE3 (1 << 17)
+#define INVERT3 (1 << 18)
+#define RELOAD3 (1 << 19)
+
+/* CPLD-Register for controlling vfd-blank-signal */
+#define VFD_DISABLE (*(volatile uchar *)0x04038000=0x0000)
+#define VFD_ENABLE (*(volatile uchar *)0x04038000=0x0001)
+
+/* Supported VFD Types */
+#define VFD_TYPE_T119C 1 /* Noritake T119C VFD */
+#define VFD_TYPE_MN11236 2
+
+/*#define NEW_CPLD_CLK*/
+
+int vfd_board_id;
+
+/* taken from armboot/common/vfd.c */
+unsigned long adr_vfd_table[112][18][2][4][2];
+unsigned char bit_vfd_table[112][18][2][4][2];
+
+/*
+ * initialize the values for the VFD-grid-control in the framebuffer
+ */
+void init_grid_ctrl(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ ulong adr, grid_cycle;
+ unsigned int bit, display;
+ unsigned char temp, bit_nr;
+
+ /*
+ * clear frame buffer (logical clear => set to "black")
+ */
+ memset ((void *)(gd->fb_base), 0, FRAME_BUF_SIZE);
+
+ switch (gd->vfd_type) {
+ case VFD_TYPE_T119C:
+ for (display=0; display<4; display++) {
+ for(grid_cycle=0; grid_cycle<56; grid_cycle++) {
+ bit = grid_cycle * 256 * 4 +
+ (grid_cycle + 200) * 4 +
+ frame_buf_offs + display;
+ /* wrap arround if offset (see manual S3C2400) */
+ if (bit>=FRAME_BUF_SIZE*8)
+ bit = bit - (FRAME_BUF_SIZE * 8);
+ adr = gd->fb_base + (bit/32) * 4 + (3 - (bit%32) / 8);
+ bit_nr = bit % 8;
+ bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
+ temp=(*(volatile unsigned char*)(adr));
+ temp |= (1<<bit_nr);
+ (*(volatile unsigned char*)(adr))=temp;
+
+ if(grid_cycle<55)
+ bit = grid_cycle*256*4+(grid_cycle+201)*4+frame_buf_offs+display;
+ else
+ bit = grid_cycle*256*4+200*4+frame_buf_offs+display-4; /* grid nr. 0 */
+ /* wrap arround if offset (see manual S3C2400) */
+ if (bit>=FRAME_BUF_SIZE*8)
+ bit = bit-(FRAME_BUF_SIZE*8);
+ adr = gd->fb_base+(bit/32)*4+(3-(bit%32)/8);
+ bit_nr = bit%8;
+ bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+ temp=(*(volatile unsigned char*)(adr));
+ temp |= (1<<bit_nr);
+ (*(volatile unsigned char*)(adr))=temp;
+ }
+ }
+ break;
+ case VFD_TYPE_MN11236:
+ for (display=0; display<4; display++) {
+ for (grid_cycle=0; grid_cycle<38; grid_cycle++) {
+ bit = grid_cycle * 256 * 4 +
+ (253 - grid_cycle) * 4 +
+ frame_buf_offs + display;
+ /* wrap arround if offset (see manual S3C2400) */
+ if (bit>=FRAME_BUF_SIZE*8)
+ bit = bit - (FRAME_BUF_SIZE * 8);
+ adr = gd->fb_base + (bit/32) * 4 + (3 - (bit%32) / 8);
+ bit_nr = bit % 8;
+ bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
+ temp=(*(volatile unsigned char*)(adr));
+ temp |= (1<<bit_nr);
+ (*(volatile unsigned char*)(adr))=temp;
+
+ if(grid_cycle<37)
+ bit = grid_cycle*256*4+(252-grid_cycle)*4+frame_buf_offs+display;
+
+ /* wrap arround if offset (see manual S3C2400) */
+ if (bit>=FRAME_BUF_SIZE*8)
+ bit = bit-(FRAME_BUF_SIZE*8);
+ adr = gd->fb_base+(bit/32)*4+(3-(bit%32)/8);
+ bit_nr = bit%8;
+ bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+ temp=(*(volatile unsigned char*)(adr));
+ temp |= (1<<bit_nr);
+ (*(volatile unsigned char*)(adr))=temp;
+ }
+ }
+ break;
+ default:
+ printf ("Warning: unknown display type\n");
+ break;
+ }
+}
+
+/*
+ *create translation table for getting easy the right position in the
+ *physical framebuffer for some x/y-coordinates of the VFDs
+ */
+void create_vfd_table(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ unsigned long vfd_table[112][18][2][4][2];
+ unsigned int x, y, color, display, entry, pixel;
+ unsigned int x_abcdef = 0;
+
+ switch (gd->vfd_type) {
+ case VFD_TYPE_T119C:
+ for(y=0; y<=17; y++) { /* Line */
+ for(x=0; x<=111; x++) { /* Column */
+ for(display=0; display <=3; display++) {
+
+ /* Display 0 blue pixels */
+ vfd_table[x][y][0][display][0] =
+ (x==0) ? y*16+display
+ : (x%4)*4+y*16+((x-1)/2)*1024+display;
+ /* Display 0 red pixels */
+ vfd_table[x][y][1][display][0] =
+ (x==0) ? y*16+512+display
+ : (x%4)*4+y*16+((x-1)/2)*1024+512+display;
+ }
+ }
+ }
+ break;
+ case VFD_TYPE_MN11236:
+ for(y=0; y<=17; y++) { /* Line */
+ for(x=0; x<=111; x++) { /* Column */
+ for(display=0; display <=3; display++) {
+
+ vfd_table[x][y][0][display][0]=0;
+ vfd_table[x][y][0][display][1]=0;
+ vfd_table[x][y][1][display][0]=0;
+ vfd_table[x][y][1][display][1]=0;
+
+ switch (x%6) {
+ case 0: x_abcdef=0; break; /* a -> a */
+ case 1: x_abcdef=2; break; /* b -> c */
+ case 2: x_abcdef=4; break; /* c -> e */
+ case 3: x_abcdef=5; break; /* d -> f */
+ case 4: x_abcdef=3; break; /* e -> d */
+ case 5: x_abcdef=1; break; /* f -> b */
+ }
+
+ /* blue pixels */
+ vfd_table[x][y][0][display][0] =
+ (x>1) ? x_abcdef*4+((x-1)/3)*1024+y*48+display
+ : x_abcdef*4+ 0+y*48+display;
+ /* blue pixels */
+ if (x>1 && (x-1)%3)
+ vfd_table[x][y][0][display][1] = x_abcdef*4+((x-1)/3+1)*1024+y*48+display;
+
+ /* red pixels */
+ vfd_table[x][y][1][display][0] =
+ (x>1) ? x_abcdef*4+24+((x-1)/3)*1024+y*48+display
+ : x_abcdef*4+24+ 0+y*48+display;
+ /* red pixels */
+ if (x>1 && (x-1)%3)
+ vfd_table[x][y][1][display][1] = x_abcdef*4+24+((x-1)/3+1)*1024+y*48+display;
+ }
+ }
+ }
+ break;
+ default:
+ /* do nothing */
+ return;
+ }
+
+ /*
+ * Create table with entries for physical byte adresses and
+ * bit-number within the byte
+ * from table with bit-numbers within the total framebuffer
+ */
+ for(y=0;y<18;y++) {
+ for(x=0;x<112;x++) {
+ for(color=0;color<2;color++) {
+ for(display=0;display<4;display++) {
+ for(entry=0;entry<2;entry++) {
+ unsigned long adr = gd->fb_base;
+ unsigned int bit_nr = 0;
+
+ if (vfd_table[x][y][color][display][entry]) {
+
+ pixel = vfd_table[x][y][color][display][entry] + frame_buf_offs;
+ /*
+ * wrap arround if offset
+ * (see manual S3C2400)
+ */
+ if (pixel>=FRAME_BUF_SIZE*8)
+ pixel = pixel-(FRAME_BUF_SIZE*8);
+ adr = gd->fb_base+(pixel/32)*4+(3-(pixel%32)/8);
+ bit_nr = pixel%8;
+ bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
+ }
+ adr_vfd_table[x][y][color][display][entry] = adr;
+ bit_vfd_table[x][y][color][display][entry] = bit_nr;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Set/clear pixel of the VFDs
+ */
+void set_vfd_pixel(unsigned char x, unsigned char y,
+ unsigned char color, unsigned char display,
+ unsigned char value)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ ulong adr;
+ unsigned char bit_nr, temp;
+
+ if (! gd->vfd_type) {
+ /* Unknown type. */
+ return;
+ }
+
+ /* Pixel-Eintrag Nr. 1 */
+ adr = adr_vfd_table[x][y][color][display][0];
+ /* Pixel-Eintrag Nr. 1 */
+ bit_nr = bit_vfd_table[x][y][color][display][0];
+ temp=(*(volatile unsigned char*)(adr));
+
+ if (value)
+ temp |= (1<<bit_nr);
+ else
+ temp &= ~(1<<bit_nr);
+
+ (*(volatile unsigned char*)(adr))=temp;
+}
+
+/*
+ * transfer image from BMP-File
+ */
+void transfer_pic(int display, unsigned char *adr, int height, int width)
+{
+ int x, y;
+ unsigned char temp;
+
+ for (; height > 0; height -= 18)
+ {
+ if (height > 18)
+ y = 18;
+ else
+ y = height;
+ for (; y > 0; y--)
+ {
+ for (x = 0; x < width; x += 2)
+ {
+ temp = *adr++;
+ set_vfd_pixel(x, y-1, 0, display, 0);
+ set_vfd_pixel(x, y-1, 1, display, 0);
+ if ((temp >> 4) == BLAU)
+ set_vfd_pixel(x, y-1, 0, display, 1);
+ else if ((temp >> 4) == ROT)
+ set_vfd_pixel(x, y-1, 1, display, 1);
+ else if ((temp >> 4) == VIOLETT)
+ {
+ set_vfd_pixel(x, y-1, 0, display, 1);
+ set_vfd_pixel(x, y-1, 1, display, 1);
+ }
+ set_vfd_pixel(x+1, y-1, 0, display, 0);
+ set_vfd_pixel(x+1, y-1, 1, display, 0);
+ if ((temp & 0x0F) == BLAU)
+ set_vfd_pixel(x+1, y-1, 0, display, 1);
+ else if ((temp & 0x0F) == ROT)
+ set_vfd_pixel(x+1, y-1, 1, display, 1);
+ else if ((temp & 0x0F) == VIOLETT)
+ {
+ set_vfd_pixel(x+1, y-1, 0, display, 1);
+ set_vfd_pixel(x+1, y-1, 1, display, 1);
+ }
+ }
+ }
+ if (display > 0)
+ display--;
+ else
+ display = 3;
+ }
+}
+
+/*
+ * This function initializes VFD clock that is needed for the CPLD that
+ * manages the keyboard.
+ */
+int vfd_init_clocks (void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+ S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
+ S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();
+
+ /* try to determine display type from the value
+ * defined by pull-ups
+ */
+ gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pullups */
+ gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as inputs */
+ udelay (10); /* allow signals to settle */
+ vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
+
+ VFD_DISABLE; /* activate blank for the vfd */
+
+#define NEW_CPLD_CLK
+
+#ifdef NEW_CPLD_CLK
+ if (vfd_board_id) {
+ /* If new board revision, then use PWM 3 as cpld-clock */
+ /* Enable 500 Hz timer for fill level sensor to operate properly */
+ /* Configure TOUT3 as functional pin, disable pull-up */
+ gpio->PDCON &= ~0x30000;
+ gpio->PDCON |= 0x20000;
+ gpio->PDUP |= (1 << 8);
+
+ /* Configure the prescaler */
+ timers->TCFG0 &= ~0xff00;
+ timers->TCFG0 |= 0x0f00;
+
+ /* Select MUX input (divider) for timer3 (1/16) */
+ timers->TCFG1 &= ~0xf000;
+ timers->TCFG1 |= 0x3000;
+
+ /* Enable autoreload and set the counter and compare
+ * registers to values for the 500 Hz clock
+ * (for a given prescaler (15) and divider (16)):
+ * counter = (66000000 / 500) >> 9;
+ */
+ timers->ch[3].TCNTB = 0x101;
+ timers->ch[3].TCMPB = 0x101 / 2;
+
+ /* Start timer */
+ timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
+ timers->TCON = (timers->TCON | START3) & ~UPDATE3;
+ }
+#endif
+ /* If old board revision, then use vm-signal as cpld-clock */
+ lcd->LCDCON2 = 0x00FFC000;
+ lcd->LCDCON3 = 0x0007FF00;
+ lcd->LCDCON4 = 0x00000000;
+ lcd->LCDCON5 = 0x00000400;
+ lcd->LCDCON1 = 0x00000B75;
+ /* VM (GPD1) is used as clock for the CPLD */
+ gpio->PDCON = (gpio->PDCON & 0xFFFFFFF3) | 0x00000008;
+
+ return 0;
+}
+
+/*
+ * initialize LCD-Controller of the S3C2400 for using VFDs
+ *
+ * VFD detection depends on the board revision:
+ * starting from Rev. 200 a type code can be read from the data pins,
+ * driven by some pull-up resistors; all earlier systems must be
+ * manually configured. The type is set in the "vfd_type" environment
+ * variable.
+ */
+int drv_vfd_init(void)
+{
+ S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+ char *tmp;
+ ulong palette;
+ static int vfd_init_done = 0;
+ int vfd_inv_data = 0;
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ if (vfd_init_done != 0)
+ return (0);
+ vfd_init_done = 1;
+
+ debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_board_id);
+
+ switch (vfd_board_id) {
+ case 0: /* board revision < Rev.200 */
+ if ((tmp = getenv ("vfd_type")) == NULL) {
+ break;
+ }
+ if (strcmp(tmp, "T119C") == 0) {
+ gd->vfd_type = VFD_TYPE_T119C;
+ } else if (strcmp(tmp, "MN11236") == 0) {
+ gd->vfd_type = VFD_TYPE_MN11236;
+ } else {
+ /* cannot use printf for a warning here */
+ gd->vfd_type = 0; /* unknown */
+ }
+
+ break;
+ default: /* default to MN11236, data inverted */
+ gd->vfd_type = VFD_TYPE_MN11236;
+ vfd_inv_data = 1;
+ setenv ("vfd_type", "MN11236");
+ }
+ debug ("VFD type: %s%s\n",
+ (gd->vfd_type == VFD_TYPE_T119C) ? "T119C" :
+ (gd->vfd_type == VFD_TYPE_MN11236) ? "MN11236" :
+ "unknown",
+ vfd_inv_data ? ", inverted data" : "");
+
+ gd->fb_base = gd->fb_base;
+ create_vfd_table();
+ init_grid_ctrl();
+
+ for (palette=0; palette < 16; palette++)
+ (*(volatile unsigned int*)(PALETTE+(palette*4)))=palette;
+ for (palette=16; palette < 256; palette++)
+ (*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00;
+
+ /*
+ * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben
+ * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt
+ * das letzte angezeigte Pixel wird aus dem ersten Nibble geholt
+ * (wrap around)
+ * see manual S3C2400
+ */
+ /* Stopp LCD-Controller */
+ lcd->LCDCON1 = 0x00000000;
+ /* frame buffer startadr */
+ lcd->LCDSADDR1 = gd->fb_base >> 1;
+ /* frame buffer endadr */
+ lcd->LCDSADDR2 = (gd->fb_base + FRAME_BUF_SIZE) >> 1;
+ lcd->LCDSADDR3 = ((256/4));
+ lcd->LCDCON2 = 0x000DC000;
+ if(gd->vfd_type == VFD_TYPE_MN11236)
+ lcd->LCDCON2 = 37 << 14; /* MN11236: 38 lines */
+ else
+ lcd->LCDCON2 = 55 << 14; /* T119C: 56 lines */
+ lcd->LCDCON3 = 0x0051000A;
+ lcd->LCDCON4 = 0x00000001;
+ if (gd->vfd_type && vfd_inv_data)
+ lcd->LCDCON5 = 0x000004C0;
+ else
+ lcd->LCDCON5 = 0x00000440;
+
+ /* Port pins as LCD output */
+ gpio->PCCON = (gpio->PCCON & 0xFFFFFF00)| 0x000000AA;
+ gpio->PDCON = (gpio->PDCON & 0xFFFFFF03)| 0x000000A8;
+
+ /* Synchronize VFD enable with LCD controller to avoid flicker */
+ lcd->LCDCON1 = 0x00000B75; /* Start LCD-Controller */
+ while((lcd->LCDCON5 & 0x180000)!=0x100000); /* Wait for end of VSYNC */
+ while((lcd->LCDCON5 & 0x060000)!=0x040000); /* Wait for next HSYNC */
+ while((lcd->LCDCON5 & 0x060000)==0x040000);
+ while((lcd->LCDCON5 & 0x060000)!=0x000000);
+ if(gd->vfd_type)
+ VFD_ENABLE;
+
+ debug ("LCDSADDR1: %lX\n", lcd->LCDSADDR1);
+ debug ("LCDSADDR2: %lX\n", lcd->LCDSADDR2);
+ debug ("LCDSADDR3: %lX\n", lcd->LCDSADDR3);
+
+ return 0;
+}
+
+/*
+ * Disable VFD: should be run before resetting the system:
+ * disable VM, enable pull-up
+ */
+void disable_vfd (void)
+{
+ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+ VFD_DISABLE;
+ gpio->PDCON &= ~0xC;
+ gpio->PDUP &= ~0x2;
+}
+
+/************************************************************************/
+/* ** ROM capable initialization part - needed to reserve FB memory */
+/************************************************************************/
+
+/*
+ * This is called early in the system initialization to grab memory
+ * for the VFD controller.
+ *
+ * Note that this is running from ROM, so no write access to global data.
+ */
+ulong vfd_setmem (ulong addr)
+{
+ ulong size;
+
+ /* Round up to nearest full page */
+ size = (FRAME_BUF_SIZE + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+
+ debug ("Reserving %ldk for VFD Framebuffer at: %08lx\n", size>>10, addr);
+
+ return (size);
+}
+
+/*
+ * Calculate fb size for VIDEOLFB_ATAG. Size returned contains fb,
+ * descriptors and palette areas.
+ */
+ulong calc_fbsize (void)
+{
+ return FRAME_BUF_SIZE;
+}
+
+#endif /* CONFIG_VFD */