The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ncsw/Peripherals/FM/Rtc/fm_rtc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright 2008-2012 Freescale Semiconductor Inc.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions are met:
    6  *     * Redistributions of source code must retain the above copyright
    7  *       notice, this list of conditions and the following disclaimer.
    8  *     * Redistributions in binary form must reproduce the above copyright
    9  *       notice, this list of conditions and the following disclaimer in the
   10  *       documentation and/or other materials provided with the distribution.
   11  *     * Neither the name of Freescale Semiconductor nor the
   12  *       names of its contributors may be used to endorse or promote products
   13  *       derived from this software without specific prior written permission.
   14  *
   15  *
   16  * ALTERNATIVELY, this software may be distributed under the terms of the
   17  * GNU General Public License ("GPL") as published by the Free Software
   18  * Foundation, either version 2 of that License or (at your option) any
   19  * later version.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
   22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   24  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
   25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 
   34 /******************************************************************************
   35  @File          fm_rtc.c
   36 
   37  @Description   FM RTC driver implementation.
   38 
   39  @Cautions      None
   40 *//***************************************************************************/
   41 #include <linux/math64.h>
   42 #include "error_ext.h"
   43 #include "debug_ext.h"
   44 #include "string_ext.h"
   45 #include "part_ext.h"
   46 #include "xx_ext.h"
   47 #include "ncsw_ext.h"
   48 
   49 #include "fm_rtc.h"
   50 #include "fm_common.h"
   51 
   52 
   53 
   54 /*****************************************************************************/
   55 static t_Error CheckInitParameters(t_FmRtc *p_Rtc)
   56 {
   57     struct rtc_cfg  *p_RtcDriverParam = p_Rtc->p_RtcDriverParam;
   58     int                 i;
   59 
   60     if ((p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL) &&
   61         (p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_SYSTEM) &&
   62         (p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR))
   63         RETURN_ERROR(MAJOR, E_INVALID_CLOCK, ("Source clock undefined"));
   64 
   65     if (p_Rtc->outputClockDivisor == 0)
   66     {
   67         RETURN_ERROR(MAJOR, E_INVALID_VALUE,
   68                      ("Divisor for output clock (should be positive)"));
   69     }
   70 
   71     for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++)
   72     {
   73         if ((p_RtcDriverParam->alarm_polarity[i] != E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW) &&
   74             (p_RtcDriverParam->alarm_polarity[i] != E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH))
   75         {
   76             RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm %d signal polarity", i));
   77         }
   78     }
   79     for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++)
   80     {
   81         if ((p_RtcDriverParam->trigger_polarity[i] != E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE) &&
   82             (p_RtcDriverParam->trigger_polarity[i] != E_FMAN_RTC_TRIGGER_ON_RISING_EDGE))
   83         {
   84             RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Trigger %d signal polarity", i));
   85         }
   86     }
   87 
   88     return E_OK;
   89 }
   90 
   91 /*****************************************************************************/
   92 static void RtcExceptions(t_Handle h_FmRtc)
   93 {
   94     t_FmRtc             *p_Rtc = (t_FmRtc *)h_FmRtc;
   95     struct rtc_regs     *p_MemMap;
   96     register uint32_t   events;
   97 
   98     ASSERT_COND(p_Rtc);
   99     p_MemMap = p_Rtc->p_MemMap;
  100 
  101     events = fman_rtc_check_and_clear_event(p_MemMap);
  102     if (events & FMAN_RTC_TMR_TEVENT_ALM1)
  103     {
  104         if (p_Rtc->alarmParams[0].clearOnExpiration)
  105         {
  106             fman_rtc_set_timer_alarm_l(p_MemMap, 0, 0);
  107             fman_rtc_disable_interupt(p_MemMap, FMAN_RTC_TMR_TEVENT_ALM1);
  108         }
  109         ASSERT_COND(p_Rtc->alarmParams[0].f_AlarmCallback);
  110         p_Rtc->alarmParams[0].f_AlarmCallback(p_Rtc->h_App, 0);
  111     }
  112     if (events & FMAN_RTC_TMR_TEVENT_ALM2)
  113     {
  114         if (p_Rtc->alarmParams[1].clearOnExpiration)
  115         {
  116             fman_rtc_set_timer_alarm_l(p_MemMap, 1, 0);
  117             fman_rtc_disable_interupt(p_MemMap, FMAN_RTC_TMR_TEVENT_ALM2);
  118         }
  119         ASSERT_COND(p_Rtc->alarmParams[1].f_AlarmCallback);
  120         p_Rtc->alarmParams[1].f_AlarmCallback(p_Rtc->h_App, 1);
  121     }
  122     if (events & FMAN_RTC_TMR_TEVENT_PP1)
  123     {
  124         ASSERT_COND(p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback);
  125         p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback(p_Rtc->h_App, 0);
  126     }
  127     if (events & FMAN_RTC_TMR_TEVENT_PP2)
  128     {
  129         ASSERT_COND(p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback);
  130         p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback(p_Rtc->h_App, 1);
  131     }
  132     if (events & FMAN_RTC_TMR_TEVENT_ETS1)
  133     {
  134         ASSERT_COND(p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback);
  135         p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback(p_Rtc->h_App, 0);
  136     }
  137     if (events & FMAN_RTC_TMR_TEVENT_ETS2)
  138     {
  139         ASSERT_COND(p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback);
  140         p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback(p_Rtc->h_App, 1);
  141     }
  142 }
  143 
  144 
  145 /*****************************************************************************/
  146 t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam)
  147 {
  148     t_FmRtc *p_Rtc;
  149 
  150     SANITY_CHECK_RETURN_VALUE(p_FmRtcParam, E_NULL_POINTER, NULL);
  151 
  152     /* Allocate memory for the FM RTC driver parameters */
  153     p_Rtc = (t_FmRtc *)XX_Malloc(sizeof(t_FmRtc));
  154     if (!p_Rtc)
  155     {
  156         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver structure"));
  157         return NULL;
  158     }
  159 
  160     memset(p_Rtc, 0, sizeof(t_FmRtc));
  161 
  162     /* Allocate memory for the FM RTC driver parameters */
  163     p_Rtc->p_RtcDriverParam = (struct rtc_cfg *)XX_Malloc(sizeof(struct rtc_cfg));
  164     if (!p_Rtc->p_RtcDriverParam)
  165     {
  166         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver parameters"));
  167         XX_Free(p_Rtc);
  168         return NULL;
  169     }
  170 
  171     memset(p_Rtc->p_RtcDriverParam, 0, sizeof(struct rtc_cfg));
  172 
  173     /* Store RTC configuration parameters */
  174     p_Rtc->h_Fm = p_FmRtcParam->h_Fm;
  175 
  176     /* Set default RTC configuration parameters */
  177     fman_rtc_defconfig(p_Rtc->p_RtcDriverParam);
  178 
  179     p_Rtc->outputClockDivisor = DEFAULT_OUTPUT_CLOCK_DIVISOR;
  180     p_Rtc->p_RtcDriverParam->bypass = DEFAULT_BYPASS;
  181     p_Rtc->clockPeriodNanoSec = DEFAULT_CLOCK_PERIOD; /* 1 usec */
  182 
  183 
  184     /* Store RTC parameters in the RTC control structure */
  185     p_Rtc->p_MemMap = (struct rtc_regs *)UINT_TO_PTR(p_FmRtcParam->baseAddress);
  186     p_Rtc->h_App    = p_FmRtcParam->h_App;
  187 
  188     return p_Rtc;
  189 }
  190 
  191 /*****************************************************************************/
  192 t_Error FM_RTC_Init(t_Handle h_FmRtc)
  193 {
  194     t_FmRtc             *p_Rtc = (t_FmRtc *)h_FmRtc;
  195     struct rtc_cfg      *p_RtcDriverParam;
  196     struct rtc_regs     *p_MemMap;
  197     uint32_t            freqCompensation = 0;
  198     uint64_t            tmpDouble;
  199     bool                init_freq_comp = FALSE;
  200 
  201     p_RtcDriverParam = p_Rtc->p_RtcDriverParam;
  202     p_MemMap = p_Rtc->p_MemMap;
  203 
  204     if (CheckInitParameters(p_Rtc)!=E_OK)
  205         RETURN_ERROR(MAJOR, E_CONFLICT,
  206                      ("Init Parameters are not Valid"));
  207 
  208     /* TODO check that no timestamping MACs are working in this stage. */
  209 
  210     /* find source clock frequency in Mhz */
  211     if (p_Rtc->p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_SYSTEM)
  212         p_Rtc->srcClkFreqMhz = p_Rtc->p_RtcDriverParam->ext_src_clk_freq;
  213     else
  214         p_Rtc->srcClkFreqMhz = (uint32_t)(FmGetMacClockFreq(p_Rtc->h_Fm));
  215 
  216     /* if timer in Master mode Initialize TMR_CTRL */
  217     /* We want the counter (TMR_CNT) to count in nano-seconds */
  218     if (!p_RtcDriverParam->timer_slave_mode && p_Rtc->p_RtcDriverParam->bypass)
  219         p_Rtc->clockPeriodNanoSec = (1000 / p_Rtc->srcClkFreqMhz);
  220     else
  221     {
  222         /* Initialize TMR_ADD with the initial frequency compensation value:
  223            freqCompensation = (2^32 / frequency ratio) */
  224         /* frequency ratio = sorce clock/rtc clock =
  225          * (p_Rtc->srcClkFreqMhz*1000000))/ 1/(p_Rtc->clockPeriodNanoSec * 1000000000) */
  226         init_freq_comp = TRUE;
  227         freqCompensation = (uint32_t)DIV_CEIL(ACCUMULATOR_OVERFLOW * 1000,
  228                                               p_Rtc->clockPeriodNanoSec * p_Rtc->srcClkFreqMhz);
  229     }
  230 
  231     /* check the legality of the relation between source and destination clocks */
  232     /* should be larger than 1.0001 */
  233     tmpDouble = 10000 * (uint64_t)p_Rtc->clockPeriodNanoSec * (uint64_t)p_Rtc->srcClkFreqMhz;
  234     if ((tmpDouble) <= 10001)
  235         RETURN_ERROR(MAJOR, E_CONFLICT,
  236               ("Invalid relation between source and destination clocks. Should be larger than 1.0001"));
  237 
  238     fman_rtc_init(p_RtcDriverParam,
  239              p_MemMap,
  240              FM_RTC_NUM_OF_ALARMS,
  241              FM_RTC_NUM_OF_PERIODIC_PULSES,
  242              FM_RTC_NUM_OF_EXT_TRIGGERS,
  243              init_freq_comp,
  244              freqCompensation,
  245              p_Rtc->outputClockDivisor);
  246 
  247     /* Register the FM RTC interrupt */
  248     FmRegisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL, RtcExceptions , p_Rtc);
  249 
  250     /* Free parameters structures */
  251     XX_Free(p_Rtc->p_RtcDriverParam);
  252     p_Rtc->p_RtcDriverParam = NULL;
  253 
  254     return E_OK;
  255 }
  256 
  257 /*****************************************************************************/
  258 t_Error FM_RTC_Free(t_Handle h_FmRtc)
  259 {
  260     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  261 
  262     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  263 
  264     if (p_Rtc->p_RtcDriverParam)
  265     {
  266         XX_Free(p_Rtc->p_RtcDriverParam);
  267     }
  268     else
  269     {
  270         FM_RTC_Disable(h_FmRtc);
  271     }
  272 
  273     /* Unregister FM RTC interrupt */
  274     FmUnregisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL);
  275     XX_Free(p_Rtc);
  276 
  277     return E_OK;
  278 }
  279 
  280 /*****************************************************************************/
  281 t_Error FM_RTC_ConfigSourceClock(t_Handle         h_FmRtc,
  282                                     e_FmSrcClk    srcClk,
  283                                     uint32_t      freqInMhz)
  284 {
  285     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  286 
  287     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  288     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  289 
  290     p_Rtc->p_RtcDriverParam->src_clk = (enum fman_src_clock)srcClk;
  291     if (srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM)
  292         p_Rtc->p_RtcDriverParam->ext_src_clk_freq = freqInMhz;
  293 
  294     return E_OK;
  295 }
  296 
  297 /*****************************************************************************/
  298 t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period)
  299 {
  300     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  301 
  302     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  303     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  304 
  305     p_Rtc->clockPeriodNanoSec = period;
  306 
  307     return E_OK;
  308 }
  309 
  310 /*****************************************************************************/
  311 t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled)
  312 {
  313     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  314 
  315     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  316     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  317 
  318     p_Rtc->p_RtcDriverParam->bypass = enabled;
  319 
  320     return E_OK;
  321 }
  322 
  323 /*****************************************************************************/
  324 t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted)
  325 {
  326     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  327 
  328     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  329     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  330 
  331     p_Rtc->p_RtcDriverParam->invert_input_clk_phase = inverted;
  332 
  333     return E_OK;
  334 }
  335 
  336 /*****************************************************************************/
  337 t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted)
  338 {
  339     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  340 
  341     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  342     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  343 
  344     p_Rtc->p_RtcDriverParam->invert_output_clk_phase = inverted;
  345 
  346     return E_OK;
  347 }
  348 
  349 /*****************************************************************************/
  350 t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor)
  351 {
  352     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  353 
  354     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  355     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  356 
  357     p_Rtc->outputClockDivisor = divisor;
  358 
  359     return E_OK;
  360 }
  361 
  362 /*****************************************************************************/
  363 t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable)
  364 {
  365     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  366 
  367     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  368     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  369 
  370     p_Rtc->p_RtcDriverParam->pulse_realign = enable;
  371 
  372     return E_OK;
  373 }
  374 
  375 /*****************************************************************************/
  376 t_Error FM_RTC_ConfigAlarmPolarity(t_Handle             h_FmRtc,
  377                                    uint8_t              alarmId,
  378                                    e_FmRtcAlarmPolarity alarmPolarity)
  379 {
  380     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  381 
  382     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  383     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  384 
  385     if (alarmId >= FM_RTC_NUM_OF_ALARMS)
  386         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID"));
  387 
  388     p_Rtc->p_RtcDriverParam->alarm_polarity[alarmId] =
  389         (enum fman_rtc_alarm_polarity)alarmPolarity;
  390 
  391     return E_OK;
  392 }
  393 
  394 /*****************************************************************************/
  395 t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle               h_FmRtc,
  396                                              uint8_t                triggerId,
  397                                              e_FmRtcTriggerPolarity triggerPolarity)
  398 {
  399     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  400 
  401     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  402     SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  403 
  404     if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
  405     {
  406         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID"));
  407     }
  408 
  409     p_Rtc->p_RtcDriverParam->trigger_polarity[triggerId] =
  410         (enum fman_rtc_trigger_polarity)triggerPolarity;
  411 
  412     return E_OK;
  413 }
  414 
  415 /*****************************************************************************/
  416 t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock)
  417 {
  418     t_FmRtc         *p_Rtc = (t_FmRtc *)h_FmRtc;
  419 
  420     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  421     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  422 
  423     fman_rtc_enable(p_Rtc->p_MemMap, resetClock);
  424     return E_OK;
  425 }
  426 
  427 /*****************************************************************************/
  428 t_Error FM_RTC_Disable(t_Handle h_FmRtc)
  429 {
  430     t_FmRtc         *p_Rtc = (t_FmRtc *)h_FmRtc;
  431 
  432     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  433     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  434 
  435     /* TODO A check must be added here, that no timestamping MAC's
  436      * are working in this stage. */
  437     fman_rtc_disable(p_Rtc->p_MemMap);
  438 
  439     return E_OK;
  440 }
  441 
  442 /*****************************************************************************/
  443 t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset)
  444 {
  445     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  446 
  447     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  448     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  449 
  450     fman_rtc_set_timer_offset(p_Rtc->p_MemMap, offset);
  451     return E_OK;
  452 }
  453 
  454 /*****************************************************************************/
  455 t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams)
  456 {
  457     t_FmRtc         *p_Rtc = (t_FmRtc *)h_FmRtc;
  458     uint64_t        tmpAlarm;
  459     bool            enable = FALSE;
  460 
  461     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  462     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  463 
  464     if (p_FmRtcAlarmParams->alarmId >= FM_RTC_NUM_OF_ALARMS)
  465     {
  466         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID"));
  467     }
  468 
  469     if (p_FmRtcAlarmParams->alarmTime < p_Rtc->clockPeriodNanoSec)
  470         RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
  471                      ("Alarm time must be equal or larger than RTC period - %d nanoseconds",
  472                       p_Rtc->clockPeriodNanoSec));
  473     tmpAlarm = p_FmRtcAlarmParams->alarmTime;
  474     if (do_div(tmpAlarm, p_Rtc->clockPeriodNanoSec))
  475         RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
  476                      ("Alarm time must be a multiple of RTC period - %d nanoseconds",
  477                       p_Rtc->clockPeriodNanoSec));
  478 
  479     if (p_FmRtcAlarmParams->f_AlarmCallback)
  480     {
  481         p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].f_AlarmCallback = p_FmRtcAlarmParams->f_AlarmCallback;
  482         p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].clearOnExpiration = p_FmRtcAlarmParams->clearOnExpiration;
  483         enable = TRUE;
  484     }
  485 
  486     fman_rtc_set_alarm(p_Rtc->p_MemMap, p_FmRtcAlarmParams->alarmId, (unsigned long)tmpAlarm, enable);
  487 
  488     return E_OK;
  489 }
  490 
  491 /*****************************************************************************/
  492 t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams)
  493 {
  494     t_FmRtc         *p_Rtc = (t_FmRtc *)h_FmRtc;
  495     bool            enable = FALSE;
  496     uint64_t        tmpFiper;
  497 
  498     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  499     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  500 
  501     if (p_FmRtcPeriodicPulseParams->periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES)
  502     {
  503         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID"));
  504     }
  505     if (fman_rtc_is_enabled(p_Rtc->p_MemMap))
  506         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Can't set Periodic pulse when RTC is enabled."));
  507     if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod < p_Rtc->clockPeriodNanoSec)
  508         RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
  509                      ("Periodic pulse must be equal or larger than RTC period - %d nanoseconds",
  510                       p_Rtc->clockPeriodNanoSec));
  511     tmpFiper = p_FmRtcPeriodicPulseParams->periodicPulsePeriod;
  512     if (do_div(tmpFiper, p_Rtc->clockPeriodNanoSec))
  513         RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
  514                      ("Periodic pulse must be a multiple of RTC period - %d nanoseconds",
  515                       p_Rtc->clockPeriodNanoSec));
  516     if (tmpFiper & 0xffffffff00000000LL)
  517         RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
  518                      ("Periodic pulse/RTC Period must be smaller than 4294967296",
  519                       p_Rtc->clockPeriodNanoSec));
  520 
  521     if (p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback)
  522     {
  523         p_Rtc->periodicPulseParams[p_FmRtcPeriodicPulseParams->periodicPulseId].f_PeriodicPulseCallback =
  524                                                                 p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback;
  525         enable = TRUE;
  526     }
  527     fman_rtc_set_periodic_pulse(p_Rtc->p_MemMap, p_FmRtcPeriodicPulseParams->periodicPulseId, (uint32_t)tmpFiper, enable);
  528     return E_OK;
  529 }
  530 
  531 /*****************************************************************************/
  532 t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId)
  533 {
  534     t_FmRtc     *p_Rtc = (t_FmRtc *)h_FmRtc;
  535 
  536     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  537     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  538 
  539     if (periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES)
  540     {
  541         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID"));
  542     }
  543 
  544     p_Rtc->periodicPulseParams[periodicPulseId].f_PeriodicPulseCallback = NULL;
  545     fman_rtc_clear_periodic_pulse(p_Rtc->p_MemMap, periodicPulseId);
  546 
  547     return E_OK;
  548 }
  549 
  550 /*****************************************************************************/
  551 t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams)
  552 {
  553     t_FmRtc     *p_Rtc = (t_FmRtc *)h_FmRtc;
  554     bool        enable = FALSE;
  555 
  556     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  557     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  558 
  559     if (p_FmRtcExternalTriggerParams->externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
  560     {
  561         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID"));
  562     }
  563 
  564     if (p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback)
  565     {
  566         p_Rtc->externalTriggerParams[p_FmRtcExternalTriggerParams->externalTriggerId].f_ExternalTriggerCallback = p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback;
  567         enable = TRUE;
  568     }
  569 
  570     fman_rtc_set_ext_trigger(p_Rtc->p_MemMap, p_FmRtcExternalTriggerParams->externalTriggerId, enable, p_FmRtcExternalTriggerParams->usePulseAsInput);
  571     return E_OK;
  572 }
  573 
  574 /*****************************************************************************/
  575 t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t externalTriggerId)
  576 {
  577     t_FmRtc     *p_Rtc = (t_FmRtc *)h_FmRtc;
  578 
  579     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  580     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  581 
  582     if (externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
  583         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID"));
  584 
  585     p_Rtc->externalTriggerParams[externalTriggerId].f_ExternalTriggerCallback = NULL;
  586 
  587     fman_rtc_clear_external_trigger(p_Rtc->p_MemMap, externalTriggerId);
  588 
  589     return E_OK;
  590 }
  591 
  592 /*****************************************************************************/
  593 t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle             h_FmRtc,
  594                                               uint8_t           triggerId,
  595                                               uint64_t          *p_TimeStamp)
  596 {
  597     t_FmRtc     *p_Rtc = (t_FmRtc *)h_FmRtc;
  598 
  599     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  600     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  601 
  602     if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
  603         RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID"));
  604 
  605     *p_TimeStamp = fman_rtc_get_trigger_stamp(p_Rtc->p_MemMap, triggerId)*p_Rtc->clockPeriodNanoSec;
  606 
  607     return E_OK;
  608 }
  609 
  610 /*****************************************************************************/
  611 t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts)
  612 {
  613     t_FmRtc     *p_Rtc = (t_FmRtc *)h_FmRtc;
  614 
  615     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  616     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  617 
  618     *p_Ts = fman_rtc_get_timer(p_Rtc->p_MemMap)*p_Rtc->clockPeriodNanoSec;
  619 
  620     return E_OK;
  621 }
  622 
  623 /*****************************************************************************/
  624 t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts)
  625 {
  626     t_FmRtc     *p_Rtc = (t_FmRtc *)h_FmRtc;
  627 
  628     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  629     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  630 
  631     do_div(ts, p_Rtc->clockPeriodNanoSec);
  632     fman_rtc_set_timer(p_Rtc->p_MemMap, (int64_t)ts);
  633 
  634     return E_OK;
  635 }
  636 
  637 /*****************************************************************************/
  638 t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation)
  639 {
  640     t_FmRtc     *p_Rtc = (t_FmRtc *)h_FmRtc;
  641 
  642     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  643     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  644 
  645     *p_Compensation = fman_rtc_get_frequency_compensation(p_Rtc->p_MemMap);
  646 
  647     return E_OK;
  648 }
  649 
  650 /*****************************************************************************/
  651 t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation)
  652 {
  653     t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  654 
  655     SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  656     SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  657 
  658     /* set the new freqCompensation */
  659     fman_rtc_set_frequency_compensation(p_Rtc->p_MemMap, freqCompensation);
  660 
  661     return E_OK;
  662 }
  663 
  664 #ifdef CONFIG_PTP_1588_CLOCK_DPAA
  665 /*****************************************************************************/
  666 t_Error FM_RTC_EnableInterrupt(t_Handle h_FmRtc, uint32_t events)
  667 {
  668         t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  669 
  670         SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  671         SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  672 
  673         /* enable interrupt */
  674         fman_rtc_enable_interupt(p_Rtc->p_MemMap, events);
  675 
  676         return E_OK;
  677 }
  678 
  679 /*****************************************************************************/
  680 t_Error FM_RTC_DisableInterrupt(t_Handle h_FmRtc, uint32_t events)
  681 {
  682         t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
  683 
  684         SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
  685         SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
  686 
  687         /* disable interrupt */
  688         fman_rtc_disable_interupt(p_Rtc->p_MemMap, events);
  689 
  690         return E_OK;
  691 }
  692 #endif

Cache object: 2650fa935adf41ff6aed4c5ccf6d041e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.