1/*
2 * Copyright 2013 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#ifndef __FSL_FMAN_RTC_H
34#define __FSL_FMAN_RTC_H
35
36#include "common/general.h"
37
38/* FM RTC Registers definitions */
39#define FMAN_RTC_TMR_CTRL_ALMP1                  0x80000000
40#define FMAN_RTC_TMR_CTRL_ALMP2                  0x40000000
41#define FMAN_RTC_TMR_CTRL_FS                     0x10000000
42#define FMAN_RTC_TMR_CTRL_PP1L                   0x08000000
43#define FMAN_RTC_TMR_CTRL_PP2L                   0x04000000
44#define FMAN_RTC_TMR_CTRL_TCLK_PERIOD_MASK       0x03FF0000
45#define FMAN_RTC_TMR_CTRL_FRD                    0x00004000
46#define FMAN_RTC_TMR_CTRL_SLV                    0x00002000
47#define FMAN_RTC_TMR_CTRL_ETEP1                  0x00000100
48#define FMAN_RTC_TMR_CTRL_COPH                   0x00000080
49#define FMAN_RTC_TMR_CTRL_CIPH                   0x00000040
50#define FMAN_RTC_TMR_CTRL_TMSR                   0x00000020
51#define FMAN_RTC_TMR_CTRL_DBG                    0x00000010
52#define FMAN_RTC_TMR_CTRL_BYP                    0x00000008
53#define FMAN_RTC_TMR_CTRL_TE                     0x00000004
54#define FMAN_RTC_TMR_CTRL_CKSEL_OSC_CLK          0x00000003
55#define FMAN_RTC_TMR_CTRL_CKSEL_MAC_CLK          0x00000001
56#define FMAN_RTC_TMR_CTRL_CKSEL_EXT_CLK          0x00000000
57#define FMAN_RTC_TMR_CTRL_TCLK_PERIOD_SHIFT      16
58
59#define FMAN_RTC_TMR_TEVENT_ETS2                 0x02000000
60#define FMAN_RTC_TMR_TEVENT_ETS1                 0x01000000
61#define FMAN_RTC_TMR_TEVENT_ALM2                 0x00020000
62#define FMAN_RTC_TMR_TEVENT_ALM1                 0x00010000
63#define FMAN_RTC_TMR_TEVENT_PP1                  0x00000080
64#define FMAN_RTC_TMR_TEVENT_PP2                  0x00000040
65#define FMAN_RTC_TMR_TEVENT_PP3                  0x00000020
66#define FMAN_RTC_TMR_TEVENT_ALL                  (FMAN_RTC_TMR_TEVENT_ETS2 |\
67						FMAN_RTC_TMR_TEVENT_ETS1 |\
68						FMAN_RTC_TMR_TEVENT_ALM2 |\
69						FMAN_RTC_TMR_TEVENT_ALM1 |\
70						FMAN_RTC_TMR_TEVENT_PP1 |\
71						FMAN_RTC_TMR_TEVENT_PP2 |\
72						FMAN_RTC_TMR_TEVENT_PP3)
73
74#define FMAN_RTC_TMR_PRSC_OCK_MASK               0x0000FFFF
75
76/**************************************************************************//**
77 @Description   FM RTC Alarm Polarity Options.
78*//***************************************************************************/
79enum fman_rtc_alarm_polarity {
80    E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH,  /**< Active-high output polarity */
81    E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW    /**< Active-low output polarity */
82};
83
84/**************************************************************************//**
85 @Description   FM RTC Trigger Polarity Options.
86*//***************************************************************************/
87enum fman_rtc_trigger_polarity {
88    E_FMAN_RTC_TRIGGER_ON_RISING_EDGE,    /**< Trigger on rising edge */
89    E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE    /**< Trigger on falling edge */
90};
91
92/**************************************************************************//**
93 @Description   IEEE1588 Timer Module FM RTC Optional Clock Sources.
94*//***************************************************************************/
95enum fman_src_clock {
96    E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL,  /**< external high precision timer
97						reference clock */
98    E_FMAN_RTC_SOURCE_CLOCK_SYSTEM,    /**< MAC system clock */
99    E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR  /**< RTC clock oscilator */
100};
101
102/* RTC default values */
103#define DEFAULT_SRC_CLOCK                E_FMAN_RTC_SOURCE_CLOCK_SYSTEM
104#define DEFAULT_INVERT_INPUT_CLK_PHASE   FALSE
105#define DEFAULT_INVERT_OUTPUT_CLK_PHASE  FALSE
106#define DEFAULT_ALARM_POLARITY           E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH
107#define DEFAULT_TRIGGER_POLARITY         E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE
108#define DEFAULT_PULSE_REALIGN            FALSE
109
110#define FMAN_RTC_MAX_NUM_OF_ALARMS 3
111#define FMAN_RTC_MAX_NUM_OF_PERIODIC_PULSES 4
112#define FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS 3
113
114/**************************************************************************//**
115 @Description FM RTC timer alarm
116*//***************************************************************************/
117struct t_tmr_alarm{
118    uint32_t   tmr_alarm_h;    /**<  */
119    uint32_t   tmr_alarm_l;    /**<  */
120};
121
122/**************************************************************************//**
123 @Description FM RTC timer Ex trigger
124*//***************************************************************************/
125struct t_tmr_ext_trigger{
126    uint32_t   tmr_etts_h;     /**<  */
127    uint32_t   tmr_etts_l;     /**<  */
128};
129
130struct rtc_regs {
131    uint32_t tmr_id;      /* 0x000 Module ID register */
132    uint32_t tmr_id2;     /* 0x004 Controller ID register */
133    uint32_t reserved0008[30];
134    uint32_t tmr_ctrl;    /* 0x0080 timer control register */
135    uint32_t tmr_tevent;  /* 0x0084 timer event register */
136    uint32_t tmr_temask;  /* 0x0088 timer event mask register */
137    uint32_t reserved008c[3];
138    uint32_t tmr_cnt_h;   /* 0x0098 timer counter high register */
139    uint32_t tmr_cnt_l;   /* 0x009c timer counter low register */
140    uint32_t tmr_add;     /* 0x00a0 timer drift compensation addend register */
141    uint32_t tmr_acc;     /* 0x00a4 timer accumulator register */
142    uint32_t tmr_prsc;    /* 0x00a8 timer prescale */
143    uint32_t reserved00ac;
144    uint32_t tmr_off_h;    /* 0x00b0 timer offset high */
145    uint32_t tmr_off_l;    /* 0x00b4 timer offset low  */
146    struct t_tmr_alarm tmr_alarm[FMAN_RTC_MAX_NUM_OF_ALARMS]; /* 0x00b8 timer
147								alarm */
148    uint32_t tmr_fiper[FMAN_RTC_MAX_NUM_OF_PERIODIC_PULSES]; /* 0x00d0 timer
149						fixed period interval */
150    struct t_tmr_ext_trigger tmr_etts[FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS];
151			/* 0x00e0 time stamp general purpose external */
152    uint32_t reserved00f0[4];
153};
154
155struct rtc_cfg {
156    enum fman_src_clock            src_clk;
157    uint32_t                ext_src_clk_freq;
158    uint32_t                rtc_freq_hz;
159    bool                    timer_slave_mode;
160    bool                    invert_input_clk_phase;
161    bool                    invert_output_clk_phase;
162    uint32_t                events_mask;
163    bool                    bypass; /**< Indicates if frequency compensation
164					is bypassed */
165    bool                    pulse_realign;
166    enum fman_rtc_alarm_polarity    alarm_polarity[FMAN_RTC_MAX_NUM_OF_ALARMS];
167    enum fman_rtc_trigger_polarity  trigger_polarity
168					[FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS];
169};
170
171/**
172 * fman_rtc_defconfig() - Get default RTC configuration
173 * @cfg:	pointer to configuration structure.
174 *
175 * Call this function to obtain a default set of configuration values for
176 * initializing RTC.  The user can overwrite any of the values before calling
177 * fman_rtc_init(), if specific configuration needs to be applied.
178 */
179void fman_rtc_defconfig(struct rtc_cfg *cfg);
180
181/**
182 * fman_rtc_get_events() - Get the events
183 * @regs:		Pointer to RTC register block
184 *
185 * Returns: The events
186 */
187uint32_t fman_rtc_get_events(struct rtc_regs *regs);
188
189/**
190 * fman_rtc_get_interrupt_mask() - Get the events mask
191 * @regs:		Pointer to RTC register block
192 *
193 * Returns: The events mask
194 */
195uint32_t fman_rtc_get_interrupt_mask(struct rtc_regs *regs);
196
197
198/**
199 * fman_rtc_set_interrupt_mask() - Set the events mask
200 * @regs:		Pointer to RTC register block
201 * @mask:		The mask to set
202 */
203void fman_rtc_set_interrupt_mask(struct rtc_regs *regs, uint32_t mask);
204
205/**
206 * fman_rtc_get_event() - Check if specific events occurred
207 * @regs:		Pointer to RTC register block
208 * @ev_mask:	a mask of the events to check
209 *
210 * Returns: 0 if the events did not occur. Non zero if one of the events occurred
211 */
212uint32_t fman_rtc_get_event(struct rtc_regs *regs, uint32_t ev_mask);
213
214/**
215 * fman_rtc_check_and_clear_event() - Clear events which are on
216 * @regs:		Pointer to RTC register block
217 *
218 * Returns: A mask of the events which were cleared
219 */
220uint32_t fman_rtc_check_and_clear_event(struct rtc_regs *regs);
221
222/**
223 * fman_rtc_ack_event() - Clear events
224 * @regs:		Pointer to RTC register block
225 * @events:		The events to disable
226 */
227void fman_rtc_ack_event(struct rtc_regs *regs, uint32_t events);
228
229/**
230 * fman_rtc_enable_interupt() - Enable events interrupts
231 * @regs:		Pointer to RTC register block
232 * @mask:		The events to disable
233 */
234void fman_rtc_enable_interupt(struct rtc_regs *regs, uint32_t mask);
235
236/**
237 * fman_rtc_disable_interupt() - Disable events interrupts
238 * @regs:		Pointer to RTC register block
239 * @mask:		The events to disable
240 */
241void fman_rtc_disable_interupt(struct rtc_regs *regs, uint32_t mask);
242
243/**
244 * fman_rtc_get_timer_ctrl() - Get the control register
245 * @regs:		Pointer to RTC register block
246 *
247 * Returns: The control register value
248 */
249uint32_t fman_rtc_get_timer_ctrl(struct rtc_regs *regs);
250
251/**
252 * fman_rtc_set_timer_ctrl() - Set timer control register
253 * @regs:		Pointer to RTC register block
254 * @val:		The value to set
255 */
256void fman_rtc_set_timer_ctrl(struct rtc_regs *regs, uint32_t val);
257
258/**
259 * fman_rtc_get_frequency_compensation() - Get the frequency compensation
260 * @regs:		Pointer to RTC register block
261 *
262 * Returns: The timer counter
263 */
264uint32_t fman_rtc_get_frequency_compensation(struct rtc_regs *regs);
265
266/**
267 * fman_rtc_set_frequency_compensation() - Set frequency compensation
268 * @regs:		Pointer to RTC register block
269 * @val:		The value to set
270 */
271void fman_rtc_set_frequency_compensation(struct rtc_regs *regs, uint32_t val);
272
273/**
274 * fman_rtc_get_trigger_stamp() - Get a trigger stamp
275 * @regs:		Pointer to RTC register block
276 * @id:	The id of the trigger stamp
277 *
278 * Returns: The time stamp
279 */
280uint64_t fman_rtc_get_trigger_stamp(struct rtc_regs *regs,  int id);
281
282/**
283 * fman_rtc_set_timer_alarm_l() - Set timer alarm low register
284 * @regs:		Pointer to RTC register block
285 * @index:		The index of alarm to set
286 * @val:		The value to set
287 */
288void fman_rtc_set_timer_alarm_l(struct rtc_regs *regs, int index,
289		uint32_t val);
290
291/**
292 * fman_rtc_set_timer_alarm() - Set timer alarm
293 * @regs:		Pointer to RTC register block
294 * @index:		The index of alarm to set
295 * @val:		The value to set
296 */
297void fman_rtc_set_timer_alarm(struct rtc_regs *regs, int index, int64_t val);
298
299/**
300 * fman_rtc_set_timer_fiper() - Set timer fiper
301 * @regs:		Pointer to RTC register block
302 * @index:		The index of fiper to set
303 * @val:		The value to set
304 */
305void fman_rtc_set_timer_fiper(struct rtc_regs *regs, int index, uint32_t val);
306
307/**
308 * fman_rtc_set_timer_offset() - Set timer offset
309 * @regs:		Pointer to RTC register block
310 * @val:		The value to set
311 */
312void fman_rtc_set_timer_offset(struct rtc_regs *regs, int64_t val);
313
314/**
315 * fman_rtc_get_timer() - Get the timer counter
316 * @regs:		Pointer to RTC register block
317 *
318 * Returns: The timer counter
319 */
320static inline uint64_t fman_rtc_get_timer(struct rtc_regs *regs)
321{
322	uint64_t time;
323    /* TMR_CNT_L must be read first to get an accurate value */
324    time = (uint64_t)ioread32be(&regs->tmr_cnt_l);
325    time |= ((uint64_t)ioread32be(&regs->tmr_cnt_h) << 32);
326
327    return time;
328}
329
330/**
331 * fman_rtc_set_timer() - Set timer counter
332 * @regs:		Pointer to RTC register block
333 * @val:		The value to set
334 */
335static inline void fman_rtc_set_timer(struct rtc_regs *regs, int64_t val)
336{
337	iowrite32be((uint32_t)val, &regs->tmr_cnt_l);
338	iowrite32be((uint32_t)(val >> 32), &regs->tmr_cnt_h);
339}
340
341/**
342 * fman_rtc_timers_soft_reset() - Soft reset
343 * @regs:		Pointer to RTC register block
344 *
345 * Resets all the timer registers and state machines for the 1588 IP and
346 * the attached client 1588
347 */
348void fman_rtc_timers_soft_reset(struct rtc_regs *regs);
349
350/**
351 * fman_rtc_clear_external_trigger() - Clear an external trigger
352 * @regs:		Pointer to RTC register block
353 * @id: The id of the trigger to clear
354 */
355void fman_rtc_clear_external_trigger(struct rtc_regs *regs, int id);
356
357/**
358 * fman_rtc_clear_periodic_pulse() - Clear periodic pulse
359 * @regs:		Pointer to RTC register block
360 * @id: The id of the fiper to clear
361 */
362void fman_rtc_clear_periodic_pulse(struct rtc_regs *regs, int id);
363
364/**
365 * fman_rtc_enable() - Enable RTC hardware block
366 * @regs:		Pointer to RTC register block
367 */
368void fman_rtc_enable(struct rtc_regs *regs, bool reset_clock);
369
370/**
371 * fman_rtc_is_enabled() - Is RTC hardware block enabled
372 * @regs:		Pointer to RTC register block
373 *
374 * Return: TRUE if enabled
375 */
376bool fman_rtc_is_enabled(struct rtc_regs *regs);
377
378/**
379 * fman_rtc_disable() - Disable RTC hardware block
380 * @regs:		Pointer to RTC register block
381 */
382void fman_rtc_disable(struct rtc_regs *regs);
383
384/**
385 * fman_rtc_init() - Init RTC hardware block
386 * @cfg:		RTC configuration data
387 * @regs:		Pointer to RTC register block
388 * @num_alarms:		Number of alarms in RTC
389 * @num_fipers:		Number of fipers in RTC
390 * @num_ext_triggers:	Number of external triggers in RTC
391 * @freq_compensation:		Frequency compensation
392 * @output_clock_divisor:		Output clock divisor
393 *
394 * This function initializes RTC and applies basic configuration.
395 */
396void fman_rtc_init(struct rtc_cfg *cfg, struct rtc_regs *regs, int num_alarms,
397		int num_fipers, int num_ext_triggers, bool init_freq_comp,
398		uint32_t freq_compensation, uint32_t output_clock_divisor);
399
400/**
401 * fman_rtc_set_alarm() - Set an alarm
402 * @regs:		Pointer to RTC register block
403 * @id:			id of alarm
404 * @val:		value to write
405 * @enable:		should interrupt be enabled
406 */
407void fman_rtc_set_alarm(struct rtc_regs *regs, int id, uint32_t val, bool enable);
408
409/**
410 * fman_rtc_set_periodic_pulse() - Set an alarm
411 * @regs:		Pointer to RTC register block
412 * @id:			id of fiper
413 * @val:		value to write
414 * @enable:		should interrupt be enabled
415 */
416void fman_rtc_set_periodic_pulse(struct rtc_regs *regs, int id, uint32_t val,
417	bool enable);
418
419/**
420 * fman_rtc_set_ext_trigger() - Set an external trigger
421 * @regs:		Pointer to RTC register block
422 * @id:			id of trigger
423 * @enable:		should interrupt be enabled
424 * @use_pulse_as_input: use the pulse as input
425 */
426void fman_rtc_set_ext_trigger(struct rtc_regs *regs, int id, bool enable,
427	bool use_pulse_as_input);
428
429struct fm_rtc_alarm_params {
430	uint8_t alarm_id;            	/**< 0 or 1 */
431	uint64_t alarm_time;         	/**< In nanoseconds, the time when the
432					alarm should go off - must be a
433					multiple of the RTC period */
434	void (*f_alarm_callback)(void* app, uint8_t id); /**< This routine will
435					be called when RTC reaches alarmTime */
436	bool clear_on_expiration;   	/**< TRUE to turn off the alarm once
437					expired.*/
438};
439
440struct fm_rtc_periodic_pulse_params {
441	uint8_t periodic_pulse_id;      /**< 0 or 1 */
442	uint64_t periodic_pulse_period; /**< In Nanoseconds. Must be a multiple
443					of the RTC period */
444	void (*f_periodic_pulse_callback)(void* app, uint8_t id); /**< This
445					routine will be called every
446					periodicPulsePeriod. */
447};
448
449#endif /* __FSL_FMAN_RTC_H */
450