diff options
Diffstat (limited to 'qemu/roms/u-boot/board/gen860t/flash.c')
-rw-r--r-- | qemu/roms/u-boot/board/gen860t/flash.c | 628 |
1 files changed, 0 insertions, 628 deletions
diff --git a/qemu/roms/u-boot/board/gen860t/flash.c b/qemu/roms/u-boot/board/gen860t/flash.c deleted file mode 100644 index ca1ed3d62..000000000 --- a/qemu/roms/u-boot/board/gen860t/flash.c +++ /dev/null @@ -1,628 +0,0 @@ -/* - * (C) Copyright 2001 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * Keith Outwater, keith_outwater@mvsi.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <mpc8xx.h> - -#if defined(CONFIG_ENV_IS_IN_FLASH) -# ifndef CONFIG_ENV_ADDR -# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET) -# endif -# ifndef CONFIG_ENV_SIZE -# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE -# endif -# ifndef CONFIG_ENV_SECT_SIZE -# define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE -# endif -#endif - -/* - * Use buffered writes to flash by default - they are about 32x faster than - * single byte writes. - */ -#ifndef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER -#define CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER -#endif - -/* - * Max time to wait (in mS) for flash device to allocate a write buffer. - */ -#ifndef CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT -#define CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT 100 -#endif - -/* - * These functions support a single Intel StrataFlash device (28F128J3A) - * in byte mode only!. The flash routines are very basic and simple - * since there isn't really any remapping necessary. - */ - -/* - * Intel SCS (Scalable Command Set) command definitions - * (taken from 28F128J3A datasheet) - */ -#define SCS_READ_CMD 0xff -#define SCS_READ_ID_CMD 0x90 -#define SCS_QUERY_CMD 0x98 -#define SCS_READ_STATUS_CMD 0x70 -#define SCS_CLEAR_STATUS_CMD 0x50 -#define SCS_WRITE_BUF_CMD 0xe8 -#define SCS_PROGRAM_CMD 0x40 -#define SCS_BLOCK_ERASE_CMD 0x20 -#define SCS_BLOCK_ERASE_RESUME_CMD 0xd0 -#define SCS_PROGRAM_RESUME_CMD 0xd0 -#define SCS_BLOCK_ERASE_SUSPEND_CMD 0xb0 -#define SCS_SET_BLOCK_LOCK_CMD 0x60 -#define SCS_CLR_BLOCK_LOCK_CMD 0x60 - -/* - * SCS status/extended status register bit definitions - */ -#define SCS_SR7 0x80 -#define SCS_XSR7 0x80 - -/*---------------------------------------------------------------------*/ -#if 0 -#define DEBUG_FLASH -#endif - -#ifdef DEBUG_FLASH -#define PRINTF(fmt,args...) printf(fmt ,##args) -#else -#define PRINTF(fmt,args...) -#endif -/*---------------------------------------------------------------------*/ - -flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; - -/*----------------------------------------------------------------------- - * Functions - */ -static ulong flash_get_size (vu_char *addr, flash_info_t *info); -static int write_data8 (flash_info_t *info, ulong dest, uchar data); -static void flash_get_offsets (ulong base, flash_info_t *info); - -/*----------------------------------------------------------------------- - * Initialize the flash memory. - */ -unsigned long -flash_init (void) -{ - volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; - volatile memctl8xx_t *memctl = &immap->im_memctl; - unsigned long size_b0; - int i; - - for (i= 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) { - flash_info[i].flash_id = FLASH_UNKNOWN; - } - - /* - * The gen860t board only has one FLASH memory device, so the - * FLASH Bank configuration is done statically. - */ - PRINTF("\n## Get flash bank 1 size @ 0x%08x\n", FLASH_BASE0_PRELIM); - size_b0 = flash_get_size((vu_char *)FLASH_BASE0_PRELIM, &flash_info[0]); - if (flash_info[0].flash_id == FLASH_UNKNOWN) { - printf ("## Unknown FLASH on Bank 0: " - "ID 0x%lx, Size = 0x%08lx = %ld MB\n", - flash_info[0].flash_id,size_b0, size_b0 << 20); - } - - PRINTF("## Before remap:\n" - " BR0: 0x%08x OR0: 0x%08x\n BR1: 0x%08x OR1: 0x%08x\n", - memctl->memc_br0, memctl->memc_or0, - memctl->memc_br1, memctl->memc_or1); - - /* - * Remap FLASH according to real size - */ - memctl->memc_or0 |= (-size_b0 & 0xFFFF8000); - memctl->memc_br0 |= (CONFIG_SYS_FLASH_BASE & BR_BA_MSK); - - PRINTF("## After remap:\n" - " BR0: 0x%08x OR0: 0x%08x\n", memctl->memc_br0, memctl->memc_or0); - - /* - * Re-do sizing to get full correct info - */ - size_b0 = flash_get_size ((vu_char *)CONFIG_SYS_FLASH_BASE, &flash_info[0]); - flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]); - flash_info[0].size = size_b0; - -#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE - /* - * Monitor protection is ON by default - */ - flash_protect(FLAG_PROTECT_SET, - CONFIG_SYS_MONITOR_BASE, - CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, - &flash_info[0]); -#endif - -#ifdef CONFIG_ENV_IS_IN_FLASH - /* - * Environment protection ON by default - */ - flash_protect(FLAG_PROTECT_SET, - CONFIG_ENV_ADDR, - CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, - &flash_info[0]); -#endif - - PRINTF("## Final Flash bank size: 0x%08lx\n",size_b0); - return (size_b0); -} - - -/*----------------------------------------------------------------------- - * Fill in the FLASH offset table - */ -static void -flash_get_offsets (ulong base, flash_info_t *info) -{ - int i; - - if (info->flash_id == FLASH_UNKNOWN) { - return; - } - - switch (info->flash_id & FLASH_VENDMASK) { - case FLASH_MAN_INTEL: - for (i = 0; i < info->sector_count; i++) { - info->start[i] = base; - base += 1024 * 128; - } - return; - - default: - printf ("Don't know sector offsets for FLASH" - " type 0x%lx\n", info->flash_id); - return; - } -} - - -/*----------------------------------------------------------------------- - * Display FLASH device info - */ -void -flash_print_info (flash_info_t *info) -{ - int i; - - if (info->flash_id == FLASH_UNKNOWN) { - printf ("Missing or unknown FLASH type\n"); - return; - } - - switch (info->flash_id & FLASH_VENDMASK) { - case FLASH_MAN_INTEL: - printf ("Intel "); - break; - default: - printf ("Unknown Vendor "); - break; - } - - switch (info->flash_id & FLASH_TYPEMASK) { - case FLASH_28F128J3A: - printf ("28F128J3A (128Mbit = 128K x 128)\n"); - break; - default: - printf ("Unknown Chip Type\n"); - break; - } - - if (info->size >= (1024 * 1024)) { - i = 20; - } else { - i = 10; - } - printf (" Size: %ld %cB in %d Sectors\n", - info->size >> i, - (i == 20) ? 'M' : 'k', - 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"); - return; -} - - -/*----------------------------------------------------------------------- - * Get size and other information for a FLASH device. - * NOTE: The following code cannot be run from FLASH! - */ -static -ulong flash_get_size (vu_char *addr, flash_info_t *info) -{ -#define NO_FLASH 0 - - vu_char value[2]; - - /* - * Try to read the manufacturer ID - */ - addr[0] = SCS_READ_CMD; - addr[0] = SCS_READ_ID_CMD; - value[0] = addr[0]; - value[1] = addr[2]; - addr[0] = SCS_READ_CMD; - - PRINTF("Manuf. ID @ 0x%08lx: 0x%02x\n", (ulong)addr, value[0]); - switch (value[0]) { - case (INTEL_MANUFACT & 0xff): - info->flash_id = FLASH_MAN_INTEL; - break; - default: - info->flash_id = FLASH_UNKNOWN; - info->sector_count = 0; - info->size = 0; - return (NO_FLASH); - } - - /* - * Read the device ID - */ - PRINTF("Device ID @ 0x%08lx: 0x%02x\n", (ulong)(&addr[2]), value[1]); - switch (value[1]) { - case (INTEL_ID_28F128J3A & 0xff): - info->flash_id += FLASH_28F128J3A; - info->sector_count = 128; - info->size = 16 * 1024 * 1024; - break; - - default: - info->flash_id = FLASH_UNKNOWN; - return (NO_FLASH); - } - - if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) { - printf ("** ERROR: sector count %d > max (%d) **\n", - info->sector_count, CONFIG_SYS_MAX_FLASH_SECT); - info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; - } - return (info->size); -} - - -/*----------------------------------------------------------------------- - * Erase the specified sectors in the specified FLASH device - */ -int -flash_erase(flash_info_t *info, int s_first, int s_last) -{ - int flag, prot, sect; - ulong start, now, last; - - 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; - } - - if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) { - printf ("Can erase only Intel flash types - aborted\n"); - return 1; - } - - prot = 0; - for (sect=s_first; sect<=s_last; ++sect) { - if (info->protect[sect]) { - prot++; - } - } - - if (prot) { - printf ("- Warning: %d protected sectors will not be erased!\n", - prot); - } else { - printf ("\n"); - } - - start = get_timer (0); - last = start; - - /* - * Start erase on unprotected sectors - */ - for (sect = s_first; sect<=s_last; sect++) { - if (info->protect[sect] == 0) { /* not protected */ - vu_char *addr = (uchar *)(info->start[sect]); - vu_char status; - - /* - * Disable interrupts which might cause a timeout - */ - flag = disable_interrupts(); - - *addr = SCS_CLEAR_STATUS_CMD; - *addr = SCS_BLOCK_ERASE_CMD; - *addr = SCS_BLOCK_ERASE_RESUME_CMD; - - /* - * Re-enable interrupts if necessary - */ - if (flag) - enable_interrupts(); - - /* - * Wait at least 80us - let's wait 1 ms - */ - udelay (1000); - - while (((status = *addr) & SCS_SR7) != SCS_SR7) { - if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { - printf ("Timeout\n"); - *addr = SCS_BLOCK_ERASE_SUSPEND_CMD; - *addr = SCS_READ_CMD; - return 1; - } - - /* - * Show that we're waiting - */ - if ((now - last) > 1000) { /* 1 second */ - putc ('.'); - last = now; - } - } - *addr = SCS_READ_CMD; - } - } - printf (" done\n"); - return 0; -} - - -#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER -/* - * Allocate a flash buffer, fill it with data and write it to the flash. - * 0 - OK - * 1 - Timeout on buffer request - * - * NOTE: After the last call to this function, WSM status needs to be checked! - */ -static int -write_flash_buffer8(flash_info_t *info_p, vu_char *src_p, vu_char *dest_p, - uint count) -{ - vu_char *block_addr_p = NULL; - vu_char *start_addr_p = NULL; - ulong blocksize = info_p->size / (ulong)info_p->sector_count; - - int i; - uint time = get_timer(0); - - PRINTF("%s:%d: src: 0x%p dest: 0x%p count: %d\n", - __FUNCTION__, __LINE__, src_p, dest_p, count); - - /* - * What block are we in? We already know that the source address is - * in the flash address range, but we also can't cross a block boundary. - * We assume that the block does not cross a boundary (we'll check before - * calling this function). - */ - for (i = 0; i < info_p->sector_count; ++i) { - if ( ((ulong)dest_p >= info_p->start[i]) && - ((ulong)dest_p < (info_p->start[i] + blocksize)) ) { - PRINTF("%s:%d: Dest addr 0x%p is in block %d @ 0x%.8lx\n", - __FUNCTION__, __LINE__, dest_p, i, info_p->start[i]); - block_addr_p = (vu_char *)info_p->start[i]; - break; - } - } - - /* - * Request a buffer - */ - *block_addr_p = SCS_WRITE_BUF_CMD; - while ((*block_addr_p & SCS_XSR7) != SCS_XSR7) { - if (get_timer(time) > CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT) { - PRINTF("%s:%d: Buffer allocation timeout @ 0x%p (waited %d mS)\n", - __FUNCTION__, __LINE__, block_addr_p, - CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT); - return 1; - } - *block_addr_p = SCS_WRITE_BUF_CMD; - } - - /* - * Fill the buffer with data - */ - start_addr_p = dest_p; - *block_addr_p = count - 1; /* flash device wants count - 1 */ - PRINTF("%s:%d: Fill buffer at block addr 0x%p\n", - __FUNCTION__, __LINE__, block_addr_p); - for (i = 0; i < count; i++) { - *start_addr_p++ = *src_p++; - } - - /* - * Flush buffer to flash - */ - *block_addr_p = SCS_PROGRAM_RESUME_CMD; -#if 1 - time = get_timer(0); - while ((*block_addr_p & SCS_SR7) != SCS_SR7) { - if (get_timer(time) > CONFIG_SYS_FLASH_WRITE_TOUT) { - PRINTF("%s:%d: Write timeout @ 0x%p (waited %d mS)\n", - __FUNCTION__, __LINE__, block_addr_p, CONFIG_SYS_FLASH_WRITE_TOUT); - return 1; - } - } - -#endif - return 0; -} -#endif - - -/*----------------------------------------------------------------------- - * Copy memory to flash, returns: - * 0 - OK - * 1 - write timeout - * 2 - Flash not erased - * 4 - Flash not identified - */ -int -write_buff(flash_info_t *info_p, uchar *src_p, ulong addr, ulong count) -{ - int rc = 0; -#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER -#define FLASH_WRITE_BUF_SIZE 0x00000020 /* 32 bytes */ - int i; - uint bufs; - ulong buf_count; - vu_char *sp; - vu_char *dp; -#else - ulong wp; -#endif - - PRINTF("\n%s:%d: src: 0x%.8lx dest: 0x%.8lx size: %d (0x%.8lx)\n", - __FUNCTION__, __LINE__, (ulong)src_p, addr, (uint)count, count); - - if (info_p->flash_id == FLASH_UNKNOWN) { - return 4; - } - -#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER - sp = src_p; - dp = (uchar *)addr; - - /* - * For maximum performance, we want to align the start address to - * the beginning of a write buffer boundary (i.e. A4-A0 of the - * start address = 0). See how many bytes are required to get to a - * write-buffer-aligned address. If that number is non-zero, do - * non buffered writes of the non-aligned data. By doing non-buffered - * writes, we avoid the problem of crossing a block (sector) boundary - * with buffered writes. - */ - buf_count = FLASH_WRITE_BUF_SIZE - (addr & (FLASH_WRITE_BUF_SIZE - 1)); - if (buf_count == FLASH_WRITE_BUF_SIZE) { /* already on a boundary */ - buf_count = 0; - } - if (buf_count > count) { /* not a full buffers worth of data to write */ - buf_count = count; - } - count -= buf_count; - - PRINTF("%s:%d: Write buffer alignment count = %ld\n", - __FUNCTION__, __LINE__, buf_count); - while (buf_count-- >= 1) { - if ((rc = write_data8(info_p, (ulong)dp++, *sp++)) != 0) { - return (rc); - } - } - - PRINTF("%s:%d: count = %ld\n", __FUNCTION__, __LINE__, count); - if (count == 0) { /* all done */ - PRINTF("%s:%d: Less than 1 buffer (%d) worth of bytes\n", - __FUNCTION__, __LINE__, FLASH_WRITE_BUF_SIZE); - return (rc); - } - - /* - * Now that we are write buffer aligned, write full or partial buffers. - * The fact that we are write buffer aligned automatically avoids - * crossing a block address during a write buffer operation. - */ - bufs = count / FLASH_WRITE_BUF_SIZE; - PRINTF("%s:%d: %d (0x%x) buffers to write\n", __FUNCTION__, __LINE__, - bufs, bufs); - while (bufs >= 1) { - rc = write_flash_buffer8(info_p, sp, dp, FLASH_WRITE_BUF_SIZE); - if (rc != 0) { - PRINTF("%s:%d: ** Error writing buf %d\n", - __FUNCTION__, __LINE__, bufs); - return (rc); - } - bufs--; - sp += FLASH_WRITE_BUF_SIZE; - dp += FLASH_WRITE_BUF_SIZE; - } - - /* - * Do the leftovers - */ - i = count % FLASH_WRITE_BUF_SIZE; - PRINTF("%s:%d: %d (0x%x) leftover bytes\n", __FUNCTION__, __LINE__, i, i); - if (i > 0) { - rc = write_flash_buffer8(info_p, sp, dp, i); - } - - sp = (vu_char*)info_p->start[0]; - *sp = SCS_READ_CMD; - return (rc); - -#else - wp = addr; - while (count-- >= 1) { - if((rc = write_data8(info_p, wp++, *src_p++)) != 0) - return (rc); - } - return 0; -#endif -} - - -/*----------------------------------------------------------------------- - * Write a byte to Flash, returns: - * 0 - OK - * 1 - write timeout - * 2 - Flash not erased - */ -static int -write_data8 (flash_info_t *info, ulong dest, uchar data) -{ - vu_char *addr = (vu_char *)dest; - vu_char status; - ulong start; - int flag; - - /* Check if Flash is (sufficiently) erased */ - if ((*addr & data) != data) { - return (2); - } - /* Disable interrupts which might cause a timeout here */ - flag = disable_interrupts(); - - *addr = SCS_PROGRAM_CMD; - *addr = data; - - /* re-enable interrupts if necessary */ - if (flag) - enable_interrupts(); - - start = get_timer (0); - - while (((status = *addr) & SCS_SR7) != SCS_SR7) { - if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) { - *addr = SCS_READ_CMD; - return (1); - } - } - *addr = SCS_READ_CMD; - return (0); -} - -/* vim: set ts=4 sw=4 tw=78: */ |