summaryrefslogtreecommitdiffstats
path: root/board/evb64260
diff options
context:
space:
mode:
Diffstat (limited to 'board/evb64260')
-rw-r--r--board/evb64260/64260.h31
-rw-r--r--board/evb64260/Makefile50
-rw-r--r--board/evb64260/README54
-rw-r--r--board/evb64260/README.EVB-64260-750CX7
-rw-r--r--board/evb64260/bootseq.txt94
-rw-r--r--board/evb64260/ecctest.c111
-rw-r--r--board/evb64260/eth.c808
-rw-r--r--board/evb64260/eth.h75
-rw-r--r--board/evb64260/eth_addrtbl.c218
-rw-r--r--board/evb64260/eth_addrtbl.h83
-rw-r--r--board/evb64260/evb64260.c452
-rw-r--r--board/evb64260/flash.c853
-rw-r--r--board/evb64260/i2c.c310
-rw-r--r--board/evb64260/i2c.h7
-rw-r--r--board/evb64260/intel_flash.c277
-rw-r--r--board/evb64260/intel_flash.h160
-rw-r--r--board/evb64260/local.h62
-rw-r--r--board/evb64260/memory.c457
-rw-r--r--board/evb64260/misc.S182
-rw-r--r--board/evb64260/mpsc.c854
-rw-r--r--board/evb64260/mpsc.h142
-rw-r--r--board/evb64260/pci.c760
-rw-r--r--board/evb64260/sdram_init.c666
-rw-r--r--board/evb64260/serial.c192
-rw-r--r--board/evb64260/serial.h63
-rw-r--r--board/evb64260/u-boot.lds102
-rw-r--r--board/evb64260/zuma_pbb.c220
-rw-r--r--board/evb64260/zuma_pbb.h346
-rw-r--r--board/evb64260/zuma_pbb_mbox.c208
-rw-r--r--board/evb64260/zuma_pbb_mbox.h43
30 files changed, 7887 insertions, 0 deletions
diff --git a/board/evb64260/64260.h b/board/evb64260/64260.h
new file mode 100644
index 0000000..d106ced
--- /dev/null
+++ b/board/evb64260/64260.h
@@ -0,0 +1,31 @@
+#ifndef __64260_H__
+#define __64260_H__
+
+/* CPU Configuration bits */
+#define CPU_CONF_ADDR_MISS_EN (1 << 8)
+#define CPU_CONF_AACK_DELAY (1 << 11)
+#define CPU_CONF_ENDIANESS (1 << 12)
+#define CPU_CONF_PIPELINE (1 << 13)
+#define CPU_CONF_TA_DELAY (1 << 15)
+#define CPU_CONF_RD_OOO (1 << 16)
+#define CPU_CONF_STOP_RETRY (1 << 17)
+#define CPU_CONF_MULTI_DECODE (1 << 18)
+#define CPU_CONF_DP_VALID (1 << 19)
+#define CPU_CONF_PERR_PROP (1 << 22)
+#define CPU_CONF_FAST_CLK (1 << 23)
+#define CPU_CONF_AACK_DELAY_2 (1 << 25)
+#define CPU_CONF_AP_VALID (1 << 26)
+#define CPU_CONF_REMAP_WR_DIS (1 << 27)
+#define CPU_CONF_CONF_SB_DIS (1 << 28)
+#define CPU_CONF_IO_SB_DIS (1 << 29)
+#define CPU_CONF_CLK_SYNC (1 << 30)
+
+/* CPU Master Control bits */
+#define CPU_MAST_CTL_ARB_EN (1 << 8)
+#define CPU_MAST_CTL_MASK_BR_1 (1 << 9)
+#define CPU_MAST_CTL_M_WR_TRIG (1 << 10)
+#define CPU_MAST_CTL_M_RD_TRIG (1 << 11)
+#define CPU_MAST_CTL_CLEAN_BLK (1 << 12)
+#define CPU_MAST_CTL_FLUSH_BLK (1 << 13)
+
+#endif /* __64260_H__ */
diff --git a/board/evb64260/Makefile b/board/evb64260/Makefile
new file mode 100644
index 0000000..d72465e
--- /dev/null
+++ b/board/evb64260/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2001
+# Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).o
+
+SOBJS = misc.o
+COBJS = $(BOARD).o flash.o serial.o memory.o pci.o \
+ eth.o eth_addrtbl.o mpsc.o i2c.o \
+ sdram_init.o zuma_pbb.o intel_flash.o zuma_pbb_mbox.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/evb64260/README b/board/evb64260/README
new file mode 100644
index 0000000..74211de
--- /dev/null
+++ b/board/evb64260/README
@@ -0,0 +1,54 @@
+This file contains status information for the port of U-Boot to the
+Galileo Evaluation Board.
+
+Author: Josh Huber <huber@mclx.com>
+ Mission Critical Linux, Inc.
+
+The support for the Galileo Evaluation board is fairly minimal now.
+It's sufficient to boot Linux, but doesn't provide too much more than
+what's required to do this.
+
+Both DUART channels are supported (to use the second one, you have to
+modify the board -- see the schematics for where to solder on the
+devices module). The ethernet ports are supported, and the MPSC is
+supported as a console driver. (keep in mind that the kernel has no
+support for this yet)
+
+There are still occaisonal lockups with the MPSC console driver due to
+(we think!) overrun problems. If you're looking for something stable
+to use for Linux development, consider sticking with the DUART console
+for now.
+
+Automatic memory sizing mostly works. We've had problems with some
+combinations of memory. Please send us email if you're having trouble
+with respect to the memory detection.
+
+Right now, only the 512k boot flash is supported. Support for the
+16MB flash on the devices module is forthcoming. Right now the flash
+is stored at the 256k boundry in flash, wasting a whole sector (64k!)
+for environment data. This isn't really a big deal since we're not
+using the 512k for anything else. (Just U-Boot and the environment)
+
+Finally, here is a sample output session:
+
+U-Boot 1.0.0-pre1 (Jun 6 2001 - 12:45:11)
+
+Initializing...
+ CPU: MPC7400 (altivec enabled) v2.9
+ Board: EVB64260
+ DRAM: 256 MB
+ FLASH: 512 kB
+ In: serial
+ Out: serial
+ Err: serial
+
+=>
+
+The default configuration should be correct for the evaluation board,
+as it's shipped from Galileo. Keep in mind that the default baudrate
+is set to 38400, 8N1.
+
+Good luck, and make sure to send any bugreports to us (or the
+u-boot-users list).
+
+Josh
diff --git a/board/evb64260/README.EVB-64260-750CX b/board/evb64260/README.EVB-64260-750CX
new file mode 100644
index 0000000..5ea38ea
--- /dev/null
+++ b/board/evb64260/README.EVB-64260-750CX
@@ -0,0 +1,7 @@
+The EVB-64260-750CX is quite similar to the EVB-64260-BP already
+supported except the following differences:
+* It has an IBM-750CXe soldiered on board instead of the slot-1 in the
+ BP.
+* It has a single PCI male connector instead of the 4 PCI female
+ connectors on the BP. It also gets power trough the PCI connector.
+* It has only a single DIMM slot instead of the 2 slots in the BP.
diff --git a/board/evb64260/bootseq.txt b/board/evb64260/bootseq.txt
new file mode 100644
index 0000000..6cae9ea
--- /dev/null
+++ b/board/evb64260/bootseq.txt
@@ -0,0 +1,94 @@
+(cpu/mpc7xxx/start.S)
+
+start:
+ b boot_cold
+
+start_warm:
+ b boot_warm
+
+
+boot_cold:
+boot_warm:
+ clear bats
+ init l2 (if enabled)
+ init altivec (if enabled)
+ invalidate l2 (if enabled)
+ setup bats (from defines in config_EVB)
+ enable_addr_trans: (if MMU enabled)
+ enable MSR_IR and MSR_DR
+ jump to in_flash
+
+in_flash:
+ enable l1 dcache
+ gal_low_init: (board/evb64260/sdram_init.S)
+ config SDRAM (CFG, TIMING, DECODE)
+ init scratch regs (810 + 814)
+
+ detect DIMM0 (bank 0 only)
+ config SDRAM_PARA0 to 256/512Mbit
+ bl sdram_op_mode
+ detect bank0 width
+ write scratch reg 810
+ config SDRAM_PARA0 with results
+ config SDRAM_PARA1 with results
+
+ detect DIMM1 (bank 2 only)
+ config SDRAM_PARA2 to 256/512Mbit
+ detect bank2 width
+ write scratch reg 814
+ config SDRAM_PARA2 with results
+ config SDRAM_PARA3 with results
+
+ setup device bus timings/width
+ setup boot device timings/width
+
+ setup CPU_CONF (0x0)
+ setup cpu master control register 0x160
+ setup PCI0 TIMEOUT
+ setup PCI1 TIMEOUT
+ setup PCI0 BAR
+ setup PCI1 BAR
+
+ setup MPP control 0-3
+ setup GPP level control
+ setup Serial ports multiplex
+
+ setup stack pointer (r1)
+ setup GOT
+ call cpu_init_f
+ debug leds
+ board_init_f: (common/board.c)
+ board_early_init_f:
+ remap gt regs?
+ map PCI mem/io
+ map device space
+ clear out interrupts
+ init_timebase
+ env_init
+ serial_init
+ console_init_f
+ display_options
+ initdram: (board/evb64260/evb64260.c)
+ detect memory
+ for each bank:
+ dram_size()
+ setup PCI slave memory mappings
+ setup SCS
+ setup monitor
+ alloc board info struct
+ init bd struct
+ relocate_code: (cpu/mpc7xxx/start.S)
+ copy,got,clearbss
+ board_init_r(bd, dest_addr) (common/board.c)
+ setup bd function pointers
+ trap_init
+ flash_init: (board/evb64260/flash.c)
+ setup bd flash info
+ cpu_init_r: (cpu/mpc7xxx/cpu_init.c)
+ nothing
+ mem_malloc_init
+ malloc_bin_reloc
+ spi_init (r or f)??? (CONFIG_ENV_IS_IN_EEPROM)
+ env_relocated
+ misc_init_r(bd): (board/evb64260/evb64260.c)
+ mpsc_init2
diff --git a/board/evb64260/ecctest.c b/board/evb64260/ecctest.c
new file mode 100644
index 0000000..5d3679a
--- /dev/null
+++ b/board/evb64260/ecctest.c
@@ -0,0 +1,111 @@
+indent: Standard input:27: Warning:old style assignment ambiguity in "=*". Assuming "= *"
+
+#ifdef ECC_TEST
+static inline void ecc_off (void)
+{
+ *(volatile int *) (INTERNAL_REG_BASE_ADDR + 0x4b4) &= ~0x00200000;
+}
+
+static inline void ecc_on (void)
+{
+ *(volatile int *) (INTERNAL_REG_BASE_ADDR + 0x4b4) |= 0x00200000;
+}
+
+static int putshex (const char *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ printf ("%02x", buf[i]);
+ }
+ return 0;
+}
+
+static int char_memcpy (void *d, const void *s, int len)
+{
+ int i;
+ char *cd = d;
+ const char *cs = s;
+
+ for (i = 0; i < len; i++) {
+ *(cd++) = *(cs++);
+ }
+ return 0;
+}
+
+static int memory_test (char *buf)
+{
+ const char src[][16] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02},
+ {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04},
+ {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08},
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20},
+ {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40},
+ {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80},
+ {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55},
+ {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa},
+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ };
+ const int foo[] = { 0 };
+ int i, j, a;
+
+ printf ("\ntest @ %d %p\n", foo[0], buf);
+ for (i = 0; i < 12; i++) {
+ for (a = 0; a < 8; a++) {
+ const char *s = src[i] + a;
+ int align = (unsigned) (s) & 0x7;
+
+ /* ecc_off(); */
+ memcpy (buf, s, 8);
+ /* ecc_on(); */
+ putshex (s, 8);
+ if (memcmp (buf, s, 8)) {
+ putc ('\n');
+ putshex (buf, 8);
+ printf (" [FAIL] (%p) align=%d\n", s, align);
+ for (j = 0; j < 8; j++) {
+ s[j] == buf[j] ? puts (" ") :
+ printf ("%02x",
+ (s[j]) ^ (buf[j]));
+ }
+ putc ('\n');
+ } else {
+ printf (" [PASS] (%p) align=%d\n", s, align);
+ }
+ /* ecc_off(); */
+ char_memcpy (buf, s, 8);
+ /* ecc_on(); */
+ putshex (s, 8);
+ if (memcmp (buf, s, 8)) {
+ putc ('\n');
+ putshex (buf, 8);
+ printf (" [FAIL] (%p) align=%d\n", s, align);
+ for (j = 0; j < 8; j++) {
+ s[j] == buf[j] ? puts (" ") :
+ printf ("%02x",
+ (s[j]) ^ (buf[j]));
+ }
+ putc ('\n');
+ } else {
+ printf (" [PASS] (%p) align=%d\n", s, align);
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
diff --git a/board/evb64260/eth.c b/board/evb64260/eth.c
new file mode 100644
index 0000000..a3a3276
--- /dev/null
+++ b/board/evb64260/eth.c
@@ -0,0 +1,808 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Skeleton NIC driver for Etherboot
+***************************************************************************/
+
+/*
+ * 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, or (at
+ * your option) any later version.
+ */
+
+/*
+ * This file is a modified version from the Galileo polled mode
+ * network driver for the ethernet contained within the GT64260
+ * chip. It has been modified to fit into the U-Boot framework, from
+ * the original (etherboot) setup. Also, additional cleanup and features
+ * were added.
+ *
+ * - Josh Huber <huber@mclx.com>
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <galileo/gt64260R.h>
+#include <galileo/core.h>
+#include <asm/cache.h>
+#include <miiphy.h>
+#include <net.h>
+#include <netdev.h>
+
+#include "eth.h"
+#include "eth_addrtbl.h"
+
+#if defined(CONFIG_CMD_NET)
+
+#define GT6426x_ETH_BUF_SIZE 1536
+
+/* if you like verbose output, turn this on! */
+#undef DEBUG
+
+/* Restart autoneg if we detect link is up on phy init. */
+
+/*
+ * The GT doc's say that after Rst is deasserted, and the PHY
+ * reports autoneg complete, it runs through its autoneg
+ * procedures. This doesn't seem to be the case for MII
+ * PHY's. To work around this check for link up && autoneg
+ * complete when initilizing the port. If they are both set,
+ * then restart PHY autoneg. Of course, it may be something
+ * completly different.
+ */
+#ifdef CONFIG_ETHER_PORT_MII
+# define RESTART_AUTONEG
+#endif
+
+/* do this if you dont want to use snooping */
+#define USE_SOFTWARE_CACHE_MANAGEMENT
+
+#ifdef USE_SOFTWARE_CACHE_MANAGEMENT
+#define FLUSH_DCACHE(a,b) if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));}
+#define FLUSH_AND_INVALIDATE_DCACHE(a,b) if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));}
+#define INVALIDATE_DCACHE(a,b) if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));}
+#else
+/* bummer - w/o flush, nothing works, even with snooping - FIXME */
+/* #define FLUSH_DCACHE(a,b) */
+#define FLUSH_DCACHE(a,b) if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));}
+#define FLUSH_AND_INVALIDATE_DCACHE(a,b)
+#define INVALIDATE_DCACHE(a,b)
+#endif
+struct eth_dev_s {
+ eth0_tx_desc_single *eth_tx_desc;
+ eth0_rx_desc_single *eth_rx_desc;
+ char *eth_tx_buffer;
+ char *eth_rx_buffer[NR];
+ int tdn, rdn;
+ int dev;
+ unsigned int reg_base;
+};
+
+
+#ifdef CONFIG_INTEL_LXT97X
+/* for intel LXT972 */
+static const char ether_port_phy_addr[3]={0,1,2};
+#else
+static const char ether_port_phy_addr[3]={4,5,6};
+#endif
+
+/* MII PHY access routines are common for all i/f, use gal_ent0 */
+#define GT6426x_MII_DEVNAME "gal_enet0"
+
+int gt6426x_miiphy_read(const char *devname, unsigned char phy,
+ unsigned char reg, unsigned short *val);
+
+static inline unsigned short
+miiphy_read_ret(unsigned short phy, unsigned short reg)
+{
+ unsigned short val;
+ gt6426x_miiphy_read(GT6426x_MII_DEVNAME,phy,reg,&val);
+ return val;
+}
+
+
+/**************************************************************************
+RESET - Reset adapter
+***************************************************************************/
+void
+gt6426x_eth_reset(void *v)
+{
+ /* we should do something here...
+ struct eth_device *wp = (struct eth_device *)v;
+ struct eth_dev_s *p = wp->priv;
+ */
+
+ printf ("RESET\n");
+ /* put the card in its initial state */
+}
+
+static void gt6426x_handle_SMI(struct eth_dev_s *p, unsigned int icr)
+{
+#ifdef DEBUG
+ printf("SMI interrupt: ");
+
+ if(icr&0x20000000) {
+ printf("SMI done\n");
+ }
+#endif
+
+ if(icr&0x10000000) {
+#ifdef DEBUG
+ unsigned int psr;
+
+ psr=GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + p->reg_base);
+ printf("PHY state change:\n"
+ " GT:%s:%s:%s:%s\n",
+ psr & 1 ? "100" : " 10",
+ psr & 8 ? " Link" : "nLink",
+ psr & 2 ? "FD" : "HD",
+ psr & 4 ? " FC" : "nFC");
+
+#ifdef CONFIG_INTEL_LXT97X /* non-standard mii reg (intel lxt972a) */
+ {
+ unsigned short mii_11;
+ mii_11 = miiphy_read_ret(ether_port_phy_addr[p->dev], 0x11);
+
+ printf(" mii:%s:%s:%s:%s %s:%s %s\n",
+ mii_11 & (1 << 14) ? "100" : " 10",
+ mii_11 & (1 << 10) ? " Link" : "nLink",
+ mii_11 & (1 << 9) ? "FD" : "HD",
+ mii_11 & (1 << 4) ? " FC" : "nFC",
+
+ mii_11 & (1 << 7) ? "ANc" : "ANnc",
+ mii_11 & (1 << 8) ? "AN" : "Manual",
+ ""
+ );
+ }
+#endif /* CONFIG_INTEL_LXT97X */
+#endif /* DEBUG */
+ }
+}
+
+static int
+gt6426x_eth_receive(struct eth_dev_s *p,unsigned int icr)
+{
+ int eth_len=0;
+ char *eth_data;
+
+ eth0_rx_desc_single *rx = &p->eth_rx_desc[(p->rdn)];
+
+ INVALIDATE_DCACHE((unsigned int)rx,(unsigned int)(rx+1));
+
+ if (rx->command_status & 0x80000000) {
+ return 0; /* No packet received */
+ }
+
+ eth_len = (unsigned int)
+ (rx->buff_size_byte_count) & 0x0000ffff;
+ eth_data = (char *) p->eth_rx_buffer[p->rdn];
+
+#ifdef DEBUG
+ if (eth_len) {
+ printf ("%s: Recived %d byte Packet @ 0x%p\n",
+ __FUNCTION__, eth_len, eth_data);
+ }
+#endif
+ /*
+ * packet is now in:
+ * eth0_rx_buffer[RDN_ETH0];
+ */
+
+ /* let the upper layer handle the packet */
+ NetReceive ((uchar *)eth_data, eth_len);
+
+ rx->buff_size_byte_count = GT6426x_ETH_BUF_SIZE<<16;
+
+
+ /* GT96100 Owner */
+ rx->command_status = 0x80000000;
+
+ FLUSH_DCACHE((unsigned int)rx,(unsigned int)(rx+1));
+
+ p->rdn ++;
+ if (p->rdn == NR) {p->rdn = 0;}
+
+ sync();
+
+ /* Start Rx*/
+ GT_REG_WRITE (ETHERNET0_SDMA_COMMAND_REGISTER + p->reg_base, 0x00000080);
+
+#ifdef DEBUG
+ {
+ int i;
+ for (i=0;i<12;i++) {
+ printf(" %02x", eth_data[i]);
+ }
+ }
+ printf(": %d bytes\n", eth_len);
+#endif
+ INVALIDATE_DCACHE((unsigned int)eth_data,
+ (unsigned int)eth_data+eth_len);
+ return eth_len;
+}
+
+/**************************************************************************
+POLL - look for an rx frame, handle other conditions
+***************************************************************************/
+int
+gt6426x_eth_poll(void *v)
+{
+ struct eth_device *wp = (struct eth_device *)v;
+ struct eth_dev_s *p = wp->priv;
+ unsigned int icr=GTREGREAD(ETHERNET0_INTERRUPT_CAUSE_REGISTER + p->reg_base);
+
+ if(icr) {
+ GT_REG_WRITE(ETHERNET0_INTERRUPT_CAUSE_REGISTER +p->reg_base, 0);
+#ifdef DEBUG
+ printf("poll got ICR %08x\n", icr);
+#endif
+ /* SMI done or PHY state change*/
+ if(icr&0x30000000) gt6426x_handle_SMI(p, icr);
+ }
+ /* always process. We aren't using RX interrupts */
+ return gt6426x_eth_receive(p, icr);
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+int gt6426x_eth_transmit(void *v, char *p, unsigned int s)
+{
+ struct eth_device *wp = (struct eth_device *)v;
+ struct eth_dev_s *dev = (struct eth_dev_s *)wp->priv;
+#ifdef DEBUG
+ unsigned int old_command_stat,old_psr;
+#endif
+ eth0_tx_desc_single *tx = &dev->eth_tx_desc[dev->tdn];
+
+ /* wait for tx to be ready */
+ INVALIDATE_DCACHE((unsigned int)tx,(unsigned int)(tx+1));
+ while (tx->command_status & 0x80000000) {
+ int i;
+ for(i=0;i<1000;i++);
+ INVALIDATE_DCACHE((unsigned int)tx,(unsigned int)(tx+1));
+ }
+
+ GT_REG_WRITE (ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0 + dev->reg_base,
+ (unsigned int)tx);
+
+#ifdef DEBUG
+ printf("copying to tx_buffer [%p], length %x, desc = %p\n",
+ dev->eth_tx_buffer, s, dev->eth_tx_desc);
+#endif
+ memcpy(dev->eth_tx_buffer, (char *) p, s);
+
+ tx->buff_pointer = (uchar *)dev->eth_tx_buffer;
+ tx->bytecount_reserved = ((__u16)s) << 16;
+
+ /* 31 - own
+ * 22 - gencrc
+ * 18:16 - pad, last, first */
+ tx->command_status = (1<<31) | (1<<22) | (7<<16);
+#if 0
+ /* FEr #18 */
+ tx->next_desc = NULL;
+#else
+ tx->next_desc =
+ (struct eth0_tx_desc_struct *)
+ &dev->eth_tx_desc[(dev->tdn+1)%NT].bytecount_reserved;
+
+ /* cpu owned */
+ dev->eth_tx_desc[(dev->tdn+1)%NT].command_status = (7<<16); /* pad, last, first */
+#endif
+
+#ifdef DEBUG
+ old_command_stat=tx->command_status,
+ old_psr=GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + dev->reg_base);
+#endif
+
+ FLUSH_DCACHE((unsigned int)tx,
+ (unsigned int)&dev->eth_tx_desc[(dev->tdn+2)%NT]);
+
+ FLUSH_DCACHE((unsigned int)dev->eth_tx_buffer,(unsigned int)dev->eth_tx_buffer+s);
+
+ GT_REG_WRITE(ETHERNET0_SDMA_COMMAND_REGISTER + dev->reg_base, 0x01000000);
+
+#ifdef DEBUG
+ {
+ unsigned int command_stat=0;
+ printf("cmd_stat: %08x PSR: %08x\n", old_command_stat, old_psr);
+ /* wait for tx to be ready */
+ do {
+ unsigned int psr=GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + dev->reg_base);
+ command_stat=tx->command_status;
+ if(command_stat!=old_command_stat || psr !=old_psr) {
+ printf("cmd_stat: %08x PSR: %08x\n", command_stat, psr);
+ old_command_stat = command_stat;
+ old_psr = psr;
+ }
+ /* gt6426x_eth0_poll(); */
+ } while (command_stat & 0x80000000);
+
+ printf("sent %d byte frame\n", s);
+
+ if((command_stat & (3<<15)) == 3) {
+ printf("frame had error (stat=%08x)\n", command_stat);
+ }
+ }
+#endif
+ return 0;
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+void
+gt6426x_eth_disable(void *v)
+{
+ struct eth_device *wp = (struct eth_device *)v;
+ struct eth_dev_s *p = (struct eth_dev_s *)wp->priv;
+
+ GT_REG_WRITE(ETHERNET0_SDMA_COMMAND_REGISTER + p->reg_base, 0x80008000);
+}
+
+/**************************************************************************
+MII utilities - write: write to an MII register via SMI
+***************************************************************************/
+int
+gt6426x_miiphy_write(const char *devname, unsigned char phy,
+ unsigned char reg, unsigned short data)
+{
+ unsigned int temp= (reg<<21) | (phy<<16) | data;
+
+ while(GTREGREAD(ETHERNET_SMI_REGISTER) & (1<<28)); /* wait for !Busy */
+
+ GT_REG_WRITE(ETHERNET_SMI_REGISTER, temp);
+ return 0;
+}
+
+/**************************************************************************
+MII utilities - read: read from an MII register via SMI
+***************************************************************************/
+int
+gt6426x_miiphy_read(const char *devname, unsigned char phy,
+ unsigned char reg, unsigned short *val)
+{
+ unsigned int temp= (reg<<21) | (phy<<16) | 1<<26;
+
+ while(GTREGREAD(ETHERNET_SMI_REGISTER) & (1<<28)); /* wait for !Busy */
+
+ GT_REG_WRITE(ETHERNET_SMI_REGISTER, temp);
+
+ while(1) {
+ temp=GTREGREAD(ETHERNET_SMI_REGISTER);
+ if(temp & (1<<27)) break; /* wait for ReadValid */
+ }
+ *val = temp & 0xffff;
+
+ return 0;
+}
+
+#ifdef DEBUG
+/**************************************************************************
+MII utilities - dump mii registers
+***************************************************************************/
+static void
+gt6426x_dump_mii(bd_t *bis, unsigned short phy)
+{
+ printf("mii reg 0 - 3: %04x %04x %04x %04x\n",
+ miiphy_read_ret(phy, 0x0),
+ miiphy_read_ret(phy, 0x1),
+ miiphy_read_ret(phy, 0x2),
+ miiphy_read_ret(phy, 0x3)
+ );
+ printf(" 4 - 7: %04x %04x %04x %04x\n",
+ miiphy_read_ret(phy, 0x4),
+ miiphy_read_ret(phy, 0x5),
+ miiphy_read_ret(phy, 0x6),
+ miiphy_read_ret(phy, 0x7)
+ );
+ printf(" 8: %04x\n",
+ miiphy_read_ret(phy, 0x8)
+ );
+ printf(" 16-19: %04x %04x %04x %04x\n",
+ miiphy_read_ret(phy, 0x10),
+ miiphy_read_ret(phy, 0x11),
+ miiphy_read_ret(phy, 0x12),
+ miiphy_read_ret(phy, 0x13)
+ );
+ printf(" 20,30: %04x %04x\n",
+ miiphy_read_ret(phy, 20),
+ miiphy_read_ret(phy, 30)
+ );
+}
+#endif
+
+#ifdef RESTART_AUTONEG
+
+/* If link is up && autoneg compleate, and if
+ * GT and PHY disagree about link capabilitys,
+ * restart autoneg - something screwy with FD/HD
+ * unless we do this. */
+static void
+check_phy_state(struct eth_dev_s *p)
+{
+ int bmsr = miiphy_read_ret(ether_port_phy_addr[p->dev], MII_BMSR);
+ int psr = GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + p->reg_base);
+
+ if ((psr & 1<<3) && (bmsr & BMSR_LSTATUS)) {
+ int nego = miiphy_read_ret(ether_port_phy_addr[p->dev], MII_ADVERTISE) &
+ miiphy_read_ret(ether_port_phy_addr[p->dev], MII_LPA);
+ int want;
+
+ if (nego & LPA_100FULL) {
+ want = 0x3;
+ printf("MII: 100Base-TX, Full Duplex\n");
+ } else if (nego & LPA_100HALF) {
+ want = 0x1;
+ printf("MII: 100Base-TX, Half Duplex\n");
+ } else if (nego & LPA_10FULL) {
+ want = 0x2;
+ printf("MII: 10Base-T, Full Duplex\n");
+ } else if (nego & LPA_10HALF) {
+ want = 0x0;
+ printf("MII: 10Base-T, Half Duplex\n");
+ } else {
+ printf("MII: Unknown link-foo! %x\n", nego);
+ return;
+ }
+
+ if ((psr & 0x3) != want) {
+ printf("MII: GT thinks %x, PHY thinks %x, restarting autoneg..\n",
+ psr & 0x3, want);
+ miiphy_write(GT6426x_MII_DEVNAME,ether_port_phy_addr[p->dev],0,
+ miiphy_read_ret(ether_port_phy_addr[p->dev],0) | (1<<9));
+ udelay(10000); /* the EVB's GT takes a while to notice phy
+ went down and up */
+ }
+ }
+}
+#endif
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+int
+gt6426x_eth_probe(void *v, bd_t *bis)
+{
+ struct eth_device *wp = (struct eth_device *)v;
+ struct eth_dev_s *p = (struct eth_dev_s *)wp->priv;
+ int dev = p->dev;
+ unsigned int reg_base = p->reg_base;
+ unsigned long temp;
+ int i;
+
+ if (( dev < 0 ) || ( dev >= GAL_ETH_DEVS ))
+ { /* This should never happen */
+ printf("%s: Invalid device %d\n", __FUNCTION__, dev );
+ return 0;
+ }
+
+#ifdef DEBUG
+ printf ("%s: initializing %s\n", __FUNCTION__, wp->name );
+ printf ("\nCOMM_CONTROL = %08x , COMM_CONF = %08x\n",
+ GTREGREAD(COMM_UNIT_ARBITER_CONTROL),
+ GTREGREAD(COMM_UNIT_ARBITER_CONFIGURATION_REGISTER));
+#endif
+
+ /* clear MIB counters */
+ for(i=0;i<255; i++)
+ temp=GTREGREAD(ETHERNET0_MIB_COUNTER_BASE + reg_base +i);
+
+#ifdef CONFIG_INTEL_LXT97X
+ /* for intel LXT972 */
+
+ /* led 1: 0x1=txact
+ led 2: 0xc=link/rxact
+ led 3: 0x2=rxact (N/C)
+ strch: 0,2=30 ms, enable */
+ miiphy_write(GT6426x_MII_DEVNAME,ether_port_phy_addr[p->dev], 20, 0x1c22);
+
+ /* 2.7ns port rise time */
+ /*miiphy_write(ether_port_phy_addr[p->dev], 30, 0x0<<10); */
+#else
+ /* already set up in mpsc.c */
+ /*GT_REG_WRITE(MAIN_ROUTING_REGISTER, 0x7ffe38); / b400 */
+
+ /* already set up in sdram_init.S... */
+ /* MPSC0, MPSC1, RMII */
+ /*GT_REG_WRITE(SERIAL_PORT_MULTIPLEX, 0x1102); / f010 */
+#endif
+ GT_REG_WRITE(ETHERNET_PHY_ADDRESS_REGISTER,
+ ether_port_phy_addr[0] |
+ (ether_port_phy_addr[1]<<5) |
+ (ether_port_phy_addr[2]<<10)); /* 2000 */
+
+ /* 13:12 - 10: 4x64bit burst (cache line size = 32 bytes)
+ * 9 - 1: RIFB - interrupt on frame boundaries only
+ * 6:7 - 00: big endian rx and tx
+ * 5:2 - 1111: 15 retries */
+ GT_REG_WRITE(ETHERNET0_SDMA_CONFIGURATION_REGISTER + reg_base,
+ (2<<12) | (1<<9) | (0xf<<2) ); /* 2440 */
+
+#ifndef USE_SOFTWARE_CACHE_MANAGEMENT
+ /* enable rx/tx desc/buffer cache snoop */
+ GT_REG_READ(ETHERNET_0_ADDRESS_CONTROL_LOW + dev*0x20,
+ &temp); /* f200 */
+ temp|= (1<<6)| (1<<14)| (1<<22)| (1<<30);
+ GT_REG_WRITE(ETHERNET_0_ADDRESS_CONTROL_LOW + dev*0x20,
+ temp);
+#endif
+
+ /* 31 28 27 24 23 20 19 16
+ * 0000 0000 0000 0000 [0004]
+ * 15 12 11 8 7 4 3 0
+ * 1000 1101 0000 0000 [4d00]
+ * 20 - 0=MII 1=RMII
+ * 19 - 0=speed autoneg
+ * 15:14 - framesize 1536 (GT6426x_ETH_BUF_SIZE)
+ * 11 - no force link pass
+ * 10 - 1=disable fctl autoneg
+ * 8 - override prio ?? */
+ temp = 0x00004d00;
+#ifndef CONFIG_ETHER_PORT_MII
+ temp |= (1<<20); /* RMII */
+#endif
+ /* set En */
+ GT_REG_WRITE(ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER + reg_base,
+ temp); /* 2408 */
+
+ /* hardcode E1 also? */
+ /* -- according to dox, this is safer due to extra pulldowns? */
+ if (dev<2) {
+ GT_REG_WRITE(ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER + (dev+1) * 0x400,
+ temp); /* 2408 */
+ }
+
+ /* wake up MAC */ /* 2400 */
+ GT_REG_READ(ETHERNET0_PORT_CONFIGURATION_REGISTER + reg_base, &temp);
+ temp |= (1<<7); /* enable port */
+#ifdef CONFIG_GT_USE_MAC_HASH_TABLE
+ temp |= (1<<12); /* hash size 1/2k */
+#else
+ temp |= 1; /* promisc */
+#endif
+ GT_REG_WRITE(ETHERNET0_PORT_CONFIGURATION_REGISTER + reg_base, temp);
+ /* 2400 */
+
+#ifdef RESTART_AUTONEG
+ check_phy_state(p);
+#endif
+
+ printf("%s: Waiting for link up..\n", wp->name);
+ temp = 10 * 1000;
+ /* wait for link back up */
+ while(!(GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + reg_base) & 8)
+ && (--temp > 0)){
+ udelay(1000); /* wait 1 ms */
+ }
+ if ( temp == 0) {
+ printf("%s: Failed!\n", wp->name);
+ return (0);
+ }
+
+ printf("%s: OK!\n", wp->name);
+
+ p->tdn = 0;
+ p->rdn = 0;
+ p->eth_tx_desc[p->tdn].command_status = 0;
+
+ /* Initialize Rx Side */
+ for (temp = 0; temp < NR; temp++) {
+ p->eth_rx_desc[temp].buff_pointer = (uchar *)p->eth_rx_buffer[temp];
+ p->eth_rx_desc[temp].buff_size_byte_count = GT6426x_ETH_BUF_SIZE<<16;
+
+ /* GT96100 Owner */
+ p->eth_rx_desc[temp].command_status = 0x80000000;
+ p->eth_rx_desc[temp].next_desc =
+ (struct eth0_rx_desc_struct *)
+ &p->eth_rx_desc[(temp+1)%NR].buff_size_byte_count;
+ }
+
+ FLUSH_DCACHE((unsigned int)&p->eth_tx_desc[0],
+ (unsigned int)&p->eth_tx_desc[NR]);
+ FLUSH_DCACHE((unsigned int)&p->eth_rx_desc[0],
+ (unsigned int)&p->eth_rx_desc[NR]);
+
+ GT_REG_WRITE(ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0 + reg_base,
+ (unsigned int) p->eth_tx_desc);
+ GT_REG_WRITE(ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0 + reg_base,
+ (unsigned int) p->eth_rx_desc);
+ GT_REG_WRITE(ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0 + reg_base,
+ (unsigned int) p->eth_rx_desc);
+
+#ifdef DEBUG
+ printf ("\nRx descriptor pointer is %08x %08x\n",
+ GTREGREAD(ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0 + reg_base),
+ GTREGREAD(ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0 + reg_base));
+ printf ("\n\n%08x %08x\n",
+ (unsigned int)p->eth_rx_desc,p->eth_rx_desc[0].command_status);
+
+ printf ("Descriptor dump:\n");
+ printf ("cmd status: %08x\n",p->eth_rx_desc[0].command_status);
+ printf ("byte_count: %08x\n",p->eth_rx_desc[0].buff_size_byte_count);
+ printf ("buff_ptr: %08x\n",(unsigned int)p->eth_rx_desc[0].buff_pointer);
+ printf ("next_desc: %08x\n\n",(unsigned int)p->eth_rx_desc[0].next_desc);
+ printf ("%08x\n",*(unsigned int *) ((unsigned int)p->eth_rx_desc + 0x0));
+ printf ("%08x\n",*(unsigned int *) ((unsigned int)p->eth_rx_desc + 0x4));
+ printf ("%08x\n",*(unsigned int *) ((unsigned int)p->eth_rx_desc + 0x8));
+ printf ("%08x\n\n",
+ *(unsigned int *) ((unsigned int)p->eth_rx_desc + 0xc));
+#endif
+
+#ifdef DEBUG
+ gt6426x_dump_mii(bis,ether_port_phy_addr[p->dev]);
+#endif
+
+#ifdef CONFIG_GT_USE_MAC_HASH_TABLE
+ {
+ unsigned int hashtable_base;
+ u8 *b = (u8 *)(wp->enetaddr);
+ u32 macH, macL;
+
+ /* twist the MAC up into the way the discovery wants it */
+ macH= (b[0]<<8) | b[1];
+ macL= (b[2]<<24) | (b[3]<<16) | (b[4]<<8) | b[5];
+
+ /* mode 0, size 0x800 */
+ hashtable_base =initAddressTable(dev,0,1);
+
+ if(!hashtable_base) {
+ printf("initAddressTable failed\n");
+ return 0;
+ }
+
+ addAddressTableEntry(dev, macH, macL, 1, 0);
+ GT_REG_WRITE(ETHERNET0_HASH_TABLE_POINTER_REGISTER + reg_base,
+ hashtable_base);
+ }
+#endif
+
+ /* Start Rx*/
+ GT_REG_WRITE(ETHERNET0_SDMA_COMMAND_REGISTER + reg_base, 0x00000080);
+ printf("%s: gt6426x eth device %d init success \n", wp->name, dev );
+ return 1;
+}
+
+/* enter all the galileo ethernet devs into MULTI-BOOT */
+void
+gt6426x_eth_initialize(bd_t *bis)
+{
+ struct eth_device *dev;
+ struct eth_dev_s *p;
+ int devnum, x, temp;
+ char *s, *e, buf[64];
+
+#ifdef DEBUG
+ printf( "\n%s\n", __FUNCTION );
+#endif
+
+ for (devnum = 0; devnum < GAL_ETH_DEVS; devnum++) {
+ dev = calloc(sizeof(*dev), 1);
+ if (!dev) {
+ printf( "%s: gal_enet%d allocation failure, %s\n",
+ __FUNCTION__, devnum, "eth_device structure");
+ return;
+ }
+
+ /* must be less than sizeof(dev->name) */
+ sprintf(dev->name, "gal_enet%d", devnum);
+
+#ifdef DEBUG
+ printf( "Initializing %s\n", dev->name );
+#endif
+
+ /* Extract the MAC address from the environment */
+ switch (devnum)
+ {
+ case 0: s = "ethaddr"; break;
+#if (GAL_ETH_DEVS > 1)
+ case 1: s = "eth1addr"; break;
+#endif
+#if (GAL_ETH_DEVS > 2)
+ case 2: s = "eth2addr"; break;
+#endif
+ default: /* this should never happen */
+ printf( "%s: Invalid device number %d\n",
+ __FUNCTION__, devnum );
+ return;
+ }
+
+ temp = getenv_f(s, buf, sizeof(buf));
+ s = (temp > 0) ? buf : NULL;
+
+#ifdef DEBUG
+ printf ("Setting MAC %d to %s\n", devnum, s );
+#endif
+ for (x = 0; x < 6; ++x) {
+ dev->enetaddr[x] = s ? simple_strtoul(s, &e, 16) : 0;
+ if (s)
+ s = (*e) ? e+1 : e;
+ }
+
+ dev->init = (void*)gt6426x_eth_probe;
+ dev->halt = (void*)gt6426x_eth_reset;
+ dev->send = (void*)gt6426x_eth_transmit;
+ dev->recv = (void*)gt6426x_eth_poll;
+
+ p = calloc( sizeof(*p), 1 );
+ dev->priv = (void*)p;
+ if (!p)
+ {
+ printf( "%s: %s allocation failure, %s\n",
+ __FUNCTION__, dev->name, "Private Device Structure");
+ free(dev);
+ return;
+ }
+
+ p->dev = devnum;
+ p->tdn=0;
+ p->rdn=0;
+ p->reg_base = devnum * ETHERNET_PORTS_DIFFERENCE_OFFSETS;
+
+ p->eth_tx_desc =
+ (eth0_tx_desc_single *)
+ (((unsigned int) malloc(sizeof (eth0_tx_desc_single) *
+ (NT+1)) & 0xfffffff0) + 0x10);
+ if (!p)
+ {
+ printf( "%s: %s allocation failure, %s\n",
+ __FUNCTION__, dev->name, "Tx Descriptor");
+ free(dev);
+ return;
+ }
+
+ p->eth_rx_desc =
+ (eth0_rx_desc_single *)
+ (((unsigned int) malloc(sizeof (eth0_rx_desc_single) *
+ (NR+1)) & 0xfffffff0) + 0x10);
+ if (!p->eth_rx_desc)
+ {
+ printf( "%s: %s allocation failure, %s\n",
+ __FUNCTION__, dev->name, "Rx Descriptor");
+ free(dev);
+ free(p);
+ return;
+ }
+
+ p->eth_tx_buffer =
+ (char *) (((unsigned int) malloc(GT6426x_ETH_BUF_SIZE) & 0xfffffff0) + 0x10);
+ if (!p->eth_tx_buffer)
+ {
+ printf( "%s: %s allocation failure, %s\n",
+ __FUNCTION__, dev->name, "Tx Bufffer");
+ free(dev);
+ free(p);
+ free(p->eth_rx_desc);
+ return;
+ }
+
+ for (temp = 0 ; temp < NR ; temp ++) {
+ p->eth_rx_buffer[temp] =
+ (char *)
+ (((unsigned int) malloc(GT6426x_ETH_BUF_SIZE) & 0xfffffff0) + 0x10);
+ if (!p->eth_rx_buffer[temp])
+ {
+ printf( "%s: %s allocation failure, %s\n",
+ __FUNCTION__, dev->name, "Rx Buffers");
+ free(dev);
+ free(p);
+ free(p->eth_tx_buffer);
+ free(p->eth_rx_desc);
+ free(p->eth_tx_desc);
+ while (temp >= 0)
+ free(p->eth_rx_buffer[--temp]);
+ return;
+ }
+ }
+
+
+ eth_register(dev);
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+ miiphy_register(dev->name,
+ gt6426x_miiphy_read, gt6426x_miiphy_write);
+#endif
+ }
+
+}
+#endif
diff --git a/board/evb64260/eth.h b/board/evb64260/eth.h
new file mode 100644
index 0000000..76bd725
--- /dev/null
+++ b/board/evb64260/eth.h
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * eth.h - header file for the polled mode GT ethernet driver
+ */
+
+#ifndef __GT6426x_ETH_H__
+#define __GT6426x_ETH_H__
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <common.h>
+
+typedef struct eth0_tx_desc_struct {
+ volatile __u32 bytecount_reserved;
+ volatile __u32 command_status;
+ volatile struct eth0_tx_desc_struct * next_desc;
+ /* Note - the following will not work for 64 bit addressing */
+ volatile unsigned char * buff_pointer;
+} __attribute__ ((packed)) eth0_tx_desc_single;
+
+typedef struct eth0_rx_desc_struct {
+ volatile __u32 buff_size_byte_count;
+ volatile __u32 command_status;
+ volatile struct eth0_rx_desc_struct * next_desc;
+ volatile unsigned char * buff_pointer;
+} __attribute__ ((packed)) eth0_rx_desc_single;
+
+#define NT 20 /* Number of Transmit buffers */
+#define NR 20 /* Number of Receive buffers */
+#define MAX_BUFF_SIZE (1536+2*CACHE_LINE_SIZE) /* 1600 */
+#define ETHERNET_PORTS_DIFFERENCE_OFFSETS 0x400
+
+unsigned long TDN_ETH0 , RDN_ETH0; /* Rx/Tx current Descriptor Number*/
+unsigned int EVB64260_ETH0_irq;
+
+#define CLOSED 0
+#define OPENED 1
+
+#define PORT_ETH0 0
+
+extern eth0_tx_desc_single *eth0_tx_desc;
+extern eth0_rx_desc_single *eth0_rx_desc;
+extern char *eth0_tx_buffer;
+extern char *eth0_rx_buffer[NR];
+extern char *eth_data;
+
+extern int gt6426x_eth_poll(void *v);
+extern int gt6426x_eth_transmit(void *v, char *p, unsigned int s);
+extern void gt6426x_eth_disable(void *v);
+extern int gt6426x_eth_probe(void *v, bd_t *bis);
+
+#endif /* __GT64260x_ETH_H__ */
diff --git a/board/evb64260/eth_addrtbl.c b/board/evb64260/eth_addrtbl.c
new file mode 100644
index 0000000..8c2c17f
--- /dev/null
+++ b/board/evb64260/eth_addrtbl.c
@@ -0,0 +1,218 @@
+#include <common.h>
+#include <malloc.h>
+#include <galileo/gt64260R.h>
+#include <galileo/core.h>
+#include <asm/cache.h>
+#include "eth.h"
+#include "eth_addrtbl.h"
+
+#define PRINTF printf
+
+#ifdef CONFIG_GT_USE_MAC_HASH_TABLE
+
+static u32 addressTableHashMode[GAL_ETH_DEVS] = { 0, };
+static u32 addressTableHashSize[GAL_ETH_DEVS] = { 0, };
+static addrTblEntry *addressTableBase[GAL_ETH_DEVS] = { 0, };
+static void *realAddrTableBase[GAL_ETH_DEVS] = { 0, };
+
+static const u32 hashLength[2] = {
+ (0x8000), /* 8K * 4 entries */
+ (0x8000 / 16), /* 512 * 4 entries */
+};
+
+/* Initialize the address table for a port, if needed */
+unsigned int initAddressTable (u32 port, u32 hashMode, u32 hashSizeSelector)
+{
+ unsigned int tableBase;
+
+ if (port < 0 || port >= GAL_ETH_DEVS) {
+ printf ("%s: Invalid port number %d\n", __FUNCTION__, port);
+ return 0;
+ }
+
+ if (hashMode > 1) {
+ printf ("%s: Invalid Hash Mode %d\n", __FUNCTION__, port);
+ return 0;
+ }
+
+ if (realAddrTableBase[port] &&
+ (addressTableHashSize[port] != hashSizeSelector)) {
+ /* we have been here before,
+ * but now we want a different sized table
+ */
+ free (realAddrTableBase[port]);
+ realAddrTableBase[port] = 0;
+ addressTableBase[port] = 0;
+
+ }
+
+ tableBase = (unsigned int) addressTableBase[port];
+ /* we get called for every probe, so only do this once */
+ if (!tableBase) {
+ int bytes =
+ hashLength[hashSizeSelector] * sizeof (addrTblEntry);
+
+ realAddrTableBase[port] =
+ malloc (bytes + 64);
+ tableBase = (unsigned int)realAddrTableBase;
+
+ if (!tableBase) {
+ printf ("%s: alloc memory failed \n", __FUNCTION__);
+ return 0;
+ }
+
+ /* align to octal byte */
+ if (tableBase & 63)
+ tableBase = (tableBase + 63) & ~63;
+
+ addressTableHashMode[port] = hashMode;
+ addressTableHashSize[port] = hashSizeSelector;
+ addressTableBase[port] = (addrTblEntry *) tableBase;
+
+ memset ((void *) tableBase, 0, bytes);
+ }
+
+ return tableBase;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * This function will calculate the hash function of the address.
+ * depends on the hash mode and hash size.
+ * Inputs
+ * macH - the 2 most significant bytes of the MAC address.
+ * macL - the 4 least significant bytes of the MAC address.
+ * hashMode - hash mode 0 or hash mode 1.
+ * hashSizeSelector - indicates number of hash table entries (0=0x8000,1=0x800)
+ * Outputs
+ * return the calculated entry.
+ */
+u32 hashTableFunction (u32 macH, u32 macL, u32 HashSize, u32 hash_mode)
+{
+ u32 hashResult;
+ u32 addrH;
+ u32 addrL;
+ u32 addr0;
+ u32 addr1;
+ u32 addr2;
+ u32 addr3;
+ u32 addrHSwapped;
+ u32 addrLSwapped;
+
+
+ addrH = NIBBLE_SWAPPING_16_BIT (macH);
+ addrL = NIBBLE_SWAPPING_32_BIT (macL);
+
+ addrHSwapped = FLIP_4_BITS (addrH & 0xf)
+ + ((FLIP_4_BITS ((addrH >> 4) & 0xf)) << 4)
+ + ((FLIP_4_BITS ((addrH >> 8) & 0xf)) << 8)
+ + ((FLIP_4_BITS ((addrH >> 12) & 0xf)) << 12);
+
+ addrLSwapped = FLIP_4_BITS (addrL & 0xf)
+ + ((FLIP_4_BITS ((addrL >> 4) & 0xf)) << 4)
+ + ((FLIP_4_BITS ((addrL >> 8) & 0xf)) << 8)
+ + ((FLIP_4_BITS ((addrL >> 12) & 0xf)) << 12)
+ + ((FLIP_4_BITS ((addrL >> 16) & 0xf)) << 16)
+ + ((FLIP_4_BITS ((addrL >> 20) & 0xf)) << 20)
+ + ((FLIP_4_BITS ((addrL >> 24) & 0xf)) << 24)
+ + ((FLIP_4_BITS ((addrL >> 28) & 0xf)) << 28);
+
+ addrH = addrHSwapped;
+ addrL = addrLSwapped;
+
+ if (hash_mode == 0) {
+ addr0 = (addrL >> 2) & 0x03f;
+ addr1 = (addrL & 0x003) | ((addrL >> 8) & 0x7f) << 2;
+ addr2 = (addrL >> 15) & 0x1ff;
+ addr3 = ((addrL >> 24) & 0x0ff) | ((addrH & 1) << 8);
+ } else {
+ addr0 = FLIP_6_BITS (addrL & 0x03f);
+ addr1 = FLIP_9_BITS (((addrL >> 6) & 0x1ff));
+ addr2 = FLIP_9_BITS ((addrL >> 15) & 0x1ff);
+ addr3 = FLIP_9_BITS ((((addrL >> 24) & 0x0ff) |
+ ((addrH & 0x1) << 8)));
+ }
+
+ hashResult = (addr0 << 9) | (addr1 ^ addr2 ^ addr3);
+
+ if (HashSize == _8K_TABLE) {
+ hashResult = hashResult & 0xffff;
+ } else {
+ hashResult = hashResult & 0x07ff;
+ }
+
+ return (hashResult);
+}
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * This function will add an entry to the address table.
+ * depends on the hash mode and hash size that was initialized.
+ * Inputs
+ * port - ETHERNET port number.
+ * macH - the 2 most significant bytes of the MAC address.
+ * macL - the 4 least significant bytes of the MAC address.
+ * skip - if 1, skip this address.
+ * rd - the RD field in the address table.
+ * Outputs
+ * address table entry is added.
+ * true if success.
+ * false if table full
+ */
+int addAddressTableEntry (u32 port, u32 macH, u32 macL, u32 rd, u32 skip)
+{
+ addrTblEntry *entry;
+ u32 newHi;
+ u32 newLo;
+ u32 i;
+
+ newLo = (((macH >> 4) & 0xf) << 15)
+ | (((macH >> 0) & 0xf) << 11)
+ | (((macH >> 12) & 0xf) << 7)
+ | (((macH >> 8) & 0xf) << 3)
+ | (((macL >> 20) & 0x1) << 31)
+ | (((macL >> 16) & 0xf) << 27)
+ | (((macL >> 28) & 0xf) << 23)
+ | (((macL >> 24) & 0xf) << 19)
+ | (skip << SKIP_BIT) | (rd << 2) | VALID;
+
+ newHi = (((macL >> 4) & 0xf) << 15)
+ | (((macL >> 0) & 0xf) << 11)
+ | (((macL >> 12) & 0xf) << 7)
+ | (((macL >> 8) & 0xf) << 3)
+ | (((macL >> 21) & 0x7) << 0);
+
+ /*
+ * Pick the appropriate table, start scanning for free/reusable
+ * entries at the index obtained by hashing the specified MAC address
+ */
+ entry = addressTableBase[port];
+ entry += hashTableFunction (macH, macL, addressTableHashSize[port],
+ addressTableHashMode[port]);
+ for (i = 0; i < HOP_NUMBER; i++, entry++) {
+ if (!(entry->lo & VALID) /*|| (entry->lo & SKIP) */ ) {
+ break;
+ } else { /* if same address put in same position */
+ if (((entry->lo & 0xfffffff8) == (newLo & 0xfffffff8))
+ && (entry->hi == newHi)) {
+ break;
+ }
+ }
+ }
+
+ if (i == HOP_NUMBER) {
+ PRINTF ("addGT64260addressTableEntry: table section is full\n");
+ return false;
+ }
+
+ /*
+ * Update the selected entry
+ */
+ entry->hi = newHi;
+ entry->lo = newLo;
+ DCACHE_FLUSH_N_SYNC ((u32) entry, MAC_ENTRY_SIZE);
+ return true;
+}
+
+#endif /* CONFIG_GT_USE_MAC_HASH_TABLE */
diff --git a/board/evb64260/eth_addrtbl.h b/board/evb64260/eth_addrtbl.h
new file mode 100644
index 0000000..5a62c67
--- /dev/null
+++ b/board/evb64260/eth_addrtbl.h
@@ -0,0 +1,83 @@
+#ifndef _ADDRESS_TABLE_H
+#define _ADDRESS_TABLE_H 1
+
+/*
+ * ----------------------------------------------------------------------------
+ * addressTable.h - this file has all the declarations of the address table
+ */
+
+#define _8K_TABLE 0
+#define ADDRESS_TABLE_ALIGNMENT 8
+#define HASH_DEFAULT_MODE 14
+#define HASH_MODE 13
+#define HASH_SIZE 12
+#define HOP_NUMBER 12
+#define MAC_ADDRESS_STRING_SIZE 12
+#define MAC_ENTRY_SIZE sizeof(addrTblEntry)
+#define MAX_NUMBER_OF_ADDRESSES_TO_STORE 1000
+#define PROMISCUOUS_MODE 0
+#define SKIP 1<<1
+#define SKIP_BIT 1
+#define VALID 1
+
+/*
+ * ----------------------------------------------------------------------------
+ * XXX_MIKE - potential sign-extension bugs lurk here...
+ */
+#define NIBBLE_SWAPPING_32_BIT(X) ( (((X) & 0xf0f0f0f0) >> 4) \
+ | (((X) & 0x0f0f0f0f) << 4) )
+
+#define NIBBLE_SWAPPING_16_BIT(X) ( (((X) & 0x0000f0f0) >> 4) \
+ | (((X) & 0x00000f0f) << 4) )
+
+#define FLIP_4_BITS(X) ( (((X) & 0x01) << 3) | (((X) & 0x002) << 1) \
+ | (((X) & 0x04) >> 1) | (((X) & 0x008) >> 3) )
+
+#define FLIP_6_BITS(X) ( (((X) & 0x01) << 5) | (((X) & 0x020) >> 5) \
+ | (((X) & 0x02) << 3) | (((X) & 0x010) >> 3) \
+ | (((X) & 0x04) << 1) | (((X) & 0x008) >> 1) )
+
+#define FLIP_9_BITS(X) ( (((X) & 0x01) << 8) | (((X) & 0x100) >> 8) \
+ | (((X) & 0x02) << 6) | (((X) & 0x080) >> 6) \
+ | (((X) & 0x04) << 4) | (((X) & 0x040) >> 4) \
+ | ((X) & 0x10) | (((X) & 0x08) << 2) | (((X) & 0x020) >> 2) )
+
+/*
+ * V: value we're operating on
+ * O: offset of rightmost bit in field
+ * W: width of field to shift
+ * S: distance to shift left
+ */
+#define MASK( fieldWidth ) ((1 << (fieldWidth)) - 1)
+#define leftShiftedBitfield( V,O,W,S) (((V) & (MASK(W) << (O))) << (S))
+#define rightShiftedBitfield(V,O,W,S) (((u32)((V) & (MASK(W) << (O)))) >> (S))
+
+
+/*
+ * Push to main memory all cache lines associated with
+ * the specified range of virtual memory addresses
+ *
+ * A: Address of first byte in range to flush
+ * N: Number of bytes to flush
+ * Note - flush_dcache_range() does a "sync", does NOT invalidate
+ */
+#define DCACHE_FLUSH_N_SYNC( A, N ) flush_dcache_range( (A), ((A)+(N)) )
+
+
+typedef struct addressTableEntryStruct {
+ u32 hi;
+ u32 lo;
+} addrTblEntry;
+
+u32
+uncachedPages( u32 pages );
+u32
+hashTableFunction( u32 macH, u32 macL, u32 HashSize, u32 hash_mode );
+
+unsigned int
+initAddressTable( u32 port, u32 hashMode, u32 hashSize );
+
+int
+addAddressTableEntry( u32 port, u32 macH, u32 macL, u32 rd, u32 skip );
+
+#endif /* #ifndef _ADDRESS_TABLE_H */
diff --git a/board/evb64260/evb64260.c b/board/evb64260/evb64260.c
new file mode 100644
index 0000000..393320a
--- /dev/null
+++ b/board/evb64260/evb64260.c
@@ -0,0 +1,452 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * evb64260.c - main board support/init for the Galileo Eval board.
+ */
+
+#include <common.h>
+#include <74xx_7xx.h>
+#include <galileo/memory.h>
+#include <galileo/pci.h>
+#include <galileo/gt64260R.h>
+#include <net.h>
+#include <netdev.h>
+#include <linux/compiler.h>
+
+#include <asm/io.h>
+#include "eth.h"
+#include "mpsc.h"
+#include "i2c.h"
+#include "64260.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_ZUMA_V2
+extern void zuma_mbox_init(void);
+#endif
+
+#undef DEBUG
+#define MAP_PCI
+
+#ifdef DEBUG
+#define DP(x) x
+#else
+#define DP(x)
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/* this is the current GT register space location */
+/* it starts at CONFIG_SYS_DFL_GT_REGS but moves later to CONFIG_SYS_GT_REGS */
+
+/* Unfortunately, we cant change it while we are in flash, so we initialize it
+ * to the "final" value. This means that any debug_led calls before
+ * board_early_init_f wont work right (like in cpu_init_f).
+ * See also my_remap_gt_regs below. (NTL)
+ */
+
+unsigned int INTERNAL_REG_BASE_ADDR = CONFIG_SYS_GT_REGS;
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * This is a version of the GT register space remapping function that
+ * doesn't touch globals (meaning, it's ok to run from flash.)
+ *
+ * Unfortunately, this has the side effect that a writable
+ * INTERNAL_REG_BASE_ADDR is impossible. Oh well.
+ */
+
+void
+my_remap_gt_regs(u32 cur_loc, u32 new_loc)
+{
+ u32 temp;
+
+ /* check and see if it's already moved */
+ temp = in_le32((u32 *)(new_loc + INTERNAL_SPACE_DECODE));
+ if ((temp & 0xffff) == new_loc >> 20)
+ return;
+
+ temp = (in_le32((u32 *)(cur_loc + INTERNAL_SPACE_DECODE)) &
+ 0xffff0000) | (new_loc >> 20);
+
+ out_le32((u32 *)(cur_loc + INTERNAL_SPACE_DECODE), temp);
+
+ while (GTREGREAD(INTERNAL_SPACE_DECODE) != temp);
+}
+
+static void
+gt_pci_config(void)
+{
+ /* move PCI stuff out of the way - NTL */
+ /* map PCI Host 0 */
+ pciMapSpace(PCI_HOST0, PCI_REGION0, CONFIG_SYS_PCI0_0_MEM_SPACE,
+ CONFIG_SYS_PCI0_0_MEM_SPACE, CONFIG_SYS_PCI0_MEM_SIZE);
+
+ pciMapSpace(PCI_HOST0, PCI_REGION1, 0, 0, 0);
+ pciMapSpace(PCI_HOST0, PCI_REGION2, 0, 0, 0);
+ pciMapSpace(PCI_HOST0, PCI_REGION3, 0, 0, 0);
+
+ pciMapSpace(PCI_HOST0, PCI_IO, CONFIG_SYS_PCI0_IO_SPACE_PCI,
+ CONFIG_SYS_PCI0_IO_SPACE, CONFIG_SYS_PCI0_IO_SIZE);
+
+ /* map PCI Host 1 */
+ pciMapSpace(PCI_HOST1, PCI_REGION0, CONFIG_SYS_PCI1_0_MEM_SPACE,
+ CONFIG_SYS_PCI1_0_MEM_SPACE, CONFIG_SYS_PCI1_MEM_SIZE);
+
+ pciMapSpace(PCI_HOST1, PCI_REGION1, 0, 0, 0);
+ pciMapSpace(PCI_HOST1, PCI_REGION2, 0, 0, 0);
+ pciMapSpace(PCI_HOST1, PCI_REGION3, 0, 0, 0);
+
+ pciMapSpace(PCI_HOST1, PCI_IO, CONFIG_SYS_PCI1_IO_SPACE_PCI,
+ CONFIG_SYS_PCI1_IO_SPACE, CONFIG_SYS_PCI1_IO_SIZE);
+
+ /* PCI interface settings */
+ GT_REG_WRITE(PCI_0TIMEOUT_RETRY, 0xffff);
+ GT_REG_WRITE(PCI_1TIMEOUT_RETRY, 0xffff);
+ GT_REG_WRITE(PCI_0BASE_ADDRESS_REGISTERS_ENABLE, 0xfffff80e);
+ GT_REG_WRITE(PCI_1BASE_ADDRESS_REGISTERS_ENABLE, 0xfffff80e);
+
+
+}
+
+/* Setup CPU interface paramaters */
+static void
+gt_cpu_config(void)
+{
+ cpu_t cpu = get_cpu_type();
+ ulong tmp;
+
+ /* cpu configuration register */
+ tmp = GTREGREAD(CPU_CONFIGURATION);
+
+ /* set the AACK delay bit
+ * see Res#14 */
+ tmp |= CPU_CONF_AACK_DELAY;
+ tmp &= ~CPU_CONF_AACK_DELAY_2; /* New RGF */
+
+ /* Galileo claims this is necessary for all busses >= 100 MHz */
+ tmp |= CPU_CONF_FAST_CLK;
+
+ if (cpu == CPU_750CX) {
+ tmp &= ~CPU_CONF_DP_VALID; /* Safer, needed for CXe. RGF */
+ tmp &= ~CPU_CONF_AP_VALID;
+ } else {
+ tmp |= CPU_CONF_DP_VALID;
+ tmp |= CPU_CONF_AP_VALID;
+ }
+
+ /* this only works with the MPX bus */
+ tmp &= ~CPU_CONF_RD_OOO; /* Safer RGF */
+ tmp |= CPU_CONF_PIPELINE;
+ tmp |= CPU_CONF_TA_DELAY;
+
+ GT_REG_WRITE(CPU_CONFIGURATION, tmp);
+
+ /* CPU master control register */
+ tmp = GTREGREAD(CPU_MASTER_CONTROL);
+
+ tmp |= CPU_MAST_CTL_ARB_EN;
+
+ if ((cpu == CPU_7400) ||
+ (cpu == CPU_7410) ||
+ (cpu == CPU_7450)) {
+
+ tmp |= CPU_MAST_CTL_CLEAN_BLK;
+ tmp |= CPU_MAST_CTL_FLUSH_BLK;
+
+ } else {
+ /* cleanblock must be cleared for CPUs
+ * that do not support this command
+ * see Res#1 */
+ tmp &= ~CPU_MAST_CTL_CLEAN_BLK;
+ tmp &= ~CPU_MAST_CTL_FLUSH_BLK;
+ }
+ GT_REG_WRITE(CPU_MASTER_CONTROL, tmp);
+}
+
+/*
+ * board_early_init_f.
+ *
+ * set up gal. device mappings, etc.
+ */
+int board_early_init_f (void)
+{
+ uchar sram_boot = 0;
+
+ /*
+ * set up the GT the way the kernel wants it
+ * the call to move the GT register space will obviously
+ * fail if it has already been done, but we're going to assume
+ * that if it's not at the power-on location, it's where we put
+ * it last time. (huber)
+ */
+ my_remap_gt_regs(CONFIG_SYS_DFL_GT_REGS, CONFIG_SYS_GT_REGS);
+
+ gt_pci_config();
+
+ /* mask all external interrupt sources */
+ GT_REG_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, 0);
+ GT_REG_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH, 0);
+ GT_REG_WRITE(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0);
+ GT_REG_WRITE(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0);
+ GT_REG_WRITE(PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0);
+ GT_REG_WRITE(PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0);
+ GT_REG_WRITE(CPU_INT_0_MASK, 0);
+ GT_REG_WRITE(CPU_INT_1_MASK, 0);
+ GT_REG_WRITE(CPU_INT_2_MASK, 0);
+ GT_REG_WRITE(CPU_INT_3_MASK, 0);
+
+ /* now, onto the configuration */
+ GT_REG_WRITE(SDRAM_CONFIGURATION, CONFIG_SYS_SDRAM_CONFIG);
+
+ /* ----- DEVICE BUS SETTINGS ------ */
+
+ /*
+ * EVB
+ * 0 - SRAM
+ * 1 - RTC
+ * 2 - UART
+ * 3 - Flash
+ * boot - BootCS
+ *
+ * Zuma
+ * 0 - Flash
+ * boot - BootCS
+ */
+
+ /*
+ * the dual 7450 module requires burst access to the boot
+ * device, so the serial rom copies the boot device to the
+ * on-board sram on the eval board, and updates the correct
+ * registers to boot from the sram. (device0)
+ */
+#if defined(CONFIG_ZUMA_V2) || defined(CONFIG_P3G4)
+ /* Zuma has no SRAM */
+ sram_boot = 0;
+#else
+ if (memoryGetDeviceBaseAddress(DEVICE0) && 0xfff00000 == CONFIG_SYS_MONITOR_BASE)
+ sram_boot = 1;
+#endif
+
+ memoryMapDeviceSpace(DEVICE0, CONFIG_SYS_DEV0_SPACE, CONFIG_SYS_DEV0_SIZE);
+
+ memoryMapDeviceSpace(DEVICE1, CONFIG_SYS_DEV1_SPACE, CONFIG_SYS_DEV1_SIZE);
+ memoryMapDeviceSpace(DEVICE2, CONFIG_SYS_DEV2_SPACE, CONFIG_SYS_DEV2_SIZE);
+ memoryMapDeviceSpace(DEVICE3, CONFIG_SYS_DEV3_SPACE, CONFIG_SYS_DEV3_SIZE);
+
+ /* configure device timing */
+#ifdef CONFIG_SYS_DEV0_PAR
+ if (!sram_boot)
+ GT_REG_WRITE(DEVICE_BANK0PARAMETERS, CONFIG_SYS_DEV0_PAR);
+#endif
+
+#ifdef CONFIG_SYS_DEV1_PAR
+ GT_REG_WRITE(DEVICE_BANK1PARAMETERS, CONFIG_SYS_DEV1_PAR);
+#endif
+#ifdef CONFIG_SYS_DEV2_PAR
+ GT_REG_WRITE(DEVICE_BANK2PARAMETERS, CONFIG_SYS_DEV2_PAR);
+#endif
+
+#ifdef CONFIG_EVB64260
+#ifdef CONFIG_SYS_32BIT_BOOT_PAR
+ /* detect if we are booting from the 32 bit flash */
+ if (GTREGREAD(DEVICE_BOOT_BANK_PARAMETERS) & (0x3 << 20)) {
+ /* 32 bit boot flash */
+ GT_REG_WRITE(DEVICE_BANK3PARAMETERS, CONFIG_SYS_8BIT_BOOT_PAR);
+ GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CONFIG_SYS_32BIT_BOOT_PAR);
+ } else {
+ /* 8 bit boot flash */
+ GT_REG_WRITE(DEVICE_BANK3PARAMETERS, CONFIG_SYS_32BIT_BOOT_PAR);
+ GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CONFIG_SYS_8BIT_BOOT_PAR);
+ }
+#else
+ /* 8 bit boot flash only */
+ GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CONFIG_SYS_8BIT_BOOT_PAR);
+#endif
+#else /* CONFIG_EVB64260 not defined */
+ /* We are booting from 16-bit flash.
+ */
+ GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CONFIG_SYS_16BIT_BOOT_PAR);
+#endif
+
+ gt_cpu_config();
+
+ /* MPP setup */
+ GT_REG_WRITE(MPP_CONTROL0, CONFIG_SYS_MPP_CONTROL_0);
+ GT_REG_WRITE(MPP_CONTROL1, CONFIG_SYS_MPP_CONTROL_1);
+ GT_REG_WRITE(MPP_CONTROL2, CONFIG_SYS_MPP_CONTROL_2);
+ GT_REG_WRITE(MPP_CONTROL3, CONFIG_SYS_MPP_CONTROL_3);
+
+ GT_REG_WRITE(GPP_LEVEL_CONTROL, CONFIG_SYS_GPP_LEVEL_CONTROL);
+ GT_REG_WRITE(SERIAL_PORT_MULTIPLEX, CONFIG_SYS_SERIAL_PORT_MUX);
+
+ return 0;
+}
+
+/* various things to do after relocation */
+
+int misc_init_r (void)
+{
+ icache_enable();
+#ifdef CONFIG_SYS_L2
+ l2cache_enable();
+#endif
+
+#ifdef CONFIG_MPSC
+ mpsc_init2();
+#endif
+
+#ifdef CONFIG_ZUMA_V2
+ zuma_mbox_init();
+#endif
+ return (0);
+}
+
+void
+after_reloc(ulong dest_addr)
+{
+ /* check to see if we booted from the sram. If so, move things
+ * back to the way they should be. (we're running from main
+ * memory at this point now */
+
+ if (memoryGetDeviceBaseAddress(DEVICE0) == CONFIG_SYS_MONITOR_BASE) {
+ memoryMapDeviceSpace(DEVICE0, CONFIG_SYS_DEV0_SPACE, CONFIG_SYS_DEV0_SIZE);
+ memoryMapDeviceSpace(BOOT_DEVICE, CONFIG_SYS_FLASH_BASE, _1M);
+ }
+
+ /* now, jump to the main U-Boot board init code */
+ board_init_r ((gd_t *)gd, dest_addr);
+
+ /* NOTREACHED */
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Check Board Identity:
+ */
+
+int
+checkboard (void)
+{
+ puts ("Board: " CONFIG_SYS_BOARD_NAME "\n");
+ return (0);
+}
+
+/* utility functions */
+void
+debug_led(int led, int mode)
+{
+#if !defined(CONFIG_ZUMA_V2) && !defined(CONFIG_P3G4)
+ volatile int *addr = NULL;
+ __maybe_unused int dummy;
+
+ if (mode == 1) {
+ switch (led) {
+ case 0:
+ addr = (int *)((unsigned int)CONFIG_SYS_DEV1_SPACE | 0x08000);
+ break;
+
+ case 1:
+ addr = (int *)((unsigned int)CONFIG_SYS_DEV1_SPACE | 0x0c000);
+ break;
+
+ case 2:
+ addr = (int *)((unsigned int)CONFIG_SYS_DEV1_SPACE | 0x10000);
+ break;
+ }
+ } else if (mode == 0) {
+ switch (led) {
+ case 0:
+ addr = (int *)((unsigned int)CONFIG_SYS_DEV1_SPACE | 0x14000);
+ break;
+
+ case 1:
+ addr = (int *)((unsigned int)CONFIG_SYS_DEV1_SPACE | 0x18000);
+ break;
+
+ case 2:
+ addr = (int *)((unsigned int)CONFIG_SYS_DEV1_SPACE | 0x1c000);
+ break;
+ }
+ }
+ WRITE_CHAR(addr, 0);
+ dummy = *addr;
+#endif /* CONFIG_ZUMA_V2 */
+}
+
+void
+display_mem_map(void)
+{
+ int i,j;
+ unsigned int base,size,width;
+ /* SDRAM */
+ printf("SDRAM\n");
+ for(i=0;i<=BANK3;i++) {
+ base = memoryGetBankBaseAddress(i);
+ size = memoryGetBankSize(i);
+ if(size !=0)
+ {
+ printf("BANK%d: base - 0x%08x\tsize - %dM bytes\n",i,base,size>>20);
+ }
+ }
+
+ /* CPU's PCI windows */
+ for(i=0;i<=PCI_HOST1;i++) {
+ printf("\nCPU's PCI %d windows\n", i);
+ base=pciGetSpaceBase(i,PCI_IO);
+ size=pciGetSpaceSize(i,PCI_IO);
+ printf(" IO: base - 0x%08x\tsize - %dM bytes\n",base,size>>20);
+ for(j=0;j<=PCI_REGION3;j++) {
+ base = pciGetSpaceBase(i,j);
+ size = pciGetSpaceSize(i,j);
+ printf("MEMORY %d: base - 0x%08x\tsize - %dM bytes\n",j,base,
+ size>>20);
+ }
+ }
+
+ /* Devices */
+ printf("\nDEVICES\n");
+ for(i=0;i<=DEVICE3;i++) {
+ base = memoryGetDeviceBaseAddress(i);
+ size = memoryGetDeviceSize(i);
+ width= memoryGetDeviceWidth(i) * 8;
+ printf("DEV %d: base - 0x%08x\tsize - %dM bytes\twidth - %d bits\n",
+ i, base, size>>20, width);
+ }
+
+ /* Bootrom */
+ base = memoryGetDeviceBaseAddress(BOOT_DEVICE); /* Boot */
+ size = memoryGetDeviceSize(BOOT_DEVICE);
+ width= memoryGetDeviceWidth(BOOT_DEVICE) * 8;
+ printf(" BOOT: base - 0x%08x\tsize - %dM bytes\twidth - %d bits\n",
+ base, size>>20, width);
+}
+
+int board_eth_init(bd_t *bis)
+{
+ gt6426x_eth_initialize(bis);
+ return 0;
+}
diff --git a/board/evb64260/flash.c b/board/evb64260/flash.c
new file mode 100644
index 0000000..825bbaf
--- /dev/null
+++ b/board/evb64260/flash.c
@@ -0,0 +1,853 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * flash.c - flash support for the 512k, 8bit boot flash on the GEVB
+ * most of this file was based on the existing U-Boot
+ * flash drivers.
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <galileo/gt64260R.h>
+#include <galileo/memory.h>
+#include "intel_flash.h"
+
+#define FLASH_ROM 0xFFFD /* unknown flash type */
+#define FLASH_RAM 0xFFFE /* unknown flash type */
+#define FLASH_MAN_UNKNOWN 0xFFFF0000
+
+/* #define DEBUG */
+/* #define FLASH_ID_OVERRIDE */ /* Hack to set type to 040B if ROM emulator is installed.
+ * Can be used to program a ROM in circuit if a programmer
+ * is not available by swapping the rom out. */
+
+/* Intel flash commands */
+int flash_erase_intel(flash_info_t *info, int s_first, int s_last);
+int write_word_intel(bank_addr_t addr, bank_word_t value);
+
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (int portwidth, vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long
+flash_init (void)
+{
+ unsigned int i;
+ unsigned long size_b0 = 0, size_b1 = 0;
+ unsigned long base, flash_size;
+
+ /* Init: no FLASHes known */
+ for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ /* the boot flash */
+ base = CONFIG_SYS_FLASH_BASE;
+#ifndef CONFIG_SYS_BOOT_FLASH_WIDTH
+#define CONFIG_SYS_BOOT_FLASH_WIDTH 1
+#endif
+ size_b0 = flash_get_size(CONFIG_SYS_BOOT_FLASH_WIDTH, (vu_long *)base,
+ &flash_info[0]);
+
+#ifndef CONFIG_P3G4
+ printf("[");
+ print_size (size_b0, "");
+ printf("@%08lX] ", base);
+#endif
+
+ if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n",
+ base, size_b0, size_b0<<20);
+ }
+
+ base = memoryGetDeviceBaseAddress(CONFIG_SYS_EXTRA_FLASH_DEVICE);
+ for(i=1;i<CONFIG_SYS_MAX_FLASH_BANKS;i++) {
+ unsigned long size = flash_get_size(CONFIG_SYS_EXTRA_FLASH_WIDTH, (vu_long *)base, &flash_info[i]);
+
+#ifndef CONFIG_P3G4
+ printf("[");
+ print_size (size, "");
+ printf("@%08lX] ", base);
+#endif
+
+ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
+ if(i==1) {
+ printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n",
+ base, size_b1, size_b1<<20);
+ }
+ break;
+ }
+ size_b1+=size;
+ base+=size;
+ }
+
+#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
+ /* monitor protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CONFIG_SYS_MONITOR_BASE,
+ CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
+ flash_get_info(CONFIG_SYS_MONITOR_BASE));
+#endif
+
+#ifdef CONFIG_ENV_IS_IN_FLASH
+ /* ENV protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ CONFIG_ENV_ADDR,
+ CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
+ flash_get_info(CONFIG_ENV_ADDR));
+#endif
+
+ flash_size = size_b0 + size_b1;
+ return flash_size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void
+flash_get_offsets (ulong base, flash_info_t *info)
+{
+ int i;
+ int sector_size;
+
+ if(!info->sector_count) return;
+
+ /* set up sector start address table */
+ switch(info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM040:
+ case FLASH_28F128J3A:
+ case FLASH_28F640J3A:
+ case FLASH_RAM:
+ /* this chip has uniformly spaced sectors */
+ sector_size=info->size/info->sector_count;
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * sector_size);
+ break;
+ default:
+ if (info->flash_id & FLASH_BTYPE) {
+ /* set sector offsets for bottom boot block type */
+ info->start[0] = base + 0x00000000;
+ info->start[1] = base + 0x00008000;
+ info->start[2] = base + 0x0000C000;
+ info->start[3] = base + 0x00010000;
+ for (i = 4; i < info->sector_count; i++) {
+ info->start[i] = base + (i * 0x00020000) - 0x00060000;
+ }
+ } else {
+ /* set sector offsets for top boot block type */
+ i = info->sector_count - 1;
+ info->start[i--] = base + info->size - 0x00008000;
+ info->start[i--] = base + info->size - 0x0000C000;
+ info->start[i--] = base + info->size - 0x00010000;
+ for (; i >= 0; i--) {
+ info->start[i] = base + i * 0x00020000;
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+flash_info_t *flash_get_info(ulong base)
+{
+ int i;
+ flash_info_t * info;
+
+ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
+ info = & flash_info[i];
+ if (info->start[0] <= base && base <= info->start[0] + info->size - 1)
+ break;
+ }
+
+ return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void
+flash_print_info (flash_info_t *info)
+{
+ int i;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD: printf ("AMD "); break;
+ case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
+ case FLASH_MAN_INTEL: printf ("INTEL "); break;
+ default: printf ("Unknown Vendor "); break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM040:
+ printf ("AM29LV040B (4 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM400B:
+ printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM400T:
+ printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM800B:
+ printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM800T:
+ printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM160B:
+ printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM160T:
+ printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+ break;
+ case FLASH_AM320B:
+ printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+ break;
+ case FLASH_AM320T:
+ printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+ break;
+ case FLASH_28F640J3A:
+ printf ("28F640J3A (64 Mbit)\n");
+ break;
+ case FLASH_28F128J3A:
+ printf ("28F128J3A (128 Mbit)\n");
+ break;
+ case FLASH_ROM:
+ printf ("ROM\n");
+ break;
+ case FLASH_RAM:
+ printf ("RAM\n");
+ break;
+ default:
+ printf ("Unknown Chip Type\n");
+ break;
+ }
+
+ puts (" Size: ");
+ print_size (info->size, "");
+ printf (" in %d Sectors\n", 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");
+ return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static inline void flash_cmd(int width, volatile unsigned char *addr, int offset, unsigned char cmd)
+{
+ /* supports 1x8, 1x16, and 2x16 */
+ /* 2x8 and 4x8 are not supported */
+ if(width==4) {
+ /* assuming chips are in 16 bit mode */
+ /* 2x16 */
+ unsigned long cmd32=(cmd<<16)|cmd;
+ *(volatile unsigned long *)(addr+offset*2)=cmd32;
+ } else if (width == 2) {
+ /* 1x16 */
+ *(volatile unsigned short *)((unsigned short*)addr+offset)=cmd;
+ } else {
+ /* 1x8 */
+ *(volatile unsigned char *)(addr+offset)=cmd;
+ }
+}
+
+static ulong
+flash_get_size (int portwidth, vu_long *addr, flash_info_t *info)
+{
+ short i;
+ volatile unsigned char *caddr = (unsigned char *)addr;
+ volatile unsigned short *saddr = (unsigned short *)addr;
+ volatile unsigned long *laddr = (unsigned long *)addr;
+ char old[2], save;
+ ulong id, manu, base = (ulong)addr;
+
+ info->portwidth=portwidth;
+
+ save = *caddr;
+
+ flash_cmd(portwidth,caddr,0,0xf0);
+ flash_cmd(portwidth,caddr,0,0xf0);
+
+ udelay(10);
+
+ old[0] = caddr[0];
+ old[1] = caddr[1];
+
+
+ if(old[0]!=0xf0) {
+ flash_cmd(portwidth,caddr,0,0xf0);
+ flash_cmd(portwidth,caddr,0,0xf0);
+
+ udelay(10);
+
+ if(*caddr==0xf0) {
+ /* this area is ROM */
+ *caddr=save;
+#ifndef FLASH_ID_OVERRIDE
+ info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN;
+ info->sector_count = 8;
+ info->size = 0x80000;
+#else
+ info->flash_id = FLASH_MAN_AMD + FLASH_AM040;
+ info->sector_count = 8;
+ info->size = 0x80000;
+ info->chipwidth=1;
+#endif
+ flash_get_offsets(base, info);
+ return info->size;
+ }
+ } else {
+ *caddr=0;
+
+ udelay(10);
+
+ if(*caddr==0) {
+ /* this area is RAM */
+ *caddr=save;
+ info->flash_id = FLASH_RAM + FLASH_MAN_UNKNOWN;
+ info->sector_count = 8;
+ info->size = 0x80000;
+ flash_get_offsets(base, info);
+ return info->size;
+ }
+ flash_cmd(portwidth,caddr,0,0xf0);
+
+ udelay(10);
+ }
+
+ /* Write auto select command: read Manufacturer ID */
+ flash_cmd(portwidth,caddr,0x555,0xAA);
+ flash_cmd(portwidth,caddr,0x2AA,0x55);
+ flash_cmd(portwidth,caddr,0x555,0x90);
+
+ udelay(10);
+
+ if ((caddr[0] == old[0]) &&
+ (caddr[1] == old[1])) {
+
+ /* this area is ROM */
+#ifndef FLASH_ID_OVERRIDE
+ info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN;
+ info->sector_count = 8;
+ info->size = 0x80000;
+#else
+ info->flash_id = FLASH_MAN_AMD + FLASH_AM040;
+ info->sector_count = 8;
+ info->size = 0x80000;
+ info->chipwidth=1;
+#endif
+ flash_get_offsets(base, info);
+ return info->size;
+#ifdef DEBUG
+ } else {
+ printf("%px%d: %02x:%02x -> %02x:%02x\n",
+ caddr, portwidth, old[0], old[1],
+ caddr[0], caddr[1]);
+#endif
+ }
+
+ switch(portwidth) {
+ case 1:
+ manu = caddr[0];
+ manu |= manu<<16;
+ id = caddr[1];
+ break;
+ case 2:
+ manu = saddr[0];
+ manu |= manu<<16;
+ id = saddr[1];
+ id |= id<<16;
+ break;
+ case 4:
+ manu = laddr[0];
+ id = laddr[1];
+ break;
+ default:
+ id = manu = -1;
+ break;
+ }
+
+#ifdef DEBUG
+ printf("\n%08lx:%08lx:%08lx\n", base, manu, id);
+ printf("%08lx %08lx %08lx %08lx\n",
+ laddr[0],laddr[1],laddr[2],laddr[3]);
+#endif
+
+ switch (manu) {
+ case AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+ case FUJ_MANUFACT:
+ info->flash_id = FLASH_MAN_FUJ;
+ break;
+ case INTEL_MANUFACT:
+ info->flash_id = FLASH_MAN_INTEL;
+ break;
+ default:
+ printf("Unknown Mfr [%08lx]:%08lx\n", manu, id);
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return (0); /* no or unknown flash */
+ }
+
+ switch (id) {
+ case AMD_ID_LV400T:
+ info->flash_id += FLASH_AM400T;
+ info->sector_count = 11;
+ info->size = 0x00100000;
+ info->chipwidth=1;
+ break; /* => 1 MB */
+
+ case AMD_ID_LV400B:
+ info->flash_id += FLASH_AM400B;
+ info->sector_count = 11;
+ info->size = 0x00100000;
+ info->chipwidth=1;
+ break; /* => 1 MB */
+
+ case AMD_ID_LV800T:
+ info->flash_id += FLASH_AM800T;
+ info->sector_count = 19;
+ info->size = 0x00200000;
+ info->chipwidth=1;
+ break; /* => 2 MB */
+
+ case AMD_ID_LV800B:
+ info->flash_id += FLASH_AM800B;
+ info->sector_count = 19;
+ info->size = 0x00200000;
+ info->chipwidth=1;
+ break; /* => 2 MB */
+
+ case AMD_ID_LV160T:
+ info->flash_id += FLASH_AM160T;
+ info->sector_count = 35;
+ info->size = 0x00400000;
+ info->chipwidth=1;
+ break; /* => 4 MB */
+
+ case AMD_ID_LV160B:
+ info->flash_id += FLASH_AM160B;
+ info->sector_count = 35;
+ info->size = 0x00400000;
+ info->chipwidth=1;
+ break; /* => 4 MB */
+#if 0 /* enable when device IDs are available */
+ case AMD_ID_LV320T:
+ info->flash_id += FLASH_AM320T;
+ info->sector_count = 67;
+ info->size = 0x00800000;
+ break; /* => 8 MB */
+
+ case AMD_ID_LV320B:
+ info->flash_id += FLASH_AM320B;
+ info->sector_count = 67;
+ info->size = 0x00800000;
+ break; /* => 8 MB */
+#endif
+ case AMD_ID_LV040B:
+ info->flash_id += FLASH_AM040;
+ info->sector_count = 8;
+ info->size = 0x80000;
+ info->chipwidth=1;
+ break;
+
+ case INTEL_ID_28F640J3A:
+ info->flash_id += FLASH_28F640J3A;
+ info->sector_count = 64;
+ info->size = 128*1024 * 64; /* 128kbytes x 64 blocks */
+ info->chipwidth=2;
+ if(portwidth==4) info->size*=2; /* 2x16 */
+ break;
+
+ case INTEL_ID_28F128J3A:
+ info->flash_id += FLASH_28F128J3A;
+ info->sector_count = 128;
+ info->size = 128*1024 * 128; /* 128kbytes x 128 blocks */
+ info->chipwidth=2;
+ if(portwidth==4) info->size*=2; /* 2x16 */
+ break;
+
+ default:
+ printf("Unknown id %lx:[%lx]\n", manu, id);
+ info->flash_id = FLASH_UNKNOWN;
+ info->chipwidth=1;
+ return (0); /* => no or unknown flash */
+
+ }
+
+ flash_get_offsets(base, info);
+
+#if 0
+ /* set up sector start address table */
+ if (info->flash_id & FLASH_AM040) {
+ /* this chip has uniformly spaced sectors */
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x00010000);
+
+ } else if (info->flash_id & FLASH_BTYPE) {
+ /* set sector offsets for bottom boot block type */
+ info->start[0] = base + 0x00000000;
+ info->start[1] = base + 0x00008000;
+ info->start[2] = base + 0x0000C000;
+ info->start[3] = base + 0x00010000;
+ for (i = 4; i < info->sector_count; i++) {
+ info->start[i] = base + (i * 0x00020000) - 0x00060000;
+ }
+ } else {
+ /* set sector offsets for top boot block type */
+ i = info->sector_count - 1;
+ info->start[i--] = base + info->size - 0x00008000;
+ info->start[i--] = base + info->size - 0x0000C000;
+ info->start[i--] = base + info->size - 0x00010000;
+ for (; i >= 0; i--) {
+ info->start[i] = base + i * 0x00020000;
+ }
+ }
+#endif
+
+ /* check for protected sectors */
+ for (i = 0; i < info->sector_count; i++) {
+ /* read sector protection at sector address, (A7 .. A0)=0x02 */
+ /* D0 = 1 if protected */
+ caddr = (volatile unsigned char *)(info->start[i]);
+ saddr = (volatile unsigned short *)(info->start[i]);
+ laddr = (volatile unsigned long *)(info->start[i]);
+ if(portwidth==1)
+ info->protect[i] = caddr[2] & 1;
+ else if(portwidth==2)
+ info->protect[i] = saddr[2] & 1;
+ else
+ info->protect[i] = laddr[2] & 1;
+ }
+
+ /*
+ * Prevent writes to uninitialized FLASH.
+ */
+ if (info->flash_id != FLASH_UNKNOWN) {
+ caddr = (volatile unsigned char *)info->start[0];
+
+ flash_cmd(portwidth,caddr,0,0xF0); /* reset bank */
+ }
+
+ return (info->size);
+}
+
+/* TODO: 2x16 unsupported */
+int
+flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ volatile unsigned char *addr = (uchar *)(info->start[0]);
+ int flag, prot, sect, l_sect;
+ ulong start, now, last;
+
+ /* TODO: 2x16 unsupported */
+ if(info->portwidth==4) return 1;
+
+ if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 1;
+ if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
+ for (sect = s_first; sect<=s_last; sect++) {
+ int sector_size=info->size/info->sector_count;
+ addr = (uchar *)(info->start[sect]);
+ memset((void *)addr, 0, sector_size);
+ }
+ return 0;
+ }
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("- missing\n");
+ } else {
+ printf ("- no sectors to erase\n");
+ }
+ return 1;
+ }
+
+ if ((info->flash_id&FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+ return flash_erase_intel(info,
+ (unsigned short)s_first,
+ (unsigned short)s_last);
+ }
+
+#if 0
+ if ((info->flash_id == FLASH_UNKNOWN) ||
+ (info->flash_id > FLASH_AMD_COMP)) {
+ printf ("Can't erase unknown flash type %08lx - aborted\n",
+ info->flash_id);
+ return 1;
+ }
+#endif
+
+ 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");
+ }
+
+ l_sect = -1;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ flash_cmd(info->portwidth,addr,0x555,0xAA);
+ flash_cmd(info->portwidth,addr,0x2AA,0x55);
+ flash_cmd(info->portwidth,addr,0x555,0x80);
+ flash_cmd(info->portwidth,addr,0x555,0xAA);
+ flash_cmd(info->portwidth,addr,0x2AA,0x55);
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ addr = (uchar *)(info->start[sect]);
+ flash_cmd(info->portwidth,addr,0,0x30);
+ l_sect = sect;
+ }
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ /*
+ * We wait for the last triggered sector
+ */
+ if (l_sect < 0)
+ goto DONE;
+
+ start = get_timer (0);
+ last = start;
+ addr = (volatile unsigned char *)(info->start[l_sect]);
+ /* broken for 2x16: TODO */
+ while ((addr[0] & 0x80) != 0x80) {
+ if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
+ printf ("Timeout\n");
+ return 1;
+ }
+ /* show that we're waiting */
+ if ((now - last) > 1000) { /* every second */
+ putc ('.');
+ last = now;
+ }
+ }
+
+DONE:
+ /* reset to read mode */
+ addr = (volatile unsigned char *)info->start[0];
+ flash_cmd(info->portwidth,addr,0,0xf0);
+ flash_cmd(info->portwidth,addr,0,0xf0);
+
+ printf (" done\n");
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+/* broken for 2x16: TODO */
+int
+write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ ulong cp, wp, data;
+ int i, l, rc;
+
+ if(info->portwidth==4) return 1;
+
+ if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 0;
+ if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
+ memcpy((void *)addr, src, cnt);
+ return 0;
+ }
+
+ 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);
+ }
+ for (; i<4 && cnt>0; ++i) {
+ data = (data << 8) | *src++;
+ --cnt;
+ ++cp;
+ }
+ for (; cnt==0 && i<4; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 4;
+ }
+
+ /*
+ * handle word aligned part
+ */
+ while (cnt >= 4) {
+ data = 0;
+ for (i=0; i<4; ++i) {
+ data = (data << 8) | *src++;
+ }
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 4;
+ cnt -= 4;
+ }
+
+ if (cnt == 0) {
+ return (0);
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ data = 0;
+ for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+ data = (data << 8) | *src++;
+ --cnt;
+ }
+ for (; i<4; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+
+ return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+/* broken for 2x16: TODO */
+static int
+write_word (flash_info_t *info, ulong dest, ulong data)
+{
+ volatile unsigned char *addr = (uchar *)(info->start[0]);
+ ulong start;
+ int flag, i;
+
+ if(info->portwidth==4) return 1;
+
+ if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 1;
+ if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
+ *(unsigned long *)dest=data;
+ return 0;
+ }
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+ unsigned short low = data & 0xffff;
+ unsigned short hi = (data >> 16) & 0xffff;
+ int ret = write_word_intel((bank_addr_t)dest, hi);
+
+ if (!ret) ret = write_word_intel((bank_addr_t)(dest+2), low);
+
+ return ret;
+ }
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*((vu_long *)dest) & data) != data) {
+ return (2);
+ }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ /* first, perform an unlock bypass command to speed up flash writes */
+ addr[0x555] = 0xAA;
+ addr[0x2AA] = 0x55;
+ addr[0x555] = 0x20;
+
+ /* write each byte out */
+ for (i = 0; i < 4; i++) {
+ char *data_ch = (char *)&data;
+ addr[0] = 0xA0;
+ *(((char *)dest)+i) = data_ch[i];
+ udelay(10); /* XXX */
+ }
+
+ /* we're done, now do an unlock bypass reset */
+ addr[0] = 0x90;
+ addr[0] = 0x00;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* data polling for D7 */
+ start = get_timer (0);
+ while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+ if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
+ return (1);
+ }
+ }
+ return (0);
+}
diff --git a/board/evb64260/i2c.c b/board/evb64260/i2c.c
new file mode 100644
index 0000000..8119fce
--- /dev/null
+++ b/board/evb64260/i2c.c
@@ -0,0 +1,310 @@
+#include <common.h>
+#include <mpc8xx.h>
+#include <malloc.h>
+#include <galileo/gt64260R.h>
+#include <galileo/core.h>
+
+#define MAX_I2C_RETRYS 10
+#define I2C_DELAY 1000 /* Should be at least the # of MHz of Tclk */
+#undef DEBUG_I2C
+
+#ifdef DEBUG_I2C
+#define DP(x) x
+#else
+#define DP(x)
+#endif
+
+/* Assuming that there is only one master on the bus (us) */
+
+static void
+i2c_init(int speed, int slaveaddr)
+{
+ unsigned int n, m, freq, margin, power;
+ unsigned int actualn = 0, actualm = 0;
+ unsigned int control, status;
+ unsigned int minmargin = 0xffffffff;
+ unsigned int tclk = 125000000;
+
+ DP(puts("i2c_init\n"));
+
+ for (n = 0 ; n < 8 ; n++) {
+ for (m = 0 ; m < 16 ; m++) {
+ power = 2 << n; /* power = 2^(n+1) */
+ freq = tclk / (10 * (m + 1) * power);
+ if (speed > freq)
+ margin = speed - freq;
+ else
+ margin = freq - speed;
+ if (margin < minmargin) {
+ minmargin = margin;
+ actualn = n;
+ actualm = m;
+ }
+ }
+ }
+
+ DP(puts("setup i2c bus\n"));
+
+ /* Setup bus */
+
+ GT_REG_WRITE(I2C_SOFT_RESET, 0);
+
+ DP(puts("udelay...\n"));
+
+ udelay(I2C_DELAY);
+
+ DP(puts("set baudrate\n"));
+
+ GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualm << 3) | actualn);
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
+
+ udelay(I2C_DELAY * 10);
+
+ DP(puts("read control, baudrate\n"));
+
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ GT_REG_READ(I2C_CONTROL, &control);
+}
+
+static uchar
+i2c_start(void)
+{
+ unsigned int control, status;
+ int count = 0;
+
+ DP(puts("i2c_start\n"));
+
+ /* Set the start bit */
+
+ GT_REG_READ(I2C_CONTROL, &control);
+ control |= (0x1 << 5);
+ GT_REG_WRITE(I2C_CONTROL, control);
+
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+
+ count = 0;
+ while ((status & 0xff) != 0x08) {
+ udelay(I2C_DELAY);
+ if (count > 20) {
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+ return status;
+ }
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ count++;
+ }
+
+ return 0;
+}
+
+static uchar
+i2c_select_device(uchar dev_addr, uchar read, int ten_bit)
+{
+ unsigned int status, data, bits = 7;
+ int count = 0;
+
+ DP(puts("i2c_select_device\n"));
+
+ /* Output slave address */
+
+ if (ten_bit)
+ bits = 10;
+
+ data = (dev_addr << 1);
+ /* set the read bit */
+ data |= read;
+ GT_REG_WRITE(I2C_DATA, data);
+ /* assert the address */
+ RESET_REG_BITS(I2C_CONTROL, BIT3);
+
+ udelay(I2C_DELAY);
+
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ count = 0;
+ while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
+ udelay(I2C_DELAY);
+ if (count > 20) {
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+ return status;
+ }
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ count++;
+ }
+
+ if (bits == 10) {
+ printf("10 bit I2C addressing not yet implemented\n");
+ return 0xff;
+ }
+
+ return 0;
+}
+
+static uchar
+i2c_get_data(uchar *return_data, int len) {
+
+ unsigned int data, status = 0;
+ int count = 0;
+
+ DP(puts("i2c_get_data\n"));
+
+ while (len) {
+
+ /* Get and return the data */
+
+ RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
+
+ udelay(I2C_DELAY * 5);
+
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ count++;
+ while ((status & 0xff) != 0x50) {
+ udelay(I2C_DELAY);
+ if (count > 2) {
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+ return 0;
+ }
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ count++;
+ }
+ GT_REG_READ(I2C_DATA, &data);
+ len--;
+ *return_data = (uchar)data;
+ return_data++;
+ }
+ RESET_REG_BITS(I2C_CONTROL, BIT2|BIT3);
+ while ((status & 0xff) != 0x58) {
+ udelay(I2C_DELAY);
+ if (count > 200) {
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+ return status;
+ }
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ count++;
+ }
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /* stop */
+
+ return 0;
+}
+
+static uchar
+i2c_write_data(unsigned int data, int len)
+{
+ unsigned int status;
+ int count = 0;
+
+ DP(puts("i2c_write_data\n"));
+
+ if (len > 4)
+ return -1;
+
+ while (len) {
+ /* Set and assert the data */
+
+ GT_REG_WRITE(I2C_DATA, (unsigned int)data);
+ RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
+
+ udelay(I2C_DELAY);
+
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ count++;
+ while ((status & 0xff) != 0x28) {
+ udelay(I2C_DELAY);
+ if (count > 20) {
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+ return status;
+ }
+ GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+ count++;
+ }
+ len--;
+ }
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4));
+ GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
+
+ udelay(I2C_DELAY * 10);
+
+ return 0;
+}
+
+static uchar
+i2c_set_dev_offset(uchar dev_addr, unsigned int offset, int ten_bit)
+{
+ uchar status;
+
+ DP(puts("i2c_set_dev_offset\n"));
+
+ status = i2c_select_device(dev_addr, 0, ten_bit);
+ if (status) {
+#ifdef DEBUG_I2C
+ printf("Failed to select device setting offset: 0x%02x\n",
+ status);
+#endif
+ return status;
+ }
+
+ status = i2c_write_data(offset, 1);
+ if (status) {
+#ifdef DEBUG_I2C
+ printf("Failed to write data: 0x%02x\n", status);
+#endif
+ return status;
+ }
+
+ return 0;
+}
+
+uchar
+i2c_read(uchar dev_addr, unsigned int offset, int len, uchar *data,
+ int ten_bit)
+{
+ uchar status = 0;
+ unsigned int i2cfreq = 400000;
+
+ DP(puts("i2c_read\n"));
+
+ i2c_init(i2cfreq, 0);
+
+ status = i2c_start();
+
+ if (status) {
+#ifdef DEBUG_I2C
+ printf("Transaction start failed: 0x%02x\n", status);
+#endif
+ return status;
+ }
+
+ status = i2c_set_dev_offset(dev_addr, 0, 0);
+ if (status) {
+#ifdef DEBUG_I2C
+ printf("Failed to set offset: 0x%02x\n", status);
+#endif
+ return status;
+ }
+
+ i2c_init(i2cfreq, 0);
+
+ status = i2c_start();
+ if (status) {
+#ifdef DEBUG_I2C
+ printf("Transaction restart failed: 0x%02x\n", status);
+#endif
+ return status;
+ }
+
+ status = i2c_select_device(dev_addr, 1, ten_bit);
+ if (status) {
+#ifdef DEBUG_I2C
+ printf("Address not acknowledged: 0x%02x\n", status);
+#endif
+ return status;
+ }
+
+ status = i2c_get_data(data, len);
+ if (status) {
+#ifdef DEBUG_I2C
+ printf("Data not received: 0x%02x\n", status);
+#endif
+ return status;
+ }
+
+ return 0;
+}
diff --git a/board/evb64260/i2c.h b/board/evb64260/i2c.h
new file mode 100644
index 0000000..9c21992
--- /dev/null
+++ b/board/evb64260/i2c.h
@@ -0,0 +1,7 @@
+#ifndef __I2C_H__
+#define __I2C_H__
+
+/* function declarations */
+uchar i2c_read(uchar, unsigned int, int, uchar*, int);
+
+#endif
diff --git a/board/evb64260/intel_flash.c b/board/evb64260/intel_flash.c
new file mode 100644
index 0000000..994264a
--- /dev/null
+++ b/board/evb64260/intel_flash.c
@@ -0,0 +1,277 @@
+/*
+ * (C) Copyright 2000
+ * 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
+ *
+ * Hacked for the Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <galileo/gt64260R.h>
+#include <galileo/memory.h>
+#include "intel_flash.h"
+
+
+/*-----------------------------------------------------------------------
+ * Protection Flags:
+ */
+#define FLAG_PROTECT_SET 0x01
+#define FLAG_PROTECT_CLEAR 0x02
+
+static void
+bank_reset(flash_info_t *info, int sect)
+{
+ bank_addr_t addrw, eaddrw;
+
+ addrw = (bank_addr_t)info->start[sect];
+ eaddrw = BANK_ADDR_NEXT_WORD(addrw);
+
+ while (addrw < eaddrw) {
+#ifdef FLASH_DEBUG
+ printf(" writing reset cmd to addr 0x%08lx\n",
+ (unsigned long)addrw);
+#endif
+ *addrw = BANK_CMD_RST;
+ addrw++;
+ }
+}
+
+static void
+bank_erase_init(flash_info_t *info, int sect)
+{
+ bank_addr_t addrw, saddrw, eaddrw;
+ int flag;
+
+#ifdef FLASH_DEBUG
+ printf("0x%08x BANK_CMD_PROG\n", BANK_CMD_PROG);
+ printf("0x%08x BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);
+ printf("0x%08x BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);
+ printf("0x%08x BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);
+ printf("0x%08x BANK_CMD_RST\n", BANK_CMD_RST);
+ printf("0x%08x BANK_STAT_RDY\n", BANK_STAT_RDY);
+ printf("0x%08x BANK_STAT_ERR\n", BANK_STAT_ERR);
+#endif
+
+ saddrw = (bank_addr_t)info->start[sect];
+ eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
+
+#ifdef FLASH_DEBUG
+ printf("erasing sector %d, start addr = 0x%08lx "
+ "(bank next word addr = 0x%08lx)\n", sect,
+ (unsigned long)saddrw, (unsigned long)eaddrw);
+#endif
+
+ /* Disable intrs which might cause a timeout here */
+ flag = disable_interrupts();
+
+ for (addrw = saddrw; addrw < eaddrw; addrw++) {
+#ifdef FLASH_DEBUG
+ printf(" writing erase cmd to addr 0x%08lx\n",
+ (unsigned long)addrw);
+#endif
+ *addrw = BANK_CMD_ERASE1;
+ *addrw = BANK_CMD_ERASE2;
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+}
+
+static int
+bank_erase_poll(flash_info_t *info, int sect)
+{
+ bank_addr_t addrw, saddrw, eaddrw;
+ int sectdone, haderr;
+
+ saddrw = (bank_addr_t)info->start[sect];
+ eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
+
+ sectdone = 1;
+ haderr = 0;
+
+ for (addrw = saddrw; addrw < eaddrw; addrw++) {
+ bank_word_t stat = *addrw;
+
+#ifdef FLASH_DEBUG
+ printf(" checking status at addr "
+ "0x%08x [0x%08x]\n",
+ (unsigned long)addrw, stat);
+#endif
+ if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)
+ sectdone = 0;
+ else if ((stat & BANK_STAT_ERR) != 0) {
+ printf(" failed on sector %d "
+ "(stat = 0x%08x) at "
+ "address 0x%p\n",
+ sect, stat, addrw);
+ *addrw = BANK_CMD_CLR_STAT;
+ haderr = 1;
+ }
+ }
+
+ if (haderr)
+ return (-1);
+ else
+ return (sectdone);
+}
+
+int
+write_word_intel(bank_addr_t addr, bank_word_t value)
+{
+ bank_word_t stat;
+ ulong start;
+ int flag, retval;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ *addr = BANK_CMD_PROG;
+
+ *addr = value;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ retval = 0;
+
+ /* data polling for D7 */
+ start = get_timer (0);
+ do {
+ if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
+ retval = 1;
+ goto done;
+ }
+ stat = *addr;
+ } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
+
+ if ((stat & BANK_STAT_ERR) != 0) {
+ printf("flash program failed (stat = 0x%08lx) "
+ "at address 0x%08lx\n", (ulong)stat, (ulong)addr);
+ *addr = BANK_CMD_CLR_STAT;
+ retval = 3;
+ }
+
+done:
+ /* reset to read mode */
+ *addr = BANK_CMD_RST;
+
+ return (retval);
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int
+flash_erase_intel(flash_info_t *info, int s_first, int s_last)
+{
+ int prot, sect, haderr;
+ ulong start, now, last;
+
+#ifdef FLASH_DEBUG
+ printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
+ " Bank # %d: ", s_last - s_first + 1, s_first, s_last,
+ (info - flash_info) + 1);
+ flash_print_info(info);
+#endif
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("- missing\n");
+ } else {
+ printf ("- no sectors to erase\n");
+ }
+ return 1;
+ }
+
+ prot = 0;
+ for (sect=s_first; sect<=s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+
+ if (prot) {
+ printf("- Warning: %d protected sector%s will not be erased!\n",
+ prot, (prot > 1 ? "s" : ""));
+ }
+
+ start = get_timer (0);
+ last = 0;
+ haderr = 0;
+
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ ulong estart;
+ int sectdone;
+
+ bank_erase_init(info, sect);
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ estart = get_timer(start);
+
+ do {
+ now = get_timer(start);
+
+ if (now - estart > CONFIG_SYS_FLASH_ERASE_TOUT) {
+ printf ("Timeout (sect %d)\n", sect);
+ haderr = 1;
+ break;
+ }
+
+#ifndef FLASH_DEBUG
+ /* show that we're waiting */
+ if ((now - last) > 1000) { /* every second */
+ putc ('.');
+ last = now;
+ }
+#endif
+
+ sectdone = bank_erase_poll(info, sect);
+
+ if (sectdone < 0) {
+ haderr = 1;
+ break;
+ }
+
+ } while (!sectdone);
+
+ if (haderr)
+ break;
+ }
+ }
+
+ if (haderr > 0)
+ printf (" failed\n");
+ else
+ printf (" done\n");
+
+ /* reset to read mode */
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ bank_reset(info, sect);
+ }
+ }
+ return haderr;
+}
diff --git a/board/evb64260/intel_flash.h b/board/evb64260/intel_flash.h
new file mode 100644
index 0000000..cc3a339
--- /dev/null
+++ b/board/evb64260/intel_flash.h
@@ -0,0 +1,160 @@
+/*************** DEFINES for Intel StrataFlash FLASH chip ********************/
+
+/*
+ * acceptable chips types are:
+ *
+ * 28F320J5, 28F640J5, 28F320J3A, 28F640J3A and 28F128J3A
+ */
+
+/* register addresses, valid only following an CHIP_CMD_RD_ID command */
+#define CHIP_ADDR_REG_MAN 0x000000 /* manufacturer's id */
+#define CHIP_ADDR_REG_DEV 0x000001 /* device id */
+#define CHIP_ADDR_REG_CFGM 0x000003 /* master lock config */
+#define CHIP_ADDR_REG_CFG(b) (((b)<<16)|2) /* lock config for block b */
+
+/* Commands */
+#define CHIP_CMD_RST 0xFF /* reset flash */
+#define CHIP_CMD_RD_ID 0x90 /* read the id and lock bits */
+#define CHIP_CMD_RD_QUERY 0x98 /* read device capabilities */
+#define CHIP_CMD_RD_STAT 0x70 /* read the status register */
+#define CHIP_CMD_CLR_STAT 0x50 /* clear the staus register */
+#define CHIP_CMD_WR_BUF 0xE8 /* clear the staus register */
+#define CHIP_CMD_PROG 0x40 /* program word command */
+#define CHIP_CMD_ERASE1 0x20 /* 1st word for block erase */
+#define CHIP_CMD_ERASE2 0xD0 /* 2nd word for block erase */
+#define CHIP_CMD_ERASE_SUSP 0xB0 /* suspend block erase */
+#define CHIP_CMD_LOCK 0x60 /* 1st word for all lock cmds */
+#define CHIP_CMD_SET_LOCK_BLK 0x01 /* 2nd wrd set block lock bit */
+#define CHIP_CMD_SET_LOCK_MSTR 0xF1 /* 2nd wrd set master lck bit */
+#define CHIP_CMD_CLR_LOCK_BLK 0xD0 /* 2nd wrd clear blk lck bit */
+
+/* status register bits */
+#define CHIP_STAT_DPS 0x02 /* Device Protect Status */
+#define CHIP_STAT_VPPS 0x08 /* VPP Status */
+#define CHIP_STAT_PSLBS 0x10 /* Program+Set Lock Bit Stat */
+#define CHIP_STAT_ECLBS 0x20 /* Erase+Clr Lock Bit Stat */
+#define CHIP_STAT_ESS 0x40 /* Erase Suspend Status */
+#define CHIP_STAT_RDY 0x80 /* WSM Mach Status, 1=rdy */
+
+#define CHIP_STAT_ERR (CHIP_STAT_VPPS | CHIP_STAT_DPS | \
+ CHIP_STAT_ECLBS | CHIP_STAT_PSLBS)
+
+/* ID and Lock Configuration */
+#define CHIP_RD_ID_LOCK 0x01 /* Bit 0 of each byte */
+#define CHIP_RD_ID_MAN 0x89 /* Manufacturer code = 0x89 */
+#define CHIP_RD_ID_DEV CONFIG_SYS_FLASH_ID
+
+/* dimensions */
+#define CHIP_WIDTH 2 /* chips are in 16 bit mode */
+#define CHIP_WSHIFT 1 /* (log2 of CHIP_WIDTH) */
+#define CHIP_NBLOCKS 128
+#define CHIP_BLKSZ (128 * 1024) /* of 128Kbytes each */
+#define CHIP_SIZE (CHIP_BLKSZ * CHIP_NBLOCKS)
+
+/********************** DEFINES for Hymod Flash ******************************/
+
+/*
+ * The hymod board has 2 x 28F320J5 chips running in
+ * 16 bit mode, for a 32 bit wide bank.
+ */
+
+typedef unsigned short bank_word_t; /* 8/16/32/64bit unsigned int */
+typedef volatile bank_word_t *bank_addr_t;
+typedef unsigned long bank_size_t; /* want this big - >= 32 bit */
+
+#define BANK_CHIP_WIDTH 1 /* each bank is 1 chip wide */
+#define BANK_CHIP_WSHIFT 0 /* (log2 of BANK_CHIP_WIDTH) */
+
+#define BANK_WIDTH (CHIP_WIDTH * BANK_CHIP_WIDTH)
+#define BANK_WSHIFT (CHIP_WSHIFT + BANK_CHIP_WSHIFT)
+#define BANK_NBLOCKS CHIP_NBLOCKS
+#define BANK_BLKSZ (CHIP_BLKSZ * BANK_CHIP_WIDTH)
+#define BANK_SIZE (CHIP_SIZE * BANK_CHIP_WIDTH)
+
+#define MAX_BANKS 1 /* only one bank possible */
+
+/* align bank addresses and sizes to bank word boundaries */
+#define BANK_ADDR_WORD_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \
+ & ~(BANK_WIDTH - 1)))
+#define BANK_SIZE_WORD_ALIGN(s) ((bank_size_t)BANK_ADDR_WORD_ALIGN( \
+ (bank_size_t)(s) + (BANK_WIDTH - 1)))
+
+/* align bank addresses and sizes to bank block boundaries */
+#define BANK_ADDR_BLK_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \
+ & ~(BANK_BLKSZ - 1)))
+#define BANK_SIZE_BLK_ALIGN(s) ((bank_size_t)BANK_ADDR_BLK_ALIGN( \
+ (bank_size_t)(s) + (BANK_BLKSZ - 1)))
+
+/* align bank addresses and sizes to bank boundaries */
+#define BANK_ADDR_BANK_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \
+ & ~(BANK_SIZE - 1)))
+#define BANK_SIZE_BANK_ALIGN(s) ((bank_size_t)BANK_ADDR_BANK_ALIGN( \
+ (bank_size_t)(s) + (BANK_SIZE - 1)))
+
+/* add an offset to a bank address */
+#define BANK_ADDR_OFFSET(a, o) (bank_addr_t)((bank_size_t)(a) + \
+ (bank_size_t)(o))
+
+/* get base address of bank b, given flash base address a */
+#define BANK_ADDR_BASE(a, b) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \
+ (bank_size_t)(b) * BANK_SIZE)
+
+/* adjust a bank address to start of next word, block or bank */
+#define BANK_ADDR_NEXT_WORD(a) BANK_ADDR_OFFSET(BANK_ADDR_WORD_ALIGN(a), \
+ BANK_WIDTH)
+#define BANK_ADDR_NEXT_BLK(a) BANK_ADDR_OFFSET(BANK_ADDR_BLK_ALIGN(a), \
+ BANK_BLKSZ)
+#define BANK_ADDR_NEXT_BANK(a) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \
+ BANK_SIZE)
+
+/* get bank address of chip register r given a bank base address a */
+#define BANK_ADDR_REG(a, r) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \
+ ((bank_size_t)(r) << BANK_WSHIFT))
+
+/* make a bank address for each chip register address */
+
+#define BANK_ADDR_REG_MAN(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_MAN)
+#define BANK_ADDR_REG_DEV(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_DEV)
+#define BANK_ADDR_REG_CFGM(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_CFGM)
+#define BANK_ADDR_REG_CFG(b,a) BANK_ADDR_REG((a), CHIP_ADDR_REG_CFG(b))
+
+/*
+ * replicate a chip cmd/stat/rd value into each byte position within a word
+ * so that multiple chips are accessed in a single word i/o operation
+ *
+ * this must be as wide as the bank_word_t type, and take into account the
+ * chip width and bank layout
+ */
+
+#define BANK_FILL_WORD(o) ((bank_word_t)(o))
+
+/* make a bank word value for each chip cmd/stat/rd value */
+
+/* Commands */
+#define BANK_CMD_RST BANK_FILL_WORD(CHIP_CMD_RST)
+#define BANK_CMD_RD_ID BANK_FILL_WORD(CHIP_CMD_RD_ID)
+#define BANK_CMD_RD_STAT BANK_FILL_WORD(CHIP_CMD_RD_STAT)
+#define BANK_CMD_CLR_STAT BANK_FILL_WORD(CHIP_CMD_CLR_STAT)
+#define BANK_CMD_ERASE1 BANK_FILL_WORD(CHIP_CMD_ERASE1)
+#define BANK_CMD_ERASE2 BANK_FILL_WORD(CHIP_CMD_ERASE2)
+#define BANK_CMD_PROG BANK_FILL_WORD(CHIP_CMD_PROG)
+#define BANK_CMD_LOCK BANK_FILL_WORD(CHIP_CMD_LOCK)
+#define BANK_CMD_SET_LOCK_BLK BANK_FILL_WORD(CHIP_CMD_SET_LOCK_BLK)
+#define BANK_CMD_SET_LOCK_MSTR BANK_FILL_WORD(CHIP_CMD_SET_LOCK_MSTR)
+#define BANK_CMD_CLR_LOCK_BLK BANK_FILL_WORD(CHIP_CMD_CLR_LOCK_BLK)
+
+/* status register bits */
+#define BANK_STAT_DPS BANK_FILL_WORD(CHIP_STAT_DPS)
+#define BANK_STAT_PSS BANK_FILL_WORD(CHIP_STAT_PSS)
+#define BANK_STAT_VPPS BANK_FILL_WORD(CHIP_STAT_VPPS)
+#define BANK_STAT_PSLBS BANK_FILL_WORD(CHIP_STAT_PSLBS)
+#define BANK_STAT_ECLBS BANK_FILL_WORD(CHIP_STAT_ECLBS)
+#define BANK_STAT_ESS BANK_FILL_WORD(CHIP_STAT_ESS)
+#define BANK_STAT_RDY BANK_FILL_WORD(CHIP_STAT_RDY)
+
+#define BANK_STAT_ERR BANK_FILL_WORD(CHIP_STAT_ERR)
+
+/* ID and Lock Configuration */
+#define BANK_RD_ID_LOCK BANK_FILL_WORD(CHIP_RD_ID_LOCK)
+#define BANK_RD_ID_MAN BANK_FILL_WORD(CHIP_RD_ID_MAN)
+#define BANK_RD_ID_DEV BANK_FILL_WORD(CHIP_RD_ID_DEV)
diff --git a/board/evb64260/local.h b/board/evb64260/local.h
new file mode 100644
index 0000000..8a3f4b2
--- /dev/null
+++ b/board/evb64260/local.h
@@ -0,0 +1,62 @@
+/*
+ * include/local.h - local configuration options, board specific
+ */
+
+#ifndef __LOCAL_H
+#define __LOCAL_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+/* This tells U-Boot that the config options are compiled in */
+/* #undef ENV_IS_EMBEDDED */
+/* Don't touch this! U-Boot figures this out based on other
+ * magic. */
+
+/* Uncomment and define any of the below options */
+
+/* #define CONFIG_750CX */ /* The 750CX doesn't support as many things in L2CR */
+ /* Note: If you defined CONFIG_EVB64260_750CX this */
+ /* gets defined automatically. */
+
+/* These want string arguments */
+/* #define CONFIG_BOOTARGS */
+/* #define CONFIG_BOOTCOMMAND */
+/* #define CONFIG_RAMBOOTCOMMAND */
+/* #define CONFIG_NFSBOOTCOMMAND */
+/* #define CONFIG_SYS_AUTOLOAD */
+/* #define CONFIG_PREBOOT */
+
+/* These don't */
+
+/* #define CONFIG_BOOTDELAY */
+/* #define CONFIG_BAUDRATE */
+/* #define CONFIG_LOADS_ECHO */
+/* #define CONFIG_ETHADDR */
+/* #define CONFIG_ETH2ADDR */
+/* #define CONFIG_ETH3ADDR */
+/* #define CONFIG_IPADDR */
+/* #define CONFIG_SERVERIP */
+/* #define CONFIG_ROOTPATH */
+/* #define CONFIG_GATEWAYIP */
+/* #define CONFIG_NETMASK */
+/* #define CONFIG_HOSTNAME */
+/* #define CONFIG_BOOTFILE */
+/* #define CONFIG_LOADADDR */
+
+/* these hardware addresses are pretty bogus, please change them to
+ suit your needs */
+
+/* first ethernet */
+#define CONFIG_ETHADDR 00:11:22:33:44:55
+
+/* next two ethernet hwaddrs */
+#define CONFIG_HAS_ETH1
+#define CONFIG_ETH1ADDR 00:11:22:33:44:66
+#define CONFIG_HAS_ETH2
+#define CONFIG_ETH2ADDR 00:11:22:33:44:77
+
+#define CONFIG_ENV_OVERWRITE
+#endif /* __CONFIG_H */
diff --git a/board/evb64260/memory.c b/board/evb64260/memory.c
new file mode 100644
index 0000000..e339854
--- /dev/null
+++ b/board/evb64260/memory.c
@@ -0,0 +1,457 @@
+/* Memory.c - Memory mappings and remapping functions */
+
+/* Copyright - Galileo technology. */
+
+/* modified by Josh Huber to clean some things up, and
+ * fit it into the U-Boot framework */
+
+#include <galileo/core.h>
+#include <galileo/memory.h>
+
+/********************************************************************
+* memoryGetBankBaseAddress - Gets the base address of a memory bank
+* - If the memory bank size is 0 then this base address has no meaning!!!
+*
+*
+* INPUTS: MEMORY_BANK bank - The bank we ask for its base Address.
+* OUTPUT: N/A
+* RETURNS: Memory bank base address.
+*********************************************************************/
+static unsigned long memoryGetBankRegOffset(MEMORY_BANK bank)
+{
+ switch (bank)
+ {
+ case BANK0:
+ return SCS_0_LOW_DECODE_ADDRESS;
+ case BANK1:
+ return SCS_1_LOW_DECODE_ADDRESS;
+ case BANK2:
+ return SCS_2_LOW_DECODE_ADDRESS;
+ case BANK3:
+ return SCS_3_LOW_DECODE_ADDRESS;
+ }
+ return SCS_0_LOW_DECODE_ADDRESS; /* default value */
+}
+
+unsigned int memoryGetBankBaseAddress(MEMORY_BANK bank)
+{
+ unsigned int base;
+ unsigned int regOffset=memoryGetBankRegOffset(bank);
+
+ GT_REG_READ(regOffset,&base);
+ base = base << 20;
+ return base;
+}
+
+/********************************************************************
+* memoryGetDeviceBaseAddress - Gets the base address of a device.
+* - If the device size is 0 then this base address has no meaning!!!
+*
+*
+* INPUT: DEVICE device - The device we ask for its base address.
+* OUTPUT: N/A
+* RETURNS: Device base address.
+*********************************************************************/
+static unsigned int memoryGetDeviceRegOffset(DEVICE device)
+{
+ switch (device)
+ {
+ case DEVICE0:
+ return CS_0_LOW_DECODE_ADDRESS;
+ case DEVICE1:
+ return CS_1_LOW_DECODE_ADDRESS;
+ case DEVICE2:
+ return CS_2_LOW_DECODE_ADDRESS;
+ case DEVICE3:
+ return CS_3_LOW_DECODE_ADDRESS;
+ case BOOT_DEVICE:
+ return BOOTCS_LOW_DECODE_ADDRESS;
+ }
+ return CS_0_LOW_DECODE_ADDRESS; /* default value */
+}
+
+unsigned int memoryGetDeviceBaseAddress(DEVICE device)
+{
+ unsigned int regBase;
+ unsigned int regEnd;
+ unsigned int regOffset=memoryGetDeviceRegOffset(device);
+
+ GT_REG_READ(regOffset, &regBase);
+ GT_REG_READ(regOffset+8, &regEnd);
+
+ if(regEnd<=regBase) return 0xffffffff; /* ERROR !!! */
+
+ regBase = regBase << 20;
+ return regBase;
+}
+
+/********************************************************************
+* memoryGetBankSize - Returns the size of a memory bank.
+*
+*
+* INPUT: MEMORY_BANK bank - The bank we ask for its size.
+* OUTPUT: N/A
+* RETURNS: Memory bank size.
+*********************************************************************/
+unsigned int memoryGetBankSize(MEMORY_BANK bank)
+{
+ unsigned int size,base;
+ unsigned int highValue;
+ unsigned int highAddress=memoryGetBankRegOffset(bank)+8;
+
+ base = memoryGetBankBaseAddress(bank);
+ GT_REG_READ(highAddress,&highValue);
+ highValue = (highValue + 1) << 20;
+ if(base > highValue)
+ size=0;
+ else
+ size = highValue - base;
+ return size;
+}
+
+/********************************************************************
+* memoryGetDeviceSize - Returns the size of a device memory space
+*
+*
+* INPUT: DEVICE device - The device we ask for its base address.
+* OUTPUT: N/A
+* RETURNS: Size of a device memory space.
+*********************************************************************/
+unsigned int memoryGetDeviceSize(DEVICE device)
+{
+ unsigned int size,base;
+ unsigned int highValue;
+ unsigned int highAddress=memoryGetDeviceRegOffset(device)+8;
+
+ base = memoryGetDeviceBaseAddress(device);
+ GT_REG_READ(highAddress,&highValue);
+ if (highValue == 0xfff)
+ {
+ size = (~base) + 1; /* what the heck is this? */
+ return size;
+ }
+ else
+ highValue = (highValue + 1) << 20;
+
+ if(base > highValue)
+ size=0;
+ else
+ size = highValue - base;
+ return size;
+}
+
+/********************************************************************
+* memoryGetDeviceWidth - A device can be with: 1,2,4 or 8 Bytes data width.
+* The width is determine in registers: 'Device Parameters'
+* registers (0x45c, 0x460, 0x464, 0x468, 0x46c - for each device.
+* at bits: [21:20].
+*
+* INPUT: DEVICE device - Device number
+* OUTPUT: N/A
+* RETURNS: Device width in Bytes (1,2,4 or 8), 0 if error had occurred.
+*********************************************************************/
+unsigned int memoryGetDeviceWidth(DEVICE device)
+{
+ unsigned int width;
+ unsigned int regValue;
+
+ GT_REG_READ(DEVICE_BANK0PARAMETERS + device*4,&regValue);
+ width = (regValue & 0x00300000) >> 20;
+ switch (width)
+ {
+ case 0:
+ return 1;
+ case 1:
+ return 2;
+ case 2:
+ return 4;
+ case 3:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+bool memoryMapBank(MEMORY_BANK bank, unsigned int bankBase,unsigned int bankLength)
+{
+ unsigned int low=0xfff;
+ unsigned int high=0x0;
+ unsigned int regOffset=memoryGetBankRegOffset(bank);
+
+ if(bankLength!=0) {
+ low = (bankBase >> 20) & 0xffff;
+ high=((bankBase+bankLength)>>20)-1;
+ }
+
+#ifdef DEBUG
+ {
+ unsigned int oldLow, oldHigh;
+ GT_REG_READ(regOffset,&oldLow);
+ GT_REG_READ(regOffset+8,&oldHigh);
+
+ printf("b%d %x-%x->%x-%x\n", bank, oldLow, oldHigh, low, high);
+ }
+#endif
+
+ GT_REG_WRITE(regOffset,low);
+ GT_REG_WRITE(regOffset+8,high);
+
+ return true;
+}
+bool memoryMapDeviceSpace(DEVICE device, unsigned int deviceBase,unsigned int deviceLength)
+{
+ /* TODO: what are appropriate "unmapped" values? */
+ unsigned int low=0xfff;
+ unsigned int high=0x0;
+ unsigned int regOffset=memoryGetDeviceRegOffset(device);
+
+ if(deviceLength != 0) {
+ low=deviceBase>>20;
+ high=((deviceBase+deviceLength)>>20)-1;
+ } else {
+ /* big problems in here... */
+ /* this will HANG */
+ }
+
+ GT_REG_WRITE(regOffset,low);
+ GT_REG_WRITE(regOffset+8,high);
+
+ return true;
+}
+
+
+/********************************************************************
+* memoryMapInternalRegistersSpace - Sets new base address for the internals
+* registers.
+*
+* INPUTS: unsigned int internalRegBase - The new base address.
+* RETURNS: true on success, false on failure
+*********************************************************************/
+bool memoryMapInternalRegistersSpace(unsigned int internalRegBase)
+{
+ unsigned int currentValue;
+ unsigned int internalValue = internalRegBase;
+
+ internalRegBase = (internalRegBase >> 20);
+ GT_REG_READ(INTERNAL_SPACE_DECODE,&currentValue);
+ internalRegBase = (currentValue & 0xffff0000) | internalRegBase;
+ GT_REG_WRITE(INTERNAL_SPACE_DECODE,internalRegBase);
+ INTERNAL_REG_BASE_ADDR = internalValue;
+ return true;
+}
+
+/********************************************************************
+* memoryGetInternalRegistersSpace - Gets internal registers Base Address.
+*
+* INPUTS: unsigned int internalRegBase - The new base address.
+* RETURNS: true on success, false on failure
+*********************************************************************/
+unsigned int memoryGetInternalRegistersSpace(void)
+{
+ return INTERNAL_REG_BASE_ADDR;
+}
+
+/********************************************************************
+* memorySetProtectRegion - This function modifys one of the 8 regions with
+* one of the three protection mode.
+* - Be advised to check the spec before modifying them.
+*
+*
+* Inputs: CPU_PROTECT_REGION - one of the eight regions.
+* CPU_ACCESS - general access.
+* CPU_WRITE - read only access.
+* CPU_CACHE_PROTECT - chache access.
+* we defining CPU because there is another protect from the pci SIDE.
+* Returns: false if one of the parameters is wrong and true else
+*********************************************************************/
+bool memorySetProtectRegion(MEMORY_PROTECT_REGION region,
+ MEMORY_ACCESS memAccess,
+ MEMORY_ACCESS_WRITE memWrite,
+ MEMORY_CACHE_PROTECT cacheProtection,
+ unsigned int baseAddress,
+ unsigned int regionLength)
+{
+ unsigned int protectHigh = baseAddress + regionLength;
+
+ if(regionLength == 0) /* closing the region */
+ {
+ GT_REG_WRITE(CPU_LOW_PROTECT_ADDRESS_0 + 0x10*region,0x0000ffff);
+ GT_REG_WRITE(CPU_HIGH_PROTECT_ADDRESS_0 + 0x10*region,0);
+ return true;
+ }
+ baseAddress = (baseAddress & 0xfff00000) >> 20;
+ baseAddress = baseAddress | memAccess << 16 | memWrite << 17
+ | cacheProtection << 18;
+ GT_REG_WRITE(CPU_LOW_PROTECT_ADDRESS_0 + 0x10*region,baseAddress);
+ protectHigh = (protectHigh & 0xfff00000) >> 20;
+ GT_REG_WRITE(CPU_HIGH_PROTECT_ADDRESS_0 + 0x10*region,protectHigh - 1);
+ return true;
+}
+
+/********************************************************************
+* memorySetRegionSnoopMode - This function modifys one of the 4 regions which
+* supports Cache Coherency.
+*
+*
+* Inputs: SNOOP_REGION region - One of the four regions.
+* SNOOP_TYPE snoopType - There is four optional Types:
+* 1. No Snoop.
+* 2. Snoop to WT region.
+* 3. Snoop to WB region.
+* 4. Snoop & Invalidate to WB region.
+* unsigned int baseAddress - Base Address of this region.
+* unsigned int topAddress - Top Address of this region.
+* Returns: false if one of the parameters is wrong and true else
+*********************************************************************/
+bool memorySetRegionSnoopMode(MEMORY_SNOOP_REGION region,
+ MEMORY_SNOOP_TYPE snoopType,
+ unsigned int baseAddress,
+ unsigned int regionLength)
+{
+ unsigned int snoopXbaseAddress;
+ unsigned int snoopXtopAddress;
+ unsigned int data;
+ unsigned int snoopHigh = baseAddress + regionLength;
+
+ if( (region > MEM_SNOOP_REGION3) || (snoopType > MEM_SNOOP_WB) )
+ return false;
+ snoopXbaseAddress = SNOOP_BASE_ADDRESS_0 + 0x10 * region;
+ snoopXtopAddress = SNOOP_TOP_ADDRESS_0 + 0x10 * region;
+ if(regionLength == 0) /* closing the region */
+ {
+ GT_REG_WRITE(snoopXbaseAddress,0x0000ffff);
+ GT_REG_WRITE(snoopXtopAddress,0);
+ return true;
+ }
+ baseAddress = baseAddress & 0xffff0000;
+ data = (baseAddress >> 16) | snoopType << 16;
+ GT_REG_WRITE(snoopXbaseAddress,data);
+ snoopHigh = (snoopHigh & 0xfff00000) >> 20;
+ GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1);
+ return true;
+}
+
+/********************************************************************
+* memoryRemapAddress - This fubction used for address remapping.
+*
+*
+* Inputs: regOffset: remap register
+* remapValue :
+* Returns: false if one of the parameters is erroneous,true otherwise.
+*********************************************************************/
+bool memoryRemapAddress(unsigned int remapReg, unsigned int remapValue)
+{
+ unsigned int valueForReg;
+ valueForReg = (remapValue & 0xfff00000) >> 20;
+ GT_REG_WRITE(remapReg, valueForReg);
+ return true;
+}
+
+/********************************************************************
+* memoryGetDeviceParam - This function used for getting device parameters from
+* DEVICE BANK PARAMETERS REGISTER
+*
+*
+* Inputs: - deviceParam: STRUCT with paramiters for DEVICE BANK
+* PARAMETERS REGISTER
+* - deviceNum : number of device
+* Returns: false if one of the parameters is erroneous,true otherwise.
+*********************************************************************/
+bool memoryGetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum)
+{
+ unsigned int valueOfReg;
+ unsigned int calcData;
+
+ GT_REG_READ(DEVICE_BANK0PARAMETERS + 4 * deviceNum, &valueOfReg);
+ calcData = (0x7 & valueOfReg) + ((0x400000 & valueOfReg) >> 19);
+ deviceParam -> turnOff = calcData; /* Turn Off */
+
+ calcData = ((0x78 & valueOfReg) >> 3) + ((0x800000 & valueOfReg) >> 19);
+ deviceParam -> acc2First = calcData; /* Access To First */
+
+ calcData = ((0x780 & valueOfReg) >> 7) + ((0x1000000 & valueOfReg) >> 20);
+ deviceParam -> acc2Next = calcData; /* Access To Next */
+
+ calcData = ((0x3800 & valueOfReg) >> 11) + ((0x2000000 & valueOfReg) >> 22);
+ deviceParam -> ale2Wr = calcData; /* Ale To Write */
+
+ calcData = ((0x1c000 & valueOfReg) >> 14) + ((0x4000000 & valueOfReg) >> 23);
+ deviceParam -> wrLow = calcData; /* Write Active */
+
+ calcData = ((0xe0000 & valueOfReg) >> 17) + ((0x8000000 & valueOfReg) >> 24);
+ deviceParam -> wrHigh = calcData; /* Write High */
+
+ calcData = ((0x300000 & valueOfReg) >> 20);
+ switch (calcData)
+ {
+ case 0:
+ deviceParam -> deviceWidth = 1; /* one Byte - 8-bit */
+ break;
+ case 1:
+ deviceParam -> deviceWidth = 2; /* two Bytes - 16-bit */
+ break;
+ case 2:
+ deviceParam -> deviceWidth = 4; /* four Bytes - 32-bit */
+ break;
+ case 3:
+ deviceParam -> deviceWidth = 8; /* eight Bytes - 64-bit */
+ break;
+ default:
+ deviceParam -> deviceWidth = 1;
+ break;
+ }
+ return true;
+}
+
+/********************************************************************
+* memorySetDeviceParam - This function used for setting device parameters to
+* DEVICE BANK PARAMETERS REGISTER
+*
+*
+* Inputs: - deviceParam: STRUCT for store paramiters from DEVICE BANK
+* PARAMETERS REGISTER
+* - deviceNum : number of device
+* Returns: false if one of the parameters is erroneous,true otherwise.
+*********************************************************************/
+bool memorySetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum)
+{
+ unsigned int valueForReg;
+
+ if((deviceParam -> turnOff >= 0xf) || (deviceParam -> acc2First >= 0x1f) ||
+ (deviceParam -> acc2Next >= 0x1f) || (deviceParam -> ale2Wr >= 0xf) ||
+ (deviceParam -> wrLow >= 0xf) || (deviceParam -> wrHigh >= 0xf))
+ return false;
+ valueForReg = (((deviceParam -> turnOff) & 0x7) |
+ (((deviceParam -> turnOff) & 0x8) << 19) |
+ (((deviceParam -> acc2First) & 0xf) << 3) |
+ (((deviceParam -> acc2First) & 0x10) << 19) |
+ (((deviceParam -> acc2Next) & 0xf) << 7) |
+ (((deviceParam -> acc2Next) & 0x10) << 20) |
+ (((deviceParam -> ale2Wr) & 0x7) << 11) |
+ (((deviceParam -> ale2Wr) & 0xf) << 22) |
+ (((deviceParam -> wrLow) & 0x7) << 14) |
+ (((deviceParam -> wrLow) & 0xf) << 23) |
+ (((deviceParam -> wrHigh) & 0x7) << 17) |
+ (((deviceParam -> wrHigh) & 0xf) << 24));
+ /* insert the device width: */
+ switch(deviceParam->deviceWidth)
+ {
+ case 1:
+ valueForReg = valueForReg | _8BIT;
+ break;
+ case 2:
+ valueForReg = valueForReg | _16BIT;
+ break;
+ case 4:
+ valueForReg = valueForReg | _32BIT;
+ break;
+ case 8:
+ valueForReg = valueForReg | _64BIT;
+ break;
+ default:
+ valueForReg = valueForReg | _8BIT;
+ break;
+ }
+ GT_REG_WRITE(DEVICE_BANK0PARAMETERS + 4 * deviceNum, valueForReg);
+ return true;
+}
diff --git a/board/evb64260/misc.S b/board/evb64260/misc.S
new file mode 100644
index 0000000..f09528d
--- /dev/null
+++ b/board/evb64260/misc.S
@@ -0,0 +1,182 @@
+#include <config.h>
+#include <74xx_7xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#include <galileo/gt64260R.h>
+
+#ifdef CONFIG_ECC
+ /* Galileo specific asm code for initializing ECC */
+ .globl board_relocate_rom
+board_relocate_rom:
+ mflr r7
+ /* update the location of the GT registers */
+ lis r11, CONFIG_SYS_GT_REGS@h
+ /* if we're using ECC, we must use the DMA engine to copy ourselves */
+ bl start_idma_transfer_0
+ bl wait_for_idma_0
+ bl stop_idma_engine_0
+
+ mtlr r7
+ blr
+
+ .globl board_init_ecc
+board_init_ecc:
+ mflr r7
+ /* NOTE: r10 still contains the location we've been relocated to
+ * which happens to be TOP_OF_RAM - CONFIG_SYS_MONITOR_LEN */
+
+ /* now that we're running from ram, init the rest of main memory
+ * for ECC use */
+ lis r8, CONFIG_SYS_MONITOR_LEN@h
+ ori r8, r8, CONFIG_SYS_MONITOR_LEN@l
+
+ divw r3, r10, r8
+
+ /* set up the counter, and init the starting address */
+ mtctr r3
+ li r12, 0
+
+ /* bytes per transfer */
+ mr r5, r8
+about_to_init_ecc:
+1: mr r3, r12
+ mr r4, r12
+ bl start_idma_transfer_0
+ bl wait_for_idma_0
+ bl stop_idma_engine_0
+ add r12, r12, r8
+ bdnz 1b
+
+ mtlr r7
+ blr
+
+ /* r3: dest addr
+ * r4: source addr
+ * r5: byte count
+ * r11: gt regbase
+ * trashes: r6, r5
+ */
+start_idma_transfer_0:
+ /* set the byte count, including the OWN bit */
+ mr r6, r11
+ ori r6, r6, CHANNEL0_DMA_BYTE_COUNT
+ stwbrx r5, 0, (r6)
+
+ /* set the source address */
+ mr r6, r11
+ ori r6, r6, CHANNEL0_DMA_SOURCE_ADDRESS
+ stwbrx r4, 0, (r6)
+
+ /* set the dest address */
+ mr r6, r11
+ ori r6, r6, CHANNEL0_DMA_DESTINATION_ADDRESS
+ stwbrx r3, 0, (r6)
+
+ /* set the next record pointer */
+ li r5, 0
+ mr r6, r11
+ ori r6, r6, CHANNEL0NEXT_RECORD_POINTER
+ stwbrx r5, 0, (r6)
+
+ /* set the low control register */
+ /* bit 9 is NON chained mode, bit 31 is new style descriptors.
+ bit 12 is channel enable */
+ ori r5, r5, (1 << 12) | (1 << 12) | (1 << 11)
+ /* 15 shifted by 16 (oris) == bit 31 */
+ oris r5, r5, (1 << 15)
+ mr r6, r11
+ ori r6, r6, CHANNEL0CONTROL
+ stwbrx r5, 0, (r6)
+
+ blr
+
+ /* this waits for the bytecount to return to zero, indicating
+ * that the trasfer is complete */
+wait_for_idma_0:
+ mr r5, r11
+ lis r6, 0xff
+ ori r6, r6, 0xffff
+ ori r5, r5, CHANNEL0_DMA_BYTE_COUNT
+1: lwbrx r4, 0, (r5)
+ and. r4, r4, r6
+ bne 1b
+
+ blr
+
+ /* this turns off channel 0 of the idma engine */
+stop_idma_engine_0:
+ /* shut off the DMA engine */
+ li r5, 0
+ mr r6, r11
+ ori r6, r6, CHANNEL0CONTROL
+ stwbrx r5, 0, (r6)
+
+ blr
+#endif
+
+#ifdef CONFIG_SYS_BOARD_ASM_INIT
+ /* NOTE: trashes r3-r7 */
+ .globl board_asm_init
+board_asm_init:
+ /* just move the GT registers to where they belong */
+ lis r3, CONFIG_SYS_DFL_GT_REGS@h
+ ori r3, r3, CONFIG_SYS_DFL_GT_REGS@l
+ lis r4, CONFIG_SYS_GT_REGS@h
+ ori r4, r4, CONFIG_SYS_GT_REGS@l
+ li r5, INTERNAL_SPACE_DECODE
+
+ /* test to see if we've already moved */
+ lwbrx r6, r5, r4
+ andi. r6, r6, 0xffff
+ rlwinm r7, r4, 12, 16, 31
+ cmp cr0, r7, r6
+ beqlr
+
+ /* nope, have to move the registers */
+ lwbrx r6, r5, r3
+ andis. r6, r6, 0xffff
+ or r6, r6, r7
+ stwbrx r6, r5, r3
+
+ /* now, poll for the change */
+1: lwbrx r7, r5, r4
+ cmp cr0, r7, r6
+ bne 1b
+
+ /* done! */
+ blr
+#endif
+
+/* For use of the debug LEDs */
+ .global led_on0
+led_on0:
+ xor r18, r18, r18
+ lis r18, 0x1c80
+ ori r18, r18, 0x8000
+ stw r18, 0x0(r18)
+ sync
+ blr
+
+ .global led_on1
+led_on1:
+ xor r18, r18, r18
+ lis r18, 0x1c80
+ ori r18, r18, 0xc000
+ stw r18, 0x0(r18)
+ sync
+ blr
+
+ .global led_on2
+led_on2:
+ xor r18, r18, r18
+ lis r18, 0x1c81
+ ori r18, r18, 0x0000
+ stw r18, 0x0(r18)
+ sync
+ blr
diff --git a/board/evb64260/mpsc.c b/board/evb64260/mpsc.c
new file mode 100644
index 0000000..9c211ac
--- /dev/null
+++ b/board/evb64260/mpsc.c
@@ -0,0 +1,854 @@
+/*
+ * (C) Copyright 2001
+ * John Clemens <clemens@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * mpsc.c - driver for console over the MPSC.
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/cache.h>
+
+#include <malloc.h>
+#include "mpsc.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int (*mpsc_putchar)(char ch) = mpsc_putchar_early;
+
+static volatile unsigned int *rx_desc_base=NULL;
+static unsigned int rx_desc_index=0;
+static volatile unsigned int *tx_desc_base=NULL;
+static unsigned int tx_desc_index=0;
+
+/* local function declarations */
+static int galmpsc_connect(int channel, int connect);
+static int galmpsc_route_serial(int channel, int connect);
+static int galmpsc_route_rx_clock(int channel, int brg);
+static int galmpsc_route_tx_clock(int channel, int brg);
+static int galmpsc_write_config_regs(int mpsc, int mode);
+static int galmpsc_config_channel_regs(int mpsc);
+static int galmpsc_set_char_length(int mpsc, int value);
+static int galmpsc_set_stop_bit_length(int mpsc, int value);
+static int galmpsc_set_parity(int mpsc, int value);
+static int galmpsc_enter_hunt(int mpsc);
+static int galmpsc_set_brkcnt(int mpsc, int value);
+static int galmpsc_set_tcschar(int mpsc, int value);
+static int galmpsc_set_snoop(int mpsc, int value);
+static int galmpsc_shutdown(int mpsc);
+
+static int galsdma_set_RFT(int channel);
+static int galsdma_set_SFM(int channel);
+static int galsdma_set_rxle(int channel);
+static int galsdma_set_txle(int channel);
+static int galsdma_set_burstsize(int channel, unsigned int value);
+static int galsdma_set_RC(int channel, unsigned int value);
+
+static int galbrg_set_CDV(int channel, int value);
+static int galbrg_enable(int channel);
+static int galbrg_disable(int channel);
+static int galbrg_set_clksrc(int channel, int value);
+static int galbrg_set_CUV(int channel, int value);
+
+static void galsdma_enable_rx(void);
+
+/* static int galbrg_reset(int channel); */
+
+#define SOFTWARE_CACHE_MANAGEMENT
+
+#ifdef SOFTWARE_CACHE_MANAGEMENT
+#define FLUSH_DCACHE(a,b) if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));}
+#define FLUSH_AND_INVALIDATE_DCACHE(a,b) if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));}
+#define INVALIDATE_DCACHE(a,b) if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));}
+#else
+#define FLUSH_DCACHE(a,b)
+#define FLUSH_AND_INVALIDATE_DCACHE(a,b)
+#define INVALIDATE_DCACHE(a,b)
+#endif
+
+
+/* GT64240A errata: cant read MPSC/BRG registers... so make mirrors in ram for read/modify write */
+#define MIRROR_HACK ((struct _tag_mirror_hack *)&(gd->arch.mirror_hack[0]))
+
+#define GT_REG_WRITE_MIRROR_G(a,d) {MIRROR_HACK->a ## _M = d; GT_REG_WRITE(a,d);}
+#define GTREGREAD_MIRROR_G(a) (MIRROR_HACK->a ## _M)
+
+#define GT_REG_WRITE_MIRROR(a,i,g,d) {MIRROR_HACK->a ## _M[i] = d; GT_REG_WRITE(a + (i*g),d);}
+#define GTREGREAD_MIRROR(a,i,g) (MIRROR_HACK->a ## _M[i])
+
+/* make sure this isn't bigger than 16 long words (u-boot.h) */
+struct _tag_mirror_hack {
+ unsigned GALMPSC_PROTOCONF_REG_M[2]; /* 8008 */
+ unsigned GALMPSC_CHANNELREG_1_M[2]; /* 800c */
+ unsigned GALMPSC_CHANNELREG_2_M[2]; /* 8010 */
+ unsigned GALBRG_0_CONFREG_M[2]; /* b200 */
+
+ unsigned GALMPSC_ROUTING_REGISTER_M; /* b400 */
+ unsigned GALMPSC_RxC_ROUTE_M; /* b404 */
+ unsigned GALMPSC_TxC_ROUTE_M; /* b408 */
+
+ unsigned int baudrate; /* current baudrate, for tsc delay calc */
+};
+
+/* static struct _tag_mirror_hack *mh = NULL; */
+
+/* special function for running out of flash. doesn't modify any
+ * global variables [josh] */
+int
+mpsc_putchar_early(char ch)
+{
+ int mpsc=CHANNEL;
+ int temp=GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP);
+ galmpsc_set_tcschar(mpsc,ch);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP), temp|0x200);
+
+#define MAGIC_FACTOR (10*1000000)
+
+ udelay(MAGIC_FACTOR / MIRROR_HACK->baudrate);
+ return 0;
+}
+
+/* This is used after relocation, see serial.c and mpsc_init2 */
+static int
+mpsc_putchar_sdma(char ch)
+{
+ volatile unsigned int *p;
+ unsigned int temp;
+
+
+ /* align the descriptor */
+ p = tx_desc_base;
+ memset((void *)p, 0, 8 * sizeof(unsigned int));
+
+ /* fill one 64 bit buffer */
+ /* word swap, pad with 0 */
+ p[4] = 0; /* x */
+ p[5] = (unsigned int)ch; /* x */
+
+ /* CHANGED completely according to GT64260A dox - NTL */
+ p[0] = 0x00010001; /* 0 */
+ p[1] = DESC_OWNER | DESC_FIRST | DESC_LAST; /* 4 */
+ p[2] = 0; /* 8 */
+ p[3] = (unsigned int)&p[4]; /* c */
+
+#if 0
+ p[9] = DESC_FIRST | DESC_LAST;
+ p[10] = (unsigned int)&p[0];
+ p[11] = (unsigned int)&p[12];
+#endif
+
+ FLUSH_DCACHE(&p[0], &p[8]);
+
+ GT_REG_WRITE(GALSDMA_0_CUR_TX_PTR+(CHANNEL*GALSDMA_REG_DIFF),
+ (unsigned int)&p[0]);
+ GT_REG_WRITE(GALSDMA_0_FIR_TX_PTR+(CHANNEL*GALSDMA_REG_DIFF),
+ (unsigned int)&p[0]);
+
+ temp = GTREGREAD(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF));
+ temp |= (TX_DEMAND | TX_STOP);
+ GT_REG_WRITE(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF), temp);
+
+ INVALIDATE_DCACHE(&p[1], &p[2]);
+
+ while(p[1] & DESC_OWNER) {
+ udelay(100);
+ INVALIDATE_DCACHE(&p[1], &p[2]);
+ }
+
+ return 0;
+}
+
+char mpsc_getchar (void)
+{
+ static unsigned int done = 0;
+ volatile char ch;
+ unsigned int len = 0, idx = 0, temp;
+
+ volatile unsigned int *p;
+
+
+ do {
+ p = &rx_desc_base[rx_desc_index * 8];
+
+ INVALIDATE_DCACHE (&p[0], &p[1]);
+ /* Wait for character */
+ while (p[1] & DESC_OWNER) {
+ udelay (100);
+ INVALIDATE_DCACHE (&p[0], &p[1]);
+ }
+
+ /* Handle error case */
+ if (p[1] & (1 << 15)) {
+ printf ("oops, error: %08x\n", p[1]);
+
+ temp = GTREGREAD_MIRROR (GALMPSC_CHANNELREG_2,
+ CHANNEL, GALMPSC_REG_GAP);
+ temp |= (1 << 23);
+ GT_REG_WRITE_MIRROR (GALMPSC_CHANNELREG_2, CHANNEL,
+ GALMPSC_REG_GAP, temp);
+
+ /* Can't poll on abort bit, so we just wait. */
+ udelay (100);
+
+ galsdma_enable_rx ();
+ }
+
+ /* Number of bytes left in this descriptor */
+ len = p[0] & 0xffff;
+
+ if (len) {
+ /* Where to look */
+ idx = 5;
+ if (done > 3)
+ idx = 4;
+ if (done > 7)
+ idx = 7;
+ if (done > 11)
+ idx = 6;
+
+ INVALIDATE_DCACHE (&p[idx], &p[idx + 1]);
+ ch = p[idx] & 0xff;
+ done++;
+ }
+
+ if (done < len) {
+ /* this descriptor has more bytes still
+ * shift down the char we just read, and leave the
+ * buffer in place for the next time around
+ */
+ p[idx] = p[idx] >> 8;
+ FLUSH_DCACHE (&p[idx], &p[idx + 1]);
+ }
+
+ if (done == len) {
+ /* nothing left in this descriptor.
+ * go to next one
+ */
+ p[1] = DESC_OWNER | DESC_FIRST | DESC_LAST;
+ p[0] = 0x00100000;
+ FLUSH_DCACHE (&p[0], &p[1]);
+ /* Next descriptor */
+ rx_desc_index = (rx_desc_index + 1) % RX_DESC;
+ done = 0;
+ }
+ } while (len == 0); /* galileo bug.. len might be zero */
+
+ return ch;
+}
+
+int
+mpsc_test_char(void)
+{
+ volatile unsigned int *p = &rx_desc_base[rx_desc_index*8];
+
+ INVALIDATE_DCACHE(&p[1], &p[2]);
+
+ if (p[1] & DESC_OWNER) return 0;
+ else return 1;
+}
+
+int
+mpsc_init(int baud)
+{
+ memset(MIRROR_HACK, 0, sizeof(struct _tag_mirror_hack));
+ MIRROR_HACK->GALMPSC_ROUTING_REGISTER_M=0x3fffffff;
+
+ /* BRG CONFIG */
+ galbrg_set_baudrate(CHANNEL, baud);
+#if defined(CONFIG_ZUMA_V2) || defined(CONFIG_P3G4)
+ galbrg_set_clksrc(CHANNEL,0x8); /* connect TCLK -> BRG */
+#else
+ galbrg_set_clksrc(CHANNEL,0);
+#endif
+ galbrg_set_CUV(CHANNEL, 0);
+ galbrg_enable(CHANNEL);
+
+ /* Set up clock routing */
+ galmpsc_connect(CHANNEL, GALMPSC_CONNECT);
+ galmpsc_route_serial(CHANNEL, GALMPSC_CONNECT);
+ galmpsc_route_rx_clock(CHANNEL, CHANNEL);
+ galmpsc_route_tx_clock(CHANNEL, CHANNEL);
+
+ /* reset MPSC state */
+ galmpsc_shutdown(CHANNEL);
+
+ /* SDMA CONFIG */
+ galsdma_set_burstsize(CHANNEL, L1_CACHE_BYTES/8); /* in 64 bit words (8 bytes) */
+ galsdma_set_txle(CHANNEL);
+ galsdma_set_rxle(CHANNEL);
+ galsdma_set_RC(CHANNEL, 0xf);
+ galsdma_set_SFM(CHANNEL);
+ galsdma_set_RFT(CHANNEL);
+
+ /* MPSC CONFIG */
+ galmpsc_write_config_regs(CHANNEL, GALMPSC_UART);
+ galmpsc_config_channel_regs(CHANNEL);
+ galmpsc_set_char_length(CHANNEL, GALMPSC_CHAR_LENGTH_8); /* 8 */
+ galmpsc_set_parity(CHANNEL, GALMPSC_PARITY_NONE); /* N */
+ galmpsc_set_stop_bit_length(CHANNEL, GALMPSC_STOP_BITS_1); /* 1 */
+
+ /* COMM_MPSC CONFIG */
+#ifdef SOFTWARE_CACHE_MANAGEMENT
+ galmpsc_set_snoop(CHANNEL, 0); /* disable snoop */
+#else
+ galmpsc_set_snoop(CHANNEL, 1); /* enable snoop */
+#endif
+
+ return 0;
+}
+
+void
+mpsc_init2(void)
+{
+ int i;
+
+ mpsc_putchar = mpsc_putchar_sdma;
+
+ /* RX descriptors */
+ rx_desc_base = (unsigned int *)malloc(((RX_DESC+1)*8) *
+ sizeof(unsigned int));
+
+ /* align descriptors */
+ rx_desc_base = (unsigned int *)
+ (((unsigned int)rx_desc_base+32) & 0xFFFFFFF0);
+
+ rx_desc_index = 0;
+
+ memset((void *)rx_desc_base, 0, (RX_DESC*8)*sizeof(unsigned int));
+
+ for (i = 0; i < RX_DESC; i++) {
+ rx_desc_base[i*8 + 3] = (unsigned int)&rx_desc_base[i*8 + 4]; /* Buffer */
+ rx_desc_base[i*8 + 2] = (unsigned int)&rx_desc_base[(i+1)*8]; /* Next descriptor */
+ rx_desc_base[i*8 + 1] = DESC_OWNER | DESC_FIRST | DESC_LAST; /* Command & control */
+ rx_desc_base[i*8] = 0x00100000;
+ }
+ rx_desc_base[(i-1)*8 + 2] = (unsigned int)&rx_desc_base[0];
+
+ FLUSH_DCACHE(&rx_desc_base[0], &rx_desc_base[RX_DESC*8]);
+ GT_REG_WRITE(GALSDMA_0_CUR_RX_PTR+(CHANNEL*GALSDMA_REG_DIFF),
+ (unsigned int)&rx_desc_base[0]);
+
+ /* TX descriptors */
+ tx_desc_base = (unsigned int *)malloc(((TX_DESC+1)*8) *
+ sizeof(unsigned int));
+
+ /* align descriptors */
+ tx_desc_base = (unsigned int *)
+ (((unsigned int)tx_desc_base+32) & 0xFFFFFFF0);
+
+ tx_desc_index = -1;
+
+ memset((void *)tx_desc_base, 0, (TX_DESC*8)*sizeof(unsigned int));
+
+ for (i = 0; i < TX_DESC; i++) {
+ tx_desc_base[i*8 + 5] = (unsigned int)0x23232323;
+ tx_desc_base[i*8 + 4] = (unsigned int)0x23232323;
+ tx_desc_base[i*8 + 3] = (unsigned int)&tx_desc_base[i*8 + 4];
+ tx_desc_base[i*8 + 2] = (unsigned int)&tx_desc_base[(i+1)*8];
+ tx_desc_base[i*8 + 1] = DESC_OWNER | DESC_FIRST | DESC_LAST;
+
+ /* set sbytecnt and shadow byte cnt to 1 */
+ tx_desc_base[i*8] = 0x00010001;
+ }
+ tx_desc_base[(i-1)*8 + 2] = (unsigned int)&tx_desc_base[0];
+
+ FLUSH_DCACHE(&tx_desc_base[0], &tx_desc_base[TX_DESC*8]);
+
+ udelay(100);
+
+ galsdma_enable_rx();
+
+ return;
+}
+
+int
+galbrg_set_baudrate(int channel, int rate)
+{
+ int clock;
+
+ galbrg_disable(channel);
+
+#if defined(CONFIG_ZUMA_V2) || defined(CONFIG_P3G4)
+ /* from tclk */
+ clock = (CONFIG_SYS_BUS_CLK/(16*rate)) - 1;
+#else
+ clock = (3686400/(16*rate)) - 1;
+#endif
+
+ galbrg_set_CDV(channel, clock);
+
+ galbrg_enable(channel);
+
+ MIRROR_HACK->baudrate = rate;
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+/* Below are all the private functions that no one else needs */
+
+static int
+galbrg_set_CDV(int channel, int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP);
+ temp &= 0xFFFF0000;
+ temp |= (value & 0x0000FFFF);
+ GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG,channel,GALBRG_REG_GAP, temp);
+
+ return 0;
+}
+
+static int
+galbrg_enable(int channel)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP);
+ temp |= 0x00010000;
+ GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP,temp);
+
+ return 0;
+}
+
+static int
+galbrg_disable(int channel)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP);
+ temp &= 0xFFFEFFFF;
+ GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP,temp);
+
+ return 0;
+}
+
+static int
+galbrg_set_clksrc(int channel, int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG,channel, GALBRG_REG_GAP);
+ temp &= 0xFF83FFFF;
+ temp |= (value << 18);
+ GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG,channel, GALBRG_REG_GAP,temp);
+
+ return 0;
+}
+
+static int
+galbrg_set_CUV(int channel, int value)
+{
+ GT_REG_WRITE(GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value);
+
+ return 0;
+}
+
+#if 0
+static int
+galbrg_reset(int channel)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD(GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP));
+ temp |= 0x20000;
+ GT_REG_WRITE(GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp);
+
+ return 0;
+}
+#endif
+
+static int
+galsdma_set_RFT(int channel)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF));
+ temp |= 0x00000001;
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp);
+
+ return 0;
+}
+
+static int
+galsdma_set_SFM(int channel)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF));
+ temp |= 0x00000002;
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp);
+
+ return 0;
+}
+
+static int
+galsdma_set_rxle(int channel)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF));
+ temp |= 0x00000040;
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp);
+
+ return 0;
+}
+
+static int
+galsdma_set_txle(int channel)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF));
+ temp |= 0x00000080;
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp);
+
+ return 0;
+}
+
+static int
+galsdma_set_RC(int channel, unsigned int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF));
+ temp &= ~0x0000003c;
+ temp |= (value << 2);
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp);
+
+ return 0;
+}
+
+static int
+galsdma_set_burstsize(int channel, unsigned int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF));
+ temp &= 0xFFFFCFFF;
+ switch (value) {
+ case 8:
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF),
+ (temp | (0x3 << 12)));
+ break;
+
+ case 4:
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF),
+ (temp | (0x2 << 12)));
+ break;
+
+ case 2:
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF),
+ (temp | (0x1 << 12)));
+ break;
+
+ case 1:
+ GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF),
+ (temp | (0x0 << 12)));
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+static int
+galmpsc_connect(int channel, int connect)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR_G(GALMPSC_ROUTING_REGISTER);
+
+ if ((channel == 0) && connect)
+ temp &= ~0x00000007;
+ else if ((channel == 1) && connect)
+ temp &= ~(0x00000007 << 6);
+ else if ((channel == 0) && !connect)
+ temp |= 0x00000007;
+ else
+ temp |= (0x00000007 << 6);
+
+ /* Just in case... */
+ temp &= 0x3fffffff;
+
+ GT_REG_WRITE_MIRROR_G(GALMPSC_ROUTING_REGISTER, temp);
+
+ return 0;
+}
+
+static int
+galmpsc_route_serial(int channel, int connect)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD(GALMPSC_SERIAL_MULTIPLEX);
+
+ if ((channel == 0) && connect)
+ temp |= 0x00000100;
+ else if ((channel == 1) && connect)
+ temp |= 0x00001000;
+ else if ((channel == 0) && !connect)
+ temp &= ~0x00000100;
+ else
+ temp &= ~0x00001000;
+
+ GT_REG_WRITE(GALMPSC_SERIAL_MULTIPLEX,temp);
+
+ return 0;
+}
+
+static int
+galmpsc_route_rx_clock(int channel, int brg)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR_G(GALMPSC_RxC_ROUTE);
+
+ if (channel == 0)
+ temp |= brg;
+ else
+ temp |= (brg << 8);
+
+ GT_REG_WRITE_MIRROR_G(GALMPSC_RxC_ROUTE,temp);
+
+ return 0;
+}
+
+static int
+galmpsc_route_tx_clock(int channel, int brg)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR_G(GALMPSC_TxC_ROUTE);
+
+ if (channel == 0)
+ temp |= brg;
+ else
+ temp |= (brg << 8);
+
+ GT_REG_WRITE_MIRROR_G(GALMPSC_TxC_ROUTE,temp);
+
+ return 0;
+}
+
+static int
+galmpsc_write_config_regs(int mpsc, int mode)
+{
+ if (mode == GALMPSC_UART) {
+ /* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */
+ GT_REG_WRITE(GALMPSC_MCONF_LOW + (mpsc*GALMPSC_REG_GAP),
+ 0x000004c4);
+
+ /* Main config reg High (32x Rx/Tx clock mode, width=8bits */
+ GT_REG_WRITE(GALMPSC_MCONF_HIGH +(mpsc*GALMPSC_REG_GAP),
+ 0x024003f8);
+ /* 22 2222 1111 */
+ /* 54 3210 9876 */
+ /* 0000 0010 0000 0000 */
+ /* 1 */
+ /* 098 7654 3210 */
+ /* 0000 0011 1111 1000 */
+ } else
+ return -1;
+
+ return 0;
+}
+
+static int
+galmpsc_config_channel_regs(int mpsc)
+{
+ GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, 0);
+ GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, 0);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_3+(mpsc*GALMPSC_REG_GAP), 1);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_4+(mpsc*GALMPSC_REG_GAP), 0);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_5+(mpsc*GALMPSC_REG_GAP), 0);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_6+(mpsc*GALMPSC_REG_GAP), 0);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_7+(mpsc*GALMPSC_REG_GAP), 0);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_8+(mpsc*GALMPSC_REG_GAP), 0);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_9+(mpsc*GALMPSC_REG_GAP), 0);
+ GT_REG_WRITE(GALMPSC_CHANNELREG_10+(mpsc*GALMPSC_REG_GAP), 0);
+
+ galmpsc_set_brkcnt(mpsc, 0x3);
+ galmpsc_set_tcschar(mpsc, 0xab);
+
+ return 0;
+}
+
+static int
+galmpsc_set_brkcnt(int mpsc, int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP);
+ temp &= 0x0000FFFF;
+ temp |= (value << 16);
+ GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, temp);
+
+ return 0;
+}
+
+static int
+galmpsc_set_tcschar(int mpsc, int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP);
+ temp &= 0xFFFF0000;
+ temp |= value;
+ GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, temp);
+
+ return 0;
+}
+
+static int
+galmpsc_set_char_length(int mpsc, int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP);
+ temp &= 0xFFFFCFFF;
+ temp |= (value << 12);
+ GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP, temp);
+
+ return 0;
+}
+
+static int
+galmpsc_set_stop_bit_length(int mpsc, int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP);
+ temp |= (value << 14);
+ GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP,temp);
+
+ return 0;
+}
+
+static int
+galmpsc_set_parity(int mpsc, int value)
+{
+ unsigned int temp;
+
+ temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP);
+ if (value != -1) {
+ temp &= 0xFFF3FFF3;
+ temp |= ((value << 18) | (value << 2));
+ temp |= ((value << 17) | (value << 1));
+ } else {
+ temp &= 0xFFF1FFF1;
+ }
+
+ GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, temp);
+
+ return 0;
+}
+
+static int
+galmpsc_enter_hunt(int mpsc)
+{
+ int temp;
+
+ temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP);
+ temp |= 0x80000000;
+ GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, temp);
+
+ /* Should Poll on Enter Hunt bit, but the register is write-only */
+ /* errata suggests pausing 100 system cycles */
+ udelay(100);
+
+ return 0;
+}
+
+
+static int
+galmpsc_shutdown(int mpsc)
+{
+#if 0
+ unsigned int temp;
+
+ /* cause RX abort (clears RX) */
+ temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP);
+ temp |= MPSC_RX_ABORT | MPSC_TX_ABORT;
+ temp &= ~MPSC_ENTER_HUNT;
+ GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP,temp);
+#endif
+
+ GT_REG_WRITE(GALSDMA_0_COM_REG + CHANNEL * GALSDMA_REG_DIFF, 0);
+ GT_REG_WRITE(GALSDMA_0_COM_REG + CHANNEL * GALSDMA_REG_DIFF,
+ SDMA_TX_ABORT | SDMA_RX_ABORT);
+
+ /* shut down the MPSC */
+ GT_REG_WRITE(GALMPSC_MCONF_LOW, 0);
+ GT_REG_WRITE(GALMPSC_MCONF_HIGH, 0);
+ GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG, mpsc, GALMPSC_REG_GAP,0);
+
+ udelay(100);
+
+ /* shut down the sdma engines. */
+ /* reset config to default */
+ GT_REG_WRITE(GALSDMA_0_CONF_REG + CHANNEL * GALSDMA_REG_DIFF,
+ 0x000000fc);
+
+ udelay(100);
+
+ /* clear the SDMA current and first TX and RX pointers */
+ GT_REG_WRITE(GALSDMA_0_CUR_RX_PTR + CHANNEL * GALSDMA_REG_DIFF, 0);
+ GT_REG_WRITE(GALSDMA_0_CUR_TX_PTR + CHANNEL * GALSDMA_REG_DIFF, 0);
+ GT_REG_WRITE(GALSDMA_0_FIR_TX_PTR + CHANNEL * GALSDMA_REG_DIFF, 0);
+
+ udelay(100);
+
+ return 0;
+}
+
+static void
+galsdma_enable_rx(void)
+{
+ int temp;
+
+ /* Enable RX processing */
+ temp = GTREGREAD(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF));
+ temp |= RX_ENABLE;
+ GT_REG_WRITE(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF), temp);
+
+ galmpsc_enter_hunt(CHANNEL);
+}
+
+static int
+galmpsc_set_snoop(int mpsc, int value)
+{
+ int reg = mpsc ? MPSC_1_ADDRESS_CONTROL_LOW : MPSC_0_ADDRESS_CONTROL_LOW;
+ int temp=GTREGREAD(reg);
+ if(value)
+ temp |= (1<< 6) | (1<<14) | (1<<22) | (1<<30);
+ else
+ temp &= ~((1<< 6) | (1<<14) | (1<<22) | (1<<30));
+ GT_REG_WRITE(reg, temp);
+ return 0;
+}
diff --git a/board/evb64260/mpsc.h b/board/evb64260/mpsc.h
new file mode 100644
index 0000000..c71258c
--- /dev/null
+++ b/board/evb64260/mpsc.h
@@ -0,0 +1,142 @@
+/*
+ * (C) Copyright 2001
+ * John Clemens <clemens@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * mpsc.h - header file for MPSC in uart mode (console driver)
+ */
+
+#ifndef __MPSC_H__
+#define __MPSC_H__
+
+/* include actual Galileo defines */
+#include <galileo/gt64260R.h>
+
+/* driver related defines */
+
+int mpsc_init(int baud);
+void mpsc_init2(void);
+char mpsc_getchar(void);
+int mpsc_test_char(void);
+int galbrg_set_baudrate(int channel, int rate);
+
+int mpsc_putchar_early(char ch);
+extern int (*mpsc_putchar)(char ch);
+
+#define CHANNEL CONFIG_MPSC_PORT
+
+#define TX_DESC 5
+#define RX_DESC 20
+
+#define DESC_FIRST 0x00010000
+#define DESC_LAST 0x00020000
+#define DESC_OWNER 0x80000000
+
+#define TX_DEMAND 0x00800000
+#define TX_STOP 0x00010000
+#define RX_ENABLE 0x00000080
+
+#define SDMA_RX_ABORT (1 << 15)
+#define SDMA_TX_ABORT (1 << 31)
+#define MPSC_TX_ABORT (1 << 7)
+#define MPSC_RX_ABORT (1 << 23)
+#define MPSC_ENTER_HUNT (1 << 31)
+
+/* MPSC defines */
+
+#define GALMPSC_CONNECT 0x1
+#define GALMPSC_DISCONNECT 0x0
+
+#define GALMPSC_UART 0x1
+
+#define GALMPSC_STOP_BITS_1 0x0
+#define GALMPSC_STOP_BITS_2 0x1
+#define GALMPSC_CHAR_LENGTH_8 0x3
+#define GALMPSC_CHAR_LENGTH_7 0x2
+
+#define GALMPSC_PARITY_ODD 0x0
+#define GALMPSC_PARITY_EVEN 0x2
+#define GALMPSC_PARITY_MARK 0x3
+#define GALMPSC_PARITY_SPACE 0x1
+#define GALMPSC_PARITY_NONE -1
+
+#define GALMPSC_SERIAL_MULTIPLEX SERIAL_PORT_MULTIPLEX /* 0xf010 */
+#define GALMPSC_ROUTING_REGISTER MAIN_ROUTING_REGISTER /* 0xb400 */
+#define GALMPSC_RxC_ROUTE RECEIVE_CLOCK_ROUTING_REGISTER /* 0xb404 */
+#define GALMPSC_TxC_ROUTE TRANSMIT_CLOCK_ROUTING_REGISTER /* 0xb408 */
+#define GALMPSC_MCONF_LOW MPSC0_MAIN_CONFIGURATION_LOW /* 0x8000 */
+#define GALMPSC_MCONF_HIGH MPSC0_MAIN_CONFIGURATION_HIGH /* 0x8004 */
+#define GALMPSC_PROTOCONF_REG MPSC0_PROTOCOL_CONFIGURATION /* 0x8008 */
+
+#define GALMPSC_REG_GAP 0x1000
+
+#define GALMPSC_MCONF_CHREG_BASE CHANNEL0_REGISTER1 /* 0x800c */
+#define GALMPSC_CHANNELREG_1 CHANNEL0_REGISTER1 /* 0x800c */
+#define GALMPSC_CHANNELREG_2 CHANNEL0_REGISTER2 /* 0x8010 */
+#define GALMPSC_CHANNELREG_3 CHANNEL0_REGISTER3 /* 0x8014 */
+#define GALMPSC_CHANNELREG_4 CHANNEL0_REGISTER4 /* 0x8018 */
+#define GALMPSC_CHANNELREG_5 CHANNEL0_REGISTER5 /* 0x801c */
+#define GALMPSC_CHANNELREG_6 CHANNEL0_REGISTER6 /* 0x8020 */
+#define GALMPSC_CHANNELREG_7 CHANNEL0_REGISTER7 /* 0x8024 */
+#define GALMPSC_CHANNELREG_8 CHANNEL0_REGISTER8 /* 0x8028 */
+#define GALMPSC_CHANNELREG_9 CHANNEL0_REGISTER9 /* 0x802c */
+#define GALMPSC_CHANNELREG_10 CHANNEL0_REGISTER10 /* 0x8030 */
+#define GALMPSC_CHANNELREG_11 CHANNEL0_REGISTER11 /* 0x8034 */
+
+#define GALSDMA_COMMAND_FIRST (1 << 16)
+#define GALSDMA_COMMAND_LAST (1 << 17)
+#define GALSDMA_COMMAND_ENABLEINT (1 << 23)
+#define GALSDMA_COMMAND_AUTO (1 << 30)
+#define GALSDMA_COMMAND_OWNER (1 << 31)
+
+#define GALSDMA_RX 0
+#define GALSDMA_TX 1
+
+/* CHANNEL2 should be CHANNEL1, according to documentation,
+ * but to work with the current GTREGS file...
+ */
+#define GALSDMA_0_CONF_REG CHANNEL0_CONFIGURATION_REGISTER /* 0x4000 */
+#define GALSDMA_1_CONF_REG CHANNEL2_CONFIGURATION_REGISTER /* 0x6000 */
+#define GALSDMA_0_COM_REG CHANNEL0_COMMAND_REGISTER /* 0x4008 */
+#define GALSDMA_1_COM_REG CHANNEL2_COMMAND_REGISTER /* 0x6008 */
+#define GALSDMA_0_CUR_RX_PTR CHANNEL0_CURRENT_RX_DESCRIPTOR_POINTER /* 0x4810 */
+#define GALSDMA_0_CUR_TX_PTR CHANNEL0_CURRENT_TX_DESCRIPTOR_POINTER /* 0x4c10 */
+#define GALSDMA_0_FIR_TX_PTR CHANNEL0_FIRST_TX_DESCRIPTOR_POINTER /* 0x4c14 */
+#define GALSDMA_1_CUR_RX_PTR CHANNEL2_CURRENT_RX_DESCRIPTOR_POINTER /* 0x6810 */
+#define GALSDMA_1_CUR_TX_PTR CHANNEL2_CURRENT_TX_DESCRIPTOR_POINTER /* 0x6c10 */
+#define GALSDMA_1_FIR_TX_PTR CHANNEL2_FIRST_TX_DESCRIPTOR_POINTER /* 0x6c14 */
+#define GALSDMA_REG_DIFF 0x2000
+
+/* WRONG in gt64260R.h */
+#define GALSDMA_INT_CAUSE 0xb800 /* SDMA_CAUSE */
+#define GALSDMA_INT_MASK 0xb880 /* SDMA_MASK */
+
+#define GALSDMA_MODE_UART 0
+#define GALSDMA_MODE_BISYNC 1
+#define GALSDMA_MODE_HDLC 2
+#define GALSDMA_MODE_TRANSPARENT 3
+
+#define GALBRG_0_CONFREG BRG0_CONFIGURATION_REGISTER /* 0xb200 */
+#define GALBRG_REG_GAP 0x0008
+#define GALBRG_0_BTREG BRG0_BAUDE_TUNING_REGISTER /* 0xb204 */
+
+#endif /* __MPSC_H__ */
diff --git a/board/evb64260/pci.c b/board/evb64260/pci.c
new file mode 100644
index 0000000..582f24c
--- /dev/null
+++ b/board/evb64260/pci.c
@@ -0,0 +1,760 @@
+/* PCI.c - PCI functions */
+
+/* Copyright - Galileo technology. */
+
+#include <common.h>
+#include <pci.h>
+
+#include <galileo/pci.h>
+
+static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = {
+#ifdef CONFIG_ZUMA_V2
+ {0, 0, 0, 0, 0, 0, 0, 29,[8 ... PCI_MAX_DEVICES - 1] = 0},
+ {0, 0, 0, 0, 0, 0, 0, 28,[8 ... PCI_MAX_DEVICES - 1] = 0}
+#else /* EVB??? This is a guess */
+ {0, 0, 0, 0, 0, 0, 0, 27, 27,[9 ... PCI_MAX_DEVICES - 1] = 0},
+ {0, 0, 0, 0, 0, 0, 0, 29, 29,[9 ... PCI_MAX_DEVICES - 1] = 0}
+#endif
+};
+
+static const unsigned int pci_p2p_configuration_reg[] = {
+ PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION
+};
+
+static const unsigned int pci_configuration_address[] = {
+ PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS
+};
+
+static const unsigned int pci_configuration_data[] = {
+ PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER,
+ PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER
+};
+
+static const unsigned int pci_error_cause_reg[] = {
+ PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE
+};
+
+static const unsigned int pci_arbiter_control[] = {
+ PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL
+};
+
+static const unsigned int pci_snoop_control_base_0_low[] = {
+ PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW
+};
+static const unsigned int pci_snoop_control_top_0[] = {
+ PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0
+};
+
+static const unsigned int pci_access_control_base_0_low[] = {
+ PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW
+};
+static const unsigned int pci_access_control_top_0[] = {
+ PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0
+};
+
+static const unsigned int pci_scs_bank_size[2][4] = {
+ {PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE,
+ PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE},
+ {PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE,
+ PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE}
+};
+
+static const unsigned int pci_p2p_configuration[] = {
+ PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION
+};
+
+static unsigned int local_buses[] = { 0, 0 };
+
+/********************************************************************
+* pciWriteConfigReg - Write to a PCI configuration register
+* - Make sure the GT is configured as a master before writing
+* to another device on the PCI.
+* - The function takes care of Big/Little endian conversion.
+*
+*
+* Inputs: unsigned int regOffset: The register offset as it apears in the GT spec
+* (or any other PCI device spec)
+* pciDevNum: The device number needs to be addressed.
+*
+* Configuration Address 0xCF8:
+*
+* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+* |congif|Reserved| Bus |Device|Function|Register|00|
+* |Enable| |Number|Number| Number | Number | | <=field Name
+*
+*********************************************************************/
+void pciWriteConfigReg (PCI_HOST host, unsigned int regOffset,
+ unsigned int pciDevNum, unsigned int data)
+{
+ volatile unsigned int DataForAddrReg;
+ unsigned int functionNum;
+ unsigned int busNum = PCI_BUS (pciDevNum);
+ unsigned int addr;
+
+ if (pciDevNum > 32) /* illegal device Number */
+ return;
+ if (pciDevNum == SELF) { /* configure our configuration space. */
+ pciDevNum =
+ (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) &
+ 0x1f;
+ busNum = GTREGREAD (pci_p2p_configuration_reg[host]) &
+ 0xff0000;
+ }
+ functionNum = regOffset & 0x00000700;
+ pciDevNum = pciDevNum << 11;
+ regOffset = regOffset & 0xfc;
+ DataForAddrReg =
+ (regOffset | pciDevNum | functionNum | busNum) | BIT31;
+ GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg);
+ GT_REG_READ (pci_configuration_address[host], &addr);
+ if (addr != DataForAddrReg)
+ return;
+ GT_REG_WRITE (pci_configuration_data[host], data);
+}
+
+/********************************************************************
+* pciReadConfigReg - Read from a PCI0 configuration register
+* - Make sure the GT is configured as a master before reading
+* from another device on the PCI.
+* - The function takes care of Big/Little endian conversion.
+* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI
+* spec)
+* pciDevNum: The device number needs to be addressed.
+* RETURNS: data , if the data == 0xffffffff check the master abort bit in the
+* cause register to make sure the data is valid
+*
+* Configuration Address 0xCF8:
+*
+* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+* |congif|Reserved| Bus |Device|Function|Register|00|
+* |Enable| |Number|Number| Number | Number | | <=field Name
+*
+*********************************************************************/
+unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset,
+ unsigned int pciDevNum)
+{
+ volatile unsigned int DataForAddrReg;
+ unsigned int data;
+ unsigned int functionNum;
+ unsigned int busNum = PCI_BUS (pciDevNum);
+
+ if (pciDevNum > 32) /* illegal device Number */
+ return 0xffffffff;
+ if (pciDevNum == SELF) { /* configure our configuration space. */
+ pciDevNum =
+ (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) &
+ 0x1f;
+ busNum = GTREGREAD (pci_p2p_configuration_reg[host]) &
+ 0xff0000;
+ }
+ functionNum = regOffset & 0x00000700;
+ pciDevNum = pciDevNum << 11;
+ regOffset = regOffset & 0xfc;
+ DataForAddrReg =
+ (regOffset | pciDevNum | functionNum | busNum) | BIT31;
+ GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg);
+ GT_REG_READ (pci_configuration_address[host], &data);
+ if (data != DataForAddrReg)
+ return 0xffffffff;
+ GT_REG_READ (pci_configuration_data[host], &data);
+ return data;
+}
+
+/********************************************************************
+* pciOverBridgeWriteConfigReg - Write to a PCI configuration register where
+* the agent is placed on another Bus. For more
+* information read P2P in the PCI spec.
+*
+* Inputs: unsigned int regOffset - The register offset as it apears in the
+* GT spec (or any other PCI device spec).
+* unsigned int pciDevNum - The device number needs to be addressed.
+* unsigned int busNum - On which bus does the Target agent connect
+* to.
+* unsigned int data - data to be written.
+*
+* Configuration Address 0xCF8:
+*
+* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+* |congif|Reserved| Bus |Device|Function|Register|01|
+* |Enable| |Number|Number| Number | Number | | <=field Name
+*
+* The configuration Address is configure as type-I (bits[1:0] = '01') due to
+* PCI spec referring to P2P.
+*
+*********************************************************************/
+void pciOverBridgeWriteConfigReg (PCI_HOST host,
+ unsigned int regOffset,
+ unsigned int pciDevNum,
+ unsigned int busNum, unsigned int data)
+{
+ unsigned int DataForReg;
+ unsigned int functionNum;
+
+ functionNum = regOffset & 0x00000700;
+ pciDevNum = pciDevNum << 11;
+ regOffset = regOffset & 0xff;
+ busNum = busNum << 16;
+ if (pciDevNum == SELF) { /* This board */
+ DataForReg = (regOffset | pciDevNum | functionNum) | BIT0;
+ } else {
+ DataForReg = (regOffset | pciDevNum | functionNum | busNum) |
+ BIT31 | BIT0;
+ }
+ GT_REG_WRITE (pci_configuration_address[host], DataForReg);
+ if (pciDevNum == SELF) { /* This board */
+ GT_REG_WRITE (pci_configuration_data[host], data);
+ } else { /* configuration Transaction over the pci. */
+
+ /* The PCI is working in LE Mode So it swap the Data. */
+ GT_REG_WRITE (pci_configuration_data[host], WORD_SWAP (data));
+ }
+}
+
+
+/********************************************************************
+* pciOverBridgeReadConfigReg - Read from a PCIn configuration register where
+* the agent target locate on another PCI bus.
+* - Make sure the GT is configured as a master
+* before reading from another device on the PCI.
+* - The function takes care of Big/Little endian
+* conversion.
+* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI
+* spec). (configuration register offset.)
+* pciDevNum: The device number needs to be addressed.
+* busNum: the Bus number where the agent is place.
+* RETURNS: data , if the data == 0xffffffff check the master abort bit in the
+* cause register to make sure the data is valid
+*
+* Configuration Address 0xCF8:
+*
+* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+* |congif|Reserved| Bus |Device|Function|Register|01|
+* |Enable| |Number|Number| Number | Number | | <=field Name
+*
+*********************************************************************/
+unsigned int pciOverBridgeReadConfigReg (PCI_HOST host,
+ unsigned int regOffset,
+ unsigned int pciDevNum,
+ unsigned int busNum)
+{
+ unsigned int DataForReg;
+ unsigned int data;
+ unsigned int functionNum;
+
+ functionNum = regOffset & 0x00000700;
+ pciDevNum = pciDevNum << 11;
+ regOffset = regOffset & 0xff;
+ busNum = busNum << 16;
+ if (pciDevNum == SELF) { /* This board */
+ DataForReg = (regOffset | pciDevNum | functionNum) | BIT31;
+ } else { /* agent on another bus */
+
+ DataForReg = (regOffset | pciDevNum | functionNum | busNum) |
+ BIT0 | BIT31;
+ }
+ GT_REG_WRITE (pci_configuration_address[host], DataForReg);
+ if (pciDevNum == SELF) { /* This board */
+ GT_REG_READ (pci_configuration_data[host], &data);
+ return data;
+ } else { /* The PCI is working in LE Mode So it swap the Data. */
+
+ GT_REG_READ (pci_configuration_data[host], &data);
+ return WORD_SWAP (data);
+ }
+}
+
+/********************************************************************
+* pciGetRegOffset - Gets the register offset for this region config.
+*
+* INPUT: Bus, Region - The bus and region we ask for its base address.
+* OUTPUT: N/A
+* RETURNS: PCI register base address
+*********************************************************************/
+static unsigned int pciGetRegOffset (PCI_HOST host, PCI_REGION region)
+{
+ switch (host) {
+ case PCI_HOST0:
+ switch (region) {
+ case PCI_IO:
+ return PCI_0I_O_LOW_DECODE_ADDRESS;
+ case PCI_REGION0:
+ return PCI_0MEMORY0_LOW_DECODE_ADDRESS;
+ case PCI_REGION1:
+ return PCI_0MEMORY1_LOW_DECODE_ADDRESS;
+ case PCI_REGION2:
+ return PCI_0MEMORY2_LOW_DECODE_ADDRESS;
+ case PCI_REGION3:
+ return PCI_0MEMORY3_LOW_DECODE_ADDRESS;
+ }
+ case PCI_HOST1:
+ switch (region) {
+ case PCI_IO:
+ return PCI_1I_O_LOW_DECODE_ADDRESS;
+ case PCI_REGION0:
+ return PCI_1MEMORY0_LOW_DECODE_ADDRESS;
+ case PCI_REGION1:
+ return PCI_1MEMORY1_LOW_DECODE_ADDRESS;
+ case PCI_REGION2:
+ return PCI_1MEMORY2_LOW_DECODE_ADDRESS;
+ case PCI_REGION3:
+ return PCI_1MEMORY3_LOW_DECODE_ADDRESS;
+ }
+ }
+ return PCI_0MEMORY0_LOW_DECODE_ADDRESS;
+}
+
+static unsigned int pciGetRemapOffset (PCI_HOST host, PCI_REGION region)
+{
+ switch (host) {
+ case PCI_HOST0:
+ switch (region) {
+ case PCI_IO:
+ return PCI_0I_O_ADDRESS_REMAP;
+ case PCI_REGION0:
+ return PCI_0MEMORY0_ADDRESS_REMAP;
+ case PCI_REGION1:
+ return PCI_0MEMORY1_ADDRESS_REMAP;
+ case PCI_REGION2:
+ return PCI_0MEMORY2_ADDRESS_REMAP;
+ case PCI_REGION3:
+ return PCI_0MEMORY3_ADDRESS_REMAP;
+ }
+ case PCI_HOST1:
+ switch (region) {
+ case PCI_IO:
+ return PCI_1I_O_ADDRESS_REMAP;
+ case PCI_REGION0:
+ return PCI_1MEMORY0_ADDRESS_REMAP;
+ case PCI_REGION1:
+ return PCI_1MEMORY1_ADDRESS_REMAP;
+ case PCI_REGION2:
+ return PCI_1MEMORY2_ADDRESS_REMAP;
+ case PCI_REGION3:
+ return PCI_1MEMORY3_ADDRESS_REMAP;
+ }
+ }
+ return PCI_0MEMORY0_ADDRESS_REMAP;
+}
+
+bool pciMapSpace (PCI_HOST host, PCI_REGION region, unsigned int remapBase,
+ unsigned int bankBase, unsigned int bankLength)
+{
+ unsigned int low = 0xfff;
+ unsigned int high = 0x0;
+ unsigned int regOffset = pciGetRegOffset (host, region);
+ unsigned int remapOffset = pciGetRemapOffset (host, region);
+
+ if (bankLength != 0) {
+ low = (bankBase >> 20) & 0xfff;
+ high = ((bankBase + bankLength) >> 20) - 1;
+ }
+
+ GT_REG_WRITE (regOffset, low | (1 << 24)); /* no swapping */
+ GT_REG_WRITE (regOffset + 8, high);
+
+ if (bankLength != 0) { /* must do AFTER writing maps */
+ GT_REG_WRITE (remapOffset, remapBase >> 20); /* sorry, 32 bits only.
+ dont support upper 32
+ in this driver */
+ }
+ return true;
+}
+
+unsigned int pciGetSpaceBase (PCI_HOST host, PCI_REGION region)
+{
+ unsigned int low;
+ unsigned int regOffset = pciGetRegOffset (host, region);
+
+ GT_REG_READ (regOffset, &low);
+ return (low & 0xfff) << 20;
+}
+
+unsigned int pciGetSpaceSize (PCI_HOST host, PCI_REGION region)
+{
+ unsigned int low, high;
+ unsigned int regOffset = pciGetRegOffset (host, region);
+
+ GT_REG_READ (regOffset, &low);
+ GT_REG_READ (regOffset + 8, &high);
+ high &= 0xfff;
+ low &= 0xfff;
+ if (high <= low)
+ return 0;
+ return (high + 1 - low) << 20;
+}
+
+/********************************************************************
+* pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave.
+*
+* Inputs: base and size of PCI SCS
+*********************************************************************/
+void pciMapMemoryBank (PCI_HOST host, MEMORY_BANK bank,
+ unsigned int pciDramBase, unsigned int pciDramSize)
+{
+ pciDramBase = pciDramBase & 0xfffff000;
+ pciDramBase = pciDramBase | (pciReadConfigReg (host,
+ PCI_SCS_0_BASE_ADDRESS
+ + 4 * bank,
+ SELF) & 0x00000fff);
+ pciWriteConfigReg (host, PCI_SCS_0_BASE_ADDRESS + 4 * bank, SELF,
+ pciDramBase);
+ if (pciDramSize == 0)
+ pciDramSize++;
+ GT_REG_WRITE (pci_scs_bank_size[host][bank], pciDramSize - 1);
+}
+
+
+/********************************************************************
+* pciSetRegionFeatures - This function modifys one of the 8 regions with
+* feature bits given as an input.
+* - Be advised to check the spec before modifying them.
+* Inputs: PCI_PROTECT_REGION region - one of the eight regions.
+* unsigned int features - See file: pci.h there are defintion for those
+* region features.
+* unsigned int baseAddress - The region base Address.
+* unsigned int topAddress - The region top Address.
+* Returns: false if one of the parameters is erroneous true otherwise.
+*********************************************************************/
+bool pciSetRegionFeatures (PCI_HOST host, PCI_ACCESS_REGIONS region,
+ unsigned int features, unsigned int baseAddress,
+ unsigned int regionLength)
+{
+ unsigned int accessLow;
+ unsigned int accessHigh;
+ unsigned int accessTop = baseAddress + regionLength;
+
+ if (regionLength == 0) { /* close the region. */
+ pciDisableAccessRegion (host, region);
+ return true;
+ }
+ /* base Address is store is bits [11:0] */
+ accessLow = (baseAddress & 0xfff00000) >> 20;
+ /* All the features are update according to the defines in pci.h (to be on
+ the safe side we disable bits: [11:0] */
+ accessLow = accessLow | (features & 0xfffff000);
+ /* write to the Low Access Region register */
+ GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region,
+ accessLow);
+
+ accessHigh = (accessTop & 0xfff00000) >> 20;
+
+ /* write to the High Access Region register */
+ GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region,
+ accessHigh - 1);
+ return true;
+}
+
+/********************************************************************
+* pciDisableAccessRegion - Disable The given Region by writing MAX size
+* to its low Address and MIN size to its high Address.
+*
+* Inputs: PCI_ACCESS_REGIONS region - The region we to be Disabled.
+* Returns: N/A.
+*********************************************************************/
+void pciDisableAccessRegion (PCI_HOST host, PCI_ACCESS_REGIONS region)
+{
+ /* writing back the registers default values. */
+ GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region,
+ 0x01001fff);
+ GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, 0);
+}
+
+/********************************************************************
+* pciArbiterEnable - Enables PCI-0`s Arbitration mechanism.
+*
+* Inputs: N/A
+* Returns: true.
+*********************************************************************/
+bool pciArbiterEnable (PCI_HOST host)
+{
+ unsigned int regData;
+
+ GT_REG_READ (pci_arbiter_control[host], &regData);
+ GT_REG_WRITE (pci_arbiter_control[host], regData | BIT31);
+ return true;
+}
+
+/********************************************************************
+* pciArbiterDisable - Disable PCI-0`s Arbitration mechanism.
+*
+* Inputs: N/A
+* Returns: true
+*********************************************************************/
+bool pciArbiterDisable (PCI_HOST host)
+{
+ unsigned int regData;
+
+ GT_REG_READ (pci_arbiter_control[host], &regData);
+ GT_REG_WRITE (pci_arbiter_control[host], regData & 0x7fffffff);
+ return true;
+}
+
+/********************************************************************
+* pciParkingDisable - Park on last option disable, with this function you can
+* disable the park on last mechanism for each agent.
+* disabling this option for all agents results parking
+* on the internal master.
+*
+* Inputs: PCI_AGENT_PARK internalAgent - parking Disable for internal agent.
+* PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent.
+* PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent.
+* PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent.
+* PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent.
+* PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent.
+* PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent.
+* Returns: true
+*********************************************************************/
+bool pciParkingDisable (PCI_HOST host, PCI_AGENT_PARK internalAgent,
+ PCI_AGENT_PARK externalAgent0,
+ PCI_AGENT_PARK externalAgent1,
+ PCI_AGENT_PARK externalAgent2,
+ PCI_AGENT_PARK externalAgent3,
+ PCI_AGENT_PARK externalAgent4,
+ PCI_AGENT_PARK externalAgent5)
+{
+ unsigned int regData;
+ unsigned int writeData;
+
+ GT_REG_READ (pci_arbiter_control[host], &regData);
+ writeData = (internalAgent << 14) + (externalAgent0 << 15) +
+ (externalAgent1 << 16) + (externalAgent2 << 17) +
+ (externalAgent3 << 18) + (externalAgent4 << 19) +
+ (externalAgent5 << 20);
+ regData = (regData & ~(0x7f << 14)) | writeData;
+ GT_REG_WRITE (pci_arbiter_control[host], regData);
+ return true;
+}
+
+/********************************************************************
+* pciSetRegionSnoopMode - This function modifys one of the 4 regions which
+* supports Cache Coherency in the PCI_n interface.
+* Inputs: region - One of the four regions.
+* snoopType - There is four optional Types:
+* 1. No Snoop.
+* 2. Snoop to WT region.
+* 3. Snoop to WB region.
+* 4. Snoop & Invalidate to WB region.
+* baseAddress - Base Address of this region.
+* regionLength - Region length.
+* Returns: false if one of the parameters is wrong otherwise return true.
+*********************************************************************/
+bool pciSetRegionSnoopMode (PCI_HOST host, PCI_SNOOP_REGION region,
+ PCI_SNOOP_TYPE snoopType,
+ unsigned int baseAddress,
+ unsigned int regionLength)
+{
+ unsigned int snoopXbaseAddress;
+ unsigned int snoopXtopAddress;
+ unsigned int data;
+ unsigned int snoopHigh = baseAddress + regionLength;
+
+ if ((region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB))
+ return false;
+ snoopXbaseAddress =
+ pci_snoop_control_base_0_low[host] + 0x10 * region;
+ snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region;
+ if (regionLength == 0) { /* closing the region */
+ GT_REG_WRITE (snoopXbaseAddress, 0x0000ffff);
+ GT_REG_WRITE (snoopXtopAddress, 0);
+ return true;
+ }
+ baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */
+ data = (baseAddress >> 20) | snoopType << 12;
+ GT_REG_WRITE (snoopXbaseAddress, data);
+ snoopHigh = (snoopHigh & 0xfff00000) >> 20;
+ GT_REG_WRITE (snoopXtopAddress, snoopHigh - 1);
+ return true;
+}
+
+/*
+ *
+ */
+
+static int gt_read_config_dword (struct pci_controller *hose,
+ pci_dev_t dev, int offset, u32 * value)
+{
+ int bus = PCI_BUS (dev);
+
+ if ((bus == local_buses[0]) || (bus == local_buses[1])) {
+ *value = pciReadConfigReg ((PCI_HOST) hose->cfg_addr, offset,
+ PCI_DEV (dev));
+ } else {
+ *value = pciOverBridgeReadConfigReg ((PCI_HOST) hose->
+ cfg_addr, offset,
+ PCI_DEV (dev), bus);
+ }
+ return 0;
+}
+
+static int gt_write_config_dword (struct pci_controller *hose,
+ pci_dev_t dev, int offset, u32 value)
+{
+ int bus = PCI_BUS (dev);
+
+ if ((bus == local_buses[0]) || (bus == local_buses[1])) {
+ pciWriteConfigReg ((PCI_HOST) hose->cfg_addr, offset,
+ PCI_DEV (dev), value);
+ } else {
+ pciOverBridgeWriteConfigReg ((PCI_HOST) hose->cfg_addr,
+ offset, PCI_DEV (dev), value,
+ bus);
+ }
+ return 0;
+}
+
+/*
+ *
+ */
+
+static void gt_setup_ide (struct pci_controller *hose,
+ pci_dev_t dev, struct pci_config_table *entry)
+{
+ static const int ide_bar[] = { 8, 4, 8, 4, 0, 0 };
+ u32 bar_response, bar_value;
+ int bar;
+
+ for (bar = 0; bar < 6; bar++) {
+ pci_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4,
+ 0x0);
+ pci_read_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4,
+ &bar_response);
+
+ pciauto_region_allocate (bar_response &
+ PCI_BASE_ADDRESS_SPACE_IO ? hose->
+ pci_io : hose->pci_mem, ide_bar[bar],
+ &bar_value);
+
+ pci_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4,
+ bar_value);
+ }
+}
+
+#ifndef CONFIG_P3G4
+static void gt_fixup_irq (struct pci_controller *hose, pci_dev_t dev)
+{
+ unsigned char pin, irq;
+
+ pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &pin);
+
+ if (pin == 1) { /* only allow INT A */
+ irq = pci_irq_swizzle[(PCI_HOST) hose->
+ cfg_addr][PCI_DEV (dev)];
+ if (irq)
+ pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
+ }
+}
+#endif
+
+struct pci_config_table gt_config_table[] = {
+ {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide},
+
+ {}
+};
+
+struct pci_controller pci0_hose = {
+#ifndef CONFIG_P3G4
+ fixup_irq:gt_fixup_irq,
+#endif
+ config_table:gt_config_table,
+};
+
+struct pci_controller pci1_hose = {
+#ifndef CONFIG_P3G4
+ fixup_irq:gt_fixup_irq,
+#endif
+ config_table:gt_config_table,
+};
+
+void pci_init_board (void)
+{
+ unsigned int command;
+
+ pci0_hose.first_busno = 0;
+ pci0_hose.last_busno = 0xff;
+ local_buses[0] = pci0_hose.first_busno;
+ /* PCI memory space */
+ pci_set_region (pci0_hose.regions + 0,
+ CONFIG_SYS_PCI0_0_MEM_SPACE,
+ CONFIG_SYS_PCI0_0_MEM_SPACE,
+ CONFIG_SYS_PCI0_MEM_SIZE, PCI_REGION_MEM);
+
+ /* PCI I/O space */
+ pci_set_region (pci0_hose.regions + 1,
+ CONFIG_SYS_PCI0_IO_SPACE_PCI,
+ CONFIG_SYS_PCI0_IO_SPACE, CONFIG_SYS_PCI0_IO_SIZE, PCI_REGION_IO);
+
+ pci_set_ops (&pci0_hose,
+ pci_hose_read_config_byte_via_dword,
+ pci_hose_read_config_word_via_dword,
+ gt_read_config_dword,
+ pci_hose_write_config_byte_via_dword,
+ pci_hose_write_config_word_via_dword,
+ gt_write_config_dword);
+
+ pci0_hose.region_count = 2;
+
+ pci0_hose.cfg_addr = (unsigned int *) PCI_HOST0;
+
+ pci_register_hose (&pci0_hose);
+
+#ifndef CONFIG_P3G4
+ pciArbiterEnable (PCI_HOST0);
+ pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1);
+#endif
+
+ command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MASTER;
+ pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command);
+
+ pci0_hose.last_busno = pci_hose_scan (&pci0_hose);
+
+ command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MEMORY;
+ pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command);
+
+ pci1_hose.first_busno = pci0_hose.last_busno + 1;
+ pci1_hose.last_busno = 0xff;
+ pci1_hose.current_busno = pci0_hose.current_busno;
+ local_buses[1] = pci1_hose.first_busno;
+
+ /* PCI memory space */
+ pci_set_region (pci1_hose.regions + 0,
+ CONFIG_SYS_PCI1_0_MEM_SPACE,
+ CONFIG_SYS_PCI1_0_MEM_SPACE,
+ CONFIG_SYS_PCI1_MEM_SIZE, PCI_REGION_MEM);
+
+ /* PCI I/O space */
+ pci_set_region (pci1_hose.regions + 1,
+ CONFIG_SYS_PCI1_IO_SPACE_PCI,
+ CONFIG_SYS_PCI1_IO_SPACE, CONFIG_SYS_PCI1_IO_SIZE, PCI_REGION_IO);
+
+ pci_set_ops (&pci1_hose,
+ pci_hose_read_config_byte_via_dword,
+ pci_hose_read_config_word_via_dword,
+ gt_read_config_dword,
+ pci_hose_write_config_byte_via_dword,
+ pci_hose_write_config_word_via_dword,
+ gt_write_config_dword);
+
+ pci1_hose.region_count = 2;
+
+ pci1_hose.cfg_addr = (unsigned int *) PCI_HOST1;
+
+ pci_register_hose (&pci1_hose);
+
+#ifndef CONFIG_P3G4
+ pciArbiterEnable (PCI_HOST1);
+ pciParkingDisable (PCI_HOST1, 1, 1, 1, 1, 1, 1, 1);
+#endif
+
+ command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MASTER;
+ pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command);
+
+ pci1_hose.last_busno = pci_hose_scan (&pci1_hose);
+
+ command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF);
+ command |= PCI_COMMAND_MEMORY;
+ pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command);
+}
diff --git a/board/evb64260/sdram_init.c b/board/evb64260/sdram_init.c
new file mode 100644
index 0000000..6f725f6
--- /dev/null
+++ b/board/evb64260/sdram_init.c
@@ -0,0 +1,666 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* sdram_init.c - automatic memory sizing */
+
+#include <common.h>
+#include <74xx_7xx.h>
+#include <galileo/memory.h>
+#include <galileo/pci.h>
+#include <galileo/gt64260R.h>
+#include <net.h>
+#include <linux/compiler.h>
+
+#include "eth.h"
+#include "mpsc.h"
+#include "i2c.h"
+#include "64260.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* #define DEBUG */
+#define MAP_PCI
+
+#ifdef DEBUG
+#define DP(x) x
+#else
+#define DP(x)
+#endif
+
+#define GB (1 << 30)
+
+/* structure to store the relevant information about an sdram bank */
+typedef struct sdram_info {
+ uchar drb_size;
+ uchar registered, ecc;
+ uchar tpar;
+ uchar tras_clocks;
+ uchar burst_len;
+ uchar banks, slot;
+ int size; /* detected size, not from I2C but from dram_size() */
+} sdram_info_t;
+
+#ifdef DEBUG
+void dump_dimm_info (struct sdram_info *d)
+{
+ static const char *ecc_legend[] = { "", " Parity", " ECC" };
+
+ printf ("dimm%s %sDRAM: %dMibytes:\n",
+ ecc_legend[d->ecc],
+ d->registered ? "R" : "", (d->size >> 20));
+ printf (" drb=%d tpar=%d tras=%d burstlen=%d banks=%d slot=%d\n",
+ d->drb_size, d->tpar, d->tras_clocks, d->burst_len,
+ d->banks, d->slot);
+}
+#endif
+
+static int
+memory_map_bank (unsigned int bankNo,
+ unsigned int bankBase, unsigned int bankLength)
+{
+#ifdef DEBUG
+ if (bankLength > 0) {
+ printf ("mapping bank %d at %08x - %08x\n",
+ bankNo, bankBase, bankBase + bankLength - 1);
+ } else {
+ printf ("unmapping bank %d\n", bankNo);
+ }
+#endif
+
+ memoryMapBank (bankNo, bankBase, bankLength);
+
+ return 0;
+}
+
+#ifdef MAP_PCI
+static int
+memory_map_bank_pci (unsigned int bankNo,
+ unsigned int bankBase, unsigned int bankLength)
+{
+ PCI_HOST host;
+
+ for (host = PCI_HOST0; host <= PCI_HOST1; host++) {
+ const int features =
+ PREFETCH_ENABLE |
+ DELAYED_READ_ENABLE |
+ AGGRESSIVE_PREFETCH |
+ READ_LINE_AGGRESSIVE_PREFETCH |
+ READ_MULTI_AGGRESSIVE_PREFETCH |
+ MAX_BURST_4 | PCI_NO_SWAP;
+
+ pciMapMemoryBank (host, bankNo, bankBase, bankLength);
+
+ pciSetRegionSnoopMode (host, bankNo, PCI_SNOOP_WB, bankBase,
+ bankLength);
+
+ pciSetRegionFeatures (host, bankNo, features, bankBase,
+ bankLength);
+ }
+ return 0;
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/* much of this code is based on (or is) the code in the pip405 port */
+/* thanks go to the authors of said port - Josh */
+
+
+/*
+ * translate ns.ns/10 coding of SPD timing values
+ * into 10 ps unit values
+ */
+static inline unsigned short NS10to10PS (unsigned char spd_byte)
+{
+ unsigned short ns, ns10;
+
+ /* isolate upper nibble */
+ ns = (spd_byte >> 4) & 0x0F;
+ /* isolate lower nibble */
+ ns10 = (spd_byte & 0x0F);
+
+ return (ns * 100 + ns10 * 10);
+}
+
+/*
+ * translate ns coding of SPD timing values
+ * into 10 ps unit values
+ */
+static inline unsigned short NSto10PS (unsigned char spd_byte)
+{
+ return (spd_byte * 100);
+}
+
+#ifdef CONFIG_ZUMA_V2
+static int check_dimm (uchar slot, sdram_info_t * info)
+{
+ /* assume 2 dimms, 2 banks each 256M - we dont have an
+ * dimm i2c so rely on the detection routines later */
+
+ memset (info, 0, sizeof (*info));
+
+ info->slot = slot;
+ info->banks = 2; /* Detect later */
+ info->registered = 0;
+ info->drb_size = 32; /* 16 - 256MBit, 32 - 512MBit
+ but doesn't matter, both do same
+ thing in setup_sdram() */
+ info->tpar = 3;
+ info->tras_clocks = 5;
+ info->burst_len = 4;
+#ifdef CONFIG_ECC
+ info->ecc = 0; /* Detect later */
+#endif /* CONFIG_ECC */
+ return 0;
+}
+
+#elif defined(CONFIG_P3G4)
+
+static int check_dimm (uchar slot, sdram_info_t * info)
+{
+ memset (info, 0, sizeof (*info));
+
+ if (slot)
+ return 0;
+
+ info->slot = slot;
+ info->banks = 1;
+ info->registered = 0;
+ info->drb_size = 4;
+ info->tpar = 3;
+ info->tras_clocks = 6;
+ info->burst_len = 4;
+#ifdef CONFIG_ECC
+ info->ecc = 2;
+#endif
+ return 0;
+}
+
+#else /* ! CONFIG_ZUMA_V2 && ! CONFIG_P3G4 */
+
+/* This code reads the SPD chip on the sdram and populates
+ * the array which is passed in with the relevant information */
+static int check_dimm (uchar slot, sdram_info_t * info)
+{
+ uchar addr = slot == 0 ? DIMM0_I2C_ADDR : DIMM1_I2C_ADDR;
+ int ret;
+ uchar rows, cols, sdram_banks, supp_cal, width, cal_val;
+ ulong tmemclk;
+ uchar trp_clocks, trcd_clocks;
+ uchar data[128];
+
+ get_clocks ();
+
+ tmemclk = 1000000000 / (gd->bus_clk / 100); /* in 10 ps units */
+
+#ifdef CONFIG_EVB64260_750CX
+ if (0 != slot) {
+ printf ("check_dimm: The EVB-64260-750CX only has 1 DIMM,");
+ printf (" called with slot=%d insetad!\n", slot);
+ return 0;
+ }
+#endif
+ DP (puts ("before i2c read\n"));
+
+ ret = i2c_read (addr, 0, 128, data, 0);
+
+ DP (puts ("after i2c read\n"));
+
+ /* zero all the values */
+ memset (info, 0, sizeof (*info));
+
+ if (ret) {
+ DP (printf ("No DIMM in slot %d [err = %x]\n", slot, ret));
+ return 0;
+ }
+
+ /* first, do some sanity checks */
+ if (data[2] != 0x4) {
+ printf ("Not SDRAM in slot %d\n", slot);
+ return 0;
+ }
+
+ /* get various information */
+ rows = data[3];
+ cols = data[4];
+ info->banks = data[5];
+ sdram_banks = data[17];
+ width = data[13] & 0x7f;
+
+ DP (printf
+ ("sdram_banks: %d, banks: %d\n", sdram_banks, info->banks));
+
+ /* check if the memory is registered */
+ if (data[21] & (BIT1 | BIT4))
+ info->registered = 1;
+
+#ifdef CONFIG_ECC
+ /* check for ECC/parity [0 = none, 1 = parity, 2 = ecc] */
+ info->ecc = (data[11] & 2) >> 1;
+#endif
+
+ /* bit 1 is CL2, bit 2 is CL3 */
+ supp_cal = (data[18] & 0x6) >> 1;
+
+ /* compute the relevant clock values */
+ trp_clocks = (NSto10PS (data[27]) + (tmemclk - 1)) / tmemclk;
+ trcd_clocks = (NSto10PS (data[29]) + (tmemclk - 1)) / tmemclk;
+ info->tras_clocks = (NSto10PS (data[30]) + (tmemclk - 1)) / tmemclk;
+
+ DP (printf ("trp = %d\ntrcd_clocks = %d\ntras_clocks = %d\n",
+ trp_clocks, trcd_clocks, info->tras_clocks));
+
+ /* try a CAS latency of 3 first... */
+ cal_val = 0;
+ if (supp_cal & 3) {
+ if (NS10to10PS (data[9]) <= tmemclk)
+ cal_val = 3;
+ }
+
+ /* then 2... */
+ if (supp_cal & 2) {
+ if (NS10to10PS (data[23]) <= tmemclk)
+ cal_val = 2;
+ }
+
+ DP (printf ("cal_val = %d\n", cal_val));
+
+ /* bummer, did't work... */
+ if (cal_val == 0) {
+ DP (printf ("Couldn't find a good CAS latency\n"));
+ return 0;
+ }
+
+ /* get the largest delay -- these values need to all be the same
+ * see Res#6 */
+ info->tpar = cal_val;
+ if (trp_clocks > info->tpar)
+ info->tpar = trp_clocks;
+ if (trcd_clocks > info->tpar)
+ info->tpar = trcd_clocks;
+
+ DP (printf ("tpar set to: %d\n", info->tpar));
+
+#ifdef CONFIG_SYS_BROKEN_CL2
+ if (info->tpar == 2) {
+ info->tpar = 3;
+ DP (printf ("tpar fixed-up to: %d\n", info->tpar));
+ }
+#endif
+ /* compute the module DRB size */
+ info->drb_size =
+ (((1 << (rows + cols)) * sdram_banks) * width) / _16M;
+
+ DP (printf ("drb_size set to: %d\n", info->drb_size));
+
+ /* find the burst len */
+ info->burst_len = data[16] & 0xf;
+ if ((info->burst_len & 8) == 8) {
+ info->burst_len = 1;
+ } else if ((info->burst_len & 4) == 4) {
+ info->burst_len = 0;
+ } else {
+ return 0;
+ }
+
+ info->slot = slot;
+ return 0;
+}
+#endif /* ! CONFIG_ZUMA_V2 */
+
+static int setup_sdram_common (sdram_info_t info[2])
+{
+ ulong tmp;
+ int tpar = 2, tras_clocks = 5, registered = 1;
+ __maybe_unused int ecc = 2;
+
+ if (!info[0].banks && !info[1].banks)
+ return 0;
+
+ if (info[0].banks) {
+ if (info[0].tpar > tpar)
+ tpar = info[0].tpar;
+ if (info[0].tras_clocks > tras_clocks)
+ tras_clocks = info[0].tras_clocks;
+ if (!info[0].registered)
+ registered = 0;
+ if (info[0].ecc != 2)
+ ecc = 0;
+ }
+
+ if (info[1].banks) {
+ if (info[1].tpar > tpar)
+ tpar = info[1].tpar;
+ if (info[1].tras_clocks > tras_clocks)
+ tras_clocks = info[1].tras_clocks;
+ if (!info[1].registered)
+ registered = 0;
+ if (info[1].ecc != 2)
+ ecc = 0;
+ }
+
+ /* SDRAM configuration */
+ tmp = GTREGREAD (SDRAM_CONFIGURATION);
+
+ /* Turn on physical interleave if both DIMMs
+ * have even numbers of banks. */
+ if ((info[0].banks == 0 || info[0].banks == 2) &&
+ (info[1].banks == 0 || info[1].banks == 2)) {
+ /* physical interleave on */
+ tmp &= ~(1 << 15);
+ } else {
+ /* physical interleave off */
+ tmp |= (1 << 15);
+ }
+
+ tmp |= (registered << 17);
+
+ /* Use buffer 1 to return read data to the CPU
+ * See Res #12 */
+ tmp |= (1 << 26);
+
+ GT_REG_WRITE (SDRAM_CONFIGURATION, tmp);
+ DP (printf ("SDRAM config: %08x\n", GTREGREAD (SDRAM_CONFIGURATION)));
+
+ /* SDRAM timing */
+ tmp = (((tpar == 3) ? 2 : 1) |
+ (((tpar == 3) ? 2 : 1) << 2) |
+ (((tpar == 3) ? 2 : 1) << 4) | (tras_clocks << 8));
+
+#ifdef CONFIG_ECC
+ /* Setup ECC */
+ if (ecc == 2)
+ tmp |= 1 << 13;
+#endif /* CONFIG_ECC */
+
+ GT_REG_WRITE (SDRAM_TIMING, tmp);
+ DP (printf ("SDRAM timing: %08x (%d,%d,%d,%d)\n",
+ GTREGREAD (SDRAM_TIMING), tpar, tpar, tpar, tras_clocks));
+
+ /* SDRAM address decode register */
+ /* program this with the default value */
+ GT_REG_WRITE (SDRAM_ADDRESS_DECODE, 0x2);
+ DP (printf ("SDRAM decode: %08x\n",
+ GTREGREAD (SDRAM_ADDRESS_DECODE)));
+
+ return 0;
+}
+
+/* sets up the GT properly with information passed in */
+static int setup_sdram (sdram_info_t * info)
+{
+ ulong tmp;
+ ulong *addr = 0;
+ __maybe_unused ulong check;
+ int i;
+
+ /* sanity checking */
+ if (!info->banks)
+ return 0;
+
+ /* ---------------------------- */
+ /* Program the GT with the discovered data */
+
+ /* bank parameters */
+ tmp = (0xf << 16); /* leave all virt bank pages open */
+
+ DP (printf ("drb_size: %d\n", info->drb_size));
+ switch (info->drb_size) {
+ case 1:
+ tmp |= (1 << 14);
+ break;
+ case 4:
+ case 8:
+ tmp |= (2 << 14);
+ break;
+ case 16:
+ case 32:
+ tmp |= (3 << 14);
+ break;
+ default:
+ printf ("Error in dram size calculation\n");
+ return 1;
+ }
+
+ /* SDRAM bank parameters */
+ /* the param registers for slot 1 (banks 2+3) are offset by 0x8 */
+ GT_REG_WRITE (SDRAM_BANK0PARAMETERS + (info->slot * 0x8), tmp);
+ GT_REG_WRITE (SDRAM_BANK1PARAMETERS + (info->slot * 0x8), tmp);
+ DP (printf
+ ("SDRAM bankparam slot %d (bank %d+%d): %08lx\n", info->slot,
+ info->slot * 2, (info->slot * 2) + 1, tmp));
+
+ /* set the SDRAM configuration for each bank */
+ for (i = info->slot * 2; i < ((info->slot * 2) + info->banks); i++) {
+ DP (printf ("*** Running a MRS cycle for bank %d ***\n", i));
+
+ /* map the bank */
+ memory_map_bank (i, 0, GB / 4);
+
+ /* set SDRAM mode */
+ GT_REG_WRITE (SDRAM_OPERATION_MODE, 0x3);
+ check = GTREGREAD (SDRAM_OPERATION_MODE);
+
+ /* dummy write */
+ *addr = 0;
+
+ /* wait for the command to complete */
+ while ((GTREGREAD (SDRAM_OPERATION_MODE) & (1 << 31)) == 0);
+
+ /* switch back to normal operation mode */
+ GT_REG_WRITE (SDRAM_OPERATION_MODE, 0);
+ check = GTREGREAD (SDRAM_OPERATION_MODE);
+
+ /* unmap the bank */
+ memory_map_bank (i, 0, 0);
+ DP (printf ("*** MRS cycle for bank %d done ***\n", i));
+ }
+
+ return 0;
+}
+
+/*
+ * Check memory range for valid RAM. A simple memory test determines
+ * the actually available RAM size between addresses `base' and
+ * `base + maxsize'. Some (not all) hardware errors are detected:
+ * - short between address lines
+ * - short between data lines
+ */
+static long int dram_size (long int *base, long int maxsize)
+{
+ volatile long int *addr, *b = base;
+ long int cnt, val, save1, save2;
+
+#define STARTVAL (1<<20) /* start test at 1M */
+ for (cnt = STARTVAL / sizeof (long); cnt < maxsize / sizeof (long);
+ cnt <<= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ save1 = *addr; /* save contents of addr */
+ save2 = *b; /* save contents of base */
+
+ *addr = cnt; /* write cnt to addr */
+ *b = 0; /* put null at base */
+
+ /* check at base address */
+ if ((*b) != 0) {
+ *addr = save1; /* restore *addr */
+ *b = save2; /* restore *b */
+ return (0);
+ }
+ val = *addr; /* read *addr */
+
+ *addr = save1;
+ *b = save2;
+
+ if (val != cnt) {
+ /* fix boundary condition.. STARTVAL means zero */
+ if (cnt == STARTVAL / sizeof (long))
+ cnt = 0;
+ return (cnt * sizeof (long));
+ }
+ }
+ return maxsize;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* U-Boot interface function to SDRAM init - this is where all the
+ * controlling logic happens */
+phys_size_t initdram (int board_type)
+{
+ ulong checkbank[4] = {[0 ... 3] = 0 };
+ int bank_no;
+ ulong total;
+ int nhr;
+ sdram_info_t dimm_info[2];
+
+
+ /* first, use the SPD to get info about the SDRAM */
+
+ /* check the NHR bit and skip mem init if it's already done */
+ nhr = get_hid0 () & (1 << 16);
+
+ if (nhr) {
+ printf ("Skipping SDRAM setup due to NHR bit being set\n");
+ } else {
+ /* DIMM0 */
+ check_dimm (0, &dimm_info[0]);
+
+ /* DIMM1 */
+#ifndef CONFIG_EVB64260_750CX /* EVB64260_750CX has only 1 DIMM */
+ check_dimm (1, &dimm_info[1]);
+#else /* CONFIG_EVB64260_750CX */
+ memset (&dimm_info[1], 0, sizeof (sdram_info_t));
+#endif
+
+ /* unmap all banks */
+ memory_map_bank (0, 0, 0);
+ memory_map_bank (1, 0, 0);
+ memory_map_bank (2, 0, 0);
+ memory_map_bank (3, 0, 0);
+
+ /* Now, program the GT with the correct values */
+ if (setup_sdram_common (dimm_info)) {
+ printf ("Setup common failed.\n");
+ }
+
+ if (setup_sdram (&dimm_info[0])) {
+ printf ("Setup for DIMM1 failed.\n");
+ }
+
+ if (setup_sdram (&dimm_info[1])) {
+ printf ("Setup for DIMM2 failed.\n");
+ }
+
+ /* set the NHR bit */
+ set_hid0 (get_hid0 () | (1 << 16));
+ }
+ /* next, size the SDRAM banks */
+
+ total = 0;
+ if (dimm_info[0].banks > 0)
+ checkbank[0] = 1;
+ if (dimm_info[0].banks > 1)
+ checkbank[1] = 1;
+ if (dimm_info[0].banks > 2)
+ printf ("Error, SPD claims DIMM1 has >2 banks\n");
+
+ if (dimm_info[1].banks > 0)
+ checkbank[2] = 1;
+ if (dimm_info[1].banks > 1)
+ checkbank[3] = 1;
+ if (dimm_info[1].banks > 2)
+ printf ("Error, SPD claims DIMM2 has >2 banks\n");
+
+ /* Generic dram sizer: works even if we don't have i2c DIMMs,
+ * as long as the timing settings are more or less correct */
+
+ /*
+ * pass 1: size all the banks, using first bat (0-256M)
+ * limitation: we only support 256M per bank due to
+ * us only having 1 BAT for all DRAM
+ */
+ for (bank_no = 0; bank_no < CONFIG_SYS_DRAM_BANKS; bank_no++) {
+ /* skip over banks that are not populated */
+ if (!checkbank[bank_no])
+ continue;
+
+ DP (printf ("checking bank %d\n", bank_no));
+
+ memory_map_bank (bank_no, 0, GB / 4);
+ checkbank[bank_no] = dram_size (NULL, GB / 4);
+ memory_map_bank (bank_no, 0, 0);
+
+ DP (printf ("bank %d %08lx\n", bank_no, checkbank[bank_no]));
+ }
+
+ /*
+ * pass 2: contiguously map each bank into physical address
+ * space.
+ */
+ dimm_info[0].banks = dimm_info[1].banks = 0;
+ for (bank_no = 0; bank_no < CONFIG_SYS_DRAM_BANKS; bank_no++) {
+ if (!checkbank[bank_no])
+ continue;
+
+ dimm_info[bank_no / 2].banks++;
+ dimm_info[bank_no / 2].size += checkbank[bank_no];
+
+ memory_map_bank (bank_no, total, checkbank[bank_no]);
+#ifdef MAP_PCI
+ memory_map_bank_pci (bank_no, total, checkbank[bank_no]);
+#endif
+ total += checkbank[bank_no];
+ }
+
+#ifdef CONFIG_ECC
+#ifdef CONFIG_ZUMA_V2
+ /*
+ * We always enable ECC when bank 2 and 3 are unpopulated
+ * If we 2 or 3 are populated, we CAN'T support ECC.
+ * (Zuma boards only support ECC in banks 0 and 1; assume that
+ * in that configuration, ECC chips are mounted, even for stacked
+ * chips)
+ */
+ if (checkbank[2] == 0 && checkbank[3] == 0) {
+ dimm_info[0].ecc = 2;
+ GT_REG_WRITE (SDRAM_TIMING,
+ GTREGREAD (SDRAM_TIMING) | (1 << 13));
+ /* TODO: do we have to run MRS cycles again? */
+ }
+#endif /* CONFIG_ZUMA_V2 */
+
+ if (GTREGREAD (SDRAM_TIMING) & (1 << 13)) {
+ puts ("[ECC] ");
+ }
+#endif /* CONFIG_ECC */
+
+#ifdef DEBUG
+ dump_dimm_info (&dimm_info[0]);
+ dump_dimm_info (&dimm_info[1]);
+#endif
+ /* TODO: return at MOST 256M? */
+ /* return total > GB/4 ? GB/4 : total; */
+ return total;
+}
diff --git a/board/evb64260/serial.c b/board/evb64260/serial.c
new file mode 100644
index 0000000..b9ca1d7
--- /dev/null
+++ b/board/evb64260/serial.c
@@ -0,0 +1,192 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * serial.c - serial support for the gal ev board
+ */
+
+/* supports both the 16650 duart and the MPSC */
+
+#include <common.h>
+#include <command.h>
+#include <galileo/memory.h>
+#include <serial.h>
+#include <linux/compiler.h>
+
+#if (defined CONFIG_SYS_INIT_CHAN1) || (defined CONFIG_SYS_INIT_CHAN2)
+#include <ns16550.h>
+#endif
+
+#include "serial.h"
+
+#include "mpsc.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if (defined CONFIG_SYS_INIT_CHAN1) || (defined CONFIG_SYS_INIT_CHAN2)
+const NS16550_t COM_PORTS[] = { (NS16550_t) CONFIG_SYS_NS16550_COM1,
+ (NS16550_t) CONFIG_SYS_NS16550_COM2 };
+#endif
+
+#ifdef CONFIG_MPSC
+
+static int evb64260_serial_init(void)
+{
+#if (defined CONFIG_SYS_INIT_CHAN1) || (defined CONFIG_SYS_INIT_CHAN2)
+ int clock_divisor = CONFIG_SYS_NS16550_CLK / 16 / gd->baudrate;
+#endif
+
+ mpsc_init(gd->baudrate);
+
+ /* init the DUART chans so that KGDB in the kernel can use them */
+#ifdef CONFIG_SYS_INIT_CHAN1
+ NS16550_reinit(COM_PORTS[0], clock_divisor);
+#endif
+#ifdef CONFIG_SYS_INIT_CHAN2
+ NS16550_reinit(COM_PORTS[1], clock_divisor);
+#endif
+ return (0);
+}
+
+static void evb64260_serial_putc(const char c)
+{
+ if (c == '\n')
+ mpsc_putchar('\r');
+
+ mpsc_putchar(c);
+}
+
+static int evb64260_serial_getc(void)
+{
+ return mpsc_getchar();
+}
+
+static int evb64260_serial_tstc(void)
+{
+ return mpsc_test_char();
+}
+
+static void evb64260_serial_setbrg(void)
+{
+ galbrg_set_baudrate(CONFIG_MPSC_PORT, gd->baudrate);
+}
+
+#else /* ! CONFIG_MPSC */
+
+static int evb64260_serial_init(void)
+{
+ int clock_divisor = CONFIG_SYS_NS16550_CLK / 16 / gd->baudrate;
+
+#ifdef CONFIG_SYS_INIT_CHAN1
+ (void)NS16550_init(COM_PORTS[0], clock_divisor);
+#endif
+#ifdef CONFIG_SYS_INIT_CHAN2
+ (void)NS16550_init(COM_PORTS[1], clock_divisor);
+#endif
+
+ return (0);
+}
+
+static void evb64260_serial_putc(const char c)
+{
+ if (c == '\n')
+ NS16550_putc(COM_PORTS[CONFIG_SYS_DUART_CHAN], '\r');
+
+ NS16550_putc(COM_PORTS[CONFIG_SYS_DUART_CHAN], c);
+}
+
+static int evb64260_serial_getc(void)
+{
+ return NS16550_getc(COM_PORTS[CONFIG_SYS_DUART_CHAN]);
+}
+
+static int evb64260_serial_tstc(void)
+{
+ return NS16550_tstc(COM_PORTS[CONFIG_SYS_DUART_CHAN]);
+}
+
+static void evb64260_serial_setbrg(void)
+{
+ int clock_divisor = CONFIG_SYS_NS16550_CLK / 16 / gd->baudrate;
+
+#ifdef CONFIG_SYS_INIT_CHAN1
+ NS16550_reinit(COM_PORTS[0], clock_divisor);
+#endif
+#ifdef CONFIG_SYS_INIT_CHAN2
+ NS16550_reinit(COM_PORTS[1], clock_divisor);
+#endif
+}
+
+#endif /* CONFIG_MPSC */
+
+static struct serial_device evb64260_serial_drv = {
+ .name = "evb64260_serial",
+ .start = evb64260_serial_init,
+ .stop = NULL,
+ .setbrg = evb64260_serial_setbrg,
+ .putc = evb64260_serial_putc,
+ .puts = default_serial_puts,
+ .getc = evb64260_serial_getc,
+ .tstc = evb64260_serial_tstc,
+};
+
+void evb64260_serial_initialize(void)
+{
+ serial_register(&evb64260_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &evb64260_serial_drv;
+}
+
+#if defined(CONFIG_CMD_KGDB)
+void
+kgdb_serial_init(void)
+{
+}
+
+void
+putDebugChar (int c)
+{
+ serial_putc (c);
+}
+
+void
+putDebugStr (const char *str)
+{
+ serial_puts (str);
+}
+
+int
+getDebugChar (void)
+{
+ return serial_getc();
+}
+
+void
+kgdb_interruptible (int yes)
+{
+ return;
+}
+#endif
diff --git a/board/evb64260/serial.h b/board/evb64260/serial.h
new file mode 100644
index 0000000..bac9253
--- /dev/null
+++ b/board/evb64260/serial.h
@@ -0,0 +1,63 @@
+/* serial.h - mostly useful for DUART serial_init in serial.c */
+
+#ifndef __SERIAL_H__
+#define __SERIAL_H__
+
+#if 0
+
+#define B230400 1
+#define B115200 2
+#define B57600 4
+#define B38400 82
+#define B19200 163
+#define B9600 24
+#define B4800 651
+#define B2400 1302
+#define B1200 2604
+#define B600 5208
+#define B300 10417
+#define B150 20833
+#define B110 28409
+#define BDEFAULT B115200
+
+ /* this stuff is important to initialize
+ the DUART channels */
+
+#define Scale 0x01L /* distance between port addresses */
+#define COM1 0x000003f8 /* Keyboard */
+#define COM2 0x000002f8 /* Host */
+
+
+/* Port Definitions relative to base COM port addresses */
+#define DataIn (0x00*Scale) /* data input port */
+#define DataOut (0x00*Scale) /* data output port */
+#define BaudLsb (0x00*Scale) /* baud rate divisor least significant byte */
+#define BaudMsb (0x01*Scale) /* baud rate divisor most significant byte */
+#define Ier (0x01*Scale) /* interrupt enable register */
+#define Iir (0x02*Scale) /* interrupt identification register */
+#define Lcr (0x03*Scale) /* line control register */
+#define Mcr (0x04*Scale) /* modem control register */
+#define Lsr (0x05*Scale) /* line status register */
+#define Msr (0x06*Scale) /* modem status register */
+
+/* Bit Definitions for above ports */
+#define LcrDlab 0x80 /* b7: enable baud rate divisor registers */
+#define LcrDflt 0x03 /* b6-0: no parity, 1 stop, 8 data */
+
+#define McrRts 0x02 /* b1: request to send (I am ready to xmit) */
+#define McrDtr 0x01 /* b0: data terminal ready (I am alive ready to rcv) */
+#define McrDflt (McrRts|McrDtr)
+
+#define LsrTxD 0x6000 /* b5: transmit holding register empty (i.e. xmit OK!)*/
+ /* b6: transmitter empty */
+#define LsrRxD 0x0100 /* b0: received data ready (i.e. got a byte!) */
+
+#define MsrRi 0x0040 /* b6: ring indicator (other guy is ready to rcv) */
+#define MsrDsr 0x0020 /* b5: data set ready (other guy is alive ready to rcv */
+#define MsrCts 0x0010 /* b4: clear to send (other guy is ready to rcv) */
+
+#define IerRda 0xf /* b0: Enable received data available interrupt */
+
+#endif
+
+#endif /* __SERIAL_H__ */
diff --git a/board/evb64260/u-boot.lds b/board/evb64260/u-boot.lds
new file mode 100644
index 0000000..44c61eb
--- /dev/null
+++ b/board/evb64260/u-boot.lds
@@ -0,0 +1,102 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * u-boot.lds - linker script for U-Boot on the Galileo Eval Board.
+ */
+
+OUTPUT_ARCH(powerpc)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .text :
+ {
+ arch/powerpc/cpu/74xx_7xx/start.o (.text*)
+ *(.text*)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/env_embedded.o (.ppcenv*)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/board/evb64260/zuma_pbb.c b/board/evb64260/zuma_pbb.c
new file mode 100644
index 0000000..aa15fa0
--- /dev/null
+++ b/board/evb64260/zuma_pbb.c
@@ -0,0 +1,220 @@
+#include <common.h>
+#include <malloc.h>
+
+#if defined(CONFIG_CMD_BSP)
+#include <command.h>
+#endif
+
+#include <pci.h>
+#include <galileo/pci.h>
+#include "zuma_pbb.h"
+
+#undef DEBUG
+
+#define PAT_LO 0x00010203
+#define PAT_HI 0x04050607
+
+static PBB_DMA_REG_MAP *zuma_pbb_reg = NULL;
+static char test_buf1[2048];
+static char test_buf2[2048];
+void zuma_init_pbb(void);
+int zuma_mbox_init(void);
+int zuma_test_dma(int cmd, int size);
+
+int zuma_test_dma (int cmd, int size)
+{
+ static const char *const test_legend[] = {
+ "write", "verify",
+ "copy", "compare",
+ "write inc", "verify inc"
+ };
+ register int i, j;
+ unsigned int p1 = ((unsigned int) test_buf1 + 0xff) & (~0xff);
+ unsigned int p2 = ((unsigned int) test_buf2 + 0xff) & (~0xff);
+ volatile unsigned int *ps = (unsigned int *) p1;
+ volatile unsigned int *pd = (unsigned int *) p2;
+ unsigned int funct, pat_lo = PAT_LO, pat_hi = PAT_HI;
+ DMA_INT_STATUS stat;
+ int ret = 0;
+
+ if (!zuma_pbb_reg) {
+ printf ("not initted\n");
+ return -1;
+ }
+
+ if (cmd < 0 || cmd > 5) {
+ printf ("inv cmd %d\n", cmd);
+ return -1;
+ }
+
+ if (cmd == 2 || cmd == 3) {
+ /* not implemented */
+ return 0;
+ }
+
+ if (size <= 0 || size > 1024)
+ size = 1024;
+
+ size &= (~7); /* throw away bottom 3 bits */
+
+ p1 = ((unsigned int) test_buf1 + 0xff) & (~0xff);
+ p2 = ((unsigned int) test_buf2 + 0xff) & (~0xff);
+
+ memset ((void *) p1, 0, size);
+ memset ((void *) p2, 0, size);
+
+ for (i = 0; i < size / 4; i += 2) {
+ ps[i] = pat_lo;
+ ps[i + 1] = pat_hi;
+ if (cmd == 4 || cmd == 5) {
+ unsigned char *pl = (unsigned char *) &pat_lo;
+ unsigned char *ph = (unsigned char *) &pat_hi;
+
+ for (j = 0; j < 4; j++) {
+ pl[j] += 8;
+ ph[j] += 8;
+ }
+ }
+ }
+
+ funct = (1 << 31) | (cmd << 24) | (size);
+
+ zuma_pbb_reg->int_mask.pci_bits.chan0 =
+ EOF_RX_FLAG | EOF_TX_FLAG | EOB_TX_FLAG;
+
+ zuma_pbb_reg->debug_57 = PAT_LO; /* patl */
+ zuma_pbb_reg->debug_58 = PAT_HI; /* path */
+
+ zuma_pbb_reg->debug_54 = cpu_to_le32 (p1); /* src 0x01b0 */
+ zuma_pbb_reg->debug_55 = cpu_to_le32 (p2); /* dst 0x01b8 */
+ zuma_pbb_reg->debug_56 = cpu_to_le32 (funct); /* func, 0x01c0 */
+
+ /* give DMA time to chew on things.. dont use DRAM or PCI */
+ /* if you can avoid it. */
+ do {
+ for (i = 0; i < 1000 * 10; i++);
+ } while (le32_to_cpu (zuma_pbb_reg->debug_56) & (1 << 31));
+
+ stat.word = zuma_pbb_reg->status.word;
+ zuma_pbb_reg->int_mask.word = 0;
+
+ printf ("stat: %08x (%x)\n", stat.word, stat.pci_bits.chan0);
+
+ printf ("func: %08x\n", le32_to_cpu (zuma_pbb_reg->debug_56));
+ printf ("src @%08x: %08x %08x %08x %08x\n", p1, ps[0], ps[1], ps[2],
+ ps[3]);
+ printf ("dst @%08x: %08x %08x %08x %08x\n", p2, pd[0], pd[1], pd[2],
+ pd[3]);
+ printf ("func: %08x\n", le32_to_cpu (zuma_pbb_reg->debug_56));
+
+
+ if (cmd == 0 || cmd == 4) {
+ /* this is a write */
+ if (!(stat.pci_bits.chan0 & EOF_RX_FLAG) || /* not done */
+ (memcmp ((void *) ps, (void *) pd, size) != 0)) { /* cmp error */
+ for (i = 0; i < size / 4; i += 2) {
+ if ((ps[i] != pd[i]) || (ps[i + 1] != pd[i + 1])) {
+ printf ("s @%p:%08x %08x\n", &ps[i], ps[i], ps[i + 1]);
+ printf ("d @%p:%08x %08x\n", &pd[i], pd[i], pd[i + 1]);
+ }
+ }
+ ret = -1;
+ }
+ } else {
+ /* this is a verify */
+ if (!(stat.pci_bits.chan0 & EOF_TX_FLAG) || /* not done */
+ (stat.pci_bits.chan0 & EOB_TX_FLAG)) { /* cmp error */
+ printf ("%08x: %08x %08x\n",
+ le32_to_cpu (zuma_pbb_reg->debug_63),
+ zuma_pbb_reg->debug_61, zuma_pbb_reg->debug_62);
+ ret = -1;
+ }
+ }
+
+ printf ("%s cmd %d, %d bytes: %s!\n", test_legend[cmd], cmd, size,
+ (ret == 0) ? "PASSED" : "FAILED");
+ return 0;
+}
+
+void zuma_init_pbb (void)
+{
+ unsigned int iobase;
+ pci_dev_t dev =
+ pci_find_device (VENDOR_ID_ZUMA, DEVICE_ID_ZUMA_PBB, 0);
+
+ if (dev == -1) {
+ printf ("no zuma pbb\n");
+ return;
+ }
+
+ pci_read_config_dword (dev, PCI_BASE_ADDRESS_0, &iobase);
+
+ iobase &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ zuma_pbb_reg = (PBB_DMA_REG_MAP *)iobase;
+
+
+ if (!zuma_pbb_reg) {
+ printf ("zuma pbb bar none! (hah hah, get it?)\n");
+ return;
+ }
+
+ zuma_pbb_reg->int_mask.word = 0;
+
+ printf ("pbb @ %p v%d.%d, timestamp %08x\n", zuma_pbb_reg,
+ zuma_pbb_reg->version.pci_bits.rev_major,
+ zuma_pbb_reg->version.pci_bits.rev_minor,
+ zuma_pbb_reg->timestamp);
+
+}
+
+#if defined(CONFIG_CMD_BSP)
+
+static int last_cmd = 4; /* write increment */
+static int last_size = 64;
+
+int
+do_zuma_init_pbb (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ zuma_init_pbb ();
+ return 0;
+}
+
+int
+do_zuma_test_dma (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ if (argc > 1) {
+ last_cmd = simple_strtoul (argv[1], NULL, 10);
+ }
+ if (argc > 2) {
+ last_size = simple_strtoul (argv[2], NULL, 10);
+ }
+ zuma_test_dma (last_cmd, last_size);
+ return 0;
+}
+
+int
+do_zuma_init_mbox (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ zuma_mbox_init ();
+ return 0;
+}
+
+U_BOOT_CMD(
+ zinit, 1, 0, do_zuma_init_pbb,
+ "init zuma pbb",
+ "\n"
+);
+U_BOOT_CMD(
+ zdtest, 3, 1, do_zuma_test_dma,
+ "run dma test",
+ "[cmd [count]]\n"
+ " - run dma cmd (w=0,v=1,cp=2,cmp=3,wi=4,vi=5), count bytes"
+);
+U_BOOT_CMD(
+ zminit, 1, 0, do_zuma_init_mbox,
+ "init zuma mbox",
+ "\n"
+);
+
+#endif
diff --git a/board/evb64260/zuma_pbb.h b/board/evb64260/zuma_pbb.h
new file mode 100644
index 0000000..300b2fe
--- /dev/null
+++ b/board/evb64260/zuma_pbb.h
@@ -0,0 +1,346 @@
+#ifndef ZUMA_PBB_H
+#define ZUMA_PBB_H
+
+#define MAX_NUM_BUFFER_PER_RING 32
+
+#ifdef __BIG_ENDIAN
+#define cpu_bits _be_s_bits /* use with le32_to_cpu only */
+#define pci_bits _be_bits /* may contain swapped bytes,
+ but dont need le32_to_cpu */
+#endif
+
+#ifdef __LITTLE_ENDIAN
+#define cpu_bits _le_bits
+#define pci_bits _le_bits
+#endif
+
+#define VENDOR_ID_ZUMA 0x1172
+#define DEVICE_ID_ZUMA_PBB 0x0004
+
+#define RXDBP(chan) (&sip->rx_desc[chan].base) /* ch*8 */
+#define RXDP(chan) (&sip->rx_desc[chan].current) /* ch*8 + 4 */
+#define TXDBP(chan) (&sip->tx_desc[chan].base) /* ch*8 + 64 */
+#define TXDP(chan) (&sip->tx_desc[chan].current) /* ch*8 + 68 */
+
+#define PBB_DMA_OWN_BIT 0x80000000
+#define PBB_DMA_LAST_BIT 0x40000000
+
+#define EOF_RX_FLAG 1 /* bit 0 */
+#define EOB_RX_FLAG 2 /* bit 1 */
+#define EOF_TX_FLAG 4 /* bit 2 */
+#define EOB_TX_FLAG 8 /* bit 3 */
+
+#define TX_MODE(m) (((m)&7) << 16)
+
+#define RX_DESC(i) (cs->rx_desc[i])
+#define TX_DESC(i) (cs->tx_desc[i])
+
+#define RX_CONTROL(i) (RX_DESC(i).control.word)
+#define RX_CONTROL_SIZE(i) (RX_DESC(i).control.rx.size)
+#define TX_CONTROL(i) (TX_DESC(i).control.word)
+
+#define RX_DATA_P(i) (&RX_DESC(i).ptr)
+#define TX_DATA_P(i) (&TX_DESC(i).ptr)
+
+typedef volatile unsigned char V8;
+typedef volatile unsigned short V16;
+typedef volatile unsigned int V32;
+
+/* RAM descriptor layout */
+typedef struct _tag_dma_descriptor {
+ V32 ptr;
+ union {
+ struct {
+ V32 owner:1;
+ V32 last:1;
+ V32 reserved0: 10;
+ V32 tx_mode: 4;
+
+ V32 reserved1: 5;
+ V32 size: 11;
+ } tx;
+ struct {
+ V32 owner:1;
+ V32 last:1;
+ V32 reserved0: 14;
+
+ V32 reserved1: 5;
+ V32 size: 11;
+ } rx;
+ V32 word;
+ } control;
+} DMA_DESCRIPTOR;
+
+/*
+ * NOTE: DO NOT USE structure to write non-word values... all registers
+ * MUST be written 4 bytes at a time in SI version 0.
+ * Non-word writes will result in "unaccessed" bytes written as zero.
+ *
+ * Byte reads are allowed.
+ *
+ * V32 pads are because the registers are spaced every 8 bytes (64 bits)
+ *
+ */
+
+/* NOTE!!! 4 dwords */
+typedef struct _tag_dma_descriptor_ring {
+ DMA_DESCRIPTOR *base;
+ V32 pad1; /* skip high dword */
+ volatile DMA_DESCRIPTOR *current;
+ V32 pad3; /* skip high dword */
+} DMA_DESCRIPTOR_RING;
+
+/* 1 dword */
+typedef union _tag_dma_generic {
+ struct { /* byte 3 2 1 0 */
+ V32 chan7:4; /* bits 31-28 */
+ V32 chan6:4; /* bits 27-24 */
+ V32 chan5:4; /* bits 23-20 */
+ V32 chan4:4; /* bits 19-16 */
+ V32 chan3:4; /* bits 15-12 */
+ V32 chan2:4; /* bits 11-8 */
+ V32 chan1:4; /* bits 7-4 */
+ V32 chan0:4; /* bits 3-0 */
+ } _be_s_bits;
+ struct { /* byte 0 1 2 3 */
+ V32 chan1:4; /* bits 7-4 */
+ V32 chan0:4; /* bits 3-0 */
+ V32 chan3:4; /* bits 15-12 */
+ V32 chan2:4; /* bits 11-8 */
+ V32 chan5:4; /* bits 23-20 */
+ V32 chan4:4; /* bits 19-16 */
+ V32 chan7:4; /* bits 31-28 */
+ V32 chan6:4; /* bits 27-24 */
+ } _be_bits;
+ struct { /* byte 0 1 2 3 */
+ V32 chan0:4; /* bits 0-3 */
+ V32 chan1:4; /* bits 4-7 */
+ V32 chan2:4; /* bits 8-11 */
+ V32 chan3:4; /* bits 12-15 */
+ V32 chan4:4; /* bits 16-19 */
+ V32 chan5:4; /* bits 20-23 */
+ V32 chan6:4; /* bits 24-27 */
+ V32 chan7:4; /* bits 28-31 */
+ } _le_bits;
+ V8 byte[4];
+ V32 word;
+} DMA_RXTX_ENABLE, DMA_RX_DELETE,
+ DMA_INT_STATUS, DMA_INT_MASK,
+ DMA_RX_LEVEL_STATUS, DMA_RX_LEVEL_INT_MASK;
+
+/* 1 dword */
+typedef union _tag_dma_rx_timer{
+ struct {
+ V32 res0:8; /* bits 32-24 */
+ V32 res1:7; /* bits 23-17 */
+ V32 enable:1; /* bit 16 */
+ V32 value:16; /* bits 15-0 */
+ } _be_s_bits;
+ struct {
+ /* crosses byte boundary. must use swap. */
+ V32 s_value:16; /* bits 7-0,15-8 */
+ V32 enable:1; /* bit 16 */
+ V32 res1:7; /* bits 23-17 */
+ V32 res0:8; /* bits 32-24 */
+ } _be_bits;
+ struct {
+ V32 value:16; /* bits 0-15 */
+ V32 enable:1; /* bit 16 */
+ V32 res1:7; /* bits 17-23 */
+ V32 res0:8; /* bits 24-32 */
+ } _le_bits;
+ V8 byte[4];
+ V32 word;
+} DMA_RX_TIMER;
+
+/* NOTE!!!: 2 dwords */
+typedef struct _tag_dma_desc_level{
+ union {
+ struct {
+ V32 res1:8; /* bits 31-24 */
+ V32 res0:7; /* bits 23-17 */
+ V32 write:1; /* bit 16 */
+ V32 thresh:8; /* bits 15-8 */
+ V32 level:8; /* bits 7-0 */
+ } _be_s_bits;
+ struct {
+ V32 level:8; /* bits 7-0 */
+ V32 thresh:8; /* bits 15-8 */
+ V32 res0:7; /* bits 30-17 */
+ V32 write:1; /* bit 16 */
+ V32 res1:8; /* bits 31-24 */
+ } _be_bits;
+ struct {
+ V32 level:8; /* bits 0-7 */
+ V32 thresh:8; /* bits 8-15 */
+ V32 write:1; /* bit 16 */
+ V32 res0:7; /* bit 17-30 */
+ V32 res1:8; /* bits 24-31 */
+ } _le_bits;
+ V8 byte[4];
+ V32 word;
+ } desc;
+ V32 pad1;
+} DMA_DESC_LEVEL;
+
+typedef struct _tag_pbb_dma_reg_map {
+ /* 0-15 (0x000-0x078) */
+ DMA_DESCRIPTOR_RING rx_desc[8]; /* 4 dwords each, 128 bytes tot. */
+
+ /* 16-31 (0x080-0x0f8) */
+ DMA_DESCRIPTOR_RING tx_desc[8]; /* 4 dwords each, 128 bytes tot. */
+
+ /* 32/33 (0x100/0x108) */
+ V32 reserved_32;
+ V32 pad_32;
+ V32 reserved_33;
+ V32 pad_33;
+
+ /* 34 (0x110) */
+ DMA_RXTX_ENABLE rxtx_enable;
+ V32 pad_34;
+
+ /* 35 (0x118) */
+ DMA_RX_DELETE rx_delete;
+ V32 pad_35;
+
+ /* 36-38 (0x120-0x130) */
+ DMA_INT_STATUS status;
+ V32 pad_36;
+ DMA_INT_STATUS last_status;
+ V32 pad_37;
+ DMA_INT_MASK int_mask;
+ V32 pad_38;
+
+ /* 39/40 (0x138/0x140) */
+ union {
+ /* NOTE!! 4 dwords */
+ struct {
+ V32 channel_3:8;
+ V32 channel_2:8;
+ V32 channel_1:8;
+ V32 channel_0:8;
+ V32 pad1;
+ V32 channel_7:8;
+ V32 channel_6:8;
+ V32 channel_5:8;
+ V32 channel_4:8;
+ V32 pad3;
+ } _be_s_bits;
+ struct {
+ V32 channel_0:8;
+ V32 channel_1:8;
+ V32 channel_2:8;
+ V32 channel_3:8;
+ V32 pad1;
+ V32 channel_4:8;
+ V32 channel_5:8;
+ V32 channel_6:8;
+ V32 channel_7:8;
+ V32 pad3;
+ } _be_bits, _le_bits;
+ V8 byte[16];
+ V32 word[4];
+ } rx_size;
+
+ /* 41/42 (0x148/0x150) */
+ V32 reserved_41;
+ V32 pad_41;
+ V32 reserved_42;
+ V32 pad_42;
+
+ /* 43/44 (0x158/0x160) */
+ DMA_RX_LEVEL_STATUS rx_level_status;
+ V32 pad_43;
+ DMA_RX_LEVEL_INT_MASK rx_level_int_mask;
+ V32 pad_44;
+
+ /* 45 (0x168) */
+ DMA_RX_TIMER rx_timer;
+ V32 pad_45;
+
+ /* 46 (0x170) */
+ V32 reserved_46;
+ V32 pad_46;
+
+ /* 47 (0x178) */
+ V32 mbox_status;
+ V32 pad_47;
+
+ /* 48/49 (0x180/0x188) */
+ V32 mbox_out;
+ V32 pad_48;
+ V32 mbox_in;
+ V32 pad_49;
+
+ /* 50 (0x190) */
+ V32 config;
+ V32 pad_50;
+
+ /* 51/52 (0x198/0x1a0) */
+ V32 c2a_ctr;
+ V32 pad_51;
+ V32 a2c_ctr;
+ V32 pad_52;
+
+ /* 53 (0x1a8) */
+ union {
+ struct {
+ V32 rev_major:8; /* bits 31-24 */
+ V32 rev_minor:8; /* bits 23-16 */
+ V32 reserved:16; /* bits 15-0 */
+ } _be_s_bits;
+ struct {
+ V32 s_reserved:16; /* bits 7-0, 15-8 */
+ V32 rev_minor:8; /* bits 23-16 */
+ V32 rev_major:8; /* bits 31-24 */
+ } _be_bits;
+ struct {
+ V32 reserved:16; /* bits 0-15 */
+ V32 rev_minor:8; /* bits 16-23 */
+ V32 rev_major:8; /* bits 24-31 */
+ } _le_bits;
+ V8 byte[4];
+ V32 word;
+ } version;
+ V32 pad_53;
+
+ /* 54-59 (0x1b0-0x1d8) */
+ V32 debug_54;
+ V32 pad_54;
+ V32 debug_55;
+ V32 pad_55;
+ V32 debug_56;
+ V32 pad_56;
+ V32 debug_57;
+ V32 pad_57;
+ V32 debug_58;
+ V32 pad_58;
+ V32 debug_59;
+ V32 pad_59;
+
+ /* 60 (0x1e0) */
+ V32 timestamp;
+ V32 pad_60;
+
+ /* 61-63 (0x1e8-0x1f8) */
+ V32 debug_61;
+ V32 pad_61;
+ V32 debug_62;
+ V32 pad_62;
+ V32 debug_63;
+ V32 pad_63;
+
+ /* 64-71 (0x200 - 0x238) */
+ DMA_DESC_LEVEL rx_desc_level[8]; /* 2 dwords each, 32 bytes tot. */
+
+ /* 72-98 (0x240 - 0x2f8) */
+ /* reserved */
+
+ /* 96-127 (0x300 - 0x3f8) */
+ /* mirrors (0x100 - 0x1f8) */
+
+} PBB_DMA_REG_MAP;
+
+
+#endif /* ZUMA_PBB_H */
diff --git a/board/evb64260/zuma_pbb_mbox.c b/board/evb64260/zuma_pbb_mbox.c
new file mode 100644
index 0000000..621c64c
--- /dev/null
+++ b/board/evb64260/zuma_pbb_mbox.c
@@ -0,0 +1,208 @@
+#include <common.h>
+#include <galileo/pci.h>
+#include <net.h>
+#include <pci.h>
+
+#include "zuma_pbb.h"
+#include "zuma_pbb_mbox.h"
+
+
+struct _zuma_mbox_dev zuma_mbox_dev;
+
+
+static int zuma_mbox_write(struct _zuma_mbox_dev *dev, unsigned int data)
+{
+ unsigned int status, count = 0, i;
+
+ status = (volatile int) le32_to_cpu(dev->sip->mbox_status);
+
+ while ((status & OUT_PENDING) && count < 1000) {
+ count++;
+ for (i = 0; i < 1000; i++)
+ ;
+ status = (volatile int) le32_to_cpu(dev->sip->mbox_status);
+ }
+ if (count < 1000) {
+ /* if SET it means msg pending */
+ /* printf("mbox real write %08x\n",data); */
+ dev->sip->mbox_out = cpu_to_le32(data);
+ return 4;
+ }
+
+ printf("mbox tx timeout\n");
+ return 0;
+}
+
+static int zuma_mbox_read(struct _zuma_mbox_dev *dev, unsigned int *data)
+{
+ unsigned int status, count = 0, i;
+
+ status = (volatile int) le32_to_cpu(dev->sip->mbox_status);
+
+ while (!(status & IN_VALID) && count < 1000) {
+ count++;
+ for (i = 0; i < 1000; i++)
+ ;
+ status = (volatile int) le32_to_cpu(dev->sip->mbox_status);
+ }
+ if (count < 1000) {
+ /* if SET it means msg pending */
+ *data = le32_to_cpu(dev->sip->mbox_in);
+ /*printf("mbox real read %08x\n", *data); */
+ return 4;
+ }
+ printf("mbox rx timeout\n");
+ return 0;
+}
+
+static int zuma_mbox_do_one_mailbox(unsigned int out, unsigned int *in)
+{
+ int ret;
+
+ ret = zuma_mbox_write(&zuma_mbox_dev, out);
+ /*printf("write 0x%08x (%d bytes)\n", out, ret); */
+ if (ret != 4)
+ return -1;
+ ret = zuma_mbox_read(&zuma_mbox_dev, in);
+ /*printf("read 0x%08x (%d bytes)\n", *in, ret); */
+ if (ret != 4)
+ return -1;
+ return 0;
+}
+
+
+#define RET_IF_FAILED(x) if ((x) == -1) return -1
+
+static int zuma_mbox_do_all_mailbox(void)
+{
+ unsigned int data_in;
+ unsigned short sdata_in;
+
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_START, &data_in));
+
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_MACL, &data_in));
+ memcpy(zuma_acc_mac + 2, &data_in, 4);
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_MACH, &data_in));
+ sdata_in = data_in & 0xffff;
+ memcpy(zuma_acc_mac, &sdata_in, 2);
+
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_IP, &data_in));
+ zuma_ip = data_in;
+
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_SLOT, &data_in));
+ zuma_slot_bac = data_in >> 3;
+
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_BAUD, &data_in));
+ zuma_console_baud = data_in & 0xffff;
+ zuma_debug_baud = data_in >> 16;
+
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox
+ (ZUMA_MBOXMSG_ENG_PRV_MACL, &data_in));
+ memcpy(zuma_prv_mac + 2, &data_in, 4);
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox
+ (ZUMA_MBOXMSG_ENG_PRV_MACH, &data_in));
+ sdata_in = data_in & 0xffff;
+ memcpy(zuma_prv_mac, &sdata_in, 2);
+
+ RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_DONE, &data_in));
+
+ return 0;
+}
+
+
+static void zuma_mbox_dump(void)
+{
+ unsigned short s;
+ unsigned int i;
+
+ memcpy(&s, &zuma_acc_mac, sizeof(s));
+ memcpy(&i, &zuma_acc_mac[2], sizeof(i));
+ printf("ACC MAC=%04x%08x\n", s, i);
+
+ memcpy(&s, &zuma_prv_mac, sizeof(s));
+ memcpy(&s, &zuma_prv_mac[2], sizeof(i));
+ printf("PRV MAC=%04x%08x\n", s, i);
+
+ printf("slot:bac=%d:%d\n",
+ (zuma_slot_bac >> 2) & 0xf,
+ zuma_slot_bac & 0x3);
+
+ printf("BAUD1=%d BAUD2=%d\n",
+ zuma_console_baud,
+ zuma_debug_baud);
+}
+
+
+static void zuma_mbox_setenv(void)
+{
+ char *data, buf[32];
+ unsigned char save = 0;
+
+ data = getenv("baudrate");
+
+ if (!data || (zuma_console_baud != simple_strtoul(data, NULL, 10))) {
+ sprintf(buf, "%6d", zuma_console_baud);
+ setenv("baudrate", buf);
+ save = 1;
+ printf("baudrate doesn't match from mbox\n");
+ }
+
+ ip_to_string(zuma_ip, buf);
+ setenv("ipaddr", buf);
+
+ sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ zuma_prv_mac[0],
+ zuma_prv_mac[1],
+ zuma_prv_mac[2],
+ zuma_prv_mac[3], zuma_prv_mac[4], zuma_prv_mac[5]);
+ setenv("ethaddr", buf);
+
+ sprintf(buf, "%02x", zuma_slot_bac);
+ setenv("bacslot", buf);
+
+ if (save)
+ saveenv();
+}
+
+/**
+ * zuma_mbox_init:
+ */
+
+int zuma_mbox_init(void)
+{
+ unsigned int iobase;
+
+ memset(&zuma_mbox_dev, 0, sizeof(struct _zuma_mbox_dev));
+
+ zuma_mbox_dev.dev =
+ pci_find_device(VENDOR_ID_ZUMA, DEVICE_ID_ZUMA_PBB, 0);
+
+ if (zuma_mbox_dev.dev == -1) {
+ printf("no zuma pbb\n");
+ return -1;
+ }
+
+ pci_read_config_dword(zuma_mbox_dev.dev, PCI_BASE_ADDRESS_0, &iobase);
+
+ iobase &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ zuma_mbox_dev.sip = (PBB_DMA_REG_MAP *) iobase;
+
+ zuma_mbox_dev.sip->int_mask.word = 0;
+
+ printf("pbb @ %p v%d.%d, timestamp %08x\n", zuma_mbox_dev.sip,
+ zuma_mbox_dev.sip->version.pci_bits.rev_major,
+ zuma_mbox_dev.sip->version.pci_bits.rev_minor,
+ zuma_mbox_dev.sip->timestamp);
+
+ if (zuma_mbox_do_all_mailbox() == -1) {
+ printf("mailbox failed.. no ACC?\n");
+ return -1;
+ }
+
+ zuma_mbox_dump();
+
+ zuma_mbox_setenv();
+
+ return 0;
+}
diff --git a/board/evb64260/zuma_pbb_mbox.h b/board/evb64260/zuma_pbb_mbox.h
new file mode 100644
index 0000000..b4a4c0c
--- /dev/null
+++ b/board/evb64260/zuma_pbb_mbox.h
@@ -0,0 +1,43 @@
+#define IN_VALID 1
+#define OUT_PENDING 2
+
+enum {
+ ZUMA_MBOXMSG_DONE,
+ ZUMA_MBOXMSG_MACL,
+ ZUMA_MBOXMSG_MACH,
+ ZUMA_MBOXMSG_IP,
+ ZUMA_MBOXMSG_SLOT,
+ ZUMA_MBOXMSG_RESET,
+ ZUMA_MBOXMSG_BAUD,
+ ZUMA_MBOXMSG_START,
+ ZUMA_MBOXMSG_ENG_PRV_MACL,
+ ZUMA_MBOXMSG_ENG_PRV_MACH,
+
+ MBOXMSG_LAST
+};
+
+struct zuma_mailbox_info {
+ unsigned char acc_mac[6];
+ unsigned char prv_mac[6];
+ unsigned int ip;
+ unsigned int slot_bac;
+ unsigned int console_baud;
+ unsigned int debug_baud;
+};
+
+struct _zuma_mbox_dev {
+ pci_dev_t dev;
+ PBB_DMA_REG_MAP *sip;
+ struct zuma_mailbox_info mailbox;
+};
+
+#define zuma_prv_mac zuma_mbox_dev.mailbox.prv_mac
+#define zuma_acc_mac zuma_mbox_dev.mailbox.acc_mac
+#define zuma_ip zuma_mbox_dev.mailbox.ip
+#define zuma_slot_bac zuma_mbox_dev.mailbox.slot_bac
+#define zuma_console_baud zuma_mbox_dev.mailbox.console_baud
+#define zuma_debug_baud zuma_mbox_dev.mailbox.debug_baud
+
+
+extern struct _zuma_mbox_dev zuma_mbox_dev;
+extern int zuma_mbox_init (void);
OpenPOWER on IntegriCloud