1 /******************************************************************************
3 * Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /******************************************************************************/
37 * This header file contains PLL configuring functions. These Functions
38 * calculates and configures the PLL depending on desired frequency.
43 * MODIFICATION HISTORY:
45 * Ver Who Date Changes
46 * ----- ---- -------- -----------------------------------------------
47 * 1.0 mh 06/24/17 Initial release.
48 * 2.1 tu 12/29/17 LPD and FPD offsets adjusted
51 *******************************************************************************/
52 /******************************* Include Files ********************************/
53 #include "xavbuf_clk.h"
55 /**************************** Constant Definitions ****************************/
56 /*Input Frequency for the PLL with precision upto two decimals*/
57 #define XAVBUF_INPUT_REF_CLK 3333333333
59 /*Frequency of VCO before divider to meet jitter requirement*/
60 #define XAVBUF_PLL_OUT_FREQ 1450000000
62 /* Precision of Input Ref Frequency for PLL*/
63 #define XAVBUF_INPUT_FREQ_PRECISION 100
65 /* 16 bit fractional shift to get Integer */
66 #define XAVBUF_PRECISION 16
67 #define XAVBUF_SHIFT_DECIMAL (1 << XAVBUF_PRECISION)
68 #define XAVBUF_DECIMAL (XAVBUF_SHIFT_DECIMAL - 1)
69 #define XDPSSU_MAX_VIDEO_FREQ 300000000
71 #define XAVBUF_AUDIO_SAMPLES 512
72 #define XAVBUF_AUDIO_SAMPLE_RATE_44_1 44100
73 #define XAVBUF_AUDIO_SAMPLE_RATE_48_0 48000
74 #define XAVBUF_EXTERNAL_DIVIDER 2
76 /* Register offsets for address manipulation */
77 #define XAVBUF_REG_OFFSET 4
78 #define XAVBUF_FPD_CTRL_OFFSET 12
79 #define XAVBUF_LPD_CTRL_OFFSET 16
80 #define MOD_3(a) ((a) % (3))
82 /*************************** Constant Variable Definitions ********************/
84 * This typedef enumerates capacitor resistor and lock values to be programmed.
94 /* PLL fractional divide programming table*/
95 static const PllConfig PllFracDivideTable[] = {
102 {3, 14, 3, 63, 1000},
103 {3, 14, 3, 63, 1000},
104 {3, 14, 3, 63, 1000},
105 {3, 14, 3, 63, 1000},
106 {3, 14, 3, 63, 1000},
107 {3, 14, 3, 63, 1000},
108 {3, 14, 3, 63, 1000},
198 /******************************************************************************/
200 * This function initializes the parameters required to configure PLL.
202 * @param PllInstancePtr is pointer to the XAVBuf_Pll instance.
203 * @param Pll is the PLL chosen to be configured.
204 * @param Pll is the PLL chosen to be configured.
205 * @param CrossDomain is the bool which is used to mention if the PLL
206 * outputs in other domain.
207 * @param ExtDividerCnt is number of external divider out of VCO.
209 * @return XST_SUCCESS if PLL is configured without an error.
210 * XST_FAILURE otherwise.
212 * @note In order to avoid floating point usage we have a 16bit
213 * fractional fixed point arithmetic implementation
215 *******************************************************************************/
216 static void XAVBuf_PllInitialize(XAVBuf_Pll *PllInstancePtr,
217 u8 Pll, u8 CrossDomain , u8 ExtDividerCnt)
219 /* Instantiate input frequency. */
220 PllInstancePtr->InputRefClk = XAVBUF_Pss_Ref_Clk;
221 PllInstancePtr->RefClkFreqhz = XAVBUF_INPUT_REF_CLK;
222 /* Turn on internal Divider*/
223 PllInstancePtr->Divider = 1;
224 PllInstancePtr->Pll = Pll;
225 PllInstancePtr->ExtDividerCnt = ExtDividerCnt;
227 //Check if CrossDomain is requested
229 PllInstancePtr->DomainSwitchDiv = 6;
231 PllInstancePtr->DomainSwitchDiv = 1;
232 //Check where PLL falls
234 PllInstancePtr->Fpd = 0;
235 PllInstancePtr->BaseAddress = XAVBUF_CLK_LPD_BASEADDR;
236 PllInstancePtr->Offset = XAVBUF_LPD_CTRL_OFFSET;
239 PllInstancePtr->Fpd = 1;
240 PllInstancePtr->BaseAddress = XAVBUF_CLK_FPD_BASEADDR;
241 PllInstancePtr->Offset = XAVBUF_FPD_CTRL_OFFSET;
246 /******************************************************************************/
248 * This function calculates the parameters which are required to configure PLL
249 * depending upon the requested frequency.
251 * @param PllInstancePtr is pointer to the XAVBuf_Pll instance
252 * @param FreqHz is the requested frequency to DP in Hz
254 * @return XST_SUCCESS if parameters are calculated
255 * XST_FAILURE otherwise.
257 * @note In order to avoid floating point usage we have a 16bit
258 * fractional fixed point arithmetic implementation
260 *******************************************************************************/
261 static int XAVBuf_PllCalcParameterValues(XAVBuf_Pll *PllInstancePtr,
264 u64 ExtDivider, Vco, VcoIntFrac;
266 /* Instantiate input frequency. */
267 PllInstancePtr->InputRefClk = XAVBUF_Pss_Ref_Clk;
268 PllInstancePtr->RefClkFreqhz = XAVBUF_INPUT_REF_CLK ;
269 /* Turn on internal Divider*/
270 PllInstancePtr->Divider = 1;
271 PllInstancePtr->DomainSwitchDiv = 1;
273 /* Estimate the total divider. */
274 ExtDivider = (XAVBUF_PLL_OUT_FREQ / FreqHz) /
275 PllInstancePtr->DomainSwitchDiv;
276 if(ExtDivider > 63 && PllInstancePtr->ExtDividerCnt == 2){
277 PllInstancePtr->ExtDivider0 = 63;
278 PllInstancePtr->ExtDivider1 = ExtDivider / 63;
280 else if(ExtDivider < 63){
281 PllInstancePtr->ExtDivider0 = ExtDivider;
282 PllInstancePtr->ExtDivider1 = 1;
287 Vco = FreqHz *(PllInstancePtr->ExtDivider1 *
288 PllInstancePtr->ExtDivider0 * 2) *
289 PllInstancePtr->DomainSwitchDiv;
290 /* Calculate integer and fractional part. */
291 VcoIntFrac = (Vco * XAVBUF_INPUT_FREQ_PRECISION *
292 XAVBUF_SHIFT_DECIMAL) /
293 PllInstancePtr->RefClkFreqhz ;
294 PllInstancePtr->Fractional = VcoIntFrac & XAVBUF_DECIMAL;
295 PllInstancePtr->FracIntegerFBDIV = VcoIntFrac >> XAVBUF_PRECISION;
300 /******************************************************************************/
302 * This function will Read modify and write into corresponding registers.
304 * @param BaseAddress is the base address to which the value has to be
306 * @param RegOffset is the relative offset from Base address.
307 * @param Mask is used to select the number of bits to be modified.
308 * @param Shift is the number bits to be shifted from LSB.
309 * @param Data is the Data to be written.
315 *******************************************************************************/
316 static void XAVBuf_ReadModifyWriteReg(u32 BaseAddress, u32 RegOffset, u32 Mask,
321 RegValue = XAVBuf_ReadReg(BaseAddress, RegOffset);
322 RegValue = (RegValue & ~Mask) | (Data << Shift);
323 XAVBuf_WriteReg(BaseAddress, RegOffset, RegValue);
326 /******************************************************************************/
328 * This function configures PLL.
330 * @param PllInstancePtr is pointer to the XAVBuf_Pll instance.
332 * @return XST_SUCCESS if PLL is configured without an error.
333 * XST_FAILURE otherwise.
337 *******************************************************************************/
338 static int XAVBuf_ConfigurePll(XAVBuf_Pll *PllInstancePtr)
340 u64 BaseAddress = PllInstancePtr->BaseAddress;
343 u8 Pll = PllInstancePtr->Pll;
345 RegPll |= XAVBUF_ENABLE_BIT << XAVBUF_PLL_CTRL_BYPASS_SHIFT;
346 RegPll |= PllInstancePtr->FracIntegerFBDIV <<
347 XAVBUF_PLL_CTRL_FBDIV_SHIFT;
348 RegPll |= PllInstancePtr->Divider << XAVBUF_PLL_CTRL_DIV2_SHIFT;
349 RegPll |= PllInstancePtr->InputRefClk << XAVBUF_PLL_CTRL_PRE_SRC_SHIFT;
350 XAVBuf_WriteReg(BaseAddress, XAVBUF_PLL_CTRL + (MOD_3(Pll) *
351 PllInstancePtr->Offset), RegPll);
353 /* Set the values for lock dly, lock counter, capacitor and resistor. */
355 PllFracDivideTable[PllInstancePtr->FracIntegerFBDIV -25].cp
356 << XAVBUF_PLL_CFG_CP_SHIFT;
358 PllFracDivideTable[PllInstancePtr->FracIntegerFBDIV -25].res
359 << XAVBUF_PLL_CFG_RES_SHIFT;
361 PllFracDivideTable[PllInstancePtr->FracIntegerFBDIV -25].lfhf
362 << XAVBUF_PLL_CFG_LFHF_SHIFT;
364 PllFracDivideTable[PllInstancePtr->FracIntegerFBDIV -25].lock_dly
365 << XAVBUF_PLL_CFG_LOCK_DLY_SHIFT;
367 PllFracDivideTable[PllInstancePtr->FracIntegerFBDIV -25].lock_cnt
368 << XAVBUF_PLL_CFG_LOCK_CNT_SHIFT;
369 XAVBuf_WriteReg(BaseAddress, XAVBUF_PLL_CFG + (MOD_3(Pll) *
370 PllInstancePtr->Offset), RegPll);
371 /* Enable and set Fractional Data. */
372 XAVBuf_WriteReg(BaseAddress, XAVBUF_PLL_FRAC_CFG + (MOD_3(Pll) *
373 PllInstancePtr->Offset), (1 << XAVBUF_PLL_FRAC_CFG_ENABLED_SHIFT) |
374 (PllInstancePtr->Fractional <<
375 XAVBUF_PLL_FRAC_CFG_DATA_SHIFT));
376 /* Assert reset to the PLL. */
377 XAVBuf_ReadModifyWriteReg(BaseAddress, XAVBUF_PLL_CTRL + (MOD_3(Pll) *
378 PllInstancePtr->Offset),
379 XAVBUF_PLL_CTRL_RESET_MASK, XAVBUF_PLL_CTRL_RESET_SHIFT,
382 /* Deassert reset to the PLL. */
383 XAVBuf_ReadModifyWriteReg(BaseAddress, XAVBUF_PLL_CTRL + (MOD_3(Pll) *
384 PllInstancePtr->Offset),
385 XAVBUF_PLL_CTRL_RESET_MASK, XAVBUF_PLL_CTRL_RESET_SHIFT,
388 while(!(XAVBuf_ReadReg(BaseAddress, XAVBUF_PLL_STATUS -
389 ((1 - PllInstancePtr->Fpd) * XAVBUF_REG_OFFSET)) &
394 /* Deassert Bypass. */
395 XAVBuf_ReadModifyWriteReg(BaseAddress, XAVBUF_PLL_CTRL + (MOD_3(Pll) *
396 PllInstancePtr->Offset),
397 XAVBUF_PLL_CTRL_BYPASS_MASK, XAVBUF_PLL_CTRL_BYPASS_SHIFT,
400 if(PllInstancePtr->DomainSwitchDiv != 1)
401 XAVBuf_ReadModifyWriteReg(BaseAddress, (XAVBUF_DOMAIN_SWITCH_CTRL
402 + (MOD_3(Pll) * XAVBUF_REG_OFFSET) - ((1 - PllInstancePtr->Fpd)
403 * XAVBUF_REG_OFFSET)),
404 XAVBUF_DOMAIN_SWITCH_DIVISOR0_MASK,
405 XAVBUF_DOMAIN_SWITCH_DIVISOR0_SHIFT,
406 PllInstancePtr->DomainSwitchDiv);
413 /******************************************************************************/
415 * This function configures Configures external divider.
417 * @param PllInstancePtr is pointer to the XAVBuf_Pll instance.
423 *******************************************************************************/
424 static void XAVBuf_ConfigureExtDivider(XAVBuf_Pll *PllInstancePtr,
425 u64 BaseAddress, u32 Offset)
427 XAVBuf_ReadModifyWriteReg(BaseAddress, Offset,
428 XAVBUF_VIDEO_REF_CTRL_CLKACT_MASK,
429 XAVBUF_VIDEO_REF_CTRL_CLKACT_SHIFT, XAVBUF_DISABLE_BIT);
430 XAVBuf_ReadModifyWriteReg(BaseAddress, Offset,
431 XAVBUF_VIDEO_REF_CTRL_DIVISOR1_MASK,
432 XAVBUF_VIDEO_REF_CTRL_DIVISOR1_SHIFT,
433 PllInstancePtr->ExtDivider1);
434 XAVBuf_ReadModifyWriteReg(BaseAddress, Offset,
435 XAVBUF_VIDEO_REF_CTRL_DIVISOR0_MASK,
436 XAVBUF_VIDEO_REF_CTRL_DIVISOR0_SHIFT,
437 PllInstancePtr->ExtDivider0);
438 XAVBuf_ReadModifyWriteReg(BaseAddress, Offset,
439 XAVBUF_VIDEO_REF_CTRL_CLKACT_MASK,
440 XAVBUF_VIDEO_REF_CTRL_CLKACT_SHIFT, XAVBUF_ENABLE_BIT);
441 XAVBuf_WriteReg(BaseAddress, Offset, 0x1011003);
444 /******************************************************************************/
446 * This function calls API to calculate and configure PLL with desired frequency
449 * @param FreqHz is the desired frequency in Hz.
451 * @return XST_SUCCESS if PLL is configured without an error.
452 * XST_FAILURE otherwise.
454 * @note The Pll used is design specific.
456 *******************************************************************************/
457 int XAVBuf_SetPixelClock(u64 FreqHz)
460 XAVBuf_Pll PllInstancePtr;
461 u8 Pll, CrossDomain, Flag;
463 /*Verify Input Arguments*/
464 Xil_AssertNonvoid(FreqHz < XDPSSU_MAX_VIDEO_FREQ);
466 PllAssigned = XAVBuf_ReadReg(XAVBUF_CLK_FPD_BASEADDR,
467 XAVBUF_VIDEO_REF_CTRL) & XAVBUF_VIDEO_REF_CTRL_SRCSEL_MASK;
469 switch (PllAssigned) {
470 case XAVBUF_VPLL_SRC_SEL:
474 case XAVBUF_DPLL_SRC_SEL:
478 case XAVBUF_RPLL_TO_FPD_SRC_SEL:
486 /*Calculate configure PLL and External Divider*/
487 XAVBuf_PllInitialize(&PllInstancePtr, Pll, CrossDomain,
488 XAVBUF_EXTERNAL_DIVIDER);
489 Flag = XAVBuf_PllCalcParameterValues(&PllInstancePtr, FreqHz);
492 Flag = XAVBuf_ConfigurePll(&PllInstancePtr);
495 XAVBuf_ConfigureExtDivider(&PllInstancePtr, XAVBUF_CLK_FPD_BASEADDR,
496 XAVBUF_VIDEO_REF_CTRL);
501 /******************************************************************************/
503 * This function calls API to calculate and configure PLL with desired
504 * frequency for Audio.
506 * @param FreqHz is the desired frequency in Hz.
508 * @return XST_SUCCESS if PLL is configured without an error.
509 * XST_FAILURE otherwise.
511 * @note The Pll used is design specific.
513 *******************************************************************************/
514 int XAVBuf_SetAudioClock(u64 FreqHz)
516 u32 Flag, PllAssigned;
518 XAVBuf_Pll XAVBuf_RPllInstancePtr;
520 /*Verify Input Arguments*/
521 Flag = (FreqHz == (XAVBUF_AUDIO_SAMPLE_RATE_44_1 *
522 XAVBUF_AUDIO_SAMPLES)) ||
523 (FreqHz == (XAVBUF_AUDIO_SAMPLE_RATE_48_0 *
524 XAVBUF_AUDIO_SAMPLES));
525 Xil_AssertNonvoid(Flag);
527 PllAssigned = XAVBuf_ReadReg(XAVBUF_CLK_FPD_BASEADDR,
528 XAVBUF_AUDIO_REF_CTRL) &
529 XAVBUF_AUDIO_REF_CTRL_SRCSEL_MASK;
531 switch (PllAssigned) {
532 case XAVBUF_VPLL_SRC_SEL:
536 case XAVBUF_DPLL_SRC_SEL:
540 case XAVBUF_RPLL_TO_FPD_SRC_SEL:
548 /*Calculate configure PLL and External Divider*/
549 XAVBuf_PllInitialize(&XAVBuf_RPllInstancePtr, Pll, CrossDomain,
550 XAVBUF_EXTERNAL_DIVIDER);
551 Flag = XAVBuf_PllCalcParameterValues(&XAVBuf_RPllInstancePtr, FreqHz);
554 Flag = XAVBuf_ConfigurePll(&XAVBuf_RPllInstancePtr);
557 XAVBuf_ConfigureExtDivider(&XAVBuf_RPllInstancePtr,
558 XAVBUF_CLK_FPD_BASEADDR, XAVBUF_AUDIO_REF_CTRL);