diff options
Diffstat (limited to 'board/bf537-stamp')
-rw-r--r-- | board/bf537-stamp/Makefile | 3 | ||||
-rw-r--r-- | board/bf537-stamp/bf537-stamp.c | 313 | ||||
-rw-r--r-- | board/bf537-stamp/post-memory.c | 3 | ||||
-rw-r--r-- | board/bf537-stamp/post.c | 244 | ||||
-rw-r--r-- | board/bf537-stamp/spi_flash.c | 297 | ||||
-rw-r--r-- | board/bf537-stamp/u-boot.lds.S | 5 |
6 files changed, 544 insertions, 321 deletions
diff --git a/board/bf537-stamp/Makefile b/board/bf537-stamp/Makefile index cb38b96a3b..3b875a322b 100644 --- a/board/bf537-stamp/Makefile +++ b/board/bf537-stamp/Makefile @@ -29,9 +29,10 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS-y := $(BOARD).o post-memory.o cmd_bf537led.o +COBJS-y := $(BOARD).o cmd_bf537led.o COBJS-$(CONFIG_CMD_EEPROM) += spi_flash.o COBJS-$(CONFIG_CMD_NAND) += nand.o +COBJS-$(CONFIG_POST) += post.o post-memory.o SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(COBJS-y)) diff --git a/board/bf537-stamp/bf537-stamp.c b/board/bf537-stamp/bf537-stamp.c index 5b619be11b..16ffe2f1d1 100644 --- a/board/bf537-stamp/bf537-stamp.c +++ b/board/bf537-stamp/bf537-stamp.c @@ -1,7 +1,7 @@ /* - * U-boot - BF537.c + * U-boot - main board file * - * Copyright (c) 2005-2007 Analog Devices Inc. + * Copyright (c) 2005-2008 Analog Devices Inc. * * (C) Copyright 2000-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -29,15 +29,13 @@ #include <config.h> #include <command.h> #include <asm/blackfin.h> -#include <asm/io.h> +#include <asm/net.h> #include <net.h> #include <asm/mach-common/bits/bootrom.h> #include <netdev.h> DECLARE_GLOBAL_DATA_PTR; -#define POST_WORD_ADDR 0xFF903FFC - int checkboard(void) { printf("Board: ADI BF537 stamp board\n"); @@ -89,22 +87,63 @@ phys_size_t initdram(int board_type) return gd->bd->bi_memsize; } +void board_reset(void) +{ + /* workaround for weak pull ups on ssel */ + if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) { + bfin_write_PORTF_FER(bfin_read_PORTF_FER() & ~PF10); + bfin_write_PORTFIO_SET(PF10); + udelay(1); + } +} + +#ifdef CONFIG_BFIN_MAC +static void board_init_enetaddr(uchar *mac_addr) +{ +#ifdef CONFIG_SYS_NO_FLASH +# define USE_MAC_IN_FLASH 0 +#else +# define USE_MAC_IN_FLASH 1 +#endif + bool valid_mac = false; + + if (USE_MAC_IN_FLASH) { + /* we cram the MAC in the last flash sector */ + uchar *board_mac_addr = (uchar *)0x203F0000; + if (is_valid_ether_addr(board_mac_addr)) { + memcpy(mac_addr, board_mac_addr, 6); + valid_mac = true; + } + } + + if (!valid_mac) { + puts("Warning: Generating 'random' MAC address\n"); + bfin_gen_rand_mac(mac_addr); + } + + eth_setenv_enetaddr("ethaddr", mac_addr); +} + +int board_eth_init(bd_t *bis) +{ + return bfin_EMAC_initialize(bis); +} +#endif + #if defined(CONFIG_MISC_INIT_R) /* miscellaneous platform dependent initialisations */ int misc_init_r(void) { -#if defined(CONFIG_CMD_NET) - char nid[32]; - unsigned char *pMACaddr = (unsigned char *)0x203F0000; +#ifdef CONFIG_BFIN_MAC + uchar enetaddr[6]; + if (!eth_getenv_enetaddr("ethaddr", enetaddr)) + board_init_enetaddr(enetaddr); +#endif - /* 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); - } +#ifndef CONFIG_SYS_NO_FLASH + /* we use the last sector for the MAC address / POST LDR */ + extern flash_info_t flash_info[]; + flash_protect(FLAG_PROTECT_SET, 0x203F0000, 0x203FFFFF, &flash_info[0]); #endif #if defined(CONFIG_BFIN_IDE) @@ -126,245 +165,3 @@ int misc_init_r(void) return 0; } #endif /* CONFIG_MISC_INIT_R */ - -#if defined(CONFIG_BFIN_MAC) - -int board_eth_init(bd_t *bis) -{ - return bfin_EMAC_initialize(bis); -} -#endif - -#ifdef CONFIG_POST -/* 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 - -#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(CONFIG_SYS_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 *)(CONFIG_SYS_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/post-memory.c b/board/bf537-stamp/post-memory.c index 9626f4cd7a..4daea627ef 100644 --- a/board/bf537-stamp/post-memory.c +++ b/board/bf537-stamp/post-memory.c @@ -1,8 +1,6 @@ #include <common.h> #include <asm/io.h> -#ifdef CONFIG_POST - #include <post.h> #include <watchdog.h> @@ -318,4 +316,3 @@ int post_init_sdram(int sclk) } #endif /* CONFIG_POST & CONFIG_SYS_POST_MEMORY */ -#endif /* CONFIG_POST */ diff --git a/board/bf537-stamp/post.c b/board/bf537-stamp/post.c new file mode 100644 index 0000000000..4e844ba432 --- /dev/null +++ b/board/bf537-stamp/post.c @@ -0,0 +1,244 @@ +/* + * BF537-STAMP POST code + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Copyright (c) 2005-2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <config.h> +#include <command.h> +#include <asm/blackfin.h> + +#define POST_WORD_ADDR 0xFF903FFC + +/* 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; + } +} + +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; +} + +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(CONFIG_SYS_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 *)(CONFIG_SYS_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; +} diff --git a/board/bf537-stamp/spi_flash.c b/board/bf537-stamp/spi_flash.c index 7b764b497b..7b753ad6a2 100644 --- a/board/bf537-stamp/spi_flash.c +++ b/board/bf537-stamp/spi_flash.c @@ -18,6 +18,7 @@ #include <malloc.h> #include <asm/io.h> #include <asm/mach-common/bits/spi.h> +#include <asm/mach-common/bits/dma.h> /* Forcibly phase out these */ #ifdef CONFIG_SPI_FLASH_NUM_SECTORS @@ -32,53 +33,65 @@ struct flash_info { char *name; uint16_t id; + uint16_t ext_id; unsigned sector_size; unsigned num_sectors; }; /* SPI Speeds: 50 MHz / 33 MHz */ static struct flash_info flash_spansion_serial_flash[] = { - { "S25FL016", 0x0215, 64 * 1024, 32 }, - { "S25FL032", 0x0216, 64 * 1024, 64 }, - { "S25FL064", 0x0217, 64 * 1024, 128 }, - { "S25FL0128", 0x0218, 256 * 1024, 64 }, - { NULL, 0, 0, 0 } + { "S25FL016", 0x0215, 0, 64 * 1024, 32 }, + { "S25FL032", 0x0216, 0, 64 * 1024, 64 }, + { "S25FL064", 0x0217, 0, 64 * 1024, 128 }, + { "S25FL128-00", 0x2018, 0x0301, 64 * 1024, 256 }, /* Package marking FL128PIF */ + { "S25FL128-01", 0x2018, 0x0300, 128 * 1024, 64 }, /* Package marking FL128PIFL */ + { NULL, 0, 0, 0, 0 } }; /* SPI Speeds: 50 MHz / 20 MHz */ static struct flash_info flash_st_serial_flash[] = { - { "m25p05", 0x2010, 32 * 1024, 2 }, - { "m25p10", 0x2011, 32 * 1024, 4 }, - { "m25p20", 0x2012, 64 * 1024, 4 }, - { "m25p40", 0x2013, 64 * 1024, 8 }, - { "m25p16", 0x2015, 64 * 1024, 32 }, - { "m25p32", 0x2016, 64 * 1024, 64 }, - { "m25p64", 0x2017, 64 * 1024, 128 }, - { "m25p128", 0x2018, 256 * 1024, 64 }, - { NULL, 0, 0, 0 } + { "m25p05", 0x2010, 0, 32 * 1024, 2 }, + { "m25p10", 0x2011, 0, 32 * 1024, 4 }, + { "m25p20", 0x2012, 0, 64 * 1024, 4 }, + { "m25p40", 0x2013, 0, 64 * 1024, 8 }, + { "m25p80", 0x20FF, 0, 64 * 1024, 16 }, + { "m25p16", 0x2015, 0, 64 * 1024, 32 }, + { "m25p32", 0x2016, 0, 64 * 1024, 64 }, + { "m25p64", 0x2017, 0, 64 * 1024, 128 }, + { "m25p128", 0x2018, 0, 256 * 1024, 64 }, + { NULL, 0, 0, 0, 0 } +}; + +/* SPI Speeds: 20 MHz / 40 MHz */ +static struct flash_info flash_sst_serial_flash[] = { + { "SST25WF512", 0x2501, 0, 4 * 1024, 128 }, + { "SST25WF010", 0x2502, 0, 4 * 1024, 256 }, + { "SST25WF020", 0x2503, 0, 4 * 1024, 512 }, + { "SST25WF040", 0x2504, 0, 4 * 1024, 1024 }, + { NULL, 0, 0, 0, 0 } }; /* SPI Speeds: 66 MHz / 33 MHz */ static struct flash_info flash_atmel_dataflash[] = { - { "AT45DB011x", 0x0c, 264, 512 }, - { "AT45DB021x", 0x14, 264, 1025 }, - { "AT45DB041x", 0x1c, 264, 2048 }, - { "AT45DB081x", 0x24, 264, 4096 }, - { "AT45DB161x", 0x2c, 528, 4096 }, - { "AT45DB321x", 0x34, 528, 8192 }, - { "AT45DB642x", 0x3c, 1056, 8192 }, - { NULL, 0, 0, 0 } + { "AT45DB011x", 0x0c, 0, 264, 512 }, + { "AT45DB021x", 0x14, 0, 264, 1025 }, + { "AT45DB041x", 0x1c, 0, 264, 2048 }, + { "AT45DB081x", 0x24, 0, 264, 4096 }, + { "AT45DB161x", 0x2c, 0, 528, 4096 }, + { "AT45DB321x", 0x34, 0, 528, 8192 }, + { "AT45DB642x", 0x3c, 0, 1056, 8192 }, + { NULL, 0, 0, 0, 0 } }; /* SPI Speed: 50 MHz / 25 MHz or 40 MHz / 20 MHz */ static struct flash_info flash_winbond_serial_flash[] = { - { "W25X10", 0x3011, 16 * 256, 32 }, - { "W25X20", 0x3012, 16 * 256, 64 }, - { "W25X40", 0x3013, 16 * 256, 128 }, - { "W25X80", 0x3014, 16 * 256, 256 }, - { "W25P80", 0x2014, 256 * 256, 16 }, - { "W25P16", 0x2015, 256 * 256, 32 }, - { NULL, 0, 0, 0 } + { "W25X10", 0x3011, 0, 16 * 256, 32 }, + { "W25X20", 0x3012, 0, 16 * 256, 64 }, + { "W25X40", 0x3013, 0, 16 * 256, 128 }, + { "W25X80", 0x3014, 0, 16 * 256, 256 }, + { "W25P80", 0x2014, 0, 256 * 256, 16 }, + { "W25P16", 0x2015, 0, 256 * 256, 32 }, + { NULL, 0, 0, 0, 0 } }; struct flash_ops { @@ -97,6 +110,13 @@ static struct flash_ops flash_st_ops = { .status = 0x05, }; +static struct flash_ops flash_sst_ops = { + .read = OP_READ, + .write = 0x02, + .erase = 0x20, + .status = 0x05, +}; + static struct flash_ops flash_atmel_ops = { .read = OP_READ, .write = 0x82, @@ -122,7 +142,7 @@ static struct { struct manufacturer_info *manufacturer; struct flash_info *flash; struct flash_ops *ops; - uint8_t manufacturer_id, device_id1, device_id2; + uint8_t manufacturer_id, device_id1, device_id2, device_extid1, device_extid2; unsigned int write_length; unsigned long sector_size, num_sectors; } flash; @@ -130,6 +150,7 @@ static struct { enum { JED_MANU_SPANSION = 0x01, JED_MANU_ST = 0x20, + JED_MANU_SST = 0xBF, JED_MANU_ATMEL = 0x1F, JED_MANU_WINBOND = 0xEF, }; @@ -148,6 +169,12 @@ static struct manufacturer_info flash_manufacturers[] = { .ops = &flash_st_ops, }, { + .name = "SST", + .id = JED_MANU_SST, + .flashes = flash_sst_serial_flash, + .ops = &flash_sst_ops, + }, + { .name = "Atmel", .id = JED_MANU_ATMEL, .flashes = flash_atmel_dataflash, @@ -161,7 +188,7 @@ static struct manufacturer_info flash_manufacturers[] = { }, }; -#define TIMEOUT 5000 /* timeout of 5 seconds */ +#define TIMEOUT 5000 /* timeout of 5 seconds */ /* If part has multiple SPI flashes, assume SPI0 as that is * the one we can boot off of ... @@ -189,6 +216,7 @@ static void SPI_INIT(void) /* [#3541] This delay appears to be necessary, but not sure * exactly why as the history behind it is non-existant. */ + *pSPI_CTL = 0; udelay(CONFIG_CCLK_HZ / 25000000); /* enable SPI pins: SSEL, MOSI, MISO, SCK */ @@ -205,14 +233,13 @@ static void SPI_INIT(void) #endif /* initate communication upon write of TDBR */ - *pSPI_CTL = (SPE|MSTR|CPHA|CPOL|0x01); + *pSPI_CTL = (SPE | MSTR | CPHA | CPOL | TDBR_CORE); *pSPI_BAUD = CONFIG_SPI_BAUD; } static void SPI_DEINIT(void) { - /* put SPI settings back to reset state */ - *pSPI_CTL = 0x0400; + *pSPI_CTL = 0; *pSPI_BAUD = 0; SSYNC(); } @@ -275,6 +302,7 @@ static int wait_for_ready_status(void) switch (flash.manufacturer_id) { case JED_MANU_SPANSION: case JED_MANU_ST: + case JED_MANU_SST: case JED_MANU_WINBOND: if (!(read_status_register() & 0x01)) return 0; @@ -296,19 +324,68 @@ static int wait_for_ready_status(void) return -1; } +static int enable_writing(void) +{ + ulong start; + + if (flash.manufacturer_id == JED_MANU_ATMEL) + return 0; + + /* A write enable instruction must previously have been executed */ + SPI_ON(); + spi_write_read_byte(0x06); + SPI_OFF(); + + /* The status register will be polled to check the write enable latch "WREN" */ + start = get_timer(0); + while (get_timer(0) - start < TIMEOUT) { + if (read_status_register() & 0x02) + return 0; + + if (ctrlc()) { + puts("\nAbort\n"); + return -1; + } + } + + puts("Timeout\n"); + return -1; +} + +static void write_status_register(uint8_t val) +{ + if (flash.manufacturer_id != JED_MANU_SST) + hang(); + + if (enable_writing()) + return; + + /* send instruction to write status register */ + SPI_ON(); + spi_write_read_byte(0x01); + /* and clear it! */ + spi_write_read_byte(val); + SPI_OFF(); +} + /* Request and read the manufacturer and device id of parts which * are compatible with the JEDEC standard (JEP106) and use that to * setup other operating conditions. */ static int spi_detect_part(void) { - uint16_t dev_id; + uint16_t dev_id, dev_extid; size_t i; static char called_init; if (called_init) return 0; +#ifdef CONFIG_SPI_FLASH_M25P80 + flash.manufacturer_id = JED_MANU_ST; + flash.device_id1 = 0x20; + flash.device_id2 = 0xFF; +#else SPI_ON(); /* Send the request for the part identification */ @@ -327,9 +404,15 @@ static int spi_detect_part(void) /* Now read in the second device id byte */ flash.device_id2 = spi_write_read_byte(0); + /* Read extended device ids */ + flash.device_extid1 = spi_write_read_byte(0); + flash.device_extid2 = spi_write_read_byte(0); + SPI_OFF(); +#endif dev_id = (flash.device_id1 << 8) | flash.device_id2; + dev_extid = (flash.device_extid1 << 8) | flash.device_extid2; for (i = 0; i < ARRAY_SIZE(flash_manufacturers); ++i) { if (flash.manufacturer_id == flash_manufacturers[i].id) @@ -344,9 +427,12 @@ static int spi_detect_part(void) switch (flash.manufacturer_id) { case JED_MANU_SPANSION: case JED_MANU_ST: + case JED_MANU_SST: case JED_MANU_WINBOND: for (i = 0; flash.manufacturer->flashes[i].name; ++i) { - if (dev_id == flash.manufacturer->flashes[i].id) + if (dev_id == flash.manufacturer->flashes[i].id && + (flash.manufacturer->flashes[i].ext_id == 0 || + flash.manufacturer->flashes[i].ext_id == dev_extid)) break; } if (!flash.manufacturer->flashes[i].name) @@ -355,7 +441,11 @@ static int spi_detect_part(void) flash.flash = &flash.manufacturer->flashes[i]; flash.sector_size = flash.flash->sector_size; flash.num_sectors = flash.flash->num_sectors; - flash.write_length = 256; + + if (flash.manufacturer_id == JED_MANU_SST) + flash.write_length = 1; /* pwnt :( */ + else + flash.write_length = 256; break; case JED_MANU_ATMEL: { @@ -381,6 +471,10 @@ static int spi_detect_part(void) } } + /* the SST parts power up with software protection enabled by default */ + if (flash.manufacturer_id == JED_MANU_SST) + write_status_register(0); + called_init = 1; return 0; @@ -538,9 +632,10 @@ static void transmit_address(uint32_t addr) * int pnData - pointer to store value read from flash * long lCount - number of elements to read */ +#ifdef CONFIG_SPI_READFLASH_NODMA static int read_flash(unsigned long address, long count, uchar *buffer) { - size_t i; + size_t i, j; /* Send the read command to SPI device */ SPI_ON(); @@ -554,44 +649,134 @@ static int read_flash(unsigned long address, long count, uchar *buffer) /* After the SPI device address has been placed on the MOSI pin the data can be */ /* received on the MISO pin. */ + j = flash.sector_size << 1; for (i = 1; i <= count; ++i) { *buffer++ = spi_write_read_byte(0); - if (i % flash.sector_size == 0) + if (!j--) { puts("."); + j = flash.sector_size; + } } SPI_OFF(); return 0; } +#else -static int enable_writing(void) +#ifdef __ADSPBF54x__ +#define bfin_write_DMA_SPI_IRQ_STATUS bfin_write_DMA4_IRQ_STATUS +#define bfin_read_DMA_SPI_IRQ_STATUS bfin_read_DMA4_IRQ_STATUS +#define bfin_write_DMA_SPI_CURR_DESC_PTR bfin_write_DMA4_CURR_DESC_PTR +#define bfin_write_DMA_SPI_CONFIG bfin_write_DMA4_CONFIG +#elif defined(__ADSPBF533__) || defined(__ADSPBF532__) || defined(__ADSPBF531__) || \ + defined(__ADSPBF538__) || defined(__ADSPBF539__) +#define bfin_write_DMA_SPI_IRQ_STATUS bfin_write_DMA5_IRQ_STATUS +#define bfin_read_DMA_SPI_IRQ_STATUS bfin_read_DMA5_IRQ_STATUS +#define bfin_write_DMA_SPI_CURR_DESC_PTR bfin_write_DMA5_CURR_DESC_PTR +#define bfin_write_DMA_SPI_CONFIG bfin_write_DMA5_CONFIG +#elif defined(__ADSPBF561__) +#define bfin_write_DMA_SPI_IRQ_STATUS bfin_write_DMA16_IRQ_STATUS +#define bfin_read_DMA_SPI_IRQ_STATUS bfin_read_DMA16_IRQ_STATUS +#define bfin_write_DMA_SPI_CURR_DESC_PTR bfin_write_DMA16_CURR_DESC_PTR +#define bfin_write_DMA_SPI_CONFIG bfin_write_DMA16_CONFIG +#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) || \ + defined(__ADSPBF52x__) || defined(__ADSPBF51x__) +#define bfin_write_DMA_SPI_IRQ_STATUS bfin_write_DMA7_IRQ_STATUS +#define bfin_read_DMA_SPI_IRQ_STATUS bfin_read_DMA7_IRQ_STATUS +#define bfin_write_DMA_SPI_CURR_DESC_PTR bfin_write_DMA7_CURR_DESC_PTR +#define bfin_write_DMA_SPI_CONFIG bfin_write_DMA7_CONFIG +#else +#error "Please provide SPI DMA channel defines" +#endif + +struct dmadesc_array { + unsigned long start_addr; + unsigned short cfg; + unsigned short x_count; + short x_modify; + unsigned short y_count; + short y_modify; +} __attribute__((packed)); + +/* + * 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 + */ + +static int read_flash(unsigned long address, long count, uchar *buffer) { - ulong start; + unsigned int ndsize; + struct dmadesc_array dma[2]; + /* Send the read command to SPI device */ - if (flash.manufacturer_id == JED_MANU_ATMEL) + if (!count) return 0; - /* A write enable instruction must previously have been executed */ + dma[0].start_addr = (unsigned long)buffer; + dma[0].x_modify = 1; + if (count <= 65536) { + blackfin_dcache_flush_invalidate_range(buffer, buffer + count); + ndsize = NDSIZE_5; + dma[0].cfg = NDSIZE_0 | WNR | WDSIZE_8 | FLOW_STOP | DMAEN | DI_EN; + dma[0].x_count = count; + } else { + blackfin_dcache_flush_invalidate_range(buffer, buffer + 65536 - 1); + ndsize = NDSIZE_7; + dma[0].cfg = NDSIZE_5 | WNR | WDSIZE_8 | FLOW_ARRAY | DMAEN | DMA2D; + dma[0].x_count = 0; /* 2^16 */ + dma[0].y_count = count >> 16; /* count / 2^16 */ + dma[0].y_modify = 1; + dma[1].start_addr = (unsigned long)(buffer + (count & ~0xFFFF)); + dma[1].cfg = NDSIZE_0 | WNR | WDSIZE_8 | FLOW_STOP | DMAEN | DI_EN; + dma[1].x_count = count & 0xFFFF; /* count % 2^16 */ + dma[1].x_modify = 1; + } + + bfin_write_DMA_SPI_CONFIG(0); + bfin_write_DMA_SPI_IRQ_STATUS(DMA_DONE | DMA_ERR); + bfin_write_DMA_SPI_CURR_DESC_PTR(dma); + SPI_ON(); - spi_write_read_byte(0x06); + + spi_write_read_byte(flash.ops->read); + transmit_address(address); + +#ifndef CONFIG_SPI_FLASH_SLOW_READ + /* Send dummy byte when doing SPI fast reads */ + spi_write_read_byte(0); +#endif + + bfin_write_DMA_SPI_CONFIG(ndsize | FLOW_ARRAY | DMAEN); + *pSPI_CTL = (MSTR | CPHA | CPOL | RDBR_DMA | SPE | SZ); + SSYNC(); + + /* + * We already invalidated the first 64k, + * now while we just wait invalidate the remaining part. + * Its not likely that the DMA is going to overtake + */ + if (count > 65536) + blackfin_dcache_flush_invalidate_range(buffer + 65536, + buffer + count); + + while (!(bfin_read_DMA_SPI_IRQ_STATUS() & DMA_DONE)) + if (ctrlc()) + break; + SPI_OFF(); - /* The status register will be polled to check the write enable latch "WREN" */ - start = get_timer(0); - while (get_timer(0) - start < TIMEOUT) { - if (read_status_register() & 0x02) - return 0; + *pSPI_CTL = 0; - if (ctrlc()) { - puts("\nAbort\n"); - return -1; - } - } + bfin_write_DMA_SPI_CONFIG(0); - puts("Timeout\n"); - return -1; + *pSPI_CTL = (SPE | MSTR | CPHA | CPOL | TDBR_CORE); + + return 0; } +#endif static long address_to_sector(unsigned long address) { diff --git a/board/bf537-stamp/u-boot.lds.S b/board/bf537-stamp/u-boot.lds.S index 76daa75c0d..8ddfa81dad 100644 --- a/board/bf537-stamp/u-boot.lds.S +++ b/board/bf537-stamp/u-boot.lds.S @@ -44,12 +44,11 @@ OUTPUT_ARCH(bfin) -/* The 0xC offset is so we don't clobber the tiny LDR jump block. */ MEMORY { ram : ORIGIN = CONFIG_SYS_MONITOR_BASE, LENGTH = CONFIG_SYS_MONITOR_LEN - l1_code : ORIGIN = L1_INST_SRAM+0xC, LENGTH = L1_INST_SRAM_SIZE - l1_data : ORIGIN = L1_DATA_B_SRAM, LENGTH = L1_DATA_B_SRAM_SIZE + l1_code : ORIGIN = L1_INST_SRAM, LENGTH = L1_INST_SRAM_SIZE + l1_data : ORIGIN = L1_DATA_B_SRAM, LENGTH = L1_DATA_B_SRAM_SIZE } ENTRY(_start) |