summaryrefslogtreecommitdiffstats
path: root/board/aspeed/ast2050/flash_spi.c
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineering.com>2017-08-23 15:54:21 -0500
committerTimothy Pearson <tpearson@raptorengineering.com>2017-08-23 15:54:21 -0500
commit0223e595f4033e91e93403a7317bcc9e47676b8f (patch)
tree2ccd7127bc343f82456b76eeb0da2d380f6eaf65 /board/aspeed/ast2050/flash_spi.c
downloadast2050-uboot-0223e595f4033e91e93403a7317bcc9e47676b8f.zip
ast2050-uboot-0223e595f4033e91e93403a7317bcc9e47676b8f.tar.gz
Initial import of modified u-boot tree
Original upstream URL: git://git.denx.de/u-boot.git Original upstream GIT hash: 62c175fbb8a0f9a926c88294ea9f7e88eb898f6c
Diffstat (limited to 'board/aspeed/ast2050/flash_spi.c')
-rw-r--r--board/aspeed/ast2050/flash_spi.c836
1 files changed, 836 insertions, 0 deletions
diff --git a/board/aspeed/ast2050/flash_spi.c b/board/aspeed/ast2050/flash_spi.c
new file mode 100644
index 0000000..8eda064
--- /dev/null
+++ b/board/aspeed/ast2050/flash_spi.c
@@ -0,0 +1,836 @@
+/*
+ * (C) Copyright 2002-2004
+ * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com
+ *
+ * Copyright (C) 2003 Arabella Software Ltd.
+ * Yuli Barcohen <yuli@arabellasw.com>
+ * Modified to work with AMD flashes
+ *
+ * Copyright (C) 2004
+ * Ed Okerson
+ * Modified to work with little-endian systems.
+ *
+ * Copyright (C) 2017 Raptor Engineering, LLC
+ *
+ * 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
+ *
+ * History
+ * 01/20/2004 - combined variants of original driver.
+ * 01/22/2004 - Write performance enhancements for parallel chips (Tolunay)
+ * 01/23/2004 - Support for x8/x16 chips (Rune Raknerud)
+ * 01/27/2004 - Little endian support Ed Okerson
+ *
+ * Tested Architectures
+ * Port Width Chip Width # of banks Flash Chip Board
+ * 32 16 1 28F128J3 seranoa/eagle
+ * 64 16 1 28F128J3 seranoa/falcon
+ *
+ */
+
+/* The DEBUG define must be before common to enable debugging */
+/* #define DEBUG */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/byteorder.h>
+#include <environment.h>
+
+#ifdef CONFIG_FLASH_SPI
+
+/*
+ * This file implements a Common Flash Interface (CFI) driver for U-Boot.
+ * The width of the port and the width of the chips are determined at initialization.
+ * These widths are used to calculate the address for access CFI data structures.
+ * It has been tested on an Intel Strataflash implementation and AMD 29F016D.
+ *
+ * References
+ * JEDEC Standard JESD68 - Common Flash Interface (CFI)
+ * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
+ * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
+ * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
+ *
+ * TODO
+ *
+ * Use Primary Extended Query table (PRI) and Alternate Algorithm Query
+ * Table (ALT) to determine if protection is available
+ *
+ * Add support for other command sets Use the PRI and ALT to determine command set
+ * Verify erase and program timeouts.
+ */
+
+#ifndef CONFIG_FLASH_BANKS_LIST
+#define CONFIG_FLASH_BANKS_LIST { CONFIG_FLASH_BASE }
+#endif
+
+/* use CONFIG_SYS_MAX_FLASH_BANKS_DETECT if defined */
+#ifdef CONFIG_SYS_MAX_FLASH_BANKS_DETECT
+static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS_DETECT] = CONFIG_FLASH_BANKS_LIST;
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
+#else
+static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_FLASH_BANKS_LIST;
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */
+#endif
+
+/* Support Flash ID */
+#define STM25P64 0x172020
+#define STM25P128 0x182020
+#define S25FL128P 0x182001
+#define S25FL064A 0x160201
+#define MX25L12805D 0x1820c2
+
+#define W25X16 0x1530ef
+#define W25X32 0x1630ef
+#define W25X64 0x1730ef
+
+/* SPI Define */
+#define STCBaseAddress 0x16000000
+#define SPICtrlRegOffset 0x0C
+
+#define CMD_MASK 0xFFFFFFF8
+
+#define NORMALREAD 0x00
+#define FASTREAD 0x01
+#define NORMALWRITE 0x02
+#define USERMODE 0x03
+
+#define CE_LOW 0x00
+#define CE_HIGH 0x04
+
+#define BufferSize 256
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+
+typedef unsigned long flash_sect_t;
+
+static void reset_flash (flash_info_t * info);
+static void enable_write (flash_info_t * info);
+static void write_status_register (flash_info_t * info, uchar data);
+static ulong flash_get_size (ulong base, int banknum);
+static int flash_write_buffer (flash_info_t *info, uchar *src, ulong addr, int len);
+#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_MONITOR_BASE >= CONFIG_FLASH_BASE)
+static flash_info_t *flash_get_info(ulong base);
+#endif
+
+
+/*-----------------------------------------------------------------------
+ * create an address based on the offset and the port width
+ */
+inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)
+{
+ return ((uchar *) (info->start[sect] + (offset * 1)));
+}
+
+/*-----------------------------------------------------------------------
+ * read a character at a port width address
+ */
+inline uchar flash_read_uchar (flash_info_t * info, uint offset)
+{
+ uchar *cp;
+
+ cp = flash_make_addr (info, 0, offset);
+#if defined(__LITTLE_ENDIAN)
+ return (cp[0]);
+#else
+ return (cp[1 - 1]);
+#endif
+}
+
+/*-----------------------------------------------------------------------
+ * read a short word by swapping for ppc format.
+ */
+ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)
+{
+ uchar *addr;
+ ushort retval;
+
+#ifdef DEBUG
+ int x;
+#endif
+ addr = flash_make_addr (info, sect, offset);
+
+#ifdef DEBUG
+ debug ("ushort addr is at %p 1 = %d\n", addr,
+ 1);
+ for (x = 0; x < 2 * 1; x++) {
+ debug ("addr[%x] = 0x%x\n", x, addr[x]);
+ }
+#endif
+#if defined(__LITTLE_ENDIAN)
+ retval = ((addr[(1)] << 8) | addr[0]);
+#else
+ retval = ((addr[(2 * 1) - 1] << 8) |
+ addr[1 - 1]);
+#endif
+
+ debug ("retval = 0x%x\n", retval);
+ return retval;
+}
+
+/*-----------------------------------------------------------------------
+ * read a long word by picking the least significant byte of each maiximum
+ * port size word. Swap for ppc format.
+ */
+ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
+{
+ uchar *addr;
+ ulong retval;
+
+#ifdef DEBUG
+ int x;
+#endif
+ addr = flash_make_addr (info, sect, offset);
+
+#ifdef DEBUG
+ debug ("long addr is at %p 1 = %d\n", addr,
+ 1);
+ for (x = 0; x < 4 * 1; x++) {
+ debug ("addr[%x] = 0x%x\n", x, addr[x]);
+ }
+#endif
+#if defined(__LITTLE_ENDIAN)
+ retval = (addr[0] << 16) | (addr[(1)] << 24) |
+ (addr[(2 * 1)]) | (addr[(3 * 1)] << 8);
+#else
+ retval = (addr[(2 * 1) - 1] << 24) |
+ (addr[(1) - 1] << 16) |
+ (addr[(4 * 1) - 1] << 8) |
+ addr[(3 * 1) - 1];
+#endif
+ return retval;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void reset_flash (flash_info_t * info)
+{
+ ulong ulCtrlData;
+
+ ulCtrlData = (0x0b0000) | (info->tCK_Read << 8) | (info->dummybyte << 6);
+ ulCtrlData |= CE_HIGH | FASTREAD;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+}
+
+static void enable_write (flash_info_t * info)
+{
+ ulong base;
+ ulong ulCtrlData;
+ uchar jReg;
+
+ base = info->start[0];
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x06);
+ udelay(10);
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x05);
+ udelay(10);
+ do {
+ jReg = *(volatile uchar *) (base);
+ } while (!(jReg & 0x02));
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+
+}
+
+static void write_status_register (flash_info_t * info, uchar data)
+{
+ ulong base;
+ ulong ulCtrlData;
+ uchar jReg;
+
+ base = info->start[0];
+
+ enable_write (info);
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x01);
+ udelay(10);
+ *(uchar *) (base) = (uchar) (data);
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+
+/*
+ ulCtrlData = CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x05);
+ udelay(10);
+ do {
+ jReg = *(volatile uchar *) (base);
+ } while ((jReg & 0x02));
+ ulCtrlData = CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+*/
+ ulCtrlData = CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x05);
+ udelay(10);
+ do {
+ jReg = *(volatile uchar *) (base);
+ } while ((jReg & 0x01));
+ ulCtrlData = CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+
+}
+
+/*
+ *
+ */
+static ulong flash_get_size (ulong base, int banknum)
+{
+ flash_info_t *info = &flash_info[banknum];
+ int j;
+ unsigned long sector;
+ int erase_region_size;
+ ulong ulCtrlData;
+ int usID;
+ ulong cpuclk, div, reg;
+ ulong WriteClk, EraseClk, ReadClk;
+
+ info->start[0] = base;
+ cpuclk = 266;
+ erase_region_size = 0x10000;
+ WriteClk = 40;
+ EraseClk = 20;
+ ReadClk = 40;
+
+ /* Get Flash ID */
+ ulCtrlData = *(ulong *) (STCBaseAddress + SPICtrlRegOffset) & CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x9F);
+ udelay(10);
+ usID = *(int *) (base) & 0xFFFFFF;
+ ulCtrlData = *(ulong *) (STCBaseAddress + SPICtrlRegOffset) & CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ info->flash_id = usID;
+
+ printf("SPI Flash ID: %x \n", usID);
+
+ switch (info->flash_id)
+ {
+ case STM25P64:
+ info->sector_count = 128;
+ info->size = 0x800000;
+ erase_region_size = 0x10000;
+ info->dummybyte = 1;
+ WriteClk = 40;
+ EraseClk = 20;
+ ReadClk = 40;
+ break;
+ case STM25P128:
+ info->sector_count = 64;
+ info->size = 0x1000000;
+ erase_region_size = 0x40000;
+ info->dummybyte = 1;
+ WriteClk = 50;
+ EraseClk = 20;
+ ReadClk = 50;
+ break;
+ case S25FL128P:
+ info->sector_count = 256;
+ info->size = 0x1000000;
+ erase_region_size = 0x10000;
+ info->dummybyte = 1;
+ WriteClk = 100;
+ EraseClk = 40;
+ ReadClk = 100;
+ break;
+ case S25FL064A:
+ info->sector_count = 128;
+ info->size = 0x800000;
+ erase_region_size = 0x10000;
+ info->dummybyte = 1;
+ WriteClk = 50;
+ EraseClk = 25;
+ ReadClk = 50;
+ break;
+
+ case W25X16:
+ info->sector_count = 32;
+ info->size = 0x200000;
+ erase_region_size = 0x10000;
+ info->dummybyte = 1;
+ WriteClk = 50;
+ EraseClk = 25;
+ ReadClk = 50;
+ break;
+ case W25X32:
+ info->sector_count = 64;
+ info->size = 0x400000;
+ erase_region_size = 0x10000;
+ info->dummybyte = 1;
+ WriteClk = 50;
+ EraseClk = 25;
+ ReadClk = 50;
+ break;
+ case W25X64:
+ info->sector_count = 128;
+ info->size = 0x800000;
+ erase_region_size = 0x10000;
+ info->dummybyte = 1;
+ WriteClk = 50;
+ EraseClk = 25;
+ ReadClk = 50;
+ break;
+ case MX25L12805D:
+ info->sector_count = 256;
+ info->size = 0x1000000;
+ erase_region_size = 0x10000;
+ info->dummybyte = 1;
+ WriteClk = 50;
+ EraseClk = 33;
+ ReadClk = 50;
+ break;
+
+ default:
+ printf("Can't support this SPI Flash!! \n");
+ break;
+ }
+
+ debug ("erase_region_size = %d\n",
+ erase_region_size);
+
+ sector = base;
+ for (j = 0; j < info->sector_count; j++) {
+
+ info->start[j] = sector;
+ sector += erase_region_size;
+ info->protect[j] = 0; /* default: not protected */
+ }
+
+ /* set SPI flash extended info */
+ reg = *((volatile ulong*) 0x1e6e2070);
+ switch (reg & 0xe00)
+ {
+ case 0x000:
+ cpuclk = 266;
+ break;
+ case 0x200:
+ cpuclk = 233;
+ break;
+ case 0x400:
+ cpuclk = 200;
+ break;
+ case 0x600:
+ cpuclk = 166;
+ break;
+ case 0x800:
+ cpuclk = 133;
+ break;
+ case 0xA00:
+ cpuclk = 100;
+ break;
+ case 0xC00:
+ cpuclk = 300;
+ break;
+ case 0xE00:
+ cpuclk = 24;
+ break;
+ }
+ switch (reg & 0x3000)
+ {
+ case 0x1000:
+ cpuclk /= 2;
+ break;
+ case 0x2000:
+ cpuclk /= 4;
+ break;
+ case 0x3000:
+ cpuclk /= 3;
+ break;
+ }
+ div = 2;
+ info->tCK_Write = 7;
+ while ( (cpuclk/div) > WriteClk )
+ {
+ info->tCK_Write--;
+ div +=2;
+ }
+ div = 2;
+ info->tCK_Erase = 7;
+ while ( (cpuclk/div) > EraseClk )
+ {
+ info->tCK_Erase--;
+ div +=2;
+ }
+ div = 2;
+ info->tCK_Read = 7;
+ while ( (cpuclk/div) > ReadClk )
+ {
+ info->tCK_Read--;
+ div +=2;
+ }
+
+ /* unprotect flash */
+ write_status_register(info, 0);
+
+ reset_flash(info);
+
+ return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+static int flash_write_buffer (flash_info_t *info, uchar *src, ulong addr, int len)
+{
+ ulong j, base, offset;
+ ulong ulCtrlData;
+ uchar jReg;
+
+ base = info->start[0];
+ offset = addr - base;
+
+ enable_write (info);
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x02);
+ udelay(10);
+ *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
+ udelay(10);
+ *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
+ udelay(10);
+ *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
+ udelay(10);
+
+ for (j=0; j<len; j++)
+ {
+ *(uchar *) (base) = *(uchar *) (src++);
+ udelay(10);
+ }
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x05);
+ udelay(10);
+ do {
+ jReg = *(volatile uchar *) (base);
+ } while ((jReg & 0x01));
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ */
+//static int flash_read_buffer (flash_info_t *info, uchar *dest, ulong addr, int len)
+//{
+// ulong j, base, offset;
+// ulong ulCtrlData;
+// uchar jReg;
+//
+// base = info->start[0];
+// offset = addr - base;
+//
+// /* Set Normal Reading */
+// ulCtrlData = (info->tCK_Read << 8);
+// ulCtrlData &= 0xfffffffC;
+// *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+// udelay(100);
+// *(uchar *) (base) = (uchar) (0x03);
+// udelay(10);
+// *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
+// udelay(10);
+// *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
+// udelay(10);
+// *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
+// udelay(10);
+//
+// for (j=0; j<len; j++)
+// {
+// *(uchar *) (dest++) = *(uchar *) (base);
+// udelay(10);
+// }
+//
+// ulCtrlData = (info->tCK_Write << 8);
+// ulCtrlData |= CE_LOW | USERMODE;
+// *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+// udelay(100);
+// *(uchar *) (base) = (uchar) (0x05);
+// udelay(10);
+// do {
+// jReg = *(volatile uchar *) (base);
+// } while ((jReg & 0x01));
+// ulCtrlData = (info->tCK_Write << 8);
+// ulCtrlData |= CE_HIGH | USERMODE;
+// *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+// udelay(100);
+//
+// return 0;
+//}
+
+/*-----------------------------------------------------------------------
+ *
+ * export functions
+ *
+ */
+
+/*-----------------------------------------------------------------------
+ *
+ */
+unsigned long flash_init (void)
+{
+ unsigned long size = 0;
+ int i;
+
+ /* Init: no FLASHes known */
+ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ size += flash_info[i].size = flash_get_size (bank_base[i], i);
+ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
+#ifndef CONFIG_FLASH_QUIET_TEST
+ printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
+ i, flash_info[i].size, flash_info[i].size << 20);
+#endif /* CONFIG_FLASH_QUIET_TEST */
+ }
+ }
+
+ /* Monitor protection ON by default */
+#if (CONFIG_MONITOR_BASE >= CONFIG_FLASH_BASE)
+ flash_protect (FLAG_PROTECT_SET,
+ CONFIG_MONITOR_BASE,
+ CONFIG_MONITOR_BASE + monitor_flash_len - 1,
+ flash_get_info(CONFIG_MONITOR_BASE));
+#endif
+
+ /* Environment protection ON by default */
+#ifdef CONFIG_ENV_IS_IN_FLASH
+ flash_protect (FLAG_PROTECT_SET,
+ CONFIG_ENV_ADDR,
+ CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
+ flash_get_info(CONFIG_ENV_ADDR));
+#endif
+
+ /* Redundant environment protection ON by default */
+#ifdef CONFIG_ENV_ADDR_REDUND
+ flash_protect (FLAG_PROTECT_SET,
+ CONFIG_ENV_ADDR_REDUND,
+ CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SIZE_REDUND - 1,
+ flash_get_info(CONFIG_ENV_ADDR_REDUND));
+#endif
+ return (size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_MONITOR_BASE >= CONFIG_FLASH_BASE)
+static flash_info_t *flash_get_info(ulong base)
+{
+ int i;
+ flash_info_t * info = 0;
+
+ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++)
+ {
+ info = & flash_info[i];
+ if (info->size && info->start[0] <= base &&
+ base <= info->start[0] + info->size - 1)
+ break;
+ }
+
+ return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
+}
+#endif
+
+/*-----------------------------------------------------------------------
+ */
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+ int rcode = 0;
+ int prot;
+ flash_sect_t sect;
+
+ ulong base, offset;
+ ulong ulCtrlData;
+ uchar jReg;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ puts ("- no sectors to erase\n");
+ return 1;
+ }
+
+ prot = 0;
+ for (sect = s_first; sect <= s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+ if (prot) {
+ printf ("- Warning: %d protected sectors will not be erased!\n", prot);
+ } else {
+ putc ('\n');
+ }
+
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ /* start erasing */
+ enable_write(info);
+
+ base = info->start[0];
+ offset = info->start[sect] - base;
+
+ ulCtrlData = (info->tCK_Erase << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0xd8);
+ udelay(10);
+ *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
+ udelay(10);
+ *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
+ udelay(10);
+ *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
+ udelay(10);
+
+ ulCtrlData = (info->tCK_Erase << 8);
+ ulCtrlData |= CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+
+ ulCtrlData = (info->tCK_Erase << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+ *(uchar *) (base) = (uchar) (0x05);
+ udelay(10);
+ do {
+ jReg = *(volatile uchar *) (base);
+ } while ((jReg & 0x01));
+ ulCtrlData = (info->tCK_Erase << 8);
+ ulCtrlData |= CE_HIGH | USERMODE;
+ *(ulong *) (STCBaseAddress + SPICtrlRegOffset) = ulCtrlData;
+ udelay(100);
+
+ putc ('.');
+ }
+ }
+ puts (" done\n");
+
+ reset_flash(info);
+
+ return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+ putc ('\n');
+ return;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+ int count;
+
+ /* get lower aligned address */
+ if (addr & (BufferSize - 1))
+ {
+ count = cnt >= BufferSize ? (BufferSize - (addr & 0xff)):cnt;
+ flash_write_buffer (info, src, addr, count);
+ addr+= count;
+ src += count;
+ cnt -= count;
+ }
+
+ /* prog */
+ while (cnt > 0) {
+ count = cnt >= BufferSize ? BufferSize:cnt;
+ flash_write_buffer (info, src, addr, count);
+ addr+= count;
+ src += count;
+ cnt -= count;
+ }
+
+ reset_flash(info);
+
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+int read_buff (flash_info_t * info, uchar * dest, ulong addr, ulong cnt)
+{
+ ulong buf;
+
+ while (cnt >=4) {
+
+ buf = *(ulong *)addr;
+ *(dest+3) = buf >> 24;
+ *(dest+2) = buf >> 16;
+ *(dest+1) = buf >> 8;
+ *(dest+0) = buf;
+
+ dest += 4;
+ addr +=4;
+ cnt -= 4;
+ };
+
+ while (cnt--)
+ {
+ *dest = *(uchar *)addr;
+ dest++,addr++;
+ }
+ return 0;
+}
+#endif /* CONFIG_FLASH_SPI */
OpenPOWER on IntegriCloud