#ifndef STW_FLASH_H
#define STW_FLASH_H


/*
  Copyright (C) 2003  Chin Zhou (czhou@ati.com), ATI 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; version 2
  of the License, June 1991.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, 
  MA  02111-1307, USA.
*/


/************************************************************************/

#define SAMSUNG_ID          0xEC
#define SAMSUNG_K9F6408Q0C  0x39
#define SAMSUNG_K9F6408U0C  0xE6
#define SAMSUNG_K9F6408U0B  0xE6
#define SAMSUNG_K9F2808Q0C  0x33
#define SAMSUNG_K9F2808U0C  0x73
#define SAMSUNG_K9F2816Q0C  0x43
#define SAMSUNG_K9F2816U0C  0x53
#define SAMSUNG_K9F2808Q0B  0x33
#define SAMSUNG_K9F2808U0B  0x73
#define SAMSUNG_K9F5608Q0B  0x35
#define SAMSUNG_K9F5608U0B  0x75
#define SAMSUNG_K9F5616Q0B  0x45
#define SAMSUNG_K9F5616U0B  0x55
#define SAMSUNG_K9F5608U0A  0x75
#define SAMSUNG_K9F1208Q0A  0x36
#define SAMSUNG_K9F1208U0A  0x76
#define SAMSUNG_K9F1216Q0A  0x46
#define SAMSUNG_K9F1216U0A  0x56

#define TOSHIBA_ID          0x98
#define TOSHIBA_TC58V16BFT  0xEA
#define TOSHIBA_TC58V32AFT  0xE5
#define TOSHIBA_TC58V64AFT  0xE6
#define TOSHIBA_TC58V64BFT  0xE6
#define TOSHIBA_TC58128FT   0x73
#define TOSHIBA_TC58128AFT  0x73
#define TOSHIBA_TC58256FT   0x75
#define TOSHIBA_TC58256AFT  0x75
#define TOSHIBA_TH58512FT   0x76
#define TOSHIBA_TH58100FT   0x79

#define AMD_ID              0x01
#define AMD_AM30LV0064D     0xE6

#define PFLASH_CMD_TRIGGER_BLOCK_ERASE  0x1
#define PFLASH_CMD_TRIGGER_STATUS_RESET 0x2
#define PFLASH_CMD_TRIGGER_STATUS_READ  0x3
#define PFLASH_CMD_TRIGGER_ID_READ      0x4


#define SPARE_AREA_L256_ECC0_OFFSET     0x0
#define SPARE_AREA_L256_ECC1_OFFSET     0x1
#define SPARE_AREA_L256_ECC2_OFFSET     0x2
#define SPARE_AREA_U256_ECC0_OFFSET     0x3
#define SPARE_AREA_VALID_BLOCK_OFFSET   0x5
#define SPARE_AREA_U256_ECC1_OFFSET     0x6
#define SPARE_AREA_U256_ECC2_OFFSET     0x7

#define SPARE_AREA_VALID_BLOCK_VALUE    0xFF

#define PFLASH_PAGE_SIZE                0x200

#define STW_NAND_BLOCK_NUM_SHIFT        0x5
#define BLOCK_NUM_TOTAL_SHIFT           (STW_NAND_BLOCK_NUM_SHIFT + \
                                         PFLASH_BE_ADDR__BLOCK_ERASE_ADDR__SHIFT) 

#define STW_MAX_NUM_BLOCKS              0x400

#define PFLASH_NAND_CS1_OFFSET          0x01000000

#define PFLASH_VALID_BLOCK_VALUE        0xff
#define PFLASH_INVALID_BLOCK_VALUE      0xbd

#define PFF_ECC                         (1<<0)
#define PFF_ALLOW_MB                    (1<<30)
#define PFF_ALLOW_IBT                   (1<<31)

/* add invalid block table (IBT) feature */

#define IBT_GOOD_BLOCK          0x00000000
#define IBT_FACTORY_BAD_BLOCK   0x000000FF
#define IBT_DETECTED_BAD_BLOCK  0x0000FF00
#define IBT_TABLE_0_BLOCK       0x00FF0000
#define IBT_TABLE_1_BLOCK       0xFF000000
#define IBT_MONITOR_BOOT_BLOCK  0xFFFF0000

#define IBT_UNKNOWN_BLOCK       (-1)

#define MAKE_MAGIC(a,b,c,d) (((a)<<0)|((b)<<8)|((c)<<16)|((d)<<24))
#define MONITORBOOT_MAGIC   MAKE_MAGIC('M','O', 'N', '0')


#define PFLASH0_NUM              0
#define PFLASH1_NUM              1
#define SFLASH_NUM               2
#define PFLASH0_MASK             (1<<PFLASH0_NUM)
#define PFLASH1_MASK             (1<<PFLASH1_NUM)
#define SFLASH_MASK              (1<<SFLASH_NUM)


/************************************************************************/

enum
{
    PFLASH_CMD_BLOCK_ERASE=1,
    PFLASH_CMD_RESET=2,
    PFLASH_CMD_READ_STATUS=3,
    PFLASH_CMD_ID_READ =4,
};

typedef enum
{
    CS0,
    CS1,
    CS_INVALID
}
CHIP_SEL;

typedef enum
{
    SEC0,
    SEC1,
    SEC2,
    SEC3,
    OUT_OF_RANGE
}
SECTOR_NUM;

enum
{
    PFLASH_OK=0,
    PFLASH_NOT_FOUND,
    PFLASH_TIME_OUT,
    PFLASH_SEPROM_BUSY,
    PFLASH_CMD_TRIG_BUSY,
    PFLASH_ID_STAT_DATA_ERROR,
    PFLASH_STATUS_ERROR,
    PFLASH_BLOCK_ERASE_NOT_DONE,
    PFLASH_RESET_NOT_DONE,
    PFLASH_BLOCK_INVALID,
    PFLASH_VERIFY_FAILED,
    PFLASH_READY_BUSY_TRANSITION_MISSED,
    PFLASH_LAST_ERROR
};

typedef struct
{
  uint32_t magic;
  uint32_t checksum;         /* currently not used */
  uint32_t timestamp;
  uint32_t table[2048];
}
IBT_DATA;

/************************************************************************/

uint32_t pflash_get_block_numbers(void);
uint32_t pflash_get_page_numbers(void);
uint32_t pflash_get_block_size_in_bytes(void);
uint32_t pflash_get_chip_start_address(CHIP_SEL chipsel);
uint32_t pflash_get_block_start_address(CHIP_SEL chipsel, uint32_t block);
uint32_t pflash_get_chipID(CHIP_SEL chipsel, uint32_t timeout);

void dump_mtd_info (struct mtd_info *mtd);
void dump_nand_chip_info (struct nand_chip *this);

int pflash_init(void);
int pflash_block_erase(CHIP_SEL chipsel, uint32_t block, uint32_t timeout, uint32_t flags);
int pflash_block_eraseVerify(CHIP_SEL chipsel, uint32_t block);
int pflash_block_read(CHIP_SEL chipsel, uint32_t block, char *buffer, uint32_t flags);
int pflash_block_write(CHIP_SEL chipsel, uint32_t block, char *buffer, uint32_t flags);
int pflash_block_verify(CHIP_SEL chipsel, uint32_t block, char *buffer, uint32_t flags);
int pflash_page_read(CHIP_SEL chipsel, uint32_t block, uint32_t page, char *buffer, uint32_t flags);
int pflash_page_write(CHIP_SEL chipsel, uint32_t block, uint32_t page, char *buffer, uint32_t flags);
int pflash_wait_trigger(uint32_t counter);
int pflash_get_status(uint32_t timeout);
int pflash_clear_state_machine(uint32_t timeout);
int pflash_clear_state_machine_oob_enable(uint32_t timeout);
int pflash_get_chip_size(CHIP_SEL chipsel);
int pflash_get_spare8( uint32_t offset, uint8_t *data );
int pflash_set_spare8( uint32_t offset, uint32_t data );
char *pflash_get_chipID_string(CHIP_SEL chipsel);

int   pflash_block_invalid(CHIP_SEL chipsel, uint32_t block, uint32_t flags);
int   pflash_set_block_invalid(CHIP_SEL chipsel, uint32_t block);
int   pflash_set_autoexec(char *command, uint32_t *rblock);
char *pflash_get_autoexec(uint32_t *rblock);


/* added IBT access routines */

int pflash_is_block_factory_invalid(CHIP_SEL chipsel, uint32_t block);
int pflash_write_IBTs(void);
int pflash_write_IBT0(void);
int pflash_write_IBT1(void);
int pflash_read_IBT(void);
int pflash_find_IBT(void);

#endif /* STW_FLASH_H */



