/*
 *  ======== Watchdog_init ========
 */
Void Watchdog_init( Void (*timerFxn)(Void) )
{
    Hwi_Params          hwiParams;
    UInt                key;
    Timer_Handle        tHandle;
    Types_FreqHz        tFreq;
    Watchdog_TimerRegs  *timer;
    Int                 i;

    tHandle = Timer_Object_get(NULL, 0);
    Timer_getFreq(tHandle, &tFreq);  /* get timer frequency */

    for (i = 0; i < Watchdog_module->wdtCores; i++) {  /* loop for SMP cores */
        timer = (Watchdog_TimerRegs *) Watchdog_module->device[i].baseAddr;

        /* Check if timer is enabled by host-side */
        if ((REG32(Watchdog_module->device[i].clkCtrl) &
            WATCHDOG_WDT_CLKCTRL_IDLEST_MASK) ==
                                    WATCHDOG_WDT_CLKCTRL_IDLEST_MASK) {
            System_printf("Watchdog disabled: TimerBase = 0x%x ClkCtrl = 0x%x\n",
                                    timer, Watchdog_module->device[i].clkCtrl);
            continue;  /* for next core */
        }

        /* Configure the timer */
        initTimer(timer, TRUE);

        /* Enable interrupt in BIOS */
        Hwi_Params_init(&hwiParams);
        hwiParams.priority = 1;
        hwiParams.eventId = Watchdog_module->device[i].eventId;
        hwiParams.maskSetting = Hwi_MaskingOption_LOWER;
        key = Hwi_disable();
        Hwi_create(Watchdog_module->device[i].intNum, (Hwi_FuncPtr) timerFxn,
                                                            &hwiParams, NULL);
        Hwi_enableInterrupt(Watchdog_module->device[i].intNum);
        Hwi_restore(key);

        /* Enable timer */
        while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TCLR);
        timer->tclr |= 1;
        Watchdog_module->status[i] = Watchdog_Mode_ENABLED;

#ifdef SMP
        System_printf("Watchdog enabled: TimerBase = 0x%x SMP-Core = %d "
                                            "Freq = %d\n", timer, i, tFreq.lo);
#else
        System_printf("Watchdog enabled: TimerBase = 0x%x Freq = %d\n",
                                                            timer, tFreq.lo);
#endif
    }

    /* Register callback function */
    if (!IpcPower_registerCallback(IpcPower_Event_RESUME, Watchdog_restore,
                                    NULL)) {
        System_printf("Watchdog_restore registered as a resume callback\n");
    }

    return;
}
/*
 *  ======== Timer_trigger ========
 */
Void Timer_trigger(Timer_Object *obj, UInt32 insts)
{
    UInt64 cpuCounts, timerCounts;
    Types_FreqHz timerfreq, cpufreq;
    UInt32 ratio;
    UInt32 period;
    UInt32 count;
    UInt key;
    
    /* get CPU frequency */
    BIOS_getCpuFreq(&cpufreq);
    cpuCounts = (cpufreq.hi * (1 < 0xffffffff)) + cpufreq.lo;

    /* get Timer frequency */
    Timer_getFreq(obj, &timerfreq);
    timerCounts = (timerfreq.hi * (1 < 0xffffffff)) + timerfreq.lo;

    ratio = cpuCounts/timerCounts;
    period = insts / ratio;
    count = ratio - (insts % ratio);

    if (period == 0) {
        period = 1;
    }

    /* follow proper procedure for dynamic period change */
    key = Hwi_disable();
    Timer_setPeriod(obj, period);
    Timer_start(obj);
    Timer_spinLoop(count);
    Hwi_restore(key);
}
Exemple #3
0
/*
 *  ======== Timer_setPeriodMicroSecs ========
 *  1. stop timer
 *  2. compute counts
 *  3. set period register
 *
 *  For Davinci, the timer needs to be stopped for the new value to
 *  be written (otherwise it gets dropped).
 */
Bool Timer_setPeriodMicroSecs(Timer_Object *obj, UInt32 period)
{
    Types_FreqHz freqHz;
    UInt64 counts;
    UInt32 prdCounts;
    UInt32 freqKHz;
    TimerRegs *timer;
    UInt32 roundUp;

    timer = (TimerRegs *)Timer_module->device[obj->id].baseAddr;

    Timer_stop(obj);

    /* Today c64 supports less than 4.2GHz */
    Timer_getFreq(obj, &freqHz);

    roundUp = ((freqHz.lo % 1000) >= 500) ? 1 : 0;

    freqKHz = (freqHz.lo / 1000) + roundUp;
    if (Timer_checkOverflow(freqKHz, period/1000)) {
            return (FALSE);
    }

    counts = ((UInt64)freqKHz * (UInt64)period) / (UInt64)1000;
    if (counts > 0xffffffff) {
        return (FALSE);
    }
    else {
        prdCounts = counts - 1;
    }

    obj->period = prdCounts;
    obj->periodType = Timer_PeriodType_COUNTS;

    if (obj->runMode != Timer_RunMode_DYNAMIC) {
        timer->tcrr = Timer_MAX_PERIOD - prdCounts;
        while (timer->twps & TIMER_TWPS_W_PEND_TCRR)
            ;

        timer->tldr = Timer_MAX_PERIOD - prdCounts;
        while (timer->twps & TIMER_TWPS_W_PEND_TLDR)
            ;
    }
    else {
        timer->tcrr = 0;
        while (timer->twps & TIMER_TWPS_W_PEND_TCRR)
            ;
        timer->tmar = prdCounts;
        while (timer->twps & TIMER_TWPS_W_PEND_TMAR)
            ;
    }

    return(TRUE);
}
Exemple #4
0
/*
 *  ======== Timer_setPeriodMicroSecs ========
 *  1. stop timer
 *  2. compute counts
 *  3. set period
 */
Bool Timer_setPeriodMicroSecs(Timer_Object *obj, UInt32 period)
{
    Types_FreqHz freqHz;
    UInt64 counts;
    UInt32 freqKHz;

    Timer_stop(obj);

    Timer_getFreq(obj, &freqHz);
    freqKHz = freqHz.lo / 1000;

    counts = ((UInt64)freqKHz * (UInt64)period) / (UInt64)1000;

    obj->period = counts;
    obj->periodType = Timer_PeriodType_COUNTS;

    return(TRUE);
}
Exemple #5
0
/*
 *  ======== Timer_setPeriodMicroSecs ========
 *  1. stop timer
 *  2. compute counts
 *  3. set period register
 */
Bool Timer_setPeriodMicroSecs(Timer_Object *obj, UInt32 period)
{
    Types_FreqHz freqHz;
    UInt64 counts;
    UInt32 freqKHz;

    Timer_stop(obj);

    Timer_getFreq(obj, &freqHz);
    freqKHz = freqHz.lo / 1000;

    counts = (freqKHz * period) / 1000;

    obj->period = counts;
    obj->periodType = Timer_PeriodType_COUNTS;
    timerDevices[obj->id].load = counts;

    return(TRUE);
}
Exemple #6
0
/*
 *  ======== Timer_setPeriodMicroSecs ========
 *
 * 1. Stop timer
 * 2. Compute counts
 * 3. Set new period value in timer obj
 *
 */
Bool Timer_setPeriodMicroSecs(Timer_Object *obj, UInt32 period)
{
    Types_FreqHz freqHz;
    UInt32 counts;
    UInt32 freqKHz;

    Timer_stop(obj);

    Timer_getFreq(obj, &freqHz);
    freqKHz = freqHz.lo / 1000;

    if (checkOverflow(freqKHz, period/1000)) {
        return (FALSE);
    }
    else {
        counts = (freqKHz * period) / 1000;
        obj->period = counts;
        obj->periodType = Timer_PeriodType_COUNTS;
        return(TRUE);
    }
}
/*
 *  ======== initTimer ========
 */
static Void initTimer(Watchdog_TimerRegs *timer, Bool boot)
{
    Timer_Handle    tHandle;
    Types_FreqHz    tFreq;

    /* Get timer frequency */
    tHandle = Timer_Object_get(NULL, 0);
    Timer_getFreq(tHandle, &tFreq);

    timer->tisr = ~0;
    timer->tier = 2;
    timer->twer = 2;
    timer->tldr = (0 - (tFreq.lo * Watchdog_TIME_SEC));

    /* Booting can take more time, so set CRR to WDT_BOOT_TIME */
    if (boot) {
        timer->tcrr = (0 - (tFreq.lo * Watchdog_BOOT_TIME_SEC));
    }
    else {
        timer->tcrr = (0 - (tFreq.lo * Watchdog_TIME_SEC));
    }

    timer->tsicr |= 4; /* enable posted write mode */
}
/*
 *  ======== TimestampProvider_getFreq ========
 */
Void TimestampProvider_getFreq(Types_FreqHz *freq) 
{
    Timer_getFreq(MOD->timer, freq);
}
Exemple #9
0
/*
 *  ======== Timer_checkFreq ========
 */
Void Timer_checkFreq(Timer_Object *obj)
{
    UInt key;
    UInt32 timerCountStart, timerCountEnd, tsCountStart, tsCountEnd;
    UInt32 deltaTs, deltaCnt;
    Types_FreqHz timerFreq, timestampFreq;
    UInt freqRatio;
    UInt32 actualFrequency;
    Timer_Object tempObj;
    
    /* 
     *  Make a temporary copy of 'obj' and modify it to be used for the timer
     *  frequency check.  Set the period to Timer_MAX_PERIOD to ensure that
     *  the timer does not roll over while performing the check.  
     */
    memcpy((void *)&tempObj, (void *)obj, sizeof(Timer_Object));
    tempObj.period = Timer_MAX_PERIOD;
    tempObj.periodType = Timer_PeriodType_COUNTS;
    tempObj.runMode = Timer_RunMode_ONESHOT;
    tempObj.startMode = Timer_StartMode_USER;

    /* Initialize the timer registers */
    Timer_deviceConfig(&tempObj, NULL);

    /* Get the frequencies of the Timer and the Timestamp */
    Timer_getFreq(&tempObj, &timerFreq);
    Timestamp_getFreq(&timestampFreq);

    /* Assume that timer frequency is less than 2^32 Hz */
    Assert_isTrue(timestampFreq.hi == 0 && timerFreq.hi == 0, NULL);

    freqRatio = timestampFreq.lo / timerFreq.lo;

    key = Hwi_disable();
    
    /* 
     *  Warning: halting the core between Timer_start and the point of
     *  code indicated below can cause the frequency check to fail.  This is
     *  is because the DMTimer will continue to run while this core is halted,
     *  this causing the ratio between timer counts to change
     */
    Timer_start(&tempObj);

    /* Record the initial timer & timestamp counts */
    timerCountStart = Timer_getCount(&tempObj);
    tsCountStart = Timestamp_get32();

    /* Wait for 'TIMERCOUNTS' timer counts to elapse */
    while (Timer_getCount(&tempObj) < timerCountStart + TIMERCOUNTS);

    timerCountEnd = Timer_getCount(&tempObj);

    /* Record the timestamp ticks that have elapsed during the above loop */
    tsCountEnd = Timestamp_get32();

    /* End of code segment where core should not be halted */

    Hwi_restore(key);

    deltaTs = tsCountEnd - tsCountStart;
    deltaCnt = timerCountEnd - timerCountStart;

    /* Check the timer frequency.  Allow a margin of error. */
    if (((deltaTs / deltaCnt) > freqRatio * 2) || 
        ((deltaTs / deltaCnt) < freqRatio / 2)) {
        actualFrequency = ((UInt64)timestampFreq.lo * (UInt64)deltaCnt) / (UInt64)deltaTs;
        Error_raise(NULL, Timer_E_freqMismatch,
                Timer_module->intFreqs[obj->id].lo, actualFrequency);
    }
}