/* Spansion device-init handler for spifi_rom_api 
   Copyright (C) by NXP Semiconductors 2010-11
   
   This file covers the following devices, although it 
   has not been tested with all of them:
   25FL040, 25FL008, 25FL016, 25FL032, 25FL064, 25FL128P, 25FL129P
    
   "Spansion" parts 25FLnnnK return Winbond JEDEC IDs */
 
#include "lpc43xx_spifi.h"
#include "spifi_sys_config.h"
/* spifi_sys_config.h includes "spifi.h" */
#include "mfgers.h"
#include "error.h"
 
int span (SPIFIobj *obj, unsigned options, unsigned unused) {
        uc type = obj->devType, id = obj->devID, b4;
        /* one uniform sector-erase command */
        obj->erase_ops[0] = CMD_ERASE_64K;
        /* most have 64KB erase sector */
        obj->erase_shifts[0] = 16;
        obj->erase_shifts[2] = 0;
 
        if (type == 2) {
                if (id >= 0x12
                 && id <= 0x14) {
                        /* 12 (25FL040) thru 14 (25FL016) are SPI, NR new designs */
                } else if (id >= 0x15
                        && id <= 0x16) {
                        /* 25FL032, 25FL064 */
                        /* errCK: read op   errbits   clear op */
                        obj->errCheck = 5 | 0x60<<8 | CMD_CLEAR_ERR_SPAN<<16;
                } else return ERR_SPIFI_UNKNOWN_ID;
                setSize(obj, id);
 
        } else if (type == 0x20) {
                if (id == 0x18) {  /* 1 higher than for type = 2 */
                        /* we need 4th and 5th byte of ID for 25FL128/129 */
                        switch (b4 = read04(obj, CMD_RD_JEDEC_ID, 5) >> 24) {
                                                   /* errCK: read op   errbits   clear op */
                                case 0x4D: obj->errCheck = 5 | 0x60<<8 | CMD_CLEAR_ERR_SPAN<<16;
                                case 3: break;
                                default: return ERR_SPIFI_UNKNOWN_EXT;
                        }
                        /* 64KB or 256KB sector size */
                        switch (SPIFI_DATA_BYTE) {
                                case 0: obj->erase_shifts[0] = 18;
                                                break;
                                case 1:            /* 4 prot bits in status */
                                                if (b4 == 3) obj->write_prot = 0x3C;
                                                break;
                                default: return ERR_SPIFI_UNKNOWN_EXT;
                        }
                        setSize(obj, id-1);
                } else return ERR_SPIFI_UNKNOWN_ID;
        } else return ERR_SPIFI_UNKNOWN_TYPE;
        /* error checking devices are quad and have more protection options */
        if (obj->errCheck) {
                unsigned opts, read, prog;
                /* 4 bits in config are settable */
                obj->set_prot = 0x2D80 | obj->write_prot;
                if (options & S_DUAL) {
                        opts = OPT_DUAL | OPT_PROT_STAT;
                        read = CMD_READ_DUAL_IO<<OPCODE_SHIFT | 6<<FRAMEFORM_SHIFT
                                 | 1<<INTLEN_SHIFT | 2<<PS_SHIFT | UNL_DATA;
                        prog = obj-> prog_cmd;
                } else {
                        opts = OPT_35_OR02_01 | OPT_PROT_STAT;
                        read = CMD_READ_QUAD_IO<<OPCODE_SHIFT | 6<<FRAMEFORM_SHIFT
                                 | 3<<INTLEN_SHIFT | 2<<PS_SHIFT | UNL_DATA;
                        prog = CMD_PROG_QUAD<<OPCODE_SHIFT | 4<<FRAMEFORM_SHIFT | 1<<PS_SHIFT | DOUT;
                }
                return setDev(obj, opts, read, prog);
        }
        return 0;
}
