/* SPIFI device-init for Eon serial flashes 
   called by spifi_rom_init when JEDEC ID shows Eon manufacturer code
   Copyright (C) NXP Seiconductors 2010 
   
   this file covers the following devices, though it may not 
     have been tested with all of them:
   EN25F05, EN25Q40, EN25F80, EN25Q80A, EN25F16, EN25F32, EN25Q32A/B, 
   EN25P64, EN25Q64, EN25Q128 */
 
#include "lpc43xx_spifi.h"
#include "spifi_sys_config.h"
#include "mfgers.h"
#include "error.h"
 
int eon (SPIFIobj *obj, unsigned options, unsigned unused) {
        uc type = obj->devType, id = obj->devID;
        if (type != 0x20
        && (type &  0xBE) != 0x30
         && type != 0x38) return ERR_SPIFI_UNKNOWN_TYPE;
 
        if (id < 0x10
         || id > 0x18) return ERR_SPIFI_UNKNOWN_ID;
                                
        if (id <= 0x11) obj->erase_shifts[2] = 15; /* 32KB sectors */
        else if (type == 0x20
              && id   == 0x17) {                /* no 4KB sectors */
                obj->erase_shifts[0] = 16;
                obj->erase_ops[0] = CMD_ERASE_64K;
                obj->erase_shifts[2] = 0;
        }
        setSize(obj, id-1);
        if (id   == 0x16 
         || type == 0x30 && id >= 0x16
         || type == 0x70) {
                obj->write_prot = 0x3C;
                obj->set_prot   = 0xBC;
        }
        if ((type & 0xBF) == 0x30) {
                unsigned opts, read, prog = obj->prog_cmd;
                obj->set_prot = obj->write_prot | 0xC0;  // SRP, WPDIS
 
                if (options & S_DUAL) {
                        opts = OPT_DUAL | OPT_PROT_STAT;
                        /* Eon Dual I/O doesn't have no-opcode--v */
                        read = CMD_READ_DUAL_IO<<OPCODE_SHIFT | 4<<FRAMEFORM_SHIFT
                             | 1<<INTLEN_SHIFT | 2<<PS_SHIFT | UNL_DATA;
                } else {
                        opts = OPT_SEND_38 | OPT_PROT_STAT;
                        read = CMD_READ_QUAD_IO<<OPCODE_SHIFT | 6<<FRAMEFORM_SHIFT
                             | 3<<INTLEN_SHIFT | 3<<PS_SHIFT | UNL_DATA;
                        prog |= PS_MASK;
                } /* all quad have no-opcode-----v----mode */
                return setDev(obj, opts, read, prog);
        }
        return 0;
}
