Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/ncsw/Peripherals/FM/Rtc/fm_rtc.c
48417 views
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
694