diff options
author | Kevin | 2014-11-15 11:48:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 11:48:36 +0800 |
commit | d04075478d378d9e15f3e1abfd14b0bd124077d4 (patch) | |
tree | 733dd964582f388b9e3e367c249946cd32a2851f /board/wmt/flash | |
download | FOSSEE-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-x | board/wmt/flash/nand_flash.c | 95 | ||||
-rwxr-xr-x | board/wmt/flash/nand_flash.h | 36 | ||||
-rwxr-xr-x | board/wmt/flash/nor_flash_16bit.c | 1225 | ||||
-rwxr-xr-x | board/wmt/flash/nor_flash_16bit.h | 38 | ||||
-rwxr-xr-x | board/wmt/flash/nor_flash_8bit.c | 1067 | ||||
-rwxr-xr-x | board/wmt/flash/nor_flash_8bit.h | 38 | ||||
-rwxr-xr-x | board/wmt/flash/spi_flash.c | 865 | ||||
-rwxr-xr-x | board/wmt/flash/spi_flash.h | 145 | ||||
-rwxr-xr-x | board/wmt/flash/spi_flash_lock.c | 82 |
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; +} + + + |