flash_tc58xxx.inl

来自「eCos操作系统源码」· INL 代码 · 共 432 行

INL
432
字号
#ifndef CYGONCE_DEVS_FLASH_TOSHIBA_TC58XXX_INL#define CYGONCE_DEVS_FLASH_TOSHIBA_TC58XXX_INL//==========================================================================////      flash_tc58xxx.inl////      Toshiba Tc58xxx series flash driver////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2003 Jonathan Larmour// Copyright (C) 2003, 2004 Gary Thomas//// eCos 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 or (at your option) any later version.//// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    Gary Thomas <gary@mlbassoc.com>// Contributors: // Date:         2003-09-02// Purpose:// Description:  FLASH drivers for Toshiba NAND FLASH TC58xxx devices.//               Based on Atmel AT49xxxx drivers by Jani Monoses <jani@iv.ro>////####DESCRIPTIONEND####////==========================================================================// FIXME!  Someday add support for ECC data & fixups of bad sectors#include <pkgconf/hal.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_cache.h>#include CYGHWR_MEMORY_LAYOUT_H#define  _FLASH_PRIVATE_#include <cyg/io/flash.h>// Low level debugging//   1 - command level - prints messages about read/write/erase commands//   2 - hardware level - shows all NAND device I/O data#define FLASH_DEBUG  0//----------------------------------------------------------------------------// Common device details.#define FLASH_Read_ID                   FLASHWORD(0x90)#define FLASH_Reset                     FLASHWORD(0xFF)#define FLASH_Read_Mode1                FLASHWORD(0x00)#define FLASH_Read_Mode2                FLASHWORD(0x01)#define FLASH_Read_Mode3                FLASHWORD(0x50)#define FLASH_Program                   FLASHWORD(0x10)#define FLASH_Send_Data                 FLASHWORD(0x80)#define FLASH_Status                    FLASHWORD(0x70)#define FLASH_Block_Erase               FLASHWORD(0x60)#define FLASH_Start_Erase               FLASHWORD(0xD0)#define CYGNUM_FLASH_ID_MANUFACTURER    FLASHWORD(0x98)//----------------------------------------------------------------------------// Now that device properties are defined, include magic for defining// accessor type and constants.#include <cyg/io/flash_dev.h>//----------------------------------------------------------------------------// Information about supported devicestypedef struct flash_dev_info {    flash_data_t device_id;    cyg_uint32   block_size;    cyg_uint32   page_size;    cyg_int32    block_count;    cyg_uint32   base_mask;    cyg_uint32   device_size;} flash_dev_info_t;static const flash_dev_info_t* flash_dev_info;static const flash_dev_info_t supported_devices[] = {#include <cyg/io/flash_tc58xxx_parts.inl>};#define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))//----------------------------------------------------------------------------// Functions that put the flash device into non-read mode must reside// in RAM.void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));int  flash_erase_block(void* block, unsigned int size)    __attribute__ ((section (".2ram.flash_erase_block")));int  flash_program_buf(void* addr, void* data, int len)    __attribute__ ((section (".2ram.flash_program_buf")));//----------------------------------------------------------------------------// Initialize driver detailsintflash_hwr_init(void){    flash_data_t id[4];    int i;#ifdef CYGHWR_FLASH_TC58XXX_PLF_INIT    CYGHWR_FLASH_TC58XXX_PLF_INIT();#endif    flash_dev_query(id);    // Check that flash_id data is matching the one the driver was    // configured for.    // Check manufacturer    if (id[0] != CYGNUM_FLASH_ID_MANUFACTURER) {        diag_printf("Can't identify FLASH - manufacturer is: %x, should be %x\n",                     id[0], CYGNUM_FLASH_ID_MANUFACTURER);        return FLASH_ERR_DRV_WRONG_PART;    }    // Look through table for device data    flash_dev_info = supported_devices;    for (i = 0; i < NUM_DEVICES; i++) {        if (flash_dev_info->device_id == id[1])            break;        flash_dev_info++;    }    // Did we find the device? If not, return error.    if (NUM_DEVICES == i) {        diag_printf("Can't identify FLASH - device is: %x, supported: ", id[1]);        for (i = 0;  i < NUM_DEVICES;  i++) {            diag_printf("%x ", supported_devices[i].device_id);        }        diag_printf("\n");        return FLASH_ERR_DRV_WRONG_PART;    }    // Fill in device details    flash_info.block_size = flash_dev_info->block_size;    flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;    flash_info.start = (void *)CYGNUM_FLASH_BASE;    flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));    return FLASH_ERR_OK;}//----------------------------------------------------------------------------// Map a hardware status to a package errorintflash_hwr_map_error(int e){    return e;}//----------------------------------------------------------------------------// See if a range of FLASH addresses overlaps currently running codeboolflash_code_overlaps(void *start, void *end){    extern unsigned char _stext[], _etext[];    return ((((unsigned long)&_stext >= (unsigned long)start) &&             ((unsigned long)&_stext < (unsigned long)end)) ||            (((unsigned long)&_etext >= (unsigned long)start) &&             ((unsigned long)&_etext < (unsigned long)end)));}static voidput_NAND(volatile flash_data_t *ROM, flash_data_t val){    *ROM = val;#if FLASH_DEBUG > 1    diag_printf("%02x ", val);#endif}//----------------------------------------------------------------------------// Flash Query//// Only reads the manufacturer and part number codes for the first// device(s) in series. It is assumed that any devices in series// will be of the same type.voidflash_query(void* data){    flash_data_t* id = (flash_data_t*) data;    volatile flash_data_t *ROM;    ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE;    // Send initial RESET command    CYGHWR_FLASH_TC58XXX_CE(1);    CYGHWR_FLASH_TC58XXX_CLE(1);    put_NAND(ROM, FLASH_Reset);    CYGHWR_FLASH_TC58XXX_CLE(0);    CYGHWR_FLASH_TC58XXX_CE(0);    // Now, wait for a good while    CYGACC_CALL_IF_DELAY_US(10000);  // Actually 10ms    // Issue device query    CYGHWR_FLASH_TC58XXX_CE(1);    CYGHWR_FLASH_TC58XXX_CLE(1);    put_NAND(ROM, FLASH_Read_ID);    CYGHWR_FLASH_TC58XXX_CLE(0);    CYGHWR_FLASH_TC58XXX_ALE(1);    put_NAND(ROM, 0x00);  // Dummy address    CYGHWR_FLASH_TC58XXX_ALE(0);    // Minimum 100ns delay after deasserting ALE    CYGACC_CALL_IF_DELAY_US(10);  // Actually 10us    id[0] = *ROM;    id[1] = *ROM;    CYGHWR_FLASH_TC58XXX_CLE(1);    put_NAND(ROM, FLASH_Reset);    CYGHWR_FLASH_TC58XXX_CLE(0);    CYGHWR_FLASH_TC58XXX_CE(0);}//----------------------------------------------------------------------------// Erase Blockintflash_erase_block(void* block, unsigned int size){    volatile flash_data_t* ROM;    volatile flash_data_t* b_p = (volatile flash_data_t*) block;    int res = FLASH_ERR_OK;    int len = 0;    int cnt = 0;    flash_data_t stat;#if FLASH_DEBUG > 0    diag_printf("%s - block: %x, size: %d\n", __FUNCTION__, block, size);#endif    ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE;    // Erase the next block#if FLASH_DEBUG > 1    diag_printf("<< ");#endif    CYGHWR_FLASH_TC58XXX_CE(1);    CYGHWR_FLASH_TC58XXX_CLE(1);    put_NAND(ROM, FLASH_Block_Erase);    CYGHWR_FLASH_TC58XXX_CLE(0);    CYGHWR_FLASH_TC58XXX_ALE(1);    put_NAND(ROM, ((unsigned long)b_p & 0x0001FE00) >> 9);      // A9..A16    put_NAND(ROM, ((unsigned long)b_p & 0x01FE0000) >> 17);     // A17..A24    if (flash_dev_info->device_size > 0x02000000) {        put_NAND(ROM, ((unsigned long)b_p & 0x06000000) >> 25); // A26..A27    }    CYGHWR_FLASH_TC58XXX_ALE(0);    CYGHWR_FLASH_TC58XXX_CLE(1);    put_NAND(ROM, FLASH_Start_Erase);    CYGHWR_FLASH_TC58XXX_CLE(0);            while (!CYGHWR_FLASH_TC58XXX_RDY()) cnt++;  // Wait for operation to complete    CYGHWR_FLASH_TC58XXX_CLE(1);    put_NAND(ROM, FLASH_Status);    CYGHWR_FLASH_TC58XXX_CLE(0);            stat = *ROM;    CYGHWR_FLASH_TC58XXX_CE(0);#if FLASH_DEBUG > 1    diag_printf(">>\n");#endif#if FLASH_DEBUG > 0    diag_printf("block: %x, stat: %x, count = %d\n", b_p, stat, cnt);#endif    return res;}//----------------------------------------------------------------------------// Program Bufferintflash_program_buf(void* addr, void* data, int len){    volatile flash_data_t* ROM;    volatile flash_data_t* addr_ptr = (volatile flash_data_t*) addr;    volatile flash_data_t* data_ptr = (volatile flash_data_t*) data;    int res = FLASH_ERR_OK;    int i;    int cnt;    flash_data_t stat;    ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE;#if FLASH_DEBUG > 0    diag_printf("%s - addr: %x, data: %x, len: %d, FLASH: %p/%d\n",                 __FUNCTION__, addr, data, len, ROM, sizeof(flash_data_t));#endif    while (len > 0) {        CYGHWR_FLASH_TC58XXX_CE(1);        CYGHWR_FLASH_TC58XXX_CLE(1);#if FLASH_DEBUG > 1        diag_printf("<< ");#endif        put_NAND(ROM, FLASH_Read_Mode1);        put_NAND(ROM, FLASH_Send_Data);        CYGHWR_FLASH_TC58XXX_CLE(0);        CYGHWR_FLASH_TC58XXX_ALE(1);        put_NAND(ROM, ((unsigned long)addr_ptr & 0x000000FF) >> 0);   // A0..A7        put_NAND(ROM, ((unsigned long)addr_ptr & 0x0001FE00) >> 9);   // A9..A16        put_NAND(ROM, ((unsigned long)addr_ptr & 0x01FE0000) >> 17);  // A17..A24        if (flash_dev_info->device_size > 0x02000000) {            put_NAND(ROM, ((unsigned long)addr_ptr & 0x06000000) >> 25);  // A26..A27        }        CYGHWR_FLASH_TC58XXX_ALE(0);#if FLASH_DEBUG > 1        diag_printf(">>\n");#endif        // Move one page of data to buffer        for (i = 0;  i < 512;  i++) {            put_NAND(ROM, *data_ptr++);#if FLASH_DEBUG > 1            if ((i % 16) == 15) diag_printf("\n");#endif        }        // OOB data        for (i = 0;  i < 16;  i++) {            put_NAND(ROM, 0xFF);#if FLASH_DEBUG > 1            if ((i % 16) == 15) diag_printf("\n");#endif        }#if FLASH_DEBUG > 1        diag_printf("<< ");#endif        CYGHWR_FLASH_TC58XXX_CLE(1);        put_NAND(ROM, FLASH_Program);        CYGHWR_FLASH_TC58XXX_CLE(0);        CYGACC_CALL_IF_DELAY_US(1);  // Actually 200ns        cnt = 0;        while (!CYGHWR_FLASH_TC58XXX_RDY()) cnt++;  // Wait for page data to be ready        CYGHWR_FLASH_TC58XXX_CLE(1);        put_NAND(ROM, FLASH_Status);        CYGHWR_FLASH_TC58XXX_CLE(0);        #if FLASH_DEBUG > 1        diag_printf(">>\n");#endif        stat = *ROM;        CYGHWR_FLASH_TC58XXX_CE(0);        #if FLASH_DEBUG > 0        diag_printf("program at %x, stat: %x, count = %d\n", addr_ptr, stat, cnt);#endif        addr_ptr += 512;  len -= 512;    }    return res;}//----------------------------------------------------------------------------// Read data into bufferintflash_read_buf(void* addr, void* data, int len){    volatile flash_data_t* ROM;    volatile flash_data_t  dummy;    volatile flash_data_t* addr_ptr = (volatile flash_data_t*) addr;    volatile flash_data_t* data_ptr = (volatile flash_data_t*) data;    int res = FLASH_ERR_OK;    int i;    int cnt;    ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE;#if FLASH_DEBUG > 1    diag_printf("<< ");#endif    CYGHWR_FLASH_TC58XXX_CE(1);    CYGHWR_FLASH_TC58XXX_CLE(1);    if (((unsigned long)addr & 0x100) == 0) {        // Mode 1 - reads from start of line        put_NAND(ROM, FLASH_Read_Mode1);    } else {        // Mode 2 - reads from second half of line        put_NAND(ROM, FLASH_Read_Mode2);    }    CYGHWR_FLASH_TC58XXX_CLE(0);    CYGHWR_FLASH_TC58XXX_ALE(1);    put_NAND(ROM, ((unsigned long)addr_ptr & 0x000000FF) >> 0);   // A0..A7    put_NAND(ROM, ((unsigned long)addr_ptr & 0x0001FE00) >> 9);   // A9..A16    put_NAND(ROM, ((unsigned long)addr_ptr & 0x01FE0000) >> 17);  // A17..A24    if (flash_dev_info->device_size > 0x02000000) {        put_NAND(ROM, ((unsigned long)addr_ptr & 0x06000000) >> 25);  // A26..A27    }    CYGHWR_FLASH_TC58XXX_ALE(0);#if FLASH_DEBUG > 1    diag_printf(">>\n");#endif    cnt = 0;    while (!CYGHWR_FLASH_TC58XXX_RDY()) cnt++;  // Wait for page data to be ready #if FLASH_DEBUG > 0    diag_printf("Read data starting at %p, count = %d\n", data_ptr, cnt);#endif    while (len-- > 0) {        *data_ptr++ = *ROM;        if (((unsigned long)data_ptr & 0x1FF) == 0) {            // Data page has been read, skip over ECC/OOB data            for (i = 0;  i < 16;  i++) {                dummy = *ROM;            }            cnt = 0;            while (!CYGHWR_FLASH_TC58XXX_RDY()) cnt++;  // Wait for page data to be ready#if FLASH_DEBUG > 0            diag_printf("Read data starting at %p, count = %d\n", data_ptr, cnt);#endif        }    }    CYGHWR_FLASH_TC58XXX_CE(0);    return res;}#endif // CYGONCE_DEVS_FLASH_TOSHIBA_TC58XXX_INL// EOF flash_tc58xxx.inl

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?