1 /* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. 2 * All rights reserved. 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 @File fm_rtc.c 35 36 @Description FM RTC driver implementation. 37 38 @Cautions None 39 *//***************************************************************************/ 40 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" 47 48 #include "fm_rtc.h" 49 #include "fm_common.h" 50 51 52 /*****************************************************************************/ 53 static void SetDefaultParam(t_FmRtc *p_Rtc) 54 { 55 t_FmRtcDriverParam *p_RtcDriverParam = p_Rtc->p_RtcDriverParam; 56 int i; 57 58 p_Rtc->outputClockDivisor = DEFAULT_outputClockDivisor; 59 p_Rtc->p_RtcDriverParam->bypass = DEFAULT_bypass; 60 p_RtcDriverParam->srcClk = DEFAULT_srcClock; 61 p_RtcDriverParam->invertInputClkPhase = DEFAULT_invertInputClkPhase; 62 p_RtcDriverParam->invertOutputClkPhase = DEFAULT_invertOutputClkPhase; 63 p_RtcDriverParam->pulseRealign = DEFAULT_pulseRealign; 64 for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) 65 { 66 p_RtcDriverParam->alarmPolarity[i] = DEFAULT_alarmPolarity; 67 } 68 for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++) 69 { 70 p_RtcDriverParam->triggerPolarity[i] = DEFAULT_triggerPolarity; 71 } 72 p_Rtc->clockPeriodNanoSec = DEFAULT_clockPeriod; /* 1 usec */ 73 } 74 75 /*****************************************************************************/ 76 static t_Error CheckInitParameters(t_FmRtc *p_Rtc) 77 { 78 t_FmRtcDriverParam *p_RtcDriverParam = p_Rtc->p_RtcDriverParam; 79 int i; 80 81 if ((p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_EXTERNAL) && 82 (p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM) && 83 (p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_OSCILATOR)) 84 RETURN_ERROR(MAJOR, E_INVALID_CLOCK, ("Source clock undefined")); 85 86 if (p_Rtc->outputClockDivisor == 0) 87 { 88 RETURN_ERROR(MAJOR, E_INVALID_VALUE, 89 ("Divisor for output clock (should be positive)")); 90 } 91 92 for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) 93 { 94 if ((p_RtcDriverParam->alarmPolarity[i] != e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW) && 95 (p_RtcDriverParam->alarmPolarity[i] != e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH)) 96 { 97 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm %d signal polarity", i)); 98 } 99 } 100 for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++) 101 { 102 if ((p_RtcDriverParam->triggerPolarity[i] != e_FM_RTC_TRIGGER_ON_FALLING_EDGE) && 103 (p_RtcDriverParam->triggerPolarity[i] != e_FM_RTC_TRIGGER_ON_RISING_EDGE)) 104 { 105 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Trigger %d signal polarity", i)); 106 } 107 } 108 109 #ifdef FM_1588_SRC_CLK_ERRATA_FMAN1 110 { 111 t_FmRevisionInfo revInfo; 112 FM_GetRevision(p_Rtc->h_Fm, &revInfo); 113 if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)&& 114 ((p_RtcDriverParam->srcClk==e_FM_RTC_SOURCE_CLOCK_SYSTEM) && p_RtcDriverParam->invertInputClkPhase)) 115 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Can not use invertInputClkPhase when source clock is e_FM_RTC_SOURCE_CLOCK_SYSTEM")); 116 } 117 #endif /* FM_1588_SRC_CLK_ERRATA_FMAN1 */ 118 119 return E_OK; 120 } 121 122 /*****************************************************************************/ 123 static void RtcExceptions(t_Handle h_FmRtc) 124 { 125 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 126 t_FmRtcMemMap *p_MemMap; 127 register uint32_t events; 128 129 ASSERT_COND(p_Rtc); 130 p_MemMap = p_Rtc->p_MemMap; 131 132 /* Get valid events */ 133 events = GET_UINT32(p_MemMap->tmr_tevent); 134 events &= GET_UINT32(p_MemMap->tmr_temask); 135 136 /* Clear event bits */ 137 WRITE_UINT32(p_MemMap->tmr_tevent, events); 138 139 if (events & TMR_TEVENT_ALM1) 140 { 141 if(p_Rtc->alarmParams[0].clearOnExpiration) 142 { 143 WRITE_UINT32(p_MemMap->tmr_alarm[0].tmr_alarm_l, 0); 144 WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) & ~TMR_TEVENT_ALM1); 145 } 146 ASSERT_COND(p_Rtc->alarmParams[0].f_AlarmCallback); 147 p_Rtc->alarmParams[0].f_AlarmCallback(p_Rtc->h_App, 0); 148 } 149 if (events & TMR_TEVENT_ALM2) 150 { 151 if(p_Rtc->alarmParams[1].clearOnExpiration) 152 { 153 WRITE_UINT32(p_MemMap->tmr_alarm[1].tmr_alarm_l, 0); 154 WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) & ~TMR_TEVENT_ALM2); 155 } 156 ASSERT_COND(p_Rtc->alarmParams[1].f_AlarmCallback); 157 p_Rtc->alarmParams[1].f_AlarmCallback(p_Rtc->h_App, 1); 158 } 159 if (events & TMR_TEVENT_PP1) 160 { 161 ASSERT_COND(p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback); 162 p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback(p_Rtc->h_App, 0); 163 } 164 if (events & TMR_TEVENT_PP2) 165 { 166 ASSERT_COND(p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback); 167 p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback(p_Rtc->h_App, 1); 168 } 169 if (events & TMR_TEVENT_ETS1) 170 { 171 ASSERT_COND(p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback); 172 p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback(p_Rtc->h_App, 0); 173 } 174 if (events & TMR_TEVENT_ETS2) 175 { 176 ASSERT_COND(p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback); 177 p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback(p_Rtc->h_App, 1); 178 } 179 } 180 181 182 /*****************************************************************************/ 183 t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam) 184 { 185 t_FmRtc *p_Rtc; 186 187 SANITY_CHECK_RETURN_VALUE(p_FmRtcParam, E_NULL_POINTER, NULL); 188 189 /* Allocate memory for the FM RTC driver parameters */ 190 p_Rtc = (t_FmRtc *)XX_Malloc(sizeof(t_FmRtc)); 191 if (!p_Rtc) 192 { 193 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver structure")); 194 return NULL; 195 } 196 197 memset(p_Rtc, 0, sizeof(t_FmRtc)); 198 199 /* Allocate memory for the FM RTC driver parameters */ 200 p_Rtc->p_RtcDriverParam = (t_FmRtcDriverParam *)XX_Malloc(sizeof(t_FmRtcDriverParam)); 201 if (!p_Rtc->p_RtcDriverParam) 202 { 203 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver parameters")); 204 XX_Free(p_Rtc); 205 return NULL; 206 } 207 208 memset(p_Rtc->p_RtcDriverParam, 0, sizeof(t_FmRtcDriverParam)); 209 210 /* Store RTC configuration parameters */ 211 p_Rtc->h_Fm = p_FmRtcParam->h_Fm; 212 213 /* Set default RTC configuration parameters */ 214 SetDefaultParam(p_Rtc); 215 216 /* Store RTC parameters in the RTC control structure */ 217 p_Rtc->p_MemMap = (t_FmRtcMemMap *)UINT_TO_PTR(p_FmRtcParam->baseAddress); 218 p_Rtc->h_App = p_FmRtcParam->h_App; 219 220 return p_Rtc; 221 } 222 223 /*****************************************************************************/ 224 t_Error FM_RTC_Init(t_Handle h_FmRtc) 225 { 226 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 227 t_FmRtcDriverParam *p_RtcDriverParam; 228 t_FmRtcMemMap *p_MemMap; 229 uint32_t freqCompensation; 230 uint32_t tmrCtrl; 231 int i; 232 uint64_t tmpDouble; 233 234 p_RtcDriverParam = p_Rtc->p_RtcDriverParam; 235 p_MemMap = p_Rtc->p_MemMap; 236 237 if(CheckInitParameters(p_Rtc)!=E_OK) 238 RETURN_ERROR(MAJOR, E_CONFLICT, 239 ("Init Parameters are not Valid")); 240 241 /* TODO A check must be added here, that no timestamping MAC's 242 * are working in this stage. */ 243 WRITE_UINT32(p_MemMap->tmr_ctrl, TMR_CTRL_TMSR); 244 XX_UDelay(10); 245 WRITE_UINT32(p_MemMap->tmr_ctrl, 0); 246 247 /* Set the source clock */ 248 switch (p_RtcDriverParam->srcClk) 249 { 250 case e_FM_RTC_SOURCE_CLOCK_SYSTEM: 251 tmrCtrl = TMR_CTRL_CKSEL_MAC_CLK; 252 break; 253 case e_FM_RTC_SOURCE_CLOCK_OSCILATOR: 254 tmrCtrl = TMR_CTRL_CKSEL_OSC_CLK; 255 break; 256 default: 257 /* Use a clock from the External TMR reference clock.*/ 258 tmrCtrl = TMR_CTRL_CKSEL_EXT_CLK; 259 break; 260 } 261 262 /* whatever period the user picked, the timestamp will advance in '1' every time 263 * the period passed. */ 264 tmrCtrl |= ((1 << TMR_CTRL_TCLK_PERIOD_SHIFT) & TMR_CTRL_TCLK_PERIOD_MASK); 265 266 if (p_RtcDriverParam->invertInputClkPhase) 267 tmrCtrl |= TMR_CTRL_CIPH; 268 if (p_RtcDriverParam->invertOutputClkPhase) 269 tmrCtrl |= TMR_CTRL_COPH; 270 271 for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) 272 { 273 if (p_RtcDriverParam->alarmPolarity[i] == e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW) 274 tmrCtrl |= (TMR_CTRL_ALMP1 >> i); 275 } 276 277 for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++) 278 if (p_RtcDriverParam->triggerPolarity[i] == e_FM_RTC_TRIGGER_ON_FALLING_EDGE) 279 tmrCtrl |= (TMR_CTRL_ETEP1 << i); 280 281 if (!p_RtcDriverParam->timerSlaveMode && p_Rtc->p_RtcDriverParam->bypass) 282 tmrCtrl |= TMR_CTRL_BYP; 283 284 WRITE_UINT32(p_MemMap->tmr_ctrl, tmrCtrl); 285 286 for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) 287 { 288 /* Clear TMR_ALARM registers */ 289 WRITE_UINT32(p_MemMap->tmr_alarm[i].tmr_alarm_l, 0xFFFFFFFF); 290 WRITE_UINT32(p_MemMap->tmr_alarm[i].tmr_alarm_h, 0xFFFFFFFF); 291 } 292 293 /* Clear TMR_TEVENT */ 294 WRITE_UINT32(p_MemMap->tmr_tevent, TMR_TEVENT_ALL); 295 296 /* Initialize TMR_TEMASK */ 297 WRITE_UINT32(p_MemMap->tmr_temask, 0); 298 299 300 /* find source clock frequency in Mhz */ 301 if (p_Rtc->p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM) 302 p_Rtc->srcClkFreqMhz = p_Rtc->p_RtcDriverParam->extSrcClkFreq; 303 else 304 p_Rtc->srcClkFreqMhz = (uint32_t)(FmGetClockFreq(p_Rtc->h_Fm)/2); 305 306 /* if timer in Master mode Initialize TMR_CTRL */ 307 /* We want the counter (TMR_CNT) to count in nano-seconds */ 308 if (!p_RtcDriverParam->timerSlaveMode && p_Rtc->p_RtcDriverParam->bypass) 309 { 310 p_Rtc->clockPeriodNanoSec = (1000 / p_Rtc->srcClkFreqMhz); 311 } 312 else 313 { 314 /* Initialize TMR_ADD with the initial frequency compensation value: 315 freqCompensation = (2^32 / frequency ratio) */ 316 /* frequency ratio = sorce clock/rtc clock = 317 * (p_Rtc->srcClkFreqMhz*1000000))/ 1/(p_Rtc->clockPeriodNanoSec * 1000000000) */ 318 freqCompensation = (uint32_t)DIV_CEIL(ACCUMULATOR_OVERFLOW * 1000, 319 p_Rtc->clockPeriodNanoSec * p_Rtc->srcClkFreqMhz); 320 WRITE_UINT32(p_MemMap->tmr_add, freqCompensation); 321 } 322 /* check the legality of the relation between source and destination clocks */ 323 /* should be larger than 1.0001 */ 324 tmpDouble = 10000 * (uint64_t)p_Rtc->clockPeriodNanoSec * (uint64_t)p_Rtc->srcClkFreqMhz; 325 if((tmpDouble) <= 10001) 326 RETURN_ERROR(MAJOR, E_CONFLICT, 327 ("Invalid relation between source and destination clocks. Should be larger than 1.0001")); 328 329 330 for (i=0; i < 2; i++) 331 /* Clear TMR_FIPER registers */ 332 WRITE_UINT32(p_MemMap->tmr_fiper[i], 0xFFFFFFFF); 333 334 /* Initialize TMR_PRSC */ 335 WRITE_UINT32(p_MemMap->tmr_prsc, p_Rtc->outputClockDivisor); 336 337 /* Clear TMR_OFF */ 338 WRITE_UINT32(p_MemMap->tmr_off_l, 0); 339 WRITE_UINT32(p_MemMap->tmr_off_h, 0); 340 341 /* Register the FM RTC interrupt */ 342 FmRegisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL, RtcExceptions , p_Rtc); 343 344 /* Free parameters structures */ 345 XX_Free(p_Rtc->p_RtcDriverParam); 346 p_Rtc->p_RtcDriverParam = NULL; 347 348 return E_OK; 349 } 350 351 /*****************************************************************************/ 352 t_Error FM_RTC_Free(t_Handle h_FmRtc) 353 { 354 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 355 356 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 357 358 if (p_Rtc->p_RtcDriverParam) 359 { 360 XX_Free(p_Rtc->p_RtcDriverParam); 361 } 362 else 363 { 364 FM_RTC_Disable(h_FmRtc); 365 } 366 367 /* Unregister FM RTC interrupt */ 368 FmUnregisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL); 369 XX_Free(p_Rtc); 370 371 return E_OK; 372 } 373 374 /*****************************************************************************/ 375 t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc, 376 e_FmSrcClk srcClk, 377 uint32_t freqInMhz) 378 { 379 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 380 381 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 382 SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 383 384 p_Rtc->p_RtcDriverParam->srcClk = srcClk; 385 if(srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM) 386 p_Rtc->p_RtcDriverParam->extSrcClkFreq = freqInMhz; 387 388 return E_OK; 389 } 390 391 /*****************************************************************************/ 392 t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period) 393 { 394 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 395 396 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 397 SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 398 399 p_Rtc->clockPeriodNanoSec = period; 400 401 return E_OK; 402 } 403 404 /*****************************************************************************/ 405 t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled) 406 { 407 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 408 409 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 410 SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 411 412 p_Rtc->p_RtcDriverParam->bypass = enabled; 413 414 return E_OK; 415 } 416 417 /*****************************************************************************/ 418 t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted) 419 { 420 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 421 422 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 423 SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 424 425 p_Rtc->p_RtcDriverParam->invertInputClkPhase = inverted; 426 427 return E_OK; 428 } 429 430 /*****************************************************************************/ 431 t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted) 432 { 433 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 434 435 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 436 SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 437 438 p_Rtc->p_RtcDriverParam->invertOutputClkPhase = inverted; 439 440 return E_OK; 441 } 442 443 /*****************************************************************************/ 444 t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor) 445 { 446 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 447 448 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 449 SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 450 451 p_Rtc->outputClockDivisor = divisor; 452 453 return E_OK; 454 } 455 456 /*****************************************************************************/ 457 t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable) 458 { 459 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 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 p_Rtc->p_RtcDriverParam->pulseRealign = enable; 465 466 return E_OK; 467 } 468 469 /*****************************************************************************/ 470 t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc, 471 uint8_t alarmId, 472 e_FmRtcAlarmPolarity alarmPolarity) 473 { 474 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 475 476 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 477 SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 478 479 if (alarmId >= FM_RTC_NUM_OF_ALARMS) 480 { 481 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID")); 482 } 483 484 p_Rtc->p_RtcDriverParam->alarmPolarity[alarmId] = alarmPolarity; 485 486 return E_OK; 487 } 488 489 /*****************************************************************************/ 490 t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc, 491 uint8_t triggerId, 492 e_FmRtcTriggerPolarity triggerPolarity) 493 { 494 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 495 496 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 497 SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 498 499 if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) 500 { 501 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID")); 502 } 503 504 p_Rtc->p_RtcDriverParam->triggerPolarity[triggerId] = triggerPolarity; 505 506 return E_OK; 507 } 508 509 /*****************************************************************************/ 510 t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock) 511 { 512 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 513 uint32_t tmrCtrl; 514 515 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 516 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 517 518 tmrCtrl = GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl); 519 520 /* TODO A check must be added here, that no timestamping MAC's 521 * are working in this stage. */ 522 if (resetClock) 523 { 524 WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl | TMR_CTRL_TMSR)); 525 526 XX_UDelay(10); 527 /* Clear TMR_OFF */ 528 WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_l, 0); 529 WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_h, 0); 530 } 531 532 WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl | TMR_CTRL_TE)); 533 534 return E_OK; 535 } 536 537 /*****************************************************************************/ 538 t_Error FM_RTC_Disable(t_Handle h_FmRtc) 539 { 540 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 541 uint32_t tmrCtrl; 542 543 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 544 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 545 546 /* TODO A check must be added here, that no timestamping MAC's 547 * are working in this stage. */ 548 tmrCtrl = GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl); 549 WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl & ~(TMR_CTRL_TE))); 550 551 return E_OK; 552 } 553 554 /*****************************************************************************/ 555 t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset) 556 { 557 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 558 559 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 560 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 561 562 /* TMR_OFF_L must be written first */ 563 WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_l, (uint32_t)offset); 564 WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_h, (uint32_t)(offset >> 32)); 565 566 return E_OK; 567 } 568 569 /*****************************************************************************/ 570 t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams) 571 { 572 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 573 t_FmRtcMemMap *p_MemMap; 574 uint32_t tmpReg; 575 uint64_t tmpAlarm; 576 577 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 578 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 579 580 p_MemMap = p_Rtc->p_MemMap; 581 582 if (p_FmRtcAlarmParams->alarmId >= FM_RTC_NUM_OF_ALARMS) 583 { 584 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID")); 585 } 586 587 if(p_FmRtcAlarmParams->alarmTime < p_Rtc->clockPeriodNanoSec) 588 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm time must be equal or larger than RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec)); 589 if(p_FmRtcAlarmParams->alarmTime % (uint64_t)p_Rtc->clockPeriodNanoSec) 590 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm time must be a multiple of RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec)); 591 tmpAlarm = p_FmRtcAlarmParams->alarmTime/(uint64_t)p_Rtc->clockPeriodNanoSec; 592 593 /* TMR_ALARM_L must be written first */ 594 WRITE_UINT32(p_MemMap->tmr_alarm[p_FmRtcAlarmParams->alarmId].tmr_alarm_l, (uint32_t)tmpAlarm); 595 WRITE_UINT32(p_MemMap->tmr_alarm[p_FmRtcAlarmParams->alarmId].tmr_alarm_h, 596 (uint32_t)(tmpAlarm >> 32)); 597 598 if (p_FmRtcAlarmParams->f_AlarmCallback) 599 { 600 p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].f_AlarmCallback = p_FmRtcAlarmParams->f_AlarmCallback; 601 p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].clearOnExpiration = p_FmRtcAlarmParams->clearOnExpiration; 602 603 if(p_FmRtcAlarmParams->alarmId == 0) 604 tmpReg = TMR_TEVENT_ALM1; 605 else 606 tmpReg = TMR_TEVENT_ALM2; 607 WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) | tmpReg); 608 } 609 610 return E_OK; 611 } 612 613 /*****************************************************************************/ 614 t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams) 615 { 616 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 617 t_FmRtcMemMap *p_MemMap; 618 uint32_t tmpReg; 619 uint64_t tmpFiper; 620 621 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 622 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 623 624 p_MemMap = p_Rtc->p_MemMap; 625 626 if (p_FmRtcPeriodicPulseParams->periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES) 627 { 628 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID")); 629 } 630 if(GET_UINT32(p_MemMap->tmr_ctrl) & TMR_CTRL_TE) 631 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Can't set Periodic pulse when RTC is enabled.")); 632 if(p_FmRtcPeriodicPulseParams->periodicPulsePeriod < p_Rtc->clockPeriodNanoSec) 633 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse must be equal or larger than RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec)); 634 if(p_FmRtcPeriodicPulseParams->periodicPulsePeriod % (uint64_t)p_Rtc->clockPeriodNanoSec) 635 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse must be a multiple of RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec)); 636 tmpFiper = p_FmRtcPeriodicPulseParams->periodicPulsePeriod/(uint64_t)p_Rtc->clockPeriodNanoSec; 637 if(tmpFiper & 0xffffffff00000000LL) 638 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse/RTC Period must be smaller than 4294967296", p_Rtc->clockPeriodNanoSec)); 639 640 WRITE_UINT32(p_MemMap->tmr_fiper[p_FmRtcPeriodicPulseParams->periodicPulseId], (uint32_t)tmpFiper); 641 642 if (p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback) 643 { 644 p_Rtc->periodicPulseParams[p_FmRtcPeriodicPulseParams->periodicPulseId].f_PeriodicPulseCallback = 645 p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback; 646 647 if(p_FmRtcPeriodicPulseParams->periodicPulseId == 0) 648 tmpReg = TMR_TEVENT_PP1; 649 else 650 tmpReg = TMR_TEVENT_PP2; 651 WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) | tmpReg); 652 } 653 654 return E_OK; 655 } 656 657 /*****************************************************************************/ 658 t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId) 659 { 660 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 661 uint32_t tmpReg; 662 663 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 664 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 665 666 if (periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES) 667 { 668 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID")); 669 } 670 671 p_Rtc->periodicPulseParams[periodicPulseId].f_PeriodicPulseCallback = NULL; 672 673 if(periodicPulseId == 0) 674 tmpReg = TMR_TEVENT_PP1; 675 else 676 tmpReg = TMR_TEVENT_PP2; 677 WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) & ~tmpReg); 678 679 if (GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & TMR_CTRL_FS) 680 WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & ~TMR_CTRL_FS); 681 682 WRITE_UINT32(p_Rtc->p_MemMap->tmr_fiper[periodicPulseId], 0xFFFFFFFF); 683 684 return E_OK; 685 } 686 687 /*****************************************************************************/ 688 t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams) 689 { 690 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 691 uint32_t tmpReg; 692 693 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 694 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 695 696 if (p_FmRtcExternalTriggerParams->externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) 697 { 698 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID")); 699 } 700 701 if (p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback) 702 { 703 p_Rtc->externalTriggerParams[p_FmRtcExternalTriggerParams->externalTriggerId].f_ExternalTriggerCallback = p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback; 704 if(p_FmRtcExternalTriggerParams->externalTriggerId == 0) 705 tmpReg = TMR_TEVENT_ETS1; 706 else 707 tmpReg = TMR_TEVENT_ETS2; 708 WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) | tmpReg); 709 } 710 711 if(p_FmRtcExternalTriggerParams->usePulseAsInput) 712 { 713 if(p_FmRtcExternalTriggerParams->externalTriggerId == 0) 714 tmpReg = TMR_CTRL_PP1L; 715 else 716 tmpReg = TMR_CTRL_PP2L; 717 WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) | tmpReg); 718 } 719 720 return E_OK; 721 } 722 723 /*****************************************************************************/ 724 t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t externalTriggerId) 725 { 726 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 727 uint32_t tmpReg; 728 729 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 730 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 731 732 if (externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) 733 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID")); 734 735 p_Rtc->externalTriggerParams[externalTriggerId].f_ExternalTriggerCallback = NULL; 736 737 if(externalTriggerId == 0) 738 tmpReg = TMR_TEVENT_ETS1; 739 else 740 tmpReg = TMR_TEVENT_ETS2; 741 WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) & ~tmpReg); 742 743 if(externalTriggerId == 0) 744 tmpReg = TMR_CTRL_PP1L; 745 else 746 tmpReg = TMR_CTRL_PP2L; 747 748 if (GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & tmpReg) 749 WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & ~tmpReg); 750 751 return E_OK; 752 } 753 754 /*****************************************************************************/ 755 t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc, 756 uint8_t triggerId, 757 uint64_t *p_TimeStamp) 758 { 759 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 760 uint64_t timeStamp; 761 762 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 763 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 764 765 if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) 766 { 767 RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID")); 768 } 769 770 timeStamp = (uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_etts[triggerId].tmr_etts_l); 771 timeStamp |= ((uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_etts[triggerId].tmr_etts_h) << 32); 772 773 timeStamp = timeStamp*p_Rtc->clockPeriodNanoSec; 774 *p_TimeStamp = timeStamp; 775 776 return E_OK; 777 } 778 779 /*****************************************************************************/ 780 t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts) 781 { 782 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 783 uint64_t time; 784 785 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 786 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 787 788 /* TMR_CNT_L must be read first to get an accurate value */ 789 time = (uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_cnt_l); 790 time |= ((uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_cnt_h) << 32); 791 792 time = time*p_Rtc->clockPeriodNanoSec; 793 794 *p_Ts = time; 795 796 return E_OK; 797 } 798 799 /*****************************************************************************/ 800 t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts) 801 { 802 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 803 804 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 805 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 806 807 ts = ts/p_Rtc->clockPeriodNanoSec; 808 /* TMR_CNT_L must be written first to get an accurate value */ 809 WRITE_UINT32(p_Rtc->p_MemMap->tmr_cnt_l, (uint32_t)ts); 810 WRITE_UINT32(p_Rtc->p_MemMap->tmr_cnt_h, (uint32_t)(ts >> 32)); 811 812 return E_OK; 813 } 814 815 /*****************************************************************************/ 816 t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation) 817 { 818 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 819 820 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 821 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 822 823 *p_Compensation = (uint32_t) 824 DIV_CEIL(ACCUMULATOR_OVERFLOW * 1000, 825 p_Rtc->clockPeriodNanoSec * p_Rtc->srcClkFreqMhz); 826 827 return E_OK; 828 } 829 830 /*****************************************************************************/ 831 t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation) 832 { 833 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 834 835 SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); 836 SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); 837 838 /* set the new freqCompensation */ 839 WRITE_UINT32(p_Rtc->p_MemMap->tmr_add, freqCompensation); 840 841 return E_OK; 842 } 843 844 /*****************************************************************************/ 845 #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) 846 t_Error FM_RTC_DumpRegs(t_Handle h_FmRtc) 847 { 848 t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; 849 t_FmRtcMemMap *p_MemMap = p_Rtc->p_MemMap; 850 int i = 0; 851 852 DECLARE_DUMP; 853 854 if (p_MemMap) 855 { 856 857 DUMP_TITLE(p_MemMap, ("RTC:")); 858 DUMP_VAR(p_MemMap, tmr_id); 859 DUMP_VAR(p_MemMap, tmr_id2); 860 DUMP_VAR(p_MemMap, tmr_ctrl); 861 DUMP_VAR(p_MemMap, tmr_tevent); 862 DUMP_VAR(p_MemMap, tmr_temask); 863 DUMP_VAR(p_MemMap, tmr_cnt_h); 864 DUMP_VAR(p_MemMap, tmr_cnt_l); 865 DUMP_VAR(p_MemMap, tmr_ctrl); 866 DUMP_VAR(p_MemMap, tmr_add); 867 DUMP_VAR(p_MemMap, tmr_acc); 868 DUMP_VAR(p_MemMap, tmr_prsc); 869 DUMP_VAR(p_MemMap, tmr_off_h); 870 DUMP_VAR(p_MemMap, tmr_off_l); 871 872 DUMP_SUBSTRUCT_ARRAY(i, 2) 873 { 874 DUMP_VAR(p_MemMap, tmr_alarm[i].tmr_alarm_h); 875 DUMP_VAR(p_MemMap, tmr_alarm[i].tmr_alarm_l); 876 } 877 DUMP_SUBSTRUCT_ARRAY(i, 2) 878 { 879 DUMP_VAR(p_MemMap, tmr_fiper[i]); 880 DUMP_VAR(p_MemMap, tmr_fiper[i]); 881 } 882 DUMP_SUBSTRUCT_ARRAY(i, 2) 883 { 884 DUMP_VAR(p_MemMap, tmr_etts[i].tmr_etts_l); 885 DUMP_VAR(p_MemMap, tmr_etts[i].tmr_etts_l); 886 } 887 } 888 889 return E_OK; 890 } 891 #endif /* (defined(DEBUG_ERRORS) && ... */ 892