|
1 | 1 | /*
|
| 2 | + * The Clear BSD License |
2 | 3 | * Copyright (c) 2016, Freescale Semiconductor, Inc.
|
3 | 4 | * Copyright (c) 2016 - 2017 , NXP
|
4 | 5 | * All rights reserved.
|
5 | 6 | *
|
| 7 | + * |
6 | 8 | * Redistribution and use in source and binary forms, with or without modification,
|
7 |
| - * are permitted provided that the following conditions are met: |
| 9 | + * are permitted (subject to the limitations in the disclaimer below) provided |
| 10 | + * that the following conditions are met: |
8 | 11 | *
|
9 | 12 | * o Redistributions of source code must retain the above copyright notice, this list
|
10 | 13 | * of conditions and the following disclaimer.
|
|
17 | 20 | * contributors may be used to endorse or promote products derived from this
|
18 | 21 | * software without specific prior written permission.
|
19 | 22 | *
|
| 23 | + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. |
20 | 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
21 | 25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
22 | 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
@@ -150,6 +154,10 @@ static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg);
|
150 | 154 | static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg);
|
151 | 155 | /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
|
152 | 156 | static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg);
|
| 157 | +/* Convert the binary to fractional part */ |
| 158 | +static double Binary2Fractional(uint32_t binaryPart); |
| 159 | +/* Calculate the powerTimes' power of 2 */ |
| 160 | +static uint32_t power2Cal(uint32_t powerTimes); |
153 | 161 | /* Get the greatest common divisor */
|
154 | 162 | static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
|
155 | 163 | /* Set PLL output based on desired output rate */
|
@@ -969,6 +977,25 @@ static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)
|
969 | 977 | return mMult;
|
970 | 978 | }
|
971 | 979 |
|
| 980 | +/* Calculate the powerTimes' power of 2 */ |
| 981 | +static uint32_t power2Cal(uint32_t powerTimes) |
| 982 | +{ |
| 983 | + if (powerTimes == 0) |
| 984 | + return 1; |
| 985 | + return 2 * power2Cal(powerTimes - 1); |
| 986 | +} |
| 987 | + |
| 988 | +/* Convert the binary to fractional part */ |
| 989 | +static double Binary2Fractional(uint32_t binaryPart) |
| 990 | +{ |
| 991 | + double fractional = 0; |
| 992 | + for (uint32_t i = 0; i <= 14; i++) |
| 993 | + { |
| 994 | + fractional += (double)((binaryPart >> i) & 0x1U) / (double)power2Cal(15 - i); |
| 995 | + } |
| 996 | + return fractional; |
| 997 | +} |
| 998 | + |
972 | 999 | /* Find greatest common divisor between m and n */
|
973 | 1000 | static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
|
974 | 1001 | {
|
@@ -1174,6 +1201,12 @@ static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup)
|
1174 | 1201 | s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromSetup(pSetup);
|
1175 | 1202 | }
|
1176 | 1203 |
|
| 1204 | +/* Update AUDIO Fractional PLL rate variable */ |
| 1205 | +static void CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t *pSetup) |
| 1206 | +{ |
| 1207 | + s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromFractSetup(pSetup); |
| 1208 | +} |
| 1209 | + |
1177 | 1210 | /* Update USB PLL rate variable */
|
1178 | 1211 | static void CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t *pSetup)
|
1179 | 1212 | {
|
@@ -1366,6 +1399,58 @@ uint32_t CLOCK_GetAudioPLLOutFromSetup(pll_setup_t *pSetup)
|
1366 | 1399 | return (uint32_t)workRate;
|
1367 | 1400 | }
|
1368 | 1401 |
|
| 1402 | +/* Return Audio PLL output clock rate from audio fractioanl setup structure */ |
| 1403 | +uint32_t CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t *pSetup) |
| 1404 | +{ |
| 1405 | + uint32_t prediv, postdiv, inPllRate; |
| 1406 | + double workRate, mMultFactional; |
| 1407 | + |
| 1408 | + inPllRate = CLOCK_GetAudioPLLInClockRate(); |
| 1409 | + if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U) |
| 1410 | + { |
| 1411 | + /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */ |
| 1412 | + /* |
| 1413 | + * 1. Pre-divider |
| 1414 | + * Pre-divider is only available when the DIRECTI is disabled. |
| 1415 | + */ |
| 1416 | + if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK)) |
| 1417 | + { |
| 1418 | + prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec); |
| 1419 | + } |
| 1420 | + else |
| 1421 | + { |
| 1422 | + prediv = 1U; /* The pre-divider is bypassed. */ |
| 1423 | + } |
| 1424 | + /* |
| 1425 | + * 2. Post-divider |
| 1426 | + * Post-divider is only available when the DIRECTO is disabled. |
| 1427 | + */ |
| 1428 | + if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK)) |
| 1429 | + { |
| 1430 | + postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec); |
| 1431 | + } |
| 1432 | + else |
| 1433 | + { |
| 1434 | + postdiv = 1U; /* The post-divider is bypassed. */ |
| 1435 | + } |
| 1436 | + /* Adjust input clock */ |
| 1437 | + inPllRate = inPllRate / prediv; |
| 1438 | + |
| 1439 | + mMultFactional = (double)(pSetup->audpllfrac >> 15) + (double)Binary2Fractional(pSetup->audpllfrac & 0x7FFFU); |
| 1440 | + workRate = (double)inPllRate * (double)mMultFactional; |
| 1441 | + |
| 1442 | + workRate = workRate / ((double)postdiv); |
| 1443 | + workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/ |
| 1444 | + } |
| 1445 | + else |
| 1446 | + { |
| 1447 | + /* In bypass mode */ |
| 1448 | + workRate = (uint64_t)inPllRate; |
| 1449 | + } |
| 1450 | + |
| 1451 | + return (uint32_t)workRate; |
| 1452 | +} |
| 1453 | + |
1369 | 1454 | /* Set the current PLL Rate */
|
1370 | 1455 | void CLOCK_SetStoredPLLClockRate(uint32_t rate)
|
1371 | 1456 | {
|
@@ -1609,6 +1694,48 @@ pll_error_t CLOCK_SetupAudioPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)
|
1609 | 1694 | return kStatus_PLL_Success;
|
1610 | 1695 | }
|
1611 | 1696 |
|
| 1697 | +/* Set AUDIO PLL output from AUDIO PLL fractional setup structure */ |
| 1698 | +pll_error_t CLOCK_SetupAudioPLLPrecFract(pll_setup_t *pSetup, uint32_t flagcfg) |
| 1699 | +{ |
| 1700 | + if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U) |
| 1701 | + { |
| 1702 | + /* Turn on the ext clock if system pll input select clk_in */ |
| 1703 | + CLOCK_Enable_SysOsc(true); |
| 1704 | + } |
| 1705 | + /* Enable power VD3 for PLLs */ |
| 1706 | + POWER_SetPLL(); |
| 1707 | + /* Power off PLL during setup changes */ |
| 1708 | + POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL); |
| 1709 | + |
| 1710 | + pSetup->flags = flagcfg; |
| 1711 | + |
| 1712 | + /* Write PLL setup data */ |
| 1713 | + SYSCON->AUDPLLCTRL = pSetup->pllctrl; |
| 1714 | + SYSCON->AUDPLLNDEC = pSetup->pllndec; |
| 1715 | + SYSCON->AUDPLLNDEC = pSetup->pllndec | (1U << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ |
| 1716 | + SYSCON->AUDPLLPDEC = pSetup->pllpdec; |
| 1717 | + SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1U << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ |
| 1718 | + SYSCON->AUDPLLMDEC = pSetup->pllmdec; |
| 1719 | + SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(0); /* enable fractional function */ |
| 1720 | + SYSCON->AUDPLLFRAC = pSetup->audpllfrac; |
| 1721 | + SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1U << SYSCON_AUDPLLFRAC_REQ_SHIFT); |
| 1722 | + |
| 1723 | + /* Enable peripheral states by setting low */ |
| 1724 | + POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL); |
| 1725 | + |
| 1726 | + if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U) |
| 1727 | + { |
| 1728 | + while (CLOCK_IsAudioPLLLocked() == false) |
| 1729 | + { |
| 1730 | + } |
| 1731 | + } |
| 1732 | + |
| 1733 | + /* Update current programmed PLL rate var */ |
| 1734 | + CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pSetup); |
| 1735 | + |
| 1736 | + return kStatus_PLL_Success; |
| 1737 | +} |
| 1738 | + |
1612 | 1739 | /* Set Audio PLL output based on the passed Audio PLL setup data */
|
1613 | 1740 | pll_error_t CLOCK_SetupAudioPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
|
1614 | 1741 | {
|
@@ -1819,7 +1946,7 @@ pll_error_t CLOCK_SetUsbPLLFreq(const usb_pll_setup_t *pSetup)
|
1819 | 1946 | }
|
1820 | 1947 |
|
1821 | 1948 | /* If configure the USB HOST clock, VD5 power for USB PHY should be enable
|
1822 |
| - before the the PLL is working */ |
| 1949 | + before the PLL is working */ |
1823 | 1950 | /* Turn on the ext clock for usb pll input */
|
1824 | 1951 | CLOCK_Enable_SysOsc(true);
|
1825 | 1952 |
|
|
0 commit comments