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 693