summaryrefslogtreecommitdiffstats
path: root/board
diff options
context:
space:
mode:
authorAubrey Li <aubrey.adi@gmail.com>2007-03-19 01:24:52 +0800
committerAubrey Li <aubrey.adi@gmail.com>2007-03-19 01:24:52 +0800
commit26bf7deca364a5b33f39e8f14ddd3f4081345015 (patch)
tree951854e1c59b9c13d706ef2419371f2ae9a01802 /board
parent0d93de11449390a5984b0236c3612e50f6dbb7e8 (diff)
downloadblackbird-obmc-uboot-26bf7deca364a5b33f39e8f14ddd3f4081345015.tar.gz
blackbird-obmc-uboot-26bf7deca364a5b33f39e8f14ddd3f4081345015.zip
[Blackfin][PATCH] Add BF537 stamp board support
Diffstat (limited to 'board')
-rw-r--r--board/bf537-stamp/Makefile58
-rw-r--r--board/bf537-stamp/bf537-stamp.c437
-rw-r--r--board/bf537-stamp/cmd_bf537led.c201
-rw-r--r--board/bf537-stamp/config.mk25
-rw-r--r--board/bf537-stamp/ether_bf537.c545
-rw-r--r--board/bf537-stamp/ether_bf537.h110
-rw-r--r--board/bf537-stamp/flash-defines.h123
-rw-r--r--board/bf537-stamp/flash.c403
-rw-r--r--board/bf537-stamp/nand.c106
-rw-r--r--board/bf537-stamp/post-memory.c322
-rw-r--r--board/bf537-stamp/stm_m25p64.c515
-rw-r--r--board/bf537-stamp/u-boot.lds.S190
12 files changed, 3035 insertions, 0 deletions
diff --git a/board/bf537-stamp/Makefile b/board/bf537-stamp/Makefile
new file mode 100644
index 0000000000..e4888441a9
--- /dev/null
+++ b/board/bf537-stamp/Makefile
@@ -0,0 +1,58 @@
+#
+# U-boot - Makefile
+#
+# Copyright (c) 2005-2007 Analog Device Inc.
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+
+COBJS := $(BOARD).o flash.o ether_bf537.o post-memory.o stm_m25p64.o cmd_bf537led.o nand.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS) u-boot.lds
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+u-boot.lds: u-boot.lds.S
+ $(CPP) $(CPPFLAGS) -P -Ubfin $^ > $@.tmp
+ mv -f $@.tmp $@
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/bf537-stamp/bf537-stamp.c b/board/bf537-stamp/bf537-stamp.c
new file mode 100644
index 0000000000..cc4e9985fe
--- /dev/null
+++ b/board/bf537-stamp/bf537-stamp.c
@@ -0,0 +1,437 @@
+/*
+ * U-boot - BF537.c
+ *
+ * Copyright (c) 2005 blackfin.uclinux.org
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <asm/blackfin.h>
+#include <asm/io.h>
+#include "ether_bf537.h"
+
+#define POST_WORD_ADDR 0xFF903FFC
+
+/*
+ * the bootldr command loads an address, checks to see if there
+ * is a Boot stream that the on-chip BOOTROM can understand,
+ * and loads it via the BOOTROM Callback. It is possible
+ * to also add booting from SPI, or TWI, but this function does
+ * not currently support that.
+ */
+int do_bootldr(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ ulong addr, entry;
+ ulong *data;
+
+ /* Get the address */
+ if (argc < 2) {
+ addr = load_addr;
+ } else {
+ addr = simple_strtoul(argv[1], NULL, 16);
+ }
+
+ /* Check if it is a LDR file */
+ data = (ulong *) addr;
+ if (*data == 0xFF800060 || *data == 0xFF800040 || *data == 0xFF800020) {
+ /* We want to boot from FLASH or SDRAM */
+ entry = _BOOTROM_BOOT_DXE_FLASH;
+ printf("## Booting ldr image at 0x%08lx ...\n", addr);
+ if (icache_status())
+ icache_disable();
+ if (dcache_status())
+ dcache_disable();
+
+ __asm__("R7=%[a];\n" "P0=%[b];\n" "JUMP (P0);\n":
+ :[a] "d"(addr),[b] "a"(entry)
+ :"R7", "P0");
+
+ } else {
+ printf("## No ldr image at address 0x%08lx\n", addr);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(bootldr, 2, 0, do_bootldr,
+ "bootldr - boot ldr image from memory\n",
+ "[addr]\n - boot ldr image stored in memory\n");
+
+int checkboard(void)
+{
+#if (BFIN_CPU == ADSP_BF534)
+ printf("CPU: ADSP BF534 Rev.: 0.%d\n", *pCHIPID >> 28);
+#elif (BFIN_CPU == ADSP_BF536)
+ printf("CPU: ADSP BF536 Rev.: 0.%d\n", *pCHIPID >> 28);
+#else
+ printf("CPU: ADSP BF537 Rev.: 0.%d\n", *pCHIPID >> 28);
+#endif
+ printf("Board: ADI BF537 stamp board\n");
+ printf(" Support: http://blackfin.uclinux.org/\n");
+ return 0;
+}
+
+#if defined(CONFIG_BFIN_IDE)
+
+void cf_outb(unsigned char val, volatile unsigned char *addr)
+{
+ *(addr) = val;
+ sync();
+}
+
+unsigned char cf_inb(volatile unsigned char *addr)
+{
+ volatile unsigned char c;
+
+ c = *(addr);
+ sync();
+
+ return c;
+}
+
+void cf_insw(unsigned short *sect_buf, unsigned short *addr, int words)
+{
+ int i;
+
+ for (i = 0; i < words; i++)
+ *(sect_buf + i) = *(addr);
+ sync();
+}
+
+void cf_outsw(unsigned short *addr, unsigned short *sect_buf, int words)
+{
+ int i;
+
+ for (i = 0; i < words; i++)
+ *(addr) = *(sect_buf + i);
+ sync();
+}
+#endif /* CONFIG_BFIN_IDE */
+
+long int initdram(int board_type)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+#ifdef DEBUG
+ int brate;
+ char *tmp = getenv("baudrate");
+ brate = simple_strtoul(tmp, NULL, 16);
+ printf("Serial Port initialized with Baud rate = %x\n", brate);
+ printf("SDRAM attributes:\n");
+ printf("tRCD %d SCLK Cycles,tRP %d SCLK Cycles,tRAS %d SCLK Cycles"
+ "tWR %d SCLK Cycles,CAS Latency %d SCLK cycles \n",
+ 3, 3, 6, 2, 3);
+ printf("SDRAM Begin: 0x%x\n", CFG_SDRAM_BASE);
+ printf("Bank size = %d MB\n", CFG_MAX_RAM_SIZE >> 20);
+#endif
+ gd->bd->bi_memstart = CFG_SDRAM_BASE;
+ gd->bd->bi_memsize = CFG_MAX_RAM_SIZE;
+ return CFG_MAX_RAM_SIZE;
+}
+
+#if defined(CONFIG_MISC_INIT_R)
+/* miscellaneous platform dependent initialisations */
+int misc_init_r(void)
+{
+#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT)
+ char nid[32];
+ unsigned char *pMACaddr = (unsigned char *)0x203F0000;
+ u8 SrcAddr[6] = { 0x02, 0x80, 0xAD, 0x20, 0x31, 0xB8 };
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+ /* The 0xFF check here is to make sure we don't use the address
+ * in flash if it's simply been erased (aka all 0xFF values) */
+ if (getenv("ethaddr") == NULL && is_valid_ether_addr(pMACaddr)) {
+ sprintf(nid, "%02x:%02x:%02x:%02x:%02x:%02x",
+ pMACaddr[0], pMACaddr[1],
+ pMACaddr[2], pMACaddr[3], pMACaddr[4], pMACaddr[5]);
+ setenv("ethaddr", nid);
+ }
+ if (getenv("ethaddr")) {
+ SetupMacAddr(SrcAddr);
+ }
+#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
+#endif /* BFIN_BOOT_MODE == BF537_BYPASS_BOOT */
+
+#if defined(CONFIG_BFIN_IDE)
+#if defined(CONFIG_BFIN_TRUE_IDE)
+ /* Enable ATASEL when in True IDE mode */
+ printf("Using CF True IDE Mode\n");
+ cf_outb(0, (unsigned char *)CONFIG_CF_ATASEL_ENA);
+ udelay(1000);
+#elif defined(CONFIG_BFIN_CF_IDE)
+ /* Disable ATASEL when we're in Common Memory Mode */
+ printf("Using CF Common Memory Mode\n");
+ cf_outb(0, (unsigned char *)CONFIG_CF_ATASEL_DIS);
+ udelay(1000);
+#elif defined(CONFIG_BFIN_HDD_IDE)
+ printf("Using HDD IDE Mode\n");
+#endif
+ ide_init();
+#endif /* CONFIG_BFIN_IDE */
+ return 0;
+}
+#endif /* CONFIG_MISC_INIT_R */
+
+#ifdef CONFIG_POST
+#if (BFIN_BOOT_MODE != BF537_BYPASS_BOOT)
+/* Using sw10-PF5 as the hotkey */
+int post_hotkeys_pressed(void)
+{
+ return 0;
+}
+#else
+/* Using sw10-PF5 as the hotkey */
+int post_hotkeys_pressed(void)
+{
+ int delay = 3;
+ int i;
+ unsigned short value;
+
+ *pPORTF_FER &= ~PF5;
+ *pPORTFIO_DIR &= ~PF5;
+ *pPORTFIO_INEN |= PF5;
+
+ printf("########Press SW10 to enter Memory POST########: %2d ", delay);
+ while (delay--) {
+ for (i = 0; i < 100; i++) {
+ value = *pPORTFIO & PF5;
+ if (value != 0) {
+ break;
+ }
+ udelay(10000);
+ }
+ printf("\b\b\b%2d ", delay);
+ }
+ printf("\b\b\b 0");
+ printf("\n");
+ if (value == 0)
+ return 0;
+ else {
+ printf("Hotkey has been pressed, Enter POST . . . . . .\n");
+ return 1;
+ }
+}
+#endif
+#endif
+
+#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER)
+void post_word_store(ulong a)
+{
+ volatile ulong *save_addr = (volatile ulong *)POST_WORD_ADDR;
+ *save_addr = a;
+}
+
+ulong post_word_load(void)
+{
+ volatile ulong *save_addr = (volatile ulong *)POST_WORD_ADDR;
+ return *save_addr;
+}
+#endif
+
+#ifdef CONFIG_POST
+int uart_post_test(int flags)
+{
+ return 0;
+}
+
+#define BLOCK_SIZE 0x10000
+#define VERIFY_ADDR 0x2000000
+extern int erase_block_flash(int);
+extern int write_data(long lStart, long lCount, uchar * pnData);
+int flash_post_test(int flags)
+{
+ unsigned short *pbuf, *temp;
+ int offset, n, i;
+ int value = 0;
+ int result = 0;
+ printf("\n");
+ pbuf = (unsigned short *)VERIFY_ADDR;
+ temp = pbuf;
+ for (n = FLASH_START_POST_BLOCK; n < FLASH_END_POST_BLOCK; n++) {
+ offset = (n - 7) * BLOCK_SIZE;
+ printf("--------Erase block:%2d..", n);
+ erase_block_flash(n);
+ printf("OK\r");
+ printf("--------Program block:%2d...", n);
+ write_data(CFG_FLASH_BASE + offset, BLOCK_SIZE, pbuf);
+ printf("OK\r");
+ printf("--------Verify block:%2d...", n);
+ for (i = 0; i < BLOCK_SIZE; i += 2) {
+ if (*(unsigned short *)(CFG_FLASH_BASE + offset + i) !=
+ *temp++) {
+ value = 1;
+ result = 1;
+ }
+ }
+ if (value)
+ printf("failed\n");
+ else
+ printf("OK %3d%%\r",
+ (int)(
+ (n + 1 -
+ FLASH_START_POST_BLOCK) *
+ 100 / (FLASH_END_POST_BLOCK -
+ FLASH_START_POST_BLOCK)));
+
+ temp = pbuf;
+ value = 0;
+ }
+ printf("\n");
+ if (result)
+ return -1;
+ else
+ return 0;
+}
+
+/****************************************************
+ * LED1 ---- PF6 LED2 ---- PF7 *
+ * LED3 ---- PF8 LED4 ---- PF9 *
+ * LED5 ---- PF10 LED6 ---- PF11 *
+ ****************************************************/
+int led_post_test(int flags)
+{
+ *pPORTF_FER &= ~(PF6 | PF7 | PF8 | PF9 | PF10 | PF11);
+ *pPORTFIO_DIR |= PF6 | PF7 | PF8 | PF9 | PF10 | PF11;
+ *pPORTFIO_INEN &= ~(PF6 | PF7 | PF8 | PF9 | PF10 | PF11);
+ *pPORTFIO &= ~(PF6 | PF7 | PF8 | PF9 | PF10 | PF11);
+ udelay(1000000);
+ printf("LED1 on");
+ *pPORTFIO |= PF6;
+ udelay(1000000);
+ printf("\b\b\b\b\b\b\b");
+ printf("LED2 on");
+ *pPORTFIO |= PF7;
+ udelay(1000000);
+ printf("\b\b\b\b\b\b\b");
+ printf("LED3 on");
+ *pPORTFIO |= PF8;
+ udelay(1000000);
+ printf("\b\b\b\b\b\b\b");
+ printf("LED4 on");
+ *pPORTFIO |= PF9;
+ udelay(1000000);
+ printf("\b\b\b\b\b\b\b");
+ printf("LED5 on");
+ *pPORTFIO |= PF10;
+ udelay(1000000);
+ printf("\b\b\b\b\b\b\b");
+ printf("lED6 on");
+ *pPORTFIO |= PF11;
+ printf("\b\b\b\b\b\b\b ");
+ return 0;
+}
+
+/************************************************
+ * SW10 ---- PF5 SW11 ---- PF4 *
+ * SW12 ---- PF3 SW13 ---- PF2 *
+ ************************************************/
+int button_post_test(int flags)
+{
+ int i, delay = 5;
+ unsigned short value = 0;
+ int result = 0;
+
+ *pPORTF_FER &= ~(PF5 | PF4 | PF3 | PF2);
+ *pPORTFIO_DIR &= ~(PF5 | PF4 | PF3 | PF2);
+ *pPORTFIO_INEN |= (PF5 | PF4 | PF3 | PF2);
+
+ printf("\n--------Press SW10: %2d ", delay);
+ while (delay--) {
+ for (i = 0; i < 100; i++) {
+ value = *pPORTFIO & PF5;
+ if (value != 0) {
+ break;
+ }
+ udelay(10000);
+ }
+ printf("\b\b\b%2d ", delay);
+ }
+ if (value != 0)
+ printf("\b\bOK");
+ else {
+ result = -1;
+ printf("\b\bfailed");
+ }
+
+ delay = 5;
+ printf("\n--------Press SW11: %2d ", delay);
+ while (delay--) {
+ for (i = 0; i < 100; i++) {
+ value = *pPORTFIO & PF4;
+ if (value != 0) {
+ break;
+ }
+ udelay(10000);
+ }
+ printf("\b\b\b%2d ", delay);
+ }
+ if (value != 0)
+ printf("\b\bOK");
+ else {
+ result = -1;
+ printf("\b\bfailed");
+ }
+
+ delay = 5;
+ printf("\n--------Press SW12: %2d ", delay);
+ while (delay--) {
+ for (i = 0; i < 100; i++) {
+ value = *pPORTFIO & PF3;
+ if (value != 0) {
+ break;
+ }
+ udelay(10000);
+ }
+ printf("\b\b\b%2d ", delay);
+ }
+ if (value != 0)
+ printf("\b\bOK");
+ else {
+ result = -1;
+ printf("\b\bfailed");
+ }
+
+ delay = 5;
+ printf("\n--------Press SW13: %2d ", delay);
+ while (delay--) {
+ for (i = 0; i < 100; i++) {
+ value = *pPORTFIO & PF2;
+ if (value != 0) {
+ break;
+ }
+ udelay(10000);
+ }
+ printf("\b\b\b%2d ", delay);
+ }
+ if (value != 0)
+ printf("\b\bOK");
+ else {
+ result = -1;
+ printf("\b\bfailed");
+ }
+ printf("\n");
+ return result;
+}
+#endif
diff --git a/board/bf537-stamp/cmd_bf537led.c b/board/bf537-stamp/cmd_bf537led.c
new file mode 100644
index 0000000000..fa650f26fe
--- /dev/null
+++ b/board/bf537-stamp/cmd_bf537led.c
@@ -0,0 +1,201 @@
+/*
+ * U-boot - cmd_bf537led.c
+ *
+ * Copyright (C) 2006 Aaron Gage, Ocean Optics 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 <common.h>
+#include <config.h>
+#include <command.h>
+#include <asm/blackfin.h>
+#include <asm-blackfin/string.h>
+#ifdef CONFIG_BF537_STAMP_LEDCMD
+
+/* Define the command usage in a reusable way */
+#define USAGE_LONG \
+ "led <number> <action>\n" \
+ " <number> - Index (0-5) of LED to change, or \"all\"\n" \
+ " <action> - Must be one of:\n" \
+ " on off toggle\n"
+
+/* Number of LEDs supported by the board */
+#define NUMBER_LEDS 6
+/* The BF537 stamp has 6 LEDs. This mask indicates that all should be lit. */
+#define LED_ALL_MASK 0x003F
+
+void show_cmd_usage(void);
+void set_led_state(int index, int state);
+void configure_GPIO_to_output(int index);
+
+/* Map of LEDs according to their GPIO ports. This can be rearranged or
+ * otherwise changed to account for different GPIO configurations.
+ */
+int led_ports[] = { PF6, PF7, PF8, PF9, PF10, PF11 };
+
+#define ACTION_TOGGLE -1
+#define ACTION_OFF 0
+#define ACTION_ON 1
+
+#define LED_STATE_OFF 0
+#define LED_STATE_ON 1
+
+/* This is a trivial atoi implementation since we don't have one available */
+int atoi(char *string)
+{
+ int length;
+ int retval = 0;
+ int i;
+ int sign = 1;
+
+ length = strlen(string);
+ for (i = 0; i < length; i++) {
+ if (0 == i && string[0] == '-') {
+ sign = -1;
+ continue;
+ }
+ if (string[i] > '9' || string[i] < '0') {
+ break;
+ }
+ retval *= 10;
+ retval += string[i] - '0';
+ }
+ retval *= sign;
+ return retval;
+}
+
+int do_bf537led(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ int led_mask = 0;
+ int led_current_state = 0;
+ int action = ACTION_OFF;
+ int temp;
+
+ if (3 != argc) {
+ /* Not enough arguments, so just show usage information */
+ show_cmd_usage();
+ return 1;
+ }
+
+ if (strcmp(argv[1], "all") == 0) {
+ led_mask = LED_ALL_MASK;
+ } else {
+ temp = atoi(argv[1]);
+ if (temp < 0 || temp >= NUMBER_LEDS) {
+ printf("Invalid LED number [%s]\n", argv[1]);
+ show_cmd_usage();
+ return 2;
+ }
+ led_mask |= (1 << temp);
+ }
+
+ if (strcmp(argv[2], "off") == 0) {
+ action = ACTION_OFF;
+ } else if (strcmp(argv[2], "on") == 0) {
+ action = ACTION_ON;
+ } else if (strcmp(argv[2], "toggle") == 0) {
+ action = ACTION_TOGGLE;
+ } else {
+ printf("Invalid action [%s]\n", argv[2]);
+ show_cmd_usage();
+ return 3;
+ }
+
+ for (temp = 0; temp < NUMBER_LEDS; temp++) {
+ if ((led_mask & (1 << temp)) > 0) {
+ /*
+ * It is possible that the user has wired one of PF6-PF11 to
+ * something other than an LED, so this will only change a pin
+ * to output if the user has indicated a state change. This may
+ * happen a lot, but this way is safer than just setting all pins
+ * to output.
+ */
+ configure_GPIO_to_output(temp);
+
+ led_current_state =
+ ((*pPORTFIO & led_ports[temp]) >
+ 0) ? LED_STATE_ON : LED_STATE_OFF;
+ /*
+ printf("LED state for index %d (%x) is %d\n", temp, led_ports[temp],
+ led_current_state);
+ printf("*pPORTFIO is %x\n", *pPORTFIO);
+ */
+ if (ACTION_ON == action
+ || (ACTION_TOGGLE == action
+ && 0 == led_current_state)) {
+ printf("Turning LED %d on\n", temp);
+ set_led_state(temp, LED_STATE_ON);
+ } else {
+ printf("Turning LED %d off\n", temp);
+ set_led_state(temp, LED_STATE_OFF);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * The GPIO pins that go to the LEDs on the BF537 stamp must be configured
+ * as output. This function simply configures them that way. This could
+ * be done to all of the GPIO lines at once, but if a user is using a
+ * custom board, this will try to be nice and only change the GPIO lines
+ * that the user specifically names.
+ */
+void configure_GPIO_to_output(int index)
+{
+ int port;
+
+ port = led_ports[index];
+
+ /* Clear the Port F Function Enable Register */
+ *pPORTF_FER &= ~port;
+ /* Set the Port F I/O direction register */
+ *pPORTFIO_DIR |= port;
+ /* Clear the Port F I/O Input Enable Register */
+ *pPORTFIO_INEN &= ~port;
+}
+
+/* Enforce the given state on the GPIO line for the indicated LED */
+void set_led_state(int index, int state)
+{
+ int port;
+
+ port = led_ports[index];
+
+ if (LED_STATE_OFF == state) {
+ /* Clear the bit to turn off the LED */
+ *pPORTFIO &= ~port;
+ } else {
+ /* Set the bit to turn on the LED */
+ *pPORTFIO |= port;
+ }
+}
+
+/* Display usage information */
+void show_cmd_usage()
+{
+ printf("Usage:\n%s", USAGE_LONG);
+}
+
+/* Register information for u-boot to find this command */
+U_BOOT_CMD(led, 3, 1, do_bf537led,
+ "led- Control BF537 stamp LEDs\n", USAGE_LONG);
+
+#endif
diff --git a/board/bf537-stamp/config.mk b/board/bf537-stamp/config.mk
new file mode 100644
index 0000000000..a623c3df0c
--- /dev/null
+++ b/board/bf537-stamp/config.mk
@@ -0,0 +1,25 @@
+#
+# (C) Copyright 2001
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+# TEXT_BASE should be defined as the MAX_SDRAM Address - 256k bytes
+# 256k is defined as CFG_MONITOR_LEN in ./include/configs/<board>.h
+TEXT_BASE = 0x03FC0000
diff --git a/board/bf537-stamp/ether_bf537.c b/board/bf537-stamp/ether_bf537.c
new file mode 100644
index 0000000000..f00837aad2
--- /dev/null
+++ b/board/bf537-stamp/ether_bf537.c
@@ -0,0 +1,545 @@
+/*
+ * ADI Blackfin 537 MAC Ethernet
+ *
+ * Copyright (c) 2005 Analog Device, 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 <common.h>
+#include <config.h>
+#include <asm/blackfin.h>
+#include <net.h>
+#include <command.h>
+#include <malloc.h>
+#include "ether_bf537.h"
+
+#ifdef CONFIG_POST
+#include <post.h>
+#endif
+
+#undef DEBUG_ETHERNET
+
+#ifdef DEBUG_ETHERNET
+#define DEBUGF(fmt,args...) printf(fmt,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+
+#define RXBUF_BASE_ADDR 0xFF900000
+#define TXBUF_BASE_ADDR 0xFF800000
+#define TX_BUF_CNT 1
+
+#define TOUT_LOOP 1000000
+
+ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT];
+ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX];
+static u16 txIdx; /* index of the current RX buffer */
+static u16 rxIdx; /* index of the current TX buffer */
+
+u8 SrcAddr[6];
+u16 PHYregs[NO_PHY_REGS]; /* u16 PHYADDR; */
+
+/* DMAx_CONFIG values at DMA Restart */
+const ADI_DMA_CONFIG_REG rxdmacfg = { 1, 1, 2, 0, 0, 0, 0, 5, 7 };
+
+#if 0
+ rxdmacfg.b_DMA_EN = 1; /* enabled */
+ rxdmacfg.b_WNR = 1; /* write to memory */
+ rxdmacfg.b_WDSIZE = 2; /* wordsize is 32 bits */
+ rxdmacfg.b_DMA2D = 0; /* N/A */
+ rxdmacfg.b_RESTART= 0; /* N/A */
+ rxdmacfg.b_DI_SEL = 0; /* N/A */
+ rxdmacfg.b_DI_EN = 0; /* no interrupt */
+ rxdmacfg.b_NDSIZE = 5; /* 5 half words is desc size. */
+ rxdmacfg.b_FLOW = 7; /* large desc flow */
+#endif
+
+const ADI_DMA_CONFIG_REG txdmacfg = { 1, 0, 2, 0, 0, 0, 0, 5, 7 };
+
+#if 0
+ txdmacfg.b_DMA_EN = 1; /* enabled */
+ txdmacfg.b_WNR = 0; /* read from memory */
+ txdmacfg.b_WDSIZE = 2; /* wordsize is 32 bits */
+ txdmacfg.b_DMA2D = 0; /* N/A */
+ txdmacfg.b_RESTART= 0; /* N/A */
+ txdmacfg.b_DI_SEL = 0; /* N/A */
+ txdmacfg.b_DI_EN = 0; /* no interrupt */
+ txdmacfg.b_NDSIZE = 5; /* 5 half words is desc size. */
+ txdmacfg.b_FLOW = 7; /* large desc flow */
+#endif
+
+ADI_ETHER_BUFFER *SetupRxBuffer(int no);
+ADI_ETHER_BUFFER *SetupTxBuffer(int no);
+
+static int bfin_EMAC_init(struct eth_device *dev, bd_t * bd);
+static void bfin_EMAC_halt(struct eth_device *dev);
+static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet,
+ int length);
+static int bfin_EMAC_recv(struct eth_device *dev);
+
+int bfin_EMAC_initialize(bd_t * bis)
+{
+ struct eth_device *dev;
+ dev = (struct eth_device *)malloc(sizeof(*dev));
+ if (dev == NULL)
+ hang();
+
+ memset(dev, 0, sizeof(*dev));
+ sprintf(dev->name, "BF537 ETHERNET");
+
+ dev->iobase = 0;
+ dev->priv = 0;
+ dev->init = bfin_EMAC_init;
+ dev->halt = bfin_EMAC_halt;
+ dev->send = bfin_EMAC_send;
+ dev->recv = bfin_EMAC_recv;
+
+ eth_register(dev);
+
+ return 1;
+}
+
+static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet,
+ int length)
+{
+ int i;
+ int result = 0;
+ unsigned int *buf;
+ buf = (unsigned int *)packet;
+
+ if (length <= 0) {
+ printf("Ethernet: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ if ((*pDMA2_IRQ_STATUS & DMA_ERR) != 0) {
+ printf("Ethernet: tx DMA error\n");
+ goto out;
+ }
+
+ for (i = 0; (*pDMA2_IRQ_STATUS & DMA_RUN) != 0; i++) {
+ if (i > TOUT_LOOP) {
+ puts("Ethernet: tx time out\n");
+ goto out;
+ }
+ }
+ txbuf[txIdx]->FrmData->NoBytes = length;
+ memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length);
+ txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData;
+ *pDMA2_NEXT_DESC_PTR = &txbuf[txIdx]->Dma[0];
+ *pDMA2_CONFIG = *(u16 *) (void *)(&txdmacfg);
+ *pEMAC_OPMODE |= TE;
+
+ for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) {
+ if (i > TOUT_LOOP) {
+ puts("Ethernet: tx error\n");
+ goto out;
+ }
+ }
+ result = txbuf[txIdx]->StatusWord;
+ txbuf[txIdx]->StatusWord = 0;
+ if ((txIdx + 1) >= TX_BUF_CNT)
+ txIdx = 0;
+ else
+ txIdx++;
+ out:
+ DEBUGF("BFIN EMAC send: length = %d\n", length);
+ return result;
+}
+
+static int bfin_EMAC_recv(struct eth_device *dev)
+{
+ int length = 0;
+
+ for (;;) {
+ if ((rxbuf[rxIdx]->StatusWord & RX_COMP) == 0) {
+ length = -1;
+ break;
+ }
+ if ((rxbuf[rxIdx]->StatusWord & RX_DMAO) != 0) {
+ printf("Ethernet: rx dma overrun\n");
+ break;
+ }
+ if ((rxbuf[rxIdx]->StatusWord & RX_OK) == 0) {
+ printf("Ethernet: rx error\n");
+ break;
+ }
+ length = rxbuf[rxIdx]->StatusWord & 0x000007FF;
+ if (length <= 4) {
+ printf("Ethernet: bad frame\n");
+ break;
+ }
+ NetRxPackets[rxIdx] =
+ (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest);
+ NetReceive(NetRxPackets[rxIdx], length - 4);
+ *pDMA1_IRQ_STATUS |= DMA_DONE | DMA_ERR;
+ rxbuf[rxIdx]->StatusWord = 0x00000000;
+ if ((rxIdx + 1) >= PKTBUFSRX)
+ rxIdx = 0;
+ else
+ rxIdx++;
+ }
+
+ return length;
+}
+
+/**************************************************************
+ *
+ * Ethernet Initialization Routine
+ *
+ *************************************************************/
+
+static int bfin_EMAC_init(struct eth_device *dev, bd_t * bd)
+{
+ u32 opmode;
+ int dat;
+ int i;
+ DEBUGF("Eth_init: ......\n");
+
+ txIdx = 0;
+ rxIdx = 0;
+
+/* Initialize System Register */
+ if (SetupSystemRegs(&dat) < 0)
+ return -1;
+
+/* Initialize EMAC address */
+ SetupMacAddr(SrcAddr);
+
+/* Initialize TX and RX buffer */
+ for (i = 0; i < PKTBUFSRX; i++) {
+ rxbuf[i] = SetupRxBuffer(i);
+ if (i > 0) {
+ rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR =
+ &(rxbuf[i]->Dma[0]);
+ if (i == (PKTBUFSRX - 1))
+ rxbuf[i]->Dma[1].NEXT_DESC_PTR =
+ &(rxbuf[0]->Dma[0]);
+ }
+ }
+ for (i = 0; i < TX_BUF_CNT; i++) {
+ txbuf[i] = SetupTxBuffer(i);
+ if (i > 0) {
+ txbuf[i - 1]->Dma[1].NEXT_DESC_PTR =
+ &(txbuf[i]->Dma[0]);
+ if (i == (TX_BUF_CNT - 1))
+ txbuf[i]->Dma[1].NEXT_DESC_PTR =
+ &(txbuf[0]->Dma[0]);
+ }
+ }
+
+ /* Set RX DMA */
+ *pDMA1_NEXT_DESC_PTR = &rxbuf[0]->Dma[0];
+ *pDMA1_CONFIG = *((u16 *) (void *)&rxbuf[0]->Dma[0].CONFIG);
+
+ /* Wait MII done */
+ PollMdcDone();
+
+ /* We enable only RX here */
+ /* ASTP : Enable Automatic Pad Stripping
+ PR : Promiscuous Mode for test
+ PSF : Receive frames with total length less than 64 bytes.
+ FDMODE : Full Duplex Mode
+ LB : Internal Loopback for test
+ RE : Receiver Enable */
+ if (dat == FDMODE)
+ opmode = ASTP | FDMODE | PSF;
+ else
+ opmode = ASTP | PSF;
+ opmode |= RE;
+#ifdef CONFIG_BFIN_MAC_RMII
+ opmode |= TE | RMII;
+#endif
+ /* Turn on the EMAC */
+ *pEMAC_OPMODE = opmode;
+ return 0;
+}
+
+static void bfin_EMAC_halt(struct eth_device *dev)
+{
+ DEBUGF("Eth_halt: ......\n");
+ /* Turn off the EMAC */
+ *pEMAC_OPMODE = 0x00000000;
+ /* Turn off the EMAC RX DMA */
+ *pDMA1_CONFIG = 0x0000;
+ *pDMA2_CONFIG = 0x0000;
+
+}
+
+void SetupMacAddr(u8 * MACaddr)
+{
+ char *tmp, *end;
+ int i;
+ /* this depends on a little-endian machine */
+ tmp = getenv("ethaddr");
+ if (tmp) {
+ for (i = 0; i < 6; i++) {
+ MACaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
+ if (tmp)
+ tmp = (*end) ? end + 1 : end;
+ }
+
+#ifndef CONFIG_NETCONSOLE
+ printf("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n",
+ MACaddr[0], MACaddr[1],
+ MACaddr[2], MACaddr[3], MACaddr[4], MACaddr[5]);
+#endif
+ *pEMAC_ADDRLO = MACaddr[0] | MACaddr[1] << 8 |
+ MACaddr[2] << 16 | MACaddr[3] << 24;
+ *pEMAC_ADDRHI = MACaddr[4] | MACaddr[5] << 8;
+ }
+}
+
+void PollMdcDone(void)
+{
+ /* poll the STABUSY bit */
+ while (*pEMAC_STAADD & STABUSY) ;
+}
+
+void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data)
+{
+ PollMdcDone();
+
+ *pEMAC_STADAT = Data;
+
+ *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
+ STAOP | STAIE | STABUSY;
+}
+
+/*********************************************************************************
+ * Read an off-chip register in a PHY through the MDC/MDIO port *
+ *********************************************************************************/
+u16 RdPHYReg(u16 PHYAddr, u16 RegAddr)
+{
+ u16 Data;
+
+ PollMdcDone();
+
+ *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
+ STAIE | STABUSY;
+
+ PollMdcDone();
+
+ Data = (u16) * pEMAC_STADAT;
+
+ PHYregs[RegAddr] = Data; /* save shadow copy */
+
+ return Data;
+}
+
+void SoftResetPHY(void)
+{
+ u16 phydat;
+ /* set the reset bit */
+ WrPHYReg(PHYADDR, PHY_MODECTL, PHY_RESET);
+ /* and clear it again */
+ WrPHYReg(PHYADDR, PHY_MODECTL, 0x0000);
+ do {
+ /* poll until reset is complete */
+ phydat = RdPHYReg(PHYADDR, PHY_MODECTL);
+ } while ((phydat & PHY_RESET) != 0);
+}
+
+int SetupSystemRegs(int *opmode)
+{
+ u16 sysctl, phydat;
+ int count = 0;
+ /* Enable PHY output */
+ *pVR_CTL |= PHYCLKOE;
+ /* MDC = 2.5 MHz */
+ sysctl = SET_MDCDIV(24);
+ /* Odd word alignment for Receive Frame DMA word */
+ /* Configure checksum support and rcve frame word alignment */
+ sysctl |= RXDWA | RXCKS;
+ *pEMAC_SYSCTL = sysctl;
+ /* auto negotiation on */
+ /* full duplex */
+ /* 100 Mbps */
+ phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET;
+ WrPHYReg(PHYADDR, PHY_MODECTL, phydat);
+ do {
+ udelay(1000);
+ phydat = RdPHYReg(PHYADDR, PHY_MODESTAT);
+ if (count > 3000) {
+ printf
+ ("Link is down, please check your network connection\n");
+ return -1;
+ }
+ count++;
+ } while (!(phydat & 0x0004));
+
+ phydat = RdPHYReg(PHYADDR, PHY_ANLPAR);
+
+ if ((phydat & 0x0100) || (phydat & 0x0040))
+ *opmode = FDMODE;
+ else
+ *opmode = 0;
+
+ *pEMAC_MMC_CTL = RSTC | CROLL;
+
+ /* Initialize the TX DMA channel registers */
+ *pDMA2_X_COUNT = 0;
+ *pDMA2_X_MODIFY = 4;
+ *pDMA2_Y_COUNT = 0;
+ *pDMA2_Y_MODIFY = 0;
+
+ /* Initialize the RX DMA channel registers */
+ *pDMA1_X_COUNT = 0;
+ *pDMA1_X_MODIFY = 4;
+ *pDMA1_Y_COUNT = 0;
+ *pDMA1_Y_MODIFY = 0;
+ return 0;
+}
+
+ADI_ETHER_BUFFER *SetupRxBuffer(int no)
+{
+ ADI_ETHER_FRAME_BUFFER *frmbuf;
+ ADI_ETHER_BUFFER *buf;
+ int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */
+ int total_size = nobytes_buffer + RECV_BUFSIZE;
+
+ buf = (ADI_ETHER_BUFFER *) (RXBUF_BASE_ADDR + no * total_size);
+ frmbuf =
+ (ADI_ETHER_FRAME_BUFFER *) (RXBUF_BASE_ADDR + no * total_size +
+ nobytes_buffer);
+
+ memset(buf, 0x00, nobytes_buffer);
+ buf->FrmData = frmbuf;
+ memset(frmbuf, 0xfe, RECV_BUFSIZE);
+
+ /* set up first desc to point to receive frame buffer */
+ buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]);
+ buf->Dma[0].START_ADDR = (u32) buf->FrmData;
+ buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */
+ buf->Dma[0].CONFIG.b_WNR = 1; /* Write to memory */
+ buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */
+ buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */
+ buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */
+
+ /* set up second desc to point to status word */
+ buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]);
+ buf->Dma[1].START_ADDR = (u32) & buf->IPHdrChksum;
+ buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */
+ buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */
+ buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */
+ buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */
+ buf->Dma[1].CONFIG.b_NDSIZE = 5; /* must be 0 when FLOW is 0 */
+ buf->Dma[1].CONFIG.b_FLOW = 7; /* stop */
+
+ return buf;
+}
+
+ADI_ETHER_BUFFER *SetupTxBuffer(int no)
+{
+ ADI_ETHER_FRAME_BUFFER *frmbuf;
+ ADI_ETHER_BUFFER *buf;
+ int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */
+ int total_size = nobytes_buffer + RECV_BUFSIZE;
+
+ buf = (ADI_ETHER_BUFFER *) (TXBUF_BASE_ADDR + no * total_size);
+ frmbuf =
+ (ADI_ETHER_FRAME_BUFFER *) (TXBUF_BASE_ADDR + no * total_size +
+ nobytes_buffer);
+
+ memset(buf, 0x00, nobytes_buffer);
+ buf->FrmData = frmbuf;
+ memset(frmbuf, 0x00, RECV_BUFSIZE);
+
+ /* set up first desc to point to receive frame buffer */
+ buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]);
+ buf->Dma[0].START_ADDR = (u32) buf->FrmData;
+ buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */
+ buf->Dma[0].CONFIG.b_WNR = 0; /* Read to memory */
+ buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */
+ buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */
+ buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */
+
+ /* set up second desc to point to status word */
+ buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]);
+ buf->Dma[1].START_ADDR = (u32) & buf->StatusWord;
+ buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */
+ buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */
+ buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */
+ buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */
+ buf->Dma[1].CONFIG.b_NDSIZE = 0; /* must be 0 when FLOW is 0 */
+ buf->Dma[1].CONFIG.b_FLOW = 0; /* stop */
+
+ return buf;
+}
+
+#if defined(CONFIG_POST) && defined(CFG_POST_ETHER)
+int ether_post_test(int flags)
+{
+ uchar buf[64];
+ int i, value = 0;
+ int length;
+
+ printf("\n--------");
+ bfin_EMAC_init(NULL, NULL);
+ /* construct the package */
+ buf[0] = buf[6] = (unsigned char)(*pEMAC_ADDRLO & 0xFF);
+ buf[1] = buf[7] = (unsigned char)((*pEMAC_ADDRLO & 0xFF00) >> 8);
+ buf[2] = buf[8] = (unsigned char)((*pEMAC_ADDRLO & 0xFF0000) >> 16);
+ buf[3] = buf[9] = (unsigned char)((*pEMAC_ADDRLO & 0xFF000000) >> 24);
+ buf[4] = buf[10] = (unsigned char)(*pEMAC_ADDRHI & 0xFF);
+ buf[5] = buf[11] = (unsigned char)((*pEMAC_ADDRHI & 0xFF00) >> 8);
+ buf[12] = 0x08; /* Type: ARP */
+ buf[13] = 0x06;
+ buf[14] = 0x00; /* Hardware type: Ethernet */
+ buf[15] = 0x01;
+ buf[16] = 0x08; /* Protocal type: IP */
+ buf[17] = 0x00;
+ buf[18] = 0x06; /* Hardware size */
+ buf[19] = 0x04; /* Protocol size */
+ buf[20] = 0x00; /* Opcode: request */
+ buf[21] = 0x01;
+
+ for (i = 0; i < 42; i++)
+ buf[i + 22] = i;
+ printf("--------Send 64 bytes......\n");
+ bfin_EMAC_send(NULL, (volatile void *)buf, 64);
+ for (i = 0; i < 100; i++) {
+ udelay(10000);
+ if ((rxbuf[rxIdx]->StatusWord & RX_COMP) != 0) {
+ value = 1;
+ break;
+ }
+ }
+ if (value == 0) {
+ printf("--------EMAC can't receive any data\n");
+ eth_halt();
+ return -1;
+ }
+ length = rxbuf[rxIdx]->StatusWord & 0x000007FF - 4;
+ for (i = 0; i < length; i++) {
+ if (rxbuf[rxIdx]->FrmData->Dest[i] != buf[i]) {
+ printf("--------EMAC receive error data!\n");
+ eth_halt();
+ return -1;
+ }
+ }
+ printf("--------receive %d bytes, matched\n", length);
+ bfin_EMAC_halt(NULL);
+ return 0;
+}
+#endif
+#endif /* CFG_CMD_NET */
diff --git a/board/bf537-stamp/ether_bf537.h b/board/bf537-stamp/ether_bf537.h
new file mode 100644
index 0000000000..64240ba01b
--- /dev/null
+++ b/board/bf537-stamp/ether_bf537.h
@@ -0,0 +1,110 @@
+#define PHYADDR 0x01
+#define NO_PHY_REGS 0x20
+
+#define DEFAULT_PHY_PHYID1 0x0007
+#define DEFAULT_PHY_PHYID2 0xC0A3
+#define PHY_MODECTL 0x00
+#define PHY_MODESTAT 0x01
+#define PHY_PHYID1 0x02
+#define PHY_PHYID2 0x03
+#define PHY_ANAR 0x04
+#define PHY_ANLPAR 0x05
+#define PHY_ANER 0x06
+
+#define PHY_RESET 0x8000
+#define PHY_ANEG_EN 0x1000
+#define PHY_DUPLEX 0x0100
+#define PHY_SPD_SET 0x2000
+
+#define RECV_BUFSIZE (0x614)
+
+typedef volatile u32 reg32;
+typedef volatile u16 reg16;
+
+typedef struct ADI_DMA_CONFIG_REG {
+ u16 b_DMA_EN:1; /* 0 Enabled */
+ u16 b_WNR:1; /* 1 Direction */
+ u16 b_WDSIZE:2; /* 2:3 Transfer word size */
+ u16 b_DMA2D:1; /* 4 DMA mode */
+ u16 b_RESTART:1; /* 5 Retain FIFO */
+ u16 b_DI_SEL:1; /* 6 Data interrupt timing select */
+ u16 b_DI_EN:1; /* 7 Data interrupt enabled */
+ u16 b_NDSIZE:4; /* 8:11 Flex descriptor size */
+ u16 b_FLOW:3; /* 12:14Flow */
+} ADI_DMA_CONFIG_REG;
+
+typedef struct adi_ether_frame_buffer {
+ u16 NoBytes; /* the no. of following bytes */
+ u8 Dest[6]; /* destination MAC address */
+ u8 Srce[6]; /* source MAC address */
+ u16 LTfield; /* length/type field */
+ u8 Data[0]; /* payload bytes */
+} ADI_ETHER_FRAME_BUFFER;
+/* 16 bytes/struct */
+
+typedef struct dma_descriptor {
+ struct dma_descriptor *NEXT_DESC_PTR;
+ u32 START_ADDR;
+ ADI_DMA_CONFIG_REG CONFIG;
+} DMA_DESCRIPTOR;
+/* 10 bytes/struct in 12 bytes */
+
+typedef struct adi_ether_buffer {
+ DMA_DESCRIPTOR Dma[2]; /* first for the frame, second for the status */
+ ADI_ETHER_FRAME_BUFFER *FrmData;/* pointer to data */
+ struct adi_ether_buffer *pNext; /* next buffer */
+ struct adi_ether_buffer *pPrev; /* prev buffer */
+ u16 IPHdrChksum; /* the IP header checksum */
+ u16 IPPayloadChksum; /* the IP header and payload checksum */
+ volatile u32 StatusWord; /* the frame status word */
+} ADI_ETHER_BUFFER;
+/* 40 bytes/struct in 44 bytes */
+
+void SetupMacAddr(u8 * MACaddr);
+
+void PollMdcDone(void);
+void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data);
+u16 RdPHYReg(u16 PHYAddr, u16 RegAddr);
+void SoftResetPHY(void);
+void DumpPHYRegs(void);
+
+int SetupSystemRegs(int *opmode);
+
+/**
+ * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is all zeroes.
+ */
+static inline int is_zero_ether_addr(const u8 * addr)
+{
+ return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
+
+/**
+ * is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a multicast address.
+ * By definition the broadcast address is also a multicast address.
+ */
+static inline int is_multicast_ether_addr(const u8 * addr)
+{
+ return (0x01 & addr[0]);
+}
+
+/**
+ * is_valid_ether_addr - Determine if the given Ethernet address is valid
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
+ * a multicast address, and is not FF:FF:FF:FF:FF:FF.
+ *
+ * Return true if the address is valid.
+ */
+static inline int is_valid_ether_addr(const u8 * addr)
+{
+ /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
+ * explicitly check for it here. */
+ return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
+}
diff --git a/board/bf537-stamp/flash-defines.h b/board/bf537-stamp/flash-defines.h
new file mode 100644
index 0000000000..f19e171d04
--- /dev/null
+++ b/board/bf537-stamp/flash-defines.h
@@ -0,0 +1,123 @@
+/*
+ * U-boot - flash-defines.h
+ *
+ * Copyright (c) 2005 blackfin.uclinux.org
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FLASHDEFINES_H__
+#define __FLASHDEFINES_H__
+
+#include <common.h>
+
+#define V_ULONG(a) (*(volatile unsigned long *)( a ))
+#define V_BYTE(a) (*(volatile unsigned char *)( a ))
+#define TRUE 0x1
+#define FALSE 0x0
+#define BUFFER_SIZE 0x80000
+#define NO_COMMAND 0
+#define GET_CODES 1
+#define RESET 2
+#define WRITE 3
+#define FILL 4
+#define ERASE_ALL 5
+#define ERASE_SECT 6
+#define READ 7
+#define GET_SECTNUM 8
+#define FLASH_START_L 0x0000
+#define FLASH_START_H 0x2000
+#define FLASH_MAN_ST 2
+#define RESET_VAL 0xF0
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+int get_codes(void);
+int poll_toggle_bit(long lOffset);
+void reset_flash(void);
+int erase_flash(void);
+int erase_block_flash(int);
+void unlock_flash(long lOffset);
+int write_data(long lStart, long lCount, uchar * pnData);
+int read_flash(long nOffset, int *pnValue);
+int write_flash(long nOffset, int nValue);
+void get_sector_number(long lOffset, int *pnSector);
+int GetSectorProtectionStatus(flash_info_t * info, int nSector);
+int GetOffset(int nBlock);
+int AFP_NumSectors = 71;
+long AFP_SectorSize2 = 0x10000;
+int AFP_SectorSize1 = 0x2000;
+
+#define NUM_SECTORS 71
+
+#define WRITESEQ1 0x0AAA
+#define WRITESEQ2 0x0554
+#define WRITESEQ3 0x0AAA
+#define WRITESEQ4 0x0AAA
+#define WRITESEQ5 0x0554
+#define WRITESEQ6 0x0AAA
+#define WRITEDATA1 0xaa
+#define WRITEDATA2 0x55
+#define WRITEDATA3 0x80
+#define WRITEDATA4 0xaa
+#define WRITEDATA5 0x55
+#define WRITEDATA6 0x10
+#define PriFlashABegin 0
+#define SecFlashABegin 8
+#define SecFlashBBegin 36
+#define PriFlashAOff 0x0
+#define PriFlashBOff 0x100000
+#define SecFlashAOff 0x10000
+#define SecFlashBOff 0x280000
+#define INVALIDLOCNSTART 0x20270000
+#define INVALIDLOCNEND 0x20280000
+#define BlockEraseVal 0x30
+#define UNLOCKDATA1 0xaa
+#define UNLOCKDATA2 0x55
+#define UNLOCKDATA3 0xa0
+#define GETCODEDATA1 0xaa
+#define GETCODEDATA2 0x55
+#define GETCODEDATA3 0x90
+#define SecFlashASec1Off 0x200000
+#define SecFlashASec2Off 0x204000
+#define SecFlashASec3Off 0x206000
+#define SecFlashASec4Off 0x208000
+#define SecFlashAEndOff 0x210000
+#define SecFlashBSec1Off 0x280000
+#define SecFlashBSec2Off 0x284000
+#define SecFlashBSec3Off 0x286000
+#define SecFlashBSec4Off 0x288000
+#define SecFlashBEndOff 0x290000
+
+#define SECT32 32
+#define SECT33 33
+#define SECT34 34
+#define SECT35 35
+#define SECT36 36
+#define SECT37 37
+#define SECT38 38
+#define SECT39 39
+
+#define FLASH_SUCCESS 0
+#define FLASH_FAIL -1
+
+#endif
diff --git a/board/bf537-stamp/flash.c b/board/bf537-stamp/flash.c
new file mode 100644
index 0000000000..172d3bed19
--- /dev/null
+++ b/board/bf537-stamp/flash.c
@@ -0,0 +1,403 @@
+/*
+ * U-boot - flash.c Flash driver for PSD4256GV
+ *
+ * Copyright (c) 2005 blackfin.uclinux.org
+ * This file is based on BF533EzFlash.c originally written by Analog Devices, Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <malloc.h>
+#include <config.h>
+#include <asm/io.h>
+#include "flash-defines.h"
+
+void flash_reset(void)
+{
+ reset_flash();
+}
+
+unsigned long flash_get_size(ulong baseaddr, flash_info_t * info, int bank_flag)
+{
+ int id = 0, i = 0;
+ static int FlagDev = 1;
+
+ id = get_codes();
+ if (FlagDev) {
+ FlagDev = 0;
+ }
+ info->flash_id = id;
+ switch (bank_flag) {
+ case 0:
+ for (i = PriFlashABegin; i < SecFlashABegin; i++)
+ info->start[i] = (baseaddr + (i * AFP_SectorSize1));
+ for (i = SecFlashABegin; i < NUM_SECTORS; i++)
+ info->start[i] =
+ (baseaddr + SecFlashAOff +
+ ((i - SecFlashABegin) * AFP_SectorSize2));
+ info->size = 0x400000;
+ info->sector_count = NUM_SECTORS;
+ break;
+ case 1:
+ info->start[0] = baseaddr + SecFlashASec1Off;
+ info->start[1] = baseaddr + SecFlashASec2Off;
+ info->start[2] = baseaddr + SecFlashASec3Off;
+ info->start[3] = baseaddr + SecFlashASec4Off;
+ info->size = 0x10000;
+ info->sector_count = 4;
+ break;
+ case 2:
+ info->start[0] = baseaddr + SecFlashBSec1Off;
+ info->start[1] = baseaddr + SecFlashBSec2Off;
+ info->start[2] = baseaddr + SecFlashBSec3Off;
+ info->start[3] = baseaddr + SecFlashBSec4Off;
+ info->size = 0x10000;
+ info->sector_count = 4;
+ break;
+ }
+ return (info->size);
+}
+
+unsigned long flash_init(void)
+{
+ unsigned long size_b;
+ int i;
+
+ size_b = 0;
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ size_b = flash_get_size(CFG_FLASH_BASE, &flash_info[0], 0);
+
+ if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b == 0) {
+ printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+ size_b, size_b >> 20);
+ }
+
+ /* flash_protect (int flag, ulong from, ulong to, flash_info_t *info) */
+ (void)flash_protect(FLAG_PROTECT_SET, CFG_FLASH_BASE,
+ (flash_info[0].start[2] - 1), &flash_info[0]);
+#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT)
+ (void)flash_protect(FLAG_PROTECT_SET, 0x203F0000, 0x203FFFFF,
+ &flash_info[0]);
+#endif
+
+ return (size_b);
+}
+
+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) {
+ case (STM_ID_29W320EB & 0xFFFF):
+ case (STM_ID_29W320DB & 0xFFFF):
+ printf("ST Microelectronics ");
+ break;
+ default:
+ printf("Unknown Vendor: (0x%08X) ", info->flash_id);
+ break;
+ }
+ 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;
+}
+
+int flash_erase(flash_info_t * info, int s_first, int s_last)
+{
+ int cnt = 0, i;
+ int prot, sect;
+
+ 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");
+
+ cnt = s_last - s_first + 1;
+
+#if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT)
+ printf("Erasing Flash locations, Please Wait\n");
+ for (i = s_first; i <= s_last; i++) {
+ if (info->protect[i] == 0) { /* not protected */
+ if (erase_block_flash(i) < 0) {
+ printf("Error Sector erasing \n");
+ return FLASH_FAIL;
+ }
+ }
+ }
+#elif (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)
+ if (cnt == FLASH_TOT_SECT) {
+ printf("Erasing flash, Please Wait \n");
+ if (erase_flash() < 0) {
+ printf("Erasing flash failed \n");
+ return FLASH_FAIL;
+ }
+ } else {
+ printf("Erasing Flash locations, Please Wait\n");
+ for (i = s_first; i <= s_last; i++) {
+ if (info->protect[i] == 0) { /* not protected */
+ if (erase_block_flash(i) < 0) {
+ printf("Error Sector erasing \n");
+ return FLASH_FAIL;
+ }
+ }
+ }
+ }
+#endif
+ printf("\n");
+ return FLASH_SUCCESS;
+}
+
+int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+ int d;
+ if (addr % 2) {
+ read_flash(addr - 1 - CFG_FLASH_BASE, &d);
+ d = (int)((d & 0x00FF) | (*src++ << 8));
+ write_data(addr - 1, 2, (uchar *) & d);
+ write_data(addr + 1, cnt - 1, src);
+ } else
+ write_data(addr, cnt, src);
+ return FLASH_SUCCESS;
+}
+
+int write_data(long lStart, long lCount, uchar * pnData)
+{
+ long i = 0;
+ unsigned long ulOffset = lStart - CFG_FLASH_BASE;
+ int d;
+ int nSector = 0;
+ int flag = 0;
+
+ if (lCount % 2) {
+ flag = 1;
+ lCount = lCount - 1;
+ }
+
+ for (i = 0; i < lCount - 1; i += 2, ulOffset += 2) {
+ get_sector_number(ulOffset, &nSector);
+ read_flash(ulOffset, &d);
+ if (d != 0xffff) {
+ printf
+ ("Flash not erased at offset 0x%x Please erase to reprogram \n",
+ ulOffset);
+ return FLASH_FAIL;
+ }
+ unlock_flash(ulOffset);
+ d = (int)(pnData[i] | pnData[i + 1] << 8);
+ write_flash(ulOffset, d);
+ if (poll_toggle_bit(ulOffset) < 0) {
+ printf("Error programming the flash \n");
+ return FLASH_FAIL;
+ }
+ if ((i > 0) && (!(i % AFP_SectorSize2)))
+ printf(".");
+ }
+ if (flag) {
+ get_sector_number(ulOffset, &nSector);
+ read_flash(ulOffset, &d);
+ if (d != 0xffff) {
+ printf
+ ("Flash not erased at offset 0x%x Please erase to reprogram \n",
+ ulOffset);
+ return FLASH_FAIL;
+ }
+ unlock_flash(ulOffset);
+ d = (int)(pnData[i] | (d & 0xFF00));
+ write_flash(ulOffset, d);
+ if (poll_toggle_bit(ulOffset) < 0) {
+ printf("Error programming the flash \n");
+ return FLASH_FAIL;
+ }
+ }
+ return FLASH_SUCCESS;
+}
+
+int write_flash(long nOffset, int nValue)
+{
+ long addr;
+
+ addr = (CFG_FLASH_BASE + nOffset);
+ *(unsigned volatile short *)addr = nValue;
+ sync();
+#if (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)
+ if (icache_status())
+ udelay(CONFIG_CCLK_HZ / 1000000);
+#endif
+ return FLASH_SUCCESS;
+}
+
+int read_flash(long nOffset, int *pnValue)
+{
+ unsigned short *pFlashAddr =
+ (unsigned short *)(CFG_FLASH_BASE + nOffset);
+
+ *pnValue = *pFlashAddr;
+
+ return TRUE;
+}
+
+int poll_toggle_bit(long lOffset)
+{
+ unsigned int u1, u2;
+ volatile unsigned long *FB =
+ (volatile unsigned long *)(CFG_FLASH_BASE + lOffset);
+ while (1) {
+ u1 = *(volatile unsigned short *)FB;
+ u2 = *(volatile unsigned short *)FB;
+ u1 ^= u2;
+ if (!(u1 & 0x0040))
+ break;
+ if (!(u2 & 0x0020))
+ continue;
+ else {
+ u1 = *(volatile unsigned short *)FB;
+ u2 = *(volatile unsigned short *)FB;
+ u1 ^= u2;
+ if (!(u1 & 0x0040))
+ break;
+ else {
+ reset_flash();
+ return FLASH_FAIL;
+ }
+ }
+ }
+ return FLASH_SUCCESS;
+}
+
+void reset_flash(void)
+{
+ write_flash(WRITESEQ1, RESET_VAL);
+ /* Wait for 10 micro seconds */
+ udelay(10);
+}
+
+int erase_flash(void)
+{
+ write_flash(WRITESEQ1, WRITEDATA1);
+ write_flash(WRITESEQ2, WRITEDATA2);
+ write_flash(WRITESEQ3, WRITEDATA3);
+ write_flash(WRITESEQ4, WRITEDATA4);
+ write_flash(WRITESEQ5, WRITEDATA5);
+ write_flash(WRITESEQ6, WRITEDATA6);
+
+ if (poll_toggle_bit(0x0000) < 0)
+ return FLASH_FAIL;
+
+ return FLASH_SUCCESS;
+}
+
+int erase_block_flash(int nBlock)
+{
+ long ulSectorOff = 0x0;
+
+ if ((nBlock < 0) || (nBlock > AFP_NumSectors))
+ return FALSE;
+
+ // figure out the offset of the block in flash
+ if ((nBlock >= 0) && (nBlock < SecFlashABegin))
+ ulSectorOff = nBlock * AFP_SectorSize1;
+
+ else if ((nBlock >= SecFlashABegin) && (nBlock < NUM_SECTORS))
+ ulSectorOff =
+ SecFlashAOff + (nBlock - SecFlashABegin) * AFP_SectorSize2;
+ // no such sector
+ else
+ return FLASH_FAIL;
+
+ write_flash((WRITESEQ1 | ulSectorOff), WRITEDATA1);
+ write_flash((WRITESEQ2 | ulSectorOff), WRITEDATA2);
+ write_flash((WRITESEQ3 | ulSectorOff), WRITEDATA3);
+ write_flash((WRITESEQ4 | ulSectorOff), WRITEDATA4);
+ write_flash((WRITESEQ5 | ulSectorOff), WRITEDATA5);
+
+ write_flash(ulSectorOff, BlockEraseVal);
+
+ if (poll_toggle_bit(ulSectorOff) < 0)
+ return FLASH_FAIL;
+ printf(".");
+
+ return FLASH_SUCCESS;
+}
+
+void unlock_flash(long ulOffset)
+{
+ unsigned long ulOffsetAddr = ulOffset;
+ ulOffsetAddr &= 0xFFFF0000;
+
+ write_flash((WRITESEQ1 | ulOffsetAddr), UNLOCKDATA1);
+ write_flash((WRITESEQ2 | ulOffsetAddr), UNLOCKDATA2);
+ write_flash((WRITESEQ3 | ulOffsetAddr), UNLOCKDATA3);
+}
+
+int get_codes()
+{
+ int dev_id = 0;
+
+ write_flash(WRITESEQ1, GETCODEDATA1);
+ write_flash(WRITESEQ2, GETCODEDATA2);
+ write_flash(WRITESEQ3, GETCODEDATA3);
+
+ read_flash(0x0402, &dev_id);
+ dev_id &= 0x0000FFFF;
+
+ reset_flash();
+
+ return dev_id;
+}
+
+void get_sector_number(long ulOffset, int *pnSector)
+{
+ int nSector = 0;
+ long lMainEnd = 0x400000;
+ long lBootEnd = 0x10000;
+
+ // sector numbers for the FLASH A boot sectors
+ if (ulOffset < lBootEnd) {
+ nSector = (int)ulOffset / AFP_SectorSize1;
+ }
+ // sector numbers for the FLASH B boot sectors
+ else if ((ulOffset >= lBootEnd) && (ulOffset < lMainEnd)) {
+ nSector = ((ulOffset / (AFP_SectorSize2)) + 7);
+ }
+ // if it is a valid sector, set it
+ if ((nSector >= 0) && (nSector < AFP_NumSectors))
+ *pnSector = nSector;
+
+}
diff --git a/board/bf537-stamp/nand.c b/board/bf537-stamp/nand.c
new file mode 100644
index 0000000000..4d6e7760d5
--- /dev/null
+++ b/board/bf537-stamp/nand.c
@@ -0,0 +1,106 @@
+/*
+ * (C) Copyright 2006 Aubrey.Li, aubrey.li@analog.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+
+#include <nand.h>
+
+#define CONCAT(a,b,c,d) a ## b ## c ## d
+#define PORT(a,b) CONCAT(pPORT,a,b,)
+
+#ifndef CONFIG_NAND_GPIO_PORT
+#define CONFIG_NAND_GPIO_PORT F
+#endif
+
+/*
+ * hardware specific access to control-lines
+ */
+static void bfin_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+ register struct nand_chip *this = mtd->priv;
+
+ switch (cmd) {
+
+ case NAND_CTL_SETCLE:
+ this->IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_CLE;
+ break;
+ case NAND_CTL_CLRCLE:
+ this->IO_ADDR_W = CFG_NAND_BASE;
+ break;
+
+ case NAND_CTL_SETALE:
+ this->IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_ALE;
+ break;
+ case NAND_CTL_CLRALE:
+ this->IO_ADDR_W = CFG_NAND_BASE;
+ break;
+ case NAND_CTL_SETNCE:
+ case NAND_CTL_CLRNCE:
+ break;
+ }
+
+ this->IO_ADDR_R = this->IO_ADDR_W;
+
+ /* Drain the writebuffer */
+ sync();
+}
+
+int bfin_device_ready(struct mtd_info *mtd)
+{
+ int ret = (*PORT(CONFIG_NAND_GPIO_PORT, IO) & BFIN_NAND_READY) ? 1 : 0;
+ sync();
+ return ret;
+}
+
+/*
+ * Board-specific NAND initialization. The following members of the
+ * argument are board-specific (per include/linux/mtd/nand.h):
+ * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
+ * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
+ * - hwcontrol: hardwarespecific function for accesing control-lines
+ * - dev_ready: hardwarespecific function for accesing device ready/busy line
+ * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
+ * only be provided if a hardware ECC is available
+ * - eccmode: mode of ecc, see defines
+ * - chip_delay: chip dependent delay for transfering data from array to
+ * read regs (tR)
+ * - options: various chip options. They can partly be set to inform
+ * nand_scan about special functionality. See the defines for further
+ * explanation
+ * Members with a "?" were not set in the merged testing-NAND branch,
+ * so they are not set here either.
+ */
+void board_nand_init(struct nand_chip *nand)
+{
+ *PORT(CONFIG_NAND_GPIO_PORT, _FER) &= ~BFIN_NAND_READY;
+ *PORT(CONFIG_NAND_GPIO_PORT, IO_DIR) &= ~BFIN_NAND_READY;
+ *PORT(CONFIG_NAND_GPIO_PORT, IO_INEN) |= BFIN_NAND_READY;
+
+ nand->hwcontrol = bfin_hwcontrol;
+ nand->eccmode = NAND_ECC_SOFT;
+ nand->dev_ready = bfin_device_ready;
+ nand->chip_delay = 30;
+}
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
diff --git a/board/bf537-stamp/post-memory.c b/board/bf537-stamp/post-memory.c
new file mode 100644
index 0000000000..60393505a2
--- /dev/null
+++ b/board/bf537-stamp/post-memory.c
@@ -0,0 +1,322 @@
+#include <common.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include <watchdog.h>
+
+#if CONFIG_POST & CFG_POST_MEMORY
+#define CLKIN 25000000
+#define PATTERN1 0x5A5A5A5A
+#define PATTERN2 0xAAAAAAAA
+
+#define CCLK_NUM 4
+#define SCLK_NUM 3
+
+void post_out_buff(char *buff);
+int post_key_pressed(void);
+void post_init_pll(int mult, int div);
+int post_init_sdram(int sclk);
+void post_init_uart(int sclk);
+
+const int pll[CCLK_NUM][SCLK_NUM][2] = {
+ {{20, 4}, {20, 5}, {20, 10}}, /* CCLK = 500M */
+ {{16, 4}, {16, 5}, {16, 8}}, /* CCLK = 400M */
+ {{8, 2}, {8, 4}, {8, 5}}, /* CCLK = 200M */
+ {{4, 1}, {4, 2}, {4, 4}} /* CCLK = 100M */
+};
+const char *const log[CCLK_NUM][SCLK_NUM] = {
+ {"CCLK-500Mhz SCLK-125Mhz: Writing...\0",
+ "CCLK-500Mhz SCLK-100Mhz: Writing...\0",
+ "CCLK-500Mhz SCLK- 50Mhz: Writing...\0",},
+ {"CCLK-400Mhz SCLK-100Mhz: Writing...\0",
+ "CCLK-400Mhz SCLK- 80Mhz: Writing...\0",
+ "CCLK-400Mhz SCLK- 50Mhz: Writing...\0",},
+ {"CCLK-200Mhz SCLK-100Mhz: Writing...\0",
+ "CCLK-200Mhz SCLK- 50Mhz: Writing...\0",
+ "CCLK-200Mhz SCLK- 40Mhz: Writing...\0",},
+ {"CCLK-100Mhz SCLK-100Mhz: Writing...\0",
+ "CCLK-100Mhz SCLK- 50Mhz: Writing...\0",
+ "CCLK-100Mhz SCLK- 25Mhz: Writing...\0",},
+};
+
+int memory_post_test(int flags)
+{
+ int addr;
+ int m, n;
+ int sclk, sclk_temp;
+ int ret = 1;
+
+ sclk_temp = CLKIN / 1000000;
+ sclk_temp = sclk_temp * CONFIG_VCO_MULT;
+ for (sclk = 0; sclk_temp > 0; sclk++)
+ sclk_temp -= CONFIG_SCLK_DIV;
+ sclk = sclk * 1000000;
+ post_init_uart(sclk);
+ if (post_key_pressed() == 0)
+ return 0;
+
+ for (m = 0; m < CCLK_NUM; m++) {
+ for (n = 0; n < SCLK_NUM; n++) {
+ /* Calculate the sclk */
+ sclk_temp = CLKIN / 1000000;
+ sclk_temp = sclk_temp * pll[m][n][0];
+ for (sclk = 0; sclk_temp > 0; sclk++)
+ sclk_temp -= pll[m][n][1];
+ sclk = sclk * 1000000;
+
+ post_init_pll(pll[m][n][0], pll[m][n][1]);
+ post_init_sdram(sclk);
+ post_init_uart(sclk);
+ post_out_buff("\n\r\0");
+ post_out_buff(log[m][n]);
+ for (addr = 0x0; addr < CFG_MAX_RAM_SIZE; addr += 4)
+ *(unsigned long *)addr = PATTERN1;
+ post_out_buff("Reading...\0");
+ for (addr = 0x0; addr < CFG_MAX_RAM_SIZE; addr += 4) {
+ if ((*(unsigned long *)addr) != PATTERN1) {
+ post_out_buff("Error\n\r\0");
+ ret = 0;
+ }
+ }
+ post_out_buff("OK\n\r\0");
+ }
+ }
+ if (ret)
+ post_out_buff("memory POST passed\n\r\0");
+ else
+ post_out_buff("memory POST failed\n\r\0");
+
+ post_out_buff("\n\r\n\r\0");
+ return 1;
+}
+
+void post_init_uart(int sclk)
+{
+ int divisor;
+
+ for (divisor = 0; sclk > 0; divisor++)
+ sclk -= 57600 * 16;
+
+ *pPORTF_FER = 0x000F;
+ *pPORTH_FER = 0xFFFF;
+
+ *pUART_GCTL = 0x00;
+ *pUART_LCR = 0x83;
+ sync();
+ *pUART_DLL = (divisor & 0xFF);
+ sync();
+ *pUART_DLH = ((divisor >> 8) & 0xFF);
+ sync();
+ *pUART_LCR = 0x03;
+ sync();
+ *pUART_GCTL = 0x01;
+ sync();
+}
+
+void post_out_buff(char *buff)
+{
+
+ int i = 0;
+ for (i = 0; i < 0x80000; i++) ;
+ i = 0;
+ while ((buff[i] != '\0') && (i != 100)) {
+ while (!(*pUART_LSR & 0x20)) ;
+ *pUART_THR = buff[i];
+ sync();
+ i++;
+ }
+ for (i = 0; i < 0x80000; i++) ;
+}
+
+/* Using sw10-PF5 as the hotkey */
+#define KEY_LOOP 0x80000
+#define KEY_DELAY 0x80
+int post_key_pressed(void)
+{
+ int i, n;
+ unsigned short value;
+
+ *pPORTF_FER &= ~PF5;
+ *pPORTFIO_DIR &= ~PF5;
+ *pPORTFIO_INEN |= PF5;
+ sync();
+
+ post_out_buff("########Press SW10 to enter Memory POST########: 3\0");
+ for (i = 0; i < KEY_LOOP; i++) {
+ value = *pPORTFIO & PF5;
+ if (*pUART0_RBR == 0x0D) {
+ value = 0;
+ goto key_pressed;
+ }
+ if (value != 0) {
+ goto key_pressed;
+ }
+ for (n = 0; n < KEY_DELAY; n++)
+ asm("nop");
+ }
+ post_out_buff("\b2\0");
+
+ for (i = 0; i < KEY_LOOP; i++) {
+ value = *pPORTFIO & PF5;
+ if (*pUART0_RBR == 0x0D) {
+ value = 0;
+ goto key_pressed;
+ }
+ if (value != 0) {
+ goto key_pressed;
+ }
+ for (n = 0; n < KEY_DELAY; n++)
+ asm("nop");
+ }
+ post_out_buff("\b1\0");
+
+ for (i = 0; i < KEY_LOOP; i++) {
+ value = *pPORTFIO & PF5;
+ if (*pUART0_RBR == 0x0D) {
+ value = 0;
+ goto key_pressed;
+ }
+ if (value != 0) {
+ goto key_pressed;
+ }
+ for (n = 0; n < KEY_DELAY; n++)
+ asm("nop");
+ }
+ key_pressed:
+ post_out_buff("\b0");
+ post_out_buff("\n\r\0");
+ if (value == 0)
+ return 0;
+ post_out_buff("Hotkey has been pressed, Enter POST . . . . . .\n\r\0");
+ return 1;
+}
+
+void post_init_pll(int mult, int div)
+{
+
+ *pSIC_IWR = 0x01;
+ *pPLL_CTL = (mult << 9);
+ *pPLL_DIV = div;
+ asm("CLI R2;");
+ asm("IDLE;");
+ asm("STI R2;");
+ while (!(*pPLL_STAT & 0x20)) ;
+}
+
+int post_init_sdram(int sclk)
+{
+ int SDRAM_tRP, SDRAM_tRP_num, SDRAM_tRAS, SDRAM_tRAS_num, SDRAM_tRCD,
+ SDRAM_tWR;
+ int SDRAM_Tref, SDRAM_NRA, SDRAM_CL, SDRAM_SIZE, SDRAM_WIDTH,
+ mem_SDGCTL, mem_SDBCTL, mem_SDRRC;
+
+ if ((sclk > 119402985)) {
+ SDRAM_tRP = TRP_2;
+ SDRAM_tRP_num = 2;
+ SDRAM_tRAS = TRAS_7;
+ SDRAM_tRAS_num = 7;
+ SDRAM_tRCD = TRCD_2;
+ SDRAM_tWR = TWR_2;
+ } else if ((sclk > 104477612) && (sclk <= 119402985)) {
+ SDRAM_tRP = TRP_2;
+ SDRAM_tRP_num = 2;
+ SDRAM_tRAS = TRAS_6;
+ SDRAM_tRAS_num = 6;
+ SDRAM_tRCD = TRCD_2;
+ SDRAM_tWR = TWR_2;
+ } else if ((sclk > 89552239) && (sclk <= 104477612)) {
+ SDRAM_tRP = TRP_2;
+ SDRAM_tRP_num = 2;
+ SDRAM_tRAS = TRAS_5;
+ SDRAM_tRAS_num = 5;
+ SDRAM_tRCD = TRCD_2;
+ SDRAM_tWR = TWR_2;
+ } else if ((sclk > 74626866) && (sclk <= 89552239)) {
+ SDRAM_tRP = TRP_2;
+ SDRAM_tRP_num = 2;
+ SDRAM_tRAS = TRAS_4;
+ SDRAM_tRAS_num = 4;
+ SDRAM_tRCD = TRCD_2;
+ SDRAM_tWR = TWR_2;
+ } else if ((sclk > 66666667) && (sclk <= 74626866)) {
+ SDRAM_tRP = TRP_2;
+ SDRAM_tRP_num = 2;
+ SDRAM_tRAS = TRAS_3;
+ SDRAM_tRAS_num = 3;
+ SDRAM_tRCD = TRCD_2;
+ SDRAM_tWR = TWR_2;
+ } else if ((sclk > 59701493) && (sclk <= 66666667)) {
+ SDRAM_tRP = TRP_1;
+ SDRAM_tRP_num = 1;
+ SDRAM_tRAS = TRAS_4;
+ SDRAM_tRAS_num = 4;
+ SDRAM_tRCD = TRCD_1;
+ SDRAM_tWR = TWR_2;
+ } else if ((sclk > 44776119) && (sclk <= 59701493)) {
+ SDRAM_tRP = TRP_1;
+ SDRAM_tRP_num = 1;
+ SDRAM_tRAS = TRAS_3;
+ SDRAM_tRAS_num = 3;
+ SDRAM_tRCD = TRCD_1;
+ SDRAM_tWR = TWR_2;
+ } else if ((sclk > 29850746) && (sclk <= 44776119)) {
+ SDRAM_tRP = TRP_1;
+ SDRAM_tRP_num = 1;
+ SDRAM_tRAS = TRAS_2;
+ SDRAM_tRAS_num = 2;
+ SDRAM_tRCD = TRCD_1;
+ SDRAM_tWR = TWR_2;
+ } else if (sclk <= 29850746) {
+ SDRAM_tRP = TRP_1;
+ SDRAM_tRP_num = 1;
+ SDRAM_tRAS = TRAS_1;
+ SDRAM_tRAS_num = 1;
+ SDRAM_tRCD = TRCD_1;
+ SDRAM_tWR = TWR_2;
+ } else {
+ SDRAM_tRP = TRP_1;
+ SDRAM_tRP_num = 1;
+ SDRAM_tRAS = TRAS_1;
+ SDRAM_tRAS_num = 1;
+ SDRAM_tRCD = TRCD_1;
+ SDRAM_tWR = TWR_2;
+ }
+ /*SDRAM INFORMATION: */
+ SDRAM_Tref = 64; /* Refresh period in milliseconds */
+ SDRAM_NRA = 4096; /* Number of row addresses in SDRAM */
+ SDRAM_CL = CL_3; /* 2 */
+
+ SDRAM_SIZE = EBSZ_64;
+ SDRAM_WIDTH = EBCAW_10;
+
+ mem_SDBCTL = SDRAM_WIDTH | SDRAM_SIZE | EBE;
+
+ /* Equation from section 17 (p17-46) of BF533 HRM */
+ mem_SDRRC =
+ (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) -
+ (SDRAM_tRAS_num + SDRAM_tRP_num);
+
+ /* Enable SCLK Out */
+ mem_SDGCTL =
+ (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR
+ | PSS);
+
+ sync();
+
+ *pEBIU_SDGCTL |= 0x1000000;
+ /* Set the SDRAM Refresh Rate control register based on SSCLK value */
+ *pEBIU_SDRRC = mem_SDRRC;
+
+ /* SDRAM Memory Bank Control Register */
+ *pEBIU_SDBCTL = mem_SDBCTL;
+
+ /* SDRAM Memory Global Control Register */
+ *pEBIU_SDGCTL = mem_SDGCTL;
+ sync();
+ return mem_SDRRC;
+}
+
+#endif /* CONFIG_POST & CFG_POST_MEMORY */
+#endif /* CONFIG_POST */
diff --git a/board/bf537-stamp/stm_m25p64.c b/board/bf537-stamp/stm_m25p64.c
new file mode 100644
index 0000000000..7077e85f41
--- /dev/null
+++ b/board/bf537-stamp/stm_m25p64.c
@@ -0,0 +1,515 @@
+/****************************************************************************
+ * SPI flash driver for M25P64
+ ****************************************************************************/
+#include <common.h>
+#include <linux/ctype.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_SPI)
+
+/* Application definitions */
+
+#define NUM_SECTORS 128 /* number of sectors */
+#define SECTOR_SIZE 0x10000
+#define NOP_NUM 1000
+
+#define COMMON_SPI_SETTINGS (SPE|MSTR|CPHA|CPOL) /* Settings to the SPI_CTL */
+#define TIMOD01 (0x01) /* stes the SPI to work with core instructions */
+
+/* Flash commands */
+#define SPI_WREN (0x06) /*Set Write Enable Latch */
+#define SPI_WRDI (0x04) /*Reset Write Enable Latch */
+#define SPI_RDSR (0x05) /*Read Status Register */
+#define SPI_WRSR (0x01) /*Write Status Register */
+#define SPI_READ (0x03) /*Read data from memory */
+#define SPI_FAST_READ (0x0B) /*Read data from memory */
+#define SPI_PP (0x02) /*Program Data into memory */
+#define SPI_SE (0xD8) /*Erase one sector in memory */
+#define SPI_BE (0xC7) /*Erase all memory */
+#define WIP (0x1) /*Check the write in progress bit of the SPI status register */
+#define WEL (0x2) /*Check the write enable bit of the SPI status register */
+
+#define TIMEOUT 350000000
+
+typedef enum {
+ NO_ERR,
+ POLL_TIMEOUT,
+ INVALID_SECTOR,
+ INVALID_BLOCK,
+} ERROR_CODE;
+
+void spi_init_f(void);
+void spi_init_r(void);
+ssize_t spi_read(uchar *, int, uchar *, int);
+ssize_t spi_write(uchar *, int, uchar *, int);
+
+char ReadStatusRegister(void);
+void Wait_For_SPIF(void);
+void SetupSPI(const int spi_setting);
+void SPI_OFF(void);
+void SendSingleCommand(const int iCommand);
+
+ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector);
+ERROR_CODE EraseBlock(int nBlock);
+ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData);
+ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData);
+ERROR_CODE Wait_For_Status(char Statusbit);
+ERROR_CODE Wait_For_WEL(void);
+
+/*
+ * Function: spi_init_f
+ * Description: Init SPI-Controller (ROM part)
+ * return: ---
+ */
+void spi_init_f(void)
+{
+}
+
+/*
+ * Function: spi_init_r
+ * Description: Init SPI-Controller (RAM part) -
+ * The malloc engine is ready and we can move our buffers to
+ * normal RAM
+ * return: ---
+ */
+void spi_init_r(void)
+{
+ return;
+}
+
+/*
+ * Function: spi_write
+ */
+ssize_t spi_write(uchar * addr, int alen, uchar * buffer, int len)
+{
+ unsigned long offset;
+ int start_block, end_block;
+ int start_byte, end_byte;
+ ERROR_CODE result = NO_ERR;
+ uchar temp[SECTOR_SIZE];
+ int i, num;
+
+ offset = addr[0] << 16 | addr[1] << 8 | addr[2];
+ /* Get the start block number */
+ result = GetSectorNumber(offset, &start_block);
+ if (result == INVALID_SECTOR) {
+ printf("Invalid sector! ");
+ return 0;
+ }
+ /* Get the end block number */
+ result = GetSectorNumber(offset + len - 1, &end_block);
+ if (result == INVALID_SECTOR) {
+ printf("Invalid sector! ");
+ return 0;
+ }
+
+ for (num = start_block; num <= end_block; num++) {
+ ReadData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
+ start_byte = num * SECTOR_SIZE;
+ end_byte = (num + 1) * SECTOR_SIZE - 1;
+ if (start_byte < offset)
+ start_byte = offset;
+ if (end_byte > (offset + len))
+ end_byte = (offset + len - 1);
+ for (i = start_byte; i <= end_byte; i++)
+ temp[i - num * SECTOR_SIZE] = buffer[i - offset];
+ EraseBlock(num);
+ result = WriteData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
+ if (result != NO_ERR)
+ return 0;
+ printf(".");
+ }
+ return len;
+}
+
+/*
+ * Function: spi_read
+ */
+ssize_t spi_read(uchar * addr, int alen, uchar * buffer, int len)
+{
+ unsigned long offset;
+ offset = addr[0] << 16 | addr[1] << 8 | addr[2];
+ ReadData(offset, len, (int *)buffer);
+ return len;
+}
+
+void SendSingleCommand(const int iCommand)
+{
+ unsigned short dummy;
+
+ /* turns on the SPI in single write mode */
+ SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
+
+ /* sends the actual command to the SPI TX register */
+ *pSPI_TDBR = iCommand;
+ sync();
+
+ /* The SPI status register will be polled to check the SPIF bit */
+ Wait_For_SPIF();
+
+ dummy = *pSPI_RDBR;
+
+ /* The SPI will be turned off */
+ SPI_OFF();
+
+}
+
+void SetupSPI(const int spi_setting)
+{
+
+ if (icache_status() || dcache_status())
+ udelay(CONFIG_CCLK_HZ / 50000000);
+ /*sets up the PF10 to be the slave select of the SPI */
+ *pPORTF_FER |= (PF10 | PF11 | PF12 | PF13);
+ *pSPI_FLG = 0xFF02;
+ *pSPI_BAUD = CONFIG_SPI_BAUD;
+ *pSPI_CTL = spi_setting;
+ sync();
+
+ *pSPI_FLG = 0xFD02;
+ sync();
+}
+
+void SPI_OFF(void)
+{
+
+ *pSPI_CTL = 0x0400; /* disable SPI */
+ *pSPI_FLG = 0;
+ *pSPI_BAUD = 0;
+ sync();
+ udelay(CONFIG_CCLK_HZ / 50000000);
+
+}
+
+void Wait_For_SPIF(void)
+{
+ unsigned short dummyread;
+ while ((*pSPI_STAT & TXS)) ;
+ while (!(*pSPI_STAT & SPIF)) ;
+ while (!(*pSPI_STAT & RXS)) ;
+ /* Read dummy to empty the receive register */
+ dummyread = *pSPI_RDBR;
+}
+
+ERROR_CODE Wait_For_WEL(void)
+{
+ int i;
+ char status_register = 0;
+ ERROR_CODE ErrorCode = NO_ERR;
+
+ for (i = 0; i < TIMEOUT; i++) {
+ status_register = ReadStatusRegister();
+ if ((status_register & WEL)) {
+ ErrorCode = NO_ERR;
+ break;
+ }
+ ErrorCode = POLL_TIMEOUT; /* Time out error */
+ };
+
+ return ErrorCode;
+}
+
+ERROR_CODE Wait_For_Status(char Statusbit)
+{
+ int i;
+ char status_register = 0xFF;
+ ERROR_CODE ErrorCode = NO_ERR;
+
+ for (i = 0; i < TIMEOUT; i++) {
+ status_register = ReadStatusRegister();
+ if (!(status_register & Statusbit)) {
+ ErrorCode = NO_ERR;
+ break;
+ }
+ ErrorCode = POLL_TIMEOUT; /* Time out error */
+ };
+
+ return ErrorCode;
+}
+
+char ReadStatusRegister(void)
+{
+ char status_register = 0;
+
+ SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turn on the SPI */
+
+ *pSPI_TDBR = SPI_RDSR; /* send instruction to read status register */
+ sync();
+ Wait_For_SPIF(); /*wait until the instruction has been sent */
+ *pSPI_TDBR = 0; /*send dummy to receive the status register */
+ sync();
+ Wait_For_SPIF(); /*wait until the data has been sent */
+ status_register = *pSPI_RDBR; /*read the status register */
+
+ SPI_OFF(); /* Turn off the SPI */
+
+ return status_register;
+}
+
+ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector)
+{
+ int nSector = 0;
+ ERROR_CODE ErrorCode = NO_ERR;
+
+ if (ulOffset > (NUM_SECTORS * 0x10000 - 1)) {
+ ErrorCode = INVALID_SECTOR;
+ return ErrorCode;
+ }
+
+ nSector = (int)ulOffset / 0x10000;
+ *pnSector = nSector;
+
+ return ErrorCode;
+}
+
+ERROR_CODE EraseBlock(int nBlock)
+{
+ unsigned long ulSectorOff = 0x0, ShiftValue;
+ ERROR_CODE ErrorCode = NO_ERR;
+
+ /* if the block is invalid just return */
+ if ((nBlock < 0) || (nBlock > NUM_SECTORS)) {
+ ErrorCode = INVALID_BLOCK;
+ return ErrorCode;
+ }
+ /* figure out the offset of the block in flash */
+ if ((nBlock >= 0) && (nBlock < NUM_SECTORS)) {
+ ulSectorOff = (nBlock * SECTOR_SIZE);
+
+ } else {
+ ErrorCode = INVALID_BLOCK;
+ return ErrorCode;
+ }
+
+ /* A write enable instruction must previously have been executed */
+ SendSingleCommand(SPI_WREN);
+
+ /* The status register will be polled to check the write enable latch "WREN" */
+ ErrorCode = Wait_For_WEL();
+
+ if (POLL_TIMEOUT == ErrorCode) {
+ printf("SPI Erase block error\n");
+ return ErrorCode;
+ } else
+
+ /* Turn on the SPI to send single commands */
+ SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
+
+ /*
+ * Send the erase block command to the flash followed by the 24 address
+ * to point to the start of a sector
+ */
+ *pSPI_TDBR = SPI_SE;
+ sync();
+ Wait_For_SPIF();
+ /* Send the highest byte of the 24 bit address at first */
+ ShiftValue = (ulSectorOff >> 16);
+ *pSPI_TDBR = ShiftValue;
+ sync();
+ /* Wait until the instruction has been sent */
+ Wait_For_SPIF();
+ /* Send the middle byte of the 24 bit address at second */
+ ShiftValue = (ulSectorOff >> 8);
+ *pSPI_TDBR = ShiftValue;
+ sync();
+ /* Wait until the instruction has been sent */
+ Wait_For_SPIF();
+ /* Send the lowest byte of the 24 bit address finally */
+ *pSPI_TDBR = ulSectorOff;
+ sync();
+ /* Wait until the instruction has been sent */
+ Wait_For_SPIF();
+
+ /* Turns off the SPI */
+ SPI_OFF();
+
+ /* Poll the status register to check the Write in Progress bit */
+ /* Sector erase takes time */
+ ErrorCode = Wait_For_Status(WIP);
+
+ /* block erase should be complete */
+ return ErrorCode;
+}
+
+/*
+ * ERROR_CODE ReadData()
+ * Read a value from flash for verify purpose
+ * Inputs: unsigned long ulStart - holds the SPI start address
+ * int pnData - pointer to store value read from flash
+ * long lCount - number of elements to read
+ */
+ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData)
+{
+ unsigned long ShiftValue;
+ char *cnData;
+ int i;
+
+ /* Pointer cast to be able to increment byte wise */
+
+ cnData = (char *)pnData;
+ /* Start SPI interface */
+ SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
+
+#ifdef CONFIG_SPI_FLASH_FAST_READ
+ /* Send the read command to SPI device */
+ *pSPI_TDBR = SPI_FAST_READ;
+#else
+ /* Send the read command to SPI device */
+ *pSPI_TDBR = SPI_READ;
+#endif
+ sync();
+ /* Wait until the instruction has been sent */
+ Wait_For_SPIF();
+ /* Send the highest byte of the 24 bit address at first */
+ ShiftValue = (ulStart >> 16);
+ /* Send the byte to the SPI device */
+ *pSPI_TDBR = ShiftValue;
+ sync();
+ /* Wait until the instruction has been sent */
+ Wait_For_SPIF();
+ /* Send the middle byte of the 24 bit address at second */
+ ShiftValue = (ulStart >> 8);
+ /* Send the byte to the SPI device */
+ *pSPI_TDBR = ShiftValue;
+ sync();
+ /* Wait until the instruction has been sent */
+ Wait_For_SPIF();
+ /* Send the lowest byte of the 24 bit address finally */
+ *pSPI_TDBR = ulStart;
+ sync();
+ /* Wait until the instruction has been sent */
+ Wait_For_SPIF();
+
+#ifdef CONFIG_SPI_FLASH_FAST_READ
+ /* Send dummy for FAST_READ */
+ *pSPI_TDBR = 0;
+ sync();
+ /* Wait until the instruction has been sent */
+ Wait_For_SPIF();
+#endif
+
+ /* After the SPI device address has been placed on the MOSI pin the data can be */
+ /* received on the MISO pin. */
+ for (i = 0; i < lCount; i++) {
+ *pSPI_TDBR = 0;
+ sync();
+ while (!(*pSPI_STAT & RXS)) ;
+ *cnData++ = *pSPI_RDBR;
+
+ if ((i >= SECTOR_SIZE) && (i % SECTOR_SIZE == 0))
+ printf(".");
+ }
+
+ /* Turn off the SPI */
+ SPI_OFF();
+
+ return NO_ERR;
+}
+
+ERROR_CODE WriteFlash(unsigned long ulStartAddr, long lTransferCount,
+ int *iDataSource, long *lWriteCount)
+{
+
+ unsigned long ulWAddr;
+ long lWTransferCount = 0;
+ int i;
+ char iData;
+ char *temp = (char *)iDataSource;
+ ERROR_CODE ErrorCode = NO_ERR;
+
+ /* First, a Write Enable Command must be sent to the SPI. */
+ SendSingleCommand(SPI_WREN);
+
+ /*
+ * Second, the SPI Status Register will be tested whether the
+ * Write Enable Bit has been set
+ */
+ ErrorCode = Wait_For_WEL();
+ if (POLL_TIMEOUT == ErrorCode) {
+ printf("SPI Write Time Out\n");
+ return ErrorCode;
+ } else
+ /* Third, the 24 bit address will be shifted out
+ * the SPI MOSI bytewise.
+ * Turns the SPI on
+ */
+ SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
+ *pSPI_TDBR = SPI_PP;
+ sync();
+ /*wait until the instruction has been sent */
+ Wait_For_SPIF();
+ ulWAddr = (ulStartAddr >> 16);
+ *pSPI_TDBR = ulWAddr;
+ sync();
+ /*wait until the instruction has been sent */
+ Wait_For_SPIF();
+ ulWAddr = (ulStartAddr >> 8);
+ *pSPI_TDBR = ulWAddr;
+ sync();
+ /*wait until the instruction has been sent */
+ Wait_For_SPIF();
+ ulWAddr = ulStartAddr;
+ *pSPI_TDBR = ulWAddr;
+ sync();
+ /*wait until the instruction has been sent */
+ Wait_For_SPIF();
+ /*
+ * Fourth, maximum number of 256 bytes will be taken from the Buffer
+ * and sent to the SPI device.
+ */
+ for (i = 0; (i < lTransferCount) && (i < 256); i++, lWTransferCount++) {
+ iData = *temp;
+ *pSPI_TDBR = iData;
+ sync();
+ /*wait until the instruction has been sent */
+ Wait_For_SPIF();
+ temp++;
+ }
+
+ /* Turns the SPI off */
+ SPI_OFF();
+
+ /*
+ * Sixth, the SPI Write in Progress Bit must be toggled to ensure the
+ * programming is done before start of next transfer
+ */
+ ErrorCode = Wait_For_Status(WIP);
+
+ if (POLL_TIMEOUT == ErrorCode) {
+ printf("SPI Program Time out!\n");
+ return ErrorCode;
+ } else
+
+ *lWriteCount = lWTransferCount;
+
+ return ErrorCode;
+}
+
+ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData)
+{
+
+ unsigned long ulWStart = ulStart;
+ long lWCount = lCount, lWriteCount;
+ long *pnWriteCount = &lWriteCount;
+
+ ERROR_CODE ErrorCode = NO_ERR;
+
+ while (lWCount != 0) {
+ ErrorCode = WriteFlash(ulWStart, lWCount, pnData, pnWriteCount);
+
+ /*
+ * After each function call of WriteFlash the counter
+ * must be adjusted
+ */
+ lWCount -= *pnWriteCount;
+
+ /* Also, both address pointers must be recalculated. */
+ ulWStart += *pnWriteCount;
+ pnData += *pnWriteCount / 4;
+ }
+
+ /* return the appropriate error code */
+ return ErrorCode;
+}
+
+#endif /* CONFIG_SPI */
diff --git a/board/bf537-stamp/u-boot.lds.S b/board/bf537-stamp/u-boot.lds.S
new file mode 100644
index 0000000000..3fb2d0cc60
--- /dev/null
+++ b/board/bf537-stamp/u-boot.lds.S
@@ -0,0 +1,190 @@
+/*
+ * U-boot - u-boot.lds.S
+ *
+ * Copyright (c) 2005-2007 Analog Device Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+OUTPUT_ARCH(bfin)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+MEMORY
+ {
+ ram : ORIGIN = (CFG_MONITOR_BASE), LENGTH = (256 * 1024)
+ l1_code : ORIGIN = 0xFFA00000, LENGTH = 0xC000
+ l1_data : ORIGIN = 0xFF900000, LENGTH = 0x4000
+ }
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS; /*0x1000;*/
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ . = CFG_MONITOR_BASE;
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector before the environment sector. If it throws */
+ /* an error during compilation remove an object here to get */
+ /* it linked after the configuration sector. */
+
+ cpu/bf537/start.o (.text)
+ cpu/bf537/start1.o (.text)
+ cpu/bf537/traps.o (.text)
+ cpu/bf537/interrupt.o (.text)
+ cpu/bf537/serial.o (.text)
+ common/dlmalloc.o (.text)
+/* lib_blackfin/bf533_string.o (.text) */
+/* lib_generic/vsprintf.o (.text) */
+ lib_generic/crc32.o (.text)
+/* lib_generic/zlib.o (.text) */
+/* board/bf537-stamp/bf537-stamp.o (.text) */
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/environment.o (.text)
+
+ *(EXCLUDE_FILE (board/bf537-stamp/post-memory.o) .text)
+ *(.fixup)
+ *(.got1)
+ } > ram
+ _etext = .;
+ PROVIDE (etext = .);
+ .text_l1 :
+ {
+ . = ALIGN(4) ;
+ _text_l1 = .;
+ PROVIDE (text_l1 = .);
+ board/bf537-stamp/post-memory.o (.text)
+ . = ALIGN(4) ;
+ _etext_l1 = .;
+ PROVIDE (etext_l1 = .);
+ } > l1_code AT > ram
+
+ .rodata :
+ {
+ . = ALIGN(4);
+ *(EXCLUDE_FILE (board/bf537-stamp/post-memory.o) .rodata)
+ *(EXCLUDE_FILE (board/bf537-stamp/post-memory.o) .rodata1)
+ *(EXCLUDE_FILE (board/bf537-stamp/post-memory.o) .rodata.str1.4)
+ *(.eh_frame)
+ . = ALIGN(4);
+ } > ram
+
+ . = ALIGN(4);
+ _erodata = .;
+ PROVIDE (erodata = .);
+ .rodata_l1 :
+ {
+ . = ALIGN(4) ;
+ _rodata_l1 = .;
+ PROVIDE (rodata_l1 = .);
+ board/bf537-stamp/post-memory.o (.rodata)
+ board/bf537-stamp/post-memory.o (.rodata1)
+ board/bf537-stamp/post-memory.o (.rodata.str1.4)
+ . = ALIGN(4) ;
+ _erodata_l1 = .;
+ PROVIDE(erodata_l1 = .);
+ } > l1_data AT > ram
+
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ } > ram
+ _edata = .;
+ PROVIDE (edata = .);
+
+ ___u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) } > ram
+ ___u_boot_cmd_end = .;
+
+
+ __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 :
+ {
+ __bss_start = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ } > ram
+ _end = . ;
+ PROVIDE (end = .);
+}
OpenPOWER on IntegriCloud