Example #1
0
int flash_write_buf(WORD sector, int offset, byte *buffer, int numbytes)
{
    int ret = -1;
    int i;
    unsigned char *p = flash_get_memptr(sector) + offset;

    /* After writing the flash block, compare the contents to the source
     * buffer.  Try to write the sector successfully up to three times.
     */
   //Pan.Liu 
   //1. Erase flash
   //2. program flash
   //3. Verify 
    for( i = 0; i < 3; i++ ) {
	ret = flash_write(sector, offset, buffer, numbytes);
        if( !memcmp( p, buffer, numbytes ) )
            break;
        
	#ifdef DEBUGMSG	 //Pan.liu for debuging 
	printk("****Erase flash and rewrite again!****\n");
	printk("Error sector number:%d offset:%x ptr:%x\n",sector,offset,p);
	flash_sector_erase_int(sector);
        #endif
        ret = -1;
    }

    if( ret == -1 )
        printk( "Flash write error.  Verify failed\n" );

    return( ret );
}
unsigned long kerSysReadFromFlash( void *toaddr, unsigned long fromaddr,
    unsigned long len )
{
    int sect = flash_get_blk((int) fromaddr);
    unsigned char *start = flash_get_memptr(sect);
    flash_read_buf( sect, (int) fromaddr - (int) start, toaddr, len );

    return( len );
}
Example #3
0
int flash_read_buf(WORD sector, int offset,
                        byte *buffer, int numbytes)
{
    byte *fwp;
    fwp = (byte *)flash_get_memptr(sector); 
	while (numbytes) {
		*buffer++ = *(fwp + offset);
		numbytes--;
		fwp++;
    }

    return (1);
}
Example #4
0
static UINT16 flash_get_device_id()
{
    volatile UINT16 *fwp; /* flash window */
    UINT16 answer;
    
    fwp = (UINT16 *)flash_get_memptr(0);
    
    flash_command(FLASH_READ_ID, 0, 0, 0);
    answer = *(fwp + 1);
    if (answer == ID_AM29LV320M) {
        answer = *(fwp + 0xe);
        answer = *(fwp + 0xf);
    }
    
    flash_command(FLASH_RESET, 0, 0, 0);
    return( (UINT16) answer );
}
Example #5
0
static int flash_get_cfi(struct cfi_query *query, UINT16 *cfi_struct, int flashFamily)
{
    volatile UINT16 *fwp; /* flash window */
    int i=0,temp=0;

    flash_command(FLASH_CFIQUERY, 0, 0, 0);
    
    if (cfi_struct == 0)
        fwp = (UINT16 *)flash_get_memptr(0);
    else
        fwp = cfi_struct;
    
    /* Initial house-cleaning */
    for(i=0; i < 8; i++) {
        query->erase_block[i].sector_size = 0;
        query->erase_block[i].num_sectors = 0;
    }
    
    /* If not 'QRY', then we dont have a CFI enabled device in the socket */
    if( fwp[0x10] != 'Q' &&
        fwp[0x11] != 'R' &&
        fwp[0x12] != 'Y') {
        flash_command(FLASH_RESET, 0, 0, 0);
        return(-1);
    }
    temp = fwp[0x27];
    query->device_size = (int) (((int)1) << temp);


	query->num_erase_blocks = fwp[0x2C];
	if(flashFamily == FLASH_SST)
		query->num_erase_blocks = 1;
	
    for(i=0; i < query->num_erase_blocks; i++) {
			query->erase_block[i].num_sectors = fwp[(0x2D+(4*i))] + (fwp[0x2E + (4*i)] << 8);
			query->erase_block[i].num_sectors++;
			query->erase_block[i].sector_size = 256 * (256 * fwp[(0x30+(4*i))] + fwp[(0x2F+(4*i))]);
    }
    
    flash_command(FLASH_RESET, 0, 0, 0);
    return(1);
}
Example #6
0
//MXIC flash only 
//for polling erase operation
static int flash_wait_erase(WORD sector, int offset, UINT16 data)
{
    volatile UINT16 *flashptr; /* flash window */
    UINT16 d1;

    flashptr = (UINT16 *) flash_get_memptr(sector);
        do {
        	while (!(*flashptr & 0x80));  // read DQ7 to see if it is one
		d1=*flashptr;
        	d1 ^= *flashptr;
		if(d1==0)                  
		  return STATUS_READY;
	  }while(!(d1 & 0x20));                //time out DQ5

        d1 = *flashptr;        /* read data */
        d1 ^= *flashptr;   /* read it again and see what toggled */
        if (d1 != 0)
            flash_command(FLASH_RESET, 0, 0, 0);
	return STATUS_TIMEOUT;
}
Example #7
0
void flash_init_info(const NVRAM_DATA *nvRam, FLASH_ADDR_INFO *fInfo)
{
    int i = 0;
    int totalBlks = 0;
    int totalSize = 0;
    int auxFsSize = 0;
    int psiStartAddr = 0;
    int spStartAddr = 0;
    int usedBlkSize = 0;
    int needBytes = 0;
    int sBlk, eBlk;
    int blkSize, sectSize;	/* Size of all blocks in a partition or 0 */
    int totalPartSize;			/* Size in bytes for a partition */
    unsigned long  offset;   	/* Offset calulations */

    if (flash_get_flash_type() == FLASH_IFC_NAND)
    {
        /* When using NAND flash disable Bcm_flash */
        totalSize = 0;
    }
    else {
        totalBlks = flash_get_numsectors();
        totalSize = flash_get_total_size();
        printk("Total Flash size: %dK with %d sectors\n", totalSize/1024, totalBlks);
    }

    if (totalSize <= FLASH_LENGTH_BOOT_ROM) {
        /* NAND flash settings. NAND flash does not use raw flash partitioins
         * to store psi, backup psi, scratch pad and syslog.  These data items
         * are stored as files on a JFFS2 file system.
         */
        if ((nvRam->ulPsiSize != -1) && (nvRam->ulPsiSize != 0))
            fInfo->flash_persistent_length = nvRam->ulPsiSize * ONEK;
        else
            fInfo->flash_persistent_length = DEFAULT_PSI_SIZE * ONEK;

        fInfo->flash_persistent_start_blk = 0;
        fInfo->flash_rootfs_start_offset = 0;
        fInfo->flash_scratch_pad_length = SP_MAX_LEN;
        fInfo->flash_syslog_length = nvRam->ulSyslogSize * 1024;

        /* This is a boolean field for NAND flash. */
        fInfo->flash_backup_psi_number_blk = nvRam->backupPsi;
        return;
    }

    /*
    * calculate mandatory primary PSI size and set its fInfo parameters.
    */
    if ((nvRam->ulPsiSize != -1) && (nvRam->ulPsiSize != 0))
        fInfo->flash_persistent_length = nvRam->ulPsiSize * ONEK;
    else
        fInfo->flash_persistent_length = DEFAULT_PSI_SIZE * ONEK;

    psiStartAddr = totalSize - fInfo->flash_persistent_length;
    fInfo->flash_persistent_start_blk = flash_get_blk(FLASH_BASE+psiStartAddr);
    fInfo->flash_persistent_number_blk = totalBlks - fInfo->flash_persistent_start_blk;

    usedBlkSize = 0;
    for (i = fInfo->flash_persistent_start_blk; 
        i < (fInfo->flash_persistent_start_blk + fInfo->flash_persistent_number_blk); i++)
    {
        usedBlkSize += flash_get_sector_size((unsigned short) i);
    }
    fInfo->flash_persistent_blk_offset =  usedBlkSize - fInfo->flash_persistent_length;
    fInfo->flash_meta_start_blk = fInfo->flash_persistent_start_blk;

    /*
    * Next is the optional scratch pad, which is on top of the primary PSI.
    * Old code allowed scratch pad to share a sector with primary PSI.
    * That is retained for backward compatibility.  (Although depending on your
    * NOR flash sector sizes, they may still be in different sectors.)
    * If you have a new deployment, consider forcing separate sectors.
    */
    if ((fInfo->flash_persistent_blk_offset > 0) &&
        (fInfo->flash_persistent_blk_offset < SP_MAX_LEN))
    {
        /*
        * there is some room left in the first persistent sector, but it is
        * not big enough for the scratch pad. (Use this line unconditionally
        * if you want to guarentee scratch pad and primary PSI are on different
        * sectors.)
        */
        spStartAddr = psiStartAddr - fInfo->flash_persistent_blk_offset - SP_MAX_LEN;
    }
    else
    {
        /* either the primary PSI starts on a sector boundary, or there is
        * enough room at the top of the first sector for the scratch pad. */
        spStartAddr = psiStartAddr - SP_MAX_LEN ;
    }

    fInfo->flash_scratch_pad_start_blk = flash_get_blk(FLASH_BASE+spStartAddr);
    fInfo->flash_scratch_pad_length = SP_MAX_LEN;

    if (fInfo->flash_persistent_start_blk == fInfo->flash_scratch_pad_start_blk)  // share blk
    {
#if 0 /* do not used scratch pad unless it's in its own sector */
        printk("Scratch pad is not used for this flash part.\n");  
        fInfo->flash_scratch_pad_length = 0;     // no sp
#else /* allow scratch pad to share a sector with another section such as PSI */
        fInfo->flash_scratch_pad_number_blk = 1;
        fInfo->flash_scratch_pad_blk_offset = fInfo->flash_persistent_blk_offset - fInfo->flash_scratch_pad_length;
#endif
    }
    else // on different blk
    {
        fInfo->flash_scratch_pad_number_blk = fInfo->flash_persistent_start_blk - fInfo->flash_scratch_pad_start_blk;
        // find out the offset in the start_blk
        usedBlkSize = 0;
        for (i = fInfo->flash_scratch_pad_start_blk; 
            i < (fInfo->flash_scratch_pad_start_blk + fInfo->flash_scratch_pad_number_blk); i++)
            usedBlkSize += flash_get_sector_size((unsigned short) i);
        fInfo->flash_scratch_pad_blk_offset =  usedBlkSize - fInfo->flash_scratch_pad_length;
    }

    if (fInfo->flash_scratch_pad_length > 0) {

        fInfo->flash_meta_start_blk = fInfo->flash_scratch_pad_start_blk;
    }

    /*
    * Next is the optional backup PSI.
    */
    if (nvRam->backupPsi == 0x01)
    {
        needBytes = fInfo->flash_persistent_length;
        i = fInfo->flash_meta_start_blk;
        while (needBytes > 0)
        {
            i--;
            needBytes -= flash_get_sector_size((unsigned short) i);
        }
        fInfo->flash_backup_psi_start_blk = i;
        /* calclate how many blocks we actually consumed */
        needBytes = fInfo->flash_persistent_length;
        fInfo->flash_backup_psi_number_blk = 0;
        while (needBytes > 0)
        {
            needBytes -= flash_get_sector_size((unsigned short) i);
            i++;
            fInfo->flash_backup_psi_number_blk++;
        }

        fInfo->flash_meta_start_blk = fInfo->flash_backup_psi_start_blk;
    }
    else
    {
        fInfo->flash_backup_psi_number_blk = 0;
    }

    /*
    * Next is the optional persistent syslog.
    */
    if (nvRam->ulSyslogSize != 0 && nvRam->ulSyslogSize != -1)
    {
        fInfo->flash_syslog_length = nvRam->ulSyslogSize * 1024;
        needBytes = fInfo->flash_syslog_length;
        i = fInfo->flash_meta_start_blk;
        while (needBytes > 0)
        {
            i--;
            needBytes -= flash_get_sector_size((unsigned short) i);
        }
        fInfo->flash_syslog_start_blk = i;
        /* calclate how many blocks we actually consumed */
        needBytes = fInfo->flash_syslog_length;
        fInfo->flash_syslog_number_blk = 0;
        while (needBytes > 0)
        {
            needBytes -= flash_get_sector_size((unsigned short) i);
            i++;
            fInfo->flash_syslog_number_blk++;
        }

        fInfo->flash_meta_start_blk = fInfo->flash_syslog_start_blk;
    }
    else
    {
        fInfo->flash_syslog_length = 0;
        fInfo->flash_syslog_number_blk = 0;
    }

#if 1   //for AUXFS 

   if ( (nvRam->ucAuxFSPercent != 0)
    && (nvRam->ucAuxFSPercent <= MAX_AUXFS_PERCENT))
    {
        /* Estimate the Auxillary File System size */
        auxFsSize = (totalSize * (int)nvRam->ucAuxFSPercent)/100;
        
        /* JFFS_AUXFS offset */
        offset = totalSize - auxFsSize - flash_get_reserved_bytes_at_end(fInfo);
		
        sBlk = flash_get_blk(offset+FLASH_BASE);
	  eBlk = fInfo->flash_meta_start_blk;

	  /*
         * Implementation Note:
         * Ensure that we have even number of blocks for
         * ROOTFS+KERNEL to support dual image booting
        */
        if ( ( (sBlk+1) < eBlk)
          && ((((sBlk+1) - flash_get_blk(fInfo->flash_rootfs_start_offset + FLASH_BASE)) % 2) == 0))
        {
            sBlk += 1;	/* Round up */
        }

        blkSize = flash_get_sector_size(sBlk);
        for ( i=sBlk+1, totalPartSize = blkSize; i<eBlk; i++)
        {
            sectSize = flash_get_sector_size(i);
            //if ( blkSize != sectSize ) blkSize = 0;
            if ( blkSize != sectSize ) break;
            totalPartSize += sectSize;
        }
        fAuxFsInfo.sect_size = blkSize;
        auxFsSize = totalPartSize;


        printk("Flash split %d : AuxFS[%d]\n",
               (int)nvRam->ucAuxFSPercent,auxFsSize );
    }
    else
    {
	/*
	 * Implementation Note: When there is no AuxFS Partition.
	 * Total number of rootfs/kernel blocks will always be ODD.
	 * Option: Increase RESERVED section ??? but this would
	 * decrease the space available for a single kernel image
	 */
        sBlk = eBlk = 0;
        fAuxFsInfo.sect_size = 0;
        auxFsSize = 0;
        printk("Flash not used for Auxillary File System\n");
     }


	/*------------*/
	/* JFFS_AUXFS */
	/*------------*/

    sprintf(fAuxFsInfo.name, "JFFS_AUXFS");
    fAuxFsInfo.start_blk = sBlk;
    fAuxFsInfo.number_blk = eBlk - sBlk;
    fAuxFsInfo.blk_offset = 0;
    fAuxFsInfo.total_len = auxFsSize;
    fAuxFsInfo.mem_base = (unsigned long) flash_get_memptr( sBlk )
                                   +  fAuxFsInfo.blk_offset;
    fAuxFsInfo.mem_length = auxFsSize;
    
#endif

#ifdef DEBUG_FLASH_TOO_MUCH
    /* dump sizes of all sectors in flash */
    for (i=0; i<totalBlks; i++)
        printk("blk %03d: %d\n", i, flash_get_sector_size((unsigned short) i));
#endif

#if defined(DEBUG_FLASH)
    printk("FLASH_BASE                    =0x%08x\n\n", (unsigned int)FLASH_BASE);

    printk("fInfo->flash_rootfs_start_offset =0x%08x\n\n", (unsigned int)fInfo->flash_rootfs_start_offset);

    printk("fInfo->flash_meta_start_blk = %d\n\n", fInfo->flash_meta_start_blk);

    printk("fInfo->flash_syslog_start_blk  = %d\n", fInfo->flash_syslog_start_blk);
    printk("fInfo->flash_syslog_number_blk = %d\n", fInfo->flash_syslog_number_blk);
    printk("fInfo->flash_syslog_length=0x%x\n\n", (unsigned int)fInfo->flash_syslog_length);

    printk("fInfo->flash_backup_psi_start_blk = %d\n", fInfo->flash_backup_psi_start_blk);
    printk("fInfo->flash_backup_psi_number_blk = %d\n\n", fInfo->flash_backup_psi_number_blk);

    printk("sp startAddr = %x\n", (unsigned int) (FLASH_BASE+spStartAddr));
    printk("fInfo->flash_scratch_pad_start_blk = %d\n", fInfo->flash_scratch_pad_start_blk);
    printk("fInfo->flash_scratch_pad_number_blk = %d\n", fInfo->flash_scratch_pad_number_blk);
    printk("fInfo->flash_scratch_pad_length = 0x%x\n", fInfo->flash_scratch_pad_length);
    printk("fInfo->flash_scratch_pad_blk_offset = 0x%x\n\n", (unsigned int)fInfo->flash_scratch_pad_blk_offset);

    printk("psi startAddr = %x\n", (unsigned int) (FLASH_BASE+psiStartAddr));
    printk("fInfo->flash_persistent_start_blk = %d\n", fInfo->flash_persistent_start_blk);
    printk("fInfo->flash_persistent_number_blk = %d\n", fInfo->flash_persistent_number_blk);
    printk("fInfo->flash_persistent_length=0x%x\n", (unsigned int)fInfo->flash_persistent_length);
    printk("fInfo->flash_persistent_blk_offset = 0x%x\n\n", (unsigned int)fInfo->flash_persistent_blk_offset);
    printk("AuxFs.start_blk = %d\n",fAuxFsInfo.start_blk );
    printk("AuxFs,number_blk = %d\n", fAuxFsInfo.number_blk);
    printk("AuxFs.total_len = 0x%x\n",fAuxFsInfo.total_len);
    printk("AuxFs.sect_size = 0x%x\n",fAuxFsInfo.sect_size);
#endif
}
Example #8
0
static int flash_wait(WORD sector, int offset, UINT16 data)
{
    volatile UINT16 *flashptr; /* flash window */
    UINT16 d1,d2;
    UINT16 var=0x20;
    
    flashptr = (UINT16 *) flash_get_memptr(sector);
   if ( flashFamily == FLASH_SST)
   	var=0x40;

    if (flashFamily == FLASH_AMD || flashFamily == FLASH_SST || flashFamily==FLASH_MXIC) {
   #if defined(_BCM96338_) || defined(CONFIG_BCM96338)
            /* If the word written does not yet compare, try for another 100ms.
             * This check is done for SST39VF800A.
	     */
      if(flashFamily == FLASH_SST){
        /* If the word written does not yet compare, try for another 100ms.
         * This check is done for SST39VF800A.
         */
          int i;
            for( i = 0; i < 10000; i++ ) {
                d1 = flashptr[offset/2];
                if (d1 == data)
                    return STATUS_READY;
                udelay(10);//CFI_USLEEP(10);
            }

        d1 = flashptr[offset/2];
        if (d1 != data) {
            flash_command(FLASH_RESET, 0, 0, 0);
            return STATUS_TIMEOUT;
        }
     }
     else {
	   do {
            d1 = flashptr[offset/2];
            if (d1 == data)
                return STATUS_READY;
        } while (!(d1 & 0x20));

        d1 = flashptr[offset/2];

	}

#else
if(flashFamily == FLASH_SST)
{
        // timeout error
	/* If the word written does not yet compare, try for another 100ms.
         * This check is done for SST39VF800A.
         */
 	  DWORD i,cycles;
	  if(flashPrg==0)
		cycles=357143;
	  else
		cycles=143;
            for( i = 0; i < cycles; i++ ) {
                d1 = flashptr[offset/2];
                if (d1 == data)
                {
		    Delay_1_Micro_Seconds();		    
                    return STATUS_READY;
                }
            }

        d1 = flashptr[offset/2];
        if (d1 != data) {
            flash_command(FLASH_RESET, 0, 0, 0);
            return STATUS_TIMEOUT;
        }
}
else if(flashFamily==FLASH_AMD)
{
	do {
            d1 = *flashptr;    /* read data */
            d1 ^= *flashptr;   /* read it again and see what toggled */
            if (d1 == 0)       /* no toggles, nothing's happening */
                return STATUS_READY;
        } while (!(d1 & 0x20));

        d1 = *flashptr;        /* read data */
        d1 ^= *flashptr;   /* read it again and see what toggled */

        if (d1 != 0) {
            flash_command(FLASH_RESET, 0, 0, 0);
            return STATUS_TIMEOUT;
        }

}
else if(flashFamily == FLASH_MXIC)
{
	do { 
	      d2 = *flashptr;
	      d2 ^= *flashptr;
	     if(d2==0)	           // see what toggle
	     {
              d1 = flashptr[offset/2];  //compare with input data if the same then output status ready signal
	      if(d1==data)
               	  return STATUS_READY;
	     }
        } while (!(*flashptr & 0x20));
       
       d1 = flashptr[offset/2];
        if (d1 != data) {
            flash_command(FLASH_RESET, 0, 0, 0);
            return STATUS_TIMEOUT;
        }
}
#endif
    } else if (flashFamily == FLASH_INTEL) {
        flashptr[0] = 0x70;
        /* Wait for completion */
        while(!(*flashptr & 0x80));
        if (*flashptr & 0x30) {
            flashptr[0] = 0x50;
            flash_command(FLASH_RESET, 0, 0, 0);
            return STATUS_TIMEOUT;
        }
        flashptr[0] = 0x50;
        flash_command(FLASH_RESET, 0, 0, 0);
    }
    
    return STATUS_READY;
}
Example #9
0
static void flash_command(int command, WORD sector, int offset, UINT16 data)
{
    volatile UINT16 *flashptr;
    volatile UINT16 *flashbase;

    flashptr = (UINT16 *) flash_get_memptr(sector);
    flashbase = (UINT16 *) flash_get_memptr(0);
    
    switch (flashFamily) {
    case FLASH_UNDEFINED:
        /* These commands should work for AMD, Intel and SST flashes */
        switch (command) {
        case FLASH_RESET:
            flashptr[0] = 0xF0;
            flashptr[0] = 0xFF;
            break;
        case FLASH_READ_ID:
	    flashptr[0x5555] = 0xAA;       /* unlock 1 */
            flashptr[0x2AAA] = 0x55;       /* unlock 2 */
            flashptr[0x5555] = 0x90;
            break;
	case FLASH_CFIQUERY:
            flashbase[0x5555] = 0xAA;       /* unlock 1 */
            flashbase[0x2AAA] = 0x55;       /* unlock 2 */
            flashbase[0x5555] = 0x90;
            break;
        default:
            break;
        }
        break;
    case FLASH_AMD:   //Pan.Liu AMD and MXIC share the same flash command
    case FLASH_MXIC:
        switch (command) {
        case FLASH_RESET:
            flashptr[0] = 0xF0;
            break;
        case FLASH_READ_ID:
            flashptr[0x555] = 0xAA;       /* unlock 1 */
            flashptr[0x2AA] = 0x55;       /* unlock 2 */
            flashptr[0x555] = 0x90;
            break;
        case FLASH_CFIQUERY:
            flashptr[0x55] = 0x98;
            break;
        case FLASH_UB:
            flashptr[0x555] = 0xAA;       /* unlock 1 */
            flashptr[0x2AA] = 0x55;       /* unlock 2 */
            flashptr[0x555] = 0x20;
            break;
        case FLASH_PROG:
            flashptr[0] = 0xA0;
            flashptr[offset/2] = data;
            break;
        case FLASH_UBRESET:
            flashptr[0] = 0x90;
            flashptr[0] = 0x00;
            break;
        case FLASH_SERASE:
            flashptr[0x555] = 0xAA;       /* unlock 1 */
            flashptr[0x2AA] = 0x55;       /* unlock 2 */
            flashptr[0x555] = 0x80;
            flashptr[0x555] = 0xAA;
            flashptr[0x2AA] = 0x55;
            flashptr[0] = 0x30;
            break;
        default:
            break;
        }
        break;
    case FLASH_INTEL:
        switch (command) {
        case FLASH_RESET:
            flashptr[0] = 0xFF;
            break;
        case FLASH_READ_ID:
            flashptr[0] = 0x90;
            break;
        case FLASH_CFIQUERY:
            flashptr[0] = 0x98;
            break;
        case FLASH_PROG:
            flashptr[0] = 0x40;
            flashptr[offset/2] = data;
            break;
        case FLASH_SERASE:
            flashptr[0] = 0x60;
            flashptr[0] = 0xD0;
            flashptr[0] = 0x20;
            flashptr[0] = 0xD0;
            break;
        default:
            break;
        }
        break;
    case FLASH_SST:
        switch (command) {
        case FLASH_RESET:
            flashbase[0x5555] = 0xAA;       /* unlock 1 */
            flashbase[0x2AAA] = 0x55;       /* unlock 2 */
            flashbase[0x5555] = 0xf0;
	    break;
        case FLASH_READ_ID:
            flashbase[0x5555] = 0xAA;       /* unlock 1 */
            flashbase[0x2AAA] = 0x55;       /* unlock 2 */
            flashbase[0x5555] = 0x90;
            break;
        case FLASH_CFIQUERY:
            flashbase[0x5555] = 0xAA;       /* unlock 1 */
            flashbase[0x2AAA] = 0x55;       /* unlock 2 */
            flashbase[0x5555] = 0x98;
            break;
        case FLASH_UB:
            break;
        case FLASH_PROG:
            flashbase[0x5555] = 0xAA;       /* unlock 1 */
            flashbase[0x2AAA] = 0x55;       /* unlock 2 */
            flashbase[0x5555] = 0xa0;
            flashptr[offset/2] = data;
	    flashPrg=1;
            break; 
        case FLASH_UBRESET:
            break;
        case FLASH_SERASE:
            flashbase[0x5555] = 0xAA;       /* unlock 1 */
            flashbase[0x2AAA] = 0x55;       /* unlock 2 */
            flashbase[0x5555] = 0x80;
            flashbase[0x5555] = 0xAA;
            flashbase[0x2AAA] = 0x55;
            flashptr[0] = 0x30;
	    flashPrg=0;
	    break;
        default:
            break;
        }
        break;
    default:
        break;
    }
}