/*****************************************************************************
 *   eeprom.c:  Flash Memory Controller C file for NXP LPC29xx Family 
 *   Microprocessors
 *
 *   Copyright(C) 2007, NXP Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2007.07.20  ver 1.00    Preliminary version, first Release
 *
 ****************************************************************************
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * products. This software is supplied "AS IS" without any warranties.
 * NXP Semiconductors assumes no responsibility or liability for the
 * use of the software, conveys no license or title under any patent,
 * copyright, or mask work right to the product. NXP Semiconductors
 * reserves the right to make changes in the software without
 * notification. NXP Semiconductors also make no representation or
 * warranty that such application will be suitable for the specified
 * use without further testing or modification.
 *****************************************************************************/

#include "LPC29xx.h"                        /* LPC29xx definitions */
#include "type.h"
#include "irq.h"
#include "target.h"
#include "eeprom.h"

DWORD or_mask[4] = {0x00000000, 0xFFFFFF00, 0xFFFF0000, 0xFF000000};

volatile DWORD eorw_flag = 0, eobs_flag = 0, eop1_flag = 0;

/*****************************************************************************
** Function name:		EEPROM_Handler
**
** Descriptions:		EEPROM handler for EEPROM Controller
**
** parameters:			None
** Returned value:		None
** 
*****************************************************************************/
void EEPROM_Handler(void)
{
  DWORD regVal;

  regVal = FMC_INT_STATUS;
  if ( regVal & EORW )		/* End of Erasing */
  {
  	eorw_flag++;
  	FMC_INT_CLR_STATUS = EORW;
  }
  if ( regVal & EOBS )		/* End of Burning */ 
  {
  	eobs_flag++;
  	FMC_INT_CLR_STATUS = EOBS;
  }
  if ( regVal & EOP1 )		/* Signature Generation */
  {
  	eop1_flag++;
  	FMC_INT_CLR_STATUS = EOP1;
  }
  return;
}

/*****************************************************************************
** Function name:		FMCInit
**
** Descriptions:		Initialize EEPROM controller(FMC)
**
** parameters:			None
** Returned value:		None
** 
*****************************************************************************/
void EEPROM_Init( void )
{
  EECLKDIV = CPU_CLK/375000;   // set clock divider to get 375kHz (spec. +/- 6.67%)
  
  EEWSTATE = (EE_PHASE1<<16)|(EE_PHASE2<<8)|(EE_PHASE3<<0);    // set the wait state time

#if EEPROM_INTERRUPT_ENABLED
  /* EEPROM driver can be made interrupt driven, but, in these simple
  test program, Erase and Programming are handled in the polling mode */
  install_irq( FLASH_INT, (void *)EEPROM_Handler, HIGHEST_PRIORITY );
  EnableIntReq_IRQ( FLASH_INT, ACTIVE_HIGH, HIGHEST_PRIORITY );
#endif
  FMC_INT_CLR_STATUS = EORW|EOBS|EOP1;	/* Clear EORW|EOBS|EOP1 */
  FMC_INT_SET_ENABLE = EORW|EOBS|EOP1;	/* Set EORW|EOBS|EOP1 */
  return;
}

/*****************************************************************************
** Function name:   EEPROM_WritePage
**
** Descriptions:    Write EEPROM page, the size is fixed, EEPROM_PAGE_SIZE 64 
**
** parameters:      The first parameter is the destination page [0-255],
**                  The second parameter is the pointer to the ssrc addr
**	            The third parameter is the size
**                  The fouth parameter is the write size (WRITE8, WRITE16, WRITE32)
** Returned value:  None
** 
*****************************************************************************/
void EEPROM_WritePage( BYTE pageWrite, DWORD* pBuf, DWORD pSize, BYTE Command )
{
  DWORD i;
  
  /* Make sure selected page >= 256 */
  pageWrite &= 0xFF;
  
  /* Write command register */
  EECMD = Command;
  /* Data write address starts at byte 0 of page register */
  EEADDR = 0x00;
  
  for (i=0;i<pSize;i++)             // write the page 
  {
    EEWDATA = *pBuf; 

    pBuf++;

#if EEPROM_INTERRUPT_ENABLED
    while ( eorw_flag == 0 );
    eorw_flag = 0;
#else   
    /* Poll for EEPROM to be ready, wait for End of Read/Write occur. */
    while ((FMC_INT_STATUS & EORW) != EORW);
    FMC_INT_CLR_STATUS = EORW|EOBS|EOP1;;
#endif
  }
  
  /* Burn Page */
  EEADDR = (pageWrite) << 6;
  EECMD = PROGRAM; 				// erase/program page

#if EEPROM_INTERRUPT_ENABLED
  while ( eop1_flag == 0 );
  eop1_flag = 0;
#else   
  /* Poll for flash to be ready, wait for End of Burn occur. */
  while ((FMC_INT_STATUS & EOP1) != EOP1);
  FMC_INT_CLR_STATUS = EORW|EOBS|EOP1;;
#endif
  return;
}

/*****************************************************************************
** Function name:     EEPROM_WritePage
**
** Descriptions:      Write EEPROM page, the size is fixed, EEPROM_PAGE_SIZE 64 
**
** parameters:        The first parameter is the destination page,
**                    The second parameter is the pointer to the ssrc addr
**                    The third parameter is the size
**                    The fouth parameter is the write size (WRITE8, WRITE16, WRITE32)
** Returned value:    None
** 
*****************************************************************************/
void EEPROM_ReadPage( BYTE pageRead, DWORD* pBuf, DWORD pSize, BYTE Command )
{
  DWORD i;


  EEADDR = (pageRead << 6);

  EECMD = Command|PREFETCH; 		// 16 bit read  with prefetch enabled
  for (i=0;i<pSize;i++)             // write the page 
  {
    *pBuf = (DWORD)EERDATA; 
    pBuf++;

#if EEPROM_INTERRUPT_ENABLED
    while ( eorw_flag == 0 );
    eorw_flag = 0;
#else   
    /* Poll for EEPROM to be ready, wait for End of Read/Write occur. */
    while ((FMC_INT_STATUS & EORW) != EORW);
    FMC_INT_CLR_STATUS = EORW|EOBS|EOP1;;
#endif

  }
}

/*****************************************************************************
** Function name:     EEPROM_ReadAddress
**
** Descriptions:      Read EEPROM address
**
** parameters:        The first parameter is the destination address,
**                    The second parameter is the pointer to the ssrc addr
**                    The third parameter is the write size (READ8, READ16, READ32)
** Returned value:    None
** 
*****************************************************************************/
void EEPROM_ReadAddr( DWORD addrRead, DWORD* pBuf, BYTE Command )
{
  
  EEADDR = addrRead & 0x3FFF;
  EECMD = Command|PREFETCH; 	// 16 bit read  with prefetch enabled
  *pBuf = (DWORD)EERDATA;
  
#if EEPROM_INTERRUPT_ENABLED
    while ( eorw_flag == 0 );
    eorw_flag = 0;
#else   
    /* Poll for EEPROM to be ready, wait for End of Read/Write occur. */
    while ((FMC_INT_STATUS & EORW) != EORW);
    FMC_INT_CLR_STATUS = EOBS;
#endif
  
}

/******************************************************************************
**                            End Of File
******************************************************************************/
