You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1541 lines
37 KiB
1541 lines
37 KiB
/* vxbArmv7GenTimer.c - ARMV7 Generic Timer driver for VxBus */
|
|
|
|
/*
|
|
*
|
|
* This program is OPEN SOURCE software: you can redistribute it and/or modify it;
|
|
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
*/
|
|
|
|
/* includes */
|
|
|
|
#include <vxWorks.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <intLib.h>
|
|
#include <vsbConfig.h>
|
|
#include <hwif/vxbus/vxBus.h>
|
|
#include <vxbTimerLib.h>
|
|
#include <hwif/util/hwMemLib.h>
|
|
#include <hwif/vxbus/hwConf.h>
|
|
|
|
#ifdef _WRS_CONFIG_SMP
|
|
#include <cpuset.h>
|
|
#include <taskLib.h>
|
|
#include <private/cpcLibP.h>
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
IMPORT int uartf(const char * fmt, ...);
|
|
|
|
|
|
/* defines */
|
|
|
|
#ifdef ARMBE8
|
|
# define SWAP32 vxbSwap32
|
|
#else
|
|
# define SWAP32
|
|
#endif /* ARMBE8 */
|
|
|
|
/* debug macro */
|
|
|
|
#undef GEN_TIMER_DBG_ON
|
|
#ifdef GEN_TIMER_DBG_ON
|
|
|
|
/* turning local symbols into global symbols */
|
|
|
|
#ifdef LOCAL
|
|
#undef LOCAL
|
|
#define LOCAL
|
|
#endif
|
|
|
|
#include <private/kwriteLibP.h> /* _func_kprintf */
|
|
#define GEN_TIMER_DBG_OFF 0x00000000
|
|
#define GEN_TIMER_DBG_ISR 0x00000001
|
|
#define GEN_TIMER_DBG_ERR 0x00000002
|
|
#define GEN_TIMER_DBG_INFO 0x00000004
|
|
#define GEN_TIMER_DBG_ALL 0xffffffff
|
|
|
|
LOCAL UINT32 armv7GenTimerDbgMask = GEN_TIMER_DBG_ALL;
|
|
|
|
#define GEN_TIMER_DBG(mask, ...) \
|
|
do \
|
|
{ \
|
|
if ((armv7GenTimerDbgMask & (mask)) || \
|
|
((mask) == GEN_TIMER_DBG_ALL)) \
|
|
{ \
|
|
uartf(__VA_ARGS__); \
|
|
} \
|
|
} \
|
|
while ((FALSE))
|
|
#else
|
|
#define GEN_TIMER_DBG(...)
|
|
#endif /* GEN_TIMER_DBG_ON */
|
|
|
|
#undef TIMERFUNC_TO_TIMERDATA
|
|
#define TIMERFUNC_TO_TIMERDATA(pTimerFunc) \
|
|
(ARMV7_GEN_TIMER_DATA *)((ULONG)(pTimerFunc) - \
|
|
OFFSET (ARMV7_GEN_TIMER_DATA, timerFunc))
|
|
|
|
#define ARMV7_GEN_TIMER_NAME "armv7GenTimer"
|
|
#define ARMV7_GEN_TIMER_MAX_COUNT 0x7fffffff
|
|
#define ARMV7_GEN_TIMER_DEFAULT_TPS 60 /*default*/
|
|
#define ARMV7_GEN_TIMER_DEFAULT_MIN_FREQ 10 /*default*/
|
|
#define ARMV7_GEN_TIMER_DEFAULT_MAX_FREQ 5000 /*default*/
|
|
#define ARMV7_GEN_TIMER_MAX_CLK_FREQ 50000000
|
|
#define ARMV7_GEN_TIMER_MIN_CLK_FREQ 1000000
|
|
|
|
#define GEN_TIMER_REG_CTL 0
|
|
#define GEN_TIMER_REG_TVAL 1
|
|
|
|
#define GEN_TIMER_CTRL_ENABLE (1 << 0)
|
|
#define GEN_TIMER_CTRL_IMASK (1 << 1)
|
|
#define GEN_TIMER_CTRL_ISTATUS (1 << 2)
|
|
|
|
#define GEN_TIMER_SECURE_PHY_PPI (0)
|
|
#define GEN_TIMER_NON_SECURE_PHY_PPI (1)
|
|
#define GEN_TIMER_VIRTURE_PPI (2)
|
|
#define GEN_TIMER_HYP_PPI (3)
|
|
#define GEN_TIMER_MAX_PPI (4)
|
|
|
|
/* externs */
|
|
|
|
/* globals */
|
|
|
|
/* structure to store the timer information */
|
|
|
|
typedef struct armv7GenTimerData
|
|
{
|
|
VXB_DEVICE_ID pInst;
|
|
struct vxbTimerFunctionality timerFunc;
|
|
void (*pIsrFunc)(int);
|
|
int arg;
|
|
spinlockIsr_t spinLock;
|
|
UINT32 maxCount;
|
|
UINT32 flags;
|
|
BOOL isEnabled;
|
|
BOOL isVirtual;
|
|
BOOL secPhyAvail;
|
|
BOOL nonSecPhyAvail;
|
|
BOOL autoReload;
|
|
} ARMV7_GEN_TIMER_DATA;
|
|
|
|
ARMV7_GEN_TIMER_DATA * pArmv7GenTimer = NULL;
|
|
|
|
/* function declarations */
|
|
|
|
|
|
LOCAL STATUS armv7GenTimerAttach (VXB_DEVICE_ID pDev);
|
|
LOCAL void armv7GenTimerInt (ARMV7_GEN_TIMER_DATA * pTimer);
|
|
|
|
LOCAL STATUS armv7GenTimerAllocate (
|
|
VXB_DEVICE_ID pInst,
|
|
UINT32 flags,
|
|
void ** pCookie,
|
|
UINT32 timerNo
|
|
);
|
|
LOCAL STATUS armv7GenTimerRelease (
|
|
VXB_DEVICE_ID pInst,
|
|
void* pCookie
|
|
);
|
|
LOCAL STATUS armv7GenTimerRolloverGet (void * pCookie, UINT32 * count);
|
|
LOCAL STATUS armv7GenTimerCountGet (void * pCookie, UINT32 * count);
|
|
LOCAL STATUS armv7GenTimerCountGet64 (void * pCookie, UINT64 * count64);
|
|
LOCAL STATUS armv7GenTimerDisable (void * pCookie);
|
|
LOCAL STATUS armv7GenTimerEnable (void * pCookie, UINT32 maxTimerCount);
|
|
LOCAL STATUS armv7GenTimerISRSet (void * pCookie, void (*pFunc)(int), int arg);
|
|
IMPORT volatile UINT32 __inline__GetVirtTimerCnt(void);
|
|
IMPORT volatile UINT32 __inline__GetPhyTimerCnt(void);
|
|
|
|
LOCAL void armv7GenTimerInstInit
|
|
(
|
|
struct vxbDev * pDev
|
|
);
|
|
LOCAL void armv7GenTimerInstInit2
|
|
(
|
|
struct vxbDev * pDev
|
|
);
|
|
LOCAL void armv7GenTimerInstConnect
|
|
(
|
|
struct vxbDev * pDev
|
|
);
|
|
|
|
/* locals */
|
|
LOCAL struct drvBusFuncs armv7GenTimerFuncs =
|
|
{
|
|
armv7GenTimerInstInit, /* devInstanceInit */
|
|
armv7GenTimerInstInit2, /* devInstanceInit2 */
|
|
armv7GenTimerInstConnect /* devConnect */
|
|
};
|
|
|
|
|
|
LOCAL STATUS armv7GenTimerFuncGet
|
|
(
|
|
VXB_DEVICE_ID pInst,
|
|
struct vxbTimerFunctionality** pTimerFunc,
|
|
int timerNo
|
|
);
|
|
|
|
/* driver methods */
|
|
|
|
LOCAL device_method_t davinciTimerDrv_methods[] =
|
|
{
|
|
DEVMETHOD(vxbTimerFuncGet,armv7GenTimerFuncGet),
|
|
{0, NULL}
|
|
};
|
|
|
|
|
|
LOCAL struct vxbDevRegInfo armv7GenTimerRegistration =
|
|
{
|
|
NULL, /* pNext */
|
|
VXB_DEVID_DEVICE, /* devID */
|
|
VXB_BUSID_PLB, /* busID = PLB */
|
|
VXB_VER_4_0_0, /* vxbVersion */
|
|
"armGenTimer", /* drvName */
|
|
&armv7GenTimerFuncs, /* pDrvBusFuncs */
|
|
NULL,
|
|
NULL, /* devProbe */
|
|
NULL /* pParamDefaults */
|
|
};
|
|
|
|
|
|
void armv7GenTimerRegister(void)
|
|
{
|
|
vxbDevRegister((struct vxbDevRegInfo *)&armv7GenTimerRegistration);
|
|
}
|
|
|
|
LOCAL void armv7GenTimerInstInit
|
|
(
|
|
struct vxbDev * pDev
|
|
)
|
|
{
|
|
armv7GenTimerAttach(pDev);
|
|
return;
|
|
}
|
|
LOCAL void armv7GenTimerInstInit2
|
|
(
|
|
struct vxbDev * pDev
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
LOCAL void armv7GenTimerInstConnect
|
|
(
|
|
struct vxbDev * pDev
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* The inline assembly to access generic timer on c14 follows diab's inline
|
|
* assembly syntax, so diab compiler must be used.
|
|
*/
|
|
|
|
#ifndef __DCC__
|
|
|
|
UINT32 __inline__GetCntFreq (void)
|
|
{
|
|
UINT32 rtn;
|
|
|
|
__asm__ volatile (
|
|
"mrc p15, 0, %0, c14, c0, 0 \n"
|
|
: "=r" (rtn)
|
|
);
|
|
return (rtn);
|
|
}
|
|
|
|
UINT32 __inline__GetVirtTimerValue (void)
|
|
{
|
|
UINT32 rtn;
|
|
__asm__ volatile (
|
|
"mrc p15, 0, %0, c14, c3, 0 \n"
|
|
: "=r" (rtn)
|
|
);
|
|
return (rtn);
|
|
}
|
|
|
|
UINT32 __inline__GetVirtTimerCtrl (void)
|
|
{
|
|
UINT32 rtn;
|
|
__asm__ volatile (
|
|
"mrc p15, 0, %0, c14, c3, 1\n"
|
|
: "=r" (rtn)
|
|
);
|
|
return (rtn);
|
|
}
|
|
|
|
void __inline__SetVirtTimerValue (UINT32 val)
|
|
{
|
|
__asm__ volatile (
|
|
"mcr p15, 0, %0, c14, c3, 0 \n"
|
|
:
|
|
: "r" (val) : "memory"
|
|
);
|
|
}
|
|
|
|
void __inline__SetVirtTimerCtrl (UINT32 val)
|
|
{
|
|
__asm__ volatile (
|
|
"mcr p15, 0, %0, c14, c3, 1 \n"
|
|
:
|
|
: "r" (val) : "memory"
|
|
);
|
|
}
|
|
|
|
/* unsigned int sys_gtimer_timervalue_get(void) */
|
|
UINT32 __inline__GetPhyTimerValue (void)
|
|
{
|
|
UINT32 rtn;
|
|
__asm__ volatile (
|
|
"mrc p15, 0, %0, c14, c2, 0 \n"
|
|
: "=r" (rtn)
|
|
);
|
|
return (rtn);
|
|
}
|
|
|
|
|
|
|
|
/* sys_gtimer_timervalue_set(unsigned int value) */
|
|
void __inline__SetPhyTimerValue (UINT32 val)
|
|
{
|
|
__asm__ volatile (
|
|
|
|
"mcr p15, 0, %0, c14, c2, 0 \n"
|
|
:
|
|
: "r" (val) : "memory"
|
|
);
|
|
}
|
|
|
|
|
|
/* sys_gtimer_pl1phyctrl_set */
|
|
void __inline__SetPhyTimerCtrl (UINT32 val)
|
|
{
|
|
__asm__ volatile (
|
|
|
|
"mcr p15, 0, %0, c14, c2, 1 \n"
|
|
:
|
|
: "r" (val) : "memory"
|
|
);
|
|
}
|
|
|
|
/* sys_gtimer_pl1phyctrl_get */
|
|
UINT32 __inline__GetPhyTimerCtrl (void)
|
|
{
|
|
UINT32 rtn;
|
|
__asm__ volatile (
|
|
"mrc p15, 0, %0, c14, c2, 1 \n"
|
|
: "=r" (rtn)
|
|
);
|
|
return (rtn);
|
|
}
|
|
#else /* __DCC__ for diab */
|
|
__asm volatile UINT32 __macro__GetCntFreq (void)
|
|
{
|
|
! "r0"
|
|
mrc p15, 0, r0, c14, c0, 0
|
|
}
|
|
volatile UINT32 __inline__GetCntFreq (void)
|
|
{
|
|
return __macro__GetCntFreq();
|
|
}
|
|
|
|
|
|
__asm volatile UINT32 __macro__GetVirtTimerValue (void)
|
|
{
|
|
! "r0"
|
|
mrc p15, 0, r0, c14, c3, 0
|
|
}
|
|
volatile UINT32 __inline__GetVirtTimerValue (void)
|
|
{
|
|
return __macro__GetVirtTimerValue ();
|
|
}
|
|
|
|
|
|
__asm volatile UINT32 __macro__GetVirtTimerCtrl (void)
|
|
{
|
|
! "r0"
|
|
mrc p15, 0, r0, c14, c3, 1
|
|
}
|
|
volatile UINT32 __inline__GetVirtTimerCtrl (void)
|
|
{
|
|
return __macro__GetVirtTimerCtrl();
|
|
}
|
|
|
|
|
|
__asm volatile void __macro__SetVirtTimerValue (UINT32 val)
|
|
{
|
|
% reg val
|
|
! "r0"
|
|
mcr p15, 0, val, c14, c3, 0
|
|
}
|
|
volatile void __inline__SetVirtTimerValue (UINT32 val)
|
|
{
|
|
__macro__SetVirtTimerValue(val);
|
|
}
|
|
|
|
__asm volatile void __macro__SetVirtTimerCtrl (UINT32 val)
|
|
{
|
|
% reg val
|
|
! "r0"
|
|
mcr p15, 0, val, c14, c3, 1
|
|
}
|
|
volatile void __inline__SetVirtTimerCtrl (UINT32 val)
|
|
{
|
|
__macro__SetVirtTimerCtrl (val);
|
|
}
|
|
|
|
|
|
__asm volatile UINT32 __macro__GetPhyTimerValue (void)
|
|
{
|
|
! "r0"
|
|
mrc p15, 0, r0, c14, c2, 0
|
|
}
|
|
volatile UINT32 __inline__GetPhyTimerValue (void)
|
|
{
|
|
return __macro__GetPhyTimerValue();
|
|
}
|
|
|
|
|
|
__asm volatile UINT32 __macro__GetPhyTimerCtrl (void)
|
|
{
|
|
! "r0"
|
|
mrc p15, 0, r0, c14, c2, 1
|
|
}
|
|
volatile UINT32 __inline__GetPhyTimerCtrl (void)
|
|
{
|
|
return __macro__GetPhyTimerCtrl();
|
|
}
|
|
|
|
|
|
__asm volatile void __macro__SetPhyTimerValue (UINT32 val)
|
|
{
|
|
% reg val
|
|
! "r0"
|
|
mcr p15, 0, val, c14, c2, 0
|
|
}
|
|
volatile void __inline__SetPhyTimerValue (UINT32 val)
|
|
{
|
|
__macro__SetPhyTimerValue (val);
|
|
}
|
|
|
|
|
|
__asm volatile void __macro__SetPhyTimerCtrl (UINT32 val)
|
|
{
|
|
% reg val
|
|
! "r0"
|
|
mcr p15, 0, val, c14, c2, 1
|
|
}
|
|
volatile void __inline__SetPhyTimerCtrl (UINT32 val)
|
|
{
|
|
__macro__SetPhyTimerCtrl (val);
|
|
}
|
|
#endif
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerWriteReg - write the timer register
|
|
*
|
|
* This routine writes value to the generic timer register.
|
|
*
|
|
* RETURNS: N/A
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
_WRS_INLINE void armv7GenTimerWriteReg
|
|
(
|
|
BOOL isVirtual,
|
|
UINT32 reg,
|
|
UINT32 val
|
|
)
|
|
{
|
|
if (isVirtual)
|
|
{
|
|
if (reg == GEN_TIMER_REG_CTL)
|
|
{
|
|
__inline__SetVirtTimerCtrl (val);
|
|
}
|
|
else
|
|
{
|
|
__inline__SetVirtTimerValue (val);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (reg == GEN_TIMER_REG_CTL)
|
|
{
|
|
__inline__SetPhyTimerCtrl (val);
|
|
}
|
|
else
|
|
{
|
|
__inline__SetPhyTimerValue (val);
|
|
}
|
|
}
|
|
|
|
WRS_ASM ("ISB");
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerReadReg - read the timer register
|
|
*
|
|
* This routine reads the generic timer register value.
|
|
*
|
|
* RETURNS: timer register value.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
_WRS_INLINE UINT32 armv7GenTimerReadReg
|
|
(
|
|
BOOL isVirtual,
|
|
UINT32 reg
|
|
)
|
|
{
|
|
UINT32 val = 0;
|
|
|
|
if (isVirtual)
|
|
{
|
|
if (reg == GEN_TIMER_REG_CTL)
|
|
{
|
|
val = __inline__GetVirtTimerCtrl ();
|
|
}
|
|
else
|
|
{
|
|
val = __inline__GetVirtTimerValue ();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (reg == GEN_TIMER_REG_CTL)
|
|
{
|
|
val = __inline__GetPhyTimerCtrl ();
|
|
}
|
|
else
|
|
{
|
|
val = __inline__GetPhyTimerValue ();
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerGetTimerCnt - get the generic timer count
|
|
*
|
|
* This routine gets the generic timer counter register value.
|
|
*
|
|
* RETURNS: timer counter.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
_WRS_INLINE UINT64 armv7GenTimerGetTimerCnt
|
|
(
|
|
BOOL isVirtual
|
|
)
|
|
{
|
|
UINT64 val = 0;
|
|
|
|
WRS_ASM ("ISB");
|
|
|
|
if (isVirtual)
|
|
{
|
|
val = __inline__GetVirtTimerCnt ();
|
|
}
|
|
else
|
|
{
|
|
val = __inline__GetPhyTimerCnt ();
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerAllocate - allocate resources for a timer
|
|
*
|
|
* This is the function called to allocate a timer for usage by the
|
|
* Timer Abstraction Layer.
|
|
*
|
|
* RETURNS: OK or ERROR if timer allocation failed.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerAllocate
|
|
(
|
|
VXB_DEVICE_ID pInst,
|
|
UINT32 flags,
|
|
void ** pCookie,
|
|
UINT32 timerNo
|
|
)
|
|
{
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO,
|
|
"%s:Line:%d\r\n", (int)__FUNCTION__, __LINE__);
|
|
VXB_ASSERT_NONNULL (pCookie, ERROR);
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)(pInst->pDrvCtrl);
|
|
|
|
/* check whether 'pTimerData' is valid or not */
|
|
|
|
if (pTimer != NULL)
|
|
{
|
|
/* if the timer is already allocated, return ERROR */
|
|
|
|
if ((pTimer->pInst != NULL) || (pTimer->timerFunc.allocated))
|
|
{
|
|
uartf("%s,%d: pTimer->pInst = %p . This is error!\r\n",__FILE__,__LINE__, pTimer->pInst);
|
|
return ERROR;
|
|
}
|
|
|
|
/* set the auto-reload flag */
|
|
|
|
if ((flags & VXB_TIMER_AUTO_RELOAD) != 0)
|
|
pTimer->autoReload = TRUE;
|
|
|
|
/* copy the instance pointer */
|
|
|
|
pTimer->pInst = pInst;
|
|
|
|
/* set the allocated flag */
|
|
|
|
pTimer->timerFunc.allocated = TRUE;
|
|
}
|
|
else
|
|
return ERROR;
|
|
|
|
/* store the timer information in the pCookie */
|
|
|
|
*pCookie = pInst->pDrvCtrl;
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "%s:Line:%d\r\n",
|
|
(int)__FUNCTION__, __LINE__);
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerDisableInternal - disable the timer without spinlock
|
|
*
|
|
* This routine stops the timer and disables interrupt generation for the
|
|
* requested hardware timer without spinlock.
|
|
*
|
|
* RETURNS: N/A
|
|
*
|
|
* ERRNO: N/A
|
|
*
|
|
*/
|
|
|
|
LOCAL void armv7GenTimerDisableInternal
|
|
(
|
|
ARMV7_GEN_TIMER_DATA * pTimer
|
|
)
|
|
{
|
|
VXB_DEVICE_ID pInst;
|
|
|
|
if (!pTimer->isEnabled)
|
|
return;
|
|
|
|
/* disable the timer */
|
|
|
|
armv7GenTimerWriteReg (pTimer->isVirtual, GEN_TIMER_REG_CTL,
|
|
GEN_TIMER_CTRL_IMASK);
|
|
|
|
/* disable the timer interrupt */
|
|
|
|
pInst = pTimer->pInst;
|
|
|
|
vxbIntDisable (pInst, 0, armv7GenTimerInt, pTimer);
|
|
|
|
pTimer->maxCount = ARMV7_GEN_TIMER_MAX_COUNT;
|
|
pTimer->isEnabled = FALSE;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerRelease - release the timer resource
|
|
*
|
|
* This is the function called to release a timer device.
|
|
*
|
|
* RETURNS: OK or ERROR if parameter is not valid.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerRelease
|
|
(
|
|
VXB_DEVICE_ID pInst,
|
|
void* pCookie
|
|
)
|
|
{
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
struct vxbTimerFunctionality * pTimerFunc;
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "%s:Line:%d\r\n",
|
|
(int)__FUNCTION__, __LINE__);
|
|
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)pCookie;
|
|
if ((pTimer == NULL) ||
|
|
(pTimer->pInst != pInst) ||
|
|
(!pTimer->timerFunc.allocated))
|
|
{
|
|
uartf("%s,%d: pTimer is bad!\r\n",__FILE__,__LINE__);
|
|
return ERROR;
|
|
}
|
|
|
|
pTimerFunc = &(pTimer->timerFunc);
|
|
|
|
SPIN_LOCK_ISR_TAKE (&pTimer->spinLock);
|
|
|
|
/* check that timer is allocated */
|
|
|
|
if (!pTimerFunc->allocated)
|
|
{
|
|
SPIN_LOCK_ISR_GIVE (&pTimer->spinLock);
|
|
return ERROR;
|
|
}
|
|
|
|
/* disable the timer */
|
|
|
|
(void)armv7GenTimerDisableInternal (pTimer);
|
|
|
|
/* reset the autoReload flag */
|
|
|
|
if (pTimer->autoReload)
|
|
{
|
|
pTimer->autoReload = FALSE;
|
|
}
|
|
|
|
pTimer->pIsrFunc = NULL;
|
|
pTimer->arg = 0;
|
|
pTimer->flags = 0;
|
|
|
|
/* reset the timer allocated flag */
|
|
|
|
pTimerFunc->allocated = FALSE;
|
|
pTimer->pInst = NULL;
|
|
|
|
SPIN_LOCK_ISR_GIVE (&pTimer->spinLock);
|
|
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "%s:Line:%d\r\n",
|
|
(int)__FUNCTION__, __LINE__);
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerRolloverGet - retrieve the maximum value of the counter
|
|
*
|
|
* This is the function called to retrieve the maximum value of the counter.
|
|
* The maximum value is returned in 'pCount' parameter.
|
|
*
|
|
* RETURNS: OK or ERROR if the parameter is invalid.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerRolloverGet
|
|
(
|
|
void * pCookie,
|
|
UINT32 * pCount
|
|
)
|
|
{
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
|
|
VXB_ASSERT_NONNULL (pCount, ERROR);
|
|
|
|
/* free run counter, always get the MAX count for timestamp */
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)pCookie;
|
|
if (pTimer == NULL)
|
|
{
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_ERR,"%s,%d: pTimer is bad!\r\n",__FILE__,__LINE__);
|
|
return ERROR;
|
|
}
|
|
*pCount = pTimer->maxCount;
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO,
|
|
"armv7GenTimerRolloverGet: %u. for vx68\r\n", pTimer->maxCount);
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO,
|
|
"armv7GenTimerRolloverGet: %u\r\n", ARMV7_GEN_TIMER_MAX_COUNT);
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerCountGet - retrieve the current value of the counter
|
|
*
|
|
* This function is used to retrieve the current value of the counter.
|
|
* The current value is returned in 'pCount' parameter.
|
|
*
|
|
* RETURNS: OK or ERROR if the parameter is invalid.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerCountGet
|
|
(
|
|
void * pCookie,
|
|
UINT32 * pCount
|
|
)
|
|
{
|
|
UINT64 cnt64;
|
|
UINT32 cnt32;
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "armv7GenTimerCountGet\r\n");
|
|
VXB_ASSERT_NONNULL (pCookie, ERROR);
|
|
VXB_ASSERT_NONNULL (pCount, ERROR);
|
|
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)pCookie;
|
|
|
|
/* the timer counter is from the lower 32 bits of the 64 bits register */
|
|
|
|
cnt64 = armv7GenTimerGetTimerCnt (pTimer->isVirtual);
|
|
cnt32 = (UINT32)(cnt64 % ((UINT32)ARMV7_GEN_TIMER_MAX_COUNT + 1));
|
|
*pCount = cnt32;
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO,
|
|
"armv7GenTimerCountGet: cnt32=%u\r\n", cnt32);
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerCountGet64 - retrieve the current 64bit value of the counter
|
|
*
|
|
* This function is used to retrieve the current 64bit value of the counter.
|
|
* The current value is returned in 'pCount' parameter.
|
|
*
|
|
* RETURNS: OK or ERROR if the parameter is invalid.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
/*
|
|
Note-20201112: verified bits[63-31] are sign bits:
|
|
-> testtmcount
|
|
v_val=0xffffffff_f859af64; p_val=0xffffffff_f859af66
|
|
-> testtmcount
|
|
v_val=0xffffffff_fd1b6b3d; p_val=0xffffffff_fd1b6b3f
|
|
-> testtmcount
|
|
v_val=0x0_02d50ffb; p_val=0x0_02d50ffe
|
|
|
|
64bit is NOT supported! This func is only a placeholder.
|
|
*/
|
|
LOCAL STATUS armv7GenTimerCountGet64
|
|
(
|
|
void * pCookie,
|
|
UINT64 * pCount64
|
|
)
|
|
{
|
|
UINT64 cnt64;
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "armv7GenTimerCountGet64\r\n");
|
|
VXB_ASSERT_NONNULL (pCookie, ERROR);
|
|
VXB_ASSERT_NONNULL (pCount64, ERROR);
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)pCookie;
|
|
|
|
cnt64 = armv7GenTimerGetTimerCnt (pTimer->isVirtual);
|
|
*pCount64 = cnt64;
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO,
|
|
"armv7GenTimerCountGet64: cnt64=%x_%08x\r\n", (UINT32)(cnt64>>32), (UINT32)(cnt64&0xFFFFFFFF));
|
|
return OK;
|
|
}
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerISRSet - set a function to be called on the timer interrupt
|
|
*
|
|
* This function is called to set a function which can be called whenever
|
|
* the timer interrupt occurs.
|
|
*
|
|
* RETURNS: OK or ERROR if the parameter is invalid.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerISRSet
|
|
(
|
|
void * pCookie,
|
|
void (*pFunc)(int),
|
|
int arg
|
|
)
|
|
{
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "armv7GenTimerISRSet\r\n");
|
|
VXB_ASSERT_NONNULL (pCookie, ERROR);
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)pCookie;
|
|
|
|
/* take the spinlock to update pIsrFunc and arg atomically */
|
|
|
|
SPIN_LOCK_ISR_TAKE (&pTimer->spinLock);
|
|
|
|
/* store the interrupt routine and argument information */
|
|
|
|
pTimer->pIsrFunc = pFunc;
|
|
pTimer->arg = arg;
|
|
|
|
/* release the spinlock */
|
|
|
|
SPIN_LOCK_ISR_GIVE (&pTimer->spinLock);
|
|
|
|
return OK;
|
|
}
|
|
|
|
#ifdef _WRS_CONFIG_SMP
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armGenTimerExecOnCpu - execute a function on the specified CPU
|
|
*
|
|
* This routine is called to execute a function on the specified CPU.
|
|
*
|
|
* RETURNS: N/A
|
|
*
|
|
* ERRNO
|
|
*/
|
|
|
|
LOCAL void armGenTimerExecOnCpu
|
|
(
|
|
ULONG * pParams,
|
|
size_t paramSize
|
|
)
|
|
{
|
|
void * func = (void *)pParams[0];
|
|
void * pCookie = (void *)pParams[1];
|
|
UINT32 maxTimerCount;
|
|
|
|
/* Execute the specified function with parameters */
|
|
|
|
if ((STATUS (*)(void *))func == armv7GenTimerDisable)
|
|
{
|
|
(void)armv7GenTimerDisable (pCookie);
|
|
}
|
|
else if ((STATUS (*)(void *, UINT32))func == armv7GenTimerEnable)
|
|
{
|
|
maxTimerCount = (UINT32)pParams[2];
|
|
(void)armv7GenTimerEnable (pCookie, maxTimerCount);
|
|
}
|
|
}
|
|
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerDisable - disable the timer interrupt
|
|
*
|
|
* This function is called to disable the timer interrupt.
|
|
*
|
|
* RETURNS: OK or ERROR if timer is not disabled
|
|
*
|
|
* ERRNO
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerDisable
|
|
(
|
|
void * pCookie
|
|
)
|
|
{
|
|
#ifdef _WRS_CONFIG_SMP
|
|
cpuset_t cpuSet;
|
|
ULONG cpcParam[2];
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "armv7GenTimerDisable\r\n");
|
|
VXB_ASSERT_NONNULL (pCookie, ERROR);
|
|
|
|
/* retrieve the pTimer */
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)pCookie;
|
|
if (pTimer == NULL)
|
|
return ERROR;
|
|
|
|
#ifdef _WRS_CONFIG_SMP
|
|
|
|
/* if not being executed on the boot processor ... */
|
|
|
|
if (vxCpuIndexGet () != 0)
|
|
{
|
|
/* send CPC to boot processor only - CPU 0 */
|
|
|
|
CPUSET_ZERO (cpuSet);
|
|
CPUSET_SET (cpuSet, 0);
|
|
|
|
cpcParam[0] = (ULONG) armv7GenTimerDisable;
|
|
cpcParam[1] = (ULONG) pCookie;
|
|
|
|
/* if not in interrupt context, taskCpuLock */
|
|
|
|
(void) taskCpuLock ();
|
|
|
|
/* execute on boot processor */
|
|
|
|
cpcInvoke (cpuSet,
|
|
(CPC_FUNC) armGenTimerExecOnCpu,
|
|
cpcParam,
|
|
sizeof (cpcParam),
|
|
VX_CPC_SYNC);
|
|
|
|
/* if not in interrupt context, taskCpuUnlock */
|
|
|
|
(void) taskCpuUnlock ();
|
|
|
|
return OK;
|
|
}
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
SPIN_LOCK_ISR_TAKE (&pTimer->spinLock);
|
|
armv7GenTimerDisableInternal (pTimer); /* close interrupt */
|
|
SPIN_LOCK_ISR_GIVE (&pTimer->spinLock);
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerEnable - enable the timer interrupt
|
|
*
|
|
* This function enables the timer interrupt.
|
|
*
|
|
* RETURNS: OK or ERROR if timer is not enabled
|
|
*
|
|
* ERRNO
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerEnable
|
|
(
|
|
void * pCookie,
|
|
UINT32 maxTimerCount
|
|
)
|
|
{
|
|
#ifdef _WRS_CONFIG_SMP
|
|
cpuset_t cpuSet;
|
|
ULONG cpcParam[3];
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
struct vxbTimerFunctionality * pTimerFunc;
|
|
VXB_DEVICE_ID pInst;
|
|
|
|
VXB_ASSERT_NONNULL (pCookie, ERROR);
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO,
|
|
"armv7GenTimerEnable: New TimerCount: %u (0x%x)\r\n", maxTimerCount,maxTimerCount);
|
|
|
|
if ((maxTimerCount > ARMV7_GEN_TIMER_MAX_COUNT) || (maxTimerCount == 0))
|
|
{
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO,
|
|
"armv7GenTimerEnable: This TimerCount is invalid!\r\n");
|
|
return ERROR;
|
|
}
|
|
|
|
/* retrieve the pTimer */
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)pCookie;
|
|
if (pTimer == NULL)
|
|
return ERROR;
|
|
|
|
pTimerFunc = &(pTimer->timerFunc);
|
|
pInst = pTimer->pInst;
|
|
|
|
#ifdef _WRS_CONFIG_SMP
|
|
|
|
/* if not being executed on the boot processor */
|
|
|
|
if (vxCpuIndexGet() != 0)
|
|
{
|
|
/* send CPC to boot processor only - CPU 0 */
|
|
|
|
CPUSET_ZERO (cpuSet);
|
|
CPUSET_SET (cpuSet, 0);
|
|
|
|
cpcParam[0] = (ULONG) armv7GenTimerEnable;
|
|
cpcParam[1] = (ULONG) pCookie;
|
|
cpcParam[2] = (ULONG) maxTimerCount;
|
|
|
|
/* if not in interrupt context, taskCpuLock */
|
|
|
|
(void) taskCpuLock ();
|
|
|
|
/* execute on boot processor */
|
|
|
|
cpcInvoke (cpuSet,
|
|
(CPC_FUNC) armGenTimerExecOnCpu,
|
|
cpcParam,
|
|
sizeof(cpcParam),
|
|
VX_CPC_SYNC);
|
|
|
|
/* if not in interrupt context, taskCpuUnlock */
|
|
|
|
(void) taskCpuUnlock ();
|
|
|
|
return OK;
|
|
}
|
|
#endif /* _WRS_CONFIG_SMP */
|
|
|
|
|
|
SPIN_LOCK_ISR_TAKE (&pTimer->spinLock);
|
|
|
|
/* if the timer is already running, stop it before making adjustments */
|
|
|
|
if (pTimer->isEnabled)
|
|
{
|
|
(void)armv7GenTimerDisableInternal (pTimer);
|
|
}
|
|
|
|
pTimer->maxCount = maxTimerCount;
|
|
|
|
/* recalculate ticksPerSecond */
|
|
|
|
pTimerFunc->ticksPerSecond = pTimerFunc->clkFrequency / pTimer->maxCount;
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "armv7GenTimerEnable New ticksPerSecond = %d.(should be 60)\r\n",
|
|
pTimerFunc->ticksPerSecond);
|
|
|
|
/* update the timer value register with maxTimerCount */
|
|
|
|
armv7GenTimerWriteReg (pTimer->isVirtual, GEN_TIMER_REG_TVAL,
|
|
maxTimerCount);
|
|
|
|
/* set up the timer control register */
|
|
|
|
armv7GenTimerWriteReg (pTimer->isVirtual, GEN_TIMER_REG_CTL,
|
|
GEN_TIMER_CTRL_ENABLE);
|
|
|
|
pTimer->isEnabled = TRUE;
|
|
SPIN_LOCK_ISR_GIVE (&pTimer->spinLock);
|
|
|
|
if (pTimer->isVirtual)
|
|
{
|
|
if (vxbIntEnable (pInst, 0,armv7GenTimerInt, pTimer) != OK)
|
|
{
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_ERR,
|
|
"Interrupt enable failed for virtual timer\n");
|
|
/*SPIN_LOCK_ISR_GIVE (&pTimer->spinLock);*/
|
|
return ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pTimer->secPhyAvail &&
|
|
(vxbIntEnable (pInst, 0,armv7GenTimerInt, pTimer) != OK))
|
|
{
|
|
pTimer->secPhyAvail = FALSE;
|
|
}
|
|
if (pTimer->nonSecPhyAvail &&
|
|
(vxbIntEnable (pInst, 0,armv7GenTimerInt, pTimer) != OK))
|
|
{
|
|
pTimer->nonSecPhyAvail = FALSE;
|
|
}
|
|
if (!pTimer->secPhyAvail && !pTimer->nonSecPhyAvail)
|
|
{
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_ERR,
|
|
"Interrupt enable failed for physical timer\n");
|
|
/*SPIN_LOCK_ISR_GIVE (&pTimer->spinLock);*/
|
|
return ERROR;
|
|
}
|
|
}
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "armv7GenTimerEnable OK\r\n");
|
|
return OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerInt - ISR for the ARM Generic Timer
|
|
*
|
|
* This routine handles the ARM Generic Timer interrupt.
|
|
*
|
|
* RETURNS : N/A
|
|
*/
|
|
|
|
LOCAL void armv7GenTimerInt
|
|
(
|
|
ARMV7_GEN_TIMER_DATA * pTimer
|
|
)
|
|
{
|
|
UINT32 ctl;
|
|
|
|
|
|
ctl = armv7GenTimerReadReg (pTimer->isVirtual, GEN_TIMER_REG_CTL);
|
|
if ((ctl & GEN_TIMER_CTRL_ISTATUS) == 0)
|
|
{
|
|
uartf("\033[34m%s,%d: ctl=0x%x. pTimer->maxCount=0x%x. No TimerInt. Return directly!\033[m\r\n",__FILE__,__LINE__,ctl, pTimer->maxCount);
|
|
return;
|
|
}
|
|
|
|
/* auto reload */
|
|
|
|
if ((pTimer->timerFunc.features & VXB_TIMER_AUTO_RELOAD) != 0)
|
|
{
|
|
armv7GenTimerWriteReg (pTimer->isVirtual, GEN_TIMER_REG_TVAL,
|
|
pTimer->maxCount);
|
|
}
|
|
else
|
|
{
|
|
armv7GenTimerWriteReg (pTimer->isVirtual, GEN_TIMER_REG_CTL,
|
|
GEN_TIMER_CTRL_IMASK);
|
|
}
|
|
|
|
/* call the ISR hooked by armv7GenTimerISRSet() */
|
|
|
|
if (pTimer->pIsrFunc != NULL)
|
|
pTimer->pIsrFunc (pTimer->arg);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* armv7GenTimerAttach - attach arm generic timer device
|
|
*
|
|
* This is the arm generic timer initialization routine.
|
|
*
|
|
* RETURNS: OK, or ERROR if initialization failed.
|
|
*
|
|
* ERRNO: N/A
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerAttach
|
|
(
|
|
VXB_DEVICE_ID pDev
|
|
)
|
|
{
|
|
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
struct vxbTimerFunctionality * pTimerFunc;
|
|
HCF_DEVICE * pHcf = NULL;
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "Enter armv7GenTimerAttach\r\n");
|
|
|
|
/* check for valid parameter */
|
|
|
|
VXB_ASSERT_NONNULL (pDev, ERROR);
|
|
|
|
/* get the HCF_DEVICE address */
|
|
|
|
pHcf = hcfDeviceGet(pDev);
|
|
if (pHcf == NULL)
|
|
{
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_ERR,
|
|
"There is no HCF for this device.\r\n");
|
|
return ERROR;
|
|
}
|
|
|
|
/* allocate the memory for the timer structure */
|
|
|
|
pTimer = (ARMV7_GEN_TIMER_DATA *)hwMemAlloc (sizeof(ARMV7_GEN_TIMER_DATA));
|
|
if (pTimer == NULL)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
pArmv7GenTimer = pTimer;
|
|
|
|
/*
|
|
* Use virtual timer by default, but if it's not available,
|
|
* use physical timer.
|
|
*/
|
|
|
|
|
|
pTimer->secPhyAvail = TRUE;
|
|
pTimer->isVirtual = FALSE;
|
|
pTimer->nonSecPhyAvail = FALSE;
|
|
|
|
if (pTimer->secPhyAvail &&
|
|
(vxbIntConnect (pDev, 0, /*pTimer->intRes[GEN_TIMER_SECURE_PHY_PPI],*/
|
|
armv7GenTimerInt, pTimer) != OK))
|
|
{
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_ERR,
|
|
"Secure physical timer is not available\r\n");
|
|
pTimer->secPhyAvail = FALSE;
|
|
|
|
}
|
|
|
|
/* locate the timer functionality data structure */
|
|
|
|
pTimerFunc = &(pTimer->timerFunc);
|
|
|
|
if (devResourceGet(pHcf,"minClkRate",HCF_RES_INT,
|
|
(void *)&pTimerFunc->minFrequency) != OK)
|
|
{
|
|
/*default value. */
|
|
pTimerFunc->minFrequency = ARMV7_GEN_TIMER_DEFAULT_MIN_FREQ;
|
|
}
|
|
|
|
if (devResourceGet(pHcf,"maxClkRate",HCF_RES_INT,
|
|
(void *)&pTimerFunc->maxFrequency) != OK)
|
|
{
|
|
/*default value*/
|
|
pTimerFunc->maxFrequency = ARMV7_GEN_TIMER_DEFAULT_MAX_FREQ;
|
|
}
|
|
|
|
pTimerFunc->clkFrequency = __inline__GetCntFreq();
|
|
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO,
|
|
"Clock Frequency: %d\r\n", pTimerFunc->clkFrequency);
|
|
|
|
if ((pTimerFunc->clkFrequency < ARMV7_GEN_TIMER_MIN_CLK_FREQ) ||
|
|
(pTimerFunc->clkFrequency > ARMV7_GEN_TIMER_MAX_CLK_FREQ))
|
|
{
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_ERR,
|
|
"clkFrequency wrong for ARM generic timer\r\n");
|
|
goto errOut;
|
|
}
|
|
|
|
/* store the feature provided by the timer */
|
|
|
|
pTimerFunc->features = VXB_TIMER_CAN_INTERRUPT |
|
|
VXB_TIMER_INTERMEDIATE_COUNT |
|
|
VXB_TIMER_SIZE_32 |
|
|
VXB_TIMER_SIZE_64 |
|
|
VXB_TIMER_AUTO_RELOAD ;
|
|
|
|
/* set the default ticks per second */
|
|
|
|
pTimerFunc->ticksPerSecond = ARMV7_GEN_TIMER_DEFAULT_TPS;
|
|
|
|
/*
|
|
* Requires to initialize maxCount field for timestamp timer.
|
|
* It will be used as a return value for sysTimestampPeriod().
|
|
*/
|
|
|
|
pTimer->maxCount = pTimerFunc->clkFrequency/ARMV7_GEN_TIMER_DEFAULT_TPS;
|
|
|
|
pTimerFunc->rolloverPeriod = pTimer->maxCount / pTimerFunc->clkFrequency;
|
|
|
|
(void)strncpy (pTimerFunc->timerName,
|
|
ARMV7_GEN_TIMER_NAME, MAX_DRV_NAME_LEN);
|
|
|
|
/* populate the function pointers */
|
|
|
|
pTimerFunc->timerAllocate = armv7GenTimerAllocate;
|
|
pTimerFunc->timerRelease = armv7GenTimerRelease;
|
|
pTimerFunc->timerRolloverGet = armv7GenTimerRolloverGet;
|
|
pTimerFunc->timerCountGet = armv7GenTimerCountGet;
|
|
pTimerFunc->timerCountGet64 = armv7GenTimerCountGet64;
|
|
pTimerFunc->timerDisable = armv7GenTimerDisable;
|
|
pTimerFunc->timerEnable = armv7GenTimerEnable;
|
|
pTimerFunc->timerISRSet = armv7GenTimerISRSet;
|
|
|
|
/* initialize the spinlock */
|
|
|
|
SPIN_LOCK_ISR_INIT (&pTimer->spinLock, 0);
|
|
|
|
/* publish methods */
|
|
|
|
pDev->pMethods = davinciTimerDrv_methods;
|
|
pDev->pDrvCtrl = pTimer;
|
|
GEN_TIMER_DBG (GEN_TIMER_DBG_INFO, "armv7GenTimerAttach OK\r\n");
|
|
|
|
return OK;
|
|
|
|
errOut:
|
|
|
|
hwMemFree ((char * )pTimer);
|
|
return ERROR;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* armv7GenTimerFuncGet - method to retrieve the timer functionality
|
|
*
|
|
* This function is the driver method used to retrieve the timer functionality.
|
|
*
|
|
* RETURNS: OK or ERROR if functionality is not retrieved.
|
|
*
|
|
* ERRNO
|
|
*/
|
|
|
|
LOCAL STATUS armv7GenTimerFuncGet
|
|
(
|
|
VXB_DEVICE_ID pInst,
|
|
struct vxbTimerFunctionality** pTimerFunc,
|
|
int timerNo
|
|
)
|
|
{
|
|
ARMV7_GEN_TIMER_DATA * pTimerData;
|
|
|
|
/* since the device supports only a single timer functionality */
|
|
|
|
if ( timerNo != 0)
|
|
return ERROR;
|
|
|
|
/* check the validity of parameters */
|
|
|
|
if ( (pInst == NULL) || (pInst->pDrvCtrl == NULL) || (pTimerFunc == NULL) )
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
/* retrieve the timer specific data */
|
|
|
|
pTimerData = (ARMV7_GEN_TIMER_DATA *)(pInst->pDrvCtrl);
|
|
|
|
/* update the timer functionality pointer */
|
|
|
|
*pTimerFunc = &(pTimerData->timerFunc);
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
/* delay 1us */
|
|
void armV7GenUsDelay
|
|
(
|
|
int delay /* length of time in US to delay */
|
|
)
|
|
{
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
struct vxbTimerFunctionality * pTimerFunc;
|
|
|
|
volatile register UINT32 oldVal;
|
|
volatile register UINT32 newVal;
|
|
volatile register UINT32 decElapsed = 0;
|
|
register UINT32 totalDelta;
|
|
UINT32 maxTickCount;
|
|
/*UINT32 minTickCount = 0;*/
|
|
UINT32 ticksPerUs = 0;
|
|
|
|
int loopcount = 0;
|
|
|
|
UINT64 cnt64;
|
|
|
|
if(delay == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pTimer = pArmv7GenTimer;
|
|
|
|
if(pTimer == NULL)
|
|
{
|
|
uartf("No valid armv7 gen timer!\r\n");
|
|
return;
|
|
}
|
|
pTimerFunc = &(pTimer->timerFunc);
|
|
|
|
ticksPerUs = pTimerFunc->clkFrequency / 1000000;
|
|
if(ticksPerUs != 50)
|
|
{
|
|
uartf("ticksPerUs-%d should be 50 for this board, please check it!\r\n", ticksPerUs);
|
|
}
|
|
|
|
maxTickCount = pTimer->maxCount;
|
|
totalDelta = delay * (ticksPerUs); /* total clock ticks for long delay */
|
|
|
|
cnt64 = armv7GenTimerGetTimerCnt (pTimer->isVirtual);
|
|
oldVal = (UINT32)(cnt64 % ((UINT32)ARMV7_GEN_TIMER_MAX_COUNT + 1));
|
|
|
|
while (decElapsed < totalDelta)
|
|
{
|
|
loopcount++;
|
|
|
|
cnt64 = armv7GenTimerGetTimerCnt (pTimer->isVirtual);
|
|
newVal = (UINT32)(cnt64 % ((UINT32)ARMV7_GEN_TIMER_MAX_COUNT + 1));
|
|
|
|
if(newVal == oldVal)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* no rollover. count down... */
|
|
|
|
if (newVal < oldVal)
|
|
{
|
|
decElapsed += (oldVal - newVal);
|
|
}
|
|
/* rollover */
|
|
else
|
|
{
|
|
decElapsed += ((maxTickCount - newVal) + oldVal);
|
|
}
|
|
|
|
oldVal = newVal;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG_GEN_TIMER
|
|
void testtm(void)
|
|
{
|
|
ARMV7_GEN_TIMER_DATA * pTimer;
|
|
struct vxbTimerFunctionality * pTimerFunc;
|
|
|
|
volatile register UINT32 oldVal;
|
|
UINT64 cnt64;
|
|
|
|
pTimer = pArmv7GenTimer;
|
|
|
|
if(pTimer == NULL)
|
|
{
|
|
printf("No valid armv7 gen timer!\r\n");
|
|
return;
|
|
}
|
|
pTimerFunc = &(pTimer->timerFunc);
|
|
|
|
printf("pTimer->isVirtual=%d\r\n", pTimer->isVirtual);
|
|
|
|
cnt64 = armv7GenTimerGetTimerCnt (pTimer->isVirtual);
|
|
oldVal = (UINT32)(cnt64 % ((UINT32)ARMV7_GEN_TIMER_MAX_COUNT + 1));
|
|
|
|
printf("clkFreq=%d. oldVal = %d;\r\n",
|
|
pTimerFunc->clkFrequency, oldVal);
|
|
|
|
printf("cnt64=%lld", cnt64);
|
|
|
|
}
|
|
|
|
|
|
UINT64 testtmcount(void)
|
|
{
|
|
UINT64 v_val = 0;
|
|
UINT64 p_val = 0;
|
|
UINT32 reg32;
|
|
BOOL isVirtual = TRUE;
|
|
|
|
WRS_ASM ("ISB");
|
|
|
|
v_val = __inline__GetVirtTimerCnt ();
|
|
p_val = __inline__GetPhyTimerCnt ();
|
|
|
|
printf("v_val=0x%x_%08x; p_val=0x%x_%08x \r\n",
|
|
(UINT32)(v_val>>32),(UINT32)(v_val&0XFFFFFFFF),
|
|
(UINT32)(p_val>>32),(UINT32)(p_val&0XFFFFFFFF));
|
|
|
|
printf("----------- Virtual REGs ------------------- \r\n");
|
|
reg32 = armv7GenTimerReadReg(isVirtual, GEN_TIMER_REG_CTL);
|
|
printf("CTL = 0x%08x \r\n", reg32);
|
|
reg32 = armv7GenTimerReadReg(isVirtual, GEN_TIMER_REG_TVAL);
|
|
printf("TVAL = 0x%08x \r\n", reg32);
|
|
printf("--------------------------------------------- \r\n\n");
|
|
|
|
printf("----------- Phy REGs ------------------- \r\n");
|
|
isVirtual = FALSE;
|
|
reg32 = armv7GenTimerReadReg(isVirtual, GEN_TIMER_REG_CTL);
|
|
printf("CTL = 0x%08x \r\n", reg32);
|
|
reg32 = armv7GenTimerReadReg(isVirtual, GEN_TIMER_REG_TVAL);
|
|
printf("TVAL = 0x%08x \r\n", reg32);
|
|
printf("--------------------------------------------- \r\n\n");
|
|
return v_val;
|
|
}
|
|
#endif
|
|
|
|
|