i96-uboot/arch/arm/cpu/armv7/rda/ifc.c

173 lines
5.3 KiB
C

#include "common.h"
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/reg_ifc.h>
#include <asm/arch/ifc.h>
#undef assert
#ifdef DEBUG
#include <assert.h>
#else
#define assert(...)
#endif
#define HAL_TRACE(...)
HAL_IFC_REQUEST_ID_T g_halModuleIfcChannelOwner[SYS_IFC_STD_CHAN_NB];
void hal_IfcOpen(void)
{
u8 channel;
// Initialize the channel table with unknown requests.
for (channel = 0; channel < SYS_IFC_STD_CHAN_NB; channel++)
{
g_halModuleIfcChannelOwner[channel] = HAL_IFC_NO_REQWEST;
}
}
HAL_IFC_REQUEST_ID_T hal_IfcGetOwner(u8 channel)
{
// Here, we consider the transfer as previously finished.
if (channel == HAL_UNKNOWN_CHANNEL) return HAL_IFC_NO_REQWEST;
// Channel number too big.
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
return g_halModuleIfcChannelOwner[channel];
}
void hal_IfcChannelRelease(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
{
//u32 status;
// Here, we consider the transfer as previously finished.
if (channel == HAL_UNKNOWN_CHANNEL) return;
// Channel number too big.
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
//status = hal_SysEnterCriticalSection();
if (g_halModuleIfcChannelOwner[channel] == requestId)
{
// disable this channel
hwp_sysIfc->std_ch[channel].control = (SYS_IFC_REQ_SRC(requestId)
| SYS_IFC_CH_RD_HW_EXCH
| SYS_IFC_DISABLE);
// read the status of this channel
if (hwp_sysIfc->std_ch[channel].status & SYS_IFC_ENABLE)
{
HAL_TRACE(_HAL | TSTDOUT,0," Strange, the released channel not disabled yet");
}
// Write the TC to 0 for next time the channel is re-enabled
hwp_sysIfc->std_ch[channel].tc = 0;
}
//hal_SysExitCriticalSection(status);
}
void hal_IfcChannelFlush(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
{
//u32 status;
// Here, we consider the transfer as previously finished.
if (channel == HAL_UNKNOWN_CHANNEL) return;
// Channel number too big.
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
// Check that the channel is really owned by the peripheral
// which is doing the request, it could have been release
// automatically or by an IRQ handler.
//status = hal_SysEnterCriticalSection();
if (g_halModuleIfcChannelOwner[channel] == requestId)
{
// If fifo not empty, flush it.
if ( !(hwp_sysIfc->std_ch[channel].status & SYS_IFC_FIFO_EMPTY) )
{
hwp_sysIfc->std_ch[channel].control =
hwp_sysIfc->std_ch[channel].control | SYS_IFC_FLUSH;
}
}
//hal_SysExitCriticalSection(status);
}
BOOL hal_IfcChannelIsFifoEmpty(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
{
//u32 status;
BOOL fifoIsEmpty = TRUE;
// Here, we consider the transfer as previously finished.
if (channel == HAL_UNKNOWN_CHANNEL) return fifoIsEmpty;
// Channel number too big.
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
// Check that the channel is really owned by the peripheral
// which is doing the request, it could have been release
// automatically or by an IRQ handler.
//status = hal_SysEnterCriticalSection();
if (g_halModuleIfcChannelOwner[channel] == requestId)
{
fifoIsEmpty =
(FALSE != (hwp_sysIfc->std_ch[channel].status & SYS_IFC_FIFO_EMPTY));
}
//hal_SysExitCriticalSection(status);
return fifoIsEmpty;
}
u8 hal_IfcTransferStart(HAL_IFC_REQUEST_ID_T requestId, u8* memStartAddr, u32 xferSize, HAL_IFC_MODE_T ifcMode)
{
//u32 status = hal_SysEnterCriticalSection();
u8 channel;
u8 i;
// Check buffer alignment depending on the mode
if (ifcMode != HAL_IFC_SIZE_8_MODE_MANUAL && ifcMode != HAL_IFC_SIZE_8_MODE_AUTO)
{
// Then ifcMode == HAL_IFC_SIZE_32, check word alignment
assert(((u32)memStartAddr%4) == 0,
"HAL IFC: 32 bits transfer misaligned 0x@%08X", memStartAddr);
}
else
{
// ifcMode == HAL_IFC_SIZE_8, nothing to check
}
// Check the requested id is not currently already used.
for (i = 0; i < SYS_IFC_STD_CHAN_NB ; i++)
{
if (GET_BITFIELD(hwp_sysIfc->std_ch[i].control, SYS_IFC_REQ_SRC) == requestId)
{
// This channel is or was used for the requestId request.
// Check it is still in use.
assert((hwp_sysIfc->std_ch[i].status & SYS_IFC_ENABLE) == 0,
"HAL: Attempt to use the IFC to deal with a %d"
" request still active on channel %d", requestId, i);
}
}
channel = SYS_IFC_CH_TO_USE(hwp_sysIfc->get_ch) ;
if (channel >= SYS_IFC_STD_CHAN_NB)
{
serial_puts("HAL_UNKNOWN_CHANNEL\n");
//hal_SysExitCriticalSection(status);
return HAL_UNKNOWN_CHANNEL;
}
g_halModuleIfcChannelOwner[channel] = requestId;
hwp_sysIfc->std_ch[channel].start_addr = (u32) memStartAddr;
hwp_sysIfc->std_ch[channel].tc = xferSize;
hwp_sysIfc->std_ch[channel].control = (SYS_IFC_REQ_SRC(requestId)
| ifcMode
| SYS_IFC_CH_RD_HW_EXCH
| SYS_IFC_ENABLE);
//hal_SysExitCriticalSection(status);
return channel;
}