RTC.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright (c) Nuvoton Technology Corp. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/
/* Includes of system headers */
/*---------------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wbio.h"
#include "wblib.h"
#include "Common.h"
#include "RTC.h"
/*---------------------------------------------------------------------------------------------------------*/
/* Macro, type and constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_GLOBALS
//#define RTC_DEBUG
#ifdef RTC_DEBUG
#define RTCDEBUG DrvSIO_printf
#else
#define RTCDEBUG(...)
#endif
/*---------------------------------------------------------------------------------------------------------*/
/* Global file scope (static) variables */
/*---------------------------------------------------------------------------------------------------------*/
static PFN_RTC_CALLBACK *g_pfnRTCCallBack_Tick = NULL, *g_pfnRTCCallBack_Alarm = NULL, *g_pfnRTCCallBack_PSWI = NULL;
static UINT32 volatile g_u32RTC_Count = 0;
static CHAR g_chHourMode = 0;
static BOOL volatile g_bIsEnableTickInt = FALSE;
static BOOL volatile g_bIsEnableAlarmInt = FALSE;
static UINT32 volatile g_u32Reg, g_u32Reg1,g_u32hiYear,g_u32loYear,g_u32hiMonth,g_u32loMonth,g_u32hiDay,g_u32loDay;
static UINT32 volatile g_u32hiHour,g_u32loHour,g_u32hiMin,g_u32loMin,g_u32hiSec,g_u32loSec;
/*---------------------------------------------------------------------------------------------------------*/
/* Functions */
/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/
/* Function: <RTC_ISR> */
/* */
/* Parameter: */
/* VOID */
/* Returns: */
/* None */
/* Side effects: */
/* */
/* Description: */
/* Install ISR to handle interrupt event */
/*---------------------------------------------------------------------------------------------------------*/
static VOID RTC_ISR (VOID)
{
UINT32 volatile u32RegRIIR;
u32RegRIIR = inp32(RIIR);
if (u32RegRIIR & RTC_TICK_INT) /* tick interrupt occurred */
{
outp32(RIIR, RTC_TICK_INT);
g_u32RTC_Count++; /* maintain RTC tick count */
if (g_pfnRTCCallBack_Tick != NULL) /* execute tick callback function */
{
g_pfnRTCCallBack_Tick();
}
}
if (u32RegRIIR & RTC_ALARM_INT) /* alarm interrupt occurred */
{
outp32(RIIR, RTC_ALARM_INT);
RTC_Ioctl(0,RTC_IOC_DISABLE_INT,RTC_ALARM_INT,0);
if (g_pfnRTCCallBack_Alarm != NULL) /* execute alarm callback function */
{
g_pfnRTCCallBack_Alarm();
}
}
if (u32RegRIIR & RTC_PSWI_INT) /* alarm interrupt occurred */
{
outp32(RIIR, RTC_PSWI_INT);
// RTC_Ioctl(0,RTC_IOC_DISABLE_INT,RTC_PSWI_INT,0);
if (g_pfnRTCCallBack_PSWI != NULL) /* execute alarm callback function */
{
g_pfnRTCCallBack_PSWI();
}
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: RTC_SetFrequencyCompensation */
/* */
/* Parameter: */
/* float number */
/* Returns: */
/* E_SUCCESS Success. */
/* E_RTC_ERR_FCR_VALUE Wrong Compenation VALUE */
/* Side effects: */
/* */
/* DESCRIPTION */
/* */
/* Set Frequecy Compenation Data */
/*---------------------------------------------------------------------------------------------------------*/
UINT32 RTC_SetFrequencyCompensation(FLOAT fnumber)
{
INT32 i32intergerPart ;
INT32 i32fractionPart ;
INT32 i32RegInt,i32RegFra ;
UINT32 u32Reg;
i32intergerPart = (INT32) (fnumber) ;
i32fractionPart = ((INT32) ( ((fnumber - i32intergerPart) *100)) / 100);
i32RegInt = i32intergerPart - RTC_FCR_REFERENCE ;
i32RegFra = ((i32fractionPart) * 60);
/*-----------------------------------------------------------------------------------------------------*/
/* Judge Interger part is reasonable */
/*-----------------------------------------------------------------------------------------------------*/
if ( (i32RegInt < 0) | (i32RegInt > 15) )
{
return E_RTC_ERR_FCR_VALUE ;
}
u32Reg = RTC_WriteEnable();
if (u32Reg != 0)
{
return E_RTC_ERR_EIO ;
}
outp32(RTC_FCR, (UINT32)(g_u32Reg >>8 | i32RegFra));
return E_RTC_SUCCESS;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: RTC_WriteEnable */
/* */
/* Parameter: */
/* VOID */
/* Returns: */
/* E_SUCCESS Success. */
/* E_RTC_ERR_FAILED FAILED */
/* Side effects: */
/* */
/* DESCRIPTION */
/* */
/* Access PW to AER to make access other register enable */
/*---------------------------------------------------------------------------------------------------------*/
UINT32 RTC_WriteEnable (VOID)
{
INT32 i32i;
outp32(INIR, RTC_INIT_KEY);
outp32(AER, RTC_WRITE_KEY);
for (i32i = 0 ; i32i < RTC_WAIT_COUNT ; i32i++)
{
/*-------------------------------------------------------------------------------------------------*/
/* check RTC_AER[16] to find out RTC write enable */
/*-------------------------------------------------------------------------------------------------*/
if ( inp32(AER) & 0x10000 )
{
break;
}
}
if (i32i == RTC_WAIT_COUNT)
{
RTCDEBUG ("\nRTC: RTC_WriteEnable, set write enable FAILED!\n");
return E_RTC_ERR_EIO;
}
return E_RTC_SUCCESS;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: RTC_Init */
/* */
/* Parameter: */
/* VOID */
/* Returns: */
/* E_SUCCESS Success. */
/* E_RTC_ERR_EIO Initial RTC FAILED. */
/* Side effects: */
/* */
/* DESCRIPTION */
/* */
/* Initial RTC and install ISR */
/*---------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Init (VOID)
{
INT32 i32i;
/*-----------------------------------------------------------------------------------------------------*/
/* Initial time data struct and some parameters. */
/*-----------------------------------------------------------------------------------------------------*/
g_pfnRTCCallBack_Alarm = NULL;
g_pfnRTCCallBack_Tick = NULL;
g_pfnRTCCallBack_PSWI = NULL;
g_u32RTC_Count = 0;
/*-----------------------------------------------------------------------------------------------------*/
/* When RTC is power on, write 0xa5eb1357 to RTC_INIR to reset all logic. */
/*-----------------------------------------------------------------------------------------------------*/
outp32(INIR, RTC_INIT_KEY);
for (i32i = 0 ; i32i < RTC_WAIT_COUNT ; i32i++)
{
if ( inp32(INIR) & 0x01 )
{ /* Check RTC_INIR[0] to find out RTC reset signal */
break;
}
}
if (i32i == RTC_WAIT_COUNT)
{
RTCDEBUG("\nRTC: RTC_Init, initial RTC FAILED!\n");
return E_RTC_ERR_EIO;
}
/*-----------------------------------------------------------------------------------------------------*/
/* Install RTC ISR */
/*-----------------------------------------------------------------------------------------------------*/
outp32( RIIR, RTC_ALL_INT );
sysInstallISR(IRQ_LEVEL_1, IRQ_RTC, (PVOID)RTC_ISR);
sysSetLocalInterrupt(ENABLE_IRQ);
sysEnableInterrupt(IRQ_RTC);
return E_RTC_SUCCESS;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: RTC_Open */
/* */
/* Parameter: RTC_TIME_DATA_T *sPt Just Set Current_Timer */
/* */
/* Returns: */
/* E_SUCCESS Success. */
/* E_RTC_ERR_EIO Initial RTC FAILED. */
/* Side effects: */
/* */
/* DESCRIPTION */
/* Just Set Current_Timer . */
//*--------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Open (RTC_TIME_DATA_T *sPt)
{
UINT32 u32Reg;
/*-----------------------------------------------------------------------------------------------------*/
/* DO BASIC JUDGEMENT TO Check RTC time data value is reasonable or not. */
/*-----------------------------------------------------------------------------------------------------*/
if ( ((sPt->u32Year - RTC_YEAR2000) > 99)|
((sPt->u32cMonth == 0) || (sPt->u32cMonth > 12))|
((sPt->u32cDay == 0) || (sPt->u32cDay > 31)))
{
return E_RTC_ERR_CALENDAR_VALUE;
}
if (sPt->u8cClockDisplay == RTC_CLOCK_12)
{
if ( (sPt->u32cHour == 0) || (sPt->u32cHour > 12) )
{
return E_RTC_ERR_TIMESACLE_VALUE ;
}
}
else if (sPt->u8cClockDisplay == RTC_CLOCK_24)
{
if (sPt->u32cHour > 23)
{
return E_RTC_ERR_TIMESACLE_VALUE ;
}
}
else
{
return E_RTC_ERR_TIMESACLE_VALUE ;
}
if ((sPt->u32cMinute > 59) |
(sPt->u32cSecond > 59) |
(sPt->u32cSecond > 59))
{
return E_RTC_ERR_TIME_VALUE ;
}
if (sPt->u32cDayOfWeek > 6)
{
return E_RTC_ERR_DWR_VALUE ;
}
/*-----------------------------------------------------------------------------------------------------*/
/* Important, call RTC_WriteEnable() before write data into any register. */
/*-----------------------------------------------------------------------------------------------------*/
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
/*-----------------------------------------------------------------------------------------------------*/
/* Second, set RTC time data. */
/*-----------------------------------------------------------------------------------------------------*/
if (sPt->u8cClockDisplay == RTC_CLOCK_12)
{
g_chHourMode = RTC_CLOCK_12;
RTC_WriteEnable();
outp32(TSSR, RTC_CLOCK_12);
/*-------------------------------------------------------------------------------------------------*/
/* important, range of 12-hour PM mode is 21 upto 32 */
/*-------------------------------------------------------------------------------------------------*/
if (sPt->u8cAmPm == RTC_PM)
sPt->u32cHour += 20;
}
else /* RTC_CLOCK_24 */
{
g_chHourMode = RTC_CLOCK_24;
RTC_WriteEnable();
outp32(TSSR, RTC_CLOCK_24);
RTCDEBUG ("RTC: 24-hour\n");
}
outp32(DWR, (UINT32)sPt->u32cDayOfWeek);
g_u32hiYear = (sPt->u32Year - RTC_YEAR2000) / 10;
g_u32loYear = (sPt->u32Year - RTC_YEAR2000) % 10;
g_u32hiMonth = sPt->u32cMonth / 10;
g_u32loMonth = sPt->u32cMonth % 10;
g_u32hiDay = sPt->u32cDay / 10;
g_u32loDay = sPt->u32cDay % 10;
u32Reg = (g_u32hiYear << 20);
u32Reg |= (g_u32loYear << 16);
u32Reg |= (g_u32hiMonth << 12);
u32Reg |= (g_u32loMonth << 8);
u32Reg |= (g_u32hiDay << 4);
u32Reg |= g_u32loDay;
g_u32Reg = u32Reg;
outp32 (CLR, (UINT32)g_u32Reg);
g_u32hiHour = sPt->u32cHour / 10;
g_u32loHour = sPt->u32cHour % 10;
g_u32hiMin = sPt->u32cMinute / 10;
g_u32loMin = sPt->u32cMinute % 10;
g_u32hiSec = sPt->u32cSecond / 10;
g_u32loSec = sPt->u32cSecond % 10;
u32Reg = (g_u32hiHour << 20);
u32Reg |= (g_u32loHour << 16);
u32Reg |= (g_u32hiMin << 12);
u32Reg |= (g_u32loMin << 8);
u32Reg |= (g_u32hiSec << 4);
u32Reg |= g_u32loSec;
g_u32Reg = u32Reg;
outp32(TLR, (UINT32)g_u32Reg);
RTC_WriteEnable();
// u32Reg = inp32(TLR);
while( inp32(TLR) != (UINT32)g_u32Reg);
return E_RTC_SUCCESS;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: RTC_Read */
/* */
/* Parameter: */
/* eTime Currnet_Timer/ Alarm_Time */
/* RTC_TIME_DATA_T *spt Time Data */
/* Returns: */
/* E_SUCCESS Success. */
/* E_RTC_ERR_EIO Initial RTC FAILED. */
/* Side effects: */
/* */
/* DESCRIPTION */
/* Read current date/time or alarm date/time from RTC */
//*--------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Read (E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt)
{
UINT32 u32Tmp;
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
sPt->u8cClockDisplay = inp32(TSSR); /* 12/24-hour */
sPt->u32cDayOfWeek = inp32(DWR); /* Day of week */
switch (eTime)
{
case RTC_CURRENT_TIME:
{
g_u32Reg = inp32(CLR);
g_u32Reg1 = inp32(TLR);
break;
}
case RTC_ALARM_TIME:
{
g_u32Reg = inp32(CAR);
g_u32Reg1 = inp32(TAR);
break;
}
default:
{
return E_RTC_ERR_ENOTTY;
}
}
g_u32hiYear = (g_u32Reg & 0xF00000) >> 20;
g_u32loYear = (g_u32Reg & 0xF0000) >> 16;
g_u32hiMonth = (g_u32Reg & 0x1000) >> 12;
g_u32loMonth = (g_u32Reg & 0xF00) >> 8;
g_u32hiDay = (g_u32Reg & 0x30) >> 4;
g_u32loDay = g_u32Reg & 0xF;
u32Tmp = (g_u32hiYear * 10);
u32Tmp+= g_u32loYear;
sPt->u32Year = u32Tmp + RTC_YEAR2000;
u32Tmp = (g_u32hiMonth * 10);
sPt->u32cMonth = u32Tmp + g_u32loMonth;
u32Tmp = (g_u32hiDay * 10);
sPt->u32cDay = u32Tmp + g_u32loDay;
g_u32hiHour = (g_u32Reg1 & 0x300000) >> 20;
g_u32loHour = (g_u32Reg1 & 0xF0000) >> 16;
g_u32hiMin = (g_u32Reg1 & 0x7000) >> 12;
g_u32loMin = (g_u32Reg1 & 0xF00) >> 8;
g_u32hiSec = (g_u32Reg1 & 0x70) >> 4;
g_u32loSec = g_u32Reg1 & 0xF;
if (sPt->u8cClockDisplay == RTC_CLOCK_12)
{
u32Tmp = (g_u32hiHour * 10);
u32Tmp+= g_u32loHour;
sPt->u32cHour = u32Tmp; /* AM: 1~12. PM: 21~32. */
switch (eTime)
{
case RTC_CURRENT_TIME:
{
if (sPt->u32cHour >= 21)
{
sPt->u8cAmPm = RTC_PM;
sPt->u32cHour -= 20;
}
else
{
sPt->u8cAmPm = RTC_AM;
}
break;
}
case RTC_ALARM_TIME:
{
if (sPt->u32cHour < 12)
{
if(sPt->u32cHour == 0)
sPt->u32cHour = 12;
sPt->u8cAmPm = RTC_AM;
}
else
{
sPt->u32cHour -= 12;
if(sPt->u32cHour == 0)
sPt->u32cHour = 12;
sPt->u8cAmPm = RTC_PM;
}
break;
}
default:
{
return E_RTC_ERR_ENOTTY;
}
}
u32Tmp = (g_u32hiMin * 10);
u32Tmp+= g_u32loMin;
sPt->u32cMinute = u32Tmp;
u32Tmp = (g_u32hiSec * 10);
u32Tmp+= g_u32loSec;
sPt->u32cSecond = u32Tmp;
}
else
{ /* RTC_CLOCK_24 */
u32Tmp = (g_u32hiHour * 10);
u32Tmp+= g_u32loHour;
sPt->u32cHour = u32Tmp;
u32Tmp = (g_u32hiMin * 10);
u32Tmp+= g_u32loMin;
sPt->u32cMinute = u32Tmp;
u32Tmp = (g_u32hiSec * 10);
u32Tmp+= g_u32loSec;
sPt->u32cSecond = u32Tmp;
}
return E_RTC_SUCCESS;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: RTC_Write */
/* */
/* Parameter: */
/* eTime Currnet_Timer/ Alarm_Time */
/* RTC_TIME_DATA_T *sPt Time Data */
/* Returns: */
/* E_SUCCESS Success. */
/* E_RTC_ERR_EIO Initial RTC FAILED. */
/* Side effects: */
/* */
/* DESCRIPTION */
/* Read current date/time or alarm date/time from RTC */
//*--------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Write(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt)
{
UINT32 u32Reg;
/*-----------------------------------------------------------------------------------------------------*/
/* Check RTC time data value is reasonable or not. */
/*-----------------------------------------------------------------------------------------------------*/
if ( ((sPt->u32Year - RTC_YEAR2000) > 99)|
((sPt->u32cMonth == 0) || (sPt->u32cMonth > 12))|
((sPt->u32cDay == 0) || (sPt->u32cDay > 31)))
{
RTCDEBUG ("\nRTC: Year value is incorrect\n");
return E_RTC_ERR_CALENDAR_VALUE;
}
if ( (sPt->u32Year - RTC_YEAR2000) > 99 )
{
RTCDEBUG ("\nRTC: Year value is incorrect\n");
return E_RTC_ERR_CALENDAR_VALUE;
}
if ( (sPt->u32cMonth == 0) || (sPt->u32cMonth > 12) )
{
RTCDEBUG ("\nRTC: Month value is incorrect\n");
return E_RTC_ERR_CALENDAR_VALUE;
}
if ( (sPt->u32cDay == 0) || (sPt->u32cDay > 31) )
{
RTCDEBUG ("\nRTC: Day value is incorrect\n");
return E_RTC_ERR_CALENDAR_VALUE;
}
if (sPt->u8cClockDisplay == RTC_CLOCK_12)
{
if ( (sPt->u32cHour == 0) || (sPt->u32cHour > 12) )
{
RTCDEBUG ("\nRTC: Hour value is incorrect\n");
return E_RTC_ERR_TIME_VALUE;
}
}
else if (sPt->u8cClockDisplay == RTC_CLOCK_24)
{
if (sPt->u32cHour > 23)
{
RTCDEBUG ("\nRTC: Hour value is incorrect\n");
return E_RTC_ERR_TIME_VALUE;
}
}
else
{
RTCDEBUG ("\nRTC: Clock mode is incorrect\n");
return E_RTC_ERR_TIME_VALUE;
}
if (sPt->u32cMinute > 59)
{
RTCDEBUG ("\nRTC: Minute value is incorrect\n");
return E_RTC_ERR_TIME_VALUE;
}
if (sPt->u32cSecond > 59)
{
RTCDEBUG ("\nRTC: Second value is incorrect\n");
return E_RTC_ERR_TIME_VALUE;
}
if (sPt->u32cDayOfWeek > 6)
{
RTCDEBUG ("\nRTC: Day of week value is incorrect\n");
return E_RTC_ERR_DWR_VALUE;
}
/*-----------------------------------------------------------------------------------------------------*/
/* Important, call RTC_Open() before write data into any register. */
/*-----------------------------------------------------------------------------------------------------*/
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
switch (eTime)
{
case RTC_CURRENT_TIME:
/*---------------------------------------------------------------------------------------------*/
/* Second, set RTC time data. */
/*---------------------------------------------------------------------------------------------*/
if (sPt->u8cClockDisplay == RTC_CLOCK_12)
{
g_chHourMode = RTC_CLOCK_12;
outp32(TSSR, RTC_CLOCK_12);
RTCDEBUG ("RTC: 12-hour\n");
/*-----------------------------------------------------------------------------------------*/
/* important, range of 12-hour PM mode is 21 upto 32 */
/*-----------------------------------------------------------------------------------------*/
if (sPt->u8cAmPm == RTC_PM)
sPt->u32cHour += 20;
}
else /* RTC_CLOCK_24 */
{
g_chHourMode = RTC_CLOCK_24;
outp32(TSSR, RTC_CLOCK_24);
RTCDEBUG ("RTC: 24-hour\n");
}
outp32(DWR,(UINT32) sPt->u32cDayOfWeek);
g_u32hiYear = (sPt->u32Year - RTC_YEAR2000) / 10;
g_u32loYear = (sPt->u32Year - RTC_YEAR2000) % 10;
g_u32hiMonth = sPt->u32cMonth / 10;
g_u32loMonth = sPt->u32cMonth % 10;
g_u32hiDay = sPt->u32cDay / 10;
g_u32loDay = sPt->u32cDay % 10;
u32Reg = (g_u32hiYear << 20);
u32Reg|= (g_u32loYear << 16);
u32Reg|= (g_u32hiMonth << 12);
u32Reg|= (g_u32loMonth << 8);
u32Reg|= (g_u32hiDay << 4);
u32Reg|= g_u32loDay;
g_u32Reg = u32Reg;
RTCDEBUG ("RTC: REG_RTC_CLR[0x%08x]\n", inp32(CLR));
RTC_WriteEnable();
outp32 (CLR, (UINT32)g_u32Reg);
g_u32hiHour = sPt->u32cHour / 10;
g_u32loHour = sPt->u32cHour % 10;
g_u32hiMin = sPt->u32cMinute / 10;
g_u32loMin = sPt->u32cMinute % 10;
g_u32hiSec = sPt->u32cSecond / 10;
g_u32loSec = sPt->u32cSecond % 10;
u32Reg = (g_u32hiHour << 20);
u32Reg|= (g_u32loHour << 16);
u32Reg|= (g_u32hiMin << 12);
u32Reg|= (g_u32loMin << 8);
u32Reg|= (g_u32hiSec << 4);
u32Reg|= g_u32loSec;
g_u32Reg = u32Reg;
RTCDEBUG ("RTC: REG_RTC_TLR[0x%08x]\n", inp32(TLR));
RTC_WriteEnable();
outp32(TLR, (UINT32)g_u32Reg);
RTC_WriteEnable();
while(inp32(TLR) != (UINT32)g_u32Reg);
if (g_chHourMode == RTC_CLOCK_12)
{
if (sPt->u8cAmPm == RTC_PM) /* important, range of 12-hour PM mode is 21 upto 32 */
sPt->u32cHour -= 20;
}
return E_RTC_SUCCESS;
case RTC_ALARM_TIME:
g_pfnRTCCallBack_Alarm = NULL; /* Initial call back function.*/
/*---------------------------------------------------------------------------------------------*/
/* Second, set alarm time data. */
/*---------------------------------------------------------------------------------------------*/
g_u32hiYear = (sPt->u32Year - RTC_YEAR2000) / 10;
g_u32loYear = (sPt->u32Year - RTC_YEAR2000) % 10;
g_u32hiMonth = sPt->u32cMonth / 10;
g_u32loMonth = sPt->u32cMonth % 10;
g_u32hiDay = sPt->u32cDay / 10;
g_u32loDay = sPt->u32cDay % 10;
u32Reg = (g_u32hiYear << 20);
u32Reg|= (g_u32loYear << 16);
u32Reg|= (g_u32hiMonth << 12);
u32Reg|= (g_u32loMonth << 8);
u32Reg|= (g_u32hiDay << 4);
u32Reg|= g_u32loDay;
g_u32Reg = u32Reg;
outp32(CAR, (UINT32)g_u32Reg);
if (g_chHourMode == RTC_CLOCK_12)
{
if (sPt->u8cAmPm == RTC_PM) /* important, range of 12-hour PM mode is 21 upto 32 */
sPt->u32cHour += 20;
}
g_u32hiHour = sPt->u32cHour / 10;
g_u32loHour = sPt->u32cHour % 10;
g_u32hiMin = sPt->u32cMinute / 10;
g_u32loMin = sPt->u32cMinute % 10;
g_u32hiSec = sPt->u32cSecond / 10;
g_u32loSec = sPt->u32cSecond % 10;
u32Reg = (g_u32hiHour << 20);
u32Reg|= (g_u32loHour << 16);
u32Reg|= (g_u32hiMin << 12);
u32Reg|= (g_u32loMin << 8);
u32Reg|= (g_u32hiSec << 4);
u32Reg|= g_u32loSec;
g_u32Reg = u32Reg;
outp32(TAR, (UINT32)g_u32Reg);
if (g_chHourMode == RTC_CLOCK_12)
{
if (sPt->u8cAmPm == RTC_PM) /* important, range of 12-hour PM mode is 21 upto 32 */
{
sPt->u32cHour -= 20;
g_u32hiHour = (sPt->u32cHour + 12) / 10;
g_u32loHour = (sPt->u32cHour + 12) % 10;
g_u32hiMin = sPt->u32cMinute / 10;
g_u32loMin = sPt->u32cMinute % 10;
g_u32hiSec = sPt->u32cSecond / 10;
g_u32loSec = sPt->u32cSecond % 10;
u32Reg = (g_u32hiHour << 20);
u32Reg|= (g_u32loHour << 16);
u32Reg|= (g_u32hiMin << 12);
u32Reg|= (g_u32loMin << 8);
u32Reg|= (g_u32hiSec << 4);
u32Reg|= g_u32loSec;
g_u32Reg = u32Reg;
}
}
/*---------------------------------------------------------------------------------------------*/
/* Third, install alarm callback function. */
/*---------------------------------------------------------------------------------------------*/
if (sPt->pfnAlarmCallBack != NULL)
g_pfnRTCCallBack_Alarm = sPt->pfnAlarmCallBack;
/*---------------------------------------------------------------------------------------------*/
/* Finally, enable alarm interrupt. */
/*---------------------------------------------------------------------------------------------*/
RTC_Ioctl(0,RTC_IOC_ENABLE_INT,RTC_ALARM_INT,0);
u32Reg = inp32(TAR);
RTC_WriteEnable();
while(inp32(TAR) != (UINT32)g_u32Reg);
return E_RTC_SUCCESS;
default:
{
return E_RTC_ERR_ENOTTY;
}
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: RTC_Ioctl */
/* */
/* Parameter: */
/* i32Num Interface number. always set 0 */
/* eCmd Command. */
/* u32Arg0 Arguments for the command. */
/* u32Arg1 Arguments for the command. */
/* Returns: */
/* E_SUCCESS Success. */
/* E_RTC_ERR_ENOTTY Command not support, or parameter incorrect. */
/* E_RTC_ERR_ENODEV Interface number incorrect. */
/* Side effects: */
/* */
/* DESCRIPTION */
/* Support some commands for application. */
//*--------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Ioctl (INT32 i32Num, E_RTC_CMD eCmd, UINT32 u32Arg0, UINT32 u32Arg1)
{
INT32 i32Ret;
UINT32 u32Reg;
RTC_TICK_T *ptick;
if (i32Num != 0)
return E_RTC_ERR_ENODEV;
switch (eCmd)
{
case RTC_IOC_IDENTIFY_LEAP_YEAR:
{
u32Reg = inp32(LIR);
if (u32Reg & 0x01)
{
*(PUINT32)u32Arg0 = RTC_LEAP_YEAR;
RTCDEBUG("\nRTC: It's a leap year\n");
}
else
{
*(PUINT32)u32Arg0 = 0;
RTCDEBUG("\nRTC: It's not a leap year\n");
}
break;
}
case RTC_IOC_SET_TICK_MODE:
{
ptick = (RTC_TICK_T *) u32Arg0;
if (g_bIsEnableTickInt== TRUE)
{
RTC_Ioctl(0,RTC_IOC_DISABLE_INT,RTC_TICK_INT,0);
g_bIsEnableTickInt = TRUE;
}
g_u32RTC_Count = 0;
u32Reg = RTC_WriteEnable();
if (u32Reg != 0)
{
return E_RTC_ERR_EIO ;
}
if (ptick->ucMode > RTC_TICK_1_128_SEC) /*Tick mode 0 to 7 */
{
return E_RTC_ERR_ENOTTY ;
}
outp32(TTR, ptick->ucMode);
if (ptick->pfnTickCallBack != NULL)
{
g_pfnRTCCallBack_Tick = ptick->pfnTickCallBack;
}
else
{
g_pfnRTCCallBack_Tick = NULL;
}
RTC_WriteEnable();
while(inp32(TTR) != ptick->ucMode);
/*---------------------------------------------------------------------------------------------*/
/* Reset tick interrupt status if program enable tick interrupt before. */
/*---------------------------------------------------------------------------------------------*/
if (g_bIsEnableTickInt== TRUE)
{
RTC_Ioctl(0,RTC_IOC_ENABLE_INT,RTC_TICK_INT,0);
return E_RTC_SUCCESS;
}
break;
}
case RTC_IOC_GET_TICK:
{
(*(PUINT32)u32Arg0) = g_u32RTC_Count;
break;
}
case RTC_IOC_RESTORE_TICK:
{
g_u32RTC_Count = 0;
break;
}
case RTC_IOC_ENABLE_INT:
{
INT32 i32Ret;
i32Ret = RTC_WriteEnable();
if (i32Ret != 0)
{
return E_RTC_ERR_EIO;
}
switch ((RTC_INT_SOURCE)u32Arg0)
{
case RTC_TICK_INT:
{
g_bIsEnableTickInt = TRUE;
outp32(RIER, inp32(RIER) | RTC_TICK_INT) ;
break;
}
case RTC_ALARM_INT:
{
g_bIsEnableAlarmInt = TRUE;
outp32(RIER, inp32(RIER) | RTC_ALARM_INT) ;
break;
}
case RTC_PSWI_INT:
{
g_bIsEnableAlarmInt = TRUE;
outp32(RIER, inp32(RIER) | RTC_PSWI_INT) ;
break;
}
default:
{
return E_RTC_ERR_ENOTTY;
}
}
break;
}
case RTC_IOC_DISABLE_INT:
{
INT32 i32Ret;
i32Ret = RTC_WriteEnable();
if (i32Ret != 0)
{
return E_RTC_ERR_EIO;
}
switch ((RTC_INT_SOURCE)u32Arg0)
{
case RTC_TICK_INT:
{
g_bIsEnableTickInt = FALSE;
outp32( RIER, inp32(RIER) & (~RTC_TICK_INT) );
outp32( RIIR, inp32(RIIR) & (RTC_TICK_INT) );
break;
}
case RTC_ALARM_INT:
{
g_bIsEnableAlarmInt = FALSE;
outp32( RIER, inp32(RIER) & (~RTC_ALARM_INT) );
outp32( RIIR, inp32(RIIR) & (RTC_ALARM_INT) );
break;
}
case RTC_PSWI_INT:
{
g_bIsEnableAlarmInt = FALSE;
outp32( RIER, inp32(RIER) & (~RTC_PSWI_INT) );
outp32( RIIR, inp32(RIIR) & (RTC_PSWI_INT) );
break;
}
case RTC_ALL_INT:
{
g_bIsEnableTickInt = FALSE;
g_bIsEnableAlarmInt = FALSE;
outp32( RIER, 0 );
outp32( RIIR, RTC_ALL_INT );
break;
}
default:
{
return E_RTC_ERR_ENOTTY;
}
}
break;
}
case RTC_IOC_SET_FREQUENCY:
{
i32Ret= RTC_SetFrequencyCompensation(u32Arg0) ;
if (i32Ret != 0)
{
return E_RTC_ERR_ENOTTY;
}
break;
}
case RTC_IOC_SET_POWER_ON:
{
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
outp32(PWRON, inp32(PWRON) | 0x01);
break;
}
case RTC_IOC_SET_POWER_OFF:
{
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
outp32(PWRON, (inp32(PWRON) & ~0x05) | 2);
//outp32(REG_APBCLK, inp32(REG_APBCLK) & ~RTC_CKE);
outp32(REG_AHBCLK,0);
while(1);
break;
}
case RTC_IOC_SET_POWER_OFF_PERIOD:
{
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
outp32(PWRON, (inp32(PWRON) & ~0xF0000) | ((u32Arg0 & 0xF) << 16));
while(((inp32(PWRON) & 0xF0000)) != ((u32Arg0 & 0xF) << 16) );
break;
}
case RTC_IOC_ENABLE_HW_POWEROFF:
{
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
outp32(PWRON, (inp32(PWRON) | 0x04));
while(!(inp32(PWRON) & 0x04));
break;
}
case RTC_IOC_DISABLE_HW_POWEROFF:
{
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
outp32(PWRON, (inp32(PWRON) & ~0x04));
while((inp32(PWRON) & 0x04));
break;
}
case RTC_IOC_SET_PSWI_CALLBACK:
{
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
RTC_Ioctl(0, RTC_IOC_ENABLE_INT, RTC_PSWI_INT, 0);
if (((PFN_RTC_CALLBACK *) u32Arg0) != NULL)
{
g_pfnRTCCallBack_PSWI = (PFN_RTC_CALLBACK *) u32Arg0;
}
else
{
g_pfnRTCCallBack_PSWI = NULL;
}
break;
}
case RTC_IOC_GET_POWERKEY_STATUS:
{
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
g_u32Reg = RTC_WriteEnable();
if (g_u32Reg != 0)
{
return E_RTC_ERR_EIO;
}
if(inp32(PWRON) & 0x80)
*(PUINT32)u32Arg0 = 1;
else
*(PUINT32)u32Arg0 = 0;
break;
}
default:
{
return E_RTC_ERR_ENOTTY;
}
}
return E_RTC_SUCCESS;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: RTC_Close */
/* */
/* Parameter: */
/* VOID */
/* Returns: */
/* E_SUCCESS Success. */
/* E_RTC_ERR_ENODEV Interface number incorrect. */
/* Side effects: */
/* */
/* DESCRIPTION */
/* Disable AIC channel of RTC and both tick and alarm interrupt.. */
/*---------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Close (VOID)
{
g_bIsEnableTickInt = FALSE;
sysDisableInterrupt(IRQ_RTC);
RTC_Ioctl(0,RTC_IOC_DISABLE_INT,RTC_ALL_INT,0);
return E_RTC_SUCCESS;
}
extern UINT32 RTC_Init(VOID);
extern UINT32 RTC_Open(RTC_TIME_DATA_T *sPt);
extern UINT32 RTC_Ioctl(INT32 nNum, E_RTC_CMD uCmd, UINT32 uArg0, UINT32 u32Arg1);
extern UINT32 RTC_Read(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt);
extern UINT32 RTC_Write(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt);
extern UINT32 RTC_Close(VOID);
RTC.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright (c) Nuvoton Technology Corp. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
#ifndef __DRVRTC_H__
#define __DRVRTC_H__
/*---------------------------------------------------------------------------------------------------------*/
/* Includes of system headers */
/*---------------------------------------------------------------------------------------------------------*/
#include "wbio.h"
#include "w55fa93_reg.h"
#ifdef __cplusplus
extern "C"
{
#endif
/*---------------------------------------------------------------------------------------------------------*/
/* Define Version number */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_MAJOR_NUM 1
#define RTC_MINOR_NUM 0
#define RTC_BUILD_NUM 1
/*---------------------------------------------------------------------------------------------------------*/
/* Define Error Code */
/*---------------------------------------------------------------------------------------------------------*/
// E_DRVRTC_ERR_CALENDAR_VALUE Wrong Calendar Value
// E_DRVRTC_ERR_TIMESACLE_VALUE Wrong Time Scale Value
// E_DRVRTC_ERR_TIME_VALUE Wrong Time Value
// E_DRVRTC_ERR_DWR_VALUE Wrong Day Value
// E_DRVRTC_ERR_FCR_VALUE Wrong Compenation value
// E_DRVRTC_ERR_EIO Initial RTC Failed.
// E_DRVRTC_ERR_ENOTTY Command not support, or parameter incorrect.
// E_DRVRTC_ERR_ENODEV Interface number incorrect.
// E_DRVRTC_ERR_FAILED Failed.
#define E_RTC_SUCCESS 0
#define E_RTC_ERR_CALENDAR_VALUE 1
#define E_RTC_ERR_TIMESACLE_VALUE 2
#define E_RTC_ERR_TIME_VALUE 3
#define E_RTC_ERR_DWR_VALUE 4
#define E_RTC_ERR_FCR_VALUE 5
#define E_RTC_ERR_EIO 6
#define E_RTC_ERR_ENOTTY 7
#define E_RTC_ERR_ENODEV 8
/*---------------------------------------------------------------------------------------------------------*/
/* RTC Access Key */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_INIT_KEY 0xa5eb1357
#define RTC_WRITE_KEY 0xa965
/*---------------------------------------------------------------------------------------------------------*/
/* RTC Initial Time Out Value */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_WAIT_COUNT 10000
/*---------------------------------------------------------------------------------------------------------*/
/* RTC Reference */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_YEAR2000 2000
#define RTC_FCR_REFERENCE 32761
/*---------------------------------------------------------------------------------------------------------*/
/* Leap Year */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_LEAP_YEAR 1
/*---------------------------------------------------------------------------------------------------------*/
/* 12-Hour / 24-Hour */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_CLOCK_12 0
#define RTC_CLOCK_24 1
/*---------------------------------------------------------------------------------------------------------*/
/* AM / PM */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_AM 1
#define RTC_PM 2
/*---------------------------------------------------------------------------------------------------------*/
/* INTERRUPT SOURCE */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
RTC_ALARM_INT =0x01,
RTC_TICK_INT =0x02,
RTC_PSWI_INT =0x04,
RTC_ALL_INT =0x07
}RTC_INT_SOURCE;
/*---------------------------------------------------------------------------------------------------------*/
/* Define Ioctl commands */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
RTC_IOC_IDENTIFY_LEAP_YEAR = 0,
RTC_IOC_SET_TICK_MODE = 1,
RTC_IOC_GET_TICK = 2,
RTC_IOC_RESTORE_TICK = 3,
RTC_IOC_ENABLE_INT = 4,
RTC_IOC_DISABLE_INT = 5,
RTC_IOC_SET_CURRENT_TIME = 6,
RTC_IOC_SET_ALAMRM_TIME = 7,
RTC_IOC_SET_FREQUENCY = 8,
RTC_IOC_SET_POWER_ON = 9,
RTC_IOC_SET_POWER_OFF = 10,
RTC_IOC_SET_POWER_OFF_PERIOD = 11,
RTC_IOC_ENABLE_HW_POWEROFF = 12,
RTC_IOC_DISABLE_HW_POWEROFF = 13,
RTC_IOC_GET_POWERKEY_STATUS = 14,
RTC_IOC_SET_PSWI_CALLBACK = 15
}E_RTC_CMD;
/*---------------------------------------------------------------------------------------------------------*/
/* Define for RTC Tick mode */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
RTC_TICK_1_SEC = 0, /* 1 sec */
RTC_TICK_1_2_SEC = 1, /* 1/2 sec */
RTC_TICK_1_4_SEC = 2, /* 1/4 sec */
RTC_TICK_1_8_SEC = 3, /* 1/8 sec */
RTC_TICK_1_16_SEC = 4, /* 1/16 sec */
RTC_TICK_1_32_SEC = 5, /* 1/32 sec */
RTC_TICK_1_64_SEC = 6, /* 1/64 sec */
RTC_TICK_1_128_SEC = 7 /* 1/128 sec */
}RTC_TICK;
/*---------------------------------------------------------------------------------------------------------*/
/* Define Time data struct & some parameters */
/*---------------------------------------------------------------------------------------------------------*/
typedef void (PFN_RTC_CALLBACK)(void);
typedef enum
{
RTC_CURRENT_TIME = 0,
RTC_ALARM_TIME = 1
}E_RTC_TIME_SELECT;
/*---------------------------------------------------------------------------------------------------------*/
/* Define Day of week parameter */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
RTC_SUNDAY = 0,
RTC_MONDAY = 1,
RTC_TUESDAY = 2,
RTC_WEDNESDAY = 3,
RTC_THURSDAY = 4,
RTC_FRIDAY = 5,
RTC_SATURDAY = 6
}E_RTC_DWR_PARAMETER;
/*---------------------------------------------------------------------------------------------------------*/
/* Define Time Data Struct */
/*---------------------------------------------------------------------------------------------------------*/
typedef struct
{
UINT8 u8cClockDisplay; /* 12-Hour, 24-Hour */
UINT8 u8cAmPm; /* Only 12-hr used */
UINT32 u32cSecond;
UINT32 u32cMinute;
UINT32 u32cHour;
UINT32 u32cDayOfWeek;
UINT32 u32cDay;
UINT32 u32cMonth;
UINT32 u32Year;
PFN_RTC_CALLBACK *pfnAlarmCallBack;
}RTC_TIME_DATA_T;
/*---------------------------------------------------------------------------------------------------------*/
/* Define Tick Struct */
/*---------------------------------------------------------------------------------------------------------*/
typedef struct
{
UINT8 ucMode;
PFN_RTC_CALLBACK *pfnTickCallBack;
}RTC_TICK_T;
/*---------------------------------------------------------------------------------------------------------*/
/* Define Function Prototype */
/*---------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Init(VOID);
UINT32 RTC_Open(RTC_TIME_DATA_T *sPt);
UINT32 RTC_Ioctl(INT32 i32Num, E_RTC_CMD eCmd, UINT32 u32Arg0, UINT32 u32Arg1);
UINT32 RTC_Read(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt);
UINT32 RTC_Write(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt);
UINT32 RTC_SetFrequencyCompensation(FLOAT fnumber);
UINT32 RTC_WriteEnable (VOID);
UINT32 RTC_Close(VOID);
#ifdef __cplusplus
}
#endif
#endif /* __DRVRTC_H__ */
sd.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential */
/* */
/* Copyright (c) 2008 by Nuvoton Technology Corporation */
/* All rights reserved */
/* */
/*-----------------------------------------------------------------------------------*/
#ifdef ECOS
#include "drv_api.h"
#include "diag.h"
#include "Common.h"
#include "wbio.h"
#else
#include "wblib.h"
#endif
#include "w55fa93_reg.h"
#include "w55fa93_sic.h"
#include "fmi.h"
UINT32 _fmi_uFMIReferenceClock;
// define DATE CODE and show it when running to make maintaining easy.
#define SD_DATE_CODE FMI_DATE_CODE
#define SD_BLOCK_SIZE 512
#define FMI_SD_INITCOUNT 2000
#define FMI_TICKCOUNT 1000
#define FMI_TYPE_UNKNOWN 0
#define FMI_TYPE_SD_HIGH 1
#define FMI_TYPE_SD_LOW 2
#define FMI_TYPE_MMC 3
// global variables
// For response R3 (such as ACMD41, CRC-7 is invalid; but SD controller will still
// calculate CRC-7 and get an error result, software should ignore this error and clear SDISR [CRC_IF] flag
// _fmi_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error
UINT32 _fmi_uR3_CMD=0;
UINT32 _fmi_uR7_CMD=0;
DISK_DATA_T SD_DiskInfo0;
DISK_DATA_T SD_DiskInfo1;
DISK_DATA_T SD_DiskInfo2;
#define schedule();
__align(4096) UCHAR _fmi_ucSDHCBuffer[512];
UINT8 *_fmi_pSDHCBuffer;
//--- 2014/3/27, check the sector number is valid or not for current SD card.
unsigned int g_max_valid_sector; // The max valid sector number for current SD card.
static int sd0_ok = 0;
static int sd1_ok = 0;
static int sd2_ok = 0;
INT fmiSDCheckSector(UINT32 uSector, UINT32 uBufcnt)
{
if ((uSector + uBufcnt - 1) > g_max_valid_sector)
{
sysprintf("ERROR: Fail to access invalid sector number %d from SD card !!\n", uSector+uBufcnt-1);
sysprintf(" The max valid sector number for current SD card is %d.\n", g_max_valid_sector);
return FMI_SD_SELECT_ERROR; // invalid sector
}
return 0; // valid sector
}
void fmiCheckRB()
{
while(1)
{
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);
while(inpw(REG_SDCR) & SDCR_8CLK_OE);
if (inpw(REG_SDISR) & SDISR_SD_DATA0)
break;
}
}
INT fmiSDCommand(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg)
{
outpw(REG_SDARG, uArg);
outpw(REG_SDCR, (inpw(REG_SDCR)&(~SDCR_CMD_CODE))|(ucCmd << 8)|(SDCR_CO_EN));
while(inpw(REG_SDCR) & SDCR_CO_EN)
{
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
}
return Successful;
}
INT fmiSDCmdAndRsp(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg, INT ntickCount)
{
outpw(REG_SDARG, uArg);
outpw(REG_SDCR, (inpw(REG_SDCR)&(~SDCR_CMD_CODE))|(ucCmd << 8)|(SDCR_CO_EN | SDCR_RI_EN));
if (ntickCount > 0)
{
while(inpw(REG_SDCR) & SDCR_RI_EN)
{
if(ntickCount-- == 0) {
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_SWRST); // reset SD engine
return FMI_SD_INIT_TIMEOUT;
}
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
}
}
else
{
while(inpw(REG_SDCR) & SDCR_RI_EN)
{
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
}
}
if (_fmi_uR7_CMD)
{
if (((inpw(REG_SDRSP1) & 0xff) != 0x55) && ((inpw(REG_SDRSP0) & 0xf) != 0x01))
{
_fmi_uR7_CMD = 0;
return FMI_SD_CMD8_ERROR;
}
}
if (!_fmi_uR3_CMD)
{
if (inpw(REG_SDISR) & SDISR_CRC_7) // check CRC7
return Successful;
else
{
#ifdef DEBUG
sysprintf("response error [%d]!\n", ucCmd);
#endif
return FMI_SD_CRC7_ERROR;
}
}
else // ignore CRC error for R3 case
{
_fmi_uR3_CMD = 0;
outpw(REG_SDISR, SDISR_CRC_IF);
return Successful;
}
}
// Get 16 bytes CID or CSD
INT fmiSDCmdAndRsp2(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg, UINT *puR2ptr)
{
unsigned int i;
unsigned int tmpBuf[5];
outpw(REG_SDARG, uArg);
outpw(REG_SDCR, (inpw(REG_SDCR)&(~SDCR_CMD_CODE))|(ucCmd << 8)|(SDCR_CO_EN | SDCR_R2_EN));
while(inpw(REG_SDCR) & SDCR_R2_EN)
{
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
}
if (inpw(REG_SDISR) & SDISR_CRC_7)
{
for (i=0; i<5; i++)
tmpBuf[i] = Swap32(inpw(REG_FB_0+i*4));
for (i=0; i<4; i++)
*puR2ptr++ = ((tmpBuf[i] & 0x00ffffff)<<8) | ((tmpBuf[i+1] & 0xff000000)>>24);
return Successful;
}
else
return FMI_SD_CRC7_ERROR;
}
INT fmiSDCmdAndRspDataIn(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg)
{
outpw(REG_SDARG, uArg);
outpw(REG_SDCR, (inpw(REG_SDCR)&(~SDCR_CMD_CODE))|(ucCmd << 8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DI_EN));
while (inpw(REG_SDCR) & SDCR_RI_EN)
{
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
}
while (inpw(REG_SDCR) & SDCR_DI_EN)
{
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
}
if (!(inpw(REG_SDISR) & SDISR_CRC_7)) // check CRC7
{
#ifdef DEBUG
sysprintf("fmiSDCmdAndRspDataIn: response error [%d]!\n", ucCmd);
#endif
return FMI_SD_CRC7_ERROR;
}
if (!(inpw(REG_SDISR) & SDISR_CRC_16)) // check CRC16
{
#ifdef DEBUG
sysprintf("fmiSDCmdAndRspDataIn: read data CRC16 error!\n");
#endif
return FMI_SD_CRC16_ERROR;
}
return Successful;
}
// Initial
INT fmiSD_Init(FMI_SD_INFO_T *pSD)
{
int volatile i, status, rate;
unsigned int resp;
unsigned int CIDBuffer[4];
unsigned int volatile u32CmdTimeOut;
int sdport;
if (pSD == pSD0)
sdport = 0;
else if (pSD == pSD1)
sdport = 1;
else if (pSD == pSD2)
sdport = 2;
else
return FMI_SD_INIT_ERROR;
sysprintf("Initial SD NonOS Driver (%s) for SD port %d\n", SD_DATE_CODE, sdport);
#if 1
// set the clock to 200KHz
/* divider */
rate = _fmi_uFMIReferenceClock / 200;
if ((_fmi_uFMIReferenceClock % 200) == 0)
rate = rate - 1;
#else
// set the clock to 400KHz
/* divider */
rate = _fmi_uFMIReferenceClock / 400;
if ((_fmi_uFMIReferenceClock % 400) == 0)
rate = rate - 1;
#endif
for(i=0; i<100; i++);
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_S) | (0x03 << 19)); // SD clock from UPLL
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N0) | (0x07 << 16)); // SD clock divided by 8
rate /= 8;
rate &= 0xFF;
if (rate) rate--;
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N1) | (rate << 24)); // SD clock divider
for(i=0; i<1000; i++);
// power ON 74 clock
outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_74CLK_OE);
while(inpw(REG_SDCR) & SDCR_74CLK_OE)
{
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
}
fmiSDCommand(pSD, 0, 0); // reset all cards
for (i=0x100; i>0; i--);
// initial SDHC
_fmi_uR7_CMD = 1;
u32CmdTimeOut = 5000;
i = fmiSDCmdAndRsp(pSD, 8, 0x00000155, u32CmdTimeOut);
if (i == Successful)
{
// SD 2.0
fmiSDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
_fmi_uR3_CMD = 1;
fmiSDCmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 2.7v-3.6v
resp = inpw(REG_SDRSP0);
while (!(resp & 0x00800000)) // check if card is ready
{
fmiSDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
_fmi_uR3_CMD = 1;
fmiSDCmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 3.0v-3.4v
resp = inpw(REG_SDRSP0);
}
if (resp & 0x00400000)
pSD->uCardType = FMI_TYPE_SD_HIGH;
else
pSD->uCardType = FMI_TYPE_SD_LOW;
}
else
{
// SD 1.1 or MMC
fmiSDCommand(pSD, 0, 0); // reset all cards
for (i=0x100; i>0; i--);
i = fmiSDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
if (i == FMI_SD_INIT_TIMEOUT) // MMC memory
{
fmiSDCommand(pSD, 0, 0); // reset
for (i=0x100; i>0; i--);
_fmi_uR3_CMD = 1;
// 2014/8/6, to support eMMC v4.4, the argument of CMD1 should be 0x40ff8000 to support both MMC plus and eMMC cards.
if (fmiSDCmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut) != FMI_SD_INIT_TIMEOUT) // MMC memory
{
resp = inpw(REG_SDRSP0);
while (!(resp & 0x00800000)) // check if card is ready
{
_fmi_uR3_CMD = 1;
fmiSDCmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut); // high voltage
resp = inpw(REG_SDRSP0);
}
// MMC card is ready. Check the access mode of MMC card.
if (resp & 0x00400000)
pSD->uCardType = FMI_TYPE_MMC_SECTOR_MODE;
else
pSD->uCardType = FMI_TYPE_MMC;
}
else
{
pSD->uCardType = FMI_TYPE_UNKNOWN;
return FMI_ERR_DEVICE;
}
}
else if (i == Successful) // SD Memory
{
_fmi_uR3_CMD = 1;
fmiSDCmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v
resp = inpw(REG_SDRSP0);
while (!(resp & 0x00800000)) // check if card is ready
{
fmiSDCmdAndRsp(pSD, 55, 0x00,u32CmdTimeOut);
_fmi_uR3_CMD = 1;
fmiSDCmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v
resp = inpw(REG_SDRSP0);
}
pSD->uCardType = FMI_TYPE_SD_LOW;
}
else
{
pSD->uCardType = FMI_TYPE_UNKNOWN;
#ifdef DEBUG
sysprintf("CMD55 CRC error !!\n");
#endif
return FMI_SD_INIT_ERROR;
}
}
// CMD2, CMD3
if (pSD->uCardType != FMI_TYPE_UNKNOWN)
{
fmiSDCmdAndRsp2(pSD, 2, 0x00, CIDBuffer);
if ((pSD->uCardType == FMI_TYPE_MMC) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
{
// Increase RCA for next MMC card.
// The RCA value 0 is reserved to set all cards with CMD7.
// The default value is 1.
pSD->uRCA = (pSD->uRCA + 0x10000) & 0xFFFF0000; // RCA is 16-bit value at MSB
if (pSD->uRCA == 0)
pSD->uRCA = 0x10000;
if ((status = fmiSDCmdAndRsp(pSD, 3, pSD->uRCA, 0)) != Successful) // set RCA for MMC
return status;
}
else
{
if ((status = fmiSDCmdAndRsp(pSD, 3, 0x00, 0)) != Successful) // get RCA for SD
return status;
else
pSD->uRCA = (inpw(REG_SDRSP0) << 8) & 0xffff0000;
}
}
#ifdef DEBUG
switch (pSD->uCardType)
{
case FMI_TYPE_SD_HIGH:
DBG_PRINTF("This is high capacity SD memory card\n"); break;
case FMI_TYPE_SD_LOW:
DBG_PRINTF("This is standard capacity SD memory card\n"); break;
case FMI_TYPE_MMC:
DBG_PRINTF("This is standard capacity MMC memory card\n"); break;
case FMI_TYPE_MMC_SECTOR_MODE:
DBG_PRINTF("This is high capacity MMC memory card\n"); break;
}
#endif
// set data transfer clock
return Successful;
}
INT fmiSwitchToHighSpeed(FMI_SD_INFO_T *pSD)
{
int volatile status=0;
UINT16 current_comsumption, busy_status0, busy_status1;
// UINT16 fun1_info, switch_status;
outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer); // set DMA transfer starting address
outpw(REG_SDBLEN, 63); // 512 bit
if ((status = fmiSDCmdAndRspDataIn(pSD, 6, 0x00ffff01)) != Successful)
return Fail;
current_comsumption = _fmi_pSDHCBuffer[0]<<8 | _fmi_pSDHCBuffer[1];
if (!current_comsumption)
return Fail;
// fun1_info = _fmi_pSDHCBuffer[12]<<8 | _fmi_pSDHCBuffer[13];
// switch_status = _fmi_pSDHCBuffer[16] & 0xf;
busy_status0 = _fmi_pSDHCBuffer[28]<<8 | _fmi_pSDHCBuffer[29];
if (!busy_status0) // function ready
{
outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer); // set DMA transfer starting address
outpw(REG_SDBLEN, 63); // 512 bit
if ((status = fmiSDCmdAndRspDataIn(pSD, 6, 0x80ffff01)) != Successful)
return Fail;
// function change timing: 8 clocks
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);
while(inpw(REG_SDCR) & SDCR_8CLK_OE);
current_comsumption = _fmi_pSDHCBuffer[0]<<8 | _fmi_pSDHCBuffer[1];
if (!current_comsumption)
return Fail;
busy_status1 = _fmi_pSDHCBuffer[28]<<8 | _fmi_pSDHCBuffer[29];
if (!busy_status1)
sysprintf("switch into high speed mode !!!\n");
return Successful;
}
else
return Fail;
}
INT fmiSelectCard(FMI_SD_INFO_T *pSD)
{
int volatile status=0, i;
int rate;
UINT32 arg;
if ((status = fmiSDCmdAndRsp(pSD, 7, pSD->uRCA, 0)) != Successful)
return status;
fmiCheckRB();
// if SD card set 4bit
if (pSD->uCardType == FMI_TYPE_SD_HIGH)
{
_fmi_pSDHCBuffer = (UINT8 *)((UINT32)_fmi_ucSDHCBuffer | 0x80000000);
outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer); // set DMA transfer starting address
outpw(REG_SDBLEN, 7); // 64 bit
if ((status = fmiSDCmdAndRsp(pSD, 55, pSD->uRCA, 0)) != Successful)
return status;
if ((status = fmiSDCmdAndRspDataIn(pSD, 51, 0x00)) != Successful)
return status;
if ((_fmi_ucSDHCBuffer[0] & 0xf) == 0x2)
{
// support SD spec v2.0
status = fmiSwitchToHighSpeed(pSD);
if (status == Successful)
{
/* divider */
rate = _fmi_uFMIReferenceClock / SDHC_FREQ;
if ((_fmi_uFMIReferenceClock % SDHC_FREQ) > 0)
rate ++;
for(i=0; i<100; i++);
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_S) | (0x03 << 19)); // SD clock from UPLL
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N0) | (0x01 << 16)); // SD clock divided by 8
if (rate % 2)
{
rate /= 2;
rate &= 0xFF;
}
else
{
rate /= 2;
rate &= 0xFF;
rate--;
}
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N1) | (rate << 24)); // SD clock divider
for(i=0; i<1000; i++);
}
}
if ((status = fmiSDCmdAndRsp(pSD, 55, pSD->uRCA, 0)) != Successful)
return status;
if ((status = fmiSDCmdAndRsp(pSD, 6, 0x02, 0)) != Successful) // set bus width to 4-bit mode for SD card
return status;
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_DBW); // set bus width to 4-bit mode for SD host controller
}
else if (pSD->uCardType == FMI_TYPE_SD_LOW)
{
#if 0
_fmi_pSDHCBuffer = (UINT8 *)((UINT32)_fmi_ucSDHCBuffer | 0x80000000);
outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer); // set DMA transfer starting address
outpw(REG_SDBLEN, 7); // 64 bit
if ((status = fmiSDCmdAndRsp(pSD, 55, pSD->uRCA, 0)) != Successful)
return status;
if ((status = fmiSDCmdAndRspDataIn(pSD, 51, 0x00)) != Successful)
return status;
#endif
if ((status = fmiSDCmdAndRsp(pSD, 55, pSD->uRCA, 0)) != Successful)
return status;
if ((status = fmiSDCmdAndRsp(pSD, 6, 0x02, 0)) != Successful) // set bus width to 4-bit mode for SD card
return status;
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_DBW); // set bus width to 4-bit mode for SD host controller
}
else if ((pSD->uCardType == FMI_TYPE_MMC) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
{
//--- sent CMD6 to MMC card to set bus width to 4 bits mode
// set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode)
arg = (3 << 24) | (183 << 16) | (1 << 8);
if ((status = fmiSDCmdAndRsp(pSD, 6, arg, 0)) != Successful)
return status;
fmiCheckRB();
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_DBW); // set bus width to 4-bit mode for SD host controller
}
if ((status = fmiSDCmdAndRsp(pSD, 16, SD_BLOCK_SIZE, 0)) != Successful) // set block length
return status;
fmiSDCommand(pSD, 7, 0);
// According to SD spec v2.0 chapter 4.4,
// "After the last SD Memory Card bus transaction, the host is required,
// to provide 8 (eight) clock cycles for the card to complete the
// operation before shutting down the clock."
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);
#ifdef _SIC_USE_INT_
outpw(REG_SDIER, inpw(REG_SDIER)|SDIER_BLKD_IEN);
#endif //_SIC_USE_INT_
return Successful;
}
/*-----------------------------------------------------------------------------
* fmiSD_Read_in(), To read data with default black size SD_BLOCK_SIZE
*---------------------------------------------------------------------------*/
INT fmiSD_Read_in(FMI_SD_INFO_T *pSD, UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr)
{
BOOL volatile bIsSendCmd=FALSE;
unsigned int volatile reg;
int volatile i, loop, status;
//--- check input parameters
status = fmiSDCheckSector(uSector, uBufcnt);
if (status < 0)
return status; // invalid sector
if (uBufcnt == 0)
{
sysprintf("ERROR: fmiSD_Read_in(): uBufcnt cannot be 0!!\n");
return FMI_SD_SELECT_ERROR;
}
if ((status = fmiSDCmdAndRsp(pSD, 7, pSD->uRCA, 0)) != Successful)
return status;
fmiCheckRB();
outpw(REG_SDBLEN, SD_BLOCK_SIZE - 1);
if ((pSD->uCardType == FMI_TYPE_SD_HIGH) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
outpw(REG_SDARG, uSector);
else
outpw(REG_SDARG, uSector * SD_BLOCK_SIZE);
outpw(REG_DMACSAR, uDAddr);
loop = uBufcnt / 255;
for (i=0; i<loop; i++)
{
#ifdef _SIC_USE_INT_
_fmi_bIsSDDataReady = FALSE;
#endif //_SIC_USE_INT_
reg = inpw(REG_SDCR) & ~SDCR_CMD_CODE;
reg = reg | 0xff0000; // set BLK_CNT to 255
if (bIsSendCmd == FALSE)
{
outpw(REG_SDCR, reg|(18<<8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DI_EN));
bIsSendCmd = TRUE;
}
else
outpw(REG_SDCR, reg | SDCR_DI_EN);
#ifdef _SIC_USE_INT_
while(!_fmi_bIsSDDataReady)
#else
while(1)
#endif //_SIC_USE_INT_
{
#ifndef _SIC_USE_INT_
if ((inpw(REG_SDISR) & SDISR_BLKD_IF) && (!(inpw(REG_SDCR) & SDCR_DI_EN)))
{
outpw(REG_SDISR, SDISR_BLKD_IF);
break;
}
#endif
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
/* Call schedule() to release CPU power to other tasks during waiting SIC/DMA completed. */
schedule();
}
if (!(inpw(REG_SDISR) & SDISR_CRC_7)) // check CRC7
{
#ifdef DEBUG
sysprintf("fmiSD_Read_in(): response error!\n");
#endif
return FMI_SD_CRC7_ERROR;
}
if (!(inpw(REG_SDISR) & SDISR_CRC_16)) // check CRC16
{
#ifdef DEBUG
sysprintf("fmiSD_Read_in() :read data CRC16 error!\n");
#endif
return FMI_SD_CRC16_ERROR;
}
}
loop = uBufcnt % 255;
if (loop != 0)
{
#ifdef _SIC_USE_INT_
_fmi_bIsSDDataReady = FALSE;
#endif //_SIC_USE_INT_
reg = inpw(REG_SDCR) & (~SDCR_CMD_CODE);
reg = reg & (~SDCR_BLKCNT);
reg |= (loop << 16); // setup SDCR_BLKCNT
if (bIsSendCmd == FALSE)
{
outpw(REG_SDCR, reg|(18<<8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DI_EN));
bIsSendCmd = TRUE;
}
else
outpw(REG_SDCR, reg | SDCR_DI_EN);
#ifdef _SIC_USE_INT_
while(!_fmi_bIsSDDataReady)
#else
while(1)
#endif //_SIC_USE_INT_
{
#ifndef _SIC_USE_INT_
if ((inpw(REG_SDISR) & SDISR_BLKD_IF) && (!(inpw(REG_SDCR) & SDCR_DI_EN)))
{
outpw(REG_SDISR, SDISR_BLKD_IF);
break;
}
#endif
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
/* Call schedule() to release CPU power to other tasks during waiting SIC/DMA completed. */
schedule();
}
if (!(inpw(REG_SDISR) & SDISR_CRC_7)) // check CRC7
{
#ifdef DEBUG
sysprintf("fmiSD_Read_in(): response error!\n");
#endif
return FMI_SD_CRC7_ERROR;
}
if (!(inpw(REG_SDISR) & SDISR_CRC_16)) // check CRC16
{
#ifdef DEBUG
sysprintf("fmiSD_Read_in(): read data CRC16 error!\n");
#endif
return FMI_SD_CRC16_ERROR;
}
}
if (fmiSDCmdAndRsp(pSD, 12, 0, 0)) // stop command
{
#ifdef DEBUG
sysprintf("stop command fail !!\n");
#endif
return FMI_SD_CRC7_ERROR;
}
fmiCheckRB();
fmiSDCommand(pSD, 7, 0);
// According to SD spec v2.0 chapter 4.4,
// "After the last SD Memory Card bus transaction, the host is required,
// to provide 8 (eight) clock cycles for the card to complete the
// operation before shutting down the clock."
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);
return Successful;
}
/*-----------------------------------------------------------------------------
* fmiSD_Write_in(), To write data with static black size SD_BLOCK_SIZE
*---------------------------------------------------------------------------*/
INT fmiSD_Write_in(FMI_SD_INFO_T *pSD, UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr)
{
BOOL volatile bIsSendCmd=FALSE;
unsigned int volatile reg;
int volatile i, loop, status;
//--- check input parameters
status = fmiSDCheckSector(uSector, uBufcnt);
if (status < 0)
return status; // invalid sector
if (uBufcnt == 0)
{
sysprintf("ERROR: fmiSD_Write_in(): uBufcnt cannot be 0!!\n");
return FMI_SD_SELECT_ERROR;
}
if ((status = fmiSDCmdAndRsp(pSD, 7, pSD->uRCA, 0)) != Successful)
return status;
fmiCheckRB();
// According to SD Spec v2.0, the write CMD block size MUST be 512, and the start address MUST be 512*n.
outpw(REG_SDBLEN, SD_BLOCK_SIZE - 1); // set the block size
if ((pSD->uCardType == FMI_TYPE_SD_HIGH) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
outpw(REG_SDARG, uSector);
else
outpw(REG_SDARG, uSector * SD_BLOCK_SIZE); // set start address for SD CMD
outpw(REG_DMACSAR, uSAddr);
loop = uBufcnt / 255; // the maximum block count is 0xFF=255 for register SDCR[BLK_CNT]
for (i=0; i<loop; i++)
{
#ifdef _SIC_USE_INT_
_fmi_bIsSDDataReady = FALSE;
#endif //_SIC_USE_INT_
reg = inpw(REG_SDCR) & 0xff00c080;
reg = reg | 0xff0000; // set BLK_CNT to 0xFF=255
if (!bIsSendCmd)
{
outpw(REG_SDCR, reg|(25<<8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DO_EN));
bIsSendCmd = TRUE;
}
else
outpw(REG_SDCR, reg | SDCR_DO_EN);
#ifdef _SIC_USE_INT_
while(!_fmi_bIsSDDataReady)
#else
while(1)
#endif //_SIC_USE_INT_
{
#ifndef _SIC_USE_INT_
if ((inpw(REG_SDISR) & SDISR_BLKD_IF) && (!(inpw(REG_SDCR) & SDCR_DO_EN)))
{
outpw(REG_SDISR, SDISR_BLKD_IF);
break;
}
#endif
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
/* Call schedule() to release CPU power to other tasks during waiting SIC/DMA completed. */
schedule();
}
if ((inpw(REG_SDISR) & SDISR_CRC_IF) != 0) // check CRC
{
#ifdef DEBUG
sysprintf("1. fmiSD_Write:write data error [SDISR = 0x%08X]\n", inpw(REG_SDISR));
#endif
outpw(REG_SDISR, SDISR_CRC_IF);
return FMI_SD_CRC_ERROR;
}
}
loop = uBufcnt % 255;
if (loop != 0)
{
#ifdef _SIC_USE_INT_
_fmi_bIsSDDataReady = FALSE;
#endif //_SIC_USE_INT_
reg = (inpw(REG_SDCR) & 0xff00c080) | (loop << 16);
if (!bIsSendCmd)
{
outpw(REG_SDCR, reg|(25<<8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DO_EN));
bIsSendCmd = TRUE;
}
else
outpw(REG_SDCR, reg | SDCR_DO_EN);
#ifdef _SIC_USE_INT_
while(!_fmi_bIsSDDataReady)
#else
while(1)
#endif //_SIC_USE_INT_
{
#ifndef _SIC_USE_INT_
if ((inpw(REG_SDISR) & SDISR_BLKD_IF) && (!(inpw(REG_SDCR) & SDCR_DO_EN)))
{
outpw(REG_SDISR, SDISR_BLKD_IF);
break;
}
#endif
if (pSD == pSD0)
fmiSD_CardStatus();
if (pSD->bIsCardInsert == FALSE)
return FMI_NO_SD_CARD;
/* Call schedule() to release CPU power to other tasks during waiting SIC/DMA completed. */
schedule();
}
if ((inpw(REG_SDISR) & SDISR_CRC_IF) != 0) // check CRC
{
#ifdef DEBUG
sysprintf("2. fmiSD_Write:write data error [SDISR = 0x%08X]\n", inpw(REG_SDISR));
#endif
outpw(REG_SDISR, SDISR_CRC_IF);
return FMI_SD_CRC_ERROR;
}
}
outpw(REG_SDISR, SDISR_CRC_IF);
if (fmiSDCmdAndRsp(pSD, 12, 0, 0)) // stop command
{
#ifdef DEBUG
sysprintf("stop command fail !!\n");
#endif
return FMI_SD_CRC7_ERROR;
}
fmiCheckRB();
fmiSDCommand(pSD, 7, 0);
// According to SD spec v2.0 chapter 4.4,
// "After the last SD Memory Card bus transaction, the host is required,
// to provide 8 (eight) clock cycles for the card to complete the
// operation before shutting down the clock."
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);
return Successful;
}
VOID fmiGet_SD_info(FMI_SD_INFO_T *pSD, DISK_DATA_T *_info)
{
unsigned int i;
unsigned int R_LEN, C_Size, MULT, size;
unsigned int Buffer[4];
unsigned char *ptr;
int volatile status;
fmiSDCmdAndRsp2(pSD, 9, pSD->uRCA, Buffer);
#ifdef DEBUG
sysprintf("max. data transfer rate [%x][%08x]\n", Buffer[0]&0xff, Buffer[0]);
sysprintf("CSD = 0x%08X 0x%08X 0x%08X 0x%08X\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
#endif
if ((pSD->uCardType == FMI_TYPE_MMC) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
{
// for MMC/eMMC card
if ((Buffer[0] & 0xc0000000) == 0xc0000000)
{
// CSD_STRUCTURE [127:126] is 3
// CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB
fmiSDCmdAndRsp(pSD, 7, pSD->uRCA, 0);
_fmi_pSDHCBuffer = (UINT8 *)((UINT32)_fmi_ucSDHCBuffer | 0x80000000);
outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer); // set DMA transfer starting address
outpw(REG_SDBLEN, 511); // read 512 bytes for EXT_CSD
if ((status = fmiSDCmdAndRspDataIn(pSD, 8, 0x00)) != Successful)
return;
fmiSDCommand(pSD, 7, 0);
// According to SD spec v2.0 chapter 4.4,
// "After the last SD Memory Card bus transaction, the host is required,
// to provide 8 (eight) clock cycles for the card to complete the
// operation before shutting down the clock."
outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);
_info->totalSectorN = (*(UINT32 *)(_fmi_pSDHCBuffer+212));
_info->diskSize = _info->totalSectorN / 2;
}
else
{
// CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB
R_LEN = (Buffer[1] & 0x000f0000) >> 16;
C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30);
MULT = (Buffer[2] & 0x00038000) >> 15;
size = (C_Size+1) * (1<<(MULT+2)) * (1<<R_LEN);
_info->diskSize = size / 1024;
_info->totalSectorN = size / 512;
}
}
else
{
// for SD/SDHC card
if ((Buffer[0] & 0xc0000000) && (pSD->uCardType != FMI_TYPE_MMC))
{
// CSD version 2.0 in SD v2.0 spec for SDHC card
C_Size = ((Buffer[1] & 0x0000003f) << 16) | ((Buffer[2] & 0xffff0000) >> 16);
size = (C_Size+1) * 512; // Kbytes
_info->diskSize = size;
_info->totalSectorN = size << 1;
}
else
{
// CSD version 1.0 in SD v2.0 spec for SD card
R_LEN = (Buffer[1] & 0x000f0000) >> 16;
C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30);
MULT = (Buffer[2] & 0x00038000) >> 15;
size = (C_Size+1) * (1<<(MULT+2)) * (1<<R_LEN);
_info->diskSize = size / 1024;
_info->totalSectorN = size / 512;
}
}
_info->sectorSize = 512;
g_max_valid_sector = _info->totalSectorN;
fmiSDCmdAndRsp2(pSD, 10, pSD->uRCA, Buffer);
_info->vendor[0] = (Buffer[0] & 0xff000000) >> 24;
ptr = (unsigned char *)Buffer;
ptr = (unsigned char *)Buffer + 3;
for (i=0; i<5; i++)
_info->product[i] = *ptr++;
ptr = (unsigned char *)Buffer + 9;
for (i=0; i<4; i++)
_info->serial[i] = *ptr++;
#ifdef DEBUG
sysprintf("SD card CID is %08X-%08X-%08X-%08X\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
#endif
}
#if 0
INT fmiSD_CardStatus()
{
if (g_SD0_card_detect)
{
if (inpw(REG_SDISR) & SDISR_CD_Card) // CD pin status
{
pSD0->bIsCardInsert = FALSE;
return FMI_NO_SD_CARD;
}
else
{
pSD0->bIsCardInsert = TRUE;
return 0;
}
}
else
{
pSD0->bIsCardInsert = TRUE; // always report card inserted.
return 0;
}
}
#define DISK_TYPE_SD_MMC 0x00000020
INT fmiInitSDDevice(INT cardSel) /* int sd_init_onedisk(INT i) */
{
PDISK_T *pDisk;
DISK_DATA_T* pSDDisk;
FMI_SD_INFO_T *pSD_temp = NULL;
int volatile rate, i;
if(sd0_ok)
SD_DiskInfo0.totalSectorN;
//Reset FMI
outpw(REG_FMICR, FMI_SWRST); // Start reset FMI controller.
while(inpw(REG_FMICR)&FMI_SWRST);
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_SWRST); // SD software reset
while(inpw(REG_SDCR) & SDCR_SWRST);
outpw(REG_SDCR, inpw(REG_SDCR) & ~0xFF); // disable SD clock ouput
if (cardSel == 0)
{
if(sd0_ok == 1)
return(0);
pSDDisk = &SD_DiskInfo0;
}
else if (cardSel == 1)
{
if(sd1_ok == 1)
return(0);
pSDDisk = &SD_DiskInfo1;
}
else if (cardSel == 2)
{
if(sd2_ok == 1)
return(0);
pSDDisk = &SD_DiskInfo2;
}
// enable SD-0/1/2 pin?
if (fmiSD_CardSel(cardSel))
return FMI_NO_SD_CARD;
//Enable SD-0 card detectipn pin
if (cardSel==0)
{
if (g_SD0_card_detect)
outpw(REG_GPAFUN, inpw(REG_GPAFUN) | MF_GPA1); // GPA1 for SD-0 card detection
outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CDSRC); // SD card detection source from GPIO but not DAT3
}
// Disable FMI/SD host interrupt
outpw(REG_FMIIER, 0);
// outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_SDNWR) | (0x01 << 24)); // set SDNWR = 1
outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_SDNWR) | (0x09 << 24)); // set SDNWR = 9
outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_BLKCNT) | (0x01 << 16)); // set BLKCNT = 1
outpw(REG_SDCR, inpw(REG_SDCR) & ~SDCR_DBW); // SD 1-bit data bus
outpw(REG_SDTMOUT,0xFFFFFF);
pSD_temp = (FMI_SD_INFO_T *)malloc(sizeof(FMI_SD_INFO_T)+4);
if (pSD_temp == NULL)
return FMI_NO_MEMORY;
memset((char *)pSD_temp, 0, sizeof(FMI_SD_INFO_T)+4);
if (cardSel==0)
{
pSD0_offset = (UINT32)pSD_temp %4;
pSD0 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD0_offset);
}
else if (cardSel==1)
{
pSD1_offset = (UINT32)pSD_temp %4;
pSD1 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD1_offset);
}
else if (cardSel==2)
{
pSD2_offset = (UINT32)pSD_temp %4;
pSD2 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD2_offset);
}
outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CDSRC); // select GPIO detect
outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CD_IEN); // enable card detect interrupt
if (cardSel==0)
{
if (fmiSD_CardStatus() == FMI_NO_SD_CARD)
{
if (pSD0 != NULL)
{
free((FMI_SD_INFO_T *)((UINT32)pSD0 - pSD0_offset));
pSD0 = 0;
}
free((FMI_SD_INFO_T *)((UINT32)pSD0 - pSD0_offset));
sysprintf("ERROR: fmiInitSDDevice(): SD port %d has no card ! REG_SDISR = 0x%08X\n", cardSel, inpw(REG_SDISR));
return FMI_NO_SD_CARD;
}
if (fmiSD_Init(pSD0) < 0)
return FMI_SD_INIT_ERROR;
/* divider */
if (pSD0->uCardType == FMI_TYPE_MMC)
rate = _fmi_uFMIReferenceClock / MMC_FREQ;
else if (pSD0->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
else
rate = _fmi_uFMIReferenceClock / SD_FREQ;
if (pSD0->uCardType == FMI_TYPE_MMC)
{
if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
rate ++;
}
else if (pSD0->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
{
if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
rate ++;
}
else
{
if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
rate ++;
}
}
else if (cardSel==1)
{
// SD-1 no card detect
pSD1->bIsCardInsert = TRUE;
// SD-1 initial
if (fmiSD_Init(pSD1) < 0)
return FMI_SD_INIT_ERROR;
/* divider */
if (pSD1->uCardType == FMI_TYPE_MMC)
rate = _fmi_uFMIReferenceClock / MMC_FREQ;
else if (pSD1->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
else
rate = _fmi_uFMIReferenceClock / SD_FREQ;
if (pSD1->uCardType == FMI_TYPE_MMC)
{
if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
rate ++;
}
else if (pSD1->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
{
if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
rate ++;
}
else
{
if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
rate ++;
}
}
else if (cardSel==2)
{
// SD-2 no card detect
pSD2->bIsCardInsert = TRUE;
// SD-2 initial
if (fmiSD_Init(pSD2) < 0)
return FMI_SD_INIT_ERROR;
/* divider */
if (pSD2->uCardType == FMI_TYPE_MMC)
rate = _fmi_uFMIReferenceClock / MMC_FREQ;
else if (pSD2->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
else
rate = _fmi_uFMIReferenceClock / SD_FREQ;
if (pSD2->uCardType == FMI_TYPE_MMC)
{
if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
rate ++;
}
else if (pSD2->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
{
if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
rate ++;
}
else
{
if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
rate ++;
}
}
for(i=0; i<100; i++);
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_S) | (0x03 << 19)); // SD clock from UPLL
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N0) | (0x01 << 16)); // SD clock divided by 2
if (rate % 2)
{
rate /= 2;
rate &= 0xFF;
}
else
{
rate /= 2;
rate &= 0xFF;
rate--;
}
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N1) | (rate << 24)); // SD clock divider
for(i=0; i<1000; i++);
/* init SD interface */
if (cardSel==0)
{
fmiGet_SD_info(pSD0, pSDDisk);
if (fmiSelectCard(pSD0))
return FMI_SD_SELECT_ERROR;
}
else if (cardSel==1)
{
fmiGet_SD_info(pSD1, pSDDisk);
if (fmiSelectCard(pSD1))
return FMI_SD_SELECT_ERROR;
}
else if (cardSel==2)
{
fmiGet_SD_info(pSD2, pSDDisk);
if (fmiSelectCard(pSD2))
return FMI_SD_SELECT_ERROR;
}
/*
* Create physical disk descriptor
*/
pDisk = (PDISK_T *)malloc(sizeof(PDISK_T));
if (pDisk == NULL)
return FMI_NO_MEMORY;
memset((char *)pDisk, 0, sizeof(PDISK_T));
/* read Disk information */
pDisk->szManufacture[0] = '\0';
strcpy(pDisk->szProduct, (char *)pSDDisk->product);
strcpy(pDisk->szSerialNo, (char *)pSDDisk->serial);
pDisk->nDiskType = DISK_TYPE_SD_MMC;
pDisk->nPartitionN = 0;
//pDisk->ptPartList = NULL;
pDisk->nSectorSize = 512;
pDisk->uTotalSectorN = pSDDisk->totalSectorN;
pDisk->uDiskSize = pSDDisk->diskSize;
/* create relationship between UMAS device and file system hard disk device */
#ifdef DEBUG
printf("SD disk found: size=%d MB\n", (int)pDisk->uDiskSize / 1024);
#endif
if (cardSel == 0)
sd0_ok = 1;
else if (cardSel == 1)
sd1_ok = 1;
else if (cardSel == 2)
sd2_ok = 1;
return pDisk->uTotalSectorN;
}
#endif
INT fmiSD_CardSel00(INT cardSel)
{
if (cardSel==0)
{
outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x0000FFF0) | 0x0000aaa0); // SD0_CLK/CMD/DAT0_3 pins selected
outpw(REG_SDCR, inpw(REG_SDCR) & (~SDCR_SDPORT)); // SD_0 port selected
}
else if (cardSel==1)
{
outpw(REG_GPBFUN, inpw(REG_GPBFUN)&(~0x00000FFF) | 0x00000AAA); // SD1_CLK_CMD_DAT0_3 pins selected
outpw(REG_SDCR, inpw(REG_SDCR) & (~0x60000000) | 0x20000000); // SD_1 port selected
}
else if (cardSel==2)
{
outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x000F0000) | 0x00050000); // SD2_DAT0_1 pins selected
outpw(REG_GPDFUN, inpw(REG_GPDFUN)&(~0x0003FC00) | 0x00015400); // SD2_CLK/CMD/DAT2_3 pins selected
outpw(REG_SDCR, inpw(REG_SDCR) & (~0x60000000) | 0x40000000); // SD_2 port selected
}
else
return 1; // wrong SD card select
//--- 2014/2/26, Reset SD controller and DMAC to keep clean status for next access.
// Reset DMAC engine and interrupt satus
outpw(REG_DMACCSR, inpw(REG_DMACCSR) | DMAC_SWRST | DMAC_EN);
while(inpw(REG_DMACCSR) & DMAC_SWRST);
outpw(REG_DMACCSR, inpw(REG_DMACCSR) | DMAC_EN);
outpw(REG_DMACISR, WEOT_IF | TABORT_IF); // clear all interrupt flag
// Reset FMI engine and interrupt status
outpw(REG_FMICR, FMI_SWRST);
while(inpw(REG_FMICR) & FMI_SWRST);
outpw(REG_FMIISR, FMI_DAT_IF); // clear all interrupt flag
// Reset SD engine and interrupt status
outpw(REG_FMICR, FMI_SD_EN);
outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_SWRST);
while(inpw(REG_SDCR) & SDCR_SWRST);
outpw(REG_SDISR, 0xFFFFFFFF); // clear all interrupt flag
return 0;
}
INT sicSdRead00(INT32 sdSectorNo, INT32 sdSectorCount, INT32 sdTargetAddr)
{
if (fmiSD_CardSel(0))
return FMI_NO_SD_CARD;
return fmiSD_Read(sdSectorNo, sdSectorCount, sdTargetAddr);
}
INT fmiSD_Read00(UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr)
{
int status=0;
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Read_in(pSD0, uSector, uBufcnt, uDAddr);
return status;
}
INT fmiSD_Write00(UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr)
{
int status=0;
if (fmiSD_CardSel(0))
return FMI_NO_SD_CARD;
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Write_in(pSD0, uSector, uBufcnt, uSAddr);
return status;
}
UINT32 SdGetTotalSector()
{
return 0;
}
/*-----------------------------------------------------------------------------
* Get SD card status for SD port 0 and assign the status to global value pSD0->bIsCardInsert.
* Return: 0 is SD card inserted;
* FMI_NO_SD_CARD is SD card removed.
*---------------------------------------------------------------------------*/
INT fmiSD_CardStatus()
{
if (g_SD0_card_detect)
{
if (inpw(REG_SDISR) & SDISR_CD_Card) // CD pin status
{
pSD0->bIsCardInsert = FALSE;
return FMI_NO_SD_CARD;
}
else
{
pSD0->bIsCardInsert = TRUE;
return 0;
}
}
else
{
pSD0->bIsCardInsert = TRUE; // always report card inserted.
return 0;
}
}
sd.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef _SD_H
#define _SD_H
#include "Common.h"
INT fmiSD_Read(UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr);
INT fmiSD_Write(UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr);
INT fmiInitSDDevice(int cardSel);
VOID fmiInitDevice(VOID);
UINT32 SdGetTotalSector(VOID);
#endif
SDGlue.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential */
/* */
/* Copyright (c) 2008 by Nuvoton Technology Corporation */
/* All rights reserved */
/* */
/*-----------------------------------------------------------------------------------*/
/*
* Driver for FMI devices
* SD layer glue code
*
*/
#if 1
#ifdef ECOS
#include "stdlib.h"
#include "string.h"
#include "drv_api.h"
#include "diag.h"
#include "wbtypes.h"
#include "wbio.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"
#endif
#include "w55fa93_reg.h"
#include "w55fa93_sic.h"
#include "fmi.h"
#include "nvtfat.h"
FMI_SD_INFO_T *pSD0 = NULL;
FMI_SD_INFO_T *pSD1 = NULL;
FMI_SD_INFO_T *pSD2 = NULL;
UINT8 pSD0_offset = 0;
UINT8 pSD1_offset = 0;
UINT8 pSD2_offset = 0;
PDISK_T *pDisk_SD0 = NULL;
PDISK_T *pDisk_SD1 = NULL;
PDISK_T *pDisk_SD2 = NULL;
extern DISK_DATA_T SD_DiskInfo0;
extern DISK_DATA_T SD_DiskInfo1;
extern DISK_DATA_T SD_DiskInfo2;
INT32 g_SD0_card_detect = FALSE; // default is DISABLE SD0 card detect feature.
extern INT fsPhysicalDiskConnected(PDISK_T *pDisk);
static INT sd_disk_init(PDISK_T *lDisk)
{
return 0;
}
static INT sd_disk_ioctl(PDISK_T *lDisk, INT control, VOID *param)
{
return 0;
}
static INT sd_disk_read(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff)
{
int status;
fmiSD_CardSel(0);
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Read_in(pSD0, sector_no, number_of_sector, (unsigned int)buff);
if (status != Successful)
return status;
return FS_OK;
}
static INT sd_disk_write(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff, BOOL IsWait)
{
int status;
fmiSD_CardSel(0);
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Write_in(pSD0, sector_no, number_of_sector, (unsigned int)buff);
if (status != Successful)
return status;
return FS_OK;
}
static INT sd_disk_init0(PDISK_T *lDisk)
{
return 0;
}
static INT sd_disk_ioctl0(PDISK_T *lDisk, INT control, VOID *param)
{
return 0;
}
static INT sd_disk_read0(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff)
{
return sd_disk_read(pDisk, sector_no, number_of_sector, buff);
}
static INT sd_disk_write0(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff, BOOL IsWait)
{
return sd_disk_write(pDisk, sector_no, number_of_sector, buff, IsWait);
}
static INT sd_disk_init1(PDISK_T *lDisk)
{
return 0;
}
static INT sd_disk_ioctl1(PDISK_T *lDisk, INT control, VOID *param)
{
return 0;
}
static INT sd_disk_read1(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff)
{
int status;
fmiSD_CardSel(1);
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Read_in(pSD1, sector_no, number_of_sector, (unsigned int)buff);
if (status != Successful)
return status;
return FS_OK;
}
static INT sd_disk_write1(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff, BOOL IsWait)
{
int status;
fmiSD_CardSel(1);
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Write_in(pSD1, sector_no, number_of_sector, (unsigned int)buff);
if (status != Successful)
return status;
return FS_OK;
}
static INT sd_disk_init2(PDISK_T *lDisk)
{
return 0;
}
static INT sd_disk_ioctl2(PDISK_T *lDisk, INT control, VOID *param)
{
return 0;
}
static INT sd_disk_read2(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff)
{
int status;
fmiSD_CardSel(2);
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Read_in(pSD2, sector_no, number_of_sector, (unsigned int)buff);
if (status != Successful)
return status;
return FS_OK;
}
static INT sd_disk_write2(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff, BOOL IsWait)
{
int status;
fmiSD_CardSel(2);
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Write_in(pSD2, sector_no, number_of_sector, (unsigned int)buff);
if (status != Successful)
return status;
return FS_OK;
}
STORAGE_DRIVER_T _SDDiskDriver =
{
sd_disk_init,
sd_disk_read,
sd_disk_write,
sd_disk_ioctl
};
STORAGE_DRIVER_T _SD0DiskDriver =
{
sd_disk_init0,
sd_disk_read0,
sd_disk_write0,
sd_disk_ioctl0
};
STORAGE_DRIVER_T _SD1DiskDriver =
{
sd_disk_init1,
sd_disk_read1,
sd_disk_write1,
sd_disk_ioctl1
};
STORAGE_DRIVER_T _SD2DiskDriver =
{
sd_disk_init2,
sd_disk_read2,
sd_disk_write2,
sd_disk_ioctl2
};
static int sd0_ok = 0;
static int sd1_ok = 0;
static int sd2_ok = 0;
INT fmiSD_CardSel(INT cardSel)
{
if (cardSel==0)
{
outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x0000FFF0) | 0x0000aaa0); // SD0_CLK/CMD/DAT0_3 pins selected
outpw(REG_SDCR, inpw(REG_SDCR) & (~SDCR_SDPORT)); // SD_0 port selected
}
else if (cardSel==1)
{
outpw(REG_GPBFUN, inpw(REG_GPBFUN)&(~0x00000FFF) | 0x00000AAA); // SD1_CLK_CMD_DAT0_3 pins selected
outpw(REG_SDCR, inpw(REG_SDCR) & (~0x60000000) | 0x20000000); // SD_1 port selected
}
else if (cardSel==2)
{
outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x000F0000) | 0x00050000); // SD2_DAT0_1 pins selected
outpw(REG_GPDFUN, inpw(REG_GPDFUN)&(~0x0003FC00) | 0x00015400); // SD2_CLK/CMD/DAT2_3 pins selected
outpw(REG_SDCR, inpw(REG_SDCR) & (~0x60000000) | 0x40000000); // SD_2 port selected
}
else
return 1; // wrong SD card select
//--- 2014/2/26, Reset SD controller and DMAC to keep clean status for next access.
// Reset DMAC engine and interrupt satus
outpw(REG_DMACCSR, inpw(REG_DMACCSR) | DMAC_SWRST | DMAC_EN);
while(inpw(REG_DMACCSR) & DMAC_SWRST);
outpw(REG_DMACCSR, inpw(REG_DMACCSR) | DMAC_EN);
outpw(REG_DMACISR, WEOT_IF | TABORT_IF); // clear all interrupt flag
// Reset FMI engine and interrupt status
outpw(REG_FMICR, FMI_SWRST);
while(inpw(REG_FMICR) & FMI_SWRST);
outpw(REG_FMIISR, FMI_DAT_IF); // clear all interrupt flag
// Reset SD engine and interrupt status
outpw(REG_FMICR, FMI_SD_EN);
outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_SWRST);
while(inpw(REG_SDCR) & SDCR_SWRST);
outpw(REG_SDISR, 0xFFFFFFFF); // clear all interrupt flag
return 0;
}
INT fmiInitSDDevice(INT cardSel) /* int sd_init_onedisk(INT i) */
{
PDISK_T *pDisk;
DISK_DATA_T* pSDDisk;
FMI_SD_INFO_T *pSD_temp = NULL;
int volatile rate, i;
//Reset FMI
outpw(REG_FMICR, FMI_SWRST); // Start reset FMI controller.
while(inpw(REG_FMICR)&FMI_SWRST);
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_SWRST); // SD software reset
while(inpw(REG_SDCR) & SDCR_SWRST);
outpw(REG_SDCR, inpw(REG_SDCR) & ~0xFF); // disable SD clock ouput
if (cardSel == 0)
{
if(sd0_ok == 1)
return(0);
pSDDisk = &SD_DiskInfo0;
}
else if (cardSel == 1)
{
if(sd1_ok == 1)
return(0);
pSDDisk = &SD_DiskInfo1;
}
else if (cardSel == 2)
{
if(sd2_ok == 1)
return(0);
pSDDisk = &SD_DiskInfo2;
}
// enable SD-0/1/2 pin?
if (fmiSD_CardSel(cardSel))
return FMI_NO_SD_CARD;
//Enable SD-0 card detectipn pin
if (cardSel==0)
{
if (g_SD0_card_detect)
outpw(REG_GPAFUN, inpw(REG_GPAFUN) | MF_GPA1); // GPA1 for SD-0 card detection
outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CDSRC); // SD card detection source from GPIO but not DAT3
}
// Disable FMI/SD host interrupt
outpw(REG_FMIIER, 0);
// outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_SDNWR) | (0x01 << 24)); // set SDNWR = 1
outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_SDNWR) | (0x09 << 24)); // set SDNWR = 9
outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_BLKCNT) | (0x01 << 16)); // set BLKCNT = 1
outpw(REG_SDCR, inpw(REG_SDCR) & ~SDCR_DBW); // SD 1-bit data bus
outpw(REG_SDTMOUT,0xFFFFFF);
pSD_temp = malloc(sizeof(FMI_SD_INFO_T)+4);
if (pSD_temp == NULL)
return FMI_NO_MEMORY;
memset((char *)pSD_temp, 0, sizeof(FMI_SD_INFO_T)+4);
if (cardSel==0)
{
pSD0_offset = (UINT32)pSD_temp %4;
pSD0 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD0_offset);
}
else if (cardSel==1)
{
pSD1_offset = (UINT32)pSD_temp %4;
pSD1 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD1_offset);
}
else if (cardSel==2)
{
pSD2_offset = (UINT32)pSD_temp %4;
pSD2 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD2_offset);
}
outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CDSRC); // select GPIO detect
outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CD_IEN); // enable card detect interrupt
if (cardSel==0)
{
if (fmiSD_CardStatus() == FMI_NO_SD_CARD)
{
if (pSD0 != NULL)
{
free((FMI_SD_INFO_T *)((UINT32)pSD0 - pSD0_offset));
pSD0 = 0;
}
free((FMI_SD_INFO_T *)((UINT32)pSD0 - pSD0_offset));
sysprintf("ERROR: fmiInitSDDevice(): SD port %d has no card ! REG_SDISR = 0x%08X\n", cardSel, inpw(REG_SDISR));
return FMI_NO_SD_CARD;
}
if (fmiSD_Init(pSD0) < 0)
return FMI_SD_INIT_ERROR;
/* divider */
if (pSD0->uCardType == FMI_TYPE_MMC)
rate = _fmi_uFMIReferenceClock / MMC_FREQ;
else if (pSD0->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
else
rate = _fmi_uFMIReferenceClock / SD_FREQ;
if (pSD0->uCardType == FMI_TYPE_MMC)
{
if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
rate ++;
}
else if (pSD0->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
{
if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
rate ++;
}
else
{
if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
rate ++;
}
}
else if (cardSel==1)
{
// SD-1 no card detect
pSD1->bIsCardInsert = TRUE;
// SD-1 initial
if (fmiSD_Init(pSD1) < 0)
return FMI_SD_INIT_ERROR;
/* divider */
if (pSD1->uCardType == FMI_TYPE_MMC)
rate = _fmi_uFMIReferenceClock / MMC_FREQ;
else if (pSD1->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
else
rate = _fmi_uFMIReferenceClock / SD_FREQ;
if (pSD1->uCardType == FMI_TYPE_MMC)
{
if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
rate ++;
}
else if (pSD1->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
{
if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
rate ++;
}
else
{
if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
rate ++;
}
}
else if (cardSel==2)
{
// SD-2 no card detect
pSD2->bIsCardInsert = TRUE;
// SD-2 initial
if (fmiSD_Init(pSD2) < 0)
return FMI_SD_INIT_ERROR;
/* divider */
if (pSD2->uCardType == FMI_TYPE_MMC)
rate = _fmi_uFMIReferenceClock / MMC_FREQ;
else if (pSD2->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
else
rate = _fmi_uFMIReferenceClock / SD_FREQ;
if (pSD2->uCardType == FMI_TYPE_MMC)
{
if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
rate ++;
}
else if (pSD2->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
{
if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
rate ++;
}
else
{
if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
rate ++;
}
}
for(i=0; i<100; i++);
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_S) | (0x03 << 19)); // SD clock from UPLL
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N0) | (0x01 << 16)); // SD clock divided by 2
if (rate % 2)
{
rate /= 2;
rate &= 0xFF;
}
else
{
rate /= 2;
rate &= 0xFF;
rate--;
}
outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N1) | (rate << 24)); // SD clock divider
for(i=0; i<1000; i++);
/* init SD interface */
if (cardSel==0)
{
fmiGet_SD_info(pSD0, pSDDisk);
if (fmiSelectCard(pSD0))
return FMI_SD_SELECT_ERROR;
}
else if (cardSel==1)
{
fmiGet_SD_info(pSD1, pSDDisk);
if (fmiSelectCard(pSD1))
return FMI_SD_SELECT_ERROR;
}
else if (cardSel==2)
{
fmiGet_SD_info(pSD2, pSDDisk);
if (fmiSelectCard(pSD2))
return FMI_SD_SELECT_ERROR;
}
/*
* Create physical disk descriptor
*/
pDisk = malloc(sizeof(PDISK_T));
if (pDisk == NULL)
return FMI_NO_MEMORY;
memset((char *)pDisk, 0, sizeof(PDISK_T));
/* read Disk information */
pDisk->szManufacture[0] = '\0';
strcpy(pDisk->szProduct, (char *)pSDDisk->product);
strcpy(pDisk->szSerialNo, (char *)pSDDisk->serial);
pDisk->nDiskType = DISK_TYPE_SD_MMC;
pDisk->nPartitionN = 0;
//pDisk->ptPartList = NULL;
pDisk->nSectorSize = 512;
pDisk->uTotalSectorN = pSDDisk->totalSectorN;
pDisk->uDiskSize = pSDDisk->diskSize;
/* create relationship between UMAS device and file system hard disk device */
if (cardSel==0)
pDisk->ptDriver = &_SD0DiskDriver;
else if (cardSel==1)
pDisk->ptDriver = &_SD1DiskDriver;
else if (cardSel==2)
pDisk->ptDriver = &_SD2DiskDriver;
#ifdef DEBUG
printf("SD disk found: size=%d MB\n", (int)pDisk->uDiskSize / 1024);
#endif
if (cardSel==0)
{
pDisk_SD0 = pDisk;
}
else if (cardSel==1)
{
pDisk_SD1 = pDisk;
}
else if (cardSel==2)
{
pDisk_SD2 = pDisk;
}
//fsPhysicalDiskConnected(pDisk);
if (cardSel == 0)
sd0_ok = 1;
else if (cardSel == 1)
sd1_ok = 1;
else if (cardSel == 2)
sd2_ok = 1;
return pDisk->uTotalSectorN;
}
INT fmiSD_Read(UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr)
{
int status=0;
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Read_in(pSD0, uSector, uBufcnt, uDAddr);
return status;
}
INT fmiSD_Write(UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr)
{
int status=0;
// enable SD
outpw(REG_FMICR, FMI_SD_EN);
status = fmiSD_Write_in(pSD0, uSector, uBufcnt, uSAddr);
return status;
}
/*-----------------------------------------------------------------------------------*/
/* Function: */
/* sicSdOpen */
/* */
/* Parameters: */
/* sdPortNo SD port number(port0 or port1). */
/* */
/* Returns: */
/* >0 Total sector. */
/* FMI_NO_SD_CARD No SD card insert. */
/* FMI_SD_INIT_ERROR Card initial and identify error. */
/* FMI_SD_SELECT_ERROR Select card from identify mode to stand-by mode error. */
/* */
/* Side effects: */
/* None. */
/* */
/* Description: */
/* This function initial SD from identification to stand-by mode. */
/* */
/*-----------------------------------------------------------------------------------*/
INT sicSdOpen_sel(INT cardSel)
{
return fmiInitSDDevice(cardSel);
}
INT sicSdOpen(void)
{
return fmiInitSDDevice(0);
}
INT sicSdOpen0(void)
{
return fmiInitSDDevice(0);
}
INT sicSdOpen1(void)
{
return fmiInitSDDevice(1);
}
INT sicSdOpen2(void)
{
return fmiInitSDDevice(2);
}
#endif
Smpl_Pdma_SPI.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"
#include "w55fa93_edma.h"
#include "w55fa93_gpio.h"
#include "w55fa93_spi.h"
#define TEST_SIZE 4 * 1024
__align(4096) UINT8 WriteBuffer[TEST_SIZE];
__align(4096) UINT8 ReadBuffer[TEST_SIZE];
static INT32 g_PdmaCh = 0;
volatile static BOOL g_bPdmaInt = FALSE;
void SPI_SwitchToTPH() {
//1.spi_in config to GPIO
outpw(REG_GPBFUN , inpw(REG_GPBFUN) & (~BIT23) & (~BIT22)); //B11 latch
gpio_setportdir(GPIO_PORTB, BIT11, BIT11);
//2.config freq
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | (1 << 11));//clk idle high
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & (~(1 << 10)));//MSB first
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & (~(0x1f << 3)));
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | (8 << 3));//8 BIT
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & (~(1 << 2)));//tx on rising
#if defined(CPU_144MHZ_MODE)
spiIoctl(1, SPI_SET_CLOCK, 72, 9000);
#else
spiIoctl(1, SPI_SET_CLOCK, /*96*/48, 8000); // ch_20220802 : APB clock should be 48.
#endif
spiTxLen(1, 0, 8);
//2.close cs0
//outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);
//spiTxLen(0, 0, 8);
}
void SPI_SwitchToFlash(VOID)
{
#if defined(CPU_144MHZ_MODE)
spiIoctl(0, 0, 72, 18000);
#else
spiIoctl(0, 0, 48/*96*/, 12000); // ch_20220802 : APB clock should be 48.
#endif
//Startup SPI0 multi-function features, chip select using SS0
outpw(REG_GPDFUN, inpw(REG_GPDFUN) | 0xFF000000);
outpw(REG_SPI0_SSR, 0x00); // CS active low
outpw(REG_SPI0_CNTRL, 0x04); // Tx: falling edge, Rx: rising edge
}
void PdmaCallback_SPI(unsigned int arg)
{
EDMA_Free(g_PdmaCh);
g_bPdmaInt = TRUE;
}
int initSPIPDMA_Write(UINT32 src_addr, UINT32 dma_length)
{
g_PdmaCh = PDMA_FindandRequest();
EDMA_SetAPB(g_PdmaCh, //int channel,
eDRVEDMA_SPIMS0, //E_DRVEDMA_APB_DEVICE eDevice,
eDRVEDMA_WRITE_APB, //E_DRVEDMA_APB_RW eRWAPB,
eDRVEDMA_WIDTH_32BITS); //E_DRVEDMA_TRANSFER_WIDTH eTransferWidth
EDMA_SetupHandlers(g_PdmaCh, //int channel
eDRVEDMA_BLKD, //int interrupt,
PdmaCallback_SPI, //void (*irq_handler) (void *),
NULL); //void *data
EDMA_SetWrapINTType(g_PdmaCh , NULL);
EDMA_SetDirection(g_PdmaCh , eDRVEDMA_DIRECTION_INCREMENTED, eDRVEDMA_DIRECTION_FIXED);
EDMA_SetupSingle(g_PdmaCh, // int channel,
src_addr, // unsigned int src_addr, (ADC data port physical address)
REG_SPI0_TX0, //phaddrrecord, // unsigned int dest_addr,
dma_length); // unsigned int dma_length /* Lenth equal 2 half buffer */
return Successful;
}
int initSPIPDMA_Read(UINT32 dest_addr, UINT32 dma_length)
{
g_PdmaCh = PDMA_FindandRequest();
EDMA_SetAPB(g_PdmaCh, //int channel,
eDRVEDMA_SPIMS0, //E_DRVEDMA_APB_DEVICE eDevice,
eDRVEDMA_READ_APB, //E_DRVEDMA_APB_RW eRWAPB,
eDRVEDMA_WIDTH_32BITS); //E_DRVEDMA_TRANSFER_WIDTH eTransferWidth
EDMA_SetupHandlers(g_PdmaCh, //int channel
eDRVEDMA_BLKD, //int interrupt,
PdmaCallback_SPI, //void (*irq_handler) (void *),
NULL); //void *data
EDMA_SetWrapINTType(g_PdmaCh , NULL);
EDMA_SetDirection(g_PdmaCh , eDRVEDMA_DIRECTION_FIXED, eDRVEDMA_DIRECTION_INCREMENTED);
EDMA_SetupSingle(g_PdmaCh, // int channel,
REG_SPI0_RX0, // unsigned int src_addr, (ADC data port physical address)
dest_addr, //phaddrrecord, // unsigned int dest_addr,
dma_length); // unsigned int dma_length /* Lenth equal 2 half buffer */
return Successful;
}
INT spiFlashPDMAWrite(UINT32 addr, UINT32 len, UINT32 *buf)
{
int count=0, page, i;
count = len / 256;
if ((len % 256) != 0)
count++;
for (i=0; i<count; i++)
{
// check data len
if (len >= 256)
{
page = 256;
len = len - 256;
}
else
page = len;
usiWriteEnable();
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// write command
outpw(REG_SPI0_TX0, 0x02);
spiTxLen(0, 0, 8);
spiActive(0);
// address
outpw(REG_SPI0_TX0, addr+i*256);
spiTxLen(0, 0, 24);
spiActive(0);
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | BYTE_ENDIN);
spiTxLen(0, 0, 32);
initSPIPDMA_Write((UINT32)buf, page);
(UINT32)buf = (UINT32)buf + page;
EDMA_Trigger(g_PdmaCh);
outp32(REG_SPI0_EDMA, (inp32(REG_SPI0_EDMA) & ~0x03) | EDMA_GO);
while(g_bPdmaInt == FALSE);
g_bPdmaInt = FALSE;
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~BYTE_ENDIN);
spiTxLen(0, 0, 8);
outp32(REG_SPI0_EDMA, inp32(REG_SPI0_EDMA) & ~EDMA_GO);
// check status
if(usiCheckBusy(4*1.5*1000)!=Successful)
return Fail;
}
return Successful;
}
INT spiFlashPDMARead(UINT32 addr, UINT32 len, UINT32 *buf)
{
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// read command
outpw(REG_SPI0_TX0, 0x0b);
spiTxLen(0, 0, 8);
spiActive(0);
// address
outpw(REG_SPI0_TX0, addr);
spiTxLen(0, 0, 24);
spiActive(0);
// dummy byte
outp32(REG_SPI0_TX0, 0xff);
spiTxLen(0, 0, 8);
spiActive(0);
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | BYTE_ENDIN);
spiTxLen(0, 0, 32);
initSPIPDMA_Read((UINT32)buf, len);
EDMA_Trigger(g_PdmaCh);
outp32(REG_SPI0_EDMA, (inp32(REG_SPI0_EDMA) & ~0x03) | (EDMA_RW | EDMA_GO));
outp32(REG_SPI0_CNTRL, inp32(REG_SPI0_CNTRL) |GO_BUSY);
while(g_bPdmaInt == FALSE);
g_bPdmaInt = FALSE;
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~BYTE_ENDIN);
spiTxLen(0, 0, 8);
outp32(REG_SPI0_EDMA, inp32(REG_SPI0_EDMA) & ~EDMA_GO);
return Successful;
}
INT TPH_SpiEnd(VOID)
{
//clear status
outp32(REG_VDMA_ISR + 1 * 0x100, inp32(REG_VDMA_ISR + 1 * 0x100) | (EDMASG_IF | EDMABLKD_IF | EDMATABORT_IF));
outp32(REG_VDMA_IER + 1 * 0x100, inp32(REG_VDMA_IER + 1 * 0x100) & ~(SG_IEN | WAR_IE | BLKD_IE | EDMATABORT_IE));
outp32(REG_VDMA_CSR + 1 * 0x100, inp32(REG_VDMA_CSR + 1 * 0x100) & ~EDMACEN);
outp32(REG_AHBCLK,inp32(REG_AHBCLK) & ~(0x00000400 << 1));
//spiIoctl(0, 0, 48, 24000);
//g_bPdmaInt = TRUE;
return 0;
}
void TPH_SpiStart(UINT32 addr, UINT32 len, UINT32 type,void (*irq_handler) (void *))
{
UINT32 index;
UINT32 loop = 1000;
static int flag=1;
UINT32 PDMA_CSR=(eDRVEDMA_WIDTH_8BITS<<TRANSFER_WIDTH_BIT)|
(eDRVEDMA_MEMORY_TO_DEVICE << MODE_SELECT_BIT)|
(eDRVEDMA_DIRECTION_FIXED<<DESTINATION_DIRECTION_BIT) | TRIG_EN | EDMACEN;
unsigned char *pSrc;
pSrc = (UINT8 *)((UINT32)WriteBuffer | NON_CACHE_BIT);
/
// ch_20220802
// for (index = 0; index < len; index ++) {
// *(pSrc + index) = *((UINT8 *)addr + index);
// }
memcpy(pSrc, (UINT8 *)addr, len); // ch_20220802 : improve the issue of printing BLANK.
/
SPI_SwitchToTPH();
if(type)
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | LSB);
else
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) &(~LSB));
outp32(REG_AHBCLK,inp32(REG_AHBCLK) | (0x00000400 << 1)); // Enable Channel Clock
if(flag)
{
outp32(REG_EDSSR,(~CH1_TXSEL)|(0x01<<16));
sysInstallISR(IRQ_LEVEL_6, IRQ_EDMA, (PVOID)irq_handler);
sysSetInterruptType(IRQ_EDMA, HIGH_LEVEL_SENSITIVE);
outpw(REG_AIC_MECR, inp32(REG_AIC_MECR)|(1 << IRQ_EDMA));
outp32(REG_PDMA_SAR1, (UINT32)pSrc);
outp32(REG_PDMA_DAR1,REG_SPI1_TX0);
outp32(REG_PDMA_BCR1,len);
flag=0;
}
outp32(REG_PDMA_IER1, inp32(REG_PDMA_IER1)|(SG_IEN | BLKD_IE | EDMATABORT_IE));
outp32(REG_PDMA_CSR1, PDMA_CSR);
outp32(REG_SPI1_EDMA, (inp32(REG_SPI1_EDMA) & ~0x03) | EDMA_GO);
}
void test() {
}
spi.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential */
/* */
/* Copyright (c) 2008 by Nuvoton Technology Corporation */
/* All rights reserved */
/* */
/*-----------------------------------------------------------------------------------*/
/****************************************************************************
*
* FILENAME
* spi.c
*
* VERSION
* 1.0
*
* DESCRIPTION
* This file contains SPI library APIs.
*
* DATA STRUCTURES
* None
*
* FUNCTIONS
* None
*
* HISTORY
* 10/12/07 Create Ver 1.0
*
* REMARK
* None
**************************************************************************/
/* Header files */
#ifdef ECOS
#include "stdlib.h"
#include "string.h"
#include "drv_api.h"
#include "diag.h"
#include "Common.h"
#include "wbio.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"
#endif
#include "w55fa93_reg.h"
#include "w55fa93_spi.h"
//static PFN_DRVSPI_CALLBACK g_pfnSPI0callback = NULL;
//static PFN_DRVSPI_CALLBACK g_pfnSPI1callback = NULL;
/*-----------------------------------------------------------------------------------*/
int spiActive(int port)
{
if (port == 0)
{
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL)|0x01);
while(inpw(REG_SPI0_CNTRL) & 0x01);
}
else
{
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL)|0x01);
while(inpw(REG_SPI1_CNTRL) & 0x01);
}
return 0;
}
/*-----------------------------------------------------------------------------------*/
VOID spiSetGo(UINT8 u8Port)
{
UINT32 u32Reg;
if (u8Port == 0)
{
u32Reg = inpw(REG_SPI0_CNTRL);
outpw(REG_SPI0_CNTRL, u32Reg | GO_BUSY);
}
else
{
u32Reg = inpw(REG_SPI1_CNTRL);
outpw(REG_SPI1_CNTRL, u32Reg | GO_BUSY);
}
}
/*-----------------------------------------------------------------------------------*/
BOOL spiIsBusy(UINT8 u8Port)
{
UINT32 u32reg;
if(u8Port == 0)
u32reg = inpw(REG_SPI0_CNTRL);
else
u32reg = inpw(REG_SPI1_CNTRL);
return ((u32reg & GO_BUSY)?TRUE:FALSE);
}
/*-----------------------------------------------------------------------------------*/
int spiTxLen(int port, int count, int bitLen)
{
unsigned int reg;
if (port == 0)
reg = inpw(REG_SPI0_CNTRL);
else
reg = inpw(REG_SPI1_CNTRL);
if ((count < 0) || (count > 3))
return -1;
if ((bitLen <= 0) || (bitLen > 32))
return -1;
if (bitLen == 32)
reg = reg & 0xffffff07;
else
reg = (reg & 0xffffff07) | (bitLen << 3);
reg = (reg & 0xfffffcff) | (count << 8);
if (port == 0)
outpw(REG_SPI0_CNTRL, reg);
else
outpw(REG_SPI1_CNTRL, reg);
return 0;
}
/*-----------------------------------------------------------------------------------*/
void spiSetClock(int port, int clock_by_MHz, int output_by_kHz)
{
int volatile divider;
divider = (clock_by_MHz * 1000) / (2 * output_by_kHz) - 1;
if (port == 0)
outpw(REG_SPI0_DIVIDER, divider);
else
outpw(REG_SPI1_DIVIDER, divider);
}
/*-----------------------------------------------------------------------------------*/
static BOOL _spi_init_flag0 = FALSE, _spi_init_flag1 = FALSE;
int spiOpen(SPI_INFO_T *pInfo)
{
int volatile i;
if (pInfo->nPort == 0)
{
if(_spi_init_flag0)
{
sysprintf("SPI0 pin is unavailable!!\n");
return -1;
}
if (!_spi_init_flag0)
{
outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS0_CKE); // enable the clocks of SPI
outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI0RST);
outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI0RST);
for (i=0; i<200; i++);
outpw(REG_GPDFUN, inpw(REG_GPDFUN) | 0xFF000000); // enable spi0 pin function
if (pInfo->bIsSlaveMode)
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x40000);
else // master mode
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x40000);
if (pInfo->bIsClockIdleHigh)
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x800);
else // clock idle low
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x800);
if (pInfo->bIsLSBFirst)
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x400);
else // MSB first
outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x400);
if (pInfo->bIsAutoSelect)
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x8);
else
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x8);
if (pInfo->bIsActiveLow)
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x4);
else // active high
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x4);
if (pInfo->bIsTxNegative)
outpw(REG_SPI0_CNTRL, (inpw(REG_SPI0_CNTRL) & ~0x6)| 0x4); // Tx falling; Rx rising
else
outpw(REG_SPI0_CNTRL, (inpw(REG_SPI0_CNTRL) & ~0x6)| 0x2); // Tx rising; Rx falling
_spi_init_flag0 = TRUE;
}
}
else
{
if(_spi_init_flag1)
{
sysprintf("SPI1 pin is unavailable!!\n");
return -1;
}
if (!_spi_init_flag1)
{
outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS1_CKE); // enable the clocks of SPI
outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI1RST);
outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI1RST);
for (i=0; i<200; i++);
outpw(REG_GPBFUN, inpw(REG_GPBFUN) | 0x03FC0000); // enable spi1 pin function
if (pInfo->bIsSlaveMode)
{
sysprintf("SPI1 only support Master mode!!\n");
return -1;
}
else // master mode
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x40000);
if (pInfo->bIsClockIdleHigh)
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | 0x800);
else // clock idle low
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x800);
if (pInfo->bIsLSBFirst)
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | 0x400);
else // MSB first
outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x400);
if (pInfo->bIsAutoSelect)
outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x8);
else
outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x8);
if (pInfo->bIsActiveLow)
outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x4);
else // active high
outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x4);
if (pInfo->bIsTxNegative)
outpw(REG_SPI1_CNTRL, (inpw(REG_SPI1_CNTRL) & ~0x6)| 0x4); // Tx falling; Rx rising
else
outpw(REG_SPI1_CNTRL, (inpw(REG_SPI1_CNTRL) & ~0x6)| 0x2); // Tx rising; Rx falling
_spi_init_flag1 = TRUE;
}
}
return 0;
}
/*-----------------------------------------------------------------------------------*/
VOID spiIoctl(INT32 spiPort, INT32 spiFeature, INT32 spiArg0, INT32 spiArg1)
{
switch(spiFeature)
{
case SPI_SET_CLOCK:
spiSetClock(spiPort, spiArg0, spiArg1);
break;
}
}
/*-----------------------------------------------------------------------------------*/
INT spiEnable(INT32 spiPort)
{
if (spiPort == 0)
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);
else
outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x01);
return 0;
}
/*-----------------------------------------------------------------------------------*/
INT spiDisable(INT32 spiPort)
{
if (spiPort == 0)
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x01);
else
outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x01);
return 0;
}
INT spiRead(INT port, INT RxBitLen, INT len, CHAR *pDst)
{
switch (RxBitLen)
{
case SPI_32BIT:
if (port == 0)
outpw(REG_SPI0_TX0, 0xffffffff);
else
outpw(REG_SPI1_TX0, 0xffffffff);
while (len-- > 0)
{
spiTxLen(port, 0, SPI_32BIT);
spiActive(port);
if (port == 0)
*((INT32 *)pDst) = inpw(REG_SPI0_RX0) & 0xffffffff;
else
*((INT32 *)pDst) = inpw(REG_SPI1_RX0) & 0xffffffff;
pDst += 4;
}
break;
case SPI_16BIT:
if (port == 0)
outpw(REG_SPI0_TX0, 0xffff);
else
outpw(REG_SPI1_TX0, 0xffff);
while (len-- > 0)
{
spiTxLen(port, 0, SPI_16BIT);
spiActive(port);
if (port == 0)
*((INT16 *)pDst) = inpw(REG_SPI0_RX0) & 0xffff;
else
*((INT16 *)pDst) = inpw(REG_SPI1_RX0) & 0xffff;
pDst += 2;
}
break;
case SPI_8BIT:
if (port == 0)
outpw(REG_SPI0_TX0, 0xff);
else
outpw(REG_SPI1_TX0, 0xff);
while (len-- > 0)
{
spiTxLen(port, 0, SPI_8BIT);
spiActive(port);
if (port == 0)
*((INT8 *)pDst) = inpw(REG_SPI0_RX0) & 0xff;
else
*((INT8 *)pDst) = inpw(REG_SPI1_RX0) & 0xff;
pDst ++;
}
break;
}
return 0;
}
INT spiWrite(INT port, INT TxBitLen, INT len, CHAR *pSrc)
{
switch (TxBitLen)
{
case SPI_32BIT:
while (len-- > 0)
{
if (port == 0)
outpw(REG_SPI0_TX0, *((INT32 *)pSrc));
else
outpw(REG_SPI1_TX0, *((INT32 *)pSrc));
spiTxLen(port, 0, SPI_32BIT);
spiActive(port);
pSrc += 4;
}
break;
case SPI_16BIT:
while (len-- > 0)
{
if (port == 0)
outpw(REG_SPI0_TX0, *((INT16 *)pSrc));
else
outpw(REG_SPI1_TX0, *((INT16 *)pSrc));
spiTxLen(port, 0, SPI_16BIT);
spiActive(port);
pSrc += 2;
}
break;
case SPI_8BIT:
while (len-- > 0)
{
if (port == 0)
outpw(REG_SPI0_TX0, *((INT8 *)pSrc));
else
outpw(REG_SPI1_TX0, *((INT8 *)pSrc));
spiTxLen(port, 0, SPI_8BIT);
spiActive(port);
pSrc ++;
}
break;
}
return 0;
}
spi_dma.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
没文件
spi_dma.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef _SPI_DMA_H
#define _SPI_DMA_H
#include "w55fa93_edma.h"
#include "w55fa93_spi.h"
void TPH_SpiFree(void);
void TPH_SpiWrite(UINT8 * buffer, UINT32 len, PFN_DRVEDMA_CALLBACK irq);
void TPH_SpiStart(UINT32 addr, UINT32 len, UINT32 type,void (*irq_handler) (void *));
int TPH_SpiEnd(VOID);
void readStatus(void);
INT spiFlashPDMARead(UINT32 addr, UINT32 len, UINT32 *buf);
#endif
spiflash.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential */
/* */
/* Copyright (c) 2008 by Nuvoton Technology Corporation */
/* All rights reserved */
/* */
/*-----------------------------------------------------------------------------------*/
/****************************************************************************
*
* FILENAME
* spiflash.c
*
* VERSION
* 1.0
*
* DESCRIPTION
* This file contains SPI flash library APIs.
*
* DATA STRUCTURES
* None
*
* FUNCTIONS
* None
*
* HISTORY
* 10/12/07 Create Ver 1.0
* 06/12/09 Add SPI flash
*
* REMARK
* None
**************************************************************************/
/* Header files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"
#include "w55fa93_reg.h"
#include "w55fa93_spi.h"
int usiCheckBusy(unsigned int timeout)
{
// check status
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// status command
outpw(REG_SPI0_TX0, 0x05);
spiTxLen(0, 0, 8);
spiActive(0);
// get status
while(timeout)
{
outpw(REG_SPI0_TX0, 0xff);
spiTxLen(0, 0, 8);
spiActive(0);
if (((inpw(REG_SPI0_RX0) & 0xff) & 0x01) != 0x01)
break;
timeout--;
}
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
return timeout?Successful:Fail;
}
INT16 usiReadID()
{
UINT16 volatile id;
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// command 8 bit
outpw(REG_SPI0_TX0, 0x90);
spiTxLen(0, 0, 8);
spiActive(0);
// address 24 bit
outpw(REG_SPI0_TX0, 0x000000);
spiTxLen(0, 0, 24);
spiActive(0);
// data 16 bit
outpw(REG_SPI0_TX0, 0xffff);
spiTxLen(0, 0, 16);
spiActive(0);
id = inpw(REG_SPI0_RX0) & 0xffff;
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
return id;
}
int usiWriteEnable(void)
{
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
outpw(REG_SPI0_TX0, 0x06);
spiTxLen(0, 0, 8);
spiActive(0);
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
return Successful;
}
int usiWriteDisable(void)
{
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
outpw(REG_SPI0_TX0, 0x04);
spiTxLen(0, 0, 8);
spiActive(0);
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
return Successful;
}
int usiStatusWrite(UINT8 data)
{
usiWriteEnable();
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// status command
outpw(REG_SPI0_TX0, 0x01);
spiTxLen(0, 0, 8);
spiActive(0);
// write status
outpw(REG_SPI0_TX0, data);
spiTxLen(0, 0, 8);
spiActive(0);
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
return Successful;
}
/**************************************************/
INT spiFlashInit(void)
{
static BOOL bIsSpiFlashOK = 0;
static BOOL bIsSpi1FlashOK = 0;
int volatile loop;
if (!bIsSpiFlashOK)
{
outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS0_CKE); // turn on SPI clk
//Reset SPI controller first
outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI0RST);
outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI0RST);
// delay for time
// Delay
for (loop=0; loop<500; loop++);
//configure SPI0 interface, Base Address 0xB800C000
/* apb clock is 48MHz, output clock is 10MHz */
#if defined(CPU_144MHZ_MODE)
spiIoctl(0, SPI_SET_CLOCK, 72, 24000);
#else
spiIoctl(0, SPI_SET_CLOCK, 96, 24000);
#endif
//Startup SPI0 multi-function features, chip select using SS0
outpw(REG_GPDFUN, inpw(REG_GPDFUN) | 0xFF000000);
outpw(REG_SPI0_SSR, 0x00); // CS active low
outpw(REG_SPI0_CNTRL, 0x04); // Tx: falling edge, Rx: rising edge
if ((loop=usiReadID()) == -1)
{
sysprintf("read id error !! [0x%x]\n", loop&0xffff);
return -1;
}
sysprintf("SPI flash id [0x%x]\n", loop&0xffff);
usiStatusWrite(0x00); // clear block protect
// delay for time
// Delay
for (loop=0; loop<0x20000; loop++);
bIsSpiFlashOK = 1;
}
if (!bIsSpi1FlashOK)
{
outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS1_CKE); // turn on SPI clk
//Reset SPI controller first
outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI1RST);
outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI1RST);
// delay for time
// Delay
for (loop=0; loop<500; loop++);
//configure SPI0 interface, Base Address 0xB800C000
/* apb clock is 48MHz, output clock is 10MHz */
#if defined(CPU_144MHZ_MODE)
spiIoctl(1, SPI_SET_CLOCK, 72, 24000);
#else
spiIoctl(1, SPI_SET_CLOCK, 96, 24000);
#endif
//Startup SPI0 multi-function features, chip select using SS0
outpw(REG_GPDFUN, inpw(REG_GPDFUN)^(0x55<<18));
outpw(REG_SPI1_SSR, 0x00); // CS active low
outpw(REG_SPI1_CNTRL, 0x04); // Tx: falling edge, Rx: rising edge
//usiStatusWrite(0x00); // clear block protect
// delay for time
// Delay
for (loop=0; loop<0x20000; loop++);
bIsSpi1FlashOK = 1;
}
return 0;
}
INT spiFlashEraseBlock(UINT32 addr, UINT32 secCount)
{
int volatile i;
if ((addr % (64*1024)) != 0)
return -1;
for (i=0; i<secCount; i++)
{
usiWriteEnable();
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// erase command
outpw(REG_SPI0_TX0, 0xd8);
spiTxLen(0, 0, 8);
spiActive(0);
// address
outpw(REG_SPI0_TX0, addr+i*64*1024);
spiTxLen(0, 0, 24);
spiActive(0);
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
// check status
if(usiCheckBusy(1.2*1.5*1000*1000)!=Successful)
return Fail;
}
return Successful;
}
INT spiFlashEraseSector(UINT32 addr, UINT32 secCount)
{
int volatile i;
if ((addr % (4*1024)) != 0)
return -1;
for (i=0; i<secCount; i++)
{
usiWriteEnable();
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// erase command
outpw(REG_SPI0_TX0, 0x20);
spiTxLen(0, 0, 8);
spiActive(0);
// address
outpw(REG_SPI0_TX0, addr+i*4*1024);
spiTxLen(0, 0, 24);
spiActive(0);
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
// check status
if(usiCheckBusy(0.6*1000*1000)!=Successful)
return Fail;
}
return Successful;
}
INT spiFlashEraseAll(void)
{
usiWriteEnable();
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
outpw(REG_SPI0_TX0, 0xc7);
spiTxLen(0, 0, 8);
spiActive(0);
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
// check status
if(usiCheckBusy(60*1000*1000)!=Successful)
return Fail;
return Successful;
}
INT spiFlashWrite(UINT32 addr, UINT32 len, UINT32 *buf)
{
int volatile count=0, page, i;
UINT32 u32Tmp;
SPI_SwitchToFlash();
count = len / 256;
if ((len % 256) != 0)
count++;
for (i=0; i<count; i++)
{
// check data len
if (len >= 256)
{
page = 256;
len = len - 256;
}
else
page = len;
//sysprintf("len %d page %d\n",len , page);
usiWriteEnable();
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// write command
outpw(REG_SPI0_TX0, 0x02);
spiTxLen(0, 0, 8);
spiActive(0);
// address
outpw(REG_SPI0_TX0, addr+i*256);
spiTxLen(0, 0, 24);
spiActive(0);
// write data
while (page > 0)
{
u32Tmp = ((*buf & 0xFF) << 24) | ((*buf & 0xFF00) << 8) | ((*buf & 0xFF0000) >> 8)| ((*buf & 0xFF000000) >> 24);
outpw(REG_SPI0_TX0, u32Tmp);
spiTxLen(0, 0, 32);
spiActive(0);
buf++;
page -=4;
}
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
// check status
if(usiCheckBusy(4*1.5*1000)!=Successful)
return Fail;
}
return Successful;
}
INT spiFlashRead(UINT32 addr, UINT32 len, UINT32 *buf)
{
int volatile i;
UINT32 u32Tmp;
UINT8 *ptr;
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); // CS0
// read command
outpw(REG_SPI0_TX0, 03);
spiTxLen(0, 0, 8);
spiActive(0);
// address
outpw(REG_SPI0_TX0, addr);
spiTxLen(0, 0, 24);
spiActive(0);
// data
for (i=0; i<len/4; i++)
{
outpw(REG_SPI0_TX0, 0xffffffff);
spiTxLen(0, 0, 32);
spiActive(0);
u32Tmp = inp32(REG_SPI0_RX0);
*buf++ = ((u32Tmp & 0xFF) << 24) | ((u32Tmp & 0xFF00) << 8) | ((u32Tmp & 0xFF0000) >> 8)| ((u32Tmp & 0xFF000000) >> 24);
}
if(len % 4)
{
ptr = (UINT8 *)buf;
for (i=0; i<(len %4); i++)
{
outpb(REG_SPI0_TX0, 0xff);
spiTxLen(0, 0, 8);
spiActive(0);
*ptr++ = inpb(REG_SPI0_RX0);
}
}
outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe); // CS0
return Successful;
}
standalone.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*
* standalone.c - minimal bootstrap for C library
* Copyright (C) 2000 ARM Limited.
* All rights reserved.
*/
/*
* RCS $Revision: 1 $
* Checkin $Date: 07/07/05 2:54p $ 0
* Revising $Author: Sjlu0 $
*/
/*
* This code defines a run-time environment for the C library.
* Without this, the C startup code will attempt to use semi-hosting
* calls to get environment information.
*/
extern unsigned int Image$$ZI$$Limit;
void _sys_exit(int return_code)
{
label: goto label; /* endless loop */
}
void _ttywrch(int ch)
{
char tempch = (char)ch;
(void)tempch;
}
__value_in_regs struct R0_R3 {unsigned heap_base, stack_base, heap_limit, stack_limit;}
__user_initial_stackheap(unsigned int R0, unsigned int SP, unsigned int R2, unsigned int SL)
{
struct R0_R3 config;
//config.heap_base = 0x00060000;
config.heap_base = (unsigned int)&Image$$ZI$$Limit;
config.stack_base = SP;
/*
To place heap_base directly above the ZI area, use:
extern unsigned int Image$$ZI$$Limit;
config.heap_base = (unsigned int)&Image$$ZI$$Limit;
(or &Image$$region_name$$ZI$$Limit for scatterloaded images)
To specify the limits for the heap & stack, use e.g:
config.heap_limit = SL;
config.stack_limit = SL;
*/
return config;
}
/* end of file standalone.c */
usbd.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/****************************************************************************
*
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"
#include "w55fa93_reg.h"
#include "usbd.h"
#define DATA_CODE "20170606"
__align(4) volatile USBD_INFO_T usbdInfo = {0};
__align(4) volatile USBD_STATUS_T usbdStatus = {0};
USB_CMD_T _usb_cmd_pkt;
INT32 volatile usb_halt_ep;
BOOL volatile g_bHostAttached = FALSE;
VOID usbd_isr(void);
UINT32 volatile class_out_len = 0;
VOID usbdClearAllFlags(void)
{
usbdInfo.GET_DEV_Flag=0;
usbdInfo.GET_CFG_Flag=0;
usbdInfo.GET_QUL_Flag=0;
usbdInfo.GET_OSCFG_Flag=0;
usbdInfo.GET_STR_Flag=0;
usbdInfo.GET_HID_Flag = 0;
usbdInfo.GET_HID_RPT_Flag = 0;
usbdInfo.usbdGetConfig=0;
usbdInfo.usbdGetInterface=0;
usbdInfo.usbdGetStatus=0;
usbdInfo.enabletestmode = 0;
}
VOID udcOpen(void)
{
UINT32 u32PllOutKHz,u32ExtFreq;
int i;
//sysprintf("N3290 UDC Library (%s)\n",DATA_CODE);
u32ExtFreq = sysGetExternalClock();
outp32(REG_CLKDIV2, inp32(REG_CLKDIV2) & ~0x0060F0E0);
if(u32ExtFreq == 27000)
{
u32PllOutKHz = sysGetPLLOutputKhz(eSYS_UPLL, u32ExtFreq);
i = (u32PllOutKHz / 2) / 12000 - 1;
/* USB Clock source = UPLL / 2 */
/* USB Clock = USB Clock source / (i+1) */
outp32(REG_CLKDIV2, inp32(REG_CLKDIV2) | 0x00600020 | (i << 12));
}
#ifndef __USBD_FULL_SPEED_MODE__
if(inp32(PHY_CTL) & Vbus_status)
{
usbdInfo.u32VbusStatus = 1;
usbdStatus.usbConnected = 1;
}
else
{
usbdInfo.u32VbusStatus = 0;
usbdStatus.usbConnected = 0;
}
#endif
#ifdef __USBD_FULL_SPEED_MODE__
outp32(REG_AHBCLK, inp32(REG_AHBCLK) | USBH_CKE);
outp32(REG_HC_RH_OP_MODE, inp32(REG_HC_RH_OP_MODE) | (BIT16|BIT17) );
#endif
outp32(REG_AHBCLK, inp32(REG_AHBCLK) | USBD_CKE | HCLK3_CKE);
outpw(REG_AHBIPRST, inpw(REG_AHBIPRST) | UDCRST);
outpw(REG_AHBIPRST, inpw(REG_AHBIPRST) & ~UDCRST);
outp32(PHY_CTL, (0x20 | Phy_suspend));
outp32(CEP_END_ADDR, 0x7F);
while(inp32(CEP_END_ADDR) != 0x7F);
usbdInfo.u32UVC = 0;
#ifdef __USBD_FULL_SPEED_MODE__
outp32(OPER, 0x0);
while(inp32(OPER) != 0x0);
for(i=0;i<0x30000;i++)
{
if(inp32(PHY_CTL) & Vbus_status)
{
usbdInfo.u32VbusStatus = 1;
usbdStatus.usbConnected = 1;
break;
}
else
{
usbdInfo.u32VbusStatus = 0;
usbdStatus.usbConnected = 0;
}
}
#endif
}
VOID udcInit(void)
{
/* initial state */
usbdInfo._usbd_devstate = 0; //initial state
usbdInfo._usbd_address = 0; //not set
usbdInfo._usbd_confsel = 0; //not selected
usbdInfo._usbd_intfsel = 0; //not selected
#ifdef __USBD_FULL_SPEED_MODE__
usbdInfo._usbd_speedset = 1; // default at high speed mode
#else
usbdInfo._usbd_speedset = 2; // default at high speed mode
#endif
usbdInfo.AlternateFlag = 0;
usbdInfo.AlternateFlag_Audio = 0; // For UAC audio
usbdStatus.appConnected = 0;
usbdStatus.appConnected_Audio = 0; // For UAC audio
usbdInfo._usbd_haltep = -1;
sysInstallISR(IRQ_LEVEL_7, IRQ_UDC, (PVOID)usbd_isr);
sysEnableInterrupt(IRQ_UDC);
sysSetLocalInterrupt(ENABLE_IRQ);
/*
* configure mass storage interface endpoint
*/
/* Device is in High Speed */
if (usbdInfo._usbd_speedset == 2)
{
usbdInfo.pfnHighSpeedInit();
}
/* Device is in Full Speed */
else if (usbdInfo._usbd_speedset == 1)
{
usbdInfo.pfnFullSpeedInit();
}
/*
* configure USB controller
*/
outp32(IRQ_ENB_L, (USB_IE|CEP_IE|EPA_IE|EPB_IE|EPC_IE|EPD_IE)); /* enable usb, cep, epa, epb, epc interrupt */
outp32(USB_IRQ_ENB, (DMACOM_IE | RUM_IE | RST_IE|VBUS_IE));
outp32(ADDR, 0);
#ifndef __USBD_FULL_SPEED_MODE__
outp32(OPER, SET_HISPD);
#endif
/* allocate 0xff bytes mem for cep */
outp32(CEP_START_ADDR, 0);
outp32(CEP_END_ADDR, 0x7F);
outp32(CEP_IRQ_ENB, (CEP_SUPPKT | CEP_STS_END));
if(inp32(PHY_CTL) & Vbus_status)
outp32(PHY_CTL, (0x20 | Phy_suspend | vbus_detect));
}
VOID udcDeinit(void)
{
outp32(PHY_CTL, (inp32(PHY_CTL) & ~vbus_detect));
usbdInfo.USBModeFlag =0;
}
VOID udcClose(void)
{
outp32(REG_AHBCLK, inp32(REG_AHBCLK) & ~USBD_CKE);
}
BOOL udcIsAttached(void)
{
return((inp32(PHY_CTL) & Vbus_status) ? TRUE : FALSE);
}
BOOL udcIsAttachedToHost(void)
{
return g_bHostAttached;
}
VOID usbd_update_device(void)
{
/* update this device for set requests */
switch(_usb_cmd_pkt.bRequest)
{
case USBR_SET_ADDRESS:
outp32(ADDR, usbdInfo._usbd_address);
break;
case USBR_SET_CONFIGURATION:
if(usbdInfo.i32EPA_Num != -1)
{
outp32(EPA_RSP_SC, EP_TOGGLE);
}
if(usbdInfo.i32EPB_Num != -1)
{
outp32(EPB_RSP_SC, EP_TOGGLE);
}
if(usbdInfo.i32EPC_Num != -1)
{
outp32(EPC_RSP_SC, EP_TOGGLE);
}
if(usbdInfo.i32EPD_Num != -1)
{
outp32(EPD_RSP_SC, EP_TOGGLE);
}
break;
case USBR_SET_INTERFACE:
break;
case USBR_SET_FEATURE:
if(usbdInfo._usbd_haltep == 0)
outp32(CEP_CTRL_STAT, CEP_SEND_STALL);
else if(usbdInfo.i32EPA_Num != -1 && usbdInfo._usbd_haltep == usbdInfo.i32EPA_Num )
{
outp32(EPA_RSP_SC, EP_HALT);
}
else if(usbdInfo.i32EPB_Num != -1 && usbdInfo._usbd_haltep == usbdInfo.i32EPB_Num )
{
outp32(EPB_RSP_SC, EP_HALT);
}
else if(usbdInfo.i32EPC_Num != -1 && usbdInfo._usbd_haltep == usbdInfo.i32EPC_Num )
{
outp32(EPC_RSP_SC,EP_HALT);
}
else if(usbdInfo.i32EPD_Num != -1 && usbdInfo._usbd_haltep == usbdInfo.i32EPD_Num )
{
outp32(EPD_RSP_SC, EP_HALT);
}
else if(usbdInfo.enableremotewakeup == 1)
{
usbdInfo.enableremotewakeup = 0;
usbdInfo.remotewakeup = 1;
}
if(usbdInfo.enabletestmode == 1)
{
usbdInfo.enabletestmode = 0;
usbdInfo.testmode = 1;
if(usbdInfo.testselector == TEST_J)
outp32(USB_TEST, TEST_J);
else if(usbdInfo.testselector==TEST_K)
outp32(USB_TEST, TEST_K);
else if(usbdInfo.testselector==TEST_SE0_NAK)
outp32(USB_TEST, TEST_SE0_NAK);
else if(usbdInfo.testselector==TEST_PACKET)
outp32(USB_TEST, TEST_PACKET);
else if(usbdInfo.testselector==TEST_FORCE_ENABLE)
outp32(USB_TEST, TEST_FORCE_ENABLE);
}
break;
case USBR_CLEAR_FEATURE:
if(usbdInfo.i32EPA_Num != -1 && usbdInfo._usbd_unhaltep == usbdInfo.i32EPA_Num && usbdInfo._usbd_haltep == usbdInfo.i32EPA_Num)
{
outp32(EPA_RSP_SC, 0x0);
usb_halt_ep = usb_halt_ep & ~0x01;
outp32(EPA_RSP_SC, EP_TOGGLE);
usbdInfo._usbd_haltep = -1; /* just for changing the haltep value */
}
if(usbdInfo.i32EPB_Num != -1 && usbdInfo._usbd_unhaltep == usbdInfo.i32EPB_Num && usbdInfo._usbd_haltep == usbdInfo.i32EPB_Num)
{
outp32(EPB_RSP_SC, 0x0);
usb_halt_ep = usb_halt_ep & ~0x02;
outp32(EPB_RSP_SC, EP_TOGGLE);
usbdInfo._usbd_haltep = -1; /* just for changing the haltep value */
}
if(usbdInfo.i32EPC_Num != -1 && usbdInfo._usbd_unhaltep == usbdInfo.i32EPC_Num && usbdInfo._usbd_haltep == usbdInfo.i32EPC_Num)
{
outp32(EPC_RSP_SC, 0x0);
usb_halt_ep = usb_halt_ep & ~0x04;
outp32(EPC_RSP_SC, EP_TOGGLE);
usbdInfo._usbd_haltep = -1; /* just for changing the haltep value */
}
if(usbdInfo.i32EPD_Num != -1 && usbdInfo._usbd_unhaltep == usbdInfo.i32EPD_Num && usbdInfo._usbd_haltep == usbdInfo.i32EPD_Num)
{
outp32(EPD_RSP_SC, 0x0);
usb_halt_ep = usb_halt_ep & ~0x08;
outp32(EPD_RSP_SC, EP_TOGGLE);
usbdInfo._usbd_haltep = -1; /* just for changing the haltep value */
}
else if(usbdInfo.disableremotewakeup == 1)
{
usbdInfo.disableremotewakeup=0;
usbdInfo.remotewakeup=0;
}
break;
default:
break;
}
}
VOID usbd_send_descriptor(void)
{
UINT32 volatile temp_cnt;
int volatile i;
UINT32 volatile *ptr;
UINT8 volatile *pRemainder;
if ((usbdInfo.CLASS_CMD_Iflag==1) || (usbdInfo.GET_DEV_Flag == 1) || (usbdInfo.GET_QUL_Flag == 1) ||
(usbdInfo.GET_CFG_Flag == 1) || (usbdInfo.GET_OSCFG_Flag == 1) || (usbdInfo.GET_STR_Flag == 1) ||
(usbdInfo.usbdGetConfig == 1) || (usbdInfo.usbdGetInterface == 1) ||(usbdInfo.usbdGetStatus == 1)
|| (usbdInfo.GET_HID_Flag == 1) || (usbdInfo.GET_HID_RPT_Flag == 1))
{
if (usbdInfo._usbd_remlen_flag == 0)
{
if (usbdInfo.GET_DEV_Flag == 1)
ptr = (UINT32 *)usbdInfo.pu32DevDescriptor;
else if (usbdInfo.GET_QUL_Flag == 1)
ptr =(UINT32 *)usbdInfo.pu32QulDescriptor;
else if (usbdInfo.GET_CFG_Flag == 1)
{
if (usbdInfo._usbd_speedset == 2)
ptr = (UINT32 *)usbdInfo.pu32HSConfDescriptor;
else if (usbdInfo._usbd_speedset == 1)
ptr = (UINT32 *)usbdInfo.pu32FSConfDescriptor;
}
else if (usbdInfo.GET_OSCFG_Flag == 1)
{
if (usbdInfo._usbd_speedset == 2)
ptr = (UINT32 *)usbdInfo.pu32HOSConfDescriptor;
else if (usbdInfo._usbd_speedset == 1)
ptr = (UINT32 *)usbdInfo.pu32FOSConfDescriptor;
}
else if (usbdInfo.GET_STR_Flag == 1)
ptr = (UINT32 *)usbdInfo.pu32StringDescriptor[_usb_cmd_pkt.wValue & 0x7];
else if (usbdInfo.GET_HID_Flag == 1)
ptr = (UINT32 *)usbdInfo.pu32HIDDescriptor;
else if (usbdInfo.GET_HID_RPT_Flag == 1)
ptr = (UINT32 *)usbdInfo.pu32HIDRPTDescriptor;
else if (usbdInfo.usbdGetConfig == 1)
{
/* Send Configuration Selector Data (1 bytes) to Host */
outp8(CEP_DATA_BUF, usbdInfo._usbd_confsel);
outp32(IN_TRNSFR_CNT, 1);
return;
}
else if (usbdInfo.usbdGetInterface == 1)
{
/* Send Alternate Selector Data (1 bytes) to Host */
outp8(CEP_DATA_BUF, usbdInfo._usbd_altsel);
outp32(IN_TRNSFR_CNT, 1);
return;
}
else if (usbdInfo.usbdGetStatus == 1)
{
/* Send Status (2 bytes) to Host */
outp8(CEP_DATA_BUF, (UINT8)usbdInfo.usbdGetStatusData);
outp8(CEP_DATA_BUF, 0);
outp32(IN_TRNSFR_CNT, 2);
return;
}
else if (usbdInfo.CLASS_CMD_Iflag == 1)
{
if(usbdInfo.u32UVC == 1 && usbdStatus.appConnected == 1)
{
int volatile flag = 0;
int volatile i = 0;
int volatile count0 = 0, count1 = 0;
while(1)
{
count0 = inp32(EPA_DATA_CNT) & 0xFFFF;
for(i = 0; i < 5; i++)
;
count1 = inp32(EPA_DATA_CNT) & 0xFFFF;
if(count0 == count1)
flag++;
else
flag = 0;
if(flag > 5)
break;
}
}
outp32(CEP_END_ADDR, 0x7F);
/* Class Data In */
if(usbdInfo.pfnClassDataINCallBack != NULL)
usbdInfo.pfnClassDataINCallBack();
return;
}
}
else
ptr = usbdInfo._usbd_ptr;
if (_usb_cmd_pkt.wLength > 0x40)
{
usbdInfo._usbd_remlen_flag = 1;
usbdInfo._usbd_remlen = _usb_cmd_pkt.wLength - 0x40;
_usb_cmd_pkt.wLength = 0x40;
}
else if (usbdInfo._usbd_remlen != 0)
{
if (usbdInfo._usbd_remlen > 0x40)
{
usbdInfo._usbd_remlen_flag = 1;
usbdInfo._usbd_remlen = usbdInfo._usbd_remlen -0x40;
_usb_cmd_pkt.wLength = 0x40;
}
else
{
usbdInfo._usbd_remlen_flag = 0;
_usb_cmd_pkt.wLength = usbdInfo._usbd_remlen;
usbdInfo._usbd_remlen = 0;
}
}
else
{
usbdInfo._usbd_remlen_flag = 0;
usbdInfo._usbd_remlen = 0;
}
temp_cnt = _usb_cmd_pkt.wLength / 4;
for (i=0; i<temp_cnt; i++)
outp32(CEP_DATA_BUF, *ptr++);
temp_cnt = _usb_cmd_pkt.wLength % 4;
if (temp_cnt)
{
pRemainder = (UINT8 *)ptr;
for (i=0; i<temp_cnt; i++)
{
outp8(CEP_DATA_BUF, *pRemainder);
pRemainder++;
}
}
if (usbdInfo._usbd_remlen_flag)
usbdInfo._usbd_ptr = (UINT32 *)ptr;
outp32(IN_TRNSFR_CNT, _usb_cmd_pkt.wLength);
}
}
VOID usbd_control_packet(void)
{
UINT32 volatile temp;
BOOL volatile ReqErr = 0;
/* Get Command */
temp = inp32(SETUP1_0);
_usb_cmd_pkt.bmRequestType = (UINT8)temp & 0xff;
_usb_cmd_pkt.bRequest = (UINT8)(temp >> 8) & 0xff;
_usb_cmd_pkt.wValue = (UINT16)inp32(SETUP3_2);
_usb_cmd_pkt.wIndex = (UINT16)inp32(SETUP5_4);
_usb_cmd_pkt.wLength = (UINT16)inp32(SETUP7_6);
usbdClearAllFlags();
usbdInfo.CLASS_CMD_Iflag = 0;
usbdInfo.CLASS_CMD_Oflag = 0;
if ((_usb_cmd_pkt.bmRequestType &0xE0) == 0xa0) /* 0xA1 or 0xA2 is Class Get Request */
{
outp32(CEP_IRQ_STAT, CEP_STACOM_IS); /* Add by SPCheng */
if (_usb_cmd_pkt.wLength == 0)
{
/* Class Data Out without Data */
if(usbdInfo.pfnClassDataINCallBack != NULL)
usbdInfo.pfnClassDataINCallBack();
return;
}
usbdInfo.CLASS_CMD_Iflag = 1;
usbdInfo._usbd_DMA_In =1;
outp32(CEP_IRQ_STAT, CEP_IN_TK_IS); // BA+0x34 , clear status, In talken
outp32(CEP_IRQ_ENB, CEP_IN_TK_IE); //suppkt int ,status and in token
return;
}
else if ((_usb_cmd_pkt.bmRequestType &0xE0) == 0x20) //0x21 or 0x22 is Class Set Request
{
if(usbdInfo.u32UVC == 1 && usbdStatus.appConnected == 1)
{
int volatile flag = 0;
int volatile i = 0;
int volatile count0 = 0, count1 = 0;
outp32(CEP_END_ADDR, 0x7F);
while(1)
{
count0 = inp32(EPA_DATA_CNT) & 0xFFFF;
for(i = 0; i < 5; i++)
;
count1 = inp32(EPA_DATA_CNT) & 0xFFFF;
if(count0 == count1)
flag++;
else
flag = 0;
if(flag > 5)
break;
}
}
usbdInfo.CLASS_CMD_Oflag = 1;
if (_usb_cmd_pkt.wLength == 0)
{
/* Class Data Out without Data */
if(usbdInfo.pfnClassDataOUTCallBack != NULL)
usbdInfo.pfnClassDataOUTCallBack();
outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR); /* clear nak so that sts stage is complete */
}
else
outp32(CEP_IRQ_ENB, /*CEP_OUT_TK_IE |*/ CEP_DATA_RxED_IE); //OUT_TK_IE
return;
}
switch (_usb_cmd_pkt.bRequest)
{
case USBR_GET_DESCRIPTOR:
/* ReqErr = ((_usb_cmd_pkt.bmRequestType == 0x80) && ((_usb_cmd_pkt.wValue & 0xf000) == 0)
&& ((_usb_cmd_pkt.wValue & 0x80) == 0)) ? 0 : 1;
if(ReqErr==1)
{
sysprintf("ERROR\n");
break;
}*/
switch ((_usb_cmd_pkt.wValue & 0xff00) >> 8)
{
case USB_DT_DEVICE:
// clear flags
usbdClearAllFlags();
usbdInfo.GET_DEV_Flag = 1;
usbdInfo.USBModeFlag=1; /* acpi debug */
if (_usb_cmd_pkt.wLength > usbdInfo.u32DevDescriptorLen)
_usb_cmd_pkt.wLength = usbdInfo.u32DevDescriptorLen;
break;
case USB_DT_CONFIG:
usbdClearAllFlags();
usbdInfo.GET_CFG_Flag = 1;
{
if (usbdInfo._usbd_speedset == 2)
{
if (_usb_cmd_pkt.wLength > usbdInfo.u32HSConfDescriptorLen)
_usb_cmd_pkt.wLength = usbdInfo.u32HSConfDescriptorLen;
}
else
{
if (_usb_cmd_pkt.wLength > usbdInfo.u32FSConfDescriptorLen)
_usb_cmd_pkt.wLength = usbdInfo.u32FSConfDescriptorLen;
}
}
break;
case USB_DT_QUALIFIER: /* high-speed operation */
usbdClearAllFlags();
usbdInfo.GET_QUL_Flag = 1;
if (_usb_cmd_pkt.wLength > usbdInfo.u32QulDescriptorLen)
_usb_cmd_pkt.wLength = usbdInfo.u32QulDescriptorLen;
break;
case USB_DT_OSCONFIG: /* other speed configuration */
usbdClearAllFlags();
usbdInfo.GET_OSCFG_Flag = 1;
if (usbdInfo._usbd_speedset == 2)
{
if (_usb_cmd_pkt.wLength > usbdInfo.u32HOSConfDescriptorLen)
_usb_cmd_pkt.wLength = usbdInfo.u32HOSConfDescriptorLen;
}
else if (usbdInfo._usbd_speedset == 1)
{
if (_usb_cmd_pkt.wLength > usbdInfo.u32FOSConfDescriptorLen)
_usb_cmd_pkt.wLength = usbdInfo.u32FOSConfDescriptorLen;
}
break;
case USB_DT_STRING:
usbdClearAllFlags();
usbdInfo.GET_STR_Flag = 1;
if (_usb_cmd_pkt.wLength > usbdInfo.u32StringDescriptorLen[_usb_cmd_pkt.wValue & 0x7])
_usb_cmd_pkt.wLength = usbdInfo.u32StringDescriptorLen[_usb_cmd_pkt.wValue & 0x7];
break;
case USB_DT_HID:
usbdClearAllFlags();
usbdInfo.GET_HID_Flag = 1;
if (_usb_cmd_pkt.wLength > usbdInfo.u32HIDDescriptorLen)
_usb_cmd_pkt.wLength = usbdInfo.u32HIDDescriptorLen;
break;
case USB_DT_HID_RPT:
usbdClearAllFlags();
//sysprintf("USB_DT_HID_RPT\n");
usbdInfo.GET_HID_RPT_Flag = 1;
usbdStatus.appConnected = 1;
if (_usb_cmd_pkt.wLength > usbdInfo.u32HIDRPTDescriptorLen)
_usb_cmd_pkt.wLength = usbdInfo.u32HIDRPTDescriptorLen;
break;
default:
ReqErr=1;
break;
} //end of switch
if (ReqErr == 0)
{
outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
outp32(CEP_IRQ_ENB, CEP_IN_TK_IE); //suppkt int ,status and in token
}
break;
case USBR_SET_ADDRESS:
ReqErr = ((_usb_cmd_pkt.bmRequestType == 0) && ((_usb_cmd_pkt.wValue & 0xff00) == 0)
&& (_usb_cmd_pkt.wIndex == 0) && (_usb_cmd_pkt.wLength == 0)) ? 0 : 1;
if ((_usb_cmd_pkt.wValue & 0xffff) > 0x7f)
ReqErr=1; /* Devaddr > 127 */
if (usbdInfo._usbd_devstate == 3)
ReqErr=1; /* Dev is configured */
if (ReqErr==1)
break;
if(usbdInfo._usbd_devstate == 2)
{
if(_usb_cmd_pkt.wValue == 0)
usbdInfo._usbd_devstate = 1; /* enter default state */
usbdInfo._usbd_address = _usb_cmd_pkt.wValue; /* if wval !=0,use new address */
}
if(usbdInfo._usbd_devstate == 1)
{
if(_usb_cmd_pkt.wValue != 0)
{
usbdInfo._usbd_address = _usb_cmd_pkt.wValue;
usbdInfo._usbd_devstate = 2;
}
}
outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR); /* clear nak so that sts stage is complete */
outp32(CEP_IRQ_ENB, CEP_STACOM_IE); /* enable status complete interrupt */
break;
case USBR_GET_CONFIGURATION:
ReqErr = ((_usb_cmd_pkt.bmRequestType == 0x80) && (_usb_cmd_pkt.wValue == 0) &&
(_usb_cmd_pkt.wIndex == 0) && (_usb_cmd_pkt.wLength == 0x1) ) ? 0 : 1;
if (ReqErr==1)
break;
usbdClearAllFlags();
usbdInfo.usbdGetConfig=1;
outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
outp32(CEP_IRQ_ENB, CEP_IN_TK_IE); /* status and in token */
break;
case USBR_SET_CONFIGURATION:
ReqErr = ((_usb_cmd_pkt.bmRequestType == 0) && ((_usb_cmd_pkt.wValue & 0xff00) == 0) &&
((_usb_cmd_pkt.wValue & 0x80) == 0) && (_usb_cmd_pkt.wIndex == 0) &&
(_usb_cmd_pkt.wLength == 0)) ? 0 : 1;
if (usbdInfo._usbd_devstate == 1)
ReqErr=1; /* Device is in Default state */
if ((_usb_cmd_pkt.wValue != 1) && (_usb_cmd_pkt.wValue != 0) ) /* Only configuration one is supported */
ReqErr=1; /* Configuration choosed is invalid */
if(ReqErr==1)
break;
if (_usb_cmd_pkt.wValue == 0)
{
usbdInfo._usbd_confsel = 0;
usbdInfo._usbd_devstate = 2;
}
else
{
usbdInfo._usbd_confsel = _usb_cmd_pkt.wValue;
usbdInfo._usbd_devstate = 3;
}
usbdInfo.USBStartFlag = 1;
outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR); /* clear nak so that sts stage is complete */
outp32(CEP_IRQ_ENB, CEP_STACOM_IE); /* suppkt int ,status and in token */
break;
case USBR_GET_INTERFACE:
ReqErr = ((_usb_cmd_pkt.bmRequestType == 0x81) && (_usb_cmd_pkt.wValue == 0)
&& (_usb_cmd_pkt.wLength == 0x1)) ? 0 : 1;
if ((usbdInfo._usbd_devstate == 1) || (usbdInfo._usbd_devstate == 2))
ReqErr=1; /* Device state is not valid */
if(ReqErr == 1)
break; /* Request Error */
usbdClearAllFlags();
usbdInfo.usbdGetInterface = 1;
outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
outp32(CEP_IRQ_ENB, CEP_IN_TK_IE); /* status and in token */
break;
case USBR_SET_INTERFACE:
usbdInfo._usbd_altsel = _usb_cmd_pkt.wValue;
usbdInfo._usbd_intfsel = _usb_cmd_pkt.wIndex;
if(usbdInfo.u32UVC)
{
if ( usbdInfo._usbd_intfsel == 1 ) // for video interface
{
if (_usb_cmd_pkt.wValue != 0) // Set alternative interface Video
{
usbdInfo.AlternateFlag=1;
usbdStatus.appConnected = 1;
outp32(CEP_END_ADDR, 0x0);
//sysprintf("Interface 1, alter 1\n");
}
else
{
outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)|0x00000080); /* Reset DMA */
outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)&0x0000007F);
outp32(EPA_RSP_SC, BUF_FLUSH); /* flush fifo */
usbdInfo._usbd_DMA_In =1;
usbdInfo.AlternateFlag=0;
usbdStatus.appConnected = 0;
outp32(CEP_END_ADDR, 0x7F);
//sysprintf("Interface 1, alter 0\n");
}
}
else if ( usbdInfo._usbd_intfsel == 3 ) // for audio microphone interface
{
if (_usb_cmd_pkt.wValue == 1) // for audio settng of Isochronous In
{
usbdInfo.AlternateFlag_Audio=1;
usbdStatus.appConnected_Audio = 1;
//sysprintf("Setup Interface 3, alter 1\n");
}
else
{
usbdInfo.AlternateFlag_Audio=0;
usbdStatus.appConnected_Audio = 0;
//sysprintf("Setup Interface 3, alter 0\n");
}
}
else
{
//outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)|0x00000080); /* Reset DMA */
//outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)&0x0000007F);
//usbdInfo._usbd_DMA_In =1;
//sysprintf("Interface no, alter no\n");
}
}
else
{
if (_usb_cmd_pkt.wValue !=0)
{
usbdInfo.AlternateFlag=1;
usbdStatus.appConnected = 1;
outp32(CEP_START_ADDR, 0);
outp32(CEP_END_ADDR, 0x0);
}
else
{
outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)|0x00000080); /* Reset DMA */
outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)&0x0000007F);
usbdInfo._usbd_DMA_In =1;
usbdInfo.AlternateFlag=0;
usbdStatus.appConnected = 0;
}
}
outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR); /* clear nak so that sts stage is complete */
outp32(CEP_IRQ_ENB, CEP_STACOM_IE); /* suppkt int ,status and in token */
break;
case USBR_SET_FEATURE:
if (usbdInfo._usbd_devstate == 1)
{
if((_usb_cmd_pkt.bmRequestType & 0x3) == 0x0) /* Receipent is Device */
{
if((_usb_cmd_pkt.wValue & 0x3) == TEST_MODE)
{
usbdInfo.enabletestmode = 1;
usbdInfo.testselector = (_usb_cmd_pkt.wIndex >> 8);
outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
outp32(CEP_IRQ_ENB, CEP_STACOM_IE); /* suppkt int ,status and in token */
}
}
else
ReqErr=1; /* Device is in Default State */
}
if (usbdInfo._usbd_devstate == 2)
{
if ((_usb_cmd_pkt.bmRequestType & 0x3 == 2) && ((_usb_cmd_pkt.wIndex & 0xff) != 0)) /* ep but not cep */
ReqErr =1; /* Device is in Addressed State, but for noncep */
else if ((_usb_cmd_pkt.bmRequestType & 0x3) == 0x1)
ReqErr=1; /* Device is in Addressed State, but for interfac */
}
if (ReqErr == 1)
break; /* Request Error */
/* check if recipient and wvalue are appropriate */
switch(_usb_cmd_pkt.bmRequestType & 0x3)
{
case 0: /* device */
if ((_usb_cmd_pkt.wValue & 0x3) == DEVICE_REMOTE_WAKEUP)
usbdInfo.enableremotewakeup = 1;
else if((_usb_cmd_pkt.wValue & 0x3) == TEST_MODE)
{
usbdInfo.enabletestmode = 1;
usbdInfo.testselector = (_usb_cmd_pkt.wIndex >> 8);
}
else
ReqErr=1; /* No such feature for device */
break;
case 1: /* interface */
break;
case 2: /* endpoint */
if((_usb_cmd_pkt.wValue & 0x3) == ENDPOINT_HALT)
{
//dx->chgfea=dx->feature | ENDPOINT_HALT;
if((_usb_cmd_pkt.wIndex & 0xF) == 0) /* endPoint zero */
usbdInfo._usbd_haltep = 0;
else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPA_Num) /* endPoint A */
usbdInfo._usbd_haltep = usbdInfo.i32EPA_Num;
else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPB_Num) /* endPoint B */
usbdInfo._usbd_haltep = usbdInfo.i32EPB_Num;
else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPC_Num) /* endPoint C */
usbdInfo._usbd_haltep = usbdInfo.i32EPC_Num;
else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPD_Num) /* endPoint D */
usbdInfo._usbd_haltep = usbdInfo.i32EPD_Num;
else
ReqErr=1; /* Selected endpoint was not present */
}
else
ReqErr=1; /* Neither device,endpoint nor interface was choosen */
break;
default:
break;
}//device
outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR); /* clear nak so that sts stage is complete */
outp32(CEP_IRQ_ENB, CEP_STACOM_IE); /* suppkt int ,status and in token */
break;
case USBR_CLEAR_FEATURE:
ReqErr = (((_usb_cmd_pkt.bmRequestType & 0xfc) == 0) && ((_usb_cmd_pkt.wValue & 0xfffc) == 0)
&& ((_usb_cmd_pkt.wIndex & 0xff00) == 0) && (_usb_cmd_pkt.wLength == 0)) ? 0 : 1;
if (usbdInfo._usbd_devstate == 1)
ReqErr =1; /* Device is in default state */
if (usbdInfo._usbd_devstate == 2)
{
if((_usb_cmd_pkt.bmRequestType == 2) && (_usb_cmd_pkt.wIndex != 0)) //ep but not cep
ReqErr =1; /* Device is in Addressed State, but for noncep */
else if(_usb_cmd_pkt.bmRequestType == 0x1) //recip is interface
ReqErr=1; /* Device is in Addressed State, but for interface */
}
if(ReqErr == 1)
break; /* Request Error */
switch((_usb_cmd_pkt.bmRequestType & 0x3))
{
case 0: /* device */
if((_usb_cmd_pkt.wValue & 0x3) == DEVICE_REMOTE_WAKEUP)
usbdInfo.disableremotewakeup = 1;
else
ReqErr=1; /* No such feature for device */
break;
case 1: /* interface */
break;
case 2: /* endpoint */
if((_usb_cmd_pkt.wValue & 0x3) == ENDPOINT_HALT)
{
//dx->chgfea=dx->feature |ENDPOINT_HALT;
if((_usb_cmd_pkt.wIndex & 0xF) == 0) /* endPoint zero */
usbdInfo._usbd_unhaltep = 0;
else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPA_Num) /* endPoint A */
usbdInfo._usbd_unhaltep = usbdInfo.i32EPA_Num;
else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPB_Num) /* endPoint B */
usbdInfo._usbd_unhaltep = usbdInfo.i32EPB_Num;
else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPC_Num) /* endPoint C */
usbdInfo._usbd_unhaltep = usbdInfo.i32EPC_Num;
else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPD_Num) /* endPoint D */
usbdInfo._usbd_unhaltep = usbdInfo.i32EPD_Num;
else
ReqErr=1; /* endpoint choosen was not supported */
}
else
ReqErr=1; /* Neither device,interface nor endpoint was choosen */
break;
default:
break;
} //device
outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR); /* clear nak so that sts stage is complete */
outp32(CEP_IRQ_ENB, CEP_STACOM_IE);
break;
case USBR_GET_STATUS:
/* check if this is valid */
ReqErr = (((_usb_cmd_pkt.bmRequestType & 0xfc) == 0x80) && (_usb_cmd_pkt.wValue == 0)
&& ((_usb_cmd_pkt.wIndex & 0xff00) == 0) && (_usb_cmd_pkt.wLength == 0x2)) ? 0 : 1;
if (usbdInfo._usbd_devstate == 1)
ReqErr =1; /* Device is in default State */
if (usbdInfo._usbd_devstate == 2)
{
if ((_usb_cmd_pkt.bmRequestType & 0x3 == 0x2) && (_usb_cmd_pkt.wIndex != 0))
ReqErr =1; /* Device is in Addressed State, but for noncep */
else if (_usb_cmd_pkt.bmRequestType & 0x3 == 0x1)
ReqErr =1; /* Device is in Addressed State, but for interface */
}
if (ReqErr == 1)
break; /* Request Error */
usbdClearAllFlags();
usbdInfo.usbdGetStatus=1;
switch (_usb_cmd_pkt.bmRequestType & 0x3)
{
case 0:
if (usbdInfo.remotewakeup == 1)
usbdInfo.usbdGetStatusData = 0x3;
else
usbdInfo.usbdGetStatusData = 0x1;
break;
case 1: /* interface */
if (_usb_cmd_pkt.wIndex == 0)
usbdInfo.usbdGetStatusData = 0; /* Status of interface zero */
else
ReqErr=1; /* Status of interface non zero */
break;
case 2: /* endpoint */
if (_usb_cmd_pkt.wIndex == 0x0)
usbdInfo.usbdGetStatusData = 0; /* Status of Endpoint zero */
else if (((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPA_Num )||
((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPB_Num )||
((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPC_Num )||
((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPD_Num )
)
{
/* Status of Endpoint one */
if (usbdInfo._usbd_haltep == (_usb_cmd_pkt.wIndex & 0xF))
usbdInfo.usbdGetStatusData = 0x1;
else
usbdInfo.usbdGetStatusData = 0;
}
else
ReqErr=1; /* Status of non-existing Endpoint */
break;
default:
break;
}
outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
outp32(CEP_IRQ_ENB, CEP_IN_TK_IE); //suppkt int ,status and in token
break;
default:
break;
}
if (ReqErr == 1)
{
outp32(CEP_IRQ_ENB, (inp32(CEP_IRQ_ENB) | (CEP_SETUP_TK_IE |CEP_SETUP_PK_IE)));
outp32(CEP_CTRL_STAT, CEP_SETUP_PK_IS);
}
}
VOID usbd_isr(void)
{
UINT32 volatile IrqStL, IrqEnL, IrqSt, IrqEn;
IrqStL = inp32(IRQ_STAT_L); /* Wnat kind od EP's interrupt */
IrqEnL = inp32(IRQ_ENB_L); /* Which EP'S interrupt is enable */
if (!(IrqStL & IrqEnL))
return;
/* USB interrupt */
if (IrqStL & IRQ_USB_STAT)
{
IrqSt = inp32(USB_IRQ_STAT);
IrqEn = inp32(USB_IRQ_ENB);
if(IrqSt & USB_VBUS & IrqEn)
{
if(inp32(PHY_CTL) & Vbus_status)
{
usbdInfo._usbd_devstate = 1; /* default state */
usbdInfo._usbd_address = 0; /* zero */
if(usbdInfo.pfnPlug!=NULL)
usbdInfo.pfnPlug();
usbdInfo.u32VbusStatus = 1;
usbdStatus.usbConnected = 1;
outp32(PHY_CTL, (0x20 | Phy_suspend | vbus_detect));
}
else
{
if(usbdInfo.pfnUnplug!=NULL)
usbdInfo.pfnUnplug();
usbdInfo.u32VbusStatus = 0;
usbdStatus.usbConnected = 0;
usbdInfo.USBModeFlag =0;
usbdInfo.AlternateFlag = 0;
usbdStatus.appConnected = 0;
usbdInfo.AlternateFlag_Audio = 0;
usbdStatus.appConnected_Audio = 0;
usbdClearAllFlags();
g_bHostAttached = FALSE;
outp32(PHY_CTL, (0x20 | Phy_suspend));
}
outp32(USB_IRQ_STAT, VBUS_IS);
}
if (IrqSt & SOF_IS & IrqEn)
{
if(usbdInfo.pfnSOF!=NULL)
usbdInfo.pfnSOF();
g_bHostAttached = TRUE;
outp32(USB_IRQ_STAT, SOF_IS);
}
if (IrqSt & RST_IS & IrqEn)
{
usbdInfo._usbd_devstate = 0;
usbdInfo._usbd_speedset = 0;
usbdInfo._usbd_address = 0;
/* clear flags */
usbdClearAllFlags();
usbdInfo.USBModeFlag=0;
usbdInfo._usbd_DMA_Flag=0;
usbdInfo._usbd_DMA_In=1;
g_bHostAttached = TRUE;
/* reset dma */
if(usbdInfo.pfnReset!=NULL)
usbdInfo.pfnReset();
outp32(DMA_CTRL_STS, RST_DMA);
{
UINT32 iii;
for (iii=0; iii<0x100; iii++);
}
outp32(DMA_CTRL_STS, 0);
usbdInfo._usbd_devstate = 1; /* default state */
usbdInfo._usbd_address = 0; /* zero */
#ifdef __USBD_STANDARD_MODE__
if (inp32(OPER) & CUR_SPD)// 1:High Speed ; 0:Full speed
{
usbdInfo._usbd_speedset = 2;
usbdInfo.pfnHighSpeedInit();
}
else
{
usbdInfo._usbd_speedset = 1;
usbdInfo.pfnFullSpeedInit();
}
#else
#ifdef __USBD_HIGH_SPEED_MODE__
{
usbdInfo._usbd_speedset = 2; /* for high speed */
usbdInfo.pfnHighSpeedInit();
}
#endif
#ifdef __USBD_FULL_SPEED_MODE__
{
usbdInfo._usbd_speedset = 1; /* or full speed */
usbdInfo.pfnFullSpeedInit();
}
#endif
#endif
outp32(CEP_IRQ_ENB, CEP_SETUP_PK_IE); /* enable stetup interrupt */
if(usbdInfo.i32EPA_Num != -1)
{
outp32(EPA_RSP_SC, 0);
outp32(EPA_RSP_SC, BUF_FLUSH); /* flush fifo */
outp32(EPA_RSP_SC, TOGGLE);
}
if(usbdInfo.i32EPB_Num != -1)
{
outp32(EPB_RSP_SC, 0);
outp32(EPB_RSP_SC, BUF_FLUSH); /* flush fifo */
outp32(EPB_RSP_SC, TOGGLE);
}
if(usbdInfo.i32EPC_Num != -1)
{
outp32(EPC_RSP_SC, 0);
outp32(EPC_RSP_SC, BUF_FLUSH); /* flush fifo */
outp32(EPC_RSP_SC, TOGGLE);
}
if(usbdInfo.i32EPD_Num != -1)
{
outp32(EPD_RSP_SC, 0);
outp32(EPD_RSP_SC, BUF_FLUSH); /* flush fifo */
outp32(EPD_RSP_SC, TOGGLE);
}
outp32(ADDR, 0);
outp32(USB_IRQ_STAT, RST_IS);
outp32(USB_IRQ_ENB, (RST_IE|SUS_IE|RUM_IE|VBUS_IE));
outp32(CEP_IRQ_STAT, ~(CEP_SETUP_TK_IS | CEP_SETUP_PK_IS));
}
if (IrqSt & RUM_IS & IrqEn)
{
usbdInfo._usbd_resume = 1;
outp32(USB_IRQ_STAT, RUM_IS); /* Resume */
g_bHostAttached = TRUE;
outp32(USB_IRQ_ENB, (USB_RST_STS|USB_SUS_REQ|VBUS_IE));
}
if (IrqSt & SUS_IS & IrqEn)
{
int volatile i;
int volatile test;
usbdInfo._usbd_resume = 0;
g_bHostAttached = TRUE;
#ifdef __USBD_FULL_SPEED_MODE__
outp32(USB_IRQ_ENB, (USB_RST_STS|USB_RESUME|VBUS_IE));
#endif
test = inp32(PHY_CTL) & Vbus_status;
for(i=0;i<0x90000;i++)
{
if(test != (inp32(PHY_CTL) & Vbus_status))
{
if(inp32(PHY_CTL) & Vbus_status)
{
usbdInfo.u32VbusStatus = 1;
usbdStatus.usbConnected = 1;
outp32(PHY_CTL, (0x20 | Phy_suspend | vbus_detect));
}
else
{
outp32(USB_IRQ_ENB, (USB_RST_STS|USB_RESUME|VBUS_IE));
usbdInfo.u32VbusStatus = 0;
usbdStatus.usbConnected = 0;
usbdInfo.USBModeFlag =0;
usbdInfo.AlternateFlag = 0;
usbdStatus.appConnected = 0;
usbdInfo.AlternateFlag_Audio = 0;
usbdStatus.appConnected_Audio = 0;
outp32(PHY_CTL, (0x20 | Phy_suspend));
// sysprintf("Unplug(S)!!\n");
}
outp32(USB_IRQ_STAT, VBUS_IS);
break;
}
}
outp32(USB_IRQ_STAT, SUS_IS); /* Suspend */
outp32(USB_IRQ_ENB, (USB_RST_STS|USB_RESUME|VBUS_IE));
}
if (IrqSt & HISPD_IS & IrqEn)
{
usbdInfo._usbd_devstate = 1; /* default state */
usbdInfo._usbd_speedset = 2; /* for high speed */
usbdInfo._usbd_address = 0; /* zero */
g_bHostAttached = TRUE;
outp32(CEP_IRQ_ENB, CEP_SETUP_PK_IE); /* enable stetup interrupt */
outp32(USB_IRQ_STAT, HISPD_IS);
}
if (IrqSt & DMACOM_IS & IrqEn) /* DMA Completion */
{
usbdInfo._usbd_DMA_Flag = 1;
g_bHostAttached = TRUE;
outp32(USB_IRQ_STAT, DMACOM_IS);
if(usbdInfo.pfnDMACompletion!=NULL)
usbdInfo.pfnDMACompletion();
}
if (IrqSt & TCLKOK_IS & IrqEn)
outp32(USB_IRQ_STAT, TCLKOK_IS);
outp32(IRQ_STAT_L, IRQ_USB_STAT);
}
/* Control Endpoint Interrupt */
if (IrqStL & IRQ_CEP)
{
IrqSt = inp32(CEP_IRQ_STAT);
IrqEn = inp32(CEP_IRQ_ENB);
g_bHostAttached = TRUE;
//sysprintf("Control IRQ status = %x, ControlIRQ Enable=%x\n", IrqSt, IrqEn);
if (IrqSt & CEP_SUPTOK & IrqEn) /* SETUP TOKEN */
{
outp32(CEP_IRQ_STAT, CEP_SETUP_TK_IS);
return;
}
if (IrqSt & CEP_SUPPKT & IrqEn) /* SETUP PACKET */
{
outp32(CEP_IRQ_STAT, CEP_SETUP_PK_IS);
usbd_control_packet(); /* Setup Packet */
return;
}
if (IrqSt & CEP_OUT_TOK & IrqEn) /* OUT TOKEN */
{
outp32(CEP_IRQ_STAT, CEP_OUT_TK_IS);
/* DIFF */
// outp32(CEP_IRQ_ENB, (CEP_DATA_RxED_IE|CEP_STACOM_IE)); /* suppkt int//enb sts completion int */
return;
}
if (IrqSt & CEP_IN_TOK & IrqEn)
{
/* IN TOKEN */
outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
if (!(IrqSt & CEP_STACOM_IS))
{
outp32(CEP_IRQ_STAT, CEP_DATA_TxED_IS);
outp32(CEP_IRQ_ENB, CEP_DATA_TxED_IE|CEP_SETUP_PK_IE);
usbd_send_descriptor(); /* Send DAESCRIPTOR */
}
else
{
outp32(CEP_IRQ_STAT, CEP_DATA_TxED_IS);
outp32(CEP_IRQ_ENB, (CEP_STACOM_IE | CEP_DATA_TxED_IE));
}
return;
}
if (IrqSt & CEP_PING_TOK & IrqEn)
{
outp32(CEP_IRQ_STAT, CEP_PING_IS);
return;
}
if (IrqSt & CEP_DATA_TXD & IrqEn)
{
/* DIFF */
outp32(CEP_IRQ_STAT, (CEP_STACOM_IS|CEP_DATA_TxED_IS));
if (usbdInfo._usbd_remlen_flag)
{
outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
outp32(CEP_IRQ_ENB, (CEP_DATA_TxED_IE|CEP_IN_TK_IE)); /* suppkt int ,status and in token */
}
else
{
outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR); /* clear nak so that sts stage is complete */
outp32(CEP_IRQ_ENB, CEP_STACOM_IE); /* suppkt int ,status and in token */
}
if(usbdStatus.appConnected == 1)
{
if(usbdInfo.u32UVC)
outp32(CEP_END_ADDR, 0x0);
}
return;
}
if (IrqSt & CEP_DATA_RXD & IrqEn)
{
/* Data Packet receive(OUT) */
if (usbdInfo.CLASS_CMD_Oflag && usbdInfo.pfnClassDataOUTCallBack != NULL)
{
class_out_len = _usb_cmd_pkt.wLength;
class_out_len -= inp32(OUT_TRNSFR_CNT);
usbdInfo.pfnClassDataOUTCallBack();
usbdInfo.CLASS_CMD_Oflag = 0;
}
outp32(CEP_IRQ_STAT, (CEP_DATA_RxED_IS));
outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR); /* clear nak so that sts stage is complete */
if(class_out_len > 0)
{
outp32(CEP_IRQ_ENB, CEP_DATA_RxED_IE); // suppkt int//enb sts completion int
}
else
{
outp32(CEP_IRQ_ENB, (CEP_STACOM_IE|CEP_PING_IE|CEP_SETUP_PK_IE)); // suppkt int//enb sts completion int
}
if(usbdInfo.u32UVC == 1 && usbdStatus.appConnected == 1)
{
outp32(CEP_START_ADDR, 0);
outp32(CEP_END_ADDR, 0x0);
}
return;
}
if (IrqSt & CEP_NAK_IS & IrqEn)
{
outp32(CEP_IRQ_STAT, CEP_NAK_IS);
return;
}
if (IrqSt & CEP_STALL_IS & IrqEn)
{
outp32(CEP_IRQ_STAT, CEP_STALL_IS);
return;
}
if (IrqSt & CEP_ERR_IS & IrqEn)
{
outp32(CEP_IRQ_STAT, CEP_ERR_IS);
return;
}
if (IrqSt & CEP_STACOM_IS & IrqEn)
{
/* Update Device */
usbd_update_device();
outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
/* DIFF */
if (usbdInfo.CLASS_CMD_Iflag/* || usbdInfo.CLASS_CMD_Oflag*/ || usbdInfo._usbd_resume || usbdInfo.GET_DEV_Flag)
usbdInfo.USBModeFlag = 1;
outp32(CEP_IRQ_ENB, CEP_SETUP_PK_IE);
return;
}
if (IrqSt & CEP_FULL_IS & IrqEn)
{
outp32(CEP_IRQ_STAT, CEP_FULL_IS);
return;
}
if (IrqSt & CEP_EMPTY_IS & IrqEn)
{
outp32(CEP_IRQ_STAT, CEP_EMPTY_IS);
return;
}
outp32(IRQ_STAT_L, IRQ_CEP);
}
/* Endpoint Interrupt */
if (IrqStL & IRQ_NCEP)
{
g_bHostAttached = TRUE;
if (IrqStL & EPA_INT) /* Endpoint A */
{
IrqSt = inp32(EPA_IRQ_STAT);
IrqEn = inp32(EPA_IRQ_ENB);
outp32(EPA_IRQ_STAT, IrqSt);
if (usbdInfo.pfnEPACallBack != NULL)
usbdInfo.pfnEPACallBack(IrqEn, IrqSt);
}
if (IrqStL & EPB_INT) /* Endpoint B */
{
IrqSt = inp32(EPB_IRQ_STAT);
IrqEn = inp32(EPB_IRQ_ENB);
outp32(EPB_IRQ_STAT, IrqSt);
if (usbdInfo.pfnEPBCallBack != NULL)
usbdInfo.pfnEPBCallBack(IrqEn, IrqSt);
}
if (IrqStL & EPC_INT) /* Endpoint C */
{
IrqSt = inp32(EPC_IRQ_STAT);
IrqEn = inp32(EPC_IRQ_ENB);
outp32(EPC_IRQ_STAT, IrqSt);
if (usbdInfo.pfnEPCCallBack != NULL)
usbdInfo.pfnEPCCallBack(IrqEn, IrqSt);
}
if (IrqStL & EPD_INT) /* Endpoint D */
{
IrqSt = inp32(EPD_IRQ_STAT);
IrqEn = inp32(EPD_IRQ_ENB);
outp32(EPD_IRQ_STAT, IrqSt);
if (usbdInfo.pfnEPDCallBack != NULL)
usbdInfo.pfnEPDCallBack(IrqEn, IrqSt);
}
outp32(IRQ_STAT_L, IRQ_NCEP);
}
}
usbd.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef _W55FA93_USBD_H_
#define _W55FA93_USBD_H_
/*
* Standard requests
*/
#define USBR_GET_STATUS 0x00
#define USBR_CLEAR_FEATURE 0x01
#define USBR_SET_FEATURE 0x03
#define USBR_SET_ADDRESS 0x05
#define USBR_GET_DESCRIPTOR 0x06
#define USBR_SET_DESCRIPTOR 0x07
#define USBR_GET_CONFIGURATION 0x08
#define USBR_SET_CONFIGURATION 0x09
#define USBR_GET_INTERFACE 0x0A
#define USBR_SET_INTERFACE 0x0B
#define USBR_SYNCH_FRAME 0x0C
/*
* Descriptor types
*/
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
#define USB_DT_QUALIFIER 0x06
#define USB_DT_OSCONFIG 0x07
#define USB_DT_IFPOWER 0x08
#define USB_DT_HID 0x21
#define USB_DT_HID_RPT 0x22
#define EP_INPUT 0x80
#define EP_OUTPUT 0x00
// USB Endpoint Type
#define EP_ISO 0x01
#define EP_BULK 0x02
#define EP_INT 0x03
//USB FEATURE SELECTOR value
#define DEVICE_REMOTE_WAKEUP 1
#define ENDPOINT_HALT 0
#define TEST_MODE 2
//USB TEST MODES
#define TEST_J 0x01
#define TEST_K 0x02
#define TEST_SE0_NAK 0x03
#define TEST_PACKET 0x04
#define TEST_FORCE_ENABLE 0x05
//Driver definition of tokens
#define OUT_TOK 0x00
#define IN_TOK 0x01
#define SUP_TOK 0x02
#define PING_TOK 0x03
#define NO_TOK 0x04
//Bit Definitions of IRQ_ENB/STAT register
#define IRQ_USB_STAT 0x01
#define IRQ_CEP 0x02
#define IRQ_NCEP 0xfc
//Definition of Bits in USB_IRQ_STS register
#define USB_SOF 0x01
#define USB_RST_STS 0x02
#define USB_RESUME 0x04
#define USB_SUS_REQ 0x08
#define USB_HS_SETTLE 0x10
#define USB_DMA_REQ 0x20
#define USABLE_CLK 0x40
#define USB_VBUS 0x100
//Definition of Bits in USB_OPER register
#define USB_GEN_RES 0x1
#define USB_HS 0x2
#define USB_CUR_SPD_HS 0x4
//Definition of Bits in CEP_IRQ_STS register
#define CEP_SUPTOK 0x0001
#define CEP_SUPPKT 0x0002
#define CEP_OUT_TOK 0x0004
#define CEP_IN_TOK 0x0008
#define CEP_PING_TOK 0x0010
#define CEP_DATA_TXD 0x0020
#define CEP_DATA_RXD 0x0040
#define CEP_NAK_SENT 0x0080
#define CEP_STALL_SENT 0x0100
#define CEP_USB_ERR 0x0200
#define CEP_STS_END 0x0400
#define CEP_BUFF_FULL 0x0800
#define CEP_BUFF_EMPTY 0x1000
//Definition of Bits in CEP_CTRL_STS register
#define CEP_NAK_CLEAR 0x00 //writing zero clears the nak bit
#define CEP_SEND_STALL 0x02
//Definition of Bits in EP_IRQ_STS register
#define EP_BUFF_FULL 0x001
#define EP_BUFF_EMPTY 0x002
#define EP_SHORT_PKT 0x004
#define EP_DATA_TXD 0x008
#define EP_DATA_RXD 0x010
#define EP_OUT_TOK 0x020
#define EP_IN_TOK 0x040
#define EP_PING_TOK 0x080
#define EP_NAK_SENT 0x100
#define EP_STALL_SENT 0x200
#define EP_USB_ERR 0x800
//Bit Definitons of EP_RSP_SC Register
#define EP_BUFF_FLUSH 0x01
#define EP_MODE 0x06
#define EP_MODE_AUTO 0x01
#define EP_MODE_MAN 0x02
#define EP_MODE_FLY 0x03
#define EP_TOGGLE 0x8
#define EP_HALT 0x10
#define EP_ZERO_IN 0x20
#define EP_PKT_END 0x40
/* Define Endpoint feature */
#define Ep_In 0x01
#define Ep_Out 0x00
#define Ep_Bulk 0x01
#define Ep_Int 0x02
#define Ep_Iso 0x03
#define EP_A 0x00
#define EP_B 0x01
#define EP_C 0x02
#define EP_D 0x03
typedef struct usb_cmd
{
UINT8 bmRequestType;
UINT8 bRequest;
UINT16 wValue;
UINT16 wIndex;
UINT16 wLength;
} USB_CMD_T;
typedef void (*PFN_USBD_CALLBACK)(void);
typedef BOOL (PFN_USBD_EXIT_CALLBACK)(void);
typedef void (*PFN_USBD_EP_CALLBACK)(UINT32 u32IntEn,UINT32 u32IntStatus);
__packed typedef struct{
/* Descriptor pointer */
PUINT32 pu32DevDescriptor;
PUINT32 pu32QulDescriptor;
PUINT32 pu32HSConfDescriptor;
PUINT32 pu32FSConfDescriptor;
PUINT32 pu32HOSConfDescriptor;
PUINT32 pu32FOSConfDescriptor;
PUINT32 pu32HIDDescriptor;
PUINT32 pu32HIDRPTDescriptor;
PUINT32 pu32StringDescriptor[5];
/* Descriptor length */
UINT32 u32DevDescriptorLen;
UINT32 u32QulDescriptorLen;
UINT32 u32HSConfDescriptorLen;
UINT32 u32FSConfDescriptorLen;
UINT32 u32HOSConfDescriptorLen;
UINT32 u32FOSConfDescriptorLen;
UINT32 u32HIDDescriptorLen;
UINT32 u32HIDRPTDescriptorLen;
UINT32 u32StringDescriptorLen[5];
/* USBD Init */
PFN_USBD_CALLBACK pfnHighSpeedInit;
PFN_USBD_CALLBACK pfnFullSpeedInit;
/* Endpoint Number */
INT32 i32EPA_Num;
INT32 i32EPB_Num;
INT32 i32EPC_Num;
INT32 i32EPD_Num;
/* Endpoint Call Back */
PFN_USBD_EP_CALLBACK pfnEPACallBack;
PFN_USBD_EP_CALLBACK pfnEPBCallBack;
PFN_USBD_EP_CALLBACK pfnEPCCallBack;
PFN_USBD_EP_CALLBACK pfnEPDCallBack;
/* Class Call Back */
PFN_USBD_CALLBACK pfnClassDataINCallBack;
PFN_USBD_CALLBACK pfnClassDataOUTCallBack;
PFN_USBD_CALLBACK pfnDMACompletion;
PFN_USBD_CALLBACK pfnReset;
PFN_USBD_CALLBACK pfnSOF;
PFN_USBD_CALLBACK pfnPlug;
PFN_USBD_CALLBACK pfnUnplug;
/* Transfer Control */
UINT32 _usbd_remlen;
BOOL _usbd_remlen_flag;
UINT32 *_usbd_ptr;
/* Command Status Control */
UINT8 GET_DEV_Flag;
UINT8 GET_CFG_Flag;
UINT8 GET_QUL_Flag;
UINT8 GET_OSCFG_Flag;
UINT8 GET_STR_Flag;
UINT8 GET_VEN_Flag;
UINT8 GET_VENO_Flag;
UINT8 GET_HID_Flag;
UINT8 GET_HID_RPT_Flag;
UINT8 CLASS_CMD_Flag;
UINT8 CLASS_CMD_Iflag;
UINT8 CLASS_CMD_Oflag;
UINT32 usbdMaxPacketSize;
/* DMA Status flag */
UINT8 _usbd_DMA_Flag;
UINT8 _usbd_DMA_In;
/* Status flag */
UINT8 _usbd_resume;
UINT8 USBModeFlag;
UINT32 _usbd_devstate;
UINT32 _usbd_address;
UINT32 _usbd_speedset;
UINT16 _usbd_confsel;
UINT16 _usbd_intfsel;
UINT16 _usbd_altsel;
UINT32 _usbd_feature;
INT32 _usbd_haltep;
INT32 _usbd_unhaltep;
INT32 remotewakeup;
INT32 testmode;
INT32 enableremotewakeup;
INT32 enabletestmode;
INT32 disableremotewakeup;
INT32 disabletestmode;
INT32 testselector;
UINT32 usbdGetStatusData;
UINT8 usbdGetConfig;
UINT8 usbdGetInterface;
UINT8 usbdGetStatus;
/* for isochronous */
UINT32 AlternateFlag;
UINT32 u32VbusStatus;
/* for Isochronous */
UINT32 AlternateFlag_Audio;
UINT32 u32UVC;
UINT32 USBStartFlag;
}USBD_INFO_T;
__packed typedef struct{
UINT32 appConnected;
UINT32 usbConnected;
UINT32 appConnected_Audio;
}USBD_STATUS_T;
typedef struct
{
UINT8 EP_Num;
UINT8 EP_Dir;
UINT8 EP_Type;
} USB_EP_Inf_T;
VOID udcOpen(void);
VOID udcClose(void);
VOID udcInit(void);
VOID udcDeinit(void);
BOOL udcIsAttached(void);
BOOL udcIsAttachedToHost(void);
#endif
T168_111\core\N32903文件:第20~32个文件
最新推荐文章于 2024-10-17 15:34:15 发布