]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A53_64-bit_UltraScale_MPSoC/RTOSDemo_A53_bsp/psu_cortexa53_0/libsrc/ttcps_v3_5/src/xttcps.c
Update Zynq, MPSoc Cortex-A53 and MPSoc Cortex-R5 demo projects to build with the...
[freertos] / FreeRTOS / Demo / CORTEX_A53_64-bit_UltraScale_MPSoC / RTOSDemo_A53_bsp / psu_cortexa53_0 / libsrc / ttcps_v3_5 / src / xttcps.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2017 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_5
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 * 3.5   srm    10/06/17 Updated XTtcPs_GetMatchValue and XTtcPs_SetMatchValue
56 *                       APIs to use correct match register width for zynq
57 *                       (i.e. 16 bit) and zynq ultrascale+mpsoc (i.e. 32 bit).
58 *                       It fixes CR# 986617
59 * </pre>
60 *
61 ******************************************************************************/
62
63 /***************************** Include Files *********************************/
64
65 #include "xttcps.h"
66
67 /************************** Constant Definitions *****************************/
68
69 /**************************** Type Definitions *******************************/
70
71 /***************** Macros (Inline Functions) Definitions *********************/
72
73 /************************** Function Prototypes ******************************/
74
75 /************************** Variable Definitions *****************************/
76
77
78 /*****************************************************************************/
79 /**
80 *
81 * Initializes a specific XTtcPs instance such that the driver is ready to use.
82 * This function initializes a single timer counter in the triple timer counter
83 * function block.
84 *
85 * The state of the device after initialization is:
86 *  - Overflow Mode
87 *  - Internal (pclk) selected
88 *  - Counter disabled
89 *  - All Interrupts disabled
90 *  - Output waveforms disabled
91 *
92 * @param        InstancePtr is a pointer to the XTtcPs instance.
93 * @param        ConfigPtr is a reference to a structure containing information
94 *               about a specific TTC device.
95 * @param        EffectiveAddr is the device base address in the virtual memory
96 *               address space. The caller is responsible for keeping the address
97 *               mapping from EffectiveAddr to the device physical base address
98 *               unchanged once this function is invoked. Unexpected errors may
99 *               occur if the address mapping changes after this function is
100 *               called. If address translation is not used, then use
101 *               ConfigPtr->BaseAddress for this parameter, passing the physical
102 *               address instead.
103 *
104 * @return
105 *
106 *               - XST_SUCCESS if the initialization is successful.
107 *               - XST_DEVICE_IS_STARTED if the device is started. It must be
108 *                 stopped to re-initialize.
109 *
110 * @note         Device has to be stopped first to call this function to
111 *               initialize it.
112 *
113 ******************************************************************************/
114 s32 XTtcPs_CfgInitialize(XTtcPs *InstancePtr, XTtcPs_Config *ConfigPtr,
115                               u32 EffectiveAddr)
116 {
117         s32 Status;
118         u32 IsStartResult;
119         /*
120          * Assert to validate input arguments.
121          */
122         Xil_AssertNonvoid(InstancePtr != NULL);
123         Xil_AssertNonvoid(ConfigPtr != NULL);
124
125         /*
126          * Set some default values
127          */
128         InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
129         InstancePtr->Config.BaseAddress = EffectiveAddr;
130         InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
131
132         IsStartResult = XTtcPs_IsStarted(InstancePtr);
133         /*
134          * If the timer counter has already started, return an error
135          * Device should be stopped first.
136          */
137         if(IsStartResult == (u32)TRUE) {
138                 Status = XST_DEVICE_IS_STARTED;
139         } else {
140
141                 /*
142                  * stop the timer before configuring
143                  */
144                 XTtcPs_Stop(InstancePtr);
145                 /*
146                  * Reset the count control register to it's default value.
147                  */
148                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
149                                   XTTCPS_CNT_CNTRL_OFFSET,
150                                   XTTCPS_CNT_CNTRL_RESET_VALUE);
151
152                 /*
153                  * Reset the rest of the registers to the default values.
154                  */
155                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
156                                   XTTCPS_CLK_CNTRL_OFFSET, 0x00U);
157                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
158                                   XTTCPS_INTERVAL_VAL_OFFSET, 0x00U);
159                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
160                                   XTTCPS_MATCH_1_OFFSET, 0x00U);
161                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
162                                   XTTCPS_MATCH_2_OFFSET, 0x00U);
163                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
164                                   XTTCPS_MATCH_2_OFFSET, 0x00U);
165                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
166                                   XTTCPS_IER_OFFSET, 0x00U);
167                 XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
168                                   XTTCPS_ISR_OFFSET, XTTCPS_IXR_ALL_MASK);
169
170                 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
171
172                 /*
173                  * Reset the counter value
174                  */
175                 XTtcPs_ResetCounterValue(InstancePtr);
176                 Status = XST_SUCCESS;
177         }
178         return Status;
179 }
180
181 /*****************************************************************************/
182 /**
183 *
184 * This function is used to set the match registers. There are three match
185 * registers.
186 *
187 * The match 0 register is special. If the waveform output mode is enabled, the
188 * waveform will change polarity when the count matches the value in the match 0
189 * register. The polarity of the waveform output can also be set using the
190 * XTtcPs_SetOptions() function.
191 *
192 * @param        InstancePtr is a pointer to the XTtcPs instance.
193 * @param        MatchIndex is the index to the match register to be set.
194 *               Valid values are 0, 1, or 2.
195 * @param        Value is the 16-bit value to be set in the match register.
196 *
197 * @return       None
198 *
199 * @note         None
200 *
201 ****************************************************************************/
202 void XTtcPs_SetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex, XMatchRegValue Value)
203 {
204         /*
205          * Assert to validate input arguments.
206          */
207         Xil_AssertVoid(InstancePtr != NULL);
208         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
209         Xil_AssertVoid(MatchIndex < (u8)XTTCPS_NUM_MATCH_REG);
210
211         /*
212          * Write the value to the correct match register with MatchIndex
213          */
214         XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
215                           XTtcPs_Match_N_Offset(MatchIndex), Value);
216 }
217
218 /*****************************************************************************/
219 /**
220 *
221 * This function is used to get the value of the match registers. There are
222 * three match registers.
223 *
224 * @param        InstancePtr is a pointer to the XTtcPs instance.
225 * @param        MatchIndex is the index to the match register to be set.
226 *               Valid values are 0, 1, or 2.
227 *
228 * @return       The match register value
229 *
230 * @note         None
231 *
232 ****************************************************************************/
233 XMatchRegValue XTtcPs_GetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex)
234 {
235         u32 MatchReg;
236
237         /*
238          * Assert to validate input arguments.
239          */
240         Xil_AssertNonvoid(InstancePtr != NULL);
241         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
242         Xil_AssertNonvoid(MatchIndex < XTTCPS_NUM_MATCH_REG);
243
244         MatchReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
245                             XTtcPs_Match_N_Offset(MatchIndex));
246
247         return (XMatchRegValue) MatchReg;
248 }
249
250 /*****************************************************************************/
251 /**
252 *
253 * This function sets the prescaler enable bit and if needed sets the prescaler
254 * bits in the control register.
255 *
256 * @param        InstancePtr is a pointer to the XTtcPs instance.
257 * @param        PrescalerValue is a number from 0-16 that sets the prescaler
258 *               to use.
259 *               If the parameter is 0 - 15, use a prescaler on the clock of
260 *               2^(PrescalerValue+1), or 2-65536.
261 *               If the parameter is XTTCPS_CLK_CNTRL_PS_DISABLE, do not use a
262 *               prescaler.
263 *
264 * @return       None
265 *
266 * @note         None
267 *
268 ****************************************************************************/
269 void XTtcPs_SetPrescaler(XTtcPs *InstancePtr, u8 PrescalerValue)
270 {
271         u32 ClockReg;
272
273         /*
274          * Assert to validate input arguments.
275          */
276         Xil_AssertVoid(InstancePtr != NULL);
277         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
278         Xil_AssertVoid(PrescalerValue <= XTTCPS_CLK_CNTRL_PS_DISABLE);
279
280         /*
281          * Read the clock control register
282          */
283         ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
284                            XTTCPS_CLK_CNTRL_OFFSET);
285
286         /*
287          * Clear all of the prescaler control bits in the register
288          */
289         ClockReg &=
290                 ~(XTTCPS_CLK_CNTRL_PS_VAL_MASK | XTTCPS_CLK_CNTRL_PS_EN_MASK);
291
292         if (PrescalerValue < XTTCPS_CLK_CNTRL_PS_DISABLE) {
293                 /*
294                  * Set the prescaler value and enable prescaler
295                  */
296                 ClockReg |= (u32)(((u32)PrescalerValue << (u32)XTTCPS_CLK_CNTRL_PS_VAL_SHIFT) &
297                         (u32)XTTCPS_CLK_CNTRL_PS_VAL_MASK);
298                 ClockReg |= (u32)XTTCPS_CLK_CNTRL_PS_EN_MASK;
299         }
300
301         /*
302          * Write the register with the new values.
303          */
304         XTtcPs_WriteReg(InstancePtr->Config.BaseAddress,
305                           XTTCPS_CLK_CNTRL_OFFSET, ClockReg);
306 }
307
308 /*****************************************************************************/
309 /**
310 *
311 * This function gets the input clock prescaler
312 *
313 * @param        InstancePtr is a pointer to the XTtcPs instance.
314 *
315 * <pre>
316 * @return       The value(n) from which the prescalar value is calculated
317 *               as 2^(n+1). Some example values are given below :
318 *
319 *       Value           Prescaler
320 *       0               2
321 *       1               4
322 *       N               2^(n+1)
323 *       15              65536
324 *       16              1
325 * </pre>
326 *
327 * @note         None.
328 *
329 ****************************************************************************/
330 u8 XTtcPs_GetPrescaler(XTtcPs *InstancePtr)
331 {
332         u8 Status;
333         u32 ClockReg;
334
335         /*
336          * Assert to validate input arguments.
337          */
338         Xil_AssertNonvoid(InstancePtr != NULL);
339         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
340
341         /*
342          * Read the clock control register
343          */
344         ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress,
345                                     XTTCPS_CLK_CNTRL_OFFSET);
346
347         if (0 == (ClockReg & XTTCPS_CLK_CNTRL_PS_EN_MASK)) {
348                 /*
349                  * Prescaler is disabled. Return the correct flag value
350                  */
351                 Status = (u8)XTTCPS_CLK_CNTRL_PS_DISABLE;
352         }
353         else {
354
355                 Status = (u8)((ClockReg & (u32)XTTCPS_CLK_CNTRL_PS_VAL_MASK) >>
356                         (u32)XTTCPS_CLK_CNTRL_PS_VAL_SHIFT);
357         }
358         return Status;
359 }
360
361 /*****************************************************************************/
362 /**
363 *
364 * This function calculates the interval value as well as the prescaler value
365 * for a given frequency.
366 *
367 * @param        InstancePtr is a pointer to the XTtcPs instance.
368 * @param        Freq is the requested output frequency for the device.
369 * @param        Interval is the interval value for the given frequency,
370 *               it is the output value for this function.
371 * @param        Prescaler is the prescaler value for the given frequency,
372 *               it is the output value for this function.
373 *
374 * @return       None.
375 *
376 * @note
377 *  Upon successful calculation for the given frequency, Interval and Prescaler
378 *  carry the settings for the timer counter; Upon unsuccessful calculation,
379 *  Interval and Prescaler are set to 0xFF(FF) for their maximum values to
380 *  signal the caller of failure. Therefore, caller needs to check the return
381 *  interval or prescaler values for whether the function has succeeded.
382 *
383 ****************************************************************************/
384 void XTtcPs_CalcIntervalFromFreq(XTtcPs *InstancePtr, u32 Freq,
385         XInterval *Interval, u8 *Prescaler)
386 {
387         u8 TmpPrescaler;
388         u32 TempValue;
389         u32 InputClock;
390
391         InputClock = InstancePtr->Config.InputClockHz;
392         /*
393          * Find the smallest prescaler that will work for a given frequency. The
394          * smaller the prescaler, the larger the count and the more accurate the
395          *  PWM setting.
396          */
397         TempValue = InputClock/ Freq;
398
399         if (TempValue < 4U) {
400                 /*
401                  * The frequency is too high, it is too close to the input
402                  * clock value. Use maximum values to signal caller.
403                  */
404                 *Interval = XTTCPS_MAX_INTERVAL_COUNT;
405                 *Prescaler = 0xFFU;
406                 return;
407         }
408
409         /*
410          * First, do we need a prescaler or not?
411          */
412         if (((u32)65536U) > TempValue) {
413                 /*
414                  * We do not need a prescaler, so set the values appropriately
415                  */
416                 *Interval = (XInterval)TempValue;
417                 *Prescaler = XTTCPS_CLK_CNTRL_PS_DISABLE;
418                 return;
419         }
420
421
422         for (TmpPrescaler = 0U; TmpPrescaler < XTTCPS_CLK_CNTRL_PS_DISABLE;
423              TmpPrescaler++) {
424                 TempValue =     InputClock/ (Freq * (1U << (TmpPrescaler + 1U)));
425
426                 /*
427                  * The first value less than 2^16 is the best bet
428                  */
429                 if (((u32)65536U) > TempValue) {
430                         /*
431                          * Set the values appropriately
432                          */
433                         *Interval = (XInterval)TempValue;
434                         *Prescaler = TmpPrescaler;
435                         return;
436                 }
437         }
438
439         /* Can not find interval values that work for the given frequency.
440          * Return maximum values to signal caller.
441          */
442         *Interval = XTTCPS_MAX_INTERVAL_COUNT;
443         *Prescaler = 0XFFU;
444         return;
445 }
446 /** @} */