/**HEADER********************************************************************
* 
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
*************************************************************************** 
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: MT29FxG16.c$
* $Version : 3.5.1.0$
* $Date    : Nov-30-2009$
*
* Comments:
*
*   The file contains functions to program Micron MT29FxG16
*   flash device.
*
*END************************************************************************/

#include "mqx.h" 
#include "bsp.h"
#include "flashx.h"
#include "flashxprv.h"
#include "MT29FxG16.h"

/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    : _bsp_get_nfc_address
* Returned Value   : Address upon success
* Comments         :
*    This function returns the base register address of the NFC
*
*END*----------------------------------------------------------------------*/
pointer _bsp_get_nfc_address()
{
   return (pointer)(&((VMCF5441_STRUCT_PTR)_PSP_GET_IPSBAR())->NFC);
}
/*FUNCTION*-------------------------------------------------------------------
* 
* Function Name    : _mt29fxg16_erase_chip
* Returned Value   : TRUE if successful
* Comments         : 
*    This function erases entire flash chip 
* 
*END*----------------------------------------------------------------------*/

boolean _mt29fxg16_erase_chip
   (  
      /* [IN] the flash information */
      IO_FLASHX_STRUCT_PTR flashx_ptr
   )
{ /* Body */

      volatile uint_16 _PTR_  base16_ptr;

      base16_ptr = (volatile uint_16 _PTR_)flashx_ptr->BASE_ADDR;

      /* Lock sector */
      base16_ptr[0x5555] = 0xAAAA;
      base16_ptr[0x2AAA] = 0x5555;
      base16_ptr[0x5555] = 0x8080; 
      base16_ptr[0x5555] = 0xAAAA;
      base16_ptr[0x2AAA] = 0x5555;
      base16_ptr[0x5555] = 0x1010;

      _io_flashx_wait_us(10);
      
      return(TRUE);

} /* Endbody */

 /*FUNCTION*-------------------------------------------------------------------
* 
* Function Name    : _mt29fxg16_program
* Returned Value   : TRUE if successful
* Comments         : 
*    This function programs the MT29FxG16.
* 
*END*----------------------------------------------------------------------*/

boolean _mt29fxg16_program
   (  
      /* [IN] the flash information */
      IO_FLASHX_STRUCT_PTR flashx_ptr,

      /* [IN] where to copy data from */
      uchar_ptr            from_ptr,
      
      /* [OUT} where to copy data to */
      uchar_ptr            to_ptr,

      /* [IN] the amount to program */
      _mem_size            bytes
   )
{ /* Body */
   boolean result = FALSE;
   uint_32 addressInFlash;
   uint_32 pageNo;
   uint_32 byteOffset;
   uint_32 row;
   uint_32 col;
   uint_32 count1, count2;
   uint_32 size;
   uint_32 output_offset = 0;

   VMCF5XXX_NFC_STRUCT_PTR  nfc_ptr;

   if (flashx_ptr->WRITE_PROTECT) {
      (*flashx_ptr->WRITE_PROTECT)(flashx_ptr, FALSE);
   }/* Endif */
   
   /* get the pointer to nfc registers structure */
   nfc_ptr = _bsp_get_nfc_address();

   addressInFlash = ((uint_32)to_ptr);
   pageNo      = addressInFlash / BYTES_PER_PAGE;
   byteOffset  = addressInFlash - (BYTES_PER_PAGE * pageNo);

   for (; bytes ; )
   {
     if ((byteOffset+bytes) > BYTES_PER_PAGE)
     {
       size	=	BYTES_PER_PAGE -	byteOffset;
     }
	   else
	   {
		   size = bytes;	
	   }

     row = pageNo * BYTES_PER_PAGE / BYTES_PER_PAGE;
     col = (pageNo * BYTES_PER_PAGE) - (row * BYTES_PER_PAGE);
     
     nfc_ptr->CFG  = MCF5XXX_NFC_CFG_16BIT | MCF5XXX_NFC_CFG_PAGECNT(1);
     nfc_ptr->RAI  = 0;
     nfc_ptr->CMD1 = MCF5XXX_NFC_CMD1_BYTE2(0x10);
     nfc_ptr->CMD2 = MCF5XXX_NFC_CMD2_BYTE1(0x80) | MCF5XXX_NFC_CMD2_CODE(0x7FC0);
     nfc_ptr->CAR  = col & 0x07FF;
     nfc_ptr->RAR  = row & 0x01FFFF;
     nfc_ptr->SECSZ  = (size==0x800 || size + byteOffset == 0x800)?0x840: size  + byteOffset;
     nfc_ptr->ISR  |= (MCF5XXX_NFC_ISR_DONECLR | 
                       MCF5XXX_NFC_ISR_DONEEN | 
                       MCF5XXX_NFC_ISR_IDLECLR |
                       MCF5XXX_NFC_ISR_IDLEEN);
	
     nfc_ptr->CMD2 |= MCF5XXX_NFC_CMD2_BUSY_START;
	
     for (count1 = 0; count1 <= MAX_WAIT_COMMAND; count1++)
     {
       if (nfc_ptr->ISR & MCF5XXX_NFC_ISR_IDLE)
       {
         for(count2 = byteOffset; count2 < size + byteOffset; count2++) //size of the buffer in bytes should be the same as page size
         {
				   *(to_ptr + output_offset) = nfc_ptr->SRAM_B0[count2];
				   output_offset++;           	
         }
       }
       else
       {
         goto exit;
       }
     }

	   if ((byteOffset+size) < BYTES_PER_PAGE)
     {
		   byteOffset+=size;
	   }
	   else
	   {
		   byteOffset = (byteOffset+size) % BYTES_PER_PAGE;
		   pageNo++;
	   }
	
     bytes -= size;
     from_ptr += size;
   }
   result = TRUE;

exit:
   if (flashx_ptr->WRITE_PROTECT) {
      (*flashx_ptr->WRITE_PROTECT)(flashx_ptr, TRUE);
   }/* Endif */
   
   return(result);

} /* Endbody */


/*FUNCTION*-------------------------------------------------------------------
* 
* Function Name    : _mt29fxg16_sector_erase
* Returned Value   : TRUE if successful
* Comments         : 
*    This function erases the defined block of the MT29FxG16.
* 
*END*----------------------------------------------------------------------*/

boolean _mt29fxg16_sector_erase
   (
      /* [IN] the flash information */
      IO_FLASHX_STRUCT_PTR flashx_ptr,

      /* [IN] the sector to erase */
      uchar_ptr            input_sect_ptr,

      /* [IN] the number of bytes to erase */
      _mem_size            bytes
   )
{ /* Body */
   boolean result = FALSE;
   uint_32 row = *input_sect_ptr / BYTES_PER_PAGE;
   uint_32 count;

   VMCF5XXX_NFC_STRUCT_PTR  nfc_ptr;

   if (flashx_ptr->WRITE_PROTECT) {
      (*flashx_ptr->WRITE_PROTECT)(flashx_ptr, FALSE);
   }/* Endif */
	
	 /* get the pointer to nfc registers structure */
 	 nfc_ptr = _bsp_get_nfc_address();

   nfc_ptr->CFG  = MCF5XXX_NFC_CFG_16BIT;
   nfc_ptr->CMD1 = MCF5XXX_NFC_CMD1_BYTE2(0xD0);
   nfc_ptr->CMD2 = MCF5XXX_NFC_CMD2_BYTE1(0x60) | MCF5XXX_NFC_CMD2_CODE(0x4EC0);
   nfc_ptr->RAR  = row & 0x01FFFF;
   nfc_ptr->ISR  |= (MCF5XXX_NFC_ISR_IDLECLR | MCF5XXX_NFC_ISR_IDLEEN);
	
   nfc_ptr->CMD2 |= MCF5XXX_NFC_CMD2_BUSY_START;
	
   for (count = 0; count <= MAX_WAIT_COMMAND; count++)
   if (nfc_ptr->ISR & MCF5XXX_NFC_ISR_IDLE)
   {
     result = TRUE;
   }
   
   if (flashx_ptr->WRITE_PROTECT) {
      (*flashx_ptr->WRITE_PROTECT)(flashx_ptr, TRUE);
   }/* Endif */
   return(result);

} /* Endbody */

/*FUNCTION*-------------------------------------------------------------------
* 
* Function Name    : _mt29fxg16_read
* Returned Value   : TRUE if successful
* Comments         : 
*    This function reads data out of the MT29FxG16.
* 
*END*----------------------------------------------------------------------*/

boolean _mt29fxg16_read
   (  
      /* [IN] the flash information */
      IO_FLASHX_STRUCT_PTR flashx_ptr,

      /* [IN] where to copy data from */
      uchar_ptr            from_ptr,
      
      /* [OUT} where to copy data to */
      uchar_ptr            to_ptr,

      /* [IN] the amount to program */
      _mem_size            bytes
   )
{ /* Body */
   uint_32 addressInFlash;
   uint_32 pageNo;
   uint_32 byteOffset;
   uint_32 row;
   uint_32 col;
   uint_32 count1, count2;
   uint_32 size;
   uint_32 output_offset = 0;

   VMCF5XXX_NFC_STRUCT_PTR  nfc_ptr;

	 /* get the pointer to nfc registers structure */
 	 nfc_ptr = _bsp_get_nfc_address();

   addressInFlash = ((uint_32)from_ptr);
   pageNo      = addressInFlash / BYTES_PER_PAGE;
   byteOffset  = addressInFlash - (BYTES_PER_PAGE * pageNo);

   for (; bytes ; )
   {
     if ((byteOffset+bytes) > BYTES_PER_PAGE)
     {
       size	=	BYTES_PER_PAGE -	byteOffset;
     }
	   else
	   {
		   size = bytes;	
	   }

     row = pageNo * BYTES_PER_PAGE / BYTES_PER_PAGE;
     col = (pageNo * BYTES_PER_PAGE) - (row * BYTES_PER_PAGE);
     
     nfc_ptr->CFG  = MCF5XXX_NFC_CFG_16BIT | MCF5XXX_NFC_CFG_PAGECNT(1);
     nfc_ptr->RAI  = 0;
     nfc_ptr->CMD1 = MCF5XXX_NFC_CMD1_BYTE2(0x30);
     nfc_ptr->CMD2 = MCF5XXX_NFC_CMD2_BYTE1(0x00) | MCF5XXX_NFC_CMD2_CODE(0x7EE0);
     nfc_ptr->CAR  = col & 0x07FF;
     nfc_ptr->RAR  = row & 0x01FFFF;
     nfc_ptr->SECSZ  = (size==0x800 || size + byteOffset == 0x800)?0x840: size  + byteOffset;
     nfc_ptr->ISR  |= (MCF5XXX_NFC_ISR_DONECLR | 
                       MCF5XXX_NFC_ISR_DONEEN | 
                       MCF5XXX_NFC_ISR_IDLECLR |
                       MCF5XXX_NFC_ISR_IDLEEN);
	
     nfc_ptr->CMD2 |= MCF5XXX_NFC_CMD2_BUSY_START;
	
     for (count1 = 0; count1 <= MAX_WAIT_COMMAND; count1++)
     {
       if (nfc_ptr->ISR & MCF5XXX_NFC_ISR_IDLE)
       {
         for(count2 = byteOffset; count2 < size + byteOffset; count2++) //size of the buffer in bytes should be the same as page size
         {
				   *(to_ptr + output_offset) = nfc_ptr->SRAM_B0[count2];
				   output_offset++;           	
         }
       }
       else
       {
         return FALSE;
       }
     }

	   if ((byteOffset+size) < BYTES_PER_PAGE)
     {
		   byteOffset+=size;
	   }
	   else
	   {
		   byteOffset = (byteOffset+size) % BYTES_PER_PAGE;
		   pageNo++;
	   }
	
     bytes -= size;
     from_ptr += size;
   }
   return(TRUE);

} /* Endbody */

/* EOF */
