Path: blob/main/sys/contrib/ncsw/Peripherals/FM/Rtc/fm_rtc.c
48417 views
/*1* Copyright 2008-2012 Freescale Semiconductor Inc.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions are met:5* * Redistributions of source code must retain the above copyright6* notice, this list of conditions and the following disclaimer.7* * Redistributions in binary form must reproduce the above copyright8* notice, this list of conditions and the following disclaimer in the9* documentation and/or other materials provided with the distribution.10* * Neither the name of Freescale Semiconductor nor the11* names of its contributors may be used to endorse or promote products12* derived from this software without specific prior written permission.13*14*15* ALTERNATIVELY, this software may be distributed under the terms of the16* GNU General Public License ("GPL") as published by the Free Software17* Foundation, either version 2 of that License or (at your option) any18* later version.19*20* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY21* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED22* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE23* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY24* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES25* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;26* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND27* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT28* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/313233/******************************************************************************34@File fm_rtc.c3536@Description FM RTC driver implementation.3738@Cautions None39*//***************************************************************************/40#include <linux/math64.h>41#include "error_ext.h"42#include "debug_ext.h"43#include "string_ext.h"44#include "part_ext.h"45#include "xx_ext.h"46#include "ncsw_ext.h"4748#include "fm_rtc.h"49#include "fm_common.h"50515253/*****************************************************************************/54static t_Error CheckInitParameters(t_FmRtc *p_Rtc)55{56struct rtc_cfg *p_RtcDriverParam = p_Rtc->p_RtcDriverParam;57int i;5859if ((p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL) &&60(p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_SYSTEM) &&61(p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR))62RETURN_ERROR(MAJOR, E_INVALID_CLOCK, ("Source clock undefined"));6364if (p_Rtc->outputClockDivisor == 0)65{66RETURN_ERROR(MAJOR, E_INVALID_VALUE,67("Divisor for output clock (should be positive)"));68}6970for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++)71{72if ((p_RtcDriverParam->alarm_polarity[i] != E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW) &&73(p_RtcDriverParam->alarm_polarity[i] != E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH))74{75RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm %d signal polarity", i));76}77}78for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++)79{80if ((p_RtcDriverParam->trigger_polarity[i] != E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE) &&81(p_RtcDriverParam->trigger_polarity[i] != E_FMAN_RTC_TRIGGER_ON_RISING_EDGE))82{83RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Trigger %d signal polarity", i));84}85}8687return E_OK;88}8990/*****************************************************************************/91static void RtcExceptions(t_Handle h_FmRtc)92{93t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;94struct rtc_regs *p_MemMap;95register uint32_t events;9697ASSERT_COND(p_Rtc);98p_MemMap = p_Rtc->p_MemMap;99100events = fman_rtc_check_and_clear_event(p_MemMap);101if (events & FMAN_RTC_TMR_TEVENT_ALM1)102{103if (p_Rtc->alarmParams[0].clearOnExpiration)104{105fman_rtc_set_timer_alarm_l(p_MemMap, 0, 0);106fman_rtc_disable_interupt(p_MemMap, FMAN_RTC_TMR_TEVENT_ALM1);107}108ASSERT_COND(p_Rtc->alarmParams[0].f_AlarmCallback);109p_Rtc->alarmParams[0].f_AlarmCallback(p_Rtc->h_App, 0);110}111if (events & FMAN_RTC_TMR_TEVENT_ALM2)112{113if (p_Rtc->alarmParams[1].clearOnExpiration)114{115fman_rtc_set_timer_alarm_l(p_MemMap, 1, 0);116fman_rtc_disable_interupt(p_MemMap, FMAN_RTC_TMR_TEVENT_ALM2);117}118ASSERT_COND(p_Rtc->alarmParams[1].f_AlarmCallback);119p_Rtc->alarmParams[1].f_AlarmCallback(p_Rtc->h_App, 1);120}121if (events & FMAN_RTC_TMR_TEVENT_PP1)122{123ASSERT_COND(p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback);124p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback(p_Rtc->h_App, 0);125}126if (events & FMAN_RTC_TMR_TEVENT_PP2)127{128ASSERT_COND(p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback);129p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback(p_Rtc->h_App, 1);130}131if (events & FMAN_RTC_TMR_TEVENT_ETS1)132{133ASSERT_COND(p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback);134p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback(p_Rtc->h_App, 0);135}136if (events & FMAN_RTC_TMR_TEVENT_ETS2)137{138ASSERT_COND(p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback);139p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback(p_Rtc->h_App, 1);140}141}142143144/*****************************************************************************/145t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam)146{147t_FmRtc *p_Rtc;148149SANITY_CHECK_RETURN_VALUE(p_FmRtcParam, E_NULL_POINTER, NULL);150151/* Allocate memory for the FM RTC driver parameters */152p_Rtc = (t_FmRtc *)XX_Malloc(sizeof(t_FmRtc));153if (!p_Rtc)154{155REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver structure"));156return NULL;157}158159memset(p_Rtc, 0, sizeof(t_FmRtc));160161/* Allocate memory for the FM RTC driver parameters */162p_Rtc->p_RtcDriverParam = (struct rtc_cfg *)XX_Malloc(sizeof(struct rtc_cfg));163if (!p_Rtc->p_RtcDriverParam)164{165REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver parameters"));166XX_Free(p_Rtc);167return NULL;168}169170memset(p_Rtc->p_RtcDriverParam, 0, sizeof(struct rtc_cfg));171172/* Store RTC configuration parameters */173p_Rtc->h_Fm = p_FmRtcParam->h_Fm;174175/* Set default RTC configuration parameters */176fman_rtc_defconfig(p_Rtc->p_RtcDriverParam);177178p_Rtc->outputClockDivisor = DEFAULT_OUTPUT_CLOCK_DIVISOR;179p_Rtc->p_RtcDriverParam->bypass = DEFAULT_BYPASS;180p_Rtc->clockPeriodNanoSec = DEFAULT_CLOCK_PERIOD; /* 1 usec */181182183/* Store RTC parameters in the RTC control structure */184p_Rtc->p_MemMap = (struct rtc_regs *)UINT_TO_PTR(p_FmRtcParam->baseAddress);185p_Rtc->h_App = p_FmRtcParam->h_App;186187return p_Rtc;188}189190/*****************************************************************************/191t_Error FM_RTC_Init(t_Handle h_FmRtc)192{193t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;194struct rtc_cfg *p_RtcDriverParam;195struct rtc_regs *p_MemMap;196uint32_t freqCompensation = 0;197uint64_t tmpDouble;198bool init_freq_comp = FALSE;199200p_RtcDriverParam = p_Rtc->p_RtcDriverParam;201p_MemMap = p_Rtc->p_MemMap;202203if (CheckInitParameters(p_Rtc)!=E_OK)204RETURN_ERROR(MAJOR, E_CONFLICT,205("Init Parameters are not Valid"));206207/* TODO check that no timestamping MACs are working in this stage. */208209/* find source clock frequency in Mhz */210if (p_Rtc->p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_SYSTEM)211p_Rtc->srcClkFreqMhz = p_Rtc->p_RtcDriverParam->ext_src_clk_freq;212else213p_Rtc->srcClkFreqMhz = (uint32_t)(FmGetMacClockFreq(p_Rtc->h_Fm));214215/* if timer in Master mode Initialize TMR_CTRL */216/* We want the counter (TMR_CNT) to count in nano-seconds */217if (!p_RtcDriverParam->timer_slave_mode && p_Rtc->p_RtcDriverParam->bypass)218p_Rtc->clockPeriodNanoSec = (1000 / p_Rtc->srcClkFreqMhz);219else220{221/* Initialize TMR_ADD with the initial frequency compensation value:222freqCompensation = (2^32 / frequency ratio) */223/* frequency ratio = sorce clock/rtc clock =224* (p_Rtc->srcClkFreqMhz*1000000))/ 1/(p_Rtc->clockPeriodNanoSec * 1000000000) */225init_freq_comp = TRUE;226freqCompensation = (uint32_t)DIV_CEIL(ACCUMULATOR_OVERFLOW * 1000,227p_Rtc->clockPeriodNanoSec * p_Rtc->srcClkFreqMhz);228}229230/* check the legality of the relation between source and destination clocks */231/* should be larger than 1.0001 */232tmpDouble = 10000 * (uint64_t)p_Rtc->clockPeriodNanoSec * (uint64_t)p_Rtc->srcClkFreqMhz;233if ((tmpDouble) <= 10001)234RETURN_ERROR(MAJOR, E_CONFLICT,235("Invalid relation between source and destination clocks. Should be larger than 1.0001"));236237fman_rtc_init(p_RtcDriverParam,238p_MemMap,239FM_RTC_NUM_OF_ALARMS,240FM_RTC_NUM_OF_PERIODIC_PULSES,241FM_RTC_NUM_OF_EXT_TRIGGERS,242init_freq_comp,243freqCompensation,244p_Rtc->outputClockDivisor);245246/* Register the FM RTC interrupt */247FmRegisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL, RtcExceptions , p_Rtc);248249/* Free parameters structures */250XX_Free(p_Rtc->p_RtcDriverParam);251p_Rtc->p_RtcDriverParam = NULL;252253return E_OK;254}255256/*****************************************************************************/257t_Error FM_RTC_Free(t_Handle h_FmRtc)258{259t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;260261SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);262263if (p_Rtc->p_RtcDriverParam)264{265XX_Free(p_Rtc->p_RtcDriverParam);266}267else268{269FM_RTC_Disable(h_FmRtc);270}271272/* Unregister FM RTC interrupt */273FmUnregisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL);274XX_Free(p_Rtc);275276return E_OK;277}278279/*****************************************************************************/280t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc,281e_FmSrcClk srcClk,282uint32_t freqInMhz)283{284t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;285286SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);287SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);288289p_Rtc->p_RtcDriverParam->src_clk = (enum fman_src_clock)srcClk;290if (srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM)291p_Rtc->p_RtcDriverParam->ext_src_clk_freq = freqInMhz;292293return E_OK;294}295296/*****************************************************************************/297t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period)298{299t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;300301SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);302SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);303304p_Rtc->clockPeriodNanoSec = period;305306return E_OK;307}308309/*****************************************************************************/310t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled)311{312t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;313314SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);315SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);316317p_Rtc->p_RtcDriverParam->bypass = enabled;318319return E_OK;320}321322/*****************************************************************************/323t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted)324{325t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;326327SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);328SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);329330p_Rtc->p_RtcDriverParam->invert_input_clk_phase = inverted;331332return E_OK;333}334335/*****************************************************************************/336t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted)337{338t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;339340SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);341SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);342343p_Rtc->p_RtcDriverParam->invert_output_clk_phase = inverted;344345return E_OK;346}347348/*****************************************************************************/349t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor)350{351t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;352353SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);354SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);355356p_Rtc->outputClockDivisor = divisor;357358return E_OK;359}360361/*****************************************************************************/362t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable)363{364t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;365366SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);367SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);368369p_Rtc->p_RtcDriverParam->pulse_realign = enable;370371return E_OK;372}373374/*****************************************************************************/375t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc,376uint8_t alarmId,377e_FmRtcAlarmPolarity alarmPolarity)378{379t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;380381SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);382SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);383384if (alarmId >= FM_RTC_NUM_OF_ALARMS)385RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID"));386387p_Rtc->p_RtcDriverParam->alarm_polarity[alarmId] =388(enum fman_rtc_alarm_polarity)alarmPolarity;389390return E_OK;391}392393/*****************************************************************************/394t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc,395uint8_t triggerId,396e_FmRtcTriggerPolarity triggerPolarity)397{398t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;399400SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);401SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);402403if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)404{405RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID"));406}407408p_Rtc->p_RtcDriverParam->trigger_polarity[triggerId] =409(enum fman_rtc_trigger_polarity)triggerPolarity;410411return E_OK;412}413414/*****************************************************************************/415t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock)416{417t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;418419SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);420SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);421422fman_rtc_enable(p_Rtc->p_MemMap, resetClock);423return E_OK;424}425426/*****************************************************************************/427t_Error FM_RTC_Disable(t_Handle h_FmRtc)428{429t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;430431SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);432SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);433434/* TODO A check must be added here, that no timestamping MAC's435* are working in this stage. */436fman_rtc_disable(p_Rtc->p_MemMap);437438return E_OK;439}440441/*****************************************************************************/442t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset)443{444t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;445446SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);447SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);448449fman_rtc_set_timer_offset(p_Rtc->p_MemMap, offset);450return E_OK;451}452453/*****************************************************************************/454t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams)455{456t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;457uint64_t tmpAlarm;458bool enable = FALSE;459460SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);461SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);462463if (p_FmRtcAlarmParams->alarmId >= FM_RTC_NUM_OF_ALARMS)464{465RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID"));466}467468if (p_FmRtcAlarmParams->alarmTime < p_Rtc->clockPeriodNanoSec)469RETURN_ERROR(MAJOR, E_INVALID_SELECTION,470("Alarm time must be equal or larger than RTC period - %d nanoseconds",471p_Rtc->clockPeriodNanoSec));472tmpAlarm = p_FmRtcAlarmParams->alarmTime;473if (do_div(tmpAlarm, p_Rtc->clockPeriodNanoSec))474RETURN_ERROR(MAJOR, E_INVALID_SELECTION,475("Alarm time must be a multiple of RTC period - %d nanoseconds",476p_Rtc->clockPeriodNanoSec));477478if (p_FmRtcAlarmParams->f_AlarmCallback)479{480p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].f_AlarmCallback = p_FmRtcAlarmParams->f_AlarmCallback;481p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].clearOnExpiration = p_FmRtcAlarmParams->clearOnExpiration;482enable = TRUE;483}484485fman_rtc_set_alarm(p_Rtc->p_MemMap, p_FmRtcAlarmParams->alarmId, (unsigned long)tmpAlarm, enable);486487return E_OK;488}489490/*****************************************************************************/491t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams)492{493t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;494bool enable = FALSE;495uint64_t tmpFiper;496497SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);498SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);499500if (p_FmRtcPeriodicPulseParams->periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES)501{502RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID"));503}504if (fman_rtc_is_enabled(p_Rtc->p_MemMap))505RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Can't set Periodic pulse when RTC is enabled."));506if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod < p_Rtc->clockPeriodNanoSec)507RETURN_ERROR(MAJOR, E_INVALID_SELECTION,508("Periodic pulse must be equal or larger than RTC period - %d nanoseconds",509p_Rtc->clockPeriodNanoSec));510tmpFiper = p_FmRtcPeriodicPulseParams->periodicPulsePeriod;511if (do_div(tmpFiper, p_Rtc->clockPeriodNanoSec))512RETURN_ERROR(MAJOR, E_INVALID_SELECTION,513("Periodic pulse must be a multiple of RTC period - %d nanoseconds",514p_Rtc->clockPeriodNanoSec));515if (tmpFiper & 0xffffffff00000000LL)516RETURN_ERROR(MAJOR, E_INVALID_SELECTION,517("Periodic pulse/RTC Period must be smaller than 4294967296",518p_Rtc->clockPeriodNanoSec));519520if (p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback)521{522p_Rtc->periodicPulseParams[p_FmRtcPeriodicPulseParams->periodicPulseId].f_PeriodicPulseCallback =523p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback;524enable = TRUE;525}526fman_rtc_set_periodic_pulse(p_Rtc->p_MemMap, p_FmRtcPeriodicPulseParams->periodicPulseId, (uint32_t)tmpFiper, enable);527return E_OK;528}529530/*****************************************************************************/531t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId)532{533t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;534535SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);536SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);537538if (periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES)539{540RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID"));541}542543p_Rtc->periodicPulseParams[periodicPulseId].f_PeriodicPulseCallback = NULL;544fman_rtc_clear_periodic_pulse(p_Rtc->p_MemMap, periodicPulseId);545546return E_OK;547}548549/*****************************************************************************/550t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams)551{552t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;553bool enable = FALSE;554555SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);556SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);557558if (p_FmRtcExternalTriggerParams->externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)559{560RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID"));561}562563if (p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback)564{565p_Rtc->externalTriggerParams[p_FmRtcExternalTriggerParams->externalTriggerId].f_ExternalTriggerCallback = p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback;566enable = TRUE;567}568569fman_rtc_set_ext_trigger(p_Rtc->p_MemMap, p_FmRtcExternalTriggerParams->externalTriggerId, enable, p_FmRtcExternalTriggerParams->usePulseAsInput);570return E_OK;571}572573/*****************************************************************************/574t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t externalTriggerId)575{576t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;577578SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);579SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);580581if (externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)582RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID"));583584p_Rtc->externalTriggerParams[externalTriggerId].f_ExternalTriggerCallback = NULL;585586fman_rtc_clear_external_trigger(p_Rtc->p_MemMap, externalTriggerId);587588return E_OK;589}590591/*****************************************************************************/592t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc,593uint8_t triggerId,594uint64_t *p_TimeStamp)595{596t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;597598SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);599SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);600601if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)602RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID"));603604*p_TimeStamp = fman_rtc_get_trigger_stamp(p_Rtc->p_MemMap, triggerId)*p_Rtc->clockPeriodNanoSec;605606return E_OK;607}608609/*****************************************************************************/610t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts)611{612t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;613614SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);615SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);616617*p_Ts = fman_rtc_get_timer(p_Rtc->p_MemMap)*p_Rtc->clockPeriodNanoSec;618619return E_OK;620}621622/*****************************************************************************/623t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts)624{625t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;626627SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);628SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);629630do_div(ts, p_Rtc->clockPeriodNanoSec);631fman_rtc_set_timer(p_Rtc->p_MemMap, (int64_t)ts);632633return E_OK;634}635636/*****************************************************************************/637t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation)638{639t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;640641SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);642SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);643644*p_Compensation = fman_rtc_get_frequency_compensation(p_Rtc->p_MemMap);645646return E_OK;647}648649/*****************************************************************************/650t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation)651{652t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;653654SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);655SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);656657/* set the new freqCompensation */658fman_rtc_set_frequency_compensation(p_Rtc->p_MemMap, freqCompensation);659660return E_OK;661}662663#ifdef CONFIG_PTP_1588_CLOCK_DPAA664/*****************************************************************************/665t_Error FM_RTC_EnableInterrupt(t_Handle h_FmRtc, uint32_t events)666{667t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;668669SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);670SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);671672/* enable interrupt */673fman_rtc_enable_interupt(p_Rtc->p_MemMap, events);674675return E_OK;676}677678/*****************************************************************************/679t_Error FM_RTC_DisableInterrupt(t_Handle h_FmRtc, uint32_t events)680{681t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;682683SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);684SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);685686/* disable interrupt */687fman_rtc_disable_interupt(p_Rtc->p_MemMap, events);688689return E_OK;690}691#endif692693694