#include "OB90A64M1.h"
#include "fmc.h"

void FMC_Close()
{
    OB_FMC->ISPCC = 0xE8000000;
}

/**
  * @retval    0   Success
  * @retval   -1   Erase failed
  */
int32_t FMC_ChipErase()
{
    uint32_t nLoop;
    OB_FMC->ISPCC  = FMC_ISP_CHIP_ERASE | 0xE8000001;
    OB_FMC->ISPADR = 0x00;
    OB_FMC->ISPTS  = 0xE8000001;
    nLoop = 0xFFFFFF;
    while(nLoop--)
    {
        if ((OB_FMC->ISPTS & 0x01) == 0x00)
            return 0x00;
    }
    return -1;
}

/**
  * @retval       0         Success
  * @retval      -1         Erase failed
  */
int32_t FMC_PageErase(uint32_t nPageAddr)
{
    uint32_t nLoop;
    OB_FMC->ISPCC  = FMC_ISP_PAGE_ERASE | 0xE8000001;
    OB_FMC->ISPADR = nPageAddr;
    OB_FMC->ISPTS  = 0xE8000001;
    nLoop = 0xFFFFFF;
    while(nLoop--)
    {
        if ((OB_FMC->ISPTS & 0x01) == 0x00)
            return 0x00;
    }
    return -1;
}

uint32_t FMC_GetBootSource()
{
    if ((OB_FMC->BSCSR & 0x02) == 0x00)
        return 0;
    else
        return 1;
}

void FMC_Read(uint32_t nAddr, uint32_t nLength, uint32_t *pData)
{
	uint32_t *pAddr;
	uint32_t nLoop;
	pAddr = (uint32_t *)nAddr;
  nLoop = 0x00;
  while(1)
  {
		if (nLoop >= nLength)
			break;
   
    *(pData) = *pAddr;
    pAddr ++;
		pData++;
		nLoop += 4;
    }	


}

uint32_t FMC_ReadCompanyID(uint32_t nPos)
{
    uint32_t  ID;

    if (nPos == 0x00)
        FMC_Read(0x00100000, 4, &ID);
    else
        FMC_Read(0x00100004, 4, &ID);

    return ID;
}


void FMC_Write(uint32_t nAddr, uint32_t nLength, uint32_t *pData)
{
    uint32_t nLoop;
    
    OB_FMC->ISPCC  = FMC_ISP_PROGRAM | 0xE8000001;
    OB_FMC->ISPADR = nAddr;

    nLoop = 0x00;
    while(1)
    {
        if (nLoop>= nLength)
            break;

        OB_FMC->ISPDAT = *pData;
        OB_FMC->ISPTS  = 0xE8000001;
        if (FMC_WaitFinish() ==  FALSE)
            return;

        pData += 1;
        nLoop += 4;
    }
}

uint32_t FMC_WaitFinish(void)
{
    uint32_t nLoop;

    nLoop = 0xFFFFFF;
    while(nLoop--)
    {
        if ((OB_FMC->ISPTS & 0x01) == 0x00)
            return TRUE;
    }
    return FALSE;
}

int32_t FMC_ReadConfig(uint32_t *pConfig, uint32_t nStartAddr, uint32_t nCount)
{
    uint32_t nLoop;
    OB_FMC->ISPADR = nStartAddr;

    while(1)
    {
        if (nCount == 0x00)
            return 0x00;

        OB_FMC->ISPCC = FMC_ISP_READ | 0xE8000001;
        OB_FMC->ISPTS = 0xE8000001;
        nLoop = 0xFFFFFF;
        while(nLoop--)
        {
            if ((OB_FMC->ISPTS & 0x01) == 0x00)
            {
                *pConfig = OB_FMC->ISPDAT;
                break;
            }
            if (nLoop == 0x01)
            {
                return -1;
            }
        }

        pConfig = pConfig + 4;
        nCount--;
    }
}

int32_t FMC_WriteConfig(uint32_t *pConfig, uint32_t nStartAddr, uint32_t nCount)
{
    uint32_t nLoop;
    OB_FMC->ISPADR = nStartAddr;

    while(1)
    {
        if (nCount == 0x00)
            return 0x00;

        OB_FMC->ISPCC  = FMC_ISP_PROGRAM | 0xE8000001;
        OB_FMC->ISPDAT = *pConfig;
        OB_FMC->ISPTS  = 0xE8000001;
        nLoop = 0xFFFFFF;
        while(nLoop--)
        {
            if ((OB_FMC->ISPTS & 0x01) == 0x00)
                break;
            if (nLoop == 0x01)
                return -1;
        }
        pConfig = pConfig + 4;
        nCount  = nCount - 1;
    }
}

void FMC_ReLoad(void)
{
    uint32_t nLoop;
    OB_FMC->ISPCC  = FMC_ISP_CHIP_RELOAD | 0xE8000001;
    OB_FMC->ISPADR = 0x00;
    OB_FMC->ISPTS  = 0xE8000001;
    nLoop = 0xFFFFFF;
    while(nLoop--)
    {
        if ((OB_FMC->ISPTS & 0x01) == 0x00)
            break;
    }
}
uint32_t FMC_ReadCID(uint32_t WORD)
{
    uint32_t ID;

    if (WORD == 0x00)
        FMC_Read(0x00100000, 4, &ID);
    else    
        FMC_Read(0x00100004, 4, &ID);
  
    return ID;
}

