summaryrefslogtreecommitdiffstats
path: root/board/gth2/gth2.c
diff options
context:
space:
mode:
authorWolfgang Denk <wd@fifi.denx.de>2006-06-16 17:32:31 +0200
committerWolfgang Denk <wd@fifi.denx.de>2006-06-16 17:32:31 +0200
commit0c32d96ddd7309b86ff92dfc1f3694908f174cf6 (patch)
tree1136126a58dfc4f89043f65532673128dc3c9b4f /board/gth2/gth2.c
parentc12cffc543df621c162ba26e012c7f4ab0af496e (diff)
downloadbootable_bootloader_goldelico_gta04-0c32d96ddd7309b86ff92dfc1f3694908f174cf6.tar.gz
bootable_bootloader_goldelico_gta04-0c32d96ddd7309b86ff92dfc1f3694908f174cf6.tar.bz2
bootable_bootloader_goldelico_gta04-0c32d96ddd7309b86ff92dfc1f3694908f174cf6.zip
Add support for gth2 board
Patch by Thomas Lange, Aug 11 2005
Diffstat (limited to 'board/gth2/gth2.c')
-rw-r--r--board/gth2/gth2.c435
1 files changed, 435 insertions, 0 deletions
diff --git a/board/gth2/gth2.c b/board/gth2/gth2.c
new file mode 100644
index 000000000..77fc5b469
--- /dev/null
+++ b/board/gth2/gth2.c
@@ -0,0 +1,435 @@
+/*
+ * (C) Copyright 2005
+ * Thomas.Lange@corelatus.se
+ *
+ * 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 <asm/au1x00.h>
+#include <asm/addrspace.h>
+#include <asm/mipsregs.h>
+#include <watchdog.h>
+
+#include "ee_access.h"
+
+static int wdi_status = 0;
+
+unsigned long mips_io_port_base = 0;
+
+#define SDRAM_SIZE ((64*1024*1024)-(12*4096))
+
+
+#define SERIAL_LOG_BUFFER KSEG1ADDR(SDRAM_SIZE + (8*4096))
+
+void inline log_serial_char(char c){
+ char *serial_log_buffer = (char*)SERIAL_LOG_BUFFER;
+ int serial_log_offset;
+ u32 *serial_log_offsetp = (u32*)SERIAL_LOG_BUFFER;
+
+ serial_log_offset = *serial_log_offsetp;
+
+ *(serial_log_buffer + serial_log_offset) = c;
+
+ serial_log_offset++;
+
+ if(serial_log_offset >= 4096){
+ serial_log_offset = 4;
+ }
+ *serial_log_offsetp = serial_log_offset;
+}
+
+void init_log_serial(void){
+ char *serial_log_buffer = (char*)SERIAL_LOG_BUFFER;
+ u32 *serial_log_offsetp = (u32*)SERIAL_LOG_BUFFER;
+
+ /* Copy buffer from last run */
+ memcpy(serial_log_buffer + 4096,
+ serial_log_buffer,
+ 4096);
+
+ memset(serial_log_buffer, 0, 4096);
+
+ *serial_log_offsetp = 4;
+}
+
+
+void hw_watchdog_reset(void){
+ volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET;
+ volatile u32 *sys_outputclear = (volatile u32*)SYS_OUTPUTCLR;
+ if(wdi_status){
+ *sys_outputset = GPIO_CPU_LED|GPIO_WDI;
+ wdi_status = 0;
+ }
+ else{
+ *sys_outputclear = GPIO_CPU_LED|GPIO_WDI;
+ wdi_status = 1;
+ }
+}
+
+long int initdram(int board_type)
+{
+ /* Sdram is setup by assembler code */
+ /* If memory could be changed, we should return the true value here */
+
+ WATCHDOG_RESET();
+
+ return (SDRAM_SIZE);
+}
+
+/* In cpu/mips/cpu.c */
+void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 );
+
+void set_ledcard(u32 value){
+ /* Clock 24 bits to led card */
+ int i;
+ volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET;
+ volatile u32 *sys_outputclr = (volatile u32*)SYS_OUTPUTCLR;
+
+ /* Start with known values */
+ *sys_outputclr = GPIO_LEDCLK|GPIO_LEDD;
+
+ for(i=0;i<24;i++){
+ if(value&0x00800000){
+ *sys_outputset = GPIO_LEDD;
+ }
+ else{
+ *sys_outputclr = GPIO_LEDD;
+ }
+ udelay(1);
+ *sys_outputset = GPIO_LEDCLK;
+ udelay(1);
+ *sys_outputclr = GPIO_LEDCLK;
+ udelay(1);
+
+ value<<=1;
+ }
+ /* Data is enable output */
+ *sys_outputset = GPIO_LEDD;
+}
+
+int checkboard (void)
+{
+ volatile u32 *sys_counter = (volatile u32*)SYS_COUNTER_CNTRL;
+ volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET;
+ volatile u32 *sys_outputclr = (volatile u32*)SYS_OUTPUTCLR;
+ u32 proc_id;
+
+ WATCHDOG_RESET();
+
+ *sys_counter = 0x100; /* Enable 32 kHz oscillator for RTC/TOY */
+
+ proc_id = read_32bit_cp0_register(CP0_PRID);
+
+ switch (proc_id >> 24) {
+ case 0:
+ puts ("Board: GTH2\n");
+ printf ("CPU: Au1000 500 MHz, id: 0x%02x, rev: 0x%02x\n",
+ (proc_id >> 8) & 0xFF, proc_id & 0xFF);
+ break;
+ default:
+ printf ("Unsupported cpu %d, proc_id=0x%x\n", proc_id >> 24, proc_id);
+ }
+#ifdef CONFIG_IDE_PCMCIA
+ /* PCMCIA is on a 36 bit physical address.
+ We need to map it into a 32 bit addresses */
+ write_one_tlb(20, /* index */
+ 0x01ffe000, /* Pagemask, 16 MB pages */
+ CFG_PCMCIA_IO_BASE, /* Hi */
+ 0x3C000017, /* Lo0 */
+ 0x3C200017); /* Lo1 */
+
+ write_one_tlb(21, /* index */
+ 0x01ffe000, /* Pagemask, 16 MB pages */
+ CFG_PCMCIA_ATTR_BASE, /* Hi */
+ 0x3D000017, /* Lo0 */
+ 0x3D200017); /* Lo1 */
+
+ write_one_tlb(22, /* index */
+ 0x01ffe000, /* Pagemask, 16 MB pages */
+ CFG_PCMCIA_MEM_ADDR, /* Hi */
+ 0x3E000017, /* Lo0 */
+ 0x3E200017); /* Lo1 */
+
+#endif /* CONFIG_IDE_PCMCIA */
+
+ /* Wait for GPIO ports to become stable */
+ udelay(5000); /* FIXME */
+
+ /* Release reset of ethernet PHY chips */
+ /* Always do this, because linux does not know about it */
+ *sys_outputset = GPIO_ERESET;
+
+ /* Kill FPGA:s */
+ *sys_outputclr = GPIO_CACONFIG|GPIO_DPACONFIG;
+ udelay(2);
+ *sys_outputset = GPIO_CACONFIG|GPIO_DPACONFIG;
+
+ /* Turn front led yellow */
+ set_ledcard(0x00100000);
+
+ return 0;
+}
+
+#define POWER_OFFSET 0xF0000
+#define SW_WATCHDOG_REASON 13
+
+#define BOOTDATA_OFFSET 0xF8000
+#define MAX_ATTEMPTS 5
+
+#define FAILSAFE_BOOT 1
+#define SYSTEM_BOOT 2
+#define SYSTEM2_BOOT 3
+
+#define WRITE_FLASH16(a, d) \
+do \
+{ \
+ *((volatile u16 *) (a)) = (d);\
+ } while(0)
+
+static void write_bootdata (volatile u16 * addr, u8 System, u8 Count)
+{
+ u16 data;
+ volatile u16 *flash = (u16 *) (CFG_FLASH_BASE);
+
+ switch(System){
+ case FAILSAFE_BOOT:
+ printf ("Setting failsafe boot in flash\n");
+ break;
+ case SYSTEM_BOOT:
+ printf ("Setting system boot in flash\n");
+ break;
+ case SYSTEM2_BOOT:
+ printf ("Setting system2 boot in flash\n");
+ break;
+ default:
+ printf ("Invalid system data %u, setting failsafe\n", System);
+ System = FAILSAFE_BOOT;
+ }
+
+ if ((Count < 1) | (Count > MAX_ATTEMPTS)) {
+ printf ("Invalid boot count %u, setting 1\n", Count);
+ Count = 1;
+ }
+
+ printf ("Boot attempt %d\n", Count);
+
+ data = (System << 8) | Count;
+ /* AMD 16 bit */
+ WRITE_FLASH16 (&flash[0x555], 0xAAAA);
+ WRITE_FLASH16 (&flash[0x2AA], 0x5555);
+ WRITE_FLASH16 (&flash[0x555], 0xA0A0);
+
+ WRITE_FLASH16 (addr, data);
+}
+
+static int random_system(void){
+ /* EEPROM read failed. Just try to choose one
+ system release and hope it works */
+
+ /* FIXME */
+ return(SYSTEM_BOOT);
+}
+
+static int switch_system(int old_system){
+ u8 Rx[10];
+ u8 Tx[5];
+ int valid_release;
+
+ if(old_system==FAILSAFE_BOOT){
+ /* Find out which system release to use */
+
+ /* Copy from nvram to scratchpad */
+ Tx[0] = RECALL_MEMORY;
+ Tx[1] = 7; /* Page */
+ if (ee_do_cpu_command (Tx, 2, NULL, 0, 1)) {
+ printf ("EE user page 7 recall failed\n");
+ return (random_system());
+ }
+
+ Tx[0] = READ_SCRATCHPAD;
+ if (ee_do_cpu_command (Tx, 2, Rx, 9, 1)) {
+ printf ("EE user page 7 read failed\n");
+ return (random_system());
+ }
+ /* Crc in 9:th byte */
+ if (!ee_crc_ok (Rx, 8, *(Rx + 8))) {
+ printf ("EE read failed, page 7. CRC error\n");
+ return (random_system());
+ }
+
+ valid_release = Rx[7];
+ if((valid_release==0xFF)|
+ ((valid_release&1) == 0)){
+ return(SYSTEM_BOOT);
+ }
+ else{
+ return(SYSTEM2_BOOT);
+ }
+ }
+ else{
+ return(FAILSAFE_BOOT);
+ }
+}
+
+static void check_boot_tries (void)
+{
+ /* Count the number of boot attemps
+ switch system if too many */
+
+ int i;
+ volatile u16 *addr;
+ volatile u16 data;
+ u8 system = FAILSAFE_BOOT;
+ u8 count;
+
+ addr = (u16 *) (CFG_FLASH_BASE + BOOTDATA_OFFSET);
+
+ if (*addr == 0xFFFF) {
+ printf ("*** No bootdata exists. ***\n");
+ write_bootdata (addr, FAILSAFE_BOOT, 1);
+ } else {
+ /* Search for latest written bootdata */
+ i = 0;
+ while ((*(addr + 1) != 0xFFFF) & (i < 8000)) {
+ addr++;
+ i++;
+ }
+ if (i >= 8000) {
+ /* Whoa, dont write any more */
+ printf ("*** No bootdata found. Not updating flash***\n");
+ } else {
+ /* See how many times we have tried to boot real system */
+ data = *addr;
+ system = data >> 8;
+ count = data & 0xFF;
+ if ((system != SYSTEM_BOOT) &
+ (system != SYSTEM2_BOOT) &
+ (system != FAILSAFE_BOOT)) {
+ printf ("*** Wrong system %d\n", system);
+ system = FAILSAFE_BOOT;
+ count = 1;
+ } else {
+ switch (count) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ /* Try same system again if needed */
+ count++;
+ break;
+
+ case 5:
+ /* Switch system and reset tries */
+ count = 1;
+ system = switch_system(system);
+ printf ("***Too many boot attempts, switching system***\n");
+ break;
+ default:
+ /* Switch system, start over and hope it works */
+ printf ("***Unexpected data on addr 0x%x, %u***\n",
+ (u32) addr, data);
+ count = 1;
+ system = switch_system(system);
+ }
+ }
+ write_bootdata (addr + 1, system, count);
+ }
+ }
+ switch(system){
+ case FAILSAFE_BOOT:
+ printf ("Booting failsafe system\n");
+ setenv ("bootargs", "panic=1 root=/dev/hda7");
+ setenv ("bootcmd", "ide reset;disk 0x81000000 0:5;run addmisc;bootm");
+ break;
+
+ case SYSTEM_BOOT:
+ printf ("Using normal system\n");
+ setenv ("bootargs", "panic=1 root=/dev/hda4");
+ setenv ("bootcmd", "ide reset;disk 0x81000000 0:2;run addmisc;bootm");
+ break;
+
+ case SYSTEM2_BOOT:
+ printf ("Using normal system2\n");
+ setenv ("bootargs", "panic=1 root=/dev/hda9");
+ setenv ("bootcmd", "ide reset;disk 0x81000000 0:8;run addmisc;bootm");
+ break;
+ default:
+ printf ("Invalid system %d\n", system);
+ printf ("Hanging\n");
+ while(1);
+ }
+}
+
+int misc_init_r(void){
+ u8 Rx[80];
+ u8 Tx[5];
+ int page;
+ int read = 0;
+
+ WATCHDOG_RESET();
+
+ if (ee_init_cpu_data ()) {
+ printf ("EEPROM init failed\n");
+ return (0);
+ }
+
+ /* Check which release to boot */
+ check_boot_tries ();
+
+ /* Read the pages where ethernet address is stored */
+
+ for (page = EE_USER_PAGE_0; page <= EE_USER_PAGE_0 + 2; page++) {
+ /* Copy from nvram to scratchpad */
+ Tx[0] = RECALL_MEMORY;
+ Tx[1] = page;
+ if (ee_do_cpu_command (Tx, 2, NULL, 0, 1)) {
+ printf ("EE user page %d recall failed\n", page);
+ return (0);
+ }
+
+ Tx[0] = READ_SCRATCHPAD;
+ if (ee_do_cpu_command (Tx, 2, Rx + read, 9, 1)) {
+ printf ("EE user page %d read failed\n", page);
+ return (0);
+ }
+ /* Crc in 9:th byte */
+ if (!ee_crc_ok (Rx + read, 8, *(Rx + read + 8))) {
+ printf ("EE read failed, page %d. CRC error\n", page);
+ return (0);
+ }
+ read += 8;
+ }
+
+ /* Add eos after eth addr */
+ Rx[17] = 0;
+
+ printf ("Ethernet addr read from eeprom: %s\n\n", Rx);
+
+ if ((Rx[2] != ':') |
+ (Rx[5] != ':') |
+ (Rx[8] != ':') | (Rx[11] != ':') | (Rx[14] != ':')) {
+ printf ("*** ethernet addr invalid, using default ***\n");
+ } else {
+ setenv ("ethaddr", Rx);
+ }
+ return (0);
+}