]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/ttcps_v3_2/src/xttcps.c
xTaskGenericNotify() now sets xYieldPending to pdTRUE even when the 'higher priority...
[freertos] / FreeRTOS / Demo / CORTEX_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / ttcps_v3_2 / src / xttcps.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2015 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xttcps.c
36 * @addtogroup ttcps_v3_0
37 * @{
38 *
39 * This file contains the implementation of the XTtcPs driver. This driver
40 * controls the operation of one timer counter in the Triple Timer Counter (TTC)
41 * module in the Ps block. Refer to xttcps.h for more detailed description
42 * of the driver.
43 *
44 * <pre>
45 * MODIFICATION HISTORY:
46 *
47 * Ver   Who    Date     Changes
48 * ----- ------ -------- -------------------------------------------------
49 * 1.00a drg/jz 01/21/10 First release
50 * 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
51 * 3.01  pkp        01/30/16 Modified XTtcPs_CfgInitialize to add XTtcps_Stop
52 *                                               to stop the timer before configuring
53 * 3.2   mus    10/28/16 Modified XTtcPs_CalcIntervalFromFreq to calculate
54 *                       32 bit interval count for zynq ultrascale+mpsoc
55 *
56 * </pre>
57 *
58 ******************************************************************************/
59
60 /***************************** Include Files *********************************/
61
62 #include "xttcps.h"
63
64 /************************** Constant Definitions *****************************/
65
66 /**************************** Type Definitions *******************************/
67
68 /***************** Macros (Inline Functions) Definitions *********************/
69
70 /************************** Function Prototypes ******************************/
71
72 /************************** Variable Definitions *****************************/
73
74
75 /*****************************************************************************/
76 /**
77 *
78 * Initializes a specific XTtcPs instance such that the driver is ready to use.
79 * This function initializes a single timer counter in the triple timer counter
80 * function block.
81 *
82 * The state of the device after initialization is:
83 *  - Overflow Mode
84 *  - Internal (pclk) selected
85 *  - Counter disabled
86 *  - All Interrupts disabled
87 *  - Output waveforms disabled
88 *
89 * @param        InstancePtr is a pointer to the XTtcPs instance.
90 * @param        ConfigPtr is a reference to a structure containing information
91 *               about a specific TTC device.
92 * @param        EffectiveAddr is the device base address in the virtual memory
93 *               address space. The caller is responsible for keeping the address
94 *               mapping from EffectiveAddr to the device physical base address
95 *               unchanged once this function is invoked. Unexpected errors may
96 *               occur if the address mapping changes after this function is
97 *               called. If address translation is not used, then use
98 *               ConfigPtr->BaseAddress for this parameter, passing the physical
99 *               address instead.
100 *
101 * @return
102 *
103 *               - XST_SUCCESS if the initialization is successful.
104 *               - XST_DEVICE_IS_STARTED if the device is started. It must be
105 *                 stopped to re-initialize.
106 *
107 * @note         Device has to be stopped first to call this function to
108 *               initialize it.
109 *
110 ******************************************************************************/
111 s32 XTtcPs_CfgInitialize(XTtcPs *InstancePtr, XTtcPs_Config *ConfigPtr,
112                               u32 EffectiveAddr)
113 {
114         s32 Status;
115         u32 IsStartResult;
116         /*
117          * Assert to validate input arguments.
118          */
119         Xil_AssertNonvoid(InstancePtr != NULL);
120         Xil_AssertNonvoid(ConfigPtr != NULL);
121
122         /*
123          * Set some default values
124          */
125         InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
126         InstancePtr->Config.BaseAddress = EffectiveAddr;
127         InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
128
129         IsStartResult = XTtcPs_IsStarted(InstancePtr);
130         /*
131          * If the timer counter has already started, return an error
132          * Device should be stopped first.
133          */
134         if(IsStartResult == (u32)TRUE) {
135                 Status = XST_DEVICE_IS_STARTED;
136         } else {
137
138                 /*
139                  * stop the timer before configuring
140                  */
141                 XTtcPs_Stop(InstancePtr);
142                 /*
143                  * Reset the count control register to it's default value.
144                  */
145                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
146                                   XTTCPS_CNT_CNTRL_OFFSET,
147                                   XTTCPS_CNT_CNTRL_RESET_VALUE);
148
149                 /*
150                  * Reset the rest of the registers to the default values.
151                  */
152                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
153                                   XTTCPS_CLK_CNTRL_OFFSET, 0x00U);
154                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
155                                   XTTCPS_INTERVAL_VAL_OFFSET, 0x00U);
156                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
157                                   XTTCPS_MATCH_1_OFFSET, 0x00U);
158                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
159                                   XTTCPS_MATCH_2_OFFSET, 0x00U);
160                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
161                                   XTTCPS_MATCH_2_OFFSET, 0x00U);
162                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
163                                   XTTCPS_IER_OFFSET, 0x00U);
164                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
165                                   XTTCPS_ISR_OFFSET, XTTCPS_IXR_ALL_MASK);
166
167                 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
168
169                 /*
170                  * Reset the counter value
171                  */
172                 XTtcPs_ResetCounterValue(InstancePtr);
173                 Status = XST_SUCCESS;
174         }
175         return Status;
176 }
177
178 /*****************************************************************************/
179 /**
180 *
181 * This function is used to set the match registers. There are three match
182 * registers.
183 *
184 * The match 0 register is special. If the waveform output mode is enabled, the
185 * waveform will change polarity when the count matches the value in the match 0
186 * register. The polarity of the waveform output can also be set using the
187 * XTtcPs_SetOptions() function.
188 *
189 * @param        InstancePtr is a pointer to the XTtcPs instance.
190 * @param        MatchIndex is the index to the match register to be set.
191 *               Valid values are 0, 1, or 2.
192 * @param        Value is the 16-bit value to be set in the match register.
193 *
194 * @return       None
195 *
196 * @note         None
197 *
198 ****************************************************************************/
199 void XTtcPs_SetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex, u16 Value)
200 {
201         /*
202          * Assert to validate input arguments.
203          */
204         Xil_AssertVoid(InstancePtr != NULL);
205         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
206         Xil_AssertVoid(MatchIndex < (u8)XTTCPS_NUM_MATCH_REG);
207
208         /*
209          * Write the value to the correct match register with MatchIndex
210          */
211         XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
212                           XTtcPs_Match_N_Offset(MatchIndex), Value);
213 }
214
215 /*****************************************************************************/
216 /**
217 *
218 * This function is used to get the value of the match registers. There are
219 * three match registers.
220 *
221 * @param        InstancePtr is a pointer to the XTtcPs instance.
222 * @param        MatchIndex is the index to the match register to be set.
223 *               Valid values are 0, 1, or 2.
224 *
225 * @return       None
226 *
227 * @note         None
228 *
229 ****************************************************************************/
230 u16 XTtcPs_GetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex)
231 {
232         u32 MatchReg;
233
234         /*
235          * Assert to validate input arguments.
236          */
237         Xil_AssertNonvoid(InstancePtr != NULL);
238         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
239         Xil_AssertNonvoid(MatchIndex < XTTCPS_NUM_MATCH_REG);
240
241         MatchReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
242                             XTtcPs_Match_N_Offset(MatchIndex));
243
244         return (u16) MatchReg;
245 }
246
247 /*****************************************************************************/
248 /**
249 *
250 * This function sets the prescaler enable bit and if needed sets the prescaler
251 * bits in the control register.
252 *
253 * @param        InstancePtr is a pointer to the XTtcPs instance.
254 * @param        PrescalerValue is a number from 0-16 that sets the prescaler
255 *               to use.
256 *               If the parameter is 0 - 15, use a prescaler on the clock of
257 *               2^(PrescalerValue+1), or 2-65536.
258 *               If the parameter is XTTCPS_CLK_CNTRL_PS_DISABLE, do not use a
259 *               prescaler.
260 *
261 * @return       None
262 *
263 * @note         None
264 *
265 ****************************************************************************/
266 void XTtcPs_SetPrescaler(XTtcPs *InstancePtr, u8 PrescalerValue)
267 {
268         u32 ClockReg;
269
270         /*
271          * Assert to validate input arguments.
272          */
273         Xil_AssertVoid(InstancePtr != NULL);
274         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
275         Xil_AssertVoid(PrescalerValue <= XTTCPS_CLK_CNTRL_PS_DISABLE);
276
277         /*
278          * Read the clock control register
279          */
280         ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
281                            XTTCPS_CLK_CNTRL_OFFSET);
282
283         /*
284          * Clear all of the prescaler control bits in the register
285          */
286         ClockReg &=
287                 ~(XTTCPS_CLK_CNTRL_PS_VAL_MASK | XTTCPS_CLK_CNTRL_PS_EN_MASK);
288
289         if (PrescalerValue < XTTCPS_CLK_CNTRL_PS_DISABLE) {
290                 /*
291                  * Set the prescaler value and enable prescaler
292                  */
293                 ClockReg |= (u32)(((u32)PrescalerValue << (u32)XTTCPS_CLK_CNTRL_PS_VAL_SHIFT) &
294                         (u32)XTTCPS_CLK_CNTRL_PS_VAL_MASK);
295                 ClockReg |= (u32)XTTCPS_CLK_CNTRL_PS_EN_MASK;
296         }
297
298         /*
299          * Write the register with the new values.
300          */
301         XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
302                           XTTCPS_CLK_CNTRL_OFFSET, ClockReg);
303 }
304
305 /*****************************************************************************/
306 /**
307 *
308 * This function gets the input clock prescaler
309 *
310 * @param        InstancePtr is a pointer to the XTtcPs instance.
311 *
312 * <pre>
313 * @return       The value(n) from which the prescalar value is calculated
314 *               as 2^(n+1). Some example values are given below :
315 *
316 *       Value           Prescaler
317 *       0               2
318 *       1               4
319 *       N               2^(n+1)
320 *       15              65536
321 *       16              1
322 * </pre>
323 *
324 * @note         None.
325 *
326 ****************************************************************************/
327 u8 XTtcPs_GetPrescaler(XTtcPs *InstancePtr)
328 {
329         u8 Status;
330         u32 ClockReg;
331
332         /*
333          * Assert to validate input arguments.
334          */
335         Xil_AssertNonvoid(InstancePtr != NULL);
336         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
337
338         /*
339          * Read the clock control register
340          */
341         ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
342                                     XTTCPS_CLK_CNTRL_OFFSET);
343
344         if (0 == (ClockReg & XTTCPS_CLK_CNTRL_PS_EN_MASK)) {
345                 /*
346                  * Prescaler is disabled. Return the correct flag value
347                  */
348                 Status = (u8)XTTCPS_CLK_CNTRL_PS_DISABLE;
349         }
350         else {
351
352                 Status = (u8)((ClockReg & (u32)XTTCPS_CLK_CNTRL_PS_VAL_MASK) >>
353                         (u32)XTTCPS_CLK_CNTRL_PS_VAL_SHIFT);
354         }
355         return Status;
356 }
357
358 /*****************************************************************************/
359 /**
360 *
361 * This function calculates the interval value as well as the prescaler value
362 * for a given frequency.
363 *
364 * @param        InstancePtr is a pointer to the XTtcPs instance.
365 * @param        Freq is the requested output frequency for the device.
366 * @param        Interval is the interval value for the given frequency,
367 *               it is the output value for this function.
368 * @param        Prescaler is the prescaler value for the given frequency,
369 *               it is the output value for this function.
370 *
371 * @return       None.
372 *
373 * @note
374 *  Upon successful calculation for the given frequency, Interval and Prescaler
375 *  carry the settings for the timer counter; Upon unsuccessful calculation,
376 *  Interval and Prescaler are set to 0xFF(FF) for their maximum values to
377 *  signal the caller of failure. Therefore, caller needs to check the return
378 *  interval or prescaler values for whether the function has succeeded.
379 *
380 ****************************************************************************/
381 void XTtcPs_CalcIntervalFromFreq(XTtcPs *InstancePtr, u32 Freq,
382         XInterval *Interval, u8 *Prescaler)
383 {
384         u8 TmpPrescaler;
385         u32 TempValue;
386         u32 InputClock;
387
388         InputClock = InstancePtr->Config.InputClockHz;
389         /*
390          * Find the smallest prescaler that will work for a given frequency. The
391          * smaller the prescaler, the larger the count and the more accurate the
392          *  PWM setting.
393          */
394         TempValue = InputClock/ Freq;
395
396         if (TempValue < 4U) {
397                 /*
398                  * The frequency is too high, it is too close to the input
399                  * clock value. Use maximum values to signal caller.
400                  */
401                 *Interval = XTTCPS_MAX_INTERVAL_COUNT;
402                 *Prescaler = 0xFFU;
403                 return;
404         }
405
406         /*
407          * First, do we need a prescaler or not?
408          */
409         if (((u32)65536U) > TempValue) {
410                 /*
411                  * We do not need a prescaler, so set the values appropriately
412                  */
413                 *Interval = (XInterval)TempValue;
414                 *Prescaler = XTTCPS_CLK_CNTRL_PS_DISABLE;
415                 return;
416         }
417
418
419         for (TmpPrescaler = 0U; TmpPrescaler < XTTCPS_CLK_CNTRL_PS_DISABLE;
420              TmpPrescaler++) {
421                 TempValue =     InputClock/ (Freq * (1U << (TmpPrescaler + 1U)));
422
423                 /*
424                  * The first value less than 2^16 is the best bet
425                  */
426                 if (((u32)65536U) > TempValue) {
427                         /*
428                          * Set the values appropriately
429                          */
430                         *Interval = (XInterval)TempValue;
431                         *Prescaler = TmpPrescaler;
432                         return;
433                 }
434         }
435
436         /* Can not find interval values that work for the given frequency.
437          * Return maximum values to signal caller.
438          */
439         *Interval = XTTCPS_MAX_INTERVAL_COUNT;
440         *Prescaler = 0XFFU;
441         return;
442 }
443 /** @} */