summaryrefslogtreecommitdiff
path: root/board/wmt/flash
diff options
context:
space:
mode:
authorKevin2014-11-15 11:48:36 +0800
committerKevin2014-11-15 11:48:36 +0800
commitd04075478d378d9e15f3e1abfd14b0bd124077d4 (patch)
tree733dd964582f388b9e3e367c249946cd32a2851f /board/wmt/flash
downloadFOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.gz
FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.bz2
FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.zip
init commit via android 4.4 uboot
Diffstat (limited to 'board/wmt/flash')
-rwxr-xr-xboard/wmt/flash/nand_flash.c95
-rwxr-xr-xboard/wmt/flash/nand_flash.h36
-rwxr-xr-xboard/wmt/flash/nor_flash_16bit.c1225
-rwxr-xr-xboard/wmt/flash/nor_flash_16bit.h38
-rwxr-xr-xboard/wmt/flash/nor_flash_8bit.c1067
-rwxr-xr-xboard/wmt/flash/nor_flash_8bit.h38
-rwxr-xr-xboard/wmt/flash/spi_flash.c865
-rwxr-xr-xboard/wmt/flash/spi_flash.h145
-rwxr-xr-xboard/wmt/flash/spi_flash_lock.c82
9 files changed, 3591 insertions, 0 deletions
diff --git a/board/wmt/flash/nand_flash.c b/board/wmt/flash/nand_flash.c
new file mode 100755
index 0000000..8e116b9
--- /dev/null
+++ b/board/wmt/flash/nand_flash.c
@@ -0,0 +1,95 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2008 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include "nand_flash.h"
+
+extern flash_info_t flash_info_nand[CFG_MAX_NAND_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+#ifdef CFG_FLASH_PROTECTION
+static void flash_sync_real_protect(flash_info_t *info);
+#endif
+
+/*-----------------------------------------------------------------------
+ * nand_flash_init()
+ *
+ * sets up flash_info and returns size of FLASH (bytes)
+ */
+unsigned long nand_flash_init(void)
+{
+ unsigned long size_b = 0;
+ return size_b;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void nand_flash_print_info(flash_info_t *info)
+{
+}
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+static void flash_sync_real_protect(flash_info_t *info)
+{
+}
+#endif
+
+/*-----------------------------------------------------------------------
+ */
+
+int nand_flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+ int rcode = 0;
+ return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int nand_write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ int res = 0;
+ return res;
+}
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+int nand_flash_real_protect(flash_info_t *info, long sector, int prot)
+{
+ int rcode = 0; /* assume success */
+ return rcode;
+}
+#endif
diff --git a/board/wmt/flash/nand_flash.h b/board/wmt/flash/nand_flash.h
new file mode 100755
index 0000000..ab1f2d5
--- /dev/null
+++ b/board/wmt/flash/nand_flash.h
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2008 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+#ifndef _NAND_FLASH_H_
+#define _NAND_FLASH_H_
+
+#include <common.h>
+
+unsigned long nand_flash_init(void);
+void nand_flash_print_info(flash_info_t *info);
+int nand_flash_erase(flash_info_t *info, int s_first, int s_last);
+int nand_write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt);
+#ifdef CFG_FLASH_PROTECTION
+int nand_flash_real_protect(flash_info_t *info, long sector, int prot);
+#endif
+
+#endif /*_NAND_FLASH_H_*/
diff --git a/board/wmt/flash/nor_flash_16bit.c b/board/wmt/flash/nor_flash_16bit.c
new file mode 100755
index 0000000..25c7604
--- /dev/null
+++ b/board/wmt/flash/nor_flash_16bit.c
@@ -0,0 +1,1225 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2008 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+
+#include <common.h>
+#include <linux/byteorder/swab.h>
+#include <mpc8xx.h>
+#include "nor_flash_16bit.h"
+
+#define CONFIG_EON_FLASH 1
+#define NOR_FLASH_TYPE 2
+#define SPI_FLASH_TYPE 0
+
+/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
+ * has nothing to do with the flash chip being 8-bit or 16-bit.
+ */
+#define CONFIG_FLASH_16BIT 1
+#ifdef CONFIG_FLASH_8BIT
+ typedef unsigned char FLASH_PORT_WIDTH;
+ typedef volatile unsigned char FLASH_PORT_WIDTHV;
+ #define FLASH_ID_MASK 0xFF
+#else
+#ifdef CONFIG_FLASH_16BIT
+ typedef unsigned short FLASH_PORT_WIDTH;
+ typedef volatile unsigned short FLASH_PORT_WIDTHV;
+ #define SWAP(x) __swab16(x)
+ #define FLASH_ID_MASK 0xFFFF
+#else
+ typedef unsigned long FLASH_PORT_WIDTH;
+ typedef volatile unsigned long FLASH_PORT_WIDTHV;
+ #define SWAP(x) __swab32(x)
+ #define FLASH_ID_MASK 0xFFFFFFFF
+#endif
+#endif
+
+#define FPW FLASH_PORT_WIDTH
+#define FPWV FLASH_PORT_WIDTHV
+
+#define ORMASK(size) ((-size) & OR_AM_MSK)
+
+extern flash_info_t flash_info_nor[CFG_MAX_NOR_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong nor_flash_get_size(FPWV *addr, flash_info_t *info);
+static void flash_reset(flash_info_t *info);
+static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data);
+static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
+static int write_word_eon(flash_info_t *info, FPWV *dest, FPW data);
+static int write_word_mx(flash_info_t *info, FPWV *dest, FPW data);
+static void flash_get_offsets(ulong base, flash_info_t *info);
+#ifdef CFG_FLASH_PROTECTION
+static void flash_sync_real_protect(flash_info_t *info);
+#endif
+
+
+
+/*-----------------------------------------------------------------------
+ * nor_flash_init()
+ *
+ * sets up flash_info and returns size of FLASH (bytes)
+ */
+unsigned long nor_flash_16b_init(void)
+{
+ unsigned long size_b, size = 0;
+ int i;
+ unsigned int val = 0;
+ unsigned long flash_base[4];
+ val = *((volatile unsigned int *)(0xd8110100));
+ if (((val>>1)&0x3) == NOR_FLASH_TYPE) {
+ printf("nor boot only nor active\n");
+ flash_base[0] = CFG_NOR_FLASH_BASE_0;
+ flash_base[1] = CFG_NOR_FLASH_BASE_1;
+ flash_base[2] = CFG_NOR_FLASH_BASE_2;
+ flash_base[3] = CFG_NOR_FLASH_BASE_3;
+ #if (NOR_BOOT_ERASE_SIZE_KB == 128)
+ *(volatile unsigned int *)0xd8009460 = CFG_NOR_FLASH_BASE_0 | NOR_FLASH_32M;
+ *(volatile unsigned int *)0xd8009464 = CFG_NOR_FLASH_BASE_1 | NOR_FLASH_32M;
+ *(volatile unsigned int *)0xd8009468 = CFG_NOR_FLASH_BASE_2 | NOR_FLASH_32M;
+ *(volatile unsigned int *)0xd800946c = CFG_NOR_FLASH_BASE_3 | NOR_FLASH_32M;
+ #else
+ *(volatile unsigned int *)0xd8009460 = CFG_NOR_FLASH_BASE_0 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd8009464 = CFG_NOR_FLASH_BASE_1 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd8009468 = CFG_NOR_FLASH_BASE_2 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd800946c = CFG_NOR_FLASH_BASE_3 | NOR_FLASH_8M;
+ #endif
+ /*Configure the NOR Flash clock setting*/
+ *((volatile unsigned int *)(0xd8009408)) &= 0xffffff07;
+ *((volatile unsigned int *)(0xd8009408)) |= (0x1F<<3);//1F
+ *((volatile unsigned int *)(0xd8009418)) &= 0xffffff07;
+ *((volatile unsigned int *)(0xd8009418)) |= (0x1F<<3);
+ *((volatile unsigned int *)(0xd8009428)) &= 0xffffff07;
+ *((volatile unsigned int *)(0xd8009428)) |= (0x1F<<3);
+ *((volatile unsigned int *)(0xd8009438)) &= 0xffffff07;
+ *((volatile unsigned int *)(0xd8009438)) |= (0x1F<<3);
+ } else if (((val>>1)&0x3) == SPI_FLASH_TYPE) {
+ printf("spi boot, nor NOT active\n");
+ /*flash_base[0] = SPI_BOOT_FLASH_BASE_0;
+ flash_base[1] = SPI_BOOT_FLASH_BASE_1;
+ flash_base[2] = SPI_BOOT_FLASH_BASE_2;
+ flash_base[3] = SPI_BOOT_FLASH_BASE_3;
+ *(volatile unsigned int *)0xd8009460 = SPI_BOOT_FLASH_BASE_0 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd8009464 = SPI_BOOT_FLASH_BASE_1 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd8009468 = SPI_BOOT_FLASH_BASE_2 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd800946c = SPI_BOOT_FLASH_BASE_3 | NOR_FLASH_8M;*/
+ }
+
+ /* Init: no FLASHes known */
+ for (i = 0; i < CFG_MAX_NOR_FLASH_BANKS; ++i) {
+ flash_info_nor[i].flash_id = FLASH_UNKNOWN;
+
+ size_b = nor_flash_get_size((FPWV *)(flash_base[i]), &flash_info_nor[i]);
+ flash_info_nor[i].size = size_b;
+ size += size_b;
+
+ if (flash_info_nor[i].flash_id == FLASH_UNKNOWN)
+ printf("## Unknown FLASH on Bank %d - Size = 0x%08lx\n", i, size_b);
+
+ /* Do this again (was done already in flast_get_size), just
+ * in case we move it when remap the FLASH.
+ */
+ /* flash_get_offsets (flash_base[i], &flash_info_nor[i]); */
+ }
+#ifdef CFG_FLASH_PROTECTION
+ /* read the hardware protection status (if any) into the
+ * protection array in flash_info.
+ */
+ flash_sync_real_protect(&flash_info_nor[0]);
+#endif
+
+#if CFG_MONITOR_BASE >= CFG_NOR_FLASH_BASE_3
+ /* monitor protection ON by default */
+ flash_protect(
+ FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info_nor[3]
+ );
+#endif
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_reset(flash_info_t *info)
+{
+ FPWV *base = (FPWV *)(info->start[0]);
+
+ /* Put FLASH back in read mode */
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
+ *base = (FPW)0x00FF00FF; /* Intel Read Mode */
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
+ *base = (FPW)0x00F000F0; /* AMD Read Mode */
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_EON)
+ *base = (FPW)0x00F000F0; /* EON Read Mode */
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX)
+ *base = (FPW)0x00F000F0; /* MX Read Mode */
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_NUM)
+ *base = (FPW)0x00F000F0;
+ else
+ *base = (FPW)0x00F000F0;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets(ulong base, flash_info_t *info)
+{
+ int i;
+
+ /* set up sector start address table */
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
+ && (info->flash_id & FLASH_BTYPE)) {
+ int bootsect_size; /* number of bytes/boot sector */
+ int sect_size; /* number of bytes/regular sector */
+
+ bootsect_size = 0x00002000 * (sizeof(FPW)/2);
+ sect_size = 0x00010000 * (sizeof(FPW)/2);
+
+ /* set sector offsets for bottom boot block type */
+ for (i = 0; i < 8; ++i)
+ info->start[i] = base + (i * bootsect_size);
+
+ for (i = 8; i < info->sector_count; i++)
+ info->start[i] = base + ((i - 7) * sect_size);
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
+
+ int sect_size; /* number of bytes/sector */
+
+ sect_size = 0x00010000 * (sizeof(FPW)/2);
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * sect_size);
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_EON
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_EON29LV640U) {
+
+ int sect_size; /* number of bytes/sector */
+#ifdef CONFIG_FLASH_8BIT
+ sect_size = 0x00008000;
+#else
+ sect_size = 0x00010000 * (sizeof(FPW)/2);
+#endif
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ /* info->start[i] = base + (i * sect_size); */
+ if (i < 127) {
+ info->start[i] = base + (i * 0x10000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 127 * 0x10000 + ((i-127) * 0x2000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_MX29LV640T) {
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 127) {
+ info->start[i] = base + (i * 0x10000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 127 * 0x10000 + ((i-127) * 0x2000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_EON
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_EON29LV640B) {
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 8) {
+ info->start[i] = base + (i * 0x2000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 8 * 0x2000 + ((i-8) * 0x10000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_MX29LV640B) {
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 8) {
+ info->start[i] = base + (i * 0x2000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 8 * 0x2000 + ((i-8) * 0x10000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_MX29GL256E) {
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ info->start[i] = base + (i * 0x20000);
+ info->protect[i] = 0;
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_EON
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_EON29LV640H) {
+ int sect_size; /* number of bytes/sector */
+#ifdef CONFIG_FLASH_8BIT
+ sect_size = 0x00008000;
+#else
+ sect_size = 0x00010000 * (sizeof(FPW)/2);
+#endif
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x10000);
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_NUM
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_NUM29W640GT) {
+
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 127) {
+ info->start[i] = base + (i * 0x10000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 127 * 0x10000 + ((i-127) * 0x2000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_NUM
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_NUM29W640GB) {
+
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 8) {
+ info->start[i] = base + (i * 0x2000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 8 * 0x2000 + ((i-8) * 0x10000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_NUM
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_NUM29W640GHL) {
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x10000);
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_NUM
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_NUM29W128GHL) {
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * 0x20000);
+ } else
+ printf("set flash sector fail\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+void nor_flash_16b_print_info(flash_info_t *info)
+{
+ int i;
+ uchar *boottype;
+ uchar *bootletter;
+ char *fmt;
+ uchar botbootletter[] = "B";
+ uchar topbootletter[] = "T";
+ uchar botboottype[] = "bottom boot sector";
+ uchar topboottype[] = "top boot sector";
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD:
+ printf("AMD ");
+ break;
+ case FLASH_MAN_EON:
+ printf("EON ");
+ case FLASH_MAN_MX:
+ printf("MX ");
+ break;
+ case FLASH_MAN_BM:
+ printf("BRIGHT MICRO ");
+ break;
+ case FLASH_MAN_FUJ:
+ printf("FUJITSU ");
+ break;
+ case FLASH_MAN_SST:
+ printf("SST ");
+ break;
+ case FLASH_MAN_STM:
+ printf("STM ");
+ break;
+ case FLASH_MAN_INTEL:
+ printf("INTEL ");
+ break;
+ case FLASH_MAN_NUM:
+ printf("NUM ");
+ break;
+ default:
+ printf("Unknown Vendor ");
+ break;
+ }
+
+ /* check for top or bottom boot, if it applies */
+ if (info->flash_id & FLASH_BTYPE) {
+ boottype = botboottype;
+ bootletter = botbootletter;
+ } else {
+ boottype = topboottype;
+ bootletter = topbootletter;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM640U:
+ fmt = "29LV641D (64 Mbit, uniform sectors)\n";
+ break;
+ case FLASH_EON29LV640H:
+#ifdef CONFIG_FLASH_8BIT
+ fmt = "29LV640H (32 Mbit, uniform sectors)\n";
+#else
+ fmt = "29LV640H (64 Mbit, uniform sectors)\n";
+#endif
+ break;
+ case FLASH_EON29LV640U:
+ case FLASH_EON29LV640B:
+#ifdef CONFIG_FLASH_8BIT
+ fmt = "29LV641D (32 Mbit, uniform sectors)\n";
+#else
+ fmt = "29LV641D (64 Mbit, uniform sectors)\n";
+#endif
+ break;
+ case FLASH_28F800C3B:
+ case FLASH_28F800C3T:
+ fmt = "28F800C3%s (8 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL800B:
+ case FLASH_INTEL800T:
+ fmt = "28F800B3%s (8 Mbit, %s)\n";
+ break;
+ case FLASH_28F160C3B:
+ case FLASH_28F160C3T:
+ fmt = "28F160C3%s (16 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL160B:
+ case FLASH_INTEL160T:
+ fmt = "28F160B3%s (16 Mbit, %s)\n";
+ break;
+ case FLASH_28F320C3B:
+ case FLASH_28F320C3T:
+ fmt = "28F320C3%s (32 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL320B:
+ case FLASH_INTEL320T:
+ fmt = "28F320B3%s (32 Mbit, %s)\n";
+ break;
+ case FLASH_28F640C3B:
+ case FLASH_28F640C3T:
+ fmt = "28F640C3%s (64 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL640B:
+ case FLASH_INTEL640T:
+ fmt = "28F640B3%s (64 Mbit, %s)\n";
+ break;
+ case FLASH_MX29LV640B:
+ case FLASH_MX29LV640T:
+ fmt = "29LV640D (64 Mbit, uniform sectors)\n";
+ break;
+ case FLASH_MX29GL256E:
+ fmt = "29GL256E (256 Mbit, uniform sectors)\n";
+ break;
+ case FLASH_NUM29W640GT:
+ case FLASH_NUM29W640GB:
+ case FLASH_NUM29W640GHL:
+ fmt = "29W640G (64 Mbit, uniform sectors)\n";
+ break;
+ case FLASH_NUM29W128GHL:
+ fmt = "29W128GL (128 Mbit, uniform sectors)\n";
+ break;
+ default:
+ fmt = "Unknown Chip Type\n";
+ break;
+ }
+
+ printf(fmt, bootletter, boottype);
+
+ printf(" Size: %ld MB in %d Sectors\n",
+ info->size >> 20,
+ info->sector_count);
+
+ printf(" Sector Start Addresses:");
+
+ for (i = 0; i < info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ printf("\n ");
+
+ printf(" %08lX%s", info->start[i],
+ info->protect[i] ? " (RO)" : " ");
+ }
+
+ printf("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong nor_flash_get_size(FPWV *addr, flash_info_t *info)
+{
+ /* Write auto select command: read Manufacturer ID */
+ int DevId, DevId1;
+ /* Write auto select command sequence and test FLASH answer */
+#ifdef CONFIG_EON_FLASH
+ addr[0x0555] = (FPW)0x00AA00AA; /* for EON, Intel ignores this */
+ addr[0x02AA] = (FPW)0x00550055; /* for EON, Intel ignores this */
+#endif
+ addr[0x0555] = (FPW)0x00900090; /* selects Intel or AMD */
+
+ /* The manufacturer codes are only 1 byte, so just use 1 byte.
+ * This works for any bus width and any FLASH device width.
+ */
+ DevId = NOR_IDALL((addr[0]&0xFFFF), (addr[1]&0xFFFF));
+ DevId1 = NOR_IDALL((addr[14]&0xFFFF), (addr[15]&0xFFFF));
+ printf("DevId = 0x%x\n", DevId);
+ printf("DevId1 = 0x%x\n", DevId1);
+ switch (addr[0] & 0xff) {
+
+ case (uchar)AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+
+ case (uchar)INTEL_MANUFACT:
+ info->flash_id = FLASH_MAN_INTEL;
+ break;
+
+ case (uchar)EON_MANUFACT:
+ info->flash_id = FLASH_MAN_EON;
+ break;
+ case (uchar)MX_MANUFACT:
+ info->flash_id = FLASH_MAN_MX;
+ break;
+ case (uchar)NUM_MANUFACT:
+ info->flash_id = FLASH_MAN_NUM;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ break;
+ }
+
+ /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
+ if (info->flash_id != FLASH_UNKNOWN)
+ switch (addr[1]) {
+ /* case (FPW)AMD_ID_LV640U: */ /* 29LV640 and 29LV641 have same ID */
+ /* info->flash_id += FLASH_AM640U; */
+ /* info->sector_count = 128; */
+ /* info->size = 0x00800000 * (sizeof(FPW)/2); */
+ /* break; */ /* => 8 or 16 MB */
+
+ case (FPW)EON_ID_LV640U:
+ /* 29LV640 and 29LV641 have same ID */
+ info->flash_id += FLASH_EON29LV640U;
+ info->sector_count = 128;
+#ifdef CONFIG_FLASH_8BIT
+ info->size = 0x00400000;
+#else
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+#endif
+
+ break;
+ case (FPW)EON_ID_LV640B:
+ /* 29LV640 and 29LV641 have same ID */
+ if(info->flash_id == FLASH_MAN_MX)
+ info->flash_id += FLASH_MX29LV640B;
+ else
+ info->flash_id += FLASH_EON29LV640B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break;
+ case (FPW)EON_ID_LV640H:
+ if(info->flash_id == FLASH_MAN_NUM) {
+ info->sector_count = 128;
+ info->size = 0x0800000;
+ switch (DevId1) {
+ case NX_M29W640GT:
+ info->flash_id += FLASH_NUM29W640GT;
+ info->sector_count = 135;
+ break;
+ case NX_M29W640GB:
+ info->flash_id += FLASH_NUM29W640GB;
+ info->sector_count = 135;
+ break;
+ case NX_M29W640GH:
+ case NX_M29W640GL:
+ info->flash_id += FLASH_NUM29W640GHL;
+ break;
+ case NX_M29W128GH:
+ case NX_M29W128GL:
+ info->flash_id += FLASH_NUM29W128GHL;
+ info->size = 0x01000000;
+ break;
+ default:
+ info->flash_id += FLASH_NUM29W640GHL;
+ break;
+ }
+ } else if(info->flash_id == FLASH_MAN_EON) {
+ info->flash_id += FLASH_EON29LV640H;
+ info->sector_count = 128;
+ info->size = 0x00800000;
+ //info->size = 0x00800000 * (sizeof(FPW)/2);
+ break;
+ } else if(info->flash_id == FLASH_MAN_MX) {
+ info->flash_id += FLASH_MX29GL256E;
+ info->sector_count = 256;
+ info->size = 0x02000000;
+ }
+ break;
+ case (FPW)EON_ID_LV640T:
+ /* 29LV640 and 29LV641 have same ID */
+ if(info->flash_id == FLASH_MAN_MX)
+ info->flash_id += FLASH_MX29LV640T;
+ else
+ info->flash_id += FLASH_EON29LV640U;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+
+ break;
+
+ case (FPW)INTEL_ID_28F800C3B:
+ info->flash_id += FLASH_28F800C3B;
+ info->sector_count = 23;
+ info->size = 0x00100000 * (sizeof(FPW)/2);
+ break; /* => 1 or 2 MB */
+
+ case (FPW)INTEL_ID_28F800B3B:
+ info->flash_id += FLASH_INTEL800B;
+ info->sector_count = 23;
+ info->size = 0x00100000 * (sizeof(FPW)/2);
+ break; /* => 1 or 2 MB */
+
+ case (FPW)INTEL_ID_28F160C3B:
+ info->flash_id += FLASH_28F160C3B;
+ info->sector_count = 39;
+ info->size = 0x00200000 * (sizeof(FPW)/2);
+ break; /* => 2 or 4 MB */
+
+ case (FPW)INTEL_ID_28F160B3B:
+ info->flash_id += FLASH_INTEL160B;
+ info->sector_count = 39;
+ info->size = 0x00200000 * (sizeof(FPW)/2);
+ break; /* => 2 or 4 MB */
+
+ case (FPW)INTEL_ID_28F320C3B:
+ info->flash_id += FLASH_28F320C3B;
+ info->sector_count = 71;
+ info->size = 0x00400000 * (sizeof(FPW)/2);
+ break; /* => 4 or 8 MB */
+
+ case (FPW)INTEL_ID_28F320B3B:
+ info->flash_id += FLASH_INTEL320B;
+ info->sector_count = 71;
+ info->size = 0x00400000 * (sizeof(FPW)/2);
+ break; /* => 4 or 8 MB */
+
+ case (FPW)INTEL_ID_28F640C3B:
+ info->flash_id += FLASH_28F640C3B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break; /* => 8 or 16 MB */
+
+ case (FPW)INTEL_ID_28F640B3B:
+ info->flash_id += FLASH_INTEL640B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break; /* => 8 or 16 MB */
+
+ /*case (FPW)MX_ID_LV640B:
+ info->flash_id += FLASH_MX29LV640B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break;
+
+ case (FPW)MX_ID_LV640T:
+ info->flash_id += FLASH_MX29LV640B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break;*/
+
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return 0; /* => no or unknown flash */
+ }
+
+ flash_get_offsets((ulong)addr, info);
+
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+
+ return info->size;
+}
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+
+static void flash_sync_real_protect(flash_info_t *info)
+{
+ FPWV *addr = (FPWV *)(info->start[0]);
+ FPWV *sect;
+ int i;
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_28F800C3B:
+ case FLASH_28F800C3T:
+ case FLASH_28F160C3B:
+ case FLASH_28F160C3T:
+ case FLASH_28F320C3B:
+ case FLASH_28F320C3T:
+ case FLASH_28F640C3B:
+ case FLASH_28F640C3T:
+ /* check for protected sectors */
+ *addr = (FPW)0x00900090;
+ for (i = 0; i < info->sector_count; i++) {
+ /* read sector protection at sector address, (A7 .. A0) = 0x02.
+ * D0 = 1 for each device if protected.
+ * If at least one device is protected the sector is marked
+ * protected, but mixed protected and unprotected devices
+ * within a sector should never happen.
+ */
+ sect = (FPWV *)(info->start[i]);
+ info->protect[i] = (sect[2] & (FPW)(0x00010001)) ? 1 : 0;
+ }
+
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+ break;
+ case FLASH_EON29LV640H:
+ case FLASH_EON29LV640U:
+ case FLASH_EON29LV640B:
+ for (i = 0; i < info->sector_count; i++) {
+ /* check for protected sectors */
+ sect = (FPWV *)(info->start[i]);
+ sect[0x0555] = (FPW)0x00AA00AA;
+ sect[0x02AA] = (FPW)0x00550055;
+ sect[0x0555] = (FPW)0x00900090;
+
+ info->protect[i] = (sect[2] & (FPW)(0x00010001)) ? 1 : 0;
+ }
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+ break;
+ case FLASH_MX29LV640T:
+ case FLASH_MX29LV640B:
+ case FLASH_NUM29W640GT:
+ case FLASH_NUM29W640GB:
+ case FLASH_NUM29W640GHL:
+ case FLASH_NUM29W128GHL:
+ for (i = 0; i < info->sector_count; i++) {
+ /* check for protected sectors */
+ sect = (FPWV *)(info->start[i]);
+ sect[0x0555] = (FPW)0x00AA00AA;
+ sect[0x02AA] = (FPW)0x00550055;
+ sect[0x0555] = (FPW)0x00900090;
+
+ info->protect[i] = (sect[2] & (FPW)(0x00010001)) ? 1 : 0;
+ }
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+ break;
+ case FLASH_AM640U:
+ default:
+ /* no hardware protect that we support */
+ break;
+ }
+}
+#endif
+
+/*-----------------------------------------------------------------------
+ */
+
+int nor_flash_16b_erase(flash_info_t *info, int s_first, int s_last)
+{
+ FPWV *addr;
+ int flag, prot, sect;
+ int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
+ ulong start, now, last;
+ int rcode = 0;
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN)
+ printf("- missing\n");
+ else
+ printf("- no sectors to erase\n");
+ return 1;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_INTEL800B:
+ case FLASH_INTEL160B:
+ case FLASH_INTEL320B:
+ case FLASH_INTEL640B:
+ case FLASH_28F800C3B:
+ case FLASH_28F160C3B:
+ case FLASH_28F320C3B:
+ case FLASH_28F640C3B:
+ case FLASH_AM640U:
+ case FLASH_EON29LV640H:
+ case FLASH_EON29LV640U:
+ case FLASH_EON29LV640B:
+ case FLASH_MX29LV640B:
+ case FLASH_MX29LV640T:
+ case FLASH_MX29GL256E:
+ case FLASH_NUM29W640GT:
+ case FLASH_NUM29W640GB:
+ case FLASH_NUM29W640GHL:
+ case FLASH_NUM29W128GHL:
+ break;
+ case FLASH_UNKNOWN:
+ default:
+ printf("Can't erase unknown flash type %08lx - aborted\n",
+ info->flash_id);
+ 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
+ printf("\n");
+
+ /* start = get_timer(0); */
+ /* last = start; */
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
+
+ if (info->protect[sect] != 0) /* protected, skip it */
+ continue;
+ start = get_timer(0);
+ last = start;
+
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr = (FPWV *)(info->start[sect]);
+ if (intel) {
+ *addr = (FPW)0x00500050; /* clear status register */
+ *addr = (FPW)0x00200020; /* erase setup */
+ *addr = (FPW)0x00D000D0; /* erase confirm */
+ } else {
+ /* must be AMD style if not Intel */
+ FPWV *base; /* first address in bank */
+ base = (FPWV *)(info->start[0]);
+ base[0x0555] = (FPW)0x00AA00AA; /* unlock */
+ base[0x02AA] = (FPW)0x00550055; /* unlock */
+ base[0x0555] = (FPW)0x00800080; /* erase mode */
+ base[0x0555] = (FPW)0x00AA00AA; /* unlock */
+ base[0x02AA] = (FPW)0x00550055; /* unlock */
+ *addr = (FPW)0x00300030; /* erase sector */
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* wait at least 50us for AMD, 80us for Intel.
+ * Let's wait 1 ms.
+ */
+ udelay(1000);
+
+ while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
+ now = get_timer(start);
+ if (now > CFG_FLASH_ERASE_TOUT) {
+ printf("Timeout\n");
+
+ if (intel) {
+ /* suspend erase */
+ *addr = (FPW)0x00B000B0;
+ }
+
+ flash_reset(info); /* reset to read mode */
+ rcode = 1; /* failed */
+ break;
+ }
+
+ /* show that we're waiting */
+ if ((now - last) > 1000) { /* every second */
+ putc('.');
+ last = now;
+ }
+ }
+
+ flash_reset(info); /* reset to read mode */
+ }
+
+ printf(" done\n");
+ return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int nor_flash_16b_write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
+ int bytes; /* number of bytes to program in current word */
+ int left; /* number of bytes left to program */
+ int i, res;
+
+ for (left = cnt, res = 0;
+ left > 0 && res == 0;
+ addr += sizeof(data), left -= sizeof(data) - bytes) {
+
+ bytes = addr & (sizeof(data) - 1);
+ addr &= ~(sizeof(data) - 1);
+
+ /* combine source and destination data so can program
+ * an entire word of 16 or 32 bits
+ */
+ for (i = 0; i < sizeof(data); i++) {
+ data <<= 8;
+ if (i < bytes || i - bytes >= left)
+ data += *((uchar *)addr + i);
+ else
+ data += *src++;
+ }
+
+ /* write one word to the flash */
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD:
+ res = write_word_amd(info, (FPWV *)addr, data);
+ case FLASH_MAN_EON:
+ case FLASH_MAN_NUM:
+ res = write_word_eon(info, (FPWV *)addr, SWAP(data));
+ break;
+ case FLASH_MAN_MX:
+ res = write_word_mx(info, (FPWV *)addr, SWAP(data));
+ break;
+ case FLASH_MAN_INTEL:
+ res = write_word_intel(info, (FPWV *)addr, data);
+ break;
+ default:
+ /* unknown flash type, error! */
+ printf("missing or unknown FLASH type\n");
+ res = 1; /* not really a timeout, but gives error */
+ break;
+ }
+ }
+
+ return res;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for AMD FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+ FPWV *base; /* first address in flash bank */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data)
+ return 2;
+
+ base = (FPWV *)(info->start[0]);
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ base[0x0555] = (FPW)0x00AA00AA; /* unlock */
+ base[0x02AA] = (FPW)0x00550055; /* unlock */
+ base[0x0555] = (FPW)0x00A000A0; /* selects program mode */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ /* data polling for D7 */
+ while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00F000F0; /* reset bank */
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for EON FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_eon(flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+ FPWV *base; /* first address in flash bank */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data)
+ return 2;
+
+ base = (FPWV *)(info->start[0]);
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ base[0x0555] = (FPW)0x00AA00AA; /* unlock */
+ base[0x02AA] = (FPW)0x00550055; /* unlock */
+ base[0x0555] = (FPW)0x00A000A0; /* selects program mode */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ /* data polling for D7 */
+ while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00F000F0; /* reset bank */
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for MX FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_mx(flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+ FPWV *base; /* first address in flash bank */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data)
+ return 2;
+
+ base = (FPWV *)(info->start[0]);
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ base[0x0555] = (FPW)0x00AA00AA; /* unlock */
+ base[0x02AA] = (FPW)0x00550055; /* unlock */
+ base[0x0555] = (FPW)0x00A000A0; /* selects program mode */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ /* data polling for D7 */
+ while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00F000F0; /* reset bank */
+ res = 1;
+ }
+ }
+
+ return res;
+}
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for Intel FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data)
+ return 2;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ *dest = (FPW)0x00500050; /* clear status register */
+ *dest = (FPW)0x00FF00FF; /* make sure in read mode */
+ *dest = (FPW)0x00400040; /* program setup */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00B000B0; /* Suspend program */
+ res = 1;
+ }
+ }
+
+ if (res == 0 && (*dest & (FPW)0x00100010))
+ res = 1; /* write failed, time out error is close enough */
+
+ *dest = (FPW)0x00500050; /* clear status register */
+ *dest = (FPW)0x00FF00FF; /* make sure in read mode */
+
+ return res;
+}
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+int nor_flash_16b_real_protect(flash_info_t *info, long sector, int prot)
+{
+ int rcode = 0; /* assume success */
+ FPWV *addr; /* address of sector */
+ FPW value;
+
+ addr = (FPWV *) (info->start[sector]);
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_28F800C3B:
+ case FLASH_28F800C3T:
+ case FLASH_28F160C3B:
+ case FLASH_28F160C3T:
+ case FLASH_28F320C3B:
+ case FLASH_28F320C3T:
+ case FLASH_28F640C3B:
+ case FLASH_28F640C3T:
+ flash_reset(info); /* make sure in read mode */
+ *addr = (FPW) 0x00600060L; /* lock command setup */
+ if (prot)
+ *addr = (FPW) 0x00010001L; /* lock sector */
+ else
+ *addr = (FPW) 0x00D000D0L; /* unlock sector */
+ flash_reset(info); /* reset to read mode */
+
+ /* now see if it really is locked/unlocked as requested */
+ *addr = (FPW) 0x00900090;
+ /* read sector protection at sector address, (A7 .. A0) = 0x02.
+ * D0 = 1 for each device if protected.
+ * If at least one device is protected the sector is marked
+ * protected, but return failure. Mixed protected and
+ * unprotected devices within a sector should never happen.
+ */
+ value = addr[2] & (FPW) 0x00010001;
+ if (value == 0)
+ info->protect[sector] = 0;
+ else if (value == (FPW) 0x00010001)
+ info->protect[sector] = 1;
+ else {
+ /* error, mixed protected and unprotected */
+ rcode = 1;
+ info->protect[sector] = 1;
+ }
+ if (info->protect[sector] != prot)
+ rcode = 1; /* failed to protect/unprotect as requested */
+
+ /* reload all protection bits from hardware for now */
+ flash_sync_real_protect(info);
+ break;
+
+ case FLASH_EON29LV640H:
+ case FLASH_EON29LV640U:
+ case FLASH_EON29LV640B:
+ case FLASH_MX29LV640B:
+ case FLASH_MX29LV640T:
+ case FLASH_MX29GL256E:
+ case FLASH_NUM29W640GT:
+ case FLASH_NUM29W640GB:
+ case FLASH_NUM29W640GHL:
+ case FLASH_NUM29W128GHL:
+ if (prot == 0)
+ info->protect[sector] = 0;
+ else if (prot == 1)
+ info->protect[sector] = 1;
+ else {
+ /* error, mixed protected and unprotected */
+ rcode = 1;
+ info->protect[sector] = 1;
+ }
+ if (info->protect[sector] != prot)
+ rcode = 1; /* failed to protect/unprotect as requested */
+
+ break;
+
+ case FLASH_AM640U:
+ default:
+ /* no hardware protect that we support */
+ info->protect[sector] = prot;
+ break;
+ }
+
+ return rcode;
+}
+#endif
diff --git a/board/wmt/flash/nor_flash_16bit.h b/board/wmt/flash/nor_flash_16bit.h
new file mode 100755
index 0000000..15259ef
--- /dev/null
+++ b/board/wmt/flash/nor_flash_16bit.h
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2008 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+
+#ifndef _NOR_FLASH_16BIT_H_
+#define _NOR_FLASH_16BIT_H_
+
+#include <common.h>
+#include <mpc8xx.h>
+
+unsigned long nor_flash_16b_init(void);
+void nor_flash_16b_print_info(flash_info_t *info);
+int nor_flash_16b_erase(flash_info_t *info, int s_first, int s_last);
+int nor_flash_16b_write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt);
+#ifdef CFG_FLASH_PROTECTION
+int nor_flash_16b_real_protect(flash_info_t *info, long sector, int prot);
+#endif
+
+#endif /*_NOR_FLASH_16BIT_H_*/
diff --git a/board/wmt/flash/nor_flash_8bit.c b/board/wmt/flash/nor_flash_8bit.c
new file mode 100755
index 0000000..b24b2af
--- /dev/null
+++ b/board/wmt/flash/nor_flash_8bit.c
@@ -0,0 +1,1067 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2008 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+
+#include <common.h>
+#include <linux/byteorder/swab.h>
+#include <mpc8xx.h>
+#include "nor_flash_8bit.h"
+
+#define CONFIG_EON_FLASH 1
+#define NOR_FLASH_TYPE 2
+#define SPI_FLASH_TYPE 0
+
+/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
+ * has nothing to do with the flash chip being 8-bit or 16-bit.
+ */
+#define CONFIG_FLASH_8BIT 1
+#ifdef CONFIG_FLASH_8BIT
+ typedef unsigned char FLASH_PORT_WIDTH;
+ typedef volatile unsigned char FLASH_PORT_WIDTHV;
+ #define FLASH_ID_MASK 0xFF
+#else
+#ifdef CONFIG_FLASH_16BIT
+ typedef unsigned short FLASH_PORT_WIDTH;
+ typedef volatile unsigned short FLASH_PORT_WIDTHV;
+ #define SWAP(x) __swab16(x)
+ #define FLASH_ID_MASK 0xFFFF
+#else
+ typedef unsigned long FLASH_PORT_WIDTH;
+ typedef volatile unsigned long FLASH_PORT_WIDTHV;
+ #define SWAP(x) __swab32(x)
+ #define FLASH_ID_MASK 0xFFFFFFFF
+#endif
+#endif
+
+#define FPW FLASH_PORT_WIDTH
+#define FPWV FLASH_PORT_WIDTHV
+
+#define ORMASK(size) ((-size) & OR_AM_MSK)
+
+extern flash_info_t flash_info_nor[CFG_MAX_NOR_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong nor_flash_get_size(FPWV *addr, flash_info_t *info);
+static void flash_reset(flash_info_t *info);
+static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data);
+static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
+static int write_word_eon(flash_info_t *info, FPWV *dest, FPW data);
+static int write_word_mx(flash_info_t *info, FPWV *dest, FPW data);
+static void flash_get_offsets(ulong base, flash_info_t *info);
+#ifdef CFG_FLASH_PROTECTION
+static void flash_sync_real_protect(flash_info_t *info);
+#endif
+
+
+
+/*-----------------------------------------------------------------------
+ * nor_flash_init()
+ *
+ * sets up flash_info and returns size of FLASH (bytes)
+ */
+unsigned long nor_flash_8b_init(void)
+{
+ unsigned long size_b, size = 0;
+ int i;
+ unsigned int val = 0;
+ unsigned long flash_base[4];
+ val = *((volatile unsigned int *)(0xd8110100));
+ if (((val>>1)&0x3) == NOR_FLASH_TYPE) {
+ flash_base[0] = CFG_NOR_FLASH_BASE_0;
+ flash_base[1] = CFG_NOR_FLASH_BASE_1;
+ flash_base[2] = CFG_NOR_FLASH_BASE_2;
+ flash_base[3] = CFG_NOR_FLASH_BASE_3;
+ *(volatile unsigned int *)0xd8009460 = CFG_NOR_FLASH_BASE_0 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd8009464 = CFG_NOR_FLASH_BASE_1 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd8009468 = CFG_NOR_FLASH_BASE_2 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd800946c = CFG_NOR_FLASH_BASE_3 | NOR_FLASH_8M;
+ } else if (((val>>1)&0x3) == SPI_FLASH_TYPE) {
+ /*flash_base[0] = SPI_BOOT_FLASH_BASE_0;
+ flash_base[1] = SPI_BOOT_FLASH_BASE_1;
+ flash_base[2] = SPI_BOOT_FLASH_BASE_2;
+ flash_base[3] = SPI_BOOT_FLASH_BASE_3;
+ *(volatile unsigned int *)0xd8009460 = SPI_BOOT_FLASH_BASE_0 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd8009464 = SPI_BOOT_FLASH_BASE_1 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd8009468 = SPI_BOOT_FLASH_BASE_2 | NOR_FLASH_8M;
+ *(volatile unsigned int *)0xd800946c = SPI_BOOT_FLASH_BASE_3 | NOR_FLASH_8M;*/
+ }
+
+ /* Init: no FLASHes known */
+ for (i = 0; i < CFG_MAX_NOR_FLASH_BANKS; ++i) {
+ flash_info_nor[i].flash_id = FLASH_UNKNOWN;
+
+ size_b = nor_flash_get_size((FPWV *)(flash_base[i]), &flash_info_nor[i]);
+ flash_info_nor[i].size = size_b;
+ size += size_b;
+
+ if (flash_info_nor[i].flash_id == FLASH_UNKNOWN)
+ printf("## Unknown FLASH on Bank %d - Size = 0x%08lx\n", i, size_b);
+
+ /* Do this again (was done already in flast_get_size), just
+ * in case we move it when remap the FLASH.
+ */
+ /* flash_get_offsets (flash_base[i], &flash_info_nor[i]); */
+ }
+#ifdef CFG_FLASH_PROTECTION
+ /* read the hardware protection status (if any) into the
+ * protection array in flash_info.
+ */
+ flash_sync_real_protect(&flash_info_nor[0]);
+#endif
+
+#if CFG_MONITOR_BASE >= CFG_NOR_FLASH_BASE_3
+ /* monitor protection ON by default */
+ flash_protect(
+ FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info_nor[3]
+ );
+#endif
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_reset(flash_info_t *info)
+{
+ FPWV *base = (FPWV *)(info->start[0]);
+
+ /* Put FLASH back in read mode */
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
+ *base = (FPW)0x00FF00FF; /* Intel Read Mode */
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
+ *base = (FPW)0x00F000F0; /* AMD Read Mode */
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_EON)
+ *base = (FPW)0x00F000F0; /* EON Read Mode */
+ else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX)
+ *base = (FPW)0x00F000F0; /* MX Read Mode */
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets(ulong base, flash_info_t *info)
+{
+ int i;
+
+ /* set up sector start address table */
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
+ && (info->flash_id & FLASH_BTYPE)) {
+ int bootsect_size; /* number of bytes/boot sector */
+ int sect_size; /* number of bytes/regular sector */
+
+ bootsect_size = 0x00002000 * (sizeof(FPW)/2);
+ sect_size = 0x00010000 * (sizeof(FPW)/2);
+
+ /* set sector offsets for bottom boot block type */
+ for (i = 0; i < 8; ++i)
+ info->start[i] = base + (i * bootsect_size);
+
+ for (i = 8; i < info->sector_count; i++)
+ info->start[i] = base + ((i - 7) * sect_size);
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
+
+ int sect_size; /* number of bytes/sector */
+
+ sect_size = 0x00010000 * (sizeof(FPW)/2);
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++)
+ info->start[i] = base + (i * sect_size);
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_EON
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_EON29LV640B) {
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 8) {
+ info->start[i] = base + (i * 0x2000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 8 * 0x2000 + ((i-8) * 0x10000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_MX29LV640B) {
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 8) {
+ info->start[i] = base + (i * 0x2000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 8 * 0x2000 + ((i-8) * 0x10000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_EON
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_EON29LV640U) {
+
+ int sect_size; /* number of bytes/sector */
+#ifdef CONFIG_FLASH_8BIT
+ sect_size = 0x00010000;
+#else
+ sect_size = 0x00008000 * (sizeof(FPW)/2);
+#endif
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 127) {
+ info->start[i] = base + (i * 0x10000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 127 * 0x10000 + ((i-127) * 0x2000);
+ info->protect[i] = 0;
+ }
+ }
+ } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX
+ && (info->flash_id & FLASH_TYPEMASK) == FLASH_MX29LV640T) {
+
+ /* set up sector start address table (uniform sector type) */
+ for (i = 0; i < info->sector_count; i++) {
+ if (i < 127) {
+ info->start[i] = base + (i * 0x10000);
+ info->protect[i] = 0;
+ } else {
+ info->start[i] = base + 127 * 0x10000 + ((i-127) * 0x2000);
+ info->protect[i] = 0;
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+void nor_flash_8b_print_info(flash_info_t *info)
+{
+ int i;
+ uchar *boottype;
+ uchar *bootletter;
+ char *fmt;
+ uchar botbootletter[] = "B";
+ uchar topbootletter[] = "T";
+ uchar botboottype[] = "bottom boot sector";
+ uchar topboottype[] = "top boot sector";
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD:
+ printf("AMD ");
+ break;
+ case FLASH_MAN_EON:
+ printf("EON ");
+ break;
+ case FLASH_MAN_MX:
+ printf("MX ");
+ break;
+ case FLASH_MAN_BM:
+ printf("BRIGHT MICRO ");
+ break;
+ case FLASH_MAN_FUJ:
+ printf("FUJITSU ");
+ break;
+ case FLASH_MAN_SST:
+ printf("SST ");
+ break;
+ case FLASH_MAN_STM:
+ printf("STM ");
+ break;
+ case FLASH_MAN_INTEL:
+ printf("INTEL ");
+ break;
+ default:
+ printf("Unknown Vendor ");
+ break;
+ }
+
+ /* check for top or bottom boot, if it applies */
+ if (info->flash_id & FLASH_BTYPE) {
+ boottype = botboottype;
+ bootletter = botbootletter;
+ } else {
+ boottype = topboottype;
+ bootletter = topbootletter;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_AM640U:
+ fmt = "29LV641D (64 Mbit, uniform sectors)\n";
+ break;
+ case FLASH_EON29LV640U:
+#ifdef CONFIG_FLASH_8BIT
+ fmt = "29LV641D (32 Mbit, uniform sectors)\n";
+#else
+ fmt = "29LV641D (32 Mbit, uniform sectors)\n";
+#endif
+ break;
+ case FLASH_28F800C3B:
+ case FLASH_28F800C3T:
+ fmt = "28F800C3%s (8 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL800B:
+ case FLASH_INTEL800T:
+ fmt = "28F800B3%s (8 Mbit, %s)\n";
+ break;
+ case FLASH_28F160C3B:
+ case FLASH_28F160C3T:
+ fmt = "28F160C3%s (16 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL160B:
+ case FLASH_INTEL160T:
+ fmt = "28F160B3%s (16 Mbit, %s)\n";
+ break;
+ case FLASH_28F320C3B:
+ case FLASH_28F320C3T:
+ fmt = "28F320C3%s (32 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL320B:
+ case FLASH_INTEL320T:
+ fmt = "28F320B3%s (32 Mbit, %s)\n";
+ break;
+ case FLASH_28F640C3B:
+ case FLASH_28F640C3T:
+ fmt = "28F640C3%s (64 Mbit, %s)\n";
+ break;
+ case FLASH_INTEL640B:
+ case FLASH_INTEL640T:
+ fmt = "28F640B3%s (64 Mbit, %s)\n";
+ break;
+ case FLASH_MX29LV640B:
+ case FLASH_MX29LV640T:
+ fmt = "29LV640D (64 Mbit, uniform sectors)\n";
+ break;
+ default:
+ fmt = "Unknown Chip Type\n";
+ break;
+ }
+
+ printf(fmt, bootletter, boottype);
+
+ printf(" Size: %ld MB in %d Sectors\n",
+ info->size >> 20,
+ info->sector_count);
+
+ printf(" Sector Start Addresses:");
+
+ for (i = 0; i < info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ printf("\n ");
+
+ printf(" %08lX%s", info->start[i],
+ info->protect[i] ? " (RO)" : " ");
+ }
+
+ printf("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong nor_flash_get_size(FPWV *addr, flash_info_t *info)
+{
+ /* Write auto select command: read Manufacturer ID */
+
+ /* Write auto select command sequence and test FLASH answer */
+#ifdef CONFIG_EON_FLASH
+ addr[0x0AAA] = (FPW)0x00AA00AA; /* for EON, Intel ignores this */
+ addr[0x0555] = (FPW)0x00550055; /* for EON, Intel ignores this */
+#endif
+ addr[0x0AAA] = (FPW)0x00900090; /* selects Intel or AMD */
+
+ /* The manufacturer codes are only 1 byte, so just use 1 byte.
+ * This works for any bus width and any FLASH device width.
+ */
+ printf("flash manufact id = 0x%x\n", addr[0]);
+ printf("flash device id = 0x%x\n", addr[2]);
+ switch (addr[0] & 0xff) {
+
+ case (uchar)AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+
+ case (uchar)INTEL_MANUFACT:
+ info->flash_id = FLASH_MAN_INTEL;
+ break;
+
+ case (uchar)EON_MANUFACT:
+ info->flash_id = FLASH_MAN_EON;
+ break;
+ case (uchar)MX_MANUFACT:
+ info->flash_id = FLASH_MAN_MX;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ break;
+ }
+
+ /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
+ if (info->flash_id != FLASH_UNKNOWN)
+ switch (addr[2]) {
+ /* case (FPW)AMD_ID_LV640U: */ /* 29LV640 and 29LV641 have same ID */
+ /* info->flash_id += FLASH_AM640U; */
+ /* info->sector_count = 128; */
+ /* info->size = 0x00800000 * (sizeof(FPW)/2); */
+ /* break; */ /* => 8 or 16 MB */
+
+ case (FPW)EON_ID_LV640U:
+ /* 29LV640 and 29LV641 have same ID */
+ info->flash_id += FLASH_EON29LV640U;
+ info->sector_count = 128;
+#ifdef CONFIG_FLASH_8BIT
+ info->size = 0x00800000;
+#else
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+#endif
+ break;
+ case (FPW)EON_ID_LV640B:
+ /* 29LV640 and 29LV641 have same ID */
+ if(info->flash_id == FLASH_MAN_MX)
+ info->flash_id += FLASH_MX29LV640B;
+ else
+ info->flash_id += FLASH_EON29LV640B;
+ info->sector_count = 135;
+ info->size = 0x00800000;
+ break;
+
+ case (FPW)EON_ID_LV640T:
+ /* 29LV640 and 29LV641 have same ID */
+ if(info->flash_id == FLASH_MAN_MX)
+ info->flash_id += FLASH_MX29LV640T;
+ else
+ info->flash_id += FLASH_EON29LV640U;
+ info->sector_count = 135;
+ info->size = 0x00800000;
+ break;
+
+ case (FPW)INTEL_ID_28F800C3B:
+ info->flash_id += FLASH_28F800C3B;
+ info->sector_count = 23;
+ info->size = 0x00100000 * (sizeof(FPW)/2);
+ break; /* => 1 or 2 MB */
+
+ case (FPW)INTEL_ID_28F800B3B:
+ info->flash_id += FLASH_INTEL800B;
+ info->sector_count = 23;
+ info->size = 0x00100000 * (sizeof(FPW)/2);
+ break; /* => 1 or 2 MB */
+
+ case (FPW)INTEL_ID_28F160C3B:
+ info->flash_id += FLASH_28F160C3B;
+ info->sector_count = 39;
+ info->size = 0x00200000 * (sizeof(FPW)/2);
+ break; /* => 2 or 4 MB */
+
+ case (FPW)INTEL_ID_28F160B3B:
+ info->flash_id += FLASH_INTEL160B;
+ info->sector_count = 39;
+ info->size = 0x00200000 * (sizeof(FPW)/2);
+ break; /* => 2 or 4 MB */
+
+ case (FPW)INTEL_ID_28F320C3B:
+ info->flash_id += FLASH_28F320C3B;
+ info->sector_count = 71;
+ info->size = 0x00400000 * (sizeof(FPW)/2);
+ break; /* => 4 or 8 MB */
+
+ case (FPW)INTEL_ID_28F320B3B:
+ info->flash_id += FLASH_INTEL320B;
+ info->sector_count = 71;
+ info->size = 0x00400000 * (sizeof(FPW)/2);
+ break; /* => 4 or 8 MB */
+
+ case (FPW)INTEL_ID_28F640C3B:
+ info->flash_id += FLASH_28F640C3B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break; /* => 8 or 16 MB */
+
+ case (FPW)INTEL_ID_28F640B3B:
+ info->flash_id += FLASH_INTEL640B;
+ info->sector_count = 135;
+ info->size = 0x00800000 * (sizeof(FPW)/2);
+ break; /* => 8 or 16 MB */
+
+ /*case (FPW)MX_ID_LV640B:
+ info->flash_id += FLASH_MX29LV640B;
+ info->sector_count = 135;
+ info->size = 0x00800000;
+ break;
+
+ case (FPW)MX_ID_LV640T:
+ info->flash_id += FLASH_MX29LV640B;
+ info->sector_count = 135;
+ info->size = 0x00800000;
+ break;*/
+
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return 0; /* => no or unknown flash */
+ }
+
+ flash_get_offsets((ulong)addr, info);
+
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+
+ return info->size;
+}
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+
+static void flash_sync_real_protect(flash_info_t *info)
+{
+ FPWV *addr = (FPWV *)(info->start[0]);
+ FPWV *sect;
+ int i;
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_28F800C3B:
+ case FLASH_28F800C3T:
+ case FLASH_28F160C3B:
+ case FLASH_28F160C3T:
+ case FLASH_28F320C3B:
+ case FLASH_28F320C3T:
+ case FLASH_28F640C3B:
+ case FLASH_28F640C3T:
+ /* check for protected sectors */
+ *addr = (FPW)0x00900090;
+ for (i = 0; i < info->sector_count; i++) {
+ /* read sector protection at sector address, (A7 .. A0) = 0x02.
+ * D0 = 1 for each device if protected.
+ * If at least one device is protected the sector is marked
+ * protected, but mixed protected and unprotected devices
+ * within a sector should never happen.
+ */
+ sect = (FPWV *)(info->start[i]);
+ info->protect[i] = (sect[2] & (FPW)(0x00010001)) ? 1 : 0;
+ }
+
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+ break;
+ case FLASH_EON29LV640U:
+ case FLASH_EON29LV640B:
+ for (i = 0; i < info->sector_count; i++) {
+ /* check for protected sectors */
+ sect = (FPWV *)(info->start[i]);
+ sect[0x0AAA] = (FPW)0x00AA00AA;
+ sect[0x0555] = (FPW)0x00550055;
+ sect[0x0AAA] = (FPW)0x00900090;
+
+ info->protect[i] = (sect[4] & (FPW)(0x00010001)) ? 1 : 0;
+ }
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+ break;
+ case FLASH_MX29LV640T:
+ case FLASH_MX29LV640B:
+ for (i = 0; i < info->sector_count; i++) {
+ /* check for protected sectors */
+ sect = (FPWV *)(info->start[i]);
+ sect[0x0AAA] = (FPW)0x00AA00AA;
+ sect[0x0555] = (FPW)0x00550055;
+ sect[0x0AAA] = (FPW)0x00900090;
+
+ info->protect[i] = (sect[4] & (FPW)(0x00010001)) ? 1 : 0;
+ }
+ /* Put FLASH back in read mode */
+ flash_reset(info);
+ break;
+ case FLASH_AM640U:
+ default:
+ /* no hardware protect that we support */
+ break;
+ }
+}
+#endif
+
+/*-----------------------------------------------------------------------
+ */
+
+int nor_flash_8b_erase(flash_info_t *info, int s_first, int s_last)
+{
+ FPWV *addr;
+ int flag, prot, sect;
+ int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
+ ulong start, now, last;
+ int rcode = 0;
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN)
+ printf("- missing\n");
+ else
+ printf("- no sectors to erase\n");
+ return 1;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_INTEL800B:
+ case FLASH_INTEL160B:
+ case FLASH_INTEL320B:
+ case FLASH_INTEL640B:
+ case FLASH_28F800C3B:
+ case FLASH_28F160C3B:
+ case FLASH_28F320C3B:
+ case FLASH_28F640C3B:
+ case FLASH_AM640U:
+ case FLASH_EON29LV640U:
+ case FLASH_EON29LV640B:
+ case FLASH_MX29LV640B:
+ case FLASH_MX29LV640T:
+ break;
+ case FLASH_UNKNOWN:
+ default:
+ printf("Can't erase unknown flash type %08lx - aborted\n",
+ info->flash_id);
+ 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
+ printf("\n");
+
+ /* start = get_timer(0); */
+ /* last = start; */
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
+ if (info->protect[sect] != 0) /* protected, skip it */
+ continue;
+ start = get_timer(0);
+ last = start;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr = (FPWV *)(info->start[sect]);
+ if (intel) {
+ *addr = (FPW)0x00500050; /* clear status register */
+ *addr = (FPW)0x00200020; /* erase setup */
+ *addr = (FPW)0x00D000D0; /* erase confirm */
+ } else {
+ /* must be AMD style if not Intel */
+ FPWV *base; /* first address in bank */
+ base = (FPWV *)(info->start[0]);
+ base[0x0AAA] = (FPW)0x00AA00AA; /* unlock */
+ base[0x0555] = (FPW)0x00550055; /* unlock */
+ base[0x0AAA] = (FPW)0x00800080; /* erase mode */
+ base[0x0AAA] = (FPW)0x00AA00AA; /* unlock */
+ base[0x0555] = (FPW)0x00550055; /* unlock */
+ *addr = (FPW)0x00300030; /* erase sector */
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* wait at least 50us for AMD, 80us for Intel.
+ * Let's wait 1 ms.
+ */
+ udelay(1000);
+
+ while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
+ now = get_timer(start);
+ if (now > CFG_FLASH_ERASE_TOUT) {
+ printf("Timeout\n");
+
+ if (intel) {
+ /* suspend erase */
+ *addr = (FPW)0x00B000B0;
+ }
+
+ flash_reset(info); /* reset to read mode */
+ rcode = 1; /* failed */
+ break;
+ }
+
+ /* show that we're waiting */
+ if ((now - last) > 1000) { /* every second */
+ putc('.');
+ last = now;
+ }
+ }
+
+ flash_reset(info); /* reset to read mode */
+ }
+
+ printf(" done\n");
+ return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int nor_flash_8b_write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
+ int bytes; /* number of bytes to program in current word */
+ int left; /* number of bytes left to program */
+ int i, res;
+
+ for (left = cnt, res = 0;
+ left > 0 && res == 0;
+ addr += sizeof(data), left -= sizeof(data) - bytes) {
+
+ bytes = addr & (sizeof(data) - 1);
+ addr &= ~(sizeof(data) - 1);
+
+ /* combine source and destination data so can program
+ * an entire word of 16 or 32 bits
+ */
+ for (i = 0; i < sizeof(data); i++) {
+ data <<= 8;
+ if (i < bytes || i - bytes >= left)
+ data += *((uchar *)addr + i);
+ else
+ data += *src++;
+ }
+
+ /* write one word to the flash */
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD:
+ res = write_word_amd(info, (FPWV *)addr, data);
+ case FLASH_MAN_EON:
+ res = write_word_eon(info, (FPWV *)addr, data);
+ break;
+ case FLASH_MAN_MX:
+ res = write_word_mx(info, (FPWV *)addr, data);
+ break;
+ case FLASH_MAN_INTEL:
+ res = write_word_intel(info, (FPWV *)addr, data);
+ break;
+ default:
+ /* unknown flash type, error! */
+ printf("missing or unknown FLASH type\n");
+ res = 1; /* not really a timeout, but gives error */
+ break;
+ }
+ }
+
+ return res;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for AMD FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+ FPWV *base; /* first address in flash bank */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data)
+ return 2;
+
+ base = (FPWV *)(info->start[0]);
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ base[0x0AAA] = (FPW)0x00AA00AA; /* unlock */
+ base[0x0555] = (FPW)0x00550055; /* unlock */
+ base[0x0AAA] = (FPW)0x00A000A0; /* selects program mode */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ /* data polling for D7 */
+ while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00F000F0; /* reset bank */
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for EON FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_eon(flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+ FPWV *base; /* first address in flash bank */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data)
+ return 2;
+
+ base = (FPWV *)(info->start[0]);
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ base[0x0AAA] = (FPW)0x00AA00AA; /* unlock */
+ base[0x0555] = (FPW)0x00550055; /* unlock */
+ base[0x0AAA] = (FPW)0x00A000A0; /* selects program mode */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ /* data polling for D7 */
+ while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00F000F0; /* reset bank */
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for MX FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_mx(flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+ FPWV *base; /* first address in flash bank */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data)
+ return 2;
+
+ base = (FPWV *)(info->start[0]);
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ base[0x0AAA] = (FPW)0x00AA00AA; /* unlock */
+ base[0x0555] = (FPW)0x00550055; /* unlock */
+ base[0x0AAA] = (FPW)0x00A000A0; /* selects program mode */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ /* data polling for D7 */
+ while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00F000F0; /* reset bank */
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for Intel FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & data) != data)
+ return 2;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ *dest = (FPW)0x00500050; /* clear status register */
+ *dest = (FPW)0x00FF00FF; /* make sure in read mode */
+ *dest = (FPW)0x00400040; /* program setup */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (FPW)0x00B000B0; /* Suspend program */
+ res = 1;
+ }
+ }
+
+ if (res == 0 && (*dest & (FPW)0x00100010))
+ res = 1; /* write failed, time out error is close enough */
+
+ *dest = (FPW)0x00500050; /* clear status register */
+ *dest = (FPW)0x00FF00FF; /* make sure in read mode */
+
+ return res;
+}
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+int nor_flash_8b_real_protect(flash_info_t *info, long sector, int prot)
+{
+ int rcode = 0; /* assume success */
+ FPWV *addr; /* address of sector */
+ FPW value;
+
+ addr = (FPWV *) (info->start[sector]);
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_28F800C3B:
+ case FLASH_28F800C3T:
+ case FLASH_28F160C3B:
+ case FLASH_28F160C3T:
+ case FLASH_28F320C3B:
+ case FLASH_28F320C3T:
+ case FLASH_28F640C3B:
+ case FLASH_28F640C3T:
+ flash_reset(info); /* make sure in read mode */
+ *addr = (FPW) 0x00600060L; /* lock command setup */
+ if (prot)
+ *addr = (FPW) 0x00010001L; /* lock sector */
+ else
+ *addr = (FPW) 0x00D000D0L; /* unlock sector */
+ flash_reset(info); /* reset to read mode */
+
+ /* now see if it really is locked/unlocked as requested */
+ *addr = (FPW) 0x00900090;
+ /* read sector protection at sector address, (A7 .. A0) = 0x02.
+ * D0 = 1 for each device if protected.
+ * If at least one device is protected the sector is marked
+ * protected, but return failure. Mixed protected and
+ * unprotected devices within a sector should never happen.
+ */
+ value = addr[2] & (FPW) 0x00010001;
+ if (value == 0)
+ info->protect[sector] = 0;
+ else if (value == (FPW) 0x00010001)
+ info->protect[sector] = 1;
+ else {
+ /* error, mixed protected and unprotected */
+ rcode = 1;
+ info->protect[sector] = 1;
+ }
+ if (info->protect[sector] != prot)
+ rcode = 1; /* failed to protect/unprotect as requested */
+
+ /* reload all protection bits from hardware for now */
+ flash_sync_real_protect(info);
+ break;
+
+ case FLASH_EON29LV640U:
+ case FLASH_EON29LV640B:
+ case FLASH_MX29LV640B:
+ case FLASH_MX29LV640T:
+ if (prot == 0)
+ info->protect[sector] = 0;
+ else if (prot == 1)
+ info->protect[sector] = 1;
+ else {
+ /* error, mixed protected and unprotected */
+ rcode = 1;
+ info->protect[sector] = 1;
+ }
+ if (info->protect[sector] != prot)
+ rcode = 1; /* failed to protect/unprotect as requested */
+
+ break;
+
+ case FLASH_AM640U:
+ default:
+ /* no hardware protect that we support */
+ info->protect[sector] = prot;
+ break;
+ }
+
+ return rcode;
+}
+#endif
diff --git a/board/wmt/flash/nor_flash_8bit.h b/board/wmt/flash/nor_flash_8bit.h
new file mode 100755
index 0000000..5910bae
--- /dev/null
+++ b/board/wmt/flash/nor_flash_8bit.h
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2008 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+
+#ifndef _NOR_FLASH_8BIT_H_
+#define _NOR_FLASH_8BIT_H_
+
+#include <common.h>
+#include <mpc8xx.h>
+
+unsigned long nor_flash_8b_init(void);
+void nor_flash_8b_print_info(flash_info_t *info);
+int nor_flash_8b_erase(flash_info_t *info, int s_first, int s_last);
+int nor_flash_8b_write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt);
+#ifdef CFG_FLASH_PROTECTION
+int nor_flash_8b_real_protect(flash_info_t *info, long sector, int prot);
+#endif
+
+#endif /*_NOR_FLASH_8BIT_H_*/
diff --git a/board/wmt/flash/spi_flash.c b/board/wmt/flash/spi_flash.c
new file mode 100755
index 0000000..17030d3
--- /dev/null
+++ b/board/wmt/flash/spi_flash.c
@@ -0,0 +1,865 @@
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2008 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+
+/* For UBOOT */
+#include <common.h>
+#include <environment.h>
+#include "../include/wmt_clk.h"
+
+#include "spi_flash.h"
+
+/* ST M25P64 CMD */
+#define SF_CMD_WREN 0x06
+#define SF_CMD_WRDI 0x04
+#define SF_CMD_RDID 0x9F
+#define SF_CMD_RDSR 0x05
+#define SF_CMD_WRSR 0x01
+#define SF_CMD_READ 0x03
+#define SF_CMD_FAST_READ 0x0B
+#define SF_CMD_PP 0x02
+#define SF_CMD_SE 0xD8
+#define SF_CMD_BE 0xC7
+#define SF_CMD_RES 0xAB
+
+#define SF_BIT_WR_PROT_ERR 0x20 /* [5:5] */
+#define SF_BIT_MEM_REGION_ERR 0x10 /* [4:4] */
+#define SF_BIT_PWR_DWN_ACC_ERR 0x8 /* [3:3] */
+#define SF_BIT_PCMD_OP_ERR 0x4 /* [2:2] */
+#define SF_BIT_PCMD_ACC_ERR 0x2 /* [1:1] */
+#define SF_BIT_MASLOCK_ERR 0x1 /* [0:0] */
+
+#define BIT_SEQUENCE_ERROR 0x00300030
+#define BIT_TIMEOUT 0x80000000
+//#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+/* SPI Interface Configuration Register(0x40) */
+#define SF_MANUAL_MODE 0x40
+
+/* SPI Programmable Command Mode Control Register(0x200) */
+#define SF_RUN_CMD 0x01
+
+/*
+ * Chip ID list
+ */
+#define EON_MANUF 0x1C
+#define NUMONYX_MANUF 0x20
+#define MXIC_MANUF 0xC2
+#define SPANSION_MANUF 0x01
+#define SST_MANUF 0xBF
+#define WB_MANUF 0xEF
+#define ATMEL_MANUF 0x1F
+#define GD_MANUF 0xC8
+
+/* EON */
+#define EON_25P16_ID 0x2015 /* 2 MB */
+#define EON_25P64_ID 0x2017 /* 8 MB */
+#define EON_25Q64_ID 0x3017 /* 8 MB */
+#define EON_25F40_ID 0x3113 /* 512 KB */
+#define EON_25F16_ID 0x3115 /* 2 MB */
+
+/* NUMONYX */
+#define NX_25P16_ID 0x2015 /* 2 MB */
+#define NX_25P64_ID 0x2017 /* 8 MB */
+
+/* MXIC */
+#define MX_L512_ID 0x2010 /* 64 KB , 4KB*/
+#define MX_L4006E_ID 0x2013 /* 512KB */
+#define MX_L1605D_ID 0x2015 /* 2 MB */
+#define MX_L3205D_ID 0x2016 /* 4 MB */
+#define MX_L6405D_ID 0x2017 /* 8 MB */
+#define MX_L1635D_ID 0x2415 /* 2 MB */
+#define MX_L3235D_ID 0x5E16 /* 4 MB */
+#define MX_L12805D_ID 0x2018 /* 16 MB */
+
+/* SPANSION */
+#define SPAN_FL016A_ID 0x0214 /* 2 MB */
+#define SPAN_FL064A_ID 0x0216 /* 8 MB */
+
+/* SST */
+#define SST_VF016B_ID 0x2541 /* 2 MB */
+
+/* WinBond */
+#define WB_X16A_ID 0x3015 /* 2 MB */
+#define WB_X32_ID 0x3016 /* 4 MB */
+#define WB_X64_ID 0x3017 /* 8 MB */
+#define WB_X128_ID 0x4018 /* 16 MB */
+#define WB_X40BV_ID 0x3013 /* 512KB */
+
+/* ATMEL */
+#define AT_25DF041A_ID 0x4401 /* 512KB */
+
+/* GD -Giga Device- */
+#define GD_25Q40_ID 0x4013 /* 512KB */
+#define GD_25Q128_ID 0x4018 /* 16MB */
+
+#define SF_IDALL(x, y) ((x<<16)|y)
+
+struct wm_sf_dev_t {
+ ulong id;
+ ulong size;
+ ulong sector_size;
+};
+
+struct wm_sf_dev_t sf_ids[] = {
+ /* {Device ID, Total Size, Sector Size} */
+ /* EON */
+ {SF_IDALL(EON_MANUF, EON_25P16_ID), 0x200000, 0x10000},
+ {SF_IDALL(EON_MANUF, EON_25P64_ID), 0x800000, 0x10000},
+ {SF_IDALL(EON_MANUF, EON_25F40_ID), 0x80000, 0x10000},
+ {SF_IDALL(EON_MANUF, EON_25F16_ID), 0x200000, 0x10000},
+ {SF_IDALL(EON_MANUF, EON_25Q64_ID), 0x800000, 0x10000},
+ /* NUMONYX */
+ {SF_IDALL(NUMONYX_MANUF, NX_25P16_ID), 0x200000, 0x10000},
+ {SF_IDALL(NUMONYX_MANUF, NX_25P64_ID), 0x800000, 0x10000},
+ /* MXIC */
+ {SF_IDALL(MXIC_MANUF, MX_L512_ID), 0x10000, 0x10000},
+ {SF_IDALL(MXIC_MANUF, MX_L4006E_ID), 0x80000, 0x10000},
+ {SF_IDALL(MXIC_MANUF, MX_L1605D_ID), 0x200000, 0x10000},
+ {SF_IDALL(MXIC_MANUF, MX_L3205D_ID), 0x400000, 0x10000},
+ {SF_IDALL(MXIC_MANUF, MX_L6405D_ID), 0x800000, 0x10000},
+ {SF_IDALL(MXIC_MANUF, MX_L1635D_ID), 0x200000, 0x10000},
+ {SF_IDALL(MXIC_MANUF, MX_L3235D_ID), 0x400000, 0x10000},
+ {SF_IDALL(MXIC_MANUF, MX_L12805D_ID), 0x1000000, 0x10000},
+ /* SPANSION */
+ {SF_IDALL(SPANSION_MANUF, SPAN_FL016A_ID), 0x200000, 0x10000},
+ {SF_IDALL(SPANSION_MANUF, SPAN_FL064A_ID), 0x800000, 0x10000},
+ /* SST */
+ {SF_IDALL(SST_MANUF, SST_VF016B_ID), 0x200000, 0x10000},
+ /*WinBond*/
+ {SF_IDALL(WB_MANUF, WB_X16A_ID), 0x200000, 0x10000},
+ {SF_IDALL(WB_MANUF, WB_X32_ID), 0x400000, 0x10000},
+ {SF_IDALL(WB_MANUF, WB_X64_ID), 0x800000, 0x10000},
+ {SF_IDALL(WB_MANUF, WB_X128_ID), 0x1000000, 0x10000},
+ {SF_IDALL(WB_MANUF, WB_X40BV_ID), 0x80000, 0x10000},
+ /* ATMEL */
+ {SF_IDALL(ATMEL_MANUF, AT_25DF041A_ID), 0x80000, 0x10000},
+ /* GD */
+ {SF_IDALL(GD_MANUF, GD_25Q40_ID), 0x80000, 0x10000},
+ {SF_IDALL(GD_MANUF, GD_25Q128_ID), 0x1000000, 0x10000},
+};
+
+sfreg_t *sfreg ;
+
+static unsigned int phy_flash_addr_0;
+static unsigned int phy_flash_addr_1;
+
+static int spi_flash_sector_erase(unsigned long addr);
+static int flash_error(unsigned long code);
+static int flash_env_init(void);
+static int init_spi_flash(void);
+extern flash_info_t flash_info_spi[CFG_MAX_SPI_FLASH_BANKS] ;/* info for FLASH chips */
+extern int wmt_read_ostc(int *val);
+extern int spi_flash_wmt_protect(flash_info_t *info, long sector, int prot);
+extern int auto_pll_divisor(enum dev_id dev, enum clk_cmd cmd, int unit, int freq);
+
+/*
+#ifdef CFG_FLASH_PROTECTION
+static void flash_syn_real_protect(flash_info_t *info);
+#endif
+*/
+
+/*-----------------------------------------------------------------------
+ * Function
+ */
+/*
+#ifdef CFG_FLASH_PROTECTION
+static void flash_syn_real_protect(flash_info_t *info)
+{
+}
+#endif
+*/
+
+int spi_flash_read_status(int chip, int *value)
+{
+ int temp;
+ if (chip == 0)
+ temp = sfreg->SPI_MEM_0_SR_ACC;
+ else
+ temp = sfreg->SPI_MEM_1_SR_ACC;
+
+ *value = temp;
+ return temp;
+}
+
+int spi_flash_write_status(int chip, int value)
+
+{
+ unsigned long rl_data ;
+ unsigned long temp;
+ int start_time, end_time;
+ int rc ;
+
+ /* SPI flash write enable control register: write enable on chip sel 0 */
+ //tmp1 = get_timer_masked();
+ wmt_read_ostc(&start_time);
+ end_time = start_time + 1;
+ if (chip == 0) {
+ sfreg->SPI_WR_EN_CTR = SF_CS0_WR_EN;
+ sfreg->SPI_MEM_0_SR_ACC = value;
+
+ /* poll status reg of chip 0 for chip erase */
+ do {
+ temp = sfreg->SPI_MEM_0_SR_ACC;
+ temp = sfreg->SPI_MEM_0_SR_ACC;
+
+ /* please SPI flash data sheet */
+ if ((temp & 0x1) == 0x0)
+ break ;
+
+ rc = flash_error(sfreg->SPI_ERROR_STATUS);
+ if (rc != ERR_OK)
+ return rc ;
+
+ wmt_read_ostc(&end_time);
+ } while ((end_time - start_time) < CFG_FLASH_ERASE_TOUT);
+
+ if ((end_time - start_time) >= CFG_FLASH_ERASE_TOUT) {
+ rl_data = BIT_TIMEOUT;
+ rc = flash_error(rl_data);
+ return rc;
+ }
+
+ sfreg->SPI_WR_EN_CTR = SF_CS0_WR_DIS ;
+ return ERR_OK ;
+ } else {
+ sfreg->SPI_WR_EN_CTR = SF_CS1_WR_EN;
+ sfreg->SPI_MEM_1_SR_ACC = value;
+
+
+ /* poll status reg of chip 0 for chip erase */
+ do {
+ temp = sfreg->SPI_MEM_1_SR_ACC ;
+ /* please SPI flash data sheet */
+ if ((temp & 0x1) == 0x0)
+ break ;
+
+ rc = flash_error(sfreg->SPI_ERROR_STATUS);
+ if (rc != ERR_OK)
+ return rc ;
+
+ } while ((end_time - start_time) < CFG_FLASH_ERASE_TOUT);
+
+ if ((end_time - start_time) >= CFG_FLASH_ERASE_TOUT) {
+ rl_data = BIT_TIMEOUT ;
+ rc = flash_error(rl_data) ;
+ return rc;
+ }
+
+ sfreg->SPI_WR_EN_CTR = SF_CS1_WR_DIS ;
+ return ERR_OK ;
+ }
+}
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+int spi_flash_real_protect(flash_info_t *info, long sector, int prot)
+
+{
+ int rc = 0;
+ /* printf("SF real protect\n");*/
+ rc = spi_flash_wmt_protect(info, sector, prot);
+ return rc;
+}
+#endif
+
+static int flash_env_init()
+{
+ /* SF reg base address */
+ sfreg = (sfreg_t *)SF_BASE_ADDR ;
+
+ return 0 ;
+}
+
+static int init_spi_flash()
+{
+ unsigned long rl_data;
+ unsigned long phy_flash_size_0 = 0, phy_flash_size_1 = 0;
+ int i, k;
+
+ /* SPI module configuration */
+ /* SPI Read Write Control Register @ bit 0: SPI Flash Read Speed Field */
+ sfreg->SPI_RD_WR_CTR = 0x1 ; /* read status register & set fast read command */
+
+ for (i = 0; i < CFG_MAX_SPI_FLASH_BANKS; i++) {
+
+ sfreg->SPI_RD_WR_CTR = 0x11 ; /* read ID */
+ if (i == 0)
+ flash_info_spi[i].flash_id = sfreg->SPI_MEM_0_SR_ACC ;
+ else
+ flash_info_spi[i].flash_id = sfreg->SPI_MEM_1_SR_ACC ;
+
+ sfreg->SPI_RD_WR_CTR = 0x1 ; /* read status */
+
+ for (k = 0; k < ARRAY_SIZE(sf_ids); k++) {
+ if (flash_info_spi[i].flash_id == sf_ids[k].id) {
+ printf("SF%1d: ManufID = %X, DeviceID = %X\n",
+ i,
+ flash_info_spi[i].flash_id >> 16,
+ flash_info_spi[i].flash_id & 0xFFFF);
+ flash_info_spi[i].size = sf_ids[k].size;
+ flash_info_spi[i].sector_count = sf_ids[k].size/sf_ids[k].sector_size;
+ break;
+ }
+ if (k == (ARRAY_SIZE(sf_ids) - 1)) {
+ printf("SF%1d: ManufID = %X, DeviceID = %X (Missing or Unknown FLASH)\n",
+ i,
+ flash_info_spi[i].flash_id >> 16,
+ flash_info_spi[i].flash_id & 0xFFFF);
+ printf(" Use Default - Total size = 8MB, Sector size = 64KB\n", i);
+ flash_info_spi[i].size = sf_ids[1].size;
+ flash_info_spi[i].sector_count = sf_ids[1].size/sf_ids[1].sector_size;
+ }
+ }
+
+ if (((flash_info_spi[i].flash_id >> 16) == ATMEL_MANUF) &&
+ (sfreg->SPI_MEM_0_SR_ACC & 0x04)) {
+ printf(" Global Unprotect SF%d !!\n", i);
+ sfreg->SPI_INTF_CFG |= SF_MANUAL_MODE; /* enter programmable command mode */
+ sfreg->SPI_PROG_CMD_WBF[0] = SF_CMD_WREN; /* Write Enable command */
+ sfreg->SPI_PROG_CMD_CTR = (0x01000000 | (i<<1)); /* set size and chip select */
+ sfreg->SPI_PROG_CMD_CTR |= SF_RUN_CMD; /* enable programmable command */
+ while (sfreg->SPI_PROG_CMD_CTR & SF_RUN_CMD)
+ ;
+ sfreg->SPI_PROG_CMD_WBF[0] = SF_CMD_WRSR; /* Write Status Register command */
+ sfreg->SPI_PROG_CMD_WBF[1] = 0x00; /* Global Unprotect */
+ sfreg->SPI_PROG_CMD_CTR = (0x02000000 | (i<<1)); /* set size and chip select */
+ sfreg->SPI_PROG_CMD_CTR |= SF_RUN_CMD; /* enable programmable command */
+ while (sfreg->SPI_PROG_CMD_CTR & SF_RUN_CMD)
+ ;
+ sfreg->SPI_INTF_CFG &= ~SF_MANUAL_MODE; /* exit programmable command mode */
+ }
+ }
+
+ /* SPI Chip Select 0 Configuration Register */
+ /* bit 31-16: Starting Address = 16'hff80 @ bit 11-8: Memory Size = 4'b1000 (8 MB) */
+ phy_flash_addr_0 = (0xFFFFFFFF - flash_info_spi[0].size) + 1;
+ phy_flash_addr_1 = phy_flash_addr_0 - flash_info_spi[1].size;
+ for (i = 0; i < 32; i++) {
+ if ((flash_info_spi[0].size >> i) == 0x8000)
+ phy_flash_size_0 = i;
+ if ((flash_info_spi[1].size >> i) == 0x8000)
+ phy_flash_size_1 = i;
+ }
+
+ sfreg->CHIP_SEL_0_CFG = (phy_flash_addr_0 | (phy_flash_size_0 << 8));
+ rl_data = sfreg->CHIP_SEL_0_CFG ;
+
+ sfreg->CHIP_SEL_1_CFG = (phy_flash_addr_1 | (phy_flash_size_1 << 8));
+ rl_data = sfreg->CHIP_SEL_1_CFG ;
+
+ sfreg->SPI_INTF_CFG = 0x00030000 ;
+ return 0 ;
+}
+
+static int spi_flash_sector_erase(unsigned long addr)
+{
+ unsigned long rl_data ;
+ unsigned long temp;
+ int start_time, end_time;
+ int rc ;
+
+ /* SPI module chip erase */
+ /* SPI flash write enable control register: write enable on chip sel 0 */
+ wmt_read_ostc(&start_time);
+ end_time = start_time + 1;
+ if (addr >= phy_flash_addr_0) {
+ sfreg->SPI_WR_EN_CTR = SF_CS0_WR_EN ;
+
+ /* select sector to erase */
+ addr &= 0xFFFF0000 ;
+ sfreg->SPI_ER_START_ADDR = addr ;
+
+ /* SPI flash erase control register: start chip erase */
+ /* Auto clear when transmit finishes. */
+ sfreg->SPI_ER_CTR = SF_SEC_ER_EN ;
+
+ /* poll status reg of chip 0 for chip erase */
+ do {
+ temp = sfreg->SPI_MEM_0_SR_ACC ;
+ temp = sfreg->SPI_MEM_0_SR_ACC ;
+
+ /* please SPI flash data sheet */
+ if ((temp & 0x1) == 0x0)
+ break ;
+
+ rc = flash_error(sfreg->SPI_ERROR_STATUS);
+ if (rc != ERR_OK)
+ return rc ;
+
+ wmt_read_ostc(&end_time);
+ } while ((end_time - start_time) < CFG_FLASH_ERASE_TOUT);
+
+ if ((end_time - start_time) >= CFG_FLASH_ERASE_TOUT) {
+ rl_data = BIT_TIMEOUT ;
+ rc = flash_error(rl_data) ;
+ return rc;
+ }
+
+ sfreg->SPI_WR_EN_CTR = SF_CS0_WR_DIS ;
+ return ERR_OK ;
+ } else {
+ sfreg->SPI_WR_EN_CTR = SF_CS1_WR_EN ;
+
+ /* select sector to erase */
+ addr &= 0xFFFF0000 ;
+ sfreg->SPI_ER_START_ADDR = addr ;
+
+ /* SPI flash erase control register: start chip erase */
+ /* Auto clear when transmit finishes. */
+ sfreg->SPI_ER_CTR = SF_SEC_ER_EN ;
+
+ /* poll status reg of chip 0 for chip erase */
+ do {
+ temp = sfreg->SPI_MEM_1_SR_ACC ;
+ temp = sfreg->SPI_MEM_1_SR_ACC ;
+
+ /* please SPI flash data sheet */
+ if ((temp & 0x1) == 0x0)
+ break ;
+
+ rc = flash_error(sfreg->SPI_ERROR_STATUS);
+ if (rc != ERR_OK)
+ return rc ;
+
+ wmt_read_ostc(&end_time);
+ } while ((end_time - start_time) < CFG_FLASH_ERASE_TOUT);
+
+ if ((end_time - start_time) >= CFG_FLASH_ERASE_TOUT) {
+ rl_data = BIT_TIMEOUT ;
+ rc = flash_error(rl_data) ;
+ return rc;
+ }
+
+ sfreg->SPI_WR_EN_CTR = SF_CS1_WR_DIS ;
+ return ERR_OK ;
+ }
+}
+
+static int flash_error(unsigned long code)
+{
+ /* check Timeout */
+ if (code & BIT_TIMEOUT) {
+ puts("Serial Flash Timeout\n"); /* For UBOOT */
+ /* printf("Serial Flash Timeout\n"); // For DLL */
+ sfreg->SPI_ERROR_STATUS = 0x3F ; /* write 1 to clear status */
+ return ERR_TIMOUT;
+ }
+
+ if (code & SF_BIT_WR_PROT_ERR) {
+ puts("Serial Flash Write Protect Error\n") ; /* For UBOOT */
+ /* printf("Serial Flash Write Protect Error\n") ; // For DLL */
+ sfreg->SPI_ERROR_STATUS = 0x3F ; /* write 1 to clear status */
+ return ERR_PROG_ERROR;
+ }
+
+ if (code & SF_BIT_MEM_REGION_ERR) {
+ puts("Serial Flash Memory Region Error\n") ; /* For UBOOT */
+ /* printf("Serial Flash Memory Region Error\n") ; // For DLL */
+ sfreg->SPI_ERROR_STATUS = 0x3F ; /* write 1 to clear status */
+ return ERR_PROG_ERROR;
+ }
+
+ if (code & SF_BIT_PWR_DWN_ACC_ERR) {
+ puts("Serial Flash Power Down Access Error\n") ; /* For UBOOT */
+ /* printf("Serial Flash Power Down Access Error\n") ; // For DLL */
+ sfreg->SPI_ERROR_STATUS = 0x3F ; /* write 1 to clear status */
+ return ERR_PROG_ERROR;
+ }
+
+
+ if (code & SF_BIT_PCMD_OP_ERR) {
+ puts("Serial Flash Program CMD OP Error\n") ; /* For UBOOT */
+ /* printf("Serial Flash Program CMD OP Error\n") ; // For DLL */
+ sfreg->SPI_ERROR_STATUS = 0x3F ; /* write 1 to clear status */
+ return ERR_PROG_ERROR;
+ }
+
+
+ if (code & SF_BIT_PCMD_ACC_ERR) {
+ puts("Serial Flash Program CMD OP Access Error\n") ; /* For UBOOT */
+ /* printf("Serial Flash Program CMD OP Access Error\n") ; // For DLL */
+ sfreg->SPI_ERROR_STATUS = 0x3F ; /* write 1 to clear status */
+ return ERR_PROG_ERROR;
+ }
+
+
+ if (code & SF_BIT_MASLOCK_ERR) {
+ puts("Serial Flash Master Lock Error\n") ; /* For UBOOT */
+ /* printf("Serial Flash Master Lock Error\n") ; // For DLL */
+ sfreg->SPI_ERROR_STATUS = 0x3F ; /* write 1 to clear status */
+ return ERR_PROG_ERROR;
+ }
+
+ /* OK, no error */
+ return ERR_OK;
+}
+
+
+/******************************************************************************
+ *
+ * Public u-boot interface functions below
+ *
+ *****************************************************************************/
+
+/***************************************************************************
+ *
+ * Flash initialization
+ *
+ *****************************************************************************/
+
+unsigned long spi_flash_init(void)
+{
+ int i, j;
+ unsigned long size = 0;
+
+ flash_env_init() ;
+ init_spi_flash() ;
+
+ for (i = 0; i < CFG_MAX_SPI_FLASH_BANKS; i++) {
+ unsigned long flashbase = 0 ;
+
+ /* For UBOOT */
+ memset(flash_info_spi[i].protect, 0, CFG_MAX_FLASH_SECT);
+ /*
+ for (k = 0 ; k < 128 ; k++) // For DLL, not For UBOOT
+ flash_info_spi[i].protect[k] = 0 ;
+ */
+ if (i == 0)
+ flashbase = phy_flash_addr_0;
+ else
+ flashbase = phy_flash_addr_1;
+
+ for (j = 0; j < flash_info_spi[i].sector_count; j++) {
+ if (j >= CFG_MAX_FLASH_SECT) {
+ printf("Error: Sector count of SPI Flash[%d] exceeds %d\n",
+ i,
+ CFG_MAX_FLASH_SECT);
+ break;
+ }
+ flash_info_spi[i].start[j] = flashbase;
+
+ /* uniform sector size */
+ flashbase += (flash_info_spi[i].size/flash_info_spi[i].sector_count);
+ }
+ size += flash_info_spi[i].size;
+ }
+
+ /*
+ * Protect monitor and environment sectors
+ */
+/* For UBOOT
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_FLASH_BASE,
+ CFG_FLASH_BASE + monitor_flash_len - 1,
+ &flash_info_spi[0]);
+
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info_spi[0]);
+
+#ifdef CFG_ENV_ADDR_REDUND
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_ENV_ADDR_REDUND,
+ CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
+ &flash_info_spi[0]);
+#endif
+*/
+ return size;
+}
+
+
+void spi_flash_print_info(flash_info_t *info)
+{
+ int i;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf("missing or unknown FLASH type\n");
+ return;
+ }
+
+ printf("SST SPI Flash(25P64A-8MB)\n");
+ printf(" Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; i++) {
+ if ((i % 3) == 0)
+ printf("\n ");
+
+ printf("[%3d]%08lX%s", i,
+ info->start[i],
+ info->protect[i] ? " (RO)" : " ");
+ }
+ printf("\n");
+
+}
+
+int spi_flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+ int iflag, prot, sect;
+ int rc = ERR_OK;
+/* For UBOOT */
+#ifdef USE_920T_MMU
+ int cflag;
+#endif
+
+ /* debug("flash_erase: s_first %d s_last %d\n", s_first, s_last); */
+
+ if ((s_first < 0) || (s_first > s_last))
+ return ERR_INVAL;
+
+ /* For UBOOT */
+ prot = 0;
+ for (sect = s_first; sect <= s_last; ++sect) {
+ if (info->protect[sect])
+ prot++;
+ }
+
+ if (prot)
+ printf("\n- Warning: %d protected sectors will not be erased!\n", prot);
+ else
+ printf("\n");
+
+ /*
+ * Disable interrupts which might cause a timeout
+ * here. Remember that our exception vectors are
+ * at address 0 in the flash, and we don't want a
+ * (ticker) exception to happen while the flash
+ * chip is in programming mode.
+ */
+
+#ifdef USE_920T_MMU
+ cflag = dcache_status();
+ dcache_disable();
+#endif
+ iflag = disable_interrupts();
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last && !ctrlc() /*For UBOOT */; sect++) {
+ /* For UBOOT */
+ debug("Erasing sector %2d @ %08lX... ",
+ sect, info->start[sect]);
+
+ /* printf("Erasing sector %2d @ %08lX... ", // For DLL */
+ /* sect, info->start[sect]); */
+
+ /* arm simple, non interrupt dependent timer */
+ /* For UBOOT */
+ reset_timer_masked();
+
+ if (info->protect[sect] == 0) { /* not protected */
+ unsigned long addr ;
+ addr = info->start[sect] ;
+
+
+ rc = spi_flash_sector_erase(addr) ;
+
+ if (rc != ERR_OK)
+ goto outahere;
+
+ printf("ok.\n");
+ } else {
+ /* it was protected */
+ printf("protected!\n");
+ }
+ }
+
+outahere:
+ /* allow flash to settle - wait 10 ms */
+ /* For UBOOT */
+ udelay_masked(10000);
+
+ if (iflag)
+ enable_interrupts();
+
+#ifdef USE_920T_MMU
+ if (cflag)
+ dcache_enable();
+#endif
+
+ return rc;
+}
+
+int spi_write_buff(
+ flash_info_t *info,
+ unsigned char *src /*For UBOOT*/,
+ unsigned long addr,
+ unsigned long cnt
+ )
+{
+ unsigned long wp;
+ int iflag;
+ int rc;
+ unsigned char *data;
+
+#ifdef USE_920T_MMU
+ cflag = dcache_status();
+ dcache_disable();
+#endif
+ iflag = disable_interrupts();
+
+ sfreg->SPI_WR_EN_CTR = 0x3 ;
+
+ rc = ERR_OK;
+ wp = addr;
+
+ data = (unsigned char *)addr;
+ while (cnt) {
+ *data = *src;
+ cnt--;
+ src++;
+ data++;
+ }
+
+ sfreg->SPI_WR_EN_CTR = 0x0 ;
+
+/* For UBOOT */
+ if (iflag)
+ enable_interrupts();
+
+#ifdef USE_920T_MMU
+ if (cflag)
+ dcache_enable();
+#endif
+
+ return rc ;
+}
+
+static int Manu_ReadData(unsigned int chip, unsigned int byte, unsigned int sector)/*case 5*/
+{
+ sfreg->SPI_PROG_CMD_WBF[0] = 0x03;
+ sfreg->SPI_PROG_CMD_WBF[1] = (sector & 0xFF0000) >> 16;
+ sfreg->SPI_PROG_CMD_WBF[2] = (sector & 0xFF00)>> 8;
+ sfreg->SPI_PROG_CMD_WBF[3] = sector & 0xFF;
+
+ /* set size and enable programmable command */
+ sfreg->SPI_PROG_CMD_CTR = (0x04000001 | chip<<1 | byte<<16);
+
+ return 0;
+}
+
+#if 0
+static int Manu_FastRead(unsigned int chip, unsigned int byte, unsigned int sector)/*case 6*/
+{
+ sfreg->SPI_PROG_CMD_WBF[0] = 0x0B;
+ sfreg->SPI_PROG_CMD_WBF[1] = (sector & 0xFF0000) >> 16;
+ sfreg->SPI_PROG_CMD_WBF[2] = (sector & 0xFF00) >> 8;
+ sfreg->SPI_PROG_CMD_WBF[3] = sector & 0xFF;
+ sfreg->SPI_PROG_CMD_WBF[4] = 0x00;
+
+ /* set size and enable programmable command */
+ sfreg->SPI_PROG_CMD_CTR = (0x05000001 | chip<<1 | byte<<16);
+ return 0;
+}
+#endif
+
+int spi_read_buff(
+ flash_info_t *info,
+ unsigned long src /*sf ofs*/,
+ unsigned long addr, /*mem_ofs*/
+ unsigned long cnt,
+ unsigned int fast
+ )
+{
+ unsigned long size;
+ int iflag;
+ int rc, t1, t2;
+ unsigned char *wp;
+ unsigned int chip = 0, sector = 0, byte = 64, chip0_base, sf_ofs;
+ int timeout = 0, dma = 64;
+ //int t3, t4;
+ //int fb_param = 0;
+ //char *s, *endp;
+
+ rc = ERR_OK;
+ wp = (unsigned char *)addr;
+ size = cnt;
+ sf_ofs = src;
+ chip0_base = (0xffffffff - info->size) + 1;
+
+
+ auto_pll_divisor(DEV_SF, CLK_ENABLE, 0, 0);
+
+ iflag = disable_interrupts();
+
+ sfreg->SPI_RD_WR_CTR = 0; /* READ instead of FAST_READ */
+ sfreg->SPI_INTF_CFG = 0x00000040; /* enter programmable command mode */
+
+ //printf("1 sf Read chip =%d data size = 0x%x bytes chip0_base=0x%x\n", chip, byte, chip0_base);
+
+ //wmt_read_ostc(&t3);
+
+ while(size) {
+ byte = ((size > dma) ? dma : size);
+ if (sf_ofs >= chip0_base && (sf_ofs + byte) < 0xffffffff) {
+ chip = 0;
+ sector = sf_ofs - chip0_base;
+ }
+ Manu_ReadData(chip, byte, sector);
+
+ size -= byte;
+ sf_ofs += byte;
+ wmt_read_ostc(&t1);
+ timeout = 0;
+ while (1) {
+ if ((sfreg->SPI_PROG_CMD_CTR & 0x1) == 0) {
+ /*printf("Sector Num: PROG_CMD_WBF[1] = 0x%X\n", sfreg->SPI_PROG_CMD_WBF[1]);
+ for (i = 0; i < byte; i += 4) {
+ printf("SPI_PROG_CMD_RBF[%x] = 0x%8.8x \r\n", i, *((volatile unsigned int *)&sfreg->SPI_PROG_CMD_RBF[i]));
+ }*/
+ break;
+ }
+ wmt_read_ostc(&t2);
+ if ((t2 - t1) > 3000000) {
+ timeout = 1;
+ break;
+ }
+ }
+ if (timeout) {
+ printf("Read chip =%d data size = 0x%x bytes fail! \n", chip, byte);
+ }/* else
+ printf("Read chip =%d data size = 0x%x bytes success \n", chip, byte);*/
+
+ memcpy(wp, sfreg->SPI_PROG_CMD_RBF, byte);
+ //wmt_read_ostc(&t5);
+
+ wp += byte;
+ if (sf_ofs > 0xFFFFFFFF || size == 0)
+ break;
+ }
+
+ //wmt_read_ostc(&t4);
+ //printf("t4-t3=%d t21=%d t51=%d\n", t4-t3, t2-t1, t5-t1);
+
+/* For UBOOT */
+ if (iflag)
+ enable_interrupts();
+
+
+ sfreg->SPI_PROG_CMD_CTR = 0; /* reset programmable command register*/
+ sfreg->SPI_INTF_CFG &= ~SF_MANUAL_MODE; /* exit programmable command mode */
+ sfreg->SPI_RD_WR_CTR = 0x01; /* read status register & set fast read command*/
+
+ /*wmt_read_ostc(&t1);
+ t2 = t1;
+ while(((t2 - t1)/1000) < 100) {
+ wmt_read_ostc(&t2);
+ }*/
+
+ return rc ;
+}
diff --git a/board/wmt/flash/spi_flash.h b/board/wmt/flash/spi_flash.h
new file mode 100755
index 0000000..e2b873e
--- /dev/null
+++ b/board/wmt/flash/spi_flash.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2006
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2008 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+
+#ifndef __SPI_FLASH_H_
+#define __SPI_FLASH_H_
+
+#include <asm/arch/common_def.h> /* WMT common definitions and macros */
+/* GPIO reg */
+#define GPIO_BASE_ADDR 0xD8110000
+#define GPIO_ENABLE_SF_REG REG32_PTR(GPIO_BASE_ADDR+0x0)
+#define GPIO_STRAPPING_REG REG32_PTR(GPIO_BASE_ADDR+0x0100)
+
+/* PMC module reg */
+#define PMC_BASE_ADDR 0XD8130000
+#define PMC_SF_CLK_REG REG32_PTR(PMC_BASE_ADDR + 0x314)
+#define PMC_PLLB_MULTIPLIER_REG REG32_PTR(PMC_BASE_ADDR + 0x204)
+#define PMC_PLLA_MULTIPLIER_REG REG32_PTR(PMC_BASE_ADDR + 0x200)
+#define PMC_PLLC_MULTIPLIER_REG REG32_PTR(PMC_BASE_ADDR + 0x208)
+#define PMC_PLLD_MULTIPLIER_REG REG32_PTR(PMC_BASE_ADDR + 0x20C)
+
+#define SF_BASE_ADDR 0xD8002000
+
+typedef struct sfreg_s {
+ unsigned long volatile CHIP_SEL_0_CFG ; /* 0xD8002000 */
+ unsigned long volatile Res1 ; /* 0x04 */
+ unsigned long volatile CHIP_SEL_1_CFG ; /* 0xD8002008 */
+ unsigned long volatile Res2[13] ; /* 0x0C */
+ unsigned long volatile SPI_INTF_CFG ; /* 0xD8002040 */
+ unsigned long volatile Res3[3] ; /* 0x44 */
+ unsigned long volatile SPI_RD_WR_CTR ; /* 0xD8002050 */
+ unsigned long volatile Res4[3] ; /* 0x54 */
+ unsigned long volatile SPI_WR_EN_CTR ; /* 0xD8002060 */
+ unsigned long volatile Res5[3] ; /* 0x64 */
+ unsigned long volatile SPI_ER_CTR ; /* 0xD8002070 */
+ unsigned long volatile SPI_ER_START_ADDR ; /* 0xD8002074 */
+ unsigned long volatile Res6[2] ; /* 0x78 */
+ unsigned long volatile SPI_ERROR_STATUS ; /* 0xD8002080 */
+ unsigned long volatile Res7[31] ; /* 0x84 */
+ unsigned long volatile SPI_MEM_0_SR_ACC ; /* 0xD8002100 */
+ unsigned long volatile Res8[3] ; /* 0x104 */
+ unsigned long volatile SPI_MEM_1_SR_ACC ; /* 0xD8002110 */
+ unsigned long volatile Res9[27] ; /* 0x114 */
+ unsigned long volatile SPI_PDWN_CTR_0 ; /* 0xD8002180 */
+ unsigned long volatile Res10[3] ; /* 0x184 */
+ unsigned long volatile SPI_PDWN_CTR_1 ; /* 0xD8002190 */
+ unsigned long volatile Res11[27] ; /* 0x194 */
+ unsigned long volatile SPI_PROG_CMD_CTR ; /* 0xD8002200 */
+ unsigned long volatile Res12[3] ; /* 0x204 */
+ unsigned long volatile SPI_USER_CMD_VAL ; /* 0xD8002210 */
+ unsigned long volatile Res13[59] ; /* 0x214 */
+ unsigned char volatile SPI_PROG_CMD_WBF[64] ; /* 0xD8002300 */
+ unsigned long volatile Res14[16] ; /* 0x340 */
+ unsigned char volatile SPI_PROG_CMD_RBF[64] ; /* 0xD8002380 */
+} sfreg_t ;
+
+/* Chip select 0-1 configuration register, 0x0 & 0x8 */
+#define SF_START_ADDR 0xFF800000 /* [36:16] */
+#define SF_MEM_SIZE_8M 0x00000800 /* [11:8] */
+
+/* SPI interface configuration register, 0x40 */
+#define SF_PDWN_DELY 0x0 /* [31:28] */
+#define SF_RES_DELY 0x0 /* [27:24] */
+#define SF_CS_DELY 0x0 /* [18:16] */
+#define SF_PROG_CMD_MOD_EN 0x40 /* [6:6] */
+#define SF_PROG_CMD_MOD_DIS 0x0 /* [6:6] */
+#define SF_USR_WR_CMD_MOD_EN 0x20 /* [5:5] */
+#define SF_USR_WR_CMD_MOD_DIS 0x0 /* [5:5] */
+#define SF_USR_RD_CMD_MOD_EN 0x10 /* [4:4] */
+#define SF_USR_RD_CMD_MOD_DIS 0x0 /* [4:4] */
+#define SF_ADDR_WIDTH_24 0x0 /* [0:0] */
+#define SF_ADDR_WIDTH_32 0x1 /* [0:0] */
+/* SPI flash read/write control register, 0x50 */
+#define SF_ID_RD 0x10 /* [4:4] */
+#define SF_STATUS_RD 0x0 /* [4:4] */
+#define SF_RD_SPD_FAST 0x1 /* [0:0] */
+#define SF_RD_SPD_NOR 0x0 /* [0:0] */
+
+/* SPI flash write enable control register, 0x60 */
+#define SF_CS1_WR_EN 0x2 /* [1:1] */
+#define SF_CS1_WR_DIS 0x0 /* [1:1] */
+#define SF_CS0_WR_EN 0x1 /* [0:0] */
+#define SF_CS0_WR_DIS 0x0 /* [0:0] */
+
+/* SPI flash erase control register, 0x70 */
+#define SF_SEC_ER_EN 0x8000 /* [15:15] */
+#define SF_SEC_ER_DIS 0x0 /* [15:15] */
+#define SF_CHIP_ER_EN 0x1 /* [0:0] */
+#define SF_CHIP_ER_DIS 0x0 /* [0:0] */
+
+/* SPI flash erase start address register, 0x74 */
+#define SF_ER_START_ADDR 0x0 /* [31:16] */
+#define CHIP_ER_CS1 0x2 /* [1:1] */
+#define CHIP_ER_CS0 0x1 /* [0:0] */
+
+/* SPI flash error status register, 0x80 */
+#define SF_WR_PROT_ERR 0x20 /* [5:5] */
+#define SF_MEM_REGION_ERR 0x10 /* [4:4] */
+#define SF_PWR_DWN_ACC_ERR 0x8 /* [3:3] */
+#define SF_PCMD_OP_ERR 0x4 /* [2:2] */
+#define SF_PCMD_ACC_ERR 0x2 /* [1:1] */
+#define SF_MASLOCK_ERR 0x1 /* [0:0] */
+/* SPI power down control register, 0x180 & 0x190 */
+#define PWR_DWN_EN 0x1 /* [0:0] */
+#define PWR_DWN_DIS 0x0 /* [0:0] */
+/* SPI programmable command mode control register, 0x200 */
+#define SF_TX_DATA_SIZE 0x0 /* MACRO [30:24] */
+#define SF_RX_DATA_SIZE 0x0 /* MACRO [22:16] */
+#define SF_CMD_CS1 0x2 /* MACRO [1:1] */
+#define SF_CMD_CS0 0x0 /* MACRO [1:1] */
+#define SF_CMD_EN 0x1 /* [0:0] */
+#define SF_CMD_DIS 0x0 /* [0:0] */
+/* SPI user command value register, 0x210 */
+#define SF_USR_WR_CMD 0x0 /* MACRO [23:16] */
+#define SF_USR_RD_CMD 0x0 /* MACRO [7:0] */
+
+unsigned long spi_flash_init(void);
+int spi_flash_erase(flash_info_t *info, int s_first, int s_last);
+int spi_write_buff(flash_info_t *info, unsigned char *src, unsigned long addr, unsigned long cnt);
+void spi_flash_print_info(flash_info_t *info);
+#ifdef CFG_FLASH_PROTECTION
+int spi_flash_real_protect(flash_info_t *info, long sector, int prot);
+int spi_flash_write_status(int chip, int value);
+int spi_flash_read_status(int chip, int *value);
+#endif
+
+#endif /* __SPI_FLASH_H_ */
diff --git a/board/wmt/flash/spi_flash_lock.c b/board/wmt/flash/spi_flash_lock.c
new file mode 100755
index 0000000..b82611d
--- /dev/null
+++ b/board/wmt/flash/spi_flash_lock.c
@@ -0,0 +1,82 @@
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (c) 2010 WonderMedia Technologies, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+ */
+
+/* For UBOOT */
+#include <common.h>
+#include "spi_flash.h"
+
+
+int spi_flash_wmt_protect(flash_info_t *info, long sector, int prot)
+{
+ int rc = 0, value;
+ char *key = NULL;
+
+ /*key = getenv("wmt.rsa.pem");
+ if (!key) {
+ return 1;
+ }*/
+ printf("real ");
+ if (prot) {
+ /* lock sf */
+ if (sector == 0) {
+ spi_flash_read_status(0, &value);
+ if ((value&0x9C) != 0x9C)
+ rc = spi_flash_write_status(0, 0x9C);
+ else
+ printf("chip 0 already lock\n");
+ } else {
+ spi_flash_read_status(1, &value);
+ if ((value&0x9C) != 0x9C)
+ rc = spi_flash_write_status(1, 0x9C);
+ else
+ printf("chip 1 already lock\n");
+ }
+ *(volatile unsigned char *)(GPIO_BASE_ADDR + 0xDF) &= ~0x4; /*gpio31 gpio out data*/
+ *(volatile unsigned char *)(GPIO_BASE_ADDR + 0x9F) |= 0x4; /*gpio31 enable out enable*/
+ *(volatile unsigned char *)(GPIO_BASE_ADDR + 0x5F) |= 0x4; /*gpio31 enable gpio mode*/
+ /* printf("SF protect sec %d\n", sector); */
+ } else {
+ /* unlock sf */
+ *(volatile unsigned char *)(GPIO_BASE_ADDR + 0xDF) |= 0x4; /*gpio31 gpio out data*/
+ *(volatile unsigned char *)(GPIO_BASE_ADDR + 0x9F) |= 0x4; /*gpio31 enable out enable*/
+ *(volatile unsigned char *)(GPIO_BASE_ADDR + 0x5F) |= 0x4; /*gpio31 enable gpio mode*/
+ if (sector == 0) {
+ spi_flash_read_status(0, &value);
+ if ((value&0x9C) != 0)
+ rc = spi_flash_write_status(0, 0);
+ else
+ printf("chip 0 already unlock\n");
+ } else {
+ spi_flash_read_status(1, &value);
+ if ((value&0x9C) != 0)
+ rc = spi_flash_write_status(1, 0);
+ else
+ printf("chip 1 already unlock\n");
+ }
+ if (rc) {
+ *(volatile unsigned char *)(GPIO_BASE_ADDR + 0xDF) &= ~0x4; /*gpio31 gpio pull-high*/
+ /* printf("SF unprotect fail\n", sector);*/
+ }
+ }
+ return rc;
+}
+
+
+